Subversion Repositories HomeAutomation

Rev

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