Subversion Repositories HomeAutomation

Rev

Blame | Last modification | View Log | SVN | RSS feed

  1. #include "DownloadState.h"
  2.  
  3.  
  4.  
  5. static HexFile * hf;
  6. //static CSerial * serial;
  7. static SerialConnection * serial;
  8.  
  9. static HANDLE  hRunMutex;                   // "Keep Running" mutex
  10.  
  11. void downloadState(void *pMyID);
  12.  
  13. typedef enum { SEND_START, WAIT_ACK, SEND_PGM_DATA, WAIT_OWN_PACKET, WAIT_PGM_ACK, RESEND_ADDR, WAIT_DONE, SEND_DONE, DONE, WAIT_ADDR_ACK,DEBUG_STATE1,DEBUG_STATE2 } dState;
  14.  
  15.  
  16. void downloadState(void *pMyID)
  17. {
  18.     long lLastError = 0;
  19.  
  20.     dState pgs = SEND_START;
  21.     DWORD t = 0;
  22.     CanProtoMessage * outCm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));
  23.     CanProtoMessage * cm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));
  24.     unsigned char data[8];
  25.     unsigned char byteSent = 0;
  26.     unsigned long currentAddress = 0;
  27.     unsigned char bytesToWrite[PACKET_LENGTH];
  28.  
  29.     while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT )
  30.     {
  31.  
  32.         bool hasMessage = serial->getMessage(cm);
  33.         if (hasMessage)
  34.         {
  35.             unsigned char *dtmp = cm->getData();
  36.             for(int i=0;i<8;i++) data[i]=dtmp[i];
  37.             printf("[%ld] Has message\n",GetTickCount());
  38.         }
  39.  
  40.         switch(pgs)
  41.         {
  42.              case SEND_START:
  43.                 // Send boot start packet to target.
  44.                 // and wait for ack.
  45.                 currentAddress = hf->getAddrLower();
  46.                 data[RID_INDEX] = TARGET_ID;
  47.                 data[ADDRU_INDEX] = (unsigned char)((currentAddress & 0xFF0000) >> 16);
  48.                 data[ADDRH_INDEX] = (unsigned char)((currentAddress & 0xFF00) >> 8);
  49.                 data[ADDRL_INDEX] = (unsigned char)(currentAddress & 0xFF);
  50.                 outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_INIT, MY_NID, MY_ID, 8, data);
  51.                 outCm->getBytes(bytesToWrite);
  52.                 serial->write(bytesToWrite,PACKET_LENGTH);
  53.                 t = GetTickCount();
  54.                 pgs = WAIT_ACK;
  55.             break;
  56.  
  57.  
  58.             case WAIT_ACK:
  59.                
  60.                 // Check for timeout, resend start packet in that case..
  61.                 if ((GetTickCount() - t) > TIMEOUT_MS)
  62.                 {
  63.                     pgs = SEND_START;
  64.                 }
  65.  
  66.                 // If received ack.
  67.                 if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
  68.                 {
  69.                     // If no error
  70.                     if (data[ERR_INDEX] == ERR_NO_ERROR)
  71.                     {
  72.                         // Start sending program data..
  73.                         byteSent = 0;
  74.                         pgs = SEND_PGM_DATA;
  75.                     }
  76.                     else
  77.                     {
  78.                         // else resend start..
  79.                         pgs = SEND_START;
  80.                     }
  81.                 }
  82.             break;
  83.  
  84.             case SEND_PGM_DATA:
  85.                 // Send program data.
  86.                 for (int i = 0; i < 8; i++)
  87.                 {
  88.                     // Populate data.
  89.                     data[i] = hf->getByte(currentAddress + i + byteSent);
  90.                 }
  91.                 outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, (unsigned int)((unsigned int)((unsigned int)(floor(((double)byteSent/8.0)))<<2) + (FUNCC_BOOT_PGM)), MY_NID, MY_ID, 8, data);
  92.                 outCm->getBytes(bytesToWrite);
  93.                 serial->write(bytesToWrite,PACKET_LENGTH);
  94.                 t = GetTickCount();
  95.                 pgs = WAIT_OWN_PACKET;
  96.             break;
  97.  
  98.             case WAIT_OWN_PACKET:
  99.                 // Wait reciving own packet, if timeout, resend last.
  100.                 if ((GetTickCount() - t) > TIMEOUT_MS)
  101.                 {
  102.                     //pgs = dState.SEND_PGM_DATA;
  103.                     pgs = RESEND_ADDR;
  104.                 }
  105.  
  106.                 // If received own packet..
  107.                 if (hasMessage && outCm->equals(cm))
  108.                 {
  109.  
  110.                     byteSent += 8;
  111.  
  112.                     // Check if 64 bytes sent or not..
  113.                     if (byteSent == 64)
  114.                     {
  115.                         // Yes, wait for ack.
  116.                         t = GetTickCount();
  117.                         pgs = WAIT_PGM_ACK;
  118.                     }
  119.                     else
  120.                     {
  121.                         // No, send more.
  122.                         pgs = SEND_PGM_DATA;
  123.                     }
  124.  
  125.                 }
  126.             break;
  127.  
  128.  
  129.             case WAIT_PGM_ACK:
  130.                 // Wait for pgm ack.
  131.                 if ((GetTickCount() - t) > 2*TIMEOUT_MS)
  132.                 {
  133.                     // Woops, error. Resend address and start over.
  134.                     pgs = RESEND_ADDR;
  135.                 }
  136.  
  137.                 // If received ack.
  138.                 if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
  139.                 {
  140.                     // If no error
  141.                     if (data[ERR_INDEX] == ERR_NO_ERROR)
  142.                     {
  143.                         currentAddress += 64;
  144.                         // Check if end.
  145.                         if (currentAddress > hf->getAddrUpper())
  146.                         {
  147.                             // Yes, we are done, send done.
  148.                             pgs = SEND_DONE;
  149.                         }
  150.                         else
  151.                         {
  152.                             // More to write.
  153.                             byteSent = 0;
  154.                             pgs = SEND_PGM_DATA;
  155.                         }
  156.                     }
  157.                     else
  158.                     {
  159.                         // else resend start..
  160.                         pgs = RESEND_ADDR;
  161.                     }
  162.                 }
  163.             break;
  164.  
  165.  
  166.             case SEND_DONE:
  167.                 // Send done
  168.                 outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_DONE, MY_NID, MY_ID, 8, data);
  169.                 outCm->getBytes(bytesToWrite);
  170.                 serial->write(bytesToWrite,PACKET_LENGTH);
  171.                 t = GetTickCount();
  172.                 pgs = WAIT_DONE;
  173.             break;
  174.  
  175.             case RESEND_ADDR:
  176.                 // Resend addr.
  177.                 data[RID_INDEX] = TARGET_ID;
  178.                 data[ADDRU_INDEX] = (byte)((currentAddress & 0xFF0000) >> 16);
  179.                 data[ADDRH_INDEX] = (byte)((currentAddress & 0xFF00) >> 8);
  180.                 data[ADDRL_INDEX] = (byte)(currentAddress & 0xFF);
  181.                 outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_ADDR, MY_NID, MY_ID, 8, data);
  182.                 outCm->getBytes(bytesToWrite);
  183.                 serial->write(bytesToWrite,PACKET_LENGTH);
  184.                 t = GetTickCount();
  185.                 pgs = WAIT_ADDR_ACK;
  186.             break;
  187.  
  188.  
  189.             case WAIT_ADDR_ACK:
  190.                 // Check for timeout, resend addr packet in that case..
  191.                 if ((GetTickCount() - t) > TIMEOUT_MS)
  192.                 {
  193.                     pgs = RESEND_ADDR;
  194.                 }
  195.  
  196.                 // If received ack.
  197.                 if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
  198.                 {
  199.                     // If no error
  200.                     if (data[ERR_INDEX] == ERR_NO_ERROR)
  201.                     {
  202.                         // Start sending program data..
  203.                         byteSent = 0;
  204.                         pgs = SEND_PGM_DATA;
  205.                     }
  206.                     else
  207.                     {
  208.                         // else resend addr..
  209.                         pgs = RESEND_ADDR;
  210.                     }
  211.                 }
  212.             break;
  213.  
  214.             case WAIT_DONE:
  215.                 // Check for timeout, resend done packet in that case..
  216.                 if ((GetTickCount() - t) > TIMEOUT_MS)
  217.                 {
  218.                     pgs = SEND_DONE;
  219.                 }
  220.  
  221.                 // If received ack.
  222.                 if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
  223.                 {
  224.                     // If no error
  225.                     if (data[ERR_INDEX] == ERR_NO_ERROR)
  226.                     {
  227.                         // Start sending program data..
  228.                         byteSent = 0;
  229.                         pgs = DONE;
  230.                     }
  231.                     else
  232.                     {
  233.                         // else resend addr..
  234.                         pgs = RESEND_ADDR;
  235.                     }
  236.                 }
  237.             break;
  238.  
  239.             case DONE:
  240.                 downloadStop();
  241.                 printf("DONE!\n");
  242.             break;
  243.         }
  244.     }
  245.  
  246.     return;
  247. }
  248.  
  249.  
  250. void downloadStart(SerialConnection * ser,HexFile *hex)
  251. {
  252.     hf = hex;
  253.     serial = ser;
  254.     hRunMutex = CreateMutex( NULL, TRUE, NULL );      // Set
  255.     _beginthread( downloadState, 0, 0 );
  256.  
  257. }
  258.  
  259. void downloadStop( void )
  260. {
  261.     ReleaseMutex( hRunMutex );
  262.     CloseHandle( hRunMutex );
  263. }
  264.  
  265.