From: Andy Spencer Date: Sun, 9 Feb 2014 10:11:58 +0000 (+0000) Subject: Update main file add DMA code X-Git-Url: http://pileus.org/git/?p=~andy%2Fcsm213a-hw;a=commitdiff_plain;h=6eac4234f7b20b3bc6a72f4242ad3ee99516c858 Update main file add DMA code --- diff --git a/vis/device.py b/vis/device.py index 34a8be4..ab08201 100644 --- a/vis/device.py +++ b/vis/device.py @@ -10,33 +10,33 @@ from struct import * #buildingFrame = 0; #if it is a start of new frame class Const: - HEADER = 0x02 - SNS_BITS = 5 - LGT_SNS = 0x00 - ACC_SNS = 0x01 - MAG_SNS = 0x02 - TCH_SNS = 0x03 - ADC_SNS_1 = 0x04 - - INT = 0 - LONG = 1 - FLOAT = 2 - DOUBLE = 3 - TAIL = 0x0A - - START = 0 - STOP = 1 - SET_INT = 2 - buildingFrame = 0 - - snsCode = {'light':LGT_SNS,'touch':TCH_SNS,'acc':ACC_SNS,'mag':MAG_SNS,'a2d':ADC_SNS_1} - cmdCode = {'start':START, 'stop':STOP, 'set':SET_INT} - sizeMap = {INT:2, FLOAT:4, LONG:4, DOUBLE:8} - typeMap = {0:INT, 1:LONG, FLOAT:2, DOUBLE:3} + HEADER = 0x02 + SNS_BITS = 5 + LGT_SNS = 0x00 + ACC_SNS = 0x01 + MAG_SNS = 0x02 + TCH_SNS = 0x03 + ADC_SNS_1 = 0x04 + + INT = 0 + LONG = 1 + FLOAT = 2 + DOUBLE = 3 + TAIL = 0x0A + + START = 0 + STOP = 1 + SET_INT = 2 + buildingFrame = 0 + + snsCode = {'light':LGT_SNS,'touch':TCH_SNS,'acc':ACC_SNS,'mag':MAG_SNS,'a2d':ADC_SNS_1} + cmdCode = {'start':START, 'stop':STOP, 'set':SET_INT} + sizeMap = {INT:2, FLOAT:4, LONG:4, DOUBLE:8} + typeMap = {0:INT, 1:LONG, FLOAT:2, DOUBLE:3} class Static: - count = 0 + count = 0 class State: #information stored @@ -53,14 +53,14 @@ class State: #information stored class Device: # Constructors def __init__(self, config): - print("IN") + print("IN") self.config = config self.serial = None # Methods def connect(self): - print("C") - buildingFrame = 0 + print("C") + buildingFrame = 0 try: self.inbuf = [] self.serial = Serial(self.config.device, \ @@ -75,7 +75,7 @@ class Device: return str(ex) def disconnect(self): - print("DC") + print("DC") if self.serial and self.serial.isOpen(): self.serial.close() @@ -86,9 +86,9 @@ class Device: return False return True - def control(self):################# - print("CT") - frame = [None]*7 + def control(self): + print("CT") + frame = [None]*7 for key in list(self.config.enable.keys()): state = self.config.enable[key] rate = self.config.rate[key] @@ -96,7 +96,7 @@ class Device: sns = Const.snsCode[key] frame[0] = chr(Const.HEADER) frame[1] = chr(cmd<<(Const.SNS_BITS)|(0x1F&sns)) - frame[2:6] = pack('f',float(rate)) + frame[2:6] = pack('f',float(rate)) frame[6] = Const.TAIL self.serial.write(frame) print('[SEND1] ',frame) @@ -110,78 +110,78 @@ class Device: items = [] count = 0 limit = 1000 - if not self.running(): - return items; - if self.serial.readable(): - buildingFrame = 0 - while (self.serial.inWaiting() or count<(self.frame_len(self.inbuf)-1)): ###### - char = self.serial.read() - count +=1 - if char == chr(Const.TAIL) and buildingFrame and (len(self.inbuf))== self.frame_len(self.inbuf)-1: - self.inbuf.append(char) - #print("[TAIL]") - line = "".join(self.inbuf) - print(self.inbuf) - time.sleep(0.001) - #self.printHex(line) - item = self._parse_ascii(line) # analyze the received data - items.append(item) - buildingFrame = 0 # finished building one frame - #print ("BF set to 0") - self.inbuf = [] - count = 0 - elif char == chr(Const.HEADER) and buildingFrame==0: - self.inbuf = [] - buildingFrame = 1 - #print ("BF set to 1") - self.inbuf.append(char) - #print("[HEADER]") - #count +=1 - elif buildingFrame: - self.inbuf.append(char) - #print("[DT]") - #count +=1 - else: - #print("[ERROR] Byte Going Nowhere") - count = 0 - buildingFrame = 0 # reset the construction - #print ("BF set to 0!") - self.inbuf = [] - if count > limit: - count = 0 - print("[ERROR] Exceeded Read Limit") - break - return items - - - # auxilary function - def frame_len(self, frame): - if len(frame) < 3: - return -1 - dataType_snsType = ord(frame[1]) - dataNum = ord(frame[2]) - dataType = (0xE0&dataType_snsType)>>Const.SNS_BITS - snsType = 0x1F&dataType_snsType - #print(dataType_snsType) - #print(dataType) - #print(snsType) - #print(dataNum) - dataSize = Const.sizeMap[Const.typeMap[dataType]] - return (dataSize*dataNum+4) - - - def printHex(self, frame): - #print("PH") - frameLen = self.frame_len(frame) - i = 0 - while i limit: + count = 0 + print("[ERROR] Exceeded Read Limit") + break + return items + + + # auxilary function + def frame_len(self, frame): + if len(frame) < 3: + return -1 + dataType_snsType = ord(frame[1]) + dataNum = ord(frame[2]) + dataType = (0xE0&dataType_snsType)>>Const.SNS_BITS + snsType = 0x1F&dataType_snsType + #print(dataType_snsType) + #print(dataType) + #print(snsType) + #print(dataNum) + dataSize = Const.sizeMap[Const.typeMap[dataType]] + return (dataSize*dataNum+4) + + + def printHex(self, frame): + #print("PH") + frameLen = self.frame_len(frame) + i = 0 + while i>Const.SNS_BITS - snsType = 0x1F&dataType_snsType - state = State() - if snsType == Const.ACC_SNS: - line = line[3:15] - state.acc = unpack('3f',line) - elif snsType == Const.MAG_SNS: - line = line[3:9] - state.mag = unpack('3h',line) - elif snsType == Const.LGT_SNS: - state.light[0] = ord(line[3]) - elif snsType == Const.TCH_SNS: - line = line[3:11] - state.touch = sunpack('2f',line) - elif snsType == Const.ADC_SNS_1: - line = line[3:15] - state.a2d = unpack('6h', line) - else: - print('[ERROR] Nothing Happened!') - return state + #print("PA") + dataType_snsType = ord(line[1]); + dataNum = ord(line[2]); + dataType = (0xE0&dataType_snsType)>>Const.SNS_BITS + snsType = 0x1F&dataType_snsType + state = State() + if snsType == Const.ACC_SNS: + line = line[3:15] + state.acc = unpack('3f',line) + elif snsType == Const.MAG_SNS: + line = line[3:9] + state.mag = unpack('3h',line) + elif snsType == Const.LGT_SNS: + state.light[0] = ord(line[3]) + elif snsType == Const.TCH_SNS: + line = line[3:11] + state.touch = sunpack('2f',line) + elif snsType == Const.ADC_SNS_1: + line = line[3:15] + state.a2d = unpack('6h', line) + else: + print('[ERROR] Nothing Happened!') + return state diff --git a/vis/readme.txt b/vis/readme.txt index d95dc8d..b95ff1b 100644 --- a/vis/readme.txt +++ b/vis/readme.txt @@ -1,5 +1,5 @@ Main - Topleve main program Visual - gtk visualizations of sensor data Config - Saved configuration interface -Serial - Serial communication with mbed -Xively - interface to Xively +Device - Serial communication with mbed +Logger - interface to Xively diff --git a/yue/ascii.cpp b/yue/ascii.cpp new file mode 100644 index 0000000..629f5e4 --- /dev/null +++ b/yue/ascii.cpp @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------- + ## Receive Interruption of the Serial ## + -> used to receive & process user command + -> and configure the board accordingly + ---------------------------------------------------------------*/ +/*void serialRx_interrupt_userFriendlyVersion(){ + 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")){ + lgtTmr = interval; + } + if (strstr(buffer, "touch")){ + tchTmr = 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")){ + lgtEnable = false; + lgtTmr = LGT_SNS_DEFAULT; + } + if (strstr(buffer, "touch")){ + tchEnable = false; + tchTmr = TCH_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") && !lgtEnable){ + lgtEnable = true; + lgtTmr = LGT_SNS_DEFAULT; + } + if (strstr(buffer, "touch") && !tchEnable){ + tchEnable = true; + tchTmr = TCH_SNS_DEFAULT; + } + } + clock1.attach(&clock1_interrupt,TIME_ACCURACY); +} +*/ diff --git a/yue/main.cpp b/yue/main.cpp index d3addb1..e08c06d 100644 --- a/yue/main.cpp +++ b/yue/main.cpp @@ -1,335 +1,342 @@ +#include +#include + #include "mbed.h" #include "TSISensor.h" // Touch Sensor #include "MAG3110.h" // Magnetic Sensor #include "MMA8451Q.h" // AcceleroMeter -//#include "DataFrame.h" - - - -#define MMA8451_I2C_ADDRESS (0x1d<<1) // acc sensor address -#define TIME_ACCURACY 0.1 -#define LGT_SNS_DEFAULT 2 // default collecting interval in seconds -#define ACC_SNS_DEFAULT 2 -#define MAG_SNS_DEFAULT 2 -#define TCH_SNS_DEFAULT 2 - -// Parameters in Data Frame -// TODO: need to sync with the pc program -#define HEADER 0x02 +#include "serial_dma.h" // AcceleroMeter -#define SNS_BITS 5 -#define LGT_SNS 0x00 -#define ACC_SNS 0x01 -#define MAG_SNS 0x02 -#define TCH_SNS 0x03 -#define ADC_SNS_1 0x04 - -#define INT 0 -#define LONG 1 -#define FLOAT 2 -#define DOUBLE 3 -#define TAIL 0x0A // '\n' - -// Command Frame -#define START 0 -#define STOP 1 -#define SET_INT 2 +//#include "DataFrame.h" +#define CLAMP(x, min, max) \ + ((x) < (min) ? (min) : \ + (x) > (max) ? (max) : (x)) +#define MMA8451_I2C_ADDRESS (0x1d<<1) // acc sensor address +#define TIME_ACCURACY 0.01 + +#define ACC_SNS_DEFAULT 0.1 // default collecting interval in seconds +#define MAG_SNS_DEFAULT 1.0 +#define LGT_SNS_DEFAULT 1.0 +#define TCH_SNS_DEFAULT 1.0 +#define A2D_SNS_DEFAULT 1.0 + +#define MIN_RATE 1E-4 // 1 kHz +#define MAX_RATE 10.0 // 0.1 Hz + +// Common Frame Information +#define HEADER 0x02 +#define TAIL 0x0A // '\n' + +#define MAX_FRAME_SIZE 256 + +typedef enum { + ACC_SNS, + MAG_SNS, + LGT_SNS, + TCH_SNS, + A2D_SNS, +} sns_t; + +typedef enum { + INT, + LONG, + FLOAT, + DOUBLE, +} type_t; + +typedef enum { + START, + STOP, + SET_INT, +} oper_t; + +// Data Frame Information +typedef struct { + uint8_t header; + struct { + uint8_t sns : 5; + uint8_t type : 3; + } bits; + uint8_t count; + uint8_t data[]; +} state_t; + +// Command Frame Information +typedef struct { + uint8_t header; + struct { + uint8_t sns : 5; + uint8_t oper : 3; + } bits; + float interval; +} command_t; -#define MAX_FRAME_LEN 255 // Define Devices & Pins -MMA8451Q accSensor(PTE25, PTE24, MMA8451_I2C_ADDRESS); -TSISensor touchSensor; -MAG3110 magSensor(PTE25, PTE24); +MMA8451Q accSensor(PTE25, PTE24, MMA8451_I2C_ADDRESS); +MAG3110 magSensor(PTE25, PTE24); +TSISensor tchSensor; +AnalogIn lgtSensor(PTE22); +AnalogIn a2dSensor(A0); + Serial serial(USBTX, USBRX); Ticker clock1; -AnalogIn lightSensor(PTE22); - // Global Variables // Initial interval: in seconds -float lgtTmr = LGT_SNS_DEFAULT; float accTmr = ACC_SNS_DEFAULT; float magTmr = MAG_SNS_DEFAULT; float tchTmr = TCH_SNS_DEFAULT; +float lgtTmr = LGT_SNS_DEFAULT; +float a2dTmr = A2D_SNS_DEFAULT; +bool accEnable = true; +bool magEnable = false; bool lgtEnable = false; -bool accEnable = false; -bool magEnable = true; bool tchEnable = false; +bool a2dEnable = false; + +bool useStr = true; +bool useHex = false; +bool useBin = false; + +uint8_t txFrame[MAX_FRAME_SIZE]; +uint8_t rxFrame[MAX_FRAME_SIZE]; + +// Prototypes +void clock1_interrupt(void); +void serialRx_interrupt(void); + +void sendAccInfo(void); +void sendMagInfo(void); +void sendLgtInfo(void); +void sendTchInfo(void); +void sendA2dInfo(void); + +int calDataSize(uint8_t); +int packToFrame(uint8_t *frame, sns_t snsType, type_t dataType, int dataNum, void *data); + +void printStr(const char *str, ...); +void printHex(uint8_t *frame, int len); +void printBin(uint8_t *frame, int len); -void clock1_interrupt(); -void serialRx_interrupt(); -void sendLightInfo(); -void sendAccInfo(); -void sendMagInfo(); -void sendTouchInfo(); -int packToFrame(char*, char, char, int, void*); -char* floatToByte(float); -float byteToFloat(char*); -int calDataSize(char); -void printHex(char*); -void sendFrame(char*, int); - - -int main() { +/******** + * Main * + ********/ + +int main(void) { // Initialization // Interruption Declarations clock1.attach(&clock1_interrupt, TIME_ACCURACY); // maximun accuracy be 0.1s serial.attach(&serialRx_interrupt, Serial::RxIrq); // receive interrupt for serialS + serial.baud(115200); magSensor.begin(); - serial.printf("\r\n============= Start of the program ============\r\n"); + sdma_setup(UART0, 0); + + printStr("\r\n============= Start of the program ============\r\n"); + while(1){ wait(3); } } +/********************** + * Interrupt handlers * + **********************/ -/*--------------------------------------------------------------- - ## Receive Interruption of the Serial ## - -> used to receive & process user command - -> and configure the board accordingly - ---------------------------------------------------------------*/ -/*void serialRx_interrupt_userFriendlyVersion(){ - 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")){ - lgtTmr = interval; - } - if (strstr(buffer, "touch")){ - tchTmr = 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")){ - lgtEnable = false; - lgtTmr = LGT_SNS_DEFAULT; - } - if (strstr(buffer, "touch")){ - tchEnable = false; - tchTmr = TCH_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") && !lgtEnable){ - lgtEnable = true; - lgtTmr = LGT_SNS_DEFAULT; - } - if (strstr(buffer, "touch") && !tchEnable){ - tchEnable = true; - tchTmr = TCH_SNS_DEFAULT; - } - } - clock1.attach(&clock1_interrupt,TIME_ACCURACY); -} -*/ - -void serialRx_interrupt(){ // Byte version +void serialRx_interrupt(void) { // Byte version clock1.detach(); // close the interrupt temporarily int i = 0; - char frame[MAX_FRAME_LEN]; - char ch = serial.getc(); + uint8_t ch = serial.getc(); + while (ch!=HEADER){ if (serial.readable()){ ch = serial.getc(); } else{ - serial.printf("[ERROR] broken data!\r\n"); - clock1.attach(&clock1_interrupt,TIME_ACCURACY); + printStr("[ERROR] broken data!\r\n"); + clock1.attach(&clock1_interrupt, TIME_ACCURACY); return; } } + //TODO: ticker for time out while (serial.readable()){ - frame[i] = ch; - if (ch=='\n'){ + rxFrame[i] = ch; + if (ch=='\n') break; - } ch = serial.getc(); i++; } - frame[++i] = '\0'; - float interval=-1; - char snsType = frame[1]|0x1F; - char oper = (frame[1]|0xE0)>>SNS_BITS; // operation type - if (oper==SET_INT){ - memcpy(&interval,&frame[2],4); - if (interval<0.0001||interval>10){ - interval = 1; - } - } + rxFrame[++i] = '\0'; + + // Cast to command and + command_t *cmd = (command_t *)rxFrame; + + // Validate interval + sns_t snsType = (sns_t )cmd->bits.sns; + oper_t operType = (oper_t)cmd->bits.oper; + float interval = CLAMP(cmd->interval, MIN_RATE, MAX_RATE); + + // Save value to global data switch(snsType){ case ACC_SNS: - { - switch(oper){ + switch(operType){ case START: accEnable = true; break; case STOP: accEnable = false; break; case SET_INT: accTmr = interval; break; } - } + break; + case MAG_SNS: - { - switch(oper){ + switch(operType){ case START: magEnable = true; break; case STOP: magEnable = false; break; case SET_INT: magTmr = interval; break; } - } + break; + case LGT_SNS: - { - switch(oper){ + switch(operType){ case START: lgtEnable = true; break; case STOP: lgtEnable = false; break; case SET_INT: lgtTmr = interval; break; } - } + break; + case TCH_SNS: - { - switch(oper){ + switch(operType){ case START: tchEnable = true; break; case STOP: tchEnable = false; break; case SET_INT: tchTmr = interval; break; } - } + break; + + case A2D_SNS: + switch(operType){ + case START: a2dEnable = true; break; + case STOP: a2dEnable = false; break; + case SET_INT: a2dTmr = interval; break; + } + break; } - clock1.attach(&clock1_interrupt,TIME_ACCURACY); + + clock1.attach(&clock1_interrupt, TIME_ACCURACY); } -void clock1_interrupt(){ +void clock1_interrupt(void){ static int accCnt; static int magCnt; static int lgtCnt; static int tchCnt; + static int a2dCnt; accCnt++; magCnt++; lgtCnt++; tchCnt++; + a2dCnt++; // TODO: send data through Serial - if (lgtEnable && (lgtCnt<0 || lgtCnt>=lgtTmr/TIME_ACCURACY)){ - sendLightInfo(); - lgtCnt = 0; + if (accEnable && (accCnt<0 || accCnt>=accTmr/TIME_ACCURACY)){ + sendAccInfo(); + accCnt = 0; } if (magEnable && (magCnt<0 || magCnt>=magTmr/TIME_ACCURACY)){ sendMagInfo(); magCnt = 0; } + if (lgtEnable && (lgtCnt<0 || lgtCnt>=lgtTmr/TIME_ACCURACY)){ + sendLgtInfo(); + lgtCnt = 0; + } if (tchEnable && (tchCnt<0 || tchCnt>=tchTmr/TIME_ACCURACY)){ - sendTouchInfo(); + sendTchInfo(); tchCnt = 0; } - if (accEnable && (accCnt<0 || accCnt>=accTmr/TIME_ACCURACY)){ - sendAccInfo(); - accCnt = 0; + if (a2dEnable && (a2dCnt<0 || a2dCnt>=a2dTmr/TIME_ACCURACY)){ + sendA2dInfo(); + a2dCnt = 0; } -} -void sendLightInfo(){ - char frame[MAX_FRAME_LEN]; - float lightData = lightSensor.read(); - packToFrame(frame,LGT_SNS,FLOAT,1,&lightData); - serial.printf("[LGT] %s\r\n", frame); - //printHex(frame); - //serial.printf("[LGT] Light Intensity=%f\r\n", lightSensor.read()); + sdma_flush(); } +/******************* + * Sensors reading * + *******************/ -void sendTouchInfo(){ - char frame[MAX_FRAME_LEN]; - float touchData[2]; - touchData[0] = touchSensor.readPercentage(); - touchData[1] = touchSensor.readDistance(); - packToFrame(frame,TCH_SNS,FLOAT,2,touchData); - serial.printf("[TCH] %s\r\n", frame); - //printHex(frame); +void sendAccInfo(void){ + float accData[3]; + accData[0] = accSensor.getAccX(); + accData[1] = accSensor.getAccY(); + accData[2] = accSensor.getAccZ(); + int len = packToFrame(txFrame, ACC_SNS, FLOAT, 3, accData); + + printStr("[ACC] accX=%-2.4f accY=%-2.4f accZ=%-2.4f\r\n", + accData[0], accData[1], accData[2]); + printHex(txFrame, len); + printBin(txFrame, len); } -void sendMagInfo(){ - char frame[MAX_FRAME_LEN]; +void sendMagInfo(void){ int magData[3]; - magSensor.getValues(magData, magData+1, magData+2); - //serial.printf("[MAG] magX=%d magY=%d magZ=%d\r\n",magData[0],magData[1],magData[2]); - int len = packToFrame(frame,MAG_SNS,INT,3,magData); - sendFrame(frame, len); - //memcpy(magData, &frame[3], 2); - //serial.printf("[MAG] %d\r\n", magData[0]); - //printHex(frame); + magSensor.getValues(&magData[0], &magData[1], &magData[2]); + int len = packToFrame(txFrame, MAG_SNS, INT, 3, magData); + + printStr("[MAG] magX=%d magY=%d magZ=%d\r\n", + magData[0], magData[1], magData[2]); + printHex(txFrame, len); + printBin(txFrame, len); } -void sendAccInfo(){ - // get acc data - char frame[MAX_FRAME_LEN]; - float accData[3]; - accData[0] = accSensor.getAccX(); - accData[1] = accSensor.getAccY(); - accData[2] = accSensor.getAccZ(); - packToFrame(frame, ACC_SNS,FLOAT,3,accData); - serial.printf("[ACC] %s\n\r", frame); - //int num = int(frame[2]); - //memcpy(&accZ, &frame[3], 4); - // send acc data - //printHex(frame); +void sendLgtInfo(void){ + float lgtData = lgtSensor.read(); + int len = packToFrame(txFrame, LGT_SNS, FLOAT, 1, &lgtData); + + printStr("[LGT] intensity=%f\r\n", + lgtSensor.read()); + printHex(txFrame, len); + printBin(txFrame, len); } -int calDataSize(char dataType){ + +void sendTchInfo(void){ + float tchData[2]; + tchData[0] = tchSensor.readPercentage(); + tchData[1] = tchSensor.readDistance(); + int len = packToFrame(txFrame, TCH_SNS, FLOAT, 2, tchData); + + printStr("[TCH] force=%0.4f distance=%2.2f\r\n", + tchData[0], tchData[1]); + printHex(txFrame, len); + printBin(txFrame, len); +} + +void sendA2dInfo(void){ + float a2dData[6]; + a2dData[0] = 0; + a2dData[1] = 0; + a2dData[2] = 0; + a2dData[3] = 0; + a2dData[4] = 0; + a2dData[5] = 0; + int len = packToFrame(txFrame, A2D_SNS, FLOAT, 2, a2dData); + + printStr("[A2D] data=%2.2f %2.2f %2.2f %2.2f %2.2f %2.2f\r\n", + a2dData[0], a2dData[1], a2dData[2], + a2dData[3], a2dData[4], a2dData[5]); + printHex(txFrame, len); + printBin(txFrame, len); +} + +/******************** + * Helper functions * + ********************/ + +int calDataSize(uint8_t dataType){ switch(dataType){ case INT: return 2; case LONG: return 4; @@ -339,31 +346,53 @@ int calDataSize(char dataType){ return 4; } -void printHex(char* frame){ - int dataType = frame[1]&0xE0; - int dataSize = calDataSize(dataType); - int dataNum = frame[2]; - for (int i=0; i<4+dataSize*dataNum; i++){ - serial.printf("0x%x ",frame[i]); - } - serial.printf("\r\n"); +/******************* + * Frame functions * + *******************/ + +int packToFrame(uint8_t *frame, sns_t snsType, type_t dataType, int dataNum, void *data){ + int size = dataNum + calDataSize(dataType); + state_t *state = (state_t*)frame; + uint8_t *tail = &state->data[size]; + + state->header = HEADER; + state->bits.sns = snsType; + state->bits.type = dataType; + state->count = dataNum;; + memcpy(&state->data, data, size); + tail[0] = TAIL; + tail[1] = '\0'; + + return (3 + size + 1); } -int packToFrame(char* frame, char snsType,char dataType, int dataNum, void* data){ - int dataSize = calDataSize(dataType); - frame[0] = HEADER; - frame[1] = (snsType|(dataType< + +#include +#include +#include +#include + +#include "serial_dma.h" + +/* Defines */ +#define UART sdma_uart +#define DMA (&(DMA0->DMA[sdma_chan])) +#define MUX ((dma_mux_t*)&(DMAMUX0->CHCFG[sdma_chan])) + +#define NUM 2 +#define LEN 1024 + +/* Types */ +typedef struct {uint8_t CHCFG;} dma_mux_t; + +/* Setup data */ +static UART0_Type *sdma_uart; +static int sdma_chan; + +/* Error logging */ +static int sdma_stuck; +static int sdma_full; + +/* Data buffering */ +static int sdma_index; +static int sdma_length[NUM]; +static uint8_t sdma_queue[NUM][LEN]; + +/* DMA Functions */ +void sdma_setup(UART0_Type *uart, int channel) +{ + // Save configuration data + sdma_uart = uart; + sdma_chan = channel; + + // Enable DMA Cock + SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK; + SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; + + // Reset channel + DMA->DSR_BCR = DMA_DSR_BCR_DONE_MASK; + + // Configure DMA transfer + DMA->DAR = (uint32_t)&UART0->D; + DMA->DCR = DMA_DCR_CS_MASK | + DMA_DCR_SINC_MASK | + DMA_DCR_SSIZE(1) | + DMA_DCR_DSIZE(1) | + DMA_DCR_D_REQ_MASK; + + // Configure DMA Mux + MUX->CHCFG = DMAMUX_CHCFG_SOURCE(3) | + DMAMUX_CHCFG_ENBL_MASK; + + // Configure UART for DMA Channel 0 + UART->C5 |= UART0_C5_TDMAE_MASK; +} + +/* Write binary data out the DMA output queue */ +void sdma_write(void *data, int len) +{ + if (sdma_length[sdma_index] + len > LEN) { + sdma_full++; + } else { + int pos = sdma_length[sdma_index]; + void *dst = &sdma_queue[sdma_index][pos]; + memcpy(dst, data, len); + sdma_length[sdma_index] += len; + } +} + +/* Write ASCII data to the output queue */ +void sdma_vprintf(const char *fmt, va_list ap) +{ + int pos = sdma_length[sdma_index]; + void *dst = &sdma_queue[sdma_index][pos]; + sdma_length[sdma_index] += + vsnprintf((char*)dst, LEN-pos, fmt, ap); +} + +void sdma_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + sdma_vprintf(fmt, ap); + va_end(ap); +} + +/* Trigger DMA transmit of the current output queue + * and swap buffers so we can write into unused space */ +void sdma_flush(void) +{ + if (sdma_length[sdma_index] == 0) + return; + + // Wait for transmit complete + while (DMA->DSR_BCR & DMA_DSR_BCR_BCR_MASK) + sdma_stuck++; + + // Reset channel + DMA->DSR_BCR = DMA_DSR_BCR_DONE_MASK; + + // Set source address and length + DMA->SAR = (uint32_t)&sdma_queue[sdma_index]; + DMA->DSR_BCR = DMA_DSR_BCR_BCR(sdma_length[sdma_index]); + + // Enable DMA transmit + DMA->DCR |= DMA_DCR_ERQ_MASK; + + // Swap buffers + sdma_length[sdma_index] = 0; + sdma_index = (sdma_index + 1) % NUM; +} diff --git a/yue/serial_dma.h b/yue/serial_dma.h new file mode 100644 index 0000000..a0a5763 --- /dev/null +++ b/yue/serial_dma.h @@ -0,0 +1,28 @@ +#ifndef SERIAL_DMA_H +#define SERIAL_DMA_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Setup */ +void sdma_setup(UART0_Type *uart, int channel); + +/* Write */ +void sdma_write(void *data, int len); + +/* print */ +void sdma_vprintf(const char *fmt, va_list ap); +void sdma_printf(const char *fmt, ...); + +/* Write */ +void sdma_flush(void); + +#ifdef __cplusplus +} +#endif + +#endif