Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Data-Management-Honka
BluetoothComm.cpp
- Committer:
- mzling
- Date:
- 2014-12-17
- Revision:
- 2:be605799793f
- Child:
- 3:14050370593a
File content as of revision 2:be605799793f:
#include "mbed.h" #include "MODSERIAL.h" #include "BluetoothComm.h" #include "init.h" //#include "SDFile.cpp" #include <string> #include <map> //Variable indices for setValues: setValues should take an array of length NUMVARS + NUMREADONLYPARAMS = 34. //Map of variables to array indices is as follows: //0 = Torso Angle, 1 = Left Knee Angle, 2 = Right Knee Angle, 3 = Left Hip angle, 4 = Right Hip angle, 5 = Left Hip Torque, 6 = Right Hip Torque //8 = Exo State/Left Knee State/Right Knee State 9 = Torso Ref. Angle, 10 = Left Hip Ref. Angle, 11 = Right Hip Ref. Angle //12 = KP Stance, 13 = KP Swing, 14 = KP Standing, 15 = KP Sitting, 16 = KP Standing up, 17 = KP Sitting down //18 = KD Stance, 19 = KD Swing, 20 = KD Standing, 21 = KD Sitting, 22 = KD Standing up, 23 = KD sitting down //24 = Standing angle, 25 = Sitting angle, 26 = Bent Forward Angle, 27 = Forward Angle, 28 = Rear Angle, 29 = IMU Angle //30 = Knee Full Retract, 31 = Knee Full Extend, 32 = Lock Time, 33 = Rate BluetoothComm::BluetoothComm(PinName tx, PinName rx): rn42(tx, rx), len(0), counter(0), inMsg(false), numVars(22), numReadOnlyParams(12), escapesNeeded(8) { rn42.baud(9600); printf("Started BTComm init \r\n"); // rn42.baud(115200); int temp1[] = {0,1,2,3,4,8,9,10, -1}; for (int i = 0; i < escapesNeeded+1; i++) { escapeNeeded[i] = temp1[i]; } std::string temp2[] = {"KPStance", "KPSwing", "KPStanding", "KPSitting", "KPStandUp", "KPSitdown", "KDStance", "KDSwing", "KDStanding", "KDSitting", "KDStandUp", "KDSitDown", "StandingAngle", "SittingAngle", "BentForwardAngle", "ForwardAngle", "RearAngle", "IMUAngle", "KneeFullRetract", "KneeFullExtend", "LockTime", "Rate", "TorsoAng", "LKneeAng", "RKneeAng", "LHipAng", "RHipAng", "LHipTorque", "RHipTorque", "ExoAndKneeStates", "TorsoRefAngle", "LHipRefAngle", "RHipRefAngle", "Charge"}; //Populate the map of indices to param names for (int j = 0; j < (numVars + numReadOnlyParams); j += 1) { indexMap[j] = temp2[j]; } //Fill the parameter map with data from SD card readDataFromSD(); readParamsFromSD(); } //Reads read-only data from SD card, and fills in the parameter map void BluetoothComm::readDataFromSD() { / int *arr = readData.read(arr, numVars); for (int i = 0; i < numReadOnlyParams; i += 1) { paramMap[indexMap[i + numVars]] = arr[i]; } } //Reads editable parameters from SD card, and fills in the parameter map void BluetoothComm::readParamsFromSD() { int *arr = param.read(arr, numVars); for (int i = 0; i < numVars; i += 1) { paramMap[indexMap[i]] = arr[i]; } } //Calculates parity--0 if c even, 1 if odd bool BluetoothComm::parity(short c) { bool p = false; while (c != 0) { p = !p; c = (short) (c & (c-1)); } return p; } //Calculates checksum of char array, sum of all chars in array char* BluetoothComm::checkSum(char* b, int len) { char* checksum = (char*)malloc(3*sizeof(char)); short sum = 0; for (int i = 0; i < len; i += 1) { sum += ((short) b[i] & 0xff); } //sum = (short) (-1*sum); checksum[1] = (char) ((sum >> 8) & 0xff); checksum[2] = (char) (sum & 0xff); char check = (char) (sum & 0xff); //Sets escape character if the checksum contains START or END if (check == START || check == END) { checksum[0] = 1; checksum[2] = (char) (checksum[2] & 0x1); } else { checksum[0] = 0; } return checksum; } //Sends error message void BluetoothComm::sendError(char errCode) { rn42.putc(START); rn42.putc(errCode); rn42.putc(END); rn42.putc(0); rn42.putc(0); rn42.putc(0); } //Sets charge level void BluetoothComm::setCharge(short level) { // readOnlyParams[11] = level; paramMap["Charge"] = level; } //Sends the speified char array void BluetoothComm::send(char *cmd) { for (int i = 0; i < 50; i++) { rn42.putc(cmd[i]); } } //Sets the parameter map, based on the input map NEWVALUES void BluetoothComm::setValues(std::map<string, short> newValues) { for (std::map<string, short>::iterator it = newValues.begin(); it != newValues.end(); ++it) { paramMap[it->first] = it->second; } } //Writes the editable params. stored in paramMap to the SD card void BluetoothComm::writeParamsToSDCard() { int paramValues[numVars]; for (int i = 0; i < numVars; i += 1) { paramValues[i] = (int) paramMap[indexMap[i]]; } param.write(paramValues, numVars); } //Write the read-only values stored in paramMap to the SD card void BluetoothComm::writeDataToSDCard() { int dataValues[numReadOnlyParams]; for (int i = 0; i < numReadOnlyParams; i += 1) { dataValues[i] = (int) paramMap[indexMap[i + numVars]]; } param.write(dataValues, numReadOnlyParams); } //Sends the paramList with START/END, parity bits, and a checksum void BluetoothComm::sendValues(char* paramList) { char msg[2*numVars+6]; int len=2; //printf("Sending values \r\n"); msg[0] = START; msg[1] = 0; for (int i=0; i < numVars; i++) { if (i == 21) { //printf("On final loop \r\n"); } if (paramList[i] != 0xff) { short s = (short)((i << 8) | paramList[i]); //printf("In sendValues, calculating parity of %x\r\n", s); if (parity(s)) { //printf("%x requires TRUE parity bit\r\n", s); msg[len] = (char)(i | 0x40); len += 1; } else { //printf("%x requires FALSE parity bit\r\n", s); msg[len] = (char)i; len += 1; } msg[len] = paramList[i]; len += 1; } } msg[len] = END; len += 1; char* checksum = checkSum(msg, len); msg[len] = checksum[0]; msg[len+1] = checksum[1]; msg[len+2] = checksum[2]; len += 3; for (int j = 0; j < len; j++) { //printf("Sending char %x \r\n", msg[j]); rn42.putc(msg[j]); } memcpy(lastCmd, msg, 50); free(checksum); return ; } //Sends readONly Parameters, with START/END and checksum void BluetoothComm::sendReadOnlyValues() { int msgLen = 2*numReadOnlyParams+escapesNeeded+7; char message[msgLen]; message[0] = START; message[1] = 0; message[2] = READONLY_IND; int msgInd = 3; int escapes = 0; //printf("%d readonly parameters", numReadOnlyParams); for (int i = 0; i < numReadOnlyParams; i++) { if (i == escapeNeeded[escapes]) { //printf("Escape char. needed at index %d \r\n", i); //char conflict = (char)(readOnlyParams[i] & 0xff); char conflict = (char)(paramMap[indexMap[i+numVars]] & 0xff); //printf("%x possibly has a conflict in %x \r\n", readOnlyParams[i], conflict); escapes += 1; //message[msgInd+1] = (char) (readOnlyParams[i] >> 8); message[msgInd+1] = (char) (paramMap[indexMap[i+numVars]] >> 8); //printf("Set msgInd+1 to %x \r\n", message[msgInd+1]); if (conflict == (char) 0xfe) { message[msgInd] = 1; message[msgInd+2] = 0xfc; } else if (conflict == (char) 0xff) { message[msgInd] = 1; message[msgInd+2] = 0xfd; } else { message[msgInd] = 0; message[msgInd+2] = conflict; } msgInd += 3; } else { // message[msgInd] = (char) (readOnlyParams[i] >> 8); // message[msgInd+1] = (char) (readOnlyParams[i] & 0xff); message[msgInd] = (char) (paramMap[indexMap[i+numVars]] >> 8); message[msgInd+1] = (char) (paramMap[indexMap[i+numVars]] & 0xff); msgInd += 2; } } message[msgLen-4] = END; char* checksum = checkSum(message, msgLen-3); message[msgLen-3] = checksum[0]; message[msgLen-2] = checksum[1]; message[msgLen-1] = checksum[2]; //printf("Sending the following readONly values: \r\n"); for (int j=0; j < msgLen; j++) { //printf("%x \r\n", message[j]); rn42.putc(message[j]); } memcpy(lastCmd, message, 50); free(checksum); //printf("Finished sending readOnly values \r\n"); } //Checks the message with length len. Checks for START and END in correct spots, parity, all data and variable byte in proper range, and correct checksum bool BluetoothComm::msgCheck(char* message, int len) { if (message[0] != START) { //printf("Improper START or END \r\n"); sendError(START_ERR); return false; } if (message[len-4] != END) { sendError(END_ERR); return false; } bool write = message[2] & 0x80; for (int i=2; i < len-5; i+=2) { if (i == 2 && message[i] == READONLY_IND) { break; } if (i == (len-5) && message[i] == READONLY_IND) { break; } if (((message[i] & 0x80) !=0) && !write) { //printf("Does not match READ format \r\n"); sendError((char)(((message[i] & 0x3f) << 3) | RW_ERR)); return false; } if (((message[i] & 0x80) != 0x80) && write) { //printf("char %x Does not match WRITE format \r\n", message[i]); sendError((char)(((message[i] & 0x3f) << 3) | RW_ERR)); return false; } short s; if (write) { s = (short) ((message[i] << 8) | message[i+1]); } else { s = (short) (message[i] << 8); } bool parity1 = (s & 0x4000) != 0; if (parity1 != parity(s & 0x4000)) { //printf("Parity error in VAR char \r\n"); sendError((char) (((message[i] & 0xbf) << 3) | PARITY_ERR)); return false; } char c = message[i] & 0x3f; char c2 = message[i+1]; if ((int) c < 0 || (int) c > numVars) { //printf("VAR char out of range \r\n"); sendError((char) (((message[i] & 0xbf) << 3) | VAR_ERR)); return false; } if ((int) c2 < 0 || (int) c2 > 100) { //printf("DATA char out of range"); sendError((char) (((message[i] & 0xbf) << 3) | DATA_ERR)); return false; } } char* checksum = checkSum(message, len-3); if (checksum[0] != message[len-3]) { //printf("Checksum error in char 0, expected %x but got %x \r\n", checksum[0], message[len-3]); free(checksum); sendError(CHECKSUM_ERR); return false; } if (checksum[1] != message[len-2]) { //printf("Checksum error in char 1, expected %x but got %x \r\n", checksum[1], message[len-2]); free(checksum); sendError(CHECKSUM_ERR); return false; } if (checksum[2] != message[len-1]) { //printf("Checksum error in char 2, expected %x but got %x \r\n", checksum[2], message[len-1]); free(checksum); sendError(CHECKSUM_ERR); return false; } free(checksum); return true; } //Checks a received readOnly message void BluetoothComm::processReadOnly(char* message, int len) { //printf("Message is a ReadOnly \r\n"); if (!msgCheck(message, len)) { //printf("MSGCHECK failed on read! \r\n"); return; } failures = 0; //printf("Sending readOnly values \r\n"); sendReadOnlyValues(); } //Checks received READ message, and places requested data into an array void BluetoothComm::processRead(char* message, int len) { //If the received message is an error message, resend the last command if (message[2] == START) { failures += 1; if (failures < 5) { send(lastCmd); } else { failures = 0; } return; } if (!msgCheck(message, len)) { //printf("MSGCHECK failed on read! \r\n"); return; } failures = 0; //printf("Message is a read \r\n"); char paramList[numVars]; memset(paramList, 0xff, numVars); for (int i=2; i < len-5; i++) { char msg = message[i] & 0xbf; if ((msg & 0x80) != 0) { //printf("Got a non-read char %x...exiting \r\n", msg); return; } int index = msg & 0xff; //printf("Value at index %d requested \r\n", index); paramList[index] = paramMap[indexMap[index]]; } if (message[len-5] == READONLY_IND) { sendReadOnlyValues(); } sendValues(paramList); } //Checks received WRITE message and writes to localValues void BluetoothComm::processWrite(char* message, int len) { if (message[2] == START) { failures += 1; if (failures < 5) { send(lastCmd); } else { failures = 0; } return; } if (!msgCheck(message, len)) { //printf("MSGCHECK failed on write! \r\n"); return; } char paramList[numVars]; memset(paramList, 0xff, numVars); //printf("Message is a write \r\n"); for (int i=2; i < len-5; i+=2) { char msg = message[i] & 0xbf; if ((msg & 0x80) != 0x80) { return; } int index = msg & 0x7f; paramMap[indexMap[index]] = message[i+1]; paramList[index] = message[i+1]; //printf("Wrote %x to index %d of localValues \r\n", localValues[index], index); } sendValues(paramList); writeParamsToSDCard(); //SD_Card.write(localValues) //sendToControlBed(localValues+1, len-2) } //Checks if received message is a read, write or readonly void BluetoothComm::process (char* message, int len) { char c = message[2]; for (int i =0; i < len; i++) { printf("Message character: %x \r\n", message[i]); } if (c == READONLY_IND) { processReadOnly(message, len); return; } if ((c & 0x80) == 0) { processRead(message, len); return; } else { processWrite(message, len); return; } } //Warning: do not put print statements in the function attachment(); it will interfere with receiving messages void BluetoothComm::attachment() { if (rn42.readable()) { // //printf("rn42 is readable \r\n"); data=rn42.getc(); // if (data != NULL) { char b = data & 0xff; //printf("Got char: %x \r\n", b); if (b != NULL or inMsg) { // printf("Got char non null: %x \r\n", b); } //This marks the START of a message if (inMsg == false and b == START) { // printf("Msg START received \r\n"); inMsg = true; counter = 3; curMsg[len] = b; len += 1; } else if (inMsg == true and b == START) { // printf("Second start received, terminating\r\n"); inMsg = false; counter = 0; memset(curMsg, 0, 50); rn42.rxBufferFlush(); process(msg, len); len = 0; } else if (inMsg || counter > 0 ) { // printf("inMsg or counter > 0 \r\n"); curMsg[len] = b; len += 1; if (!inMsg) { counter -= 1; } //Marks end of message, and starts processing if (counter <= 0) { // printf("End of message \r\n"); memset(msg, 0, 50); memcpy(msg, curMsg, 50); memset(curMsg, 0, 50); rn42.rxBufferFlush(); process(msg, len); len = 0; } } if (b == END) { inMsg = false; // rn42.putc(msg); } // } //rn42.putc(data); } }