I messed up the merge, so pushing it over to another repo so I don't lose it. Will tidy up and remove later
Dependencies: BufferedSerial FatFileSystemCpp mbed
VIPSSerialProtocol.cpp
00001 #include "LTCApp.h" 00002 #include <cstdint> 00003 #include <cstring> 00004 00005 #define _DisableUWB 0x00 00006 #define _EnableUWB 0x01 00007 #define _GetPPSTime 0x02 00008 #define _UWBData_Legacy 0x03 00009 #define _UWBData_MOCAP 0x11 00010 #define _UWBFitted 0x04 00011 #define _VBOXReady 0x05 00012 #define _SetDeltaTime 0x07 00013 00014 #define IdleTxBuffer (txBuf == TXBuffer1)?TXBuffer2:TXBuffer1 00015 #define ActiveTxBuffer (txBuf == TXBuffer1)?TXBuffer1:TXBuffer2 00016 00017 00018 VIPSSerial::VIPSSerial(const PinName Tx, const PinName Rx) : _port(Tx,Rx) 00019 { 00020 messagePrt = 0; 00021 messageLength = 0; 00022 00023 pointCount = 0; 00024 nextPosition = 0; 00025 00026 outputPtr = NULL; 00027 statusMessage = 0; 00028 00029 enableAllUpdates = false; 00030 newFormatMsg = false; 00031 00032 queueLen = 0; 00033 00034 SmoothBy = 100; //was 500 00035 XSmoothTotal = 0; 00036 YSmoothTotal = 0; 00037 ZSmoothTotal = 0; 00038 SmoothRunning = false; 00039 00040 BypassMode = false; 00041 directTx = false; 00042 txBuf = TXBuffer1; 00043 waitingBytes = 0; 00044 TransmitFinished=false; 00045 //self=this; 00046 00047 nextPosition= 0; 00048 _outputMask = 0x44; 00049 _port.baud(115200); 00050 } 00051 00052 void VIPSSerial::run(void) 00053 { 00054 _port.attach(callback(this, &VIPSSerial::onSerialRx)); 00055 } 00056 00057 void VIPSSerial::bypassTx(char byte) 00058 { 00059 _port.putc(byte); 00060 } 00061 00062 void VIPSSerial::onTxTimeout() 00063 { 00064 TransmitFinished = true; 00065 } 00066 00067 void VIPSSerial::onSerialRx(void) 00068 { 00069 while (_port.readable()) { 00070 if (BypassMode) { 00071 vipsBypassRx(_port.getc()); 00072 } else if (directTx) { 00073 TxTimeout.attach_us(callback(this, &VIPSSerial::onTxTimeout), 200.0); 00074 if (waitingBytes < MaxBuffSize) 00075 txBuf[waitingBytes++] = _port.getc(); 00076 } else { 00077 messageInBuffer[messagePrt] = _port.getc(); 00078 if (messagePrt==0) { // look for header 00079 if ((messageInBuffer[0]==0x2A) || (messageInBuffer[0]==0x24)) { 00080 messagePrt=1; 00081 newFormatMsg=(messageInBuffer[0]==0x24); 00082 } 00083 } else if (newFormatMsg) { 00084 if (messagePrt < 4) { 00085 messagePrt++; 00086 if (messagePrt==4) { 00087 if (messageInBuffer[1]!=0xd9) 00088 messagePrt=0; 00089 messageLength = *(uint16_t*)(messageInBuffer+2); 00090 if ((messageLength>115) || (messageLength<34)) 00091 messagePrt = 0; 00092 } 00093 } else { 00094 messagePrt++; 00095 if (messagePrt == messageLength) { 00096 parsePostionInput_mocap(); 00097 messagePrt=0; 00098 } 00099 } 00100 } else { 00101 if (messagePrt==1) { 00102 if (messageInBuffer[1]<128) { // valid length 00103 messageLength = messageInBuffer[1]; 00104 messagePrt = 2; 00105 } else { 00106 messagePrt=0; 00107 } 00108 } else { // in the middle of a message 00109 messagePrt++; 00110 if (messagePrt==messageLength) { 00111 processRxMessage(); 00112 messagePrt=0; 00113 } 00114 } 00115 } 00116 } 00117 } 00118 } 00119 00120 void VIPSSerial::processRxMessage() 00121 { 00122 if (!checkCRC(&messageInBuffer[0])) { 00123 pc.puts("VIPS CRC error\r\n"); 00124 return; 00125 } 00126 00127 switch (messageInBuffer[2]) { 00128 case _UWBFitted: 00129 sendAck(messageInBuffer[2]); 00130 break; 00131 case _EnableUWB: 00132 case _DisableUWB: // for all of these just send an ack. 00133 case _SetDeltaTime: 00134 sendAck(messageInBuffer[2]); 00135 break; 00136 case _GetPPSTime: 00137 sendVBOXTime(); 00138 // send vbox tick counter 00139 break; 00140 case _VBOXReady: 00141 if (ppsActive) { 00142 sendAck(_VBOXReady); 00143 } else { 00144 sendNack(_VBOXReady); 00145 } 00146 break; 00147 case _UWBData_Legacy: 00148 parsePostionInput_legacy(); 00149 break; 00150 default: 00151 break; 00152 } 00153 } 00154 00155 00156 void VIPSSerial::sendVBOXTime() 00157 { 00158 unsigned char timeValue[3]; 00159 uint32_t timeToSend = VBOXTicks-1; // we track time at next PPS, message requires time at the last PPS. 00160 timeValue[0]= timeToSend&0x00ff; 00161 timeValue[1]= (timeToSend>>8)&0x00ff; 00162 timeValue[2]= (timeToSend>>16)&0x00ff; 00163 queueResponse(_GetPPSTime,timeValue,3); 00164 // pc.printf("Sending time = %d ",VBOXTicks); 00165 } 00166 00167 void VIPSSerial::sendAck(unsigned char function) 00168 { 00169 unsigned char ack=0x01; 00170 sendResponse(function,&ack,1); 00171 } 00172 00173 void VIPSSerial::sendNack(unsigned char function) 00174 { 00175 unsigned char nack=0x00; 00176 sendResponse(function,&nack,1); 00177 } 00178 00179 void VIPSSerial::sendResponse(unsigned char function, unsigned char* data, int dataLen) 00180 { 00181 messageOutBuffer[0]=0xff; 00182 messageOutBuffer[1]=dataLen+4; 00183 messageOutBuffer[2]=function; 00184 for (int i=0; i<dataLen; i++) 00185 messageOutBuffer[i+3] = data[i]; 00186 VIPSSerial::getCRC(messageOutBuffer,dataLen+3,messageOutBuffer+dataLen+3); 00187 for (int i=0; i<dataLen+5; i++) 00188 _port.putc(messageOutBuffer[i]); 00189 } 00190 void VIPSSerial::queueResponse(unsigned char function, unsigned char* data, int dataLen) 00191 { 00192 messageOutBuffer[0]=0xff; 00193 messageOutBuffer[1]=dataLen+4; 00194 messageOutBuffer[2]=function; 00195 for (int i=0; i<dataLen; i++) 00196 messageOutBuffer[i+3] = data[i]; 00197 VIPSSerial::getCRC(messageOutBuffer,dataLen+3,messageOutBuffer+dataLen+3); 00198 queueLen = dataLen+5; 00199 } 00200 00201 void VIPSSerial::sendQueued() 00202 { 00203 if (queueLen) { 00204 for (int i=0; i<queueLen; i++) 00205 _port.putc(messageOutBuffer[i]); 00206 queueLen = 0; 00207 } 00208 } 00209 void VIPSSerial::sendDirectTX(unsigned char* data, int dataLen) 00210 { 00211 for (int i=0; i<dataLen; i++) 00212 _port.putc(data[i]); 00213 } 00214 00215 void VIPSSerial::sendQuiet() 00216 { 00217 _port.putc(0x07); 00218 _port.putc(0x05); 00219 _port.putc(0x02); 00220 _port.putc(0x5A); 00221 _port.putc(0x27); 00222 } 00223 00224 int VIPSSerial::getWaitingBuffer(unsigned char **TXBuffer, int *bytesToSend) 00225 { 00226 int bytes; 00227 if (TransmitFinished) { 00228 __disable_irq(); 00229 bytes = waitingBytes; 00230 txBuf = IdleTxBuffer; //see Macro At Start 00231 waitingBytes = 0; 00232 __enable_irq(); 00233 *bytesToSend = bytes; 00234 *TXBuffer = IdleTxBuffer; //See Macro at Start 00235 TransmitFinished = false; 00236 } else { 00237 bytes = 0; 00238 } 00239 return bytes; 00240 } 00241 00242 void VIPSSerial::getCRC(void *data, int len, void *checksum) 00243 { 00244 uint8_t *dataPtr = (uint8_t *)data; 00245 uint8_t *crcPtr = (uint8_t *)checksum; 00246 uint16_t crc = 0x0; 00247 unsigned char x; 00248 int byteCount = 0; 00249 00250 while ((len--) > 0) { 00251 x = (unsigned char)(crc >> 8 ^ dataPtr[byteCount++]); 00252 x ^= (unsigned char)(x >> 4); 00253 crc = (uint16_t)((crc << 8) ^ (x << 12) ^ (x << 5) ^ x); 00254 } 00255 crcPtr[0] = crc >> 8; 00256 crcPtr[1] = crc &0x00ff; 00257 } 00258 00259 bool VIPSSerial::checkCRC(unsigned char* data) 00260 { 00261 unsigned char expectedCRC[2]; 00262 int length = data[1]; 00263 if (data[0] == 0xff) // for response length doesn't include the header 00264 length++; 00265 VIPSSerial::getCRC(data, length-2, expectedCRC); 00266 if ((data[length-2]==expectedCRC[0]) && (data[length-1]==expectedCRC[1])) 00267 return true; 00268 return false; 00269 } 00270 00271 00272 bool VIPSSerial::checkNewPacketRC(unsigned char* data) 00273 { 00274 unsigned char expectedCRC[2]; 00275 int length = data[2] | (((int)data[3])<<8); 00276 VIPSSerial::getCRC(data, length-2, expectedCRC); 00277 if ((data[length-2]==expectedCRC[0]) && (data[length-1]==expectedCRC[1])) 00278 return true; 00279 return false; 00280 } 00281 00282 00283 void VIPSSerial::parsePostionInput_legacy() 00284 { 00285 printf("L"); 00286 uint8_t tmpBuffer[8]; 00287 int32_t tmpInt; 00288 memcpy((uint8_t *)(&tmpInt)+1, messageInBuffer+4, 3); 00289 tmpInt &= 0x00ffffff; 00290 lastPositions[nextPosition].pos.time = tmpInt*10; 00291 memcpy(tmpBuffer, messageInBuffer+7, 8); 00292 lastPositions[nextPosition].pos.X = *(double *)(tmpBuffer); 00293 memcpy(tmpBuffer, messageInBuffer+15, 8); 00294 lastPositions[nextPosition].pos.Y = *(double *)(tmpBuffer); 00295 memcpy((uint8_t *)(&tmpInt)+1, messageInBuffer+27, 3); 00296 if (tmpInt & 0x00800000) 00297 tmpInt |= 0xff000000; 00298 lastPositions[nextPosition].pos.Height = tmpInt/100.0f; 00299 lastPositions[nextPosition].pos.roll = 0; 00300 lastPositions[nextPosition].pos.pitch = 0; 00301 lastPositions[nextPosition].pos.yaw = 0; 00302 00303 if (enableAllUpdates) { 00304 printf("Add pos\r\n"); 00305 outputPtr = &outputPosition; 00306 memcpy(outputPtr,&(lastPositions[nextPosition].pos),sizeof(position)); 00307 } 00308 00309 nextPosition++; 00310 if (nextPosition == posHistoryLen) { 00311 nextPosition = 0; 00312 } 00313 pointCount++; 00314 } 00315 00316 void VIPSSerial::parsePostionInput_mocap() 00317 { 00318 if (!checkNewPacketRC(&messageInBuffer[0])) { 00319 pc.write("CRC error\r\n",11); 00320 return; 00321 } 00322 00323 // led1=!led1; 00324 00325 lastPositions[nextPosition].time = TimeSinceLastFrame.read_us(); 00326 uint32_t mask = *(uint32_t*)(messageInBuffer+4); 00327 int offset = 32; // end of position 00328 00329 lastPositions[nextPosition].pos.time = *(uint32_t*)(messageInBuffer+8); 00330 lastPositions[nextPosition].pos.X = *(double *)(messageInBuffer+12); 00331 lastPositions[nextPosition].pos.Y = *(double *)(messageInBuffer+20); 00332 lastPositions[nextPosition].pos.Height = *(float *)(messageInBuffer+28); 00333 00334 if (mask & 0x0001) 00335 lastPositions[nextPosition].pos.LLAPosition = true; 00336 00337 if (mask & 0x0002) { // parse status 00338 lastPositions[nextPosition].pos.beacons = messageInBuffer[offset++]; 00339 lastPositions[nextPosition].pos.solutionType = messageInBuffer[offset++]; 00340 lastPositions[nextPosition].pos.KFStatus = *(uint16_t*)(messageInBuffer + offset); 00341 offset +=2; 00342 } 00343 00344 if (mask & 0x0004) { 00345 lastPositions[nextPosition].pos.roll = *(float *)(messageInBuffer+offset); 00346 lastPositions[nextPosition].pos.pitch = *(float *)(messageInBuffer+offset+4); 00347 lastPositions[nextPosition].pos.yaw = *(float *)(messageInBuffer+offset+8); 00348 offset+=12; 00349 } else { 00350 lastPositions[nextPosition].pos.roll = 0; 00351 lastPositions[nextPosition].pos.pitch = 0; 00352 lastPositions[nextPosition].pos.yaw = 0; 00353 } 00354 00355 if (mask & 0x0008) { // velocity 00356 00357 offset+=8; 00358 } 00359 if (mask & 0x0010) {// vert velocity 00360 00361 offset+=4; 00362 } 00363 if (mask & 0x0020) { // pos uncertainty 00364 00365 offset+=12; 00366 if (mask & 0x0004) { // orientation uncertainty 00367 offset += 12; 00368 } 00369 if (mask & 0x0008) { // velocity uncertainty 00370 offset += 12; 00371 } 00372 } 00373 if (mask & 0x0040) { // accuracy 00374 lastPositions[nextPosition].pos.ID = *(messageInBuffer+offset+3); 00375 offset+=4; 00376 } 00377 if (mask & 0x0080) { // raw UWB 00378 offset+=24; 00379 } 00380 if (mask & 0x0100) { // raw IMU 00381 lastPositions[nextPosition].pos.x_accel = *(float *)(messageInBuffer+offset); 00382 lastPositions[nextPosition].pos.y_accel = *(float *)(messageInBuffer+offset+4); 00383 lastPositions[nextPosition].pos.z_accel = *(float *)(messageInBuffer+offset+8); 00384 offset+=12; 00385 lastPositions[nextPosition].pos.x_gyro = *(float *)(messageInBuffer+offset); 00386 lastPositions[nextPosition].pos.y_gyro = *(float *)(messageInBuffer+offset+4); 00387 lastPositions[nextPosition].pos.z_gyro = *(float *)(messageInBuffer+offset+8); 00388 offset+=12; 00389 //offset+=24; 00390 } else { 00391 lastPositions[nextPosition].pos.x_accel = 0.0f; 00392 lastPositions[nextPosition].pos.y_accel = 0.0f; 00393 lastPositions[nextPosition].pos.z_accel = 0.0f; 00394 offset+=12; 00395 lastPositions[nextPosition].pos.x_gyro = 0.0f; 00396 lastPositions[nextPosition].pos.y_gyro = 0.0f; 00397 lastPositions[nextPosition].pos.z_gyro = 0.0f; 00398 offset+=12; 00399 } 00400 00401 if (mask & 0x0200) {// rover info 00402 offset+=4; 00403 } 00404 if (mask & 0x0400) {// FIZ data 00405 offset+=4; 00406 } 00407 if (mask & 0x0800) {// Origin 00408 offset+=24; 00409 } 00410 if (mask & 0x1000) {// Beacon list 00411 memcpy(lastPositions[nextPosition].pos.UsedBeacons, messageInBuffer+offset, 12); 00412 lastPositions[nextPosition].pos.UsedBeaconsValid = true; 00413 offset+=12; 00414 } else 00415 lastPositions[nextPosition].pos.UsedBeaconsValid = false; 00416 00417 00418 if (UserSettings.AutoHyperSmooth) { 00419 int testValue = (lastPositions[nextPosition].pos.KFStatus & 0xE634); 00420 00421 if ( ( ( testValue & 0x400) == 0x400) && (!hyperSmoothEnabled)) { 00422 EnableSmoothing(true); 00423 //pc.write("Auto HS On\r\n", 12); 00424 } else if ( ( ( testValue & 0x400) != 0x400) && (hyperSmoothEnabled) && (!forcedHyperSmooth)) { 00425 EnableSmoothing(false); 00426 //pc.write("Auto HS Off\r\n", 13); 00427 } //Auto Hypersmooth 00428 } 00429 00430 00431 smoothOutputPacket(&(lastPositions[nextPosition].pos)); 00432 00433 if (enableAllUpdates) { 00434 // printf("Add pos\r\n"); 00435 outputPtr = &outputPosition; 00436 memcpy(outputPtr,&(lastPositions[nextPosition].pos),sizeof(position)); 00437 } 00438 00439 nextPosition++; 00440 if (nextPosition == posHistoryLen) { 00441 nextPosition = 0; 00442 } 00443 pointCount++; 00444 } 00445 00446 00447 // send a position output for the requested time. Times are based on the global TimeSinceLastFrame timer. 00448 position* VIPSSerial::sendPositionForTime(uint32_t timeValue) 00449 { 00450 // static uint32_t lastPoints = 0; 00451 if (pointCount < 2) 00452 return NULL; 00453 00454 __disable_irq(); // disable IRQ and make a copy of the data we're going to interpolate. 00455 int lastPoint = nextPosition - 1; 00456 int prevPoint = nextPosition - 2; 00457 if (lastPoint<0) 00458 lastPoint+=posHistoryLen; 00459 if (prevPoint<0) 00460 prevPoint+=posHistoryLen; 00461 00462 memcpy(&lastPos,&lastPositions[lastPoint], sizeof(struct posAndTime_s)); 00463 memcpy(&prevPos,&lastPositions[prevPoint], sizeof(struct posAndTime_s)); 00464 __enable_irq(); 00465 00466 // calculate timestamps as a function of time since last frame 00467 00468 uint64_t LastTimeMark = lastPos.time; 00469 uint64_t PrevTimeMark = prevPos.time; 00470 uint64_t timeValueUnwrap = timeValue; 00471 if (PrevTimeMark > LastTimeMark) 00472 LastTimeMark += ((uint64_t)1)<<32; 00473 if (LastTimeMark > timeValueUnwrap) 00474 timeValueUnwrap += ((uint64_t)1)<<32; 00475 00476 outputPosition.time = timeValueUnwrap-PrevTimeMark; // should be between 10,000 and 20,000 00477 00478 // interpolate uses the position times. Replace them with the internal clock counts. 00479 lastPos.pos.time = LastTimeMark-PrevTimeMark; // should be very close to 10,000 00480 prevPos.pos.time = 0; 00481 00482 // interpolate position to requested time. 00483 if (position::interp(&outputPosition, &(lastPos.pos), &(prevPos.pos))) { 00484 return &outputPosition; 00485 } 00486 00487 // interpolation failed. Return most recent location 00488 return &lastPos.pos; 00489 } 00490 00491 void VIPSSerial::smoothOutputPacket(position *posPtr) 00492 { 00493 xFilter.addPoint(posPtr->X); 00494 yFilter.addPoint(posPtr->Y); 00495 zFilter.addPoint(posPtr->Height); 00496 00497 if (hyperSmoothEnabled) { 00498 if (!SmoothRunning) { 00499 XSmoothTotal = posPtr->X * (SmoothBy - 1); 00500 YSmoothTotal = posPtr->Y * (SmoothBy - 1); 00501 ZSmoothTotal = posPtr->Height * (SmoothBy - 1); 00502 SmoothRunning = true; 00503 //pc.write("Seeded Filter\r\n",11); 00504 } 00505 //smooth the KF_X and KF_Y positions 00506 XSmoothTotal += posPtr->X; 00507 posPtr->X = XSmoothTotal / SmoothBy; 00508 XSmoothTotal -= posPtr->X; 00509 00510 YSmoothTotal += posPtr->Y; 00511 posPtr->Y = YSmoothTotal / SmoothBy; 00512 YSmoothTotal -= posPtr->Y; 00513 00514 ZSmoothTotal += posPtr->Height; 00515 posPtr->Height = ZSmoothTotal / SmoothBy; 00516 ZSmoothTotal -= posPtr->Height; 00517 } else { 00518 SmoothRunning = false; 00519 // pc.printf("filterX = %f\r\n",xFilter.lastValue()); 00520 posPtr->X = xFilter.lastValue(); 00521 posPtr->Y = yFilter.lastValue(); 00522 posPtr->Height = zFilter.lastValue(); 00523 } 00524 posPtr->roll = rollFilter.addPoint(posPtr->roll); 00525 posPtr->pitch = pitchFilter.addPoint(posPtr->pitch); 00526 posPtr->yaw = yawFilter.addPoint(posPtr->yaw); 00527 } 00528 00529 bool VIPSSerial::setFilters(struct UserSettings_s *settings) 00530 { 00531 if (settings->FilterXY) { 00532 if (!xFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00533 return false; 00534 if (!yFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00535 return false; 00536 } else { 00537 xFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00538 yFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00539 } 00540 00541 if (settings->FilterZ) { 00542 if (!zFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00543 return false; 00544 } else { 00545 zFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00546 } 00547 00548 if (settings->FilterRoll) { 00549 if (!rollFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00550 return false; 00551 } else { 00552 rollFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00553 } 00554 00555 if (settings->FilterPitch) { 00556 if (!pitchFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00557 return false; 00558 } else { 00559 pitchFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00560 } 00561 00562 if (settings->FilterYaw) { 00563 if (!yawFilter.makeFilter(settings->FilterOrder,settings->FilterFreq,settings->FilterRate)) 00564 return false; 00565 } else { 00566 yawFilter.makeFilter(0,settings->FilterFreq,settings->FilterRate); 00567 } 00568 return true; 00569 }
Generated on Thu Dec 15 2022 06:07:05 by 1.7.2