Subversion Repositories HomeAutomation

Rev

Rev 876 | Rev 878 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading;
  5.  
  6. //this class should probably be integrated into canNMT instead
  7.  
  8. public class Downloader {
  9.     private HexFile hf;
  10.     private DaemonConnection dc;
  11.     private bool isBiosUpdate;
  12.     private ulong dlOffset = 0;
  13.     //private Thread down;
  14.     private byte receiveID;
  15.     private uint hwid;
  16.     private bool HWID_INUSE;
  17.    
  18.     private enum dState { SEND_START, WAIT_ACK_PRG, SEND_PGM_DATA, WAIT_ACK_DATA, RESEND_ADDR, WAIT_DONE, SEND_DONE, SEND_BIOS_UPDATE, SEND_RESET, DONE, DEBUG_STATE2, WAIT_BOOT, SEND_EMPTY_START, WAIT_ACK_PRG_EMPTY, SEND_EMPTY_DATA, WAIT_ACK_EMPTY_DATA, SEND_DONE_EMPTY, WAIT_DONE_EMPTY};
  19.    
  20.     private const byte CAN_NMT              = 0x00;
  21.    
  22.     private const byte CAN_NMT_RESET        = 0x04;
  23.     private const byte CAN_NMT_BIOS_START   = 0x08;
  24.     private const byte CAN_NMT_PGM_START    = 0x0C;
  25.     private const byte CAN_NMT_PGM_DATA     = 0x10;
  26.     private const byte CAN_NMT_PGM_END      = 0x14;
  27.     private const byte CAN_NMT_PGM_COPY     = 0x18;
  28.     private const byte CAN_NMT_PGM_ACK      = 0x1C;
  29.     private const byte CAN_NMT_PGM_NACK     = 0x20;
  30.     private const byte CAN_NMT_START_APP    = 0x24;
  31.     private const byte CAN_NMT_APP_START    = 0x28;
  32.     private const byte CAN_NMT_HEARTBEAT    = 0x2C;
  33.    
  34.     private const byte MY_ID = 0x00;
  35.     //private const byte TARGET_ID = 0x78;
  36.     private const byte MY_NID = 0x0;
  37.     private const byte ADDR0_INDEX = 0;
  38.     private const byte ADDR1_INDEX = 1;
  39.     private const byte ADDR2_INDEX = 2;
  40.     private const byte ADDR3_INDEX = 3;
  41.  
  42.     private const byte HWID0_INDEX = 4;
  43.     private const byte HWID1_INDEX = 5;
  44.     private const byte HWID2_INDEX = 6;
  45.     private const byte HWID3_INDEX = 7;
  46.    
  47.     private const int TIMEOUT_MS = 1000;
  48.     private const int TIMEOUT_SHORT_MS = 200;
  49.    
  50.     private long timeStart = 0;
  51.    
  52.     public Downloader(HexFile hf, DaemonConnection dc, byte receiveID, bool isBiosUpdate, bool HWID_INUSE, uint hwid) {
  53.         this.hf = hf;
  54.         this.dc = dc;
  55.         this.receiveID = receiveID;
  56.         this.isBiosUpdate = isBiosUpdate;
  57.         this.hwid = hwid;
  58.         this.HWID_INUSE = HWID_INUSE;
  59.     }
  60.    
  61.     public int calcCRC(HexFile hf) {
  62.         int crc=0;
  63.         for (ulong i=hf.getAddrLower(); i <= hf.getAddrUpper(); i++) {
  64.             crc = crc16_update(crc, hf.getByte(i));
  65.         }
  66.         return crc;
  67.     }
  68.    
  69.     public int crc16_update(int crc, byte a) {
  70.         int i;
  71.         crc ^= a;
  72.         for (i = 0; i < 8; ++i) {
  73.             if ((crc & 1) != 0)
  74.                 crc = (crc >> 1) ^ 0xA001;
  75.             else
  76.                 crc = (crc >> 1);
  77.         }
  78.         return crc;
  79.     }
  80.    
  81.     public bool go() {
  82.         if (dc==null || hf==null || hf.getLength()==0) return false;
  83.         return downloader();
  84.     }
  85.    
  86.     public void abort() {
  87.         //if (down != null && down.IsAlive) down.Abort();
  88.     }
  89.    
  90.     public bool downloader() {
  91.         dState pgs = dState.SEND_START;
  92.         int t = 0;
  93.         int t2 = 0;
  94.         CanPacket outCm = null;
  95.         CanPacket cm = null;
  96.         byte[] data = new byte[8];
  97.         uint byteSent = 0;
  98.         ulong currentAddress = 0;
  99.         bool done = false;
  100.         bool errorOccured = false;
  101.        
  102.         //int rotstate=0;
  103.         int dldisplaystate=0;
  104.        
  105.         try {
  106.             if (isBiosUpdate) {
  107.                 dlOffset = hf.getAddrLower();
  108.                 //Console.WriteLine(dlOffset);
  109.                 //dlOffset = 200;
  110.             }
  111.  
  112.             CanNMT cpn = new CanNMT(HWID_INUSE);
  113.             cpn.setReceiver(receiveID);
  114.             bool hasMessage = false;
  115.            
  116.             while (!done) {
  117.                 Thread.Sleep(1);
  118.                
  119.                 switch (pgs) {
  120.                     case dState.SEND_START:
  121.                         // Send boot start packet to target.
  122.                         // and wait for ack.
  123.                         currentAddress = hf.getAddrLower();
  124.                         //data[RID_INDEX] = TARGET_ID;
  125.                         data[ADDR0_INDEX] = (byte)((currentAddress-dlOffset) & 0x0000FF);
  126.                         data[ADDR1_INDEX] = (byte)(((currentAddress-dlOffset) & 0x00FF00) >> 8);
  127.                         data[ADDR2_INDEX] = (byte)(((currentAddress-dlOffset) & 0xFF0000) >> 16);
  128.                         data[ADDR3_INDEX] = 0;
  129.                         if (HWID_INUSE) {
  130.                             data[HWID0_INDEX] = (byte)((hwid) & 0xFF);
  131.                             data[HWID1_INDEX] = (byte)((hwid>>8) & 0xFF);
  132.                             data[HWID2_INDEX] = (byte)((hwid>>16) & 0xFF);
  133.                             data[HWID3_INDEX] = (byte)((hwid>>24) & 0xFF);
  134.                         }
  135.                         //outCm = new CanPacket(CAN_NMT, CAN_NMT_PGM_START, MY_ID, receiveID, 4, data);
  136.                         outCm = cpn.getPgmStartPacket(data);
  137.                         dc.sendCanPacket(outCm);
  138.                         t = Environment.TickCount;
  139.                         t2 = Environment.TickCount;
  140.                         pgs = dState.WAIT_ACK_PRG;
  141.                         timeStart = Environment.TickCount;
  142.                         Console.WriteLine("Downloading...");
  143.                         Console.Write("  0%");
  144.                         break;
  145.                    
  146.                    
  147.                     case dState.WAIT_ACK_PRG:
  148.                         // Check for timeout, resend start packet in that case..
  149.                         if ((Environment.TickCount - t) > TIMEOUT_MS) {
  150.                             Console.WriteLine("Timeout while waiting for start prg ack.");
  151.                             errorOccured = true;
  152.                             pgs = dState.SEND_RESET;
  153.                         }
  154.                         //Thread.Sleep(1);
  155.                         // If received ack.
  156.                         hasMessage = dc.getData(out cm);
  157.                         if (hasMessage) {
  158.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  159.                             if (cpnin.isNMTPacket()) {
  160.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  161.                                 // If no error
  162.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  163.                                     // Start sending program data..
  164.                                     byteSent = 0;
  165.                                     pgs = dState.SEND_PGM_DATA;
  166.                                 }
  167.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK ) {
  168.                                     // else ..
  169.                                     Console.WriteLine("Nack on CAN_NMT_PGM_START.");
  170.                                     errorOccured = true;
  171.                                     pgs = dState.SEND_RESET;
  172.                                 }
  173.                             }
  174.                         }
  175.                         break;
  176.                        
  177.                     case dState.SEND_PGM_DATA:
  178.                         //Console.WriteLine("byteSent = "+byteSent);
  179. //disable                       Console.Write(".");
  180. //Console.Write("\b");
  181. //int curleft = Console.CursorLeft;
  182. //int curtop = Console.CursorTop;
  183. //Console.SetCursorPosition(curleft, curtop-1);
  184.  
  185. //if (rotstate==0) {
  186. //   Console.Write("-");
  187. //   rotstate=1;
  188. //} else if (rotstate==1) {
  189. //   Console.Write("\\");
  190. //   rotstate=2;
  191. //} else if (rotstate==2) {
  192. //   Console.Write("|");
  193. //   rotstate=3;
  194. //} else if (rotstate==3) {
  195. //   Console.Write("/");
  196. //   rotstate=0;
  197. //}
  198. //Console.Write("\r");
  199. //dldisplaystate
  200.  
  201. //FULHACK deulx
  202.                         ulong percent = byteSent*100/(hf.getAddrUpper()-currentAddress);
  203.                        
  204.                         if (percent>9 && dldisplaystate==0) {
  205.                            Console.Write("\r");
  206.                            Console.Write(" "+percent+"%");
  207.                            dldisplaystate=1;
  208.                         } else if (percent>19 && dldisplaystate==1) {
  209.                            Console.Write("\r");
  210.                            Console.Write(" "+percent+"%");
  211.                            dldisplaystate=2;
  212.                         } else if (percent>29 && dldisplaystate==2) {
  213.                            Console.Write("\r");
  214.                            Console.Write(" "+percent+"%");
  215.                            dldisplaystate=3;
  216.                         } else if (percent>39 && dldisplaystate==3) {
  217.                            Console.Write("\r");
  218.                            Console.Write(" "+percent+"%");
  219.                            dldisplaystate=4;
  220.                         } else if (percent>49 && dldisplaystate==4) {
  221.                            Console.Write("\r");
  222.                            Console.Write(" "+percent+"%");
  223.                            dldisplaystate=5;
  224.                         } else if (percent>59 && dldisplaystate==5) {
  225.                            Console.Write("\r");
  226.                            Console.Write(" "+percent+"%");
  227.                            dldisplaystate=6;
  228.                         } else if (percent>69 && dldisplaystate==6) {
  229.                            Console.Write("\r");
  230.                            Console.Write(" "+percent+"%");
  231.                            dldisplaystate=7;
  232.                         } else if (percent>79 && dldisplaystate==7) {
  233.                            Console.Write("\r");
  234.                            Console.Write(" "+percent+"%");
  235.                            dldisplaystate=8;
  236.                         } else if (percent>89 && dldisplaystate==8) {
  237.                            Console.Write("\r");
  238.                            Console.Write(" "+percent+"%");
  239.                            dldisplaystate=9;
  240.                         } else if (percent>99 && dldisplaystate==9) {
  241.                            Console.Write("\r");
  242.                            Console.Write(" "+percent+"%");
  243.                            dldisplaystate=10;
  244.                         }
  245.                         Console.Write(".");
  246.  
  247.                         // Send program data.
  248.                         byte datalength = 2;
  249.                         for (ulong i = 0; i < 6; i++) {
  250.                             // Populate data.
  251.                             data[i+2] = hf.getByte(currentAddress + i + byteSent);
  252.                             if (currentAddress + i + byteSent > hf.getAddrUpper()) {
  253.                                 break;  //then done
  254.                             }
  255.                             datalength++;
  256.                         }
  257.                         data[0] = (byte)(byteSent & 0x00FF);
  258.                         data[1] = (byte)((byteSent & 0xFF00) >> 8);
  259.  
  260.                         outCm = cpn.getPgmDataPacket(data, datalength);
  261.                         dc.sendCanPacket(outCm);
  262.                        
  263.                         t = Environment.TickCount;
  264.                         t2 = Environment.TickCount;
  265.                         byteSent += 6;
  266.                         pgs = dState.WAIT_ACK_DATA;
  267.                         break;
  268.                        
  269.                        
  270.                     case dState.WAIT_ACK_DATA:
  271.                         // Wait for pgm ack.
  272.                         if ((Environment.TickCount - t) > TIMEOUT_MS) {
  273.                             // Woops, error.
  274.                             Console.WriteLine("Timeout while waiting for data ack.");
  275.                             errorOccured = true;
  276.                             pgs = dState.SEND_RESET;
  277.                         }
  278.                         else if ((Environment.TickCount - t2) > TIMEOUT_SHORT_MS) {
  279.                             // Woops, error.
  280. //disable                           Console.Write(":");
  281.                             byteSent -= 6;
  282.                             pgs = dState.SEND_PGM_DATA;
  283.                             break;
  284.                         }
  285.                         //Thread.Sleep(1);
  286.                         // If received ack.
  287.                         hasMessage = dc.getData(out cm);
  288.                         if (hasMessage) {
  289.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  290.                             if (cpnin.isNMTPacket()) {
  291.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  292.                                 // If no error
  293.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  294.                                     //currentAddress += 2;
  295.                                     // Check if end.
  296.                                     if (currentAddress + byteSent > hf.getAddrUpper()) {
  297.                                         // Yes, we are done, send done.
  298.                                         pgs = dState.SEND_DONE;
  299.                                     }
  300.                                     else {
  301.                                         // More to write.
  302.                                         //byteSent = 0;
  303.                                         pgs = dState.SEND_PGM_DATA;
  304.                                     }
  305.                                 }
  306.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK ) {
  307.                                     // else ..
  308.                                     Console.WriteLine("Nack on CAN_NMT_PGM_DATA.");
  309.                                     errorOccured = true;
  310.                                     pgs = dState.SEND_RESET;
  311.                                 }
  312.                             }
  313.                         }
  314.                         break;
  315.                        
  316.                     case dState.SEND_DONE:
  317.                        Console.Write("\r");
  318.                        Console.Write("100%");
  319.                         // Send done
  320.                         outCm = cpn.getPgmEndPacket();
  321.                         dc.sendCanPacket(outCm);
  322.  
  323.                         t = Environment.TickCount;
  324.                         t2 = Environment.TickCount;
  325.                         pgs = dState.WAIT_DONE;
  326.                         break;
  327.                        
  328.                        
  329.                     case dState.WAIT_DONE:
  330.                         // Check for timeout, resend done packet in that case..
  331.                         if ((Environment.TickCount - t) > TIMEOUT_MS) {
  332.                             Console.WriteLine("Timeout while waiting for end prg ack.");
  333.                             errorOccured = true;
  334.                             pgs = dState.SEND_RESET;
  335.                         }
  336.                         //Thread.Sleep(1);
  337.                        
  338.                         hasMessage = dc.getData(out cm);
  339.                         if (hasMessage) {
  340.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  341.                             if (cpnin.isNMTPacket()) {
  342.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  343.                                 // If no error
  344.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  345.                                     Console.WriteLine("");
  346.                                     //
  347.                                     int crc = calcCRC(hf);
  348.                                
  349.                                     if (cm.getDataLength() == 2) {
  350.                                         byte[] cmdata = cm.getData();
  351.                                         if ((cmdata[0] == (crc & 0xFF)) && (cmdata[1] == (crc>>8))) {
  352.                                             if (!isBiosUpdate) {
  353.                                                 Console.WriteLine("Done, successfully programmed application.");
  354.                                                 pgs = dState.SEND_RESET;
  355.                                             } else {
  356.                                                 Console.WriteLine("Done, successfully programmed bios to application space.");
  357.                                                 pgs = dState.SEND_BIOS_UPDATE;
  358.                                             }
  359.                                         } else {
  360.                                             string nodecrc = String.Format("{0:x4}", (int)cmdata[0] + (int)(cmdata[1]<<8));
  361.                                             nodecrc = "0x"+nodecrc;
  362.                                             string realcrc = String.Format("{0:x4}", (int)(crc & 0xFF) + (int)(crc & 0xFF00));
  363.                                             realcrc = "0x"+realcrc;
  364.                                             Console.WriteLine("CRC failed. Node sent CRC "+nodecrc+" but should be "+realcrc+".");
  365.                                             errorOccured = true;
  366.                                             pgs = dState.SEND_RESET;
  367.                                         }
  368.                                        
  369.                                         byteSent = 0;
  370.                                     }
  371.                                     //Console.WriteLine("crc: " + crc + " " + (crc>>8) + " " + (crc & 0xFF));
  372.                                     //Console.WriteLine("ACKpkg with CRC: " + cm.ToString());
  373.                                     //
  374.                                 }
  375.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK) {
  376.                                     // else resend addr..
  377.                                     Console.WriteLine("Nack on CAN_NMT_PGM_END.");
  378.                                     errorOccured = true;
  379.                                     pgs = dState.SEND_RESET;
  380.                                 }
  381.                             }
  382.                         }
  383.                         break;
  384.                        
  385.                     case dState.SEND_BIOS_UPDATE:
  386.                         data[0] = (byte)(0 & 0x00FF);
  387.                         data[1] = (byte)((0 & 0xFF00) >> 8);
  388.                         data[2] = (byte)(dlOffset & 0x00FF);
  389.                         data[3] = (byte)((dlOffset & 0xFF00) >> 8);
  390.                         data[4] = (byte)((hf.getAddrUpper()-hf.getAddrLower()+1) & 0x00FF);
  391.                         data[5] = (byte)(((hf.getAddrUpper()-hf.getAddrLower()+1) & 0xFF00) >> 8);
  392.                        
  393.                         outCm = cpn.getPgmCopyPacket(data);
  394.                         Console.WriteLine("Now say a prayer, moving bios");
  395.                         dc.sendCanPacket(outCm);
  396.                         t = Environment.TickCount;
  397.                         t2 = Environment.TickCount;
  398.                         pgs = dState.WAIT_BOOT;
  399.                         //pgs = dState.DONE;
  400.                         break;
  401.  
  402.                     case dState.WAIT_BOOT:
  403.                         // Wait for node reset answer (boot msg).
  404.                         if ((Environment.TickCount - t) > 3*TIMEOUT_MS) {
  405.                             // Woops, error.
  406.                             Console.WriteLine("Timeout while waiting for node to boot.");
  407.                             errorOccured = true;
  408.                             pgs = dState.SEND_DONE;
  409.                         }
  410.                         //Thread.Sleep(1);
  411.                         // If received boot msg.
  412.                         hasMessage = dc.getData(out cm);
  413.                         if (hasMessage) {
  414.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  415.                             if (cpnin.isNMTPacket()) {
  416.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  417.                                 // If no error
  418.                                 if (cpnin.getType() == CAN_NMT_BIOS_START) {
  419.                                     pgs = dState.SEND_EMPTY_START;
  420.                                 }
  421.                                 else {
  422.                                     // else ..
  423.                                 }
  424.                             }
  425.                         }
  426.                         break;
  427.                        
  428.                     case dState.SEND_EMPTY_START:
  429.                         // Send boot start packet to target.
  430.                         // and wait for ack.
  431.                        
  432.                         //data[RID_INDEX] = TARGET_ID;
  433.                         data[ADDR0_INDEX] = (byte)((0) & 0x0000FF);
  434.                         data[ADDR1_INDEX] = (byte)(((0) & 0x00FF00) >> 8);
  435.                         data[ADDR2_INDEX] = (byte)(((0) & 0xFF0000) >> 16);
  436.                         data[ADDR3_INDEX] = 0;
  437.                         if (HWID_INUSE) {
  438.                             data[HWID0_INDEX] = (byte)((hwid) & 0xFF);
  439.                             data[HWID1_INDEX] = (byte)((hwid>>8) & 0xFF);
  440.                             data[HWID2_INDEX] = (byte)((hwid>>16) & 0xFF);
  441.                             data[HWID3_INDEX] = (byte)((hwid>>24) & 0xFF);
  442.                         }
  443.                         //outCm = new CanPacket(CAN_NMT, CAN_NMT_PGM_START, MY_ID, receiveID, 4, data);
  444.                         outCm = cpn.getPgmStartPacket(data);
  445.                         dc.sendCanPacket(outCm);
  446.                         t = Environment.TickCount;
  447.                         t2 = Environment.TickCount;
  448.                         pgs = dState.WAIT_ACK_PRG_EMPTY;
  449.                         break;
  450.                    
  451.                    
  452.                     case dState.WAIT_ACK_PRG_EMPTY:
  453.                         // Check for timeout, resend start packet in that case..
  454.                         if ((Environment.TickCount - t) > 3*TIMEOUT_MS) {
  455.                             Console.WriteLine("Timeout while waiting for start prg ack during empty-first-block-cycle.");
  456.                             errorOccured = true;
  457.                             pgs = dState.SEND_RESET;
  458.                         }
  459.                         //Thread.Sleep(1);
  460.                         // If received ack.
  461.                         hasMessage = dc.getData(out cm);
  462.                         if (hasMessage) {
  463.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  464.                             if (cpnin.isNMTPacket()) {
  465.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  466.                                 // If no error
  467.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  468.                                     // Start sending program data..
  469.                                     byteSent = 0;
  470.                                     pgs = dState.SEND_EMPTY_DATA;
  471.                                 }
  472.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK ) {
  473.                                     // else ..
  474.                                     Console.WriteLine("Nack on CAN_NMT_PGM_START.");
  475.                                     errorOccured = true;
  476.                                     pgs = dState.SEND_RESET;
  477.                                 }
  478.                             }
  479.                         }
  480.                         break;
  481.                        
  482.                     case dState.SEND_EMPTY_DATA:
  483.                         // Send program data.
  484.                         data[0] = 0;
  485.                         data[1] = 0;
  486.                         data[2] = 0xff;
  487.                         data[3] = 0xff;
  488.  
  489.                         outCm = cpn.getPgmDataPacket(data, 4);
  490.                         dc.sendCanPacket(outCm);
  491.                        
  492.                         t = Environment.TickCount;
  493.                         t2 = Environment.TickCount;
  494.                         byteSent += 6;
  495.                         pgs = dState.WAIT_ACK_EMPTY_DATA;
  496.                         break;
  497.                        
  498.                        
  499.                     case dState.WAIT_ACK_EMPTY_DATA:
  500.                         // Wait for pgm ack.
  501.                         if ((Environment.TickCount - t) > 2*TIMEOUT_MS) {
  502.                             // Woops, error.
  503.                             Console.WriteLine("Timeout while waiting for data ack.");
  504.                             errorOccured = true;
  505.                             pgs = dState.SEND_RESET;
  506.                         }
  507.                         //Thread.Sleep(1);
  508.                         // If received ack.
  509.                         hasMessage = dc.getData(out cm);
  510.                         if (hasMessage) {
  511.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  512.                             if (cpnin.isNMTPacket()) {
  513.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  514.                                 // If no error
  515.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  516.                                     pgs = dState.SEND_DONE_EMPTY;
  517.                                 }
  518.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK ) {
  519.                                     // else ..
  520.                                     Console.WriteLine("Nack on CAN_NMT_PGM_DATA.");
  521.                                     errorOccured = true;
  522.                                     pgs = dState.SEND_RESET;
  523.                                 }
  524.                             }
  525.                         }
  526.                         break;
  527.                        
  528.                     case dState.SEND_DONE_EMPTY:
  529.                         // Send done
  530.                         outCm = cpn.getPgmEndPacket();
  531.                         dc.sendCanPacket(outCm);
  532.  
  533.                         t = Environment.TickCount;
  534.                         t2 = Environment.TickCount;
  535.                         pgs = dState.WAIT_DONE_EMPTY;
  536.                         break;
  537.                        
  538.                        
  539.                     case dState.WAIT_DONE_EMPTY:
  540.                         // Check for timeout, resend done packet in that case..
  541.                         if ((Environment.TickCount - t) > TIMEOUT_MS) {
  542.                             Console.WriteLine("Timeout while waiting for end prg ack.");
  543.                             errorOccured = true;
  544.                             pgs = dState.SEND_RESET;
  545.                         }
  546.                         //Thread.Sleep(1);
  547.                        
  548.                         hasMessage = dc.getData(out cm);
  549.                         if (hasMessage) {
  550.                             CanNMT cpnin = new CanNMT(cm, HWID_INUSE);
  551.                             if (cpnin.isNMTPacket()) {
  552.                             //if (cpnin.isNMTPacket() && (cpnin.getSender() == receiveID)) {
  553.                                 // If no error
  554.                                 if (cpnin.getType() == CAN_NMT_PGM_ACK) {
  555.                                     Console.WriteLine("");
  556.                                     //
  557.                                     Console.WriteLine("Done, successfully cleaned application flash.");
  558.                                     pgs = dState.SEND_RESET;
  559.                                 }
  560.                                 else if (cpnin.getType() == CAN_NMT_PGM_NACK) {
  561.                                     // else resend addr..
  562.                                     Console.WriteLine("Nack on CAN_NMT_PGM_END.");
  563.                                     errorOccured = true;
  564.                                     pgs = dState.SEND_RESET;
  565.                                 }
  566.                             }
  567.                         }
  568.                         break;                     
  569.                     case dState.SEND_RESET:
  570.                         // Send reset
  571.                         cpn.doReset(dc, receiveID, hwid);
  572.                         t = Environment.TickCount;
  573.                         t2 = Environment.TickCount;
  574.                         pgs = dState.DONE;
  575.                         break;
  576.                        
  577.                        
  578.                     case dState.DONE:
  579.                         done = true;
  580.                         //down.Abort();
  581.                         if (!errorOccured) {
  582.                             long tsecs = ((Environment.TickCount - timeStart) / 1000);
  583.                             double bitRate = hf.getLength() / ((double)(Environment.TickCount - timeStart) / 1000.0);
  584.                            
  585.                             if (tsecs <= 0) tsecs = 1;
  586.                             long mins = tsecs / 60;
  587.                             long secs = tsecs % 60;
  588.                             string pad = "";
  589.                             if (secs < 10) {
  590.                                 pad = "0";
  591.                             }
  592.                             Console.WriteLine("Time spent: " + mins + ":" + pad + secs + ", " + Math.Round(bitRate, 2) + " bytes/s");
  593.                         }
  594.                         //Console.Write("> ");
  595.                         break;
  596.                 }
  597.             }
  598.            
  599.         } catch(Exception) {
  600.             Console.WriteLine("Exception occured");
  601.             //Console.WriteLine(e);
  602.             //skriva ut antal bytes skrivna vore bra här, kanske nån annan form av hjälp för debug, något gick snett liksom
  603.            
  604.         }
  605.        
  606.         return !errorOccured;
  607.     }
  608. }
  609.