#include "inc/freeEMS.h"
#include "inc/flashWrite.h"
#include "inc/interrupts.h"
#include "inc/utils.h"
#include "inc/tableLookup.h"
#include "inc/blockDetailsLookup.h"
#include "inc/commsCore.h"
#include <string.h>
Go to the source code of this file.
Defines | |
#define | COMMSCORE_C |
Functions | |
void | populateBasicDatalog () |
Populate a basic datalog packet. | |
void | checksumAndSend () |
Checksum a packet and send it. | |
void | decodePacketAndRespond () |
Decode a packet and respond. | |
void | sendErrorIfClear (unsigned short errorID) |
Send an error if buffer free. | |
void | sendErrorBusyWait (unsigned short errorID) |
Send an error even if we must wait. | |
void | sendErrorInternal (unsigned short errorCode) |
Send an error. | |
void | sendDebugIfClear (unsigned char *message) |
Send a debug message if buffer free. | |
void | sendDebugBusyWait (unsigned char *message) |
void | sendDebugInternal (unsigned char *message) |
Send a debug message. | |
void | sendAckIfRequired () |
Send an ack if required. |
This file contains most of the core comms functionality. Currently that is only for UART serial style communication. It is already too big and needs to be split up somewhat. This will happen fairly soon during the serial refactoring and protocol fine tuning.
TODO factor many things into functions and move the receive delegator to its own file
Definition in file commsCore.c.
#define COMMSCORE_C |
Definition at line 43 of file commsCore.c.
void checksumAndSend | ( | void | ) |
Checksum a packet and send it.
This functions job is to finalise the main loop part of the packet sending process. It runs a checksum over the packet data and tags it to the end before configuring the various ISRs that need to send the data out.
Definition at line 146 of file commsCore.c.
References checksum(), COM_CLEAR_CAN0_INTERFACE_ID, COM_CLEAR_SPARE2_INTERFACE_ID, COM_CLEAR_SPARE3_INTERFACE_ID, COM_CLEAR_SPARE4_INTERFACE_ID, COM_CLEAR_SPARE5_INTERFACE_ID, COM_CLEAR_SPARE6_INTERFACE_ID, COM_CLEAR_SPARE7_INTERFACE_ID, COM_SET_CAN0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, COM_SET_SPARE2_INTERFACE_ID, COM_SET_SPARE3_INTERFACE_ID, COM_SET_SPARE4_INTERFACE_ID, COM_SET_SPARE5_INTERFACE_ID, COM_SET_SPARE6_INTERFACE_ID, COM_SET_SPARE7_INTERFACE_ID, SCI0CR2, SCI0DRL, SCI0SR1, SCICR2_TX_ISR_ENABLE, START_BYTE, TXBufferCurrentPositionHandler, TXBufferInUseFlags, TXPacketLengthToSendCAN0, and TXPacketLengthToSendSCI0.
Referenced by decodePacketAndRespond(), main(), sendDebugInternal(), and sendErrorInternal().
00146 { 00147 /* Get the length from the pointer */ 00148 unsigned short TXPacketLengthToSend = (unsigned short)TXBufferCurrentPositionHandler - (unsigned short)&TXBuffer; 00149 00150 /* Tag the checksum on the end */ 00151 *TXBufferCurrentPositionHandler = checksum((unsigned char*)&TXBuffer, TXPacketLengthToSend); 00152 TXPacketLengthToSend++; 00153 00154 /* Send it out on all the channels required. */ 00155 00156 /* SCI0 - Main serial interface */ 00157 if(TXBufferInUseFlags & COM_SET_SCI0_INTERFACE_ID){ 00158 /* Copy numbers to interface specific vars */ 00159 TXPacketLengthToSendSCI0 = TXPacketLengthToSend; 00160 TXPacketLengthToSendCAN0 = TXPacketLengthToSend; 00161 00162 /* Queue preamble by clearing and then setting transmit enable */ 00163 /* See section 11.4.5.2 of the xdp512 specification document */ 00164 //SCI0CR2 &= SCICR2_TX_DISABLE; 00165 //SCI0CR2 |= SCICR2_TX_ENABLE; 00166 00167 /* Initiate transmission */ 00168 SCI0DRL = START_BYTE; 00169 while(!(SCI0SR1 & 0x80)){/* Wait for ever until able to send then move on */} 00170 SCI0DRL = START_BYTE; // nasty hack that works... means at least one and most 2 starts are sent so stuff works, but is messy... there must be a better way. 00171 00172 /* Note : Order Is Important! */ 00173 /* TX empty flag is already set, so we must clear it by writing out before enabling the interrupt */ 00174 SCI0CR2 |= SCICR2_TX_ISR_ENABLE; 00175 } 00176 /* CAN0 - Main CAN interface */ 00177 if(TXBufferInUseFlags & COM_SET_CAN0_INTERFACE_ID){ 00178 // just clear up front for now 00179 TXBufferInUseFlags &= COM_CLEAR_CAN0_INTERFACE_ID; 00180 } 00181 /* spare2 */ 00182 if(TXBufferInUseFlags & COM_SET_SPARE2_INTERFACE_ID){ 00183 // just clear up front for now 00184 TXBufferInUseFlags &= COM_CLEAR_SPARE2_INTERFACE_ID; 00185 } 00186 /* spare3 */ 00187 if(TXBufferInUseFlags & COM_SET_SPARE3_INTERFACE_ID){ 00188 // just clear up front for now 00189 TXBufferInUseFlags &= COM_CLEAR_SPARE3_INTERFACE_ID; 00190 } 00191 /* spare4 */ 00192 if(TXBufferInUseFlags & COM_SET_SPARE4_INTERFACE_ID){ 00193 // just clear up front for now 00194 TXBufferInUseFlags &= COM_CLEAR_SPARE4_INTERFACE_ID; 00195 } 00196 /* spare5 */ 00197 if(TXBufferInUseFlags & COM_SET_SPARE5_INTERFACE_ID){ 00198 // just clear up front for now 00199 TXBufferInUseFlags &= COM_CLEAR_SPARE5_INTERFACE_ID; 00200 } 00201 /* spare6 */ 00202 if(TXBufferInUseFlags & COM_SET_SPARE6_INTERFACE_ID){ 00203 // just clear up front for now 00204 TXBufferInUseFlags &= COM_CLEAR_SPARE6_INTERFACE_ID; 00205 } 00206 /* spare7 */ 00207 if(TXBufferInUseFlags & COM_SET_SPARE7_INTERFACE_ID){ 00208 // just clear up front for now 00209 TXBufferInUseFlags &= COM_CLEAR_SPARE7_INTERFACE_ID; 00210 } 00211 }
void decodePacketAndRespond | ( | void | ) |
Decode a packet and respond.
This is the core function that controls what functionality is run when a packet is received in full by the ISR code and control is passed back to the main loop code. The vast majority of communications action happens here.
Definition at line 222 of file commsCore.c.
References adjust2dTableAxis, adjust2dTableCell, adjustMainTableCell, adjustMainTableLoadAxis, adjustMainTableRPMAxis, ARMCOP, asyncDatalogBasic, asyncDatalogOff, asyncDatalogType, BIT0, burnAllBlocksOfFlash, burnBlockFromRamToFlash, checksumAndSend(), CLEAR_ALL_SOURCE_ID_FLAGS, COM_SET_SCI0_INTERFACE_ID, configuredBasicDatalogLength, COPCTL, datalogLengthExceedsMax, eraseAllBlocksFromFlash, eraseSector(), firmwareVersion, fixedConfigs1, blockDetails::FlashAddress, blockDetails::FlashPage, forwardPacketOverCAN, forwardPacketOverOtherUART, HEADER_HAS_ACK, HEADER_HAS_ADDRS, HEADER_HAS_LENGTH, HEADER_IS_PROTO, interfaceVersionAndType, invalidFirmwarePayloadID, invalidIDForMainTableAction, invalidIDForTwoDTableAction, invalidMemoryActionForID, invalidProtocolPayloadID, lookupBlockDetails(), MAINTABLE_MAX_LOAD_LENGTH, MAINTABLE_MAX_MAIN_LENGTH, MAINTABLE_MAX_RPM_LENGTH, maxBasicDatalogLength, serialSetting::networkAddress, noSuchAsyncDatalogType, payloadLengthHeaderMismatch, payloadLengthTypeMismatch, populateBasicDatalog(), PORTK, PPAGE, blockDetails::RAMAddress, blockDetails::RAMPage, replaceBlockInFlash, replaceBlockInRAM, requestBasicDatalog, requestConfigurableDatalog, requestEchoPacketReturn, requestFirmwareVersion, requestHardSystemReset, requestInterfaceVersion, requestMaxPacketSize, requestSoftSystemReset, resetReceiveState(), retrieveBlockFromFlash, retrieveBlockFromRAM, RPAGE, RX_BUFFER_SIZE, RXBufferCurrentPosition, RXCalculatedPayloadLength, RXHeaderFlags, RXHeaderPayloadID, RXHeaderPayloadLength, RXHeaderSourceAddress, RXPacketLengthReceived, sendAckIfRequired(), sendDebugInternal(), sendErrorInternal(), fixedConfig1::serialSettings, setAsyncDatalogType, setPagedMainTableCellValue(), setPagedMainTableLoadValue(), setPagedMainTableRPMValue(), setPagedTwoDTableAxisValue(), setPagedTwoDTableCellValue(), blockDetails::size, sourceAddressIsBroadcast, sourceAddressIsDuplicate, TXBufferCurrentPositionCAN0, TXBufferCurrentPositionHandler, TXBufferCurrentPositionSCI0, TXBufferInUseFlags, unimplementedFunction, unrecognisedFirmwarePayloadID, unrecognisedProtocolPayloadID, validateMainTable(), validateTwoDTable(), writeBlock(), and writeSector().
Referenced by main().
00222 { 00223 /* Extract and build up the header fields */ 00224 RXBufferCurrentPosition = (unsigned char*)&RXBuffer; 00225 TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer; 00226 00227 /* Initialised here such that override is possible */ 00228 TXBufferCurrentPositionSCI0 = (unsigned char*)&TXBuffer; 00229 TXBufferCurrentPositionCAN0 = (unsigned char*)&TXBuffer; 00230 00231 /* Start this off as full packet length and build down to the actual length */ 00232 RXCalculatedPayloadLength = RXPacketLengthReceived; 00233 00234 /* Grab the RX header flags out of the RX buffer */ 00235 RXHeaderFlags = *RXBufferCurrentPosition; 00236 RXBufferCurrentPosition++; 00237 RXCalculatedPayloadLength--; 00238 00239 /* Flag that we are transmitting! */ 00240 TXBufferInUseFlags |= COM_SET_SCI0_INTERFACE_ID; 00241 // SCI0 only for now... 00242 00243 /* Load a blank header into the TX buffer ready for masking */ 00244 unsigned char* TXHeaderFlags = TXBufferCurrentPositionHandler; 00245 *TXHeaderFlags = 0; 00246 TXBufferCurrentPositionHandler++; 00247 00248 /* Grab the payload ID for processing and load the return ID */ 00249 RXHeaderPayloadID = *((unsigned short*)RXBufferCurrentPosition); 00250 *((unsigned short*)TXBufferCurrentPositionHandler) = RXHeaderPayloadID + 1; 00251 RXBufferCurrentPosition += 2; 00252 TXBufferCurrentPositionHandler += 2; 00253 RXCalculatedPayloadLength -= 2; 00254 00255 /* If there is an ack, copy it to the return packet */ 00256 if(RXHeaderFlags & HEADER_HAS_ACK){ 00257 *TXBufferCurrentPositionHandler = *RXBufferCurrentPosition; 00258 *TXHeaderFlags |= HEADER_HAS_ACK; 00259 RXBufferCurrentPosition++; 00260 TXBufferCurrentPositionHandler++; 00261 RXCalculatedPayloadLength--; 00262 } 00263 00264 /* If the header has addresses, check them and if OK copy them */ 00265 if(RXHeaderFlags & HEADER_HAS_ADDRS){ 00266 /* Check the destination address against our address */ 00267 if(*RXBufferCurrentPosition != fixedConfigs1.serialSettings.networkAddress){ 00268 /* Addresses do not match, discard packet without error */ 00269 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00270 TXBufferInUseFlags = 0; 00271 return; 00272 } 00273 RXBufferCurrentPosition++; 00274 00275 /* Save and check the source address */ 00276 RXHeaderSourceAddress = *RXBufferCurrentPosition; 00277 RXBufferCurrentPosition++; 00278 if(RXHeaderSourceAddress == 0){ 00279 sendErrorInternal(sourceAddressIsBroadcast); 00280 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00281 return; 00282 } 00283 if(RXHeaderSourceAddress == fixedConfigs1.serialSettings.networkAddress){ 00284 sendErrorInternal(sourceAddressIsDuplicate); 00285 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00286 return; 00287 } 00288 00289 /* All is well, setup reply addresses */ 00290 *TXHeaderFlags |= HEADER_HAS_ADDRS; 00291 /* TX destination = RX source */ 00292 *TXBufferCurrentPositionHandler = RXHeaderSourceAddress; 00293 TXBufferCurrentPositionHandler++; 00294 /* TX source = our address */ 00295 *TXBufferCurrentPositionHandler = fixedConfigs1.serialSettings.networkAddress; 00296 TXBufferCurrentPositionHandler++; 00297 /* Decrement for both at once to save a cycle */ 00298 RXCalculatedPayloadLength -= 2; 00299 } 00300 00301 /* Subtract checksum to get final length */ 00302 RXCalculatedPayloadLength--; 00303 00304 /* Grab the length if available */ 00305 if(RXHeaderFlags & HEADER_HAS_LENGTH){ 00306 RXHeaderPayloadLength = *((unsigned short*)RXBufferCurrentPosition); 00307 RXBufferCurrentPosition += 2; 00308 RXCalculatedPayloadLength -= 2; 00309 /* Already subtracted one for checksum */ 00310 if(RXHeaderPayloadLength != RXCalculatedPayloadLength){ 00311 sendErrorInternal(payloadLengthHeaderMismatch); 00312 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00313 return; 00314 } 00315 } 00316 00317 /* Please Note : */ 00318 /* length (and it's flag) should be set by each return packet type handler if required or desired. */ 00319 /* If an ack has been requested, ensure the negative ack flag is set if the opration failed. */ 00320 00321 /* Perform the requested action based on payload ID */ 00322 if (RXHeaderFlags & HEADER_IS_PROTO){ /* Protocol payload types */ 00323 /* Set the return type to be protocol too */ 00324 *TXHeaderFlags |= HEADER_IS_PROTO; 00325 00326 switch (RXHeaderPayloadID){ 00327 case requestInterfaceVersion: 00328 { 00329 if(RXCalculatedPayloadLength != 0){ 00330 sendErrorInternal(payloadLengthTypeMismatch); 00331 break; 00332 } 00333 00334 /* This type must have a length field, set that up */ 00335 *((unsigned short*)TXBufferCurrentPositionHandler) = sizeof(interfaceVersionAndType); 00336 *TXHeaderFlags |= HEADER_HAS_LENGTH; 00337 TXBufferCurrentPositionHandler += 2; 00338 /* Load the body into place */ 00339 memcpy((void*)TXBufferCurrentPositionHandler, (void*)&interfaceVersionAndType, sizeof(interfaceVersionAndType)); 00340 TXBufferCurrentPositionHandler += sizeof(interfaceVersionAndType); 00341 checksumAndSend(); 00342 break; 00343 } 00344 case requestFirmwareVersion: 00345 { 00346 if(RXCalculatedPayloadLength != 0){ 00347 sendErrorInternal(payloadLengthTypeMismatch); 00348 break; 00349 } 00350 /* This type must have a length field, set that up */ 00351 *((unsigned short*)TXBufferCurrentPositionHandler) = sizeof(firmwareVersion); 00352 *TXHeaderFlags |= HEADER_HAS_LENGTH; 00353 TXBufferCurrentPositionHandler += 2; 00354 /* Load the body into place */ 00355 memcpy((void*)TXBufferCurrentPositionHandler, (void*)&firmwareVersion, sizeof(firmwareVersion)); 00356 TXBufferCurrentPositionHandler += sizeof(firmwareVersion); 00357 checksumAndSend(); 00358 break; 00359 } 00360 case requestMaxPacketSize: 00361 { 00362 if(RXCalculatedPayloadLength != 0){ 00363 sendErrorInternal(payloadLengthTypeMismatch); 00364 break; 00365 } 00366 /* Load the size into place */ 00367 *((unsigned short*)TXBufferCurrentPositionHandler) = RX_BUFFER_SIZE; 00368 TXBufferCurrentPositionHandler += 2; 00369 checksumAndSend(); 00370 break; 00371 } 00372 case requestEchoPacketReturn: 00373 { 00374 /* This type must have a length field, set that up */ 00375 *((unsigned short*)TXBufferCurrentPositionHandler) = RXPacketLengthReceived; 00376 *TXHeaderFlags |= HEADER_HAS_LENGTH; 00377 TXBufferCurrentPositionHandler += 2; 00378 /* Load the body into place */ 00379 memcpy((void*)TXBufferCurrentPositionHandler, (void*)&RXBuffer, RXPacketLengthReceived); 00380 /* Note, there is no overflow check here because the TX buffer is slightly */ 00381 /* bigger than the RX buffer and there is overflow checking for receives anyway. */ 00382 TXBufferCurrentPositionHandler += RXPacketLengthReceived; 00383 checksumAndSend(); 00384 break; 00385 } 00386 case requestSoftSystemReset: 00387 { 00388 // hack to allow datalog on/off from the orange button (thank christ I asked for that button when I did) 00389 if(asyncDatalogType){ 00390 asyncDatalogType = asyncDatalogOff; 00391 }else{ 00392 asyncDatalogType = asyncDatalogBasic; 00393 } 00394 sendAckIfRequired(); // TODO implement 00395 break; 00396 00397 // // hack to use soft reset to request registers 00398 // /* This type must have a length field, set that up */ 00399 // *((unsigned short*)TXBufferCurrentPositionHandler) = memdumplength; 00400 // *TXHeaderFlags |= HEADER_HAS_LENGTH; 00401 // TXBufferCurrentPositionHandler += 2; 00402 // /* Load the body into place */ 00403 // memcpy((void*)TXBufferCurrentPositionHandler, memdumpaddr, memdumplength); 00404 // TXBufferCurrentPositionHandler += memdumplength; 00405 // memdumpaddr += memdumplength; 00406 // checksumAndSend(); 00407 // break; 00408 00409 // if(RXCalculatedPayloadLength != 0){ 00410 // sendErrorInternal(payloadLengthTypeMismatch); 00411 // break; 00412 // } 00413 // /* Perform soft system reset */ 00414 // _start(); 00415 } 00416 case requestHardSystemReset: 00417 { 00418 if(RXCalculatedPayloadLength != 0){ 00419 sendErrorInternal(payloadLengthTypeMismatch); 00420 break; 00421 } 00422 00423 /* This is how the serial monitor does it. */ 00424 COPCTL = 0x01; /* Arm with shortest time */ 00425 ARMCOP = 0xFF; /* Write bad value, should cause immediate reset */ 00426 /* Using _start() only resets the app ignoring the monitor switch. It does not work */ 00427 /* properly because the location of _start is not the master reset vector location. */ 00428 } 00429 default: 00430 { 00431 if((RXHeaderPayloadID % 2) == 1){ 00432 sendErrorInternal(invalidProtocolPayloadID); 00433 }else{ 00434 sendErrorInternal(unrecognisedProtocolPayloadID); 00435 } 00436 } 00437 } 00438 }else{ /* Otherwise firmware payload types */ 00439 switch (RXHeaderPayloadID) { 00440 case replaceBlockInRAM: 00441 { 00442 /* Extract the ram location ID from the received data */ 00443 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00444 RXBufferCurrentPosition += 2; 00445 00446 /* Look up the memory location details */ 00447 blockDetails details; 00448 lookupBlockDetails(locationID, &details); 00449 00450 /* Subtract two to allow for the locationID */ 00451 if((RXCalculatedPayloadLength - 2) != details.size){ 00452 sendErrorInternal(payloadLengthTypeMismatch); 00453 break; 00454 } 00455 00456 if((details.RAMPage == 0) || (details.RAMAddress == 0)){ 00457 sendErrorInternal(invalidMemoryActionForID); 00458 break; 00459 } 00460 00461 // TODO factor this out into validation delegation function once the number of types increases somewhat 00462 unsigned short errorID = 0; 00463 if(locationID < 16){ 00464 // mainTable aTable; 00465 errorID = validateMainTable((mainTable*)RXBufferCurrentPosition); 00466 }else if((locationID > 399) && (locationID < 900)){ 00467 // twoDTableUS aTable; 00468 errorID = validateTwoDTable((twoDTableUS*)RXBufferCurrentPosition); 00469 }// TODO add other table types here 00470 /* If the validation failed, report it */ 00471 if(errorID != 0){ 00472 sendErrorInternal(errorID); 00473 break; 00474 } 00475 00476 /* Save page values for restore */ 00477 unsigned char oldRamPage = RPAGE; 00478 /* Set the viewable ram page */ 00479 RPAGE = details.RAMPage; 00480 /* Copy from the RX buffer to the block of ram */ 00481 memcpy(details.RAMAddress, RXBufferCurrentPosition, details.size); 00482 /* Restore the original ram and flash pages */ 00483 RPAGE = oldRamPage; 00484 00485 sendAckIfRequired(); // TODO implement 00486 break; 00487 } 00488 case replaceBlockInFlash: 00489 { 00490 /* Extract the ram location ID from the received data */ 00491 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00492 RXBufferCurrentPosition += 2; 00493 00494 /* Look up the memory location details */ 00495 blockDetails details; 00496 lookupBlockDetails(locationID, &details); 00497 00498 /* Subtract two to allow for the locationID */ 00499 if((RXCalculatedPayloadLength - 2) != details.size){ 00500 sendErrorInternal(payloadLengthTypeMismatch); 00501 break; 00502 } 00503 00504 if((details.FlashPage == 0) || (details.FlashAddress == 0)){ 00505 sendErrorInternal(invalidMemoryActionForID); 00506 break; 00507 } 00508 00509 // TODO factor this out into validation delegation function once the number of types increases somewhat 00510 unsigned short errorID = 0; 00511 if(locationID < 16){ 00512 // mainTable aTable; 00513 errorID = validateMainTable((mainTable*)RXBufferCurrentPosition); 00514 }else if((locationID > 399) && (locationID < 900)){ 00515 // twoDTableUS aTable; 00516 errorID = validateTwoDTable((twoDTableUS*)RXBufferCurrentPosition); 00517 }// TODO add other table types here 00518 /* If the validation failed, report it */ 00519 if(errorID != 0){ 00520 sendErrorInternal(errorID); 00521 break; 00522 } 00523 00524 /* Calculate the position of the end of the stored packet for use as a buffer */ 00525 void* buffer = (void*)((unsigned short)&RXBuffer + RXPacketLengthReceived); 00526 00527 /* Swap the RAM details such that the block gets pulled down from the buffer */ 00528 unsigned char originalRAMPage = details.RAMPage; 00529 void* originalRAMAddress = details.RAMAddress; 00530 details.RAMPage = RPAGE; 00531 details.RAMAddress = RXBufferCurrentPosition; 00532 00533 /* Copy from the RX buffer to the block of flash */ 00534 errorID = writeBlock(&details, buffer); 00535 if(errorID != 0){ 00536 sendErrorInternal(errorID); 00537 break; 00538 } 00539 00540 /* If present in RAM, update that too */ 00541 if((originalRAMPage != 0) && (originalRAMAddress != 0)){ 00542 /* Save page values for restore */ 00543 unsigned char oldRamPage = RPAGE; 00544 /* Set the viewable ram page */ 00545 RPAGE = originalRAMPage; 00546 /* Copy from the RX buffer to the block of ram */ 00547 memcpy(originalRAMAddress, RXBufferCurrentPosition, details.size); 00548 /* Restore the original ram and flash pages */ 00549 RPAGE = oldRamPage; 00550 } 00551 00552 sendAckIfRequired(); 00553 // TODO document errors can always be returned and add error check in to send as response for ack and async otherwise 00554 break; 00555 } 00556 case retrieveBlockFromRAM: 00557 { 00558 if(RXCalculatedPayloadLength != 2){ 00559 sendErrorInternal(payloadLengthTypeMismatch); 00560 break; 00561 } 00562 00563 /* Extract the ram location ID from the received data */ 00564 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00565 /* Store it back into the output data */ 00566 *(unsigned short*)TXBufferCurrentPositionHandler = locationID; 00567 TXBufferCurrentPositionHandler += 2; 00568 00569 /* If it's a main table we are returning, specify the limits explicitly */ 00570 if(locationID < 16){ 00571 /* Store it back into the output data */ 00572 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_RPM_LENGTH; 00573 TXBufferCurrentPositionHandler += 2; 00574 /* Store it back into the output data */ 00575 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_LOAD_LENGTH; 00576 TXBufferCurrentPositionHandler += 2; 00577 /* Store it back into the output data */ 00578 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_MAIN_LENGTH; 00579 TXBufferCurrentPositionHandler += 2; 00580 } 00581 00582 /* Look up the memory location details */ 00583 blockDetails details; 00584 lookupBlockDetails(locationID, &details); 00585 00586 if((details.RAMPage == 0) || (details.RAMAddress == 0)){ 00587 sendErrorInternal(invalidMemoryActionForID); 00588 break; 00589 } 00590 00591 /* Save page value for restore and set the visible page */ 00592 unsigned char oldRamPage = RPAGE; 00593 RPAGE = details.RAMPage; 00594 00595 /* Copy the block of ram to the TX buffer */ 00596 memcpy(TXBufferCurrentPositionHandler, details.RAMAddress, details.size); 00597 TXBufferCurrentPositionHandler += details.size; 00598 00599 /* Restore the original ram and flash pages */ 00600 RPAGE = oldRamPage; 00601 00602 checksumAndSend(); 00603 break; 00604 } 00605 case retrieveBlockFromFlash: 00606 { 00607 if(RXCalculatedPayloadLength != 2){ 00608 sendErrorInternal(payloadLengthTypeMismatch); 00609 break; 00610 } 00611 00612 /* Extract the flash location ID from the received data */ 00613 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00614 /* Store it back into the output data */ 00615 *(unsigned short*)TXBufferCurrentPositionHandler = locationID; 00616 TXBufferCurrentPositionHandler += 2; 00617 00618 /* If it's a main table we are returning, specify the limits explicitly */ 00619 if(locationID < 16){ 00620 /* Store it back into the output data */ 00621 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_RPM_LENGTH; 00622 TXBufferCurrentPositionHandler += 2; 00623 /* Store it back into the output data */ 00624 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_LOAD_LENGTH; 00625 TXBufferCurrentPositionHandler += 2; 00626 /* Store it back into the output data */ 00627 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_MAIN_LENGTH; 00628 TXBufferCurrentPositionHandler += 2; 00629 } 00630 00631 /* Look up the memory location details */ 00632 blockDetails details; 00633 lookupBlockDetails(locationID, &details); 00634 00635 if((details.FlashPage == 0) || (details.FlashAddress == 0)){ 00636 sendErrorInternal(invalidMemoryActionForID); 00637 break; 00638 } 00639 00640 /* Save page value for restore and set the visible page */ 00641 unsigned char oldFlashPage = PPAGE; 00642 PPAGE = details.FlashPage; 00643 00644 /* Copy the block of flash to the TX buffer */ 00645 memcpy(TXBufferCurrentPositionHandler, details.FlashAddress, details.size); 00646 TXBufferCurrentPositionHandler += details.size; 00647 00648 /* Restore the original ram and flash pages */ 00649 PPAGE = oldFlashPage; 00650 00651 checksumAndSend(); 00652 break; 00653 } 00654 case burnBlockFromRamToFlash: 00655 { 00656 if(RXCalculatedPayloadLength != 2){ 00657 sendErrorInternal(payloadLengthTypeMismatch); 00658 break; 00659 } 00660 00661 /* Extract the flash location ID from the received data */ 00662 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00663 00664 /* Look up the memory location details */ 00665 blockDetails details; 00666 lookupBlockDetails(locationID, &details); 00667 00668 /* Check that all data we need is present */ 00669 if((details.RAMPage == 0) || (details.RAMAddress == 0) || (details.FlashPage == 0) || (details.FlashAddress == 0)){ 00670 sendErrorInternal(invalidMemoryActionForID); 00671 break; 00672 } 00673 00674 /* Calculate the position of the end of the stored packet for use as a buffer */ 00675 void* buffer = (void*)((unsigned short)&RXBuffer + RXPacketLengthReceived); 00676 00677 /* Write the block down from RAM to Flash */ 00678 unsigned short errorID = writeBlock(&details, buffer); 00679 00680 if(errorID != 0){ 00681 sendErrorInternal(errorID); 00682 break; 00683 } 00684 00685 sendAckIfRequired(); 00686 break; 00687 } 00688 case eraseAllBlocksFromFlash: 00689 { 00690 if(RXCalculatedPayloadLength != 0){ 00691 sendErrorInternal(payloadLengthTypeMismatch); 00692 break; 00693 } 00694 00695 // perform function TODO 00696 unsigned char page = 0xE0; 00697 unsigned short start = 0x8000; 00698 unsigned short end = 0xC000; 00699 unsigned short inc = 0x0400; 00700 for(;page < 0xF8;page++){ 00701 unsigned short addr; 00702 for(addr = start;addr < end; addr += inc){ 00703 // TODO create selfDestruct() function for loading larger code to the device using all flash pages. 00704 eraseSector(page, (unsigned short*)addr); 00705 } 00706 } 00707 sendDebugInternal("Erased three 128k Flash blocks!"); 00708 break; 00709 } 00710 case burnAllBlocksOfFlash: 00711 { 00712 if(RXCalculatedPayloadLength != 0){ 00713 sendErrorInternal(payloadLengthTypeMismatch); 00714 break; 00715 } 00716 00717 // perform function TODO 00718 unsigned char page = 0xE0; 00719 unsigned short start = 0x8000; 00720 unsigned short end = 0xC000; 00721 unsigned short inc = 0x0400; 00722 for(;page < 0xF8;page++){ 00723 unsigned short addr; 00724 for(addr = start;addr < end; addr += inc){ 00725 writeSector(RPAGE, (unsigned short*)0xc000, page, (unsigned short*)addr); 00726 } 00727 } 00728 sendDebugInternal("Overwrote three 128k Flash blocks!"); 00729 break; 00730 } 00731 case adjustMainTableCell: 00732 { 00733 if(RXCalculatedPayloadLength != 8){ 00734 sendErrorInternal(payloadLengthTypeMismatch); 00735 break; 00736 } 00737 00738 /* Extract the flash location ID from the received data */ 00739 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00740 RXBufferCurrentPosition += 2; 00741 00742 /* Check the ID to ensure it is a main table */ 00743 if(15 < locationID){ 00744 sendErrorInternal(invalidIDForMainTableAction); 00745 break; 00746 } 00747 00748 /* Extract the cell value and coordinates */ 00749 unsigned short RPMIndex = *((unsigned short*)RXBufferCurrentPosition); 00750 RXBufferCurrentPosition += 2; 00751 unsigned short LoadIndex = *((unsigned short*)RXBufferCurrentPosition); 00752 RXBufferCurrentPosition += 2; 00753 unsigned short cellValue = *((unsigned short*)RXBufferCurrentPosition); 00754 00755 /* Look up the memory location details */ 00756 blockDetails details; 00757 lookupBlockDetails(locationID, &details); 00758 00759 /* Attempt to set the value */ 00760 unsigned short errorID = setPagedMainTableCellValue(details.RAMPage, details.RAMAddress, RPMIndex, LoadIndex, cellValue); 00761 if(errorID != 0){ 00762 sendErrorInternal(errorID); 00763 }else{ 00764 sendAckIfRequired(); 00765 } 00766 break; 00767 } 00768 case adjustMainTableRPMAxis: 00769 { 00770 if(RXCalculatedPayloadLength != 6){ 00771 sendErrorInternal(payloadLengthTypeMismatch); 00772 break; 00773 } 00774 00775 /* Extract the flash location ID from the received data */ 00776 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00777 RXBufferCurrentPosition -= 2; 00778 00779 /* Check the ID to ensure it is a main table */ 00780 if(15 < locationID){ 00781 sendErrorInternal(invalidIDForMainTableAction); 00782 break; 00783 } 00784 00785 /* Extract the cell value and coordinates */ 00786 unsigned short RPMIndex = *((unsigned short*)RXBufferCurrentPosition); 00787 RXBufferCurrentPosition -= 2; 00788 unsigned short RPMValue = *((unsigned short*)RXBufferCurrentPosition); 00789 00790 /* Look up the memory location details */ 00791 blockDetails details; 00792 lookupBlockDetails(locationID, &details); 00793 00794 /* Attempt to set the value */ 00795 unsigned short errorID = setPagedMainTableRPMValue(details.RAMPage, details.RAMAddress, RPMIndex, RPMValue); 00796 if(errorID != 0){ 00797 sendErrorInternal(errorID); 00798 }else{ 00799 sendAckIfRequired(); 00800 } 00801 break; 00802 } 00803 case adjustMainTableLoadAxis: 00804 { 00805 if(RXCalculatedPayloadLength != 6){ 00806 sendErrorInternal(payloadLengthTypeMismatch); 00807 break; 00808 } 00809 00810 /* Extract the flash location ID from the received data */ 00811 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00812 RXBufferCurrentPosition -= 2; 00813 00814 /* Check the ID to ensure it is a main table */ 00815 if(15 < locationID){ 00816 sendErrorInternal(invalidIDForMainTableAction); 00817 break; 00818 } 00819 00820 /* Extract the cell value and coordinates */ 00821 unsigned short LoadIndex = *((unsigned short*)RXBufferCurrentPosition); 00822 RXBufferCurrentPosition -= 2; 00823 unsigned short LoadValue = *((unsigned short*)RXBufferCurrentPosition); 00824 00825 /* Look up the memory location details */ 00826 blockDetails details; 00827 lookupBlockDetails(locationID, &details); 00828 00829 /* Attempt to set the value */ 00830 unsigned short errorID = setPagedMainTableLoadValue(details.RAMPage, details.RAMAddress, LoadIndex, LoadValue); 00831 if(errorID != 0){ 00832 sendErrorInternal(errorID); 00833 }else{ 00834 sendAckIfRequired(); 00835 } 00836 break; 00837 } 00838 case adjust2dTableAxis: 00839 { 00840 if(RXCalculatedPayloadLength != 6){ 00841 sendErrorInternal(payloadLengthTypeMismatch); 00842 break; 00843 } 00844 00845 /* Extract the flash location ID from the received data */ 00846 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00847 RXBufferCurrentPosition -= 2; 00848 00849 /* Check the ID to ensure it is a 2d table */ 00850 if((locationID > 899) || (locationID < 400)){ 00851 sendErrorInternal(invalidIDForTwoDTableAction); 00852 break; 00853 } 00854 00855 /* Extract the cell value and coordinates */ 00856 unsigned short axisIndex = *((unsigned short*)RXBufferCurrentPosition); 00857 RXBufferCurrentPosition -= 2; 00858 unsigned short axisValue = *((unsigned short*)RXBufferCurrentPosition); 00859 00860 /* Look up the memory location details */ 00861 blockDetails details; 00862 lookupBlockDetails(locationID, &details); 00863 00864 /* Attempt to set the value */ 00865 unsigned short errorID = setPagedTwoDTableAxisValue(details.RAMPage, details.RAMAddress, axisIndex, axisValue); 00866 if(errorID != 0){ 00867 sendErrorInternal(errorID); 00868 }else{ 00869 sendAckIfRequired(); 00870 } 00871 break; 00872 } 00873 case adjust2dTableCell: 00874 { 00875 if(RXCalculatedPayloadLength != 6){ 00876 sendErrorInternal(payloadLengthTypeMismatch); 00877 break; 00878 } 00879 00880 /* Extract the flash location ID from the received data */ 00881 unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition); 00882 RXBufferCurrentPosition -= 2; 00883 00884 /* Check the ID to ensure it is a 2d table */ 00885 if((locationID > 899) || (locationID < 400)){ 00886 sendErrorInternal(invalidIDForTwoDTableAction); 00887 break; 00888 } 00889 00890 /* Extract the cell value and coordinates */ 00891 unsigned short cellIndex = *((unsigned short*)RXBufferCurrentPosition); 00892 RXBufferCurrentPosition -= 2; 00893 unsigned short cellValue = *((unsigned short*)RXBufferCurrentPosition); 00894 00895 /* Look up the memory location details */ 00896 blockDetails details; 00897 lookupBlockDetails(locationID, &details); 00898 00899 /* Attempt to set the value */ 00900 unsigned short errorID = setPagedTwoDTableCellValue(details.RAMPage, details.RAMAddress, cellIndex, cellValue); 00901 if(errorID != 0){ 00902 sendErrorInternal(errorID); 00903 }else{ 00904 sendAckIfRequired(); 00905 } 00906 break; 00907 } 00908 case requestBasicDatalog: 00909 { 00910 if((RXCalculatedPayloadLength > 2) || (RXCalculatedPayloadLength == 1)){ 00911 sendErrorInternal(payloadLengthTypeMismatch); 00912 break; 00913 }else if(RXCalculatedPayloadLength == 2){ 00914 unsigned short newConfiguredLength = *((unsigned short*)RXBufferCurrentPosition); 00915 if(newConfiguredLength > maxBasicDatalogLength){ 00916 sendErrorInternal(datalogLengthExceedsMax); 00917 break; 00918 }else{ 00919 configuredBasicDatalogLength = newConfiguredLength; 00920 } 00921 } 00922 00923 /* Set the length field up */ 00924 *TXHeaderFlags |= HEADER_HAS_LENGTH; 00925 *(unsigned short*)TXBufferCurrentPositionHandler = configuredBasicDatalogLength; 00926 00927 /* Fill out the log and send */ 00928 populateBasicDatalog(); 00929 checksumAndSend(); 00930 break; 00931 } 00932 case requestConfigurableDatalog: 00933 { 00934 // perform function TODO 00935 sendErrorInternal(unimplementedFunction); 00936 break; 00937 } 00938 case forwardPacketOverCAN: 00939 { 00940 // perform function TODO 00941 sendErrorInternal(unimplementedFunction); 00942 break; 00943 } 00944 case forwardPacketOverOtherUART: 00945 { 00946 // perform function TODO 00947 sendErrorInternal(unimplementedFunction); 00948 break; 00949 } 00950 case setAsyncDatalogType: 00951 { 00952 if(RXCalculatedPayloadLength != 1){ 00953 sendErrorInternal(payloadLengthTypeMismatch); 00954 break; 00955 } 00956 00957 unsigned char newDatalogType = *((unsigned char*)RXBufferCurrentPosition); 00958 if(newDatalogType > 0x03){ 00959 sendErrorInternal(noSuchAsyncDatalogType); 00960 break; 00961 }else{ 00962 asyncDatalogType = newDatalogType; 00963 } 00964 00965 sendAckIfRequired(); 00966 break; 00967 } 00968 default: 00969 if((RXHeaderPayloadID % 2) == 1){ 00970 sendErrorInternal(invalidFirmwarePayloadID); 00971 }else{ 00972 sendErrorInternal(unrecognisedFirmwarePayloadID); 00973 } 00974 } 00975 } 00976 /* Switch reception back on now that we are done with the received data */ 00977 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS); 00978 PORTK |= BIT0; 00979 }
void populateBasicDatalog | ( | void | ) |
Populate a basic datalog packet.
Copies various chunks of data to the transmission buffer and truncates to the configured length. If changing this, update the maxBasicDatalogLength.
Definition at line 63 of file commsCore.c.
References ADCArrays, configuredBasicDatalogLength, CoreVars, DerivedVars, and TXBufferCurrentPositionHandler.
Referenced by decodePacketAndRespond(), and main().
00063 { 00064 /* Save the current position */ 00065 unsigned char* position = TXBufferCurrentPositionHandler; 00066 00067 /* Get core vars */ 00068 memcpy(TXBufferCurrentPositionHandler, CoreVars, sizeof(CoreVar)); 00069 TXBufferCurrentPositionHandler += sizeof(CoreVar); 00070 /* Get derived vars */ 00071 memcpy(TXBufferCurrentPositionHandler, DerivedVars, sizeof(DerivedVar)); 00072 TXBufferCurrentPositionHandler += sizeof(DerivedVar); 00073 /* Get raw adc counts */ 00074 memcpy(TXBufferCurrentPositionHandler, ADCArrays, sizeof(ADCArray)); 00075 TXBufferCurrentPositionHandler += sizeof(ADCArray); 00076 00077 /* Set/Truncate the log to the specified length */ 00078 TXBufferCurrentPositionHandler = position + configuredBasicDatalogLength; 00079 }
void sendAckIfRequired | ( | void | ) |
Send an ack if required.
Currently only used to clear the TX buffer flags if we no longer need it.
Definition at line 1256 of file commsCore.c.
References TXBufferInUseFlags.
Referenced by decodePacketAndRespond().
01256 { 01257 TXBufferInUseFlags = 0; 01258 // check PPAGE while implementing TODO 01259 }
void sendDebugBusyWait | ( | unsigned char * | message | ) |
Send a debug message even if we must wait
This is a wrapper for use outside the communication handler function. This function will block until the debug message is able to be sent.
message | is a pointer to the null terminated debug message string. |
Definition at line 1112 of file commsCore.c.
References ONES, sendDebugInternal(), and TXBufferInUseFlags.
01112 { 01113 while(TXBufferInUseFlags){} /* Wait till clear to send */ 01114 TXBufferInUseFlags = ONES; 01115 sendDebugInternal(message); 01116 }
void sendDebugIfClear | ( | unsigned char * | message | ) |
Send a debug message if buffer free.
This is a wrapper for use outside the communication handler function. The debug message will only be sent if the buffer is empty and available, if not, it will be discarded.
message | is a pointer to the null terminated debug message string. |
Definition at line 1091 of file commsCore.c.
References Counter::commsDebugMessagesNotSent, Counters, ONES, sendDebugInternal(), and TXBufferInUseFlags.
01091 { 01092 if(!TXBufferInUseFlags){ 01093 TXBufferInUseFlags = ONES; 01094 sendDebugInternal(message); 01095 }else{ 01096 Counters.commsDebugMessagesNotSent++; 01097 } 01098 }
void sendDebugInternal | ( | unsigned char * | message | ) |
Send a debug message.
Sends a null terminated debug message out on the broadcast address of all available interfaces.
message | is a pointer to the null terminated debug message string. |
Definition at line 1136 of file commsCore.c.
References asyncDebugInfoPacket, checksumAndSend(), stringCopy(), and TXBufferCurrentPositionHandler.
Referenced by decodePacketAndRespond(), sendDebugBusyWait(), and sendDebugIfClear().
01136 { 01137 01138 // set buffer in use, consider blocking interrupts to do this cleanly 01139 01140 // if(TRUE){ 01141 // Counters.serialDebugUnsentCounter++; 01142 // return; 01143 // } 01144 // wrong : 01145 /* No need for atomic block here as one of two conditions will always be */ 01146 /* true when calling this. Either we have been flagged to receive and */ 01147 /* decode a packet, or we are in an ISR. In either case it is safe to */ 01148 /* check the flags and initiate the sequence if they are clear. */ 01149 //if(RXTXSerialStateFlags & TX_IN_PROGRESS){ 01150 // wrong : 01151 /* It's OK to return without resetting as it will be done by */ 01152 /* either of those processes if they are underway. The other */ 01153 /* processes are not overridden because they have priority. */ 01154 //TXBufferInUseFlags = 0; 01155 //return; 01156 // }else{ /* Turn off reception */ 01157 /* It's OK to turn this off if nothing was currently being received */ 01158 // SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 01159 // SCI0CR2 &= SCICR2_RX_DISABLE; 01160 01161 /* Build up the packet */ 01162 /* Set the pointer to the start and init the length */ 01163 TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer; 01164 01165 /* Load a protocol with length header into the TX buffer ready for masking */ 01166 *TXBufferCurrentPositionHandler = 0x11; 01167 TXBufferCurrentPositionHandler++; 01168 01169 /* Set the payload ID */ 01170 *((unsigned short*)TXBufferCurrentPositionHandler) = asyncDebugInfoPacket; 01171 TXBufferCurrentPositionHandler += 2; 01172 01173 /* Store the length location */ 01174 unsigned short* TXLength = (unsigned short*)TXBufferCurrentPositionHandler; 01175 TXBufferCurrentPositionHandler += 2; 01176 01177 /* Copy the string into place and record the length copied */ 01178 unsigned short messageLength = stringCopy(TXBufferCurrentPositionHandler, message); 01179 *TXLength = messageLength; 01180 TXBufferCurrentPositionHandler += messageLength; 01181 01182 checksumAndSend(); 01183 //} 01184 }
void sendErrorBusyWait | ( | unsigned short | errorID | ) |
Send an error even if we must wait.
This is a wrapper for use outside the communication handler function. This function will block until the error is able to be sent. This behaviour is not recommended as it will interfere with engine operation somewhat.
errorID | is the error ID to be passed out to listening devices. |
Definition at line 1018 of file commsCore.c.
References ONES, sendErrorInternal(), and TXBufferInUseFlags.
01018 { 01019 while(TXBufferInUseFlags){} /* Wait till clear to send */ 01020 TXBufferInUseFlags = ONES; 01021 sendErrorInternal(errorID); 01022 }
void sendErrorIfClear | ( | unsigned short | errorID | ) |
Send an error if buffer free.
This is a wrapper for use outside the communication handler function. The error will only be sent if the buffer is empty and available, if not, it will be discarded.
errorID | is the error ID to be passed out to listening devices. |
Definition at line 994 of file commsCore.c.
References Counter::commsErrorMessagesNotSent, Counters, ONES, sendErrorInternal(), and TXBufferInUseFlags.
Referenced by generateCoreVars(), and generateDerivedVars().
00994 { 00995 if(!TXBufferInUseFlags){ 00996 TXBufferInUseFlags = ONES; 00997 sendErrorInternal(errorID); 00998 }else{ 00999 Counters.commsErrorMessagesNotSent++; 01000 } 01001 }
void sendErrorInternal | ( | unsigned short | errorCode | ) |
Send an error.
This function is only for use inside the communication handling function. Use of it outside this environment is not supported and behaviour when used as such is undefined.
TODO decide on errorCode or errorID and consistencise it everywhere.
errorCode | is the error ID to be passed out to listening devices. |
Definition at line 1043 of file commsCore.c.
References asyncErrorCodePacket, checksumAndSend(), and TXBufferCurrentPositionHandler.
Referenced by decodePacketAndRespond(), sendErrorBusyWait(), and sendErrorIfClear().
01043 { 01044 // set buffer in use, consider blocking interrupts to do this cleanly 01045 01046 01047 // TXBufferInUseFlags = 0; 01048 /* No need for atomic block here as one of two conditions will always be */ 01049 /* true when calling this. Either we have been flagged to receive and */ 01050 /* decode a packet, or we are in an ISR. In either case it is safe to */ 01051 /* check the flags and initiate the sequence if they are clear. */ 01052 // if(RXTXSerialStateFlags & TX_IN_PROGRESS){ 01053 /* It's OK to return without resetting as it will be done by */ 01054 /* either of those processes if they are underway. The other */ 01055 /* processes are not overridden because they have priority. */ 01056 // return; 01057 // }else{ /* Turn off reception */ 01058 /* It's OK to turn this off if nothing was currently being received */ 01059 // SCI0CR2 &= SCICR2_RX_ISR_DISABLE; 01060 // SCI0CR2 &= SCICR2_RX_DISABLE; 01061 01062 /* Build up the packet */ 01063 /* Set the pointer to the start */ 01064 TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer; 01065 /* Set the length */ 01066 // TXPacketLengthToSend = 5; /* Flags + Payload ID + Error Code */ 01067 /* Flags = protocol with no extra fields */ 01068 *TXBufferCurrentPositionHandler = 0x01; 01069 TXBufferCurrentPositionHandler++; 01070 /* Set the payload ID */ 01071 *((unsigned short*)TXBufferCurrentPositionHandler) = asyncErrorCodePacket; 01072 TXBufferCurrentPositionHandler += 2; 01073 /* Set the error code */ 01074 *((unsigned short*)TXBufferCurrentPositionHandler) = errorCode; 01075 TXBufferCurrentPositionHandler += 2; 01076 checksumAndSend(); 01077 // } 01078 }