-#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