commsCore.c

Go to the documentation of this file.
00001 /*      commsCore.c
00002 
00003         Copyright 2008 Fred Cooke
00004 
00005         This file is part of the FreeEMS project.
00006 
00007         FreeEMS software is free software: you can redistribute it and/or modify
00008         it under the terms of the GNU General Public License as published by
00009         the Free Software Foundation, either version 3 of the License, or
00010         (at your option) any later version.
00011 
00012         FreeEMS software is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016 
00017         You should have received a copy of the GNU General Public License
00018         along with any FreeEMS software.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020         We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org
00021 
00022         Thank you for choosing FreeEMS to run your engine! */
00023 
00024 #define COMMSCORE_C
00025 #include "inc/freeEMS.h"
00026 #include "inc/flashWrite.h"
00027 #include "inc/interrupts.h"
00028 #include "inc/utils.h"
00029 #include "inc/tableLookup.h"
00030 #include "inc/blockDetailsLookup.h"
00031 #include "inc/commsCore.h"
00032 #include <string.h>
00033 
00034 
00035 /* Internal use without check on buffer */
00036 void sendErrorInternal(unsigned short) FPAGE_FE;
00037 void sendDebugInternal(unsigned char*) FPAGE_FE;
00038 
00039 
00040 /* If changing this, update the max constant */
00041 void populateBasicDatalog(){
00042         /* Save the current position */
00043         unsigned char* position = TXBufferCurrentPositionHandler;
00044 
00045         /* Get core vars */
00046         memcpy(TXBufferCurrentPositionHandler, CoreVars, sizeof(CoreVar));
00047         TXBufferCurrentPositionHandler += sizeof(CoreVar);
00048         /* Get derived vars */
00049         memcpy(TXBufferCurrentPositionHandler, DerivedVars, sizeof(DerivedVar));
00050         TXBufferCurrentPositionHandler += sizeof(DerivedVar);
00051         /* Get raw adc counts */
00052         memcpy(TXBufferCurrentPositionHandler, ADCArrays, sizeof(ADCArray));
00053         TXBufferCurrentPositionHandler += sizeof(ADCArray);
00054 
00055         /* Set/Truncate the log to the specified length */
00056         TXBufferCurrentPositionHandler = position + configuredBasicDatalogLength;
00057 }
00058 
00059 
00060 // TODO function to setup a packet and send it fn(populateBodyFunctionPointer(), header, other, fields, here, and, use, or, not, within){}
00061 
00062 // TODO rip dictionary out to own file
00063 
00064 // TODO factor many things into functions and move the receive delegator to its own file
00065 
00066 
00067 //void populateLogicAnalyser(){
00068 //      // get portT rpm input and inj main
00069 //      // get portB ign
00070 //      // get portA ign
00071 //      // get portK inj staged
00072 //}
00073 //
00074 //
00092 //
00093 //init :
00094 //logaddr = fixed.addr
00095 //loglen = fixed.len
00096 //
00097 //len = loglen OR 1 OR 2
00098 //
00099 //check :
00100 //if((addr < 0x0800) && (length < (0x0800 - addr))){
00101 //      // reg space is OK
00102 //}else if(((0x1000 < addr) && (addr < 0x4000)) && (length < (0x4000 - addr))){
00103 //      // ram space is OK
00104 //}else{
00105 //      // send an error instead
00106 //}
00107 //
00108 //run check at init and set time, not run time or just not check?? maybe its silly to check at all
00109 //
00111 //void populateScopeLogADCAll(){
00112 //      sampleBlockADC(TXBufferCurrentPositionHandler);
00113 //      TXBufferCurrentPositionHandler += sizeof(ADCArray);
00114 //}
00115 
00116 
00117 // TODO Look at the time stamps and where to write them, also whether to function
00118 // TODO call these simple blocks or write one function that handles all the logic.
00119 
00120 
00121 /* Checksum and initiate send process */
00122 void checksumAndSend(){
00123         /* Get the length from the pointer */
00124         unsigned short TXPacketLengthToSend = (unsigned short)TXBufferCurrentPositionHandler - (unsigned short)&TXBuffer;
00125 
00126         /* Tag the checksum on the end */
00127         *TXBufferCurrentPositionHandler = checksum((unsigned char*)&TXBuffer, TXPacketLengthToSend);
00128         TXPacketLengthToSend++;
00129 
00130         /* Send it out on all the channels required. */
00131 
00132         /* SCI0 - Main serial interface */
00133         if(TXBufferInUseFlags & COM_SET_SCI0_INTERFACE_ID){
00134                 /* Copy numbers to interface specific vars */
00135                 TXPacketLengthToSendSCI0 = TXPacketLengthToSend;
00136                 TXPacketLengthToSendCAN0 = TXPacketLengthToSend;
00137 
00138                 /* Queue preamble by clearing and then setting transmit enable  */
00139                 /* See section 11.4.5.2 of the xdp512 specification document    */
00140                 //SCI0CR2 &= SCICR2_TX_DISABLE;
00141                 //SCI0CR2 |= SCICR2_TX_ENABLE;
00142 
00143                 /* Initiate transmission */
00144                 SCI0DRL = START_BYTE;
00145                 while(!(SCI0SR1 & 0x80)){/* Wait for ever until able to send then move on */}
00146                 SCI0DRL = START_BYTE; // TODO nasty hack that works... means at least one and most 2 starts are sent so stuff works, but is messy... must be a better way.
00147 
00148                 // TODO http://freeems.aaronb.info/tracker/view.php?id=81
00149 
00150                 /* Note : Order Is Important! */
00151                 /* TX empty flag is already set, so we must clear it by writing out before enabling the interrupt */
00152                 SCI0CR2 |= SCICR2_TX_ISR_ENABLE;
00153         }
00154         /* CAN0 - Main CAN interface */
00155         if(TXBufferInUseFlags & COM_SET_CAN0_INTERFACE_ID){
00156                 // just clear up front for now
00157                 TXBufferInUseFlags &= COM_CLEAR_CAN0_INTERFACE_ID;
00158         }
00159         /* spare2 */
00160         if(TXBufferInUseFlags & COM_SET_SPARE2_INTERFACE_ID){
00161                 // just clear up front for now
00162                 TXBufferInUseFlags &= COM_CLEAR_SPARE2_INTERFACE_ID;
00163         }
00164         /* spare3 */
00165         if(TXBufferInUseFlags & COM_SET_SPARE3_INTERFACE_ID){
00166                 // just clear up front for now
00167                 TXBufferInUseFlags &= COM_CLEAR_SPARE3_INTERFACE_ID;
00168         }
00169         /* spare4 */
00170         if(TXBufferInUseFlags & COM_SET_SPARE4_INTERFACE_ID){
00171                 // just clear up front for now
00172                 TXBufferInUseFlags &= COM_CLEAR_SPARE4_INTERFACE_ID;
00173         }
00174         /* spare5 */
00175         if(TXBufferInUseFlags & COM_SET_SPARE5_INTERFACE_ID){
00176                 // just clear up front for now
00177                 TXBufferInUseFlags &= COM_CLEAR_SPARE5_INTERFACE_ID;
00178         }
00179         /* spare6 */
00180         if(TXBufferInUseFlags & COM_SET_SPARE6_INTERFACE_ID){
00181                 // just clear up front for now
00182                 TXBufferInUseFlags &= COM_CLEAR_SPARE6_INTERFACE_ID;
00183         }
00184         /* spare7 */
00185         if(TXBufferInUseFlags & COM_SET_SPARE7_INTERFACE_ID){
00186                 // just clear up front for now
00187                 TXBufferInUseFlags &= COM_CLEAR_SPARE7_INTERFACE_ID;
00188         }
00189 }
00190 
00191 
00192 // hHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
00193 // above this to another file
00194 
00195 
00196 void decodePacketAndRespond(){
00197         /* Extract and build up the header fields */
00198         RXBufferCurrentPosition = (unsigned char*)&RXBuffer;
00199         TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer;
00200 
00201         /* Initialised here such that override is possible */
00202         TXBufferCurrentPositionSCI0 = (unsigned char*)&TXBuffer;
00203         TXBufferCurrentPositionCAN0 = (unsigned char*)&TXBuffer;
00204 
00205         /* Start this off as full packet length and build down to the actual length */
00206         RXCalculatedPayloadLength = RXPacketLengthReceived;
00207 
00208         /* Grab the RX header flags out of the RX buffer */
00209         RXHeaderFlags = *RXBufferCurrentPosition;
00210         RXBufferCurrentPosition++;
00211         RXCalculatedPayloadLength--;
00212 
00213         /* Flag that we are transmitting! */
00214         TXBufferInUseFlags |= COM_SET_SCI0_INTERFACE_ID;
00215         // SCI0 only for now...
00216 
00217         /* Load a blank header into the TX buffer ready for masking */
00218         unsigned char* TXHeaderFlags = TXBufferCurrentPositionHandler;
00219         *TXHeaderFlags = 0;
00220         TXBufferCurrentPositionHandler++;
00221 
00222         /* Grab the payload ID for processing and load the return ID */
00223         RXHeaderPayloadID = *((unsigned short*)RXBufferCurrentPosition);
00224         *((unsigned short*)TXBufferCurrentPositionHandler) = RXHeaderPayloadID + 1;
00225         RXBufferCurrentPosition += 2;
00226         TXBufferCurrentPositionHandler += 2;
00227         RXCalculatedPayloadLength -= 2;
00228 
00229         /* If there is an ack, copy it to the return packet */
00230         if(RXHeaderFlags & HEADER_HAS_ACK){
00231                 *TXBufferCurrentPositionHandler = *RXBufferCurrentPosition;
00232                 *TXHeaderFlags |= HEADER_HAS_ACK;
00233                 RXBufferCurrentPosition++;
00234                 TXBufferCurrentPositionHandler++;
00235                 RXCalculatedPayloadLength--;
00236         }
00237 
00238         /* If the header has addresses, check them and if OK copy them */
00239         if(RXHeaderFlags & HEADER_HAS_ADDRS){
00240                 /* Check the destination address against our address */
00241                 if(*RXBufferCurrentPosition != fixedConfigs2.networkAddress){
00242                         /* Addresses do not match, discard packet without error */
00243                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00244                         TXBufferInUseFlags = 0;
00245                         return;
00246                 }
00247                 RXBufferCurrentPosition++;
00248 
00249                 /* Save and check the source address */
00250                 RXHeaderSourceAddress = *RXBufferCurrentPosition;
00251                 RXBufferCurrentPosition++;
00252                 if(RXHeaderSourceAddress == 0){
00253                         sendErrorInternal(sourceAddressIsBroadcast);
00254                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00255                         return;
00256                 }
00257                 if(RXHeaderSourceAddress == fixedConfigs2.networkAddress){
00258                         sendErrorInternal(sourceAddressIsDuplicate);
00259                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00260                         return;
00261                 }
00262 
00263                 /* All is well, setup reply addresses */
00264                 *TXHeaderFlags |= HEADER_HAS_ADDRS;
00265                 /* TX destination = RX source */
00266                 *TXBufferCurrentPositionHandler = RXHeaderSourceAddress;
00267                 TXBufferCurrentPositionHandler++;
00268                 /* TX source = our address */
00269                 *TXBufferCurrentPositionHandler = fixedConfigs2.networkAddress;
00270                 TXBufferCurrentPositionHandler++;
00271                 /* Decrement for both at once to save a cycle */
00272                 RXCalculatedPayloadLength -= 2;
00273         }
00274 
00275         /* Subtract checksum to get final length */
00276         RXCalculatedPayloadLength--;
00277 
00278         /* Grab the length if available */
00279         if(RXHeaderFlags & HEADER_HAS_LENGTH){
00280                 RXHeaderPayloadLength = *((unsigned short*)RXBufferCurrentPosition);
00281                 RXBufferCurrentPosition += 2;
00282                 RXCalculatedPayloadLength -= 2;
00283                 /* Already subtracted one for checksum */
00284                 if(RXHeaderPayloadLength != RXCalculatedPayloadLength){
00285                         sendErrorInternal(payloadLengthHeaderMismatch);
00286                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00287                         return;
00288                 }
00289         }
00290 
00291         /* Please Note :                                                                                                                        */
00292         /* length (and it's flag) should be set by each return packet type handler if required or desired.      */
00293         /* If an ack has been requested, ensure the negative ack flag is set if the opration failed.            */
00294 
00295         /* Perform the requested action based on payload ID */
00296         if (RXHeaderFlags & HEADER_IS_PROTO){ /* Protocol payload types */
00297                 /* Set the return type to be protocol too */
00298                 *TXHeaderFlags |= HEADER_IS_PROTO;
00299 
00300                 switch (RXHeaderPayloadID){
00301                 case requestInterfaceVersion:
00302                         if(RXCalculatedPayloadLength != 0){
00303                                 sendErrorInternal(payloadLengthTypeMismatch);
00304                                 break;
00305                         }
00306 
00307                         /* This type must have a length field, set that up */
00308                         *((unsigned short*)TXBufferCurrentPositionHandler) = sizeof(interfaceVersionAndType);
00309                         *TXHeaderFlags |= HEADER_HAS_LENGTH;
00310                         TXBufferCurrentPositionHandler += 2;
00311                         /* Load the body into place */
00312                         memcpy((void*)TXBufferCurrentPositionHandler, (void*)&interfaceVersionAndType, sizeof(interfaceVersionAndType));
00313                         TXBufferCurrentPositionHandler += sizeof(interfaceVersionAndType);
00314                         checksumAndSend();
00315                         break;
00316                 case requestFirmwareVersion:
00317                         if(RXCalculatedPayloadLength != 0){
00318                                 sendErrorInternal(payloadLengthTypeMismatch);
00319                                 break;
00320                         }
00321                         /* This type must have a length field, set that up */
00322                         *((unsigned short*)TXBufferCurrentPositionHandler) = sizeof(firmwareVersion);
00323                         *TXHeaderFlags |= HEADER_HAS_LENGTH;
00324                         TXBufferCurrentPositionHandler += 2;
00325                         /* Load the body into place */
00326                         memcpy((void*)TXBufferCurrentPositionHandler, (void*)&firmwareVersion, sizeof(firmwareVersion));
00327                         TXBufferCurrentPositionHandler += sizeof(firmwareVersion);
00328                         checksumAndSend();
00329                         break;
00330                 case requestMaxPacketSize:
00331                         if(RXCalculatedPayloadLength != 0){
00332                                 sendErrorInternal(payloadLengthTypeMismatch);
00333                                 break;
00334                         }
00335                         /* Load the size into place */
00336                         *((unsigned short*)TXBufferCurrentPositionHandler) = RX_BUFFER_SIZE;
00337                         TXBufferCurrentPositionHandler += 2;
00338                         checksumAndSend();
00339                         break;
00340                 case requestEchoPacketReturn:
00341                         /* This type must have a length field, set that up */
00342                         *((unsigned short*)TXBufferCurrentPositionHandler) = RXPacketLengthReceived;
00343                         *TXHeaderFlags |= HEADER_HAS_LENGTH;
00344                         TXBufferCurrentPositionHandler += 2;
00345                         /* Load the body into place */
00346                         memcpy((void*)TXBufferCurrentPositionHandler, (void*)&RXBuffer, RXPacketLengthReceived);
00347                         /* Note, there is no overflow check here because the TX buffer is slightly       */
00348                         /* bigger than the RX buffer and there is overflow checking for receives anyway. */
00349                         TXBufferCurrentPositionHandler += RXPacketLengthReceived;
00350                         checksumAndSend();
00351                         break;
00352                 case requestSoftSystemReset:
00353                 {
00354                         // hack to allow datalog on/off from the orange button (thank christ I asked for that button when I did)
00355                         if(asyncDatalogType){
00356                                 asyncDatalogType = asyncDatalogOff;
00357                         }else{
00358                                 asyncDatalogType = asyncDatalogBasic;
00359                         }
00360                         sendAckIfRequired(); // TODO implement
00361                         break;
00362 
00363 //                      // hack to use soft reset to request registers
00364 //                      /* This type must have a length field, set that up */
00365 //                      *((unsigned short*)TXBufferCurrentPositionHandler) = memdumplength;
00366 //                      *TXHeaderFlags |= HEADER_HAS_LENGTH;
00367 //                      TXBufferCurrentPositionHandler += 2;
00368 //                      /* Load the body into place */
00369 //                      memcpy((void*)TXBufferCurrentPositionHandler, memdumpaddr, memdumplength);
00370 //                      TXBufferCurrentPositionHandler += memdumplength;
00371 //                      memdumpaddr += memdumplength;
00372 //                      checksumAndSend();
00373 //                      break;
00374 
00375 //                      if(RXCalculatedPayloadLength != 0){
00376 //                              sendErrorInternal(payloadLengthTypeMismatch);
00377 //                              break;
00378 //                      }
00379 //                      /* Perform soft system reset */
00380 //                      _start();
00381                 }
00382                 case requestHardSystemReset:
00383                         if(RXCalculatedPayloadLength != 0){
00384                                 sendErrorInternal(payloadLengthTypeMismatch);
00385                                 break;
00386                         }
00387 
00388                         /* This is how the serial monitor does it. */
00389                         COPCTL = 0x01; /* Arm with shortest time */
00390                         ARMCOP = 0xFF; /* Write bad value, should cause immediate reset */
00391                         /* Using _start() only resets the app ignoring the monitor switch. It does not work */
00392                         /* properly because the location of _start is not the master reset vector location. */
00393                 default:
00394                         if((RXHeaderPayloadID % 2) == 1){
00395                                 sendErrorInternal(invalidProtocolPayloadID);
00396                         }else{
00397                                 sendErrorInternal(unrecognisedProtocolPayloadID);
00398                         }
00399                 }
00400         }else{ /* Otherwise firmware payload types */
00401                 switch (RXHeaderPayloadID) {
00402                 case replaceBlockInRAM:
00403                 {
00404                         /* Extract the ram location ID from the received data */
00405                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00406                         RXBufferCurrentPosition += 2;
00407 
00408                         /* Look up the memory location details */
00409                         blockDetails details;
00410                         lookupBlockDetails(locationID, &details);
00411 
00412                         /* Subtract two to allow for the locationID */
00413                         if((RXCalculatedPayloadLength - 2) != details.size){
00414                                 sendErrorInternal(payloadLengthTypeMismatch);
00415                                 break;
00416                         }
00417 
00418                         if((details.RAMPage == 0) || (details.RAMAddress == 0)){
00419                                 sendErrorInternal(invalidMemoryActionForID);
00420                                 break;
00421                         }
00422 
00423                         unsigned short errorID = 0;
00424                         if(locationID < 16){
00425                                 mainTable aTable;
00426                                 errorID = validateMainTable(&aTable);
00427                         }else if(locationID > 399){
00428                                 twoDTableUS aTable;
00429                                 errorID = validateTwoDTable(&aTable);
00430                         }// TODO add other table types here
00431                         /* If the validation failed, report it */
00432                         if(errorID != 0){
00433                                 sendErrorInternal(errorID);
00434                                 break;
00435                         }
00436 
00437                         /* Save page values for restore */
00438                         unsigned char oldRamPage = RPAGE;
00439                         /* Set the viewable ram page */
00440                         RPAGE = details.RAMPage;
00441                         /* Copy from the RX buffer to the block of ram */
00442                         memcpy(details.RAMAddress, RXBufferCurrentPosition, details.size);
00443                         /* Restore the original ram and flash pages */
00444                         RPAGE = oldRamPage;
00445 
00446                         sendAckIfRequired(); // TODO implement
00447                         break;
00448                 }
00449                 case replaceBlockInFlash:
00450                 {
00451                         /* Extract the ram location ID from the received data */
00452                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00453                         RXBufferCurrentPosition += 2;
00454 
00455                         /* Look up the memory location details */
00456                         blockDetails details;
00457                         lookupBlockDetails(locationID, &details);
00458 
00459                         /* Subtract two to allow for the locationID */
00460                         if((RXCalculatedPayloadLength - 2) != details.size){
00461                                 sendErrorInternal(payloadLengthTypeMismatch);
00462                                 break;
00463                         }
00464 
00465                         if((details.FlashPage == 0) || (details.FlashAddress == 0)){
00466                                 sendErrorInternal(invalidMemoryActionForID);
00467                                 break;
00468                         }
00469 
00470                         if(locationID < 16){
00471                                 unsigned short errorID = validateMainTable((mainTable*)RXBufferCurrentPosition);
00472                                 if(errorID != 0){
00473                                         sendErrorInternal(errorID);
00474                                         break;
00475                                 }
00476                         }/* else{ hope for the best ;-) } */
00477 
00478                         /* Copy from the RX buffer to the block of flash */
00479                         unsigned short errorID = writeBlock(details.FlashPage, (unsigned short*)details.FlashAddress, RPAGE, (unsigned short*)RXBufferCurrentPosition, details.size);
00480 
00481                         /* If flash write failed for some reason */
00482                         if(errorID != 0){
00483                                 sendErrorInternal(errorID);
00484                                 break;
00485                         }
00486 
00487                         /* If present in ram, update that too */
00488                         if((details.RAMPage != 0) && (details.RAMAddress != 0)){
00489                                 /* Save page values for restore */
00490                                 unsigned char oldRamPage = RPAGE;
00491                                 /* Set the viewable ram page */
00492                                 RPAGE = details.RAMPage;
00493                                 /* Copy from the RX buffer to the block of ram */
00494                                 memcpy(details.RAMAddress, RXBufferCurrentPosition, details.size);
00495                                 /* Restore the original ram and flash pages */
00496                                 RPAGE = oldRamPage;
00497                         }
00498 
00499                         sendAckIfRequired(); // TODO implement
00500                         // TODO document errors can always be returned and add error check in to send as response for ack and async otherwise
00501                         break;
00502                 }
00503                 case retrieveBlockFromRAM:
00504                 {
00505                         if(RXCalculatedPayloadLength != 2){
00506                                 sendErrorInternal(payloadLengthTypeMismatch);
00507                                 break;
00508                         }
00509 
00510                         /* Extract the ram location ID from the received data */
00511                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00512                         /* Store it back into the output data */
00513                         *(unsigned short*)TXBufferCurrentPositionHandler = locationID;
00514                         TXBufferCurrentPositionHandler += 2;
00515 
00516                         /* If it's a main table we are returning, specify the limits explicitly */
00517                         if(locationID < 16){
00518                                 /* Store it back into the output data */
00519                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_RPM_LENGTH;
00520                                 TXBufferCurrentPositionHandler += 2;
00521                                 /* Store it back into the output data */
00522                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_LOAD_LENGTH;
00523                                 TXBufferCurrentPositionHandler += 2;
00524                                 /* Store it back into the output data */
00525                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_MAIN_LENGTH;
00526                                 TXBufferCurrentPositionHandler += 2;
00527                         }
00528 
00529                         /* Look up the memory location details */
00530                         blockDetails details;
00531                         lookupBlockDetails(locationID, &details);
00532 
00533                         if((details.RAMPage == 0) || (details.RAMAddress == 0)){
00534                                 sendErrorInternal(invalidMemoryActionForID);
00535                                 break;
00536                         }
00537 
00538                         /* Save page value for restore and set the visible page */
00539                         unsigned char oldRamPage = RPAGE;
00540                         RPAGE = details.RAMPage;
00541 
00542                         /* Copy the block of ram to the TX buffer */
00543                         memcpy(TXBufferCurrentPositionHandler, details.RAMAddress, details.size);
00544                         TXBufferCurrentPositionHandler += details.size;
00545 
00546                         /* Restore the original ram and flash pages */
00547                         RPAGE = oldRamPage;
00548 
00549                         checksumAndSend();
00550                         break;
00551                 }
00552                 case retrieveBlockFromFlash:
00553                 {
00554                         if(RXCalculatedPayloadLength != 2){
00555                                 sendErrorInternal(payloadLengthTypeMismatch);
00556                                 break;
00557                         }
00558 
00559                         /* Extract the flash location ID from the received data */
00560                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00561                         /* Store it back into the output data */
00562                         *(unsigned short*)TXBufferCurrentPositionHandler = locationID;
00563                         TXBufferCurrentPositionHandler += 2;
00564 
00565                         /* If it's a main table we are returning, specify the limits explicitly */
00566                         if(locationID < 16){
00567                                 /* Store it back into the output data */
00568                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_RPM_LENGTH;
00569                                 TXBufferCurrentPositionHandler += 2;
00570                                 /* Store it back into the output data */
00571                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_LOAD_LENGTH;
00572                                 TXBufferCurrentPositionHandler += 2;
00573                                 /* Store it back into the output data */
00574                                 *(unsigned short*)TXBufferCurrentPositionHandler = MAINTABLE_MAX_MAIN_LENGTH;
00575                                 TXBufferCurrentPositionHandler += 2;
00576                         }
00577 
00578                         /* Look up the memory location details */
00579                         blockDetails details;
00580                         lookupBlockDetails(locationID, &details);
00581 
00582                         if((details.FlashPage == 0) || (details.FlashAddress == 0)){
00583                                 sendErrorInternal(invalidMemoryActionForID);
00584                                 break;
00585                         }
00586 
00587                         /* Save page value for restore and set the visible page */
00588                         unsigned char oldFlashPage = PPAGE;
00589                         PPAGE = details.FlashPage;
00590 
00591                         /* Copy the block of flash to the TX buffer */
00592                         memcpy(TXBufferCurrentPositionHandler, details.FlashAddress, details.size);
00593                         TXBufferCurrentPositionHandler += details.size;
00594 
00595                         /* Restore the original ram and flash pages */
00596                         PPAGE = oldFlashPage;
00597 
00598                         checksumAndSend();
00599                         break;
00600                 }
00601                 case burnBlockFromRamToFlash:
00602                 {
00603                         if(RXCalculatedPayloadLength != 2){
00604                                 sendErrorInternal(payloadLengthTypeMismatch);
00605                                 break;
00606                         }
00607 
00608                         /* Extract the flash location ID from the received data */
00609                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00610 
00611                         /* Look up the memory location details */
00612                         blockDetails details;
00613                         lookupBlockDetails(locationID, &details);
00614 
00615                         /* Check that all data we need is present */
00616                         if((details.RAMPage == 0) || (details.RAMAddress == 0) || (details.FlashPage == 0) || (details.FlashAddress == 0)){
00617                                 sendErrorInternal(invalidMemoryActionForID);
00618                                 break;
00619                         }
00620 
00621                         if(details.size < 1024){
00622                                 sendErrorInternal(0x0999);
00623                                 /* create some sort of function to copy the flash sector up into
00624                                  * the serial rx buffer in the high end and then over write with
00625                                  * the small piece defined either from incoming data, or from its
00626                                  * memory location. Then just call burn in the normal way.
00627                                  *
00628                                  * function could take :
00629                                  * pointer to the buffer region (must be 1024 long or more)
00630                                  * rpage, address, length of data to be persisted
00631                                  * ppage, address of the sector to retrieve the rest of the data from
00632                                  * pointer to the details object we want to use for the following call :
00633                                  */
00634                         }
00635 
00636                         unsigned short errorID = writeBlock(details.RAMPage, (unsigned short*)details.RAMAddress, details.FlashPage, (unsigned short*)details.FlashAddress, details.size);
00637 
00638                         if(errorID != 0){
00639                                 sendErrorInternal(errorID);
00640                                 break;
00641                         }
00642 
00643                         sendDebugInternal("Copied RAM to Flash!");
00644                         break;
00645                 }
00646                 case eraseAllBlocksFromFlash:
00647                 {
00648                         if(RXCalculatedPayloadLength != 0){
00649                                 sendErrorInternal(payloadLengthTypeMismatch);
00650                                 break;
00651                         }
00652 
00653                         // perform function TODO
00654                         unsigned char page = 0xE0;
00655                         unsigned short start = 0x8000;
00656                         unsigned short end = 0xC000;
00657                         unsigned short inc = 0x0400;
00658                         for(;page < 0xF8;page++){
00659                                 unsigned short addr;
00660                                 for(addr = start;addr < end; addr += inc){
00661                                         eraseSector(page, (unsigned short*)addr);
00662                                 }
00663                         }
00664                         sendDebugInternal("Erased three 128k Flash blocks!");
00665                         break;
00666                 }
00667                 case burnAllBlocksOfFlash:
00668                 {
00669                         if(RXCalculatedPayloadLength != 0){
00670                                 sendErrorInternal(payloadLengthTypeMismatch);
00671                                 break;
00672                         }
00673 
00674                         // perform function TODO
00675                         unsigned char page = 0xE0;
00676                         unsigned short start = 0x8000;
00677                         unsigned short end = 0xC000;
00678                         unsigned short inc = 0x0400;
00679                         for(;page < 0xF8;page++){
00680                                 unsigned short addr;
00681                                 for(addr = start;addr < end; addr += inc){
00682                                         writeSector(RPAGE, (unsigned short*)0xc000, page, (unsigned short*)addr);
00683                                 }
00684                         }
00685                         sendDebugInternal("Overwrote three 128k Flash blocks!");
00686                         break;
00687                 }
00688                 case adjustMainTableCell:
00689                 {
00690                         if(RXCalculatedPayloadLength != 8){
00691                                 sendErrorInternal(payloadLengthTypeMismatch);
00692                                 break;
00693                         }
00694 
00695                         /* Extract the flash location ID from the received data */
00696                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00697                         RXBufferCurrentPosition += 2;
00698 
00699                         /* Check the ID to ensure it is a main table */
00700                         if(15 < locationID){
00701                                 sendErrorInternal(invalidIDForMainTableAction);
00702                                 break;
00703                         }
00704 
00705                         /* Extract the cell value and coordinates */
00706                         unsigned short RPMIndex = *((unsigned short*)RXBufferCurrentPosition);
00707                         RXBufferCurrentPosition += 2;
00708                         unsigned short LoadIndex = *((unsigned short*)RXBufferCurrentPosition);
00709                         RXBufferCurrentPosition += 2;
00710                         unsigned short cellValue = *((unsigned short*)RXBufferCurrentPosition);
00711 
00712                         /* Look up the memory location details */
00713                         blockDetails details;
00714                         lookupBlockDetails(locationID, &details);
00715 
00716                         /* Attempt to set the value */
00717                         unsigned short errorID = setPagedMainTableCellValue(details.RAMPage, details.RAMAddress, RPMIndex, LoadIndex, cellValue);
00718                         if(errorID != 0){
00719                                 sendErrorInternal(errorID);
00720                         }else{
00721                                 sendAckIfRequired();
00722                         }
00723                         break;
00724                 }
00725                 case adjustMainTableRPMAxis:
00726                 {
00727                         if(RXCalculatedPayloadLength != 6){
00728                                 sendErrorInternal(payloadLengthTypeMismatch);
00729                                 break;
00730                         }
00731 
00732                         /* Extract the flash location ID from the received data */
00733                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00734                         RXBufferCurrentPosition -= 2;
00735 
00736                         /* Check the ID to ensure it is a main table */
00737                         if(15 < locationID){
00738                                 sendErrorInternal(invalidIDForMainTableAction);
00739                                 break;
00740                         }
00741 
00742                         /* Extract the cell value and coordinates */
00743                         unsigned short RPMIndex = *((unsigned short*)RXBufferCurrentPosition);
00744                         RXBufferCurrentPosition -= 2;
00745                         unsigned short RPMValue = *((unsigned short*)RXBufferCurrentPosition);
00746 
00747                         /* Look up the memory location details */
00748                         blockDetails details;
00749                         lookupBlockDetails(locationID, &details);
00750 
00751                         /* Attempt to set the value */
00752                         unsigned short errorID = setPagedMainTableRPMValue(details.RAMPage, details.RAMAddress, RPMIndex, RPMValue);
00753                         if(errorID != 0){
00754                                 sendErrorInternal(errorID);
00755                         }else{
00756                                 sendAckIfRequired();
00757                         }
00758                         break;
00759                 }
00760                 case adjustMainTableLoadAxis:
00761                 {
00762                         if(RXCalculatedPayloadLength != 6){
00763                                 sendErrorInternal(payloadLengthTypeMismatch);
00764                                 break;
00765                         }
00766 
00767                         /* Extract the flash location ID from the received data */
00768                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00769                         RXBufferCurrentPosition -= 2;
00770 
00771                         /* Check the ID to ensure it is a main table */
00772                         if(15 < locationID){
00773                                 sendErrorInternal(invalidIDForMainTableAction);
00774                                 break;
00775                         }
00776 
00777                         /* Extract the cell value and coordinates */
00778                         unsigned short LoadIndex = *((unsigned short*)RXBufferCurrentPosition);
00779                         RXBufferCurrentPosition -= 2;
00780                         unsigned short LoadValue = *((unsigned short*)RXBufferCurrentPosition);
00781 
00782                         /* Look up the memory location details */
00783                         blockDetails details;
00784                         lookupBlockDetails(locationID, &details);
00785 
00786                         /* Attempt to set the value */
00787                         unsigned short errorID = setPagedMainTableLoadValue(details.RAMPage, details.RAMAddress, LoadIndex, LoadValue);
00788                         if(errorID != 0){
00789                                 sendErrorInternal(errorID);
00790                         }else{
00791                                 sendAckIfRequired();
00792                         }
00793                         break;
00794                 }
00795                 case adjust2dTableAxis:
00796                 {
00797                         if(RXCalculatedPayloadLength != 6){
00798                                 sendErrorInternal(payloadLengthTypeMismatch);
00799                                 break;
00800                         }
00801 
00802                         /* Extract the flash location ID from the received data */
00803                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00804                         RXBufferCurrentPosition -= 2;
00805 
00806                         /* Check the ID to ensure it is a 2d table */
00807                         if((locationID > 899) || (locationID < 400)){
00808                                 sendErrorInternal(invalidIDForTwoDTableAction);
00809                                 break;
00810                         }
00811 
00812                         /* Extract the cell value and coordinates */
00813                         unsigned short axisIndex = *((unsigned short*)RXBufferCurrentPosition);
00814                         RXBufferCurrentPosition -= 2;
00815                         unsigned short axisValue = *((unsigned short*)RXBufferCurrentPosition);
00816 
00817                         /* Look up the memory location details */
00818                         blockDetails details;
00819                         lookupBlockDetails(locationID, &details);
00820 
00821                         /* Attempt to set the value */
00822                         unsigned short errorID = setPagedTwoDTableAxisValue(details.RAMPage, details.RAMAddress, axisIndex, axisValue);
00823                         if(errorID != 0){
00824                                 sendErrorInternal(errorID);
00825                         }else{
00826                                 sendAckIfRequired();
00827                         }
00828                         break;
00829                 }
00830                 case adjust2dTableCell:
00831                 {
00832                         if(RXCalculatedPayloadLength != 6){
00833                                 sendErrorInternal(payloadLengthTypeMismatch);
00834                                 break;
00835                         }
00836 
00837                         /* Extract the flash location ID from the received data */
00838                         unsigned short locationID = *((unsigned short*)RXBufferCurrentPosition);
00839                         RXBufferCurrentPosition -= 2;
00840 
00841                         /* Check the ID to ensure it is a 2d table */
00842                         if((locationID > 899) || (locationID < 400)){
00843                                 sendErrorInternal(invalidIDForTwoDTableAction);
00844                                 break;
00845                         }
00846 
00847                         /* Extract the cell value and coordinates */
00848                         unsigned short cellIndex = *((unsigned short*)RXBufferCurrentPosition);
00849                         RXBufferCurrentPosition -= 2;
00850                         unsigned short cellValue = *((unsigned short*)RXBufferCurrentPosition);
00851 
00852                         /* Look up the memory location details */
00853                         blockDetails details;
00854                         lookupBlockDetails(locationID, &details);
00855 
00856                         /* Attempt to set the value */
00857                         unsigned short errorID = setPagedTwoDTableCellValue(details.RAMPage, details.RAMAddress, cellIndex, cellValue);
00858                         if(errorID != 0){
00859                                 sendErrorInternal(errorID);
00860                         }else{
00861                                 sendAckIfRequired();
00862                         }
00863                         break;
00864                 }
00865                 case requestBasicDatalog:
00866                 {
00867                         if((RXCalculatedPayloadLength > 2) || (RXCalculatedPayloadLength == 1)){
00868                                 sendErrorInternal(payloadLengthTypeMismatch);
00869                                 break;
00870                         }else if(RXCalculatedPayloadLength == 2){
00871                                 unsigned short newConfiguredLength = *((unsigned short*)RXBufferCurrentPosition);
00872                                 if(newConfiguredLength > maxBasicDatalogLength){
00873                                         sendErrorInternal(datalogLengthExceedsMax);
00874                                         break;
00875                                 }else{
00876                                         configuredBasicDatalogLength = newConfiguredLength;
00877                                 }
00878                         }
00879 
00880                         /* Set the length field up */
00881                         *TXHeaderFlags |= HEADER_HAS_LENGTH;
00882                         *(unsigned short*)TXBufferCurrentPositionHandler = configuredBasicDatalogLength;
00883 
00884                         /* Fill out the log and send */
00885                         populateBasicDatalog();
00886                         checksumAndSend();
00887                         break;
00888                 }
00889                 case requestConfigurableDatalog:
00890                 {
00891                         // perform function TODO
00892                         sendErrorInternal(unimplementedFunction);
00893                         break;
00894                 }
00895                 case forwardPacketOverCAN:
00896                 {
00897                         // perform function TODO
00898                         sendErrorInternal(unimplementedFunction);
00899                         break;
00900                 }
00901                 case forwardPacketOverOtherUART:
00902                 {
00903                         // perform function TODO
00904                         sendErrorInternal(unimplementedFunction);
00905                         break;
00906                 }
00907                 case setAsyncDatalogType:
00908                 {
00909                         if(RXCalculatedPayloadLength != 1){
00910                                 sendErrorInternal(payloadLengthTypeMismatch);
00911                                 break;
00912                         }
00913 
00914                         unsigned char newDatalogType = *((unsigned char*)RXBufferCurrentPosition);
00915                         if(newDatalogType > 0x03){
00916                                 sendErrorInternal(noSuchAsyncDatalogType);
00917                                 break;
00918                         }else{
00919                                 asyncDatalogType = newDatalogType;
00920                         }
00921 
00922                         sendAckIfRequired();
00923                         break;
00924                 }
00925                 default:
00926                         if((RXHeaderPayloadID % 2) == 1){
00927                                 sendErrorInternal(invalidFirmwarePayloadID);
00928                         }else{
00929                                 sendErrorInternal(unrecognisedFirmwarePayloadID);
00930                         }
00931                 }
00932         }
00933         /* Switch reception back on now that we are done with the received data */
00934         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00935         PORTK |= BIT0;
00936 }
00937 
00938 //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
00939 
00940 //below this to another file for now
00941 
00942 /* Wrapper for use outside the com handler */
00943 void sendErrorIfClear(unsigned short errorID){
00944         if(!TXBufferInUseFlags){
00945                 TXBufferInUseFlags = ONES;
00946                 sendErrorInternal(errorID);
00947         }else{
00948                 Counters.commsErrorMessagesNotSent++;
00949         }
00950 }
00951 
00952 
00953 /* Wrapper for use outside the com handler */
00954 void sendErrorBusyWait(unsigned short errorID){
00955         while(TXBufferInUseFlags){} /* Wait till clear to send */
00956         TXBufferInUseFlags = ONES;
00957         sendErrorInternal(errorID);
00958 }
00959 
00960 
00961 /* Send an error code out in a frequency limited way */
00962 void sendErrorInternal(unsigned short errorCode){ // TODO build wrapper to check for use inside handler or not and not send if busy and not in handler ditto for debug
00963 
00964 //      set buffer in use, consider blocking interrupts to do this cleanly
00965 
00966 
00967         //      TXBufferInUseFlags = 0;
00968         /* No need for atomic block here as one of two conditions will always be */
00969         /* true when calling this. Either we have been flagged to receive and    */
00970         /* decode a packet, or we are in an ISR. In either case it is safe to    */
00971         /* check the flags and initiate the sequence if they are clear.          */
00972 //      if(RXTXSerialStateFlags & TX_IN_PROGRESS){
00973                 /* It's OK to return without resetting as it will be done by */
00974                 /* either of those processes if they are underway. The other */
00975                 /* processes are not overridden because they have priority.  */
00976 //              return;
00977 //      }else{ /* Turn off reception */
00978                 /* It's OK to turn this off if nothing was currently being received */
00979 //              SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00980 //              SCI0CR2 &= SCICR2_RX_DISABLE;
00981 
00982                 /* Build up the packet */
00983                 /* Set the pointer to the start */
00984                 TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer;
00985                 /* Set the length */
00986 //              TXPacketLengthToSend = 5; /* Flags + Payload ID + Error Code */
00987                 /* Flags = protocol with no extra fields */
00988                 *TXBufferCurrentPositionHandler = 0x01;
00989                 TXBufferCurrentPositionHandler++;
00990                 /* Set the payload ID */
00991                 *((unsigned short*)TXBufferCurrentPositionHandler) = asyncErrorCodePacket;
00992                 TXBufferCurrentPositionHandler += 2;
00993                 /* Set the error code */
00994                 *((unsigned short*)TXBufferCurrentPositionHandler) = errorCode;
00995                 TXBufferCurrentPositionHandler += 2;
00996                 checksumAndSend();
00997 //      }
00998 }
00999 
01000 
01001 /* Wrapper for use outside the com handler */
01002 void sendDebugIfClear(unsigned char* message){
01003         if(!TXBufferInUseFlags){
01004                 TXBufferInUseFlags = ONES;
01005                 sendDebugInternal(message);
01006         }else{
01007                 Counters.commsDebugMessagesNotSent++;
01008         }
01009 }
01010 
01011 
01012 /* Wrapper for use outside the com handler */
01013 void sendDebugBusyWait(unsigned char* message){
01014         while(TXBufferInUseFlags){} /* Wait till clear to send */
01015         TXBufferInUseFlags = ONES;
01016         sendDebugInternal(message);
01017 }
01018 
01019 
01020 /* Send a null terminated message out on the broadcast address */
01021 void sendDebugInternal(unsigned char* message){
01022 
01023 //      set buffer in use, consider blocking interrupts to do this cleanly
01024 
01025 //      if(TRUE){
01026 //              Counters.serialDebugUnsentCounter++;
01027 //              return;
01028 //      }
01029         // wrong :
01030         /* No need for atomic block here as one of two conditions will always be */
01031         /* true when calling this. Either we have been flagged to receive and    */
01032         /* decode a packet, or we are in an ISR. In either case it is safe to    */
01033         /* check the flags and initiate the sequence if they are clear.          */
01034         //if(RXTXSerialStateFlags & TX_IN_PROGRESS){
01035                 // wrong :
01036                 /* It's OK to return without resetting as it will be done by */
01037                 /* either of those processes if they are underway. The other */
01038                 /* processes are not overridden because they have priority.  */
01039                 //TXBufferInUseFlags = 0;
01040                 //return;
01041 //      }else{ /* Turn off reception */
01042                 /* It's OK to turn this off if nothing was currently being received */
01043         //      SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
01044         //      SCI0CR2 &= SCICR2_RX_DISABLE;
01045 
01046                 /* Build up the packet */
01047                 /* Set the pointer to the start and init the length */
01048                 TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer;
01049 
01050                 /* Load a protocol with length header into the TX buffer ready for masking */
01051                 *TXBufferCurrentPositionHandler = 0x11;
01052                 TXBufferCurrentPositionHandler++;
01053 
01054                 /* Set the payload ID */
01055                 *((unsigned short*)TXBufferCurrentPositionHandler) = asyncDebugInfoPacket;
01056                 TXBufferCurrentPositionHandler += 2;
01057 
01058                 /* Store the length location */
01059                 unsigned short* TXLength = (unsigned short*)TXBufferCurrentPositionHandler;
01060                 TXBufferCurrentPositionHandler += 2;
01061 
01062                 /* Copy the string into place and record the length copied */
01063                 unsigned short messageLength = stringCopy(TXBufferCurrentPositionHandler, message);
01064                 *TXLength = messageLength;
01065                 TXBufferCurrentPositionHandler += messageLength;
01066 
01067                 checksumAndSend();
01068         //}
01069 }
01070 
01071 
01072 /* This function should be period limited to about 10 seconds internally (or by scheduler) */
01073 //void checkCountersAndSendErrors(){
01074         // compare time stamps  with current time stamps and execute if old enough. (if no scheduler)
01075 
01076         // compare counters with counters cache (from last time) sending an error packet when they differ
01077 
01078         // copy counters to counters cache for next time
01079 
01080         // send errors with busy wait on the basis that all errors should be taken care of and not be sent in fairly short order?
01081 
01082         // or send with isr but just busy wait for it to finish before sending the next?
01083 
01084         // debug messages, busy wait or isr or both, perhaps busy wait till able to send, lock sending (need semaphore for this as well as sending one?) and initiate send, then carry on? investigate timeframes for sends of smallish 100byte packets.
01085 
01086         // need to figure out how to queue received packets for processing when we are currently sending stuff out.
01087 
01088         // above notes don't belong here really.
01089 //}
01090 
01091 
01092 //void prepareDatalog(){
01093 //      // send data log by default otherwise
01094 //      unsigned char chunksExpected = 8; // based on configuration, yet to determine how to calculate this number
01095 //      unsigned char chunksLoaded = 0;
01096 //      if ((!receiving) && (datalogMask & rawVarsMask)) {
01097 //              //
01098 //              chunksLoaded++;
01099 //      }
01100 //      if ((!receiving) && (datalogMask & Mask)) {
01101 //              //
01102 //              chunksLoaded++;
01103 //      }
01104 //      if ((!receiving) && (datalogMask & Mask)) {
01105 //              //
01106 //              chunksLoaded++;
01107 //      }
01108 //      if ((!receiving) && (datalogMask & Mask)) {
01109 //              //
01110 //              chunksLoaded++;
01111 //      }
01112 //      if ((!receiving) && (datalogMask & Mask)) {
01113 //              //
01114 //              chunksLoaded++;
01115 //      }
01116 //      if ((!receiving) && (datalogMask & Mask)) {
01117 //              //
01118 //              chunksLoaded++;
01119 //      }
01120 //      if ((!receiving) && (datalogMask & Mask)) {
01121 //              //
01122 //              chunksLoaded++;
01123 //      }
01124 //      if ((!receiving) && (datalogMask & Mask)) {
01125 //              //
01126 //              chunksLoaded++;
01127 //      }
01128 //      //      set the length
01129 //      //      the pointer should be correct already
01130 //}
01131 
01132 
01133 /* TODO when implementing, check that ppage is OK!!! */
01134 void sendAckIfRequired(){
01135         TXBufferInUseFlags = 0;
01136         // check PPAGE while implementing TODO
01137 }

Generated on Mon Dec 22 21:29:17 2008 for freeems by  doxygen 1.5.2