]> Pileus Git - ~andy/csm213a-hw/blobdiff - yue/main.cpp
Get things running
[~andy/csm213a-hw] / yue / main.cpp
index 20186e1f54595b01466b25c9cfc8c271b3719d27..0b42bfd9ff2dc57615cf6a4bf182acfe1c4b99be 100644 (file)
-#include "mbed.h"
-#include "TSISensor.h"          // Touch Sensor
-#include "MAG3110.h"            // Magnetic Sensor
-#include "MMA8451Q.h"           // AcceleroMeter
-
-
-#define MMA8451_I2C_ADDRESS (0x1d<<1)   // acc sensor address
-#define TIME_ACCURACY 0.1
-#define LIGHT_SNS_DEFAULT 1             // default collecting interval in seconds
-#define ACC_SNS_DEFAULT 1
-#define MAG_SNS_DEFAULT 1
-#define TOUCH_SNS_DEFAULT 1
-
-// Define Devices & Pins
-MMA8451Q accSensor(PTE25, PTE24, MMA8451_I2C_ADDRESS);
-TSISensor touchSensor;
-MAG3110 magSensor(PTE25, PTE24);
-Serial serial(USBTX, USBRX);
-Ticker clock1;
-AnalogIn lightSensor(PTE22);
-
-
-// Global Variables
-// Initial interval: in seconds
-float lightTmr = LIGHT_SNS_DEFAULT;
-float accTmr = ACC_SNS_DEFAULT;
-float magTmr = MAG_SNS_DEFAULT;
-float touchTmr = TOUCH_SNS_DEFAULT;
-
-bool lightEnable = true;
-bool accEnable = true;
-bool magEnable = true;
-bool touchEnable = true;
-
-void clock1_interrupt();
-void serialRx_interrupt();
-void sendLightInfo();
-void sendAccInfo();
-void sendMagInfo();
-void sendTouchInfo();
-
-
-int main() {
-    // Initialization
-    // Interruption Declarations
-    clock1.attach(&clock1_interrupt, TIME_ACCURACY);    // maximun accuracy be 0.1s
-    serial.attach(&serialRx_interrupt, Serial::RxIrq);  // receive interrupt for serialS
-    magSensor.begin();
-
-    serial.printf("\r\n============= Start of the program ============\r\n");
-    while(1){
-        wait(3);
-    }
-}
-
-
-/*---------------------------------------------------------------
-  ## Receive Interruption of the Serial ##
-  -> used to receive & process user command
-  -> and configure the board accordingly
-  ---------------------------------------------------------------*/
-void serialRx_interrupt(){
-    clock1.detach();                // close the interrupt
-    serial.printf("\r\n");
-
-    // Receive the Serial Input
-    float interval;
-    char buffer[255];
-    char temp[255];
-    char ch = serial.getc();
-    int i;
-    for (i=0 ; ch!='\n' && ch!='\r'; i++){
-        serial.putc(ch);
-        buffer[i] = ch;
-        if (ch==127){                // BackSpace
-            i--;
-            i--;
-        }
-        ch = serial.getc();
-    }
-    buffer[i] = '\0';
-    serial.printf("\r\nBUFFER: %s %d\r\n", buffer,i);
-    // TODO: buffer -> lower case
-
-    // Process the Serial Input
-    // Set-Interval Command
-    if (strstr(buffer, "set")!=NULL && strstr(buffer, "int")!= NULL){
-        sscanf(buffer, "%*[^0123456789.]%s", temp);       // find the number in buffer
-        sscanf(temp, "%f", &interval);                    // translate into float
-        if (interval<0.1 || interval>5){
-            interval  = 1;
-        }
-        if (strstr(buffer, "acc")){
-            accTmr = interval;
-        }
-        if (strstr(buffer, "mag")){
-            magTmr = interval;
-        }
-        if (strstr(buffer, "light")){
-            lightTmr = interval;
-        }
-        if (strstr(buffer, "touch")){
-            touchTmr = interval;
-        }
-    }
-
-    // Stop Command
-    else if (strstr(buffer, "stop")!= NULL){
-        serial.printf("STOP\r\n");
-        if (strstr(buffer, "acc")){
-            accEnable = false;
-            accTmr = ACC_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "mag")){
-            magEnable = false;
-            magTmr = MAG_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "light")){
-            lightEnable = false;
-            lightTmr = LIGHT_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "touch")){
-            touchEnable = false;
-            touchTmr = TOUCH_SNS_DEFAULT;
-        }
-    }
-
-    // Start Command
-    else if (strstr(buffer, "start")!=NULL){
-        if (strstr(buffer, "acc") && !accEnable){
-            accEnable = true;
-            accTmr = ACC_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "mag") && !magEnable){
-            magEnable = true;
-            magTmr = MAG_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "light") && !lightEnable){
-            lightEnable = true;
-            lightTmr = LIGHT_SNS_DEFAULT;
-        }
-        if (strstr(buffer, "touch") && !touchEnable){
-            touchEnable = true;
-            touchTmr = TOUCH_SNS_DEFAULT;
-        }
-    }
-    clock1.attach(&clock1_interrupt,0.1);
-}
-
-
-void clock1_interrupt(){
-    static int accCnt;
-    static int magCnt;
-    static int lightCnt;
-    static int touchCnt;
-
-    accCnt++;
-    magCnt++;
-    lightCnt++;
-    touchCnt++;
-
-    // TODO: send data through Serial
-    if (lightEnable && (lightCnt<0 || lightCnt>=lightTmr/TIME_ACCURACY)){
-        sendLightInfo();
-        lightCnt = 0;
-    }
-    if (magEnable && (magCnt<0 || magCnt>=magTmr/TIME_ACCURACY)){
-        sendMagInfo();
-        magCnt = 0;
-    }
-    if (touchEnable && (touchCnt<0 || touchCnt>=touchTmr/TIME_ACCURACY)){
-        sendTouchInfo();
-        touchCnt = 0;
-    }
-    if (accEnable && (accCnt<0 || accCnt>=accTmr/TIME_ACCURACY)){
-        sendAccInfo();
-        accCnt = 0;
-    }
-}
-
-void sendLightInfo(){
-    serial.printf("[LGT] Light Intensity=%f\r\n", lightSensor.read());
-}
-
-
-void sendAccInfo(){
-    // get acc data
-    float accX = accSensor.getAccX();
-    float accY = accSensor.getAccY();
-    float accZ = accSensor.getAccZ();
-
-    // send acc data
-    serial.printf("[ACC] accX=%-2.4f accY=%-2.4f accZ=%-2.4f\r\n",accX,accY,accZ);
-}
-
-void sendTouchInfo(){
-    // get data
-    float touchForce = touchSensor.readPercentage();
-    float distance = touchSensor.readDistance();
-
-    // send data
-    serial.printf("[TCH] Force=%0.4f Distance=%2.2f\r\n", touchForce, distance);
-}
-
-void sendMagInfo(){
-    // get data
-    int magX, magY, magZ;
-    magSensor.getValues(&magX, &magY, &magZ);
-
-    // send data
-    serial.printf("[MAG] magX=%d magY=%d magZ=%d\r\n",magX,magY,magZ);
-}
+#include <stdint.h>\r
+#include <stdarg.h>\r
+\r
+#include "mbed.h"\r
+#include "TSISensor.h"          // Touch Sensor\r
+#include "MAG3110.h"            // Magnetic Sensor\r
+#include "MMA8451Q.h"           // AcceleroMeter\r
+\r
+#include "serial_dma.h"         // AcceleroMeter\r
+\r
+//#include "DataFrame.h"\r
+\r
+#define CLAMP(x, min, max)     \\r
+        ((x) < (min) ? (min) : \\r
+         (x) > (max) ? (max) : (x))\r
+\r
+#define MMA8451_I2C_ADDRESS (0x1d<<1)   // acc sensor address\r
+#define TIME_ACCURACY     0.01\r
+\r
+#define ACC_SNS_DEFAULT   0.1   // default collecting interval in seconds\r
+#define MAG_SNS_DEFAULT   1.0\r
+#define LGT_SNS_DEFAULT   1.0\r
+#define TCH_SNS_DEFAULT   1.0\r
+#define A2D_SNS_DEFAULT   1.0\r
+#define LED_OUT_DEFAULT   0.5\r
+\r
+#define MIN_RATE          1E-4  // 1 kHz\r
+#define MAX_RATE          10.0  // 0.1 Hz\r
+\r
+// Common Frame Information\r
+#define HEADER            0x02\r
+#define TAIL              0x0A  // '\n'\r
+\r
+#define MAX_FRAME_SIZE    256\r
+\r
+#define SNS_NUM  5\r
+#define TYPE_NUM 4\r
+#define OPER_NUM 3\r
+\r
+typedef enum {\r
+    ACC_SNS,\r
+    MAG_SNS,\r
+    LGT_SNS,\r
+    TCH_SNS,\r
+    A2D_SNS,\r
+} sns_t;\r
+\r
+typedef enum {\r
+    INT,\r
+    LONG,\r
+    FLOAT,\r
+    DOUBLE,\r
+} type_t;\r
+\r
+typedef enum {\r
+    STOP,\r
+    START,\r
+    RATE,\r
+} oper_t;\r
+\r
+// Data Frame Information\r
+typedef struct {\r
+    uint8_t header;\r
+    struct {\r
+        uint8_t type : 4;\r
+        uint8_t sns  : 4;\r
+    } bits;\r
+    uint8_t count;\r
+    uint8_t data[];\r
+} __attribute__((__packed__)) state_t;\r
+\r
+// Command Frame Information\r
+typedef struct {\r
+    uint8_t header;\r
+    struct {\r
+        uint8_t oper : 4;\r
+        uint8_t sns  : 4;\r
+    } bits;\r
+    float   interval;\r
+} __attribute__((__packed__)) command_t;\r
+\r
+// Define Devices & Pins\r
+MMA8451Q   accSensor(PTE25, PTE24, MMA8451_I2C_ADDRESS);\r
+MAG3110    magSensor(PTE25, PTE24);\r
+TSISensor  tchSensor;\r
+AnalogIn   lgtSensor(PTE22);\r
+AnalogIn   a2dSensor(A0);\r
+\r
+DigitalOut led1(LED1);\r
+DigitalOut led2(LED2);\r
+\r
+Serial     serial(USBTX, USBRX);\r
+Ticker     clock1;\r
+\r
+// Global Variables\r
+// Initial interval: in seconds\r
+float accTmr = ACC_SNS_DEFAULT;\r
+float magTmr = MAG_SNS_DEFAULT;\r
+float tchTmr = TCH_SNS_DEFAULT;\r
+float lgtTmr = LGT_SNS_DEFAULT;\r
+float a2dTmr = A2D_SNS_DEFAULT;\r
+float ledTmr = LED_OUT_DEFAULT;\r
+\r
+bool accEnable = true;\r
+bool magEnable = false;\r
+bool lgtEnable = false;\r
+bool tchEnable = false;\r
+bool a2dEnable = false;\r
+bool ledEnable = true;\r
+\r
+bool useStr = false;\r
+bool useHex = false;\r
+bool useBin = true;\r
+\r
+uint8_t txFrame[MAX_FRAME_SIZE];\r
+uint8_t rxFrame[MAX_FRAME_SIZE];\r
+\r
+// Prototypes\r
+void clock1_interrupt(void);\r
+void serialRx_interrupt(void);\r
+\r
+void runCommand(command_t *cmd);\r
+\r
+void sendAccInfo(void);\r
+void sendMagInfo(void);\r
+void sendLgtInfo(void);\r
+void sendTchInfo(void);\r
+void sendA2dInfo(void);\r
+\r
+int  calDataSize(uint8_t);\r
+int  packToFrame(uint8_t *frame, sns_t snsType, type_t dataType, int dataNum, void *data);\r
+\r
+void printStr(const char *str, ...);\r
+void printHex(uint8_t *frame, int len);\r
+void printBin(uint8_t *frame, int len);\r
+\r
+/********\r
+ * Main *\r
+ ********/\r
+\r
+int main(void) {\r
+    // Initialization\r
+    // Interruption Declarations\r
+    clock1.attach(&clock1_interrupt, TIME_ACCURACY);    // maximun accuracy be 0.1s\r
+    serial.attach(&serialRx_interrupt, Serial::RxIrq);  // receive interrupt for serialS\r
+    serial.baud(115200);\r
+    magSensor.begin();\r
+\r
+    sdma_setup(UART0, 0);\r
+\r
+    printStr("\r\n============= Start of the program ============\r\n");\r
+\r
+    while(1){\r
+        wait(3);\r
+    }\r
+}\r
+\r
+/**********************\r
+ * Interrupt handlers *\r
+ **********************/\r
+\r
+void serialRx_interrupt(void) {                     // Byte version\r
+    static int state  = 0;\r
+    static int index  = 0;\r
+    static int length = 0;\r
+\r
+    command_t *cmd = (command_t*)rxFrame;\r
+\r
+    while (serial.readable()) {\r
+        rxFrame[index++] = serial.getc();\r
+        switch (state) {\r
+            case 0: // Header\r
+                if (cmd->header == HEADER)\r
+                    state = 1;\r
+                else\r
+                    index = 0;\r
+                break;\r
+            case 1: // Bits\r
+                if (cmd->bits.sns  >= SNS_NUM ||\r
+                    cmd->bits.oper >= OPER_NUM) {\r
+                    state = index = 0;\r
+                } else if (cmd->bits.oper == RATE) {\r
+                    length = 4;\r
+                    state  = 2;\r
+                } else {\r
+                    state  = 3;\r
+                }\r
+                break;\r
+            case 2: // Data\r
+                if (--length == 0)\r
+                    state = 3;\r
+                break;\r
+            case 3: // Tail\r
+                if (rxFrame[index-1] == TAIL)\r
+                    runCommand(cmd);\r
+                state = 0;\r
+                index = 0;\r
+                break;\r
+        }\r
+    }\r
+}\r
+\r
+void clock1_interrupt(void){\r
+    static int accCnt;\r
+    static int magCnt;\r
+    static int lgtCnt;\r
+    static int tchCnt;\r
+    static int a2dCnt;\r
+    static int ledCnt;\r
+\r
+    accCnt++;\r
+    magCnt++;\r
+    lgtCnt++;\r
+    tchCnt++;\r
+    a2dCnt++;\r
+    ledCnt++;\r
+\r
+    // Send data through Serial\r
+    if (accEnable && (accCnt<0 || accCnt>=accTmr/TIME_ACCURACY)){\r
+        sendAccInfo();\r
+        accCnt = 0;\r
+    }\r
+    if (magEnable && (magCnt<0 || magCnt>=magTmr/TIME_ACCURACY)){\r
+        sendMagInfo();\r
+        magCnt = 0;\r
+    }\r
+    if (lgtEnable && (lgtCnt<0 || lgtCnt>=lgtTmr/TIME_ACCURACY)){\r
+        sendLgtInfo();\r
+        lgtCnt = 0;\r
+    }\r
+    if (tchEnable && (tchCnt<0 || tchCnt>=tchTmr/TIME_ACCURACY)){\r
+        sendTchInfo();\r
+        tchCnt = 0;\r
+    }\r
+    if (a2dEnable && (a2dCnt<0 || a2dCnt>=a2dTmr/TIME_ACCURACY)){\r
+        sendA2dInfo();\r
+        a2dCnt = 0;\r
+    }\r
+\r
+    // Toggel LED for debugging\r
+    if (ledEnable && (ledCnt<0 || ledCnt>=ledTmr/TIME_ACCURACY)){\r
+        led1   = !led1;\r
+       ledCnt = 0;\r
+    }\r
+\r
+    sdma_flush();\r
+}\r
+\r
+/*******************\r
+ * Command handler *\r
+ *******************/\r
+\r
+void runCommand(command_t *cmd)\r
+{\r
+    // Validate interval\r
+    sns_t  snsType  = (sns_t )cmd->bits.sns;\r
+    oper_t operType = (oper_t)cmd->bits.oper;\r
+    float  interval = CLAMP(cmd->interval, MIN_RATE, MAX_RATE);\r
+\r
+    // Save value to global data\r
+    switch(snsType){\r
+        case ACC_SNS:\r
+            switch(operType){\r
+                case STOP:   accEnable = false; break;\r
+                case START:  accEnable = true;  break;\r
+                case RATE:   accTmr = interval; break;\r
+            }\r
+            break;\r
+\r
+        case MAG_SNS:\r
+            switch(operType){\r
+                case STOP:   magEnable = false; break;\r
+                case START:  magEnable = true;  break;\r
+                case RATE:   magTmr = interval; break;\r
+            }\r
+            break;\r
+\r
+        case LGT_SNS:\r
+            switch(operType){\r
+                case STOP:   lgtEnable = false; break;\r
+                case START:  lgtEnable = true;  break;\r
+                case RATE:   lgtTmr = interval; break;\r
+            }\r
+            break;\r
+\r
+        case TCH_SNS:\r
+            switch(operType){\r
+                case STOP:   tchEnable = false; break;\r
+                case START:  tchEnable = true;  break;\r
+                case RATE:   tchTmr = interval; break;\r
+            }\r
+            break;\r
+\r
+        case A2D_SNS:\r
+            switch(operType){\r
+                case STOP:   a2dEnable = false; break;\r
+                case START:  a2dEnable = true;  break;\r
+                case RATE:   a2dTmr = interval; break;\r
+            }\r
+            break;\r
+    }\r
+}\r
+\r
+/*******************\r
+ * Sensors reading *\r
+ *******************/\r
+\r
+void sendAccInfo(void){\r
+    float accData[3];\r
+    accData[0] = accSensor.getAccX();\r
+    accData[1] = accSensor.getAccY();\r
+    accData[2] = accSensor.getAccZ();\r
+    int len = packToFrame(txFrame, ACC_SNS, FLOAT, 3, accData);\r
+\r
+    printStr("[ACC] accX=%-2.4f accY=%-2.4f accZ=%-2.4f\r\n",\r
+                    accData[0], accData[1], accData[2]);\r
+    printHex(txFrame, len);\r
+    printBin(txFrame, len);\r
+}\r
+\r
+void sendMagInfo(void){\r
+    int magData[3];\r
+    magSensor.getValues(&magData[0], &magData[1], &magData[2]);\r
+    int len = packToFrame(txFrame, MAG_SNS, INT, 3, magData);\r
+\r
+    printStr("[MAG] magX=%d magY=%d magZ=%d\r\n",\r
+                    magData[0], magData[1], magData[2]);\r
+    printHex(txFrame, len);\r
+    printBin(txFrame, len);\r
+}\r
+\r
+void sendLgtInfo(void){\r
+    float lgtData = lgtSensor.read();\r
+    int len = packToFrame(txFrame, LGT_SNS, FLOAT, 1, &lgtData);\r
+\r
+    printStr("[LGT] intensity=%f\r\n",\r
+                    lgtSensor.read());\r
+    printHex(txFrame, len);\r
+    printBin(txFrame, len);\r
+}\r
+\r
+void sendTchInfo(void){\r
+    float tchData[2];\r
+    tchData[0] = tchSensor.readPercentage();\r
+    tchData[1] = tchSensor.readDistance();\r
+    int len = packToFrame(txFrame, TCH_SNS, FLOAT, 2, tchData);\r
+\r
+    printStr("[TCH] force=%0.4f distance=%2.2f\r\n",\r
+                    tchData[0], tchData[1]);\r
+    printHex(txFrame, len);\r
+    printBin(txFrame, len);\r
+}\r
+\r
+void sendA2dInfo(void){\r
+    float a2dData[6];\r
+    a2dData[0] = 0;\r
+    a2dData[1] = 0;\r
+    a2dData[2] = 0;\r
+    a2dData[3] = 0;\r
+    a2dData[4] = 0;\r
+    a2dData[5] = 0;\r
+    int len = packToFrame(txFrame, A2D_SNS, FLOAT, 6, a2dData);\r
+\r
+    printStr("[A2D] data=%2.2f %2.2f %2.2f %2.2f %2.2f %2.2f\r\n",\r
+                a2dData[0], a2dData[1], a2dData[2],\r
+                a2dData[3], a2dData[4], a2dData[5]);\r
+    printHex(txFrame, len);\r
+    printBin(txFrame, len);\r
+}\r
+\r
+/********************\r
+ * Helper functions *\r
+ ********************/\r
+\r
+int calDataSize(type_t dataType){\r
+    switch(dataType){\r
+        case INT:    return 2;\r
+        case LONG:   return 4;\r
+        case FLOAT:  return 4;\r
+        case DOUBLE: return 8;\r
+    }\r
+    return 4;\r
+}\r
+\r
+/*******************\r
+ * Frame functions *\r
+ *******************/\r
+\r
+int packToFrame(uint8_t *frame, sns_t snsType, type_t dataType, int dataNum, void *data){\r
+    //const char pattern[] = "\x80\x81\x82\x83"\r
+    //                       "\x84\x85\x86\x87"\r
+    //                       "\x88\x89\x8A\x8B"\r
+    //                       "\x8C\x8D\x8E\x8F";\r
+\r
+    int      size  = dataNum * calDataSize(dataType);\r
+    state_t *state = (state_t*)frame;\r
+    uint8_t *tail  = &state->data[size];\r
+\r
+    state->header    = HEADER;\r
+    state->bits.sns  = snsType;\r
+    state->bits.type = dataType;\r
+    state->count     = dataNum;;\r
+    memcpy(&state->data, data, size);\r
+    tail[0]          = TAIL;\r
+    tail[1]          = '\0';\r
+\r
+    return (3 + size + 1);\r
+}\r
+\r
+/*******************\r
+ * Print functions *\r
+ *******************/\r
+\r
+void printHex(uint8_t *frame, int len){\r
+    if (!useHex)\r
+        return;\r
+\r
+    sdma_printf("      ");\r
+    for (int i=0; i<len; i++)\r
+        sdma_printf("%02hx ", frame[i]);\r
+    sdma_printf("\r\n");\r
+}\r
+\r
+void printStr(const char *fmt, ...){\r
+    if (!useStr)\r
+        return;\r
+\r
+    va_list ap;\r
+    va_start(ap, fmt);\r
+    sdma_vprintf(fmt, ap);\r
+    va_end(ap);\r
+}\r
+\r
+void printBin(uint8_t *frame, int len){\r
+    if (!useBin)\r
+        return;\r
+\r
+    sdma_write(frame, len);\r
+}\r