}//ds30L_Downloading()	

        
        //---------------------------------------------------------------------
        // Constructor
        //---------------------------------------------------------------------
        public void DoMagic( string[] pstrArgs, ref bool pbResult ) 
        {
            pbResult = false;            

            
            //-----------------------------------------------------------------
            // If no argumentsa are specified, display help
            //-----------------------------------------------------------------
            if ( pstrArgs.Length == 0 ) {
                PrintHelp();
                return;
            }


            //-----------------------------------------------------------------
            // Validate arguments
            //-----------------------------------------------------------------
            bool bResult = false;
            clsParseSettings objParseSettings = new clsParseSettings();
            clsDownloadSettings objDownloadSettings = new clsDownloadSettings();
            ValidateParseArgs( pstrArgs, objParseSettings, objDownloadSettings, ref bResult );
            if ( bResult == false ) {
                return;
            }


            //-----------------------------------------------------------------
            // Nothing to do?
            //-----------------------------------------------------------------
			if ( objDownloadSettings.writeProgram == false && objDownloadSettings.writeEEPROM == false && objDownloadSettings.writeConfigs == false  ) {
				Console.WriteLine( "Nothing to do." );
				return;
			}


            //-----------------------------------------------------------------
            // Parse
            //-----------------------------------------------------------------
            objParseSettings.device = objDevice;
            DoParse( objParseSettings, objDownloadSettings );

            
            //-----------------------------------------------------------------
            // Create port
            //-----------------------------------------------------------------
            objPort = new clsSerialPort();
            objPort.Setup( strPort, iBaudrate );


            //-----------------------------------------------------------------
            // Increase process priority if polltime is low
            //-----------------------------------------------------------------
            if ( objDownloadSettings.polltime < 100 ) {
                try {
                    System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.AboveNormal;
                } catch {
                    clsDebugTextbox.OutputInfo( "Setting proccess priority failed." );
                }
            }


            //-----------------------------------------------------------------
            // Print settings
            //-----------------------------------------------------------------
            Console.WriteLine( "" );
            Console.WriteLine( "" );
            Console.WriteLine( "{0,-10} {1, -8}", "File:", strFile );
            Console.WriteLine( "{0,-10} {1, -8}", "Port:", strPort );
            Console.WriteLine( "{0,-10} {1, -8}", "Baudrate:", iBaudrate.ToString() );
            Console.WriteLine( "{0,-10} {1, -8}", "Device:", objDevice.name );


            //-----------------------------------------------------------------
            // 
            //-----------------------------------------------------------------            
            Console.WriteLine( "" );
            Console.WriteLine( "" );
            if ( bNonInteractive == false ) {
                Console.WriteLine( "Press any key to begin download" );
                Console.WriteLine( "" );
                Console.ReadKey();
            }
            

            //-----------------------------------------------------------------
            // Download
            //-----------------------------------------------------------------
            bool bDownloadResult = false;
            int iStartTime = Environment.TickCount;
            clsds30Loader.Download( objDevice, objPort, objHex, objDownloadSettings, 0, ref bDownloadResult );
            int iEndTime = Environment.TickCount;


            //-----------------------------------------------------------------
            // Restore process priority
            //-----------------------------------------------------------------
            if ( objDownloadSettings.polltime < 100 ) {
                try {
                    System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal;
                } catch {
                    clsDebugTextbox.OutputInfo( "Setting proccess priority failed." );
                }
            }

            //-----------------------------------------------------------------
            // Download finished
            //-----------------------------------------------------------------            
            objPort.Close();
            if ( clsds30Loader.debugMode ) {
                clsDebugTextbox.OutputInfo( "Elapsed time: " + String.Format( "{0:0.#}", Convert.ToSingle(iEndTime - iStartTime) / 1000.0 ) + " seconds", 1 );			
            } 
            pbResult = bDownloadResult;
        }// DoMagic()
Exemple #2
0
        }//ds30L_Downloading()

        //---------------------------------------------------------------------
        // Constructor
        //---------------------------------------------------------------------
        public void DoMagic(string[] pstrArgs, ref bool pbResult)
        {
            pbResult = false;


            //-----------------------------------------------------------------
            // If no argumentsa are specified, display help
            //-----------------------------------------------------------------
            if (pstrArgs.Length == 0)
            {
                PrintHelp();
                return;
            }


            //-----------------------------------------------------------------
            // Validate arguments
            //-----------------------------------------------------------------
            bool                bResult             = false;
            clsParseSettings    objParseSettings    = new clsParseSettings();
            clsDownloadSettings objDownloadSettings = new clsDownloadSettings();

            ValidateParseArgs(pstrArgs, objParseSettings, objDownloadSettings, ref bResult);
            if (bResult == false)
            {
                return;
            }


            //-----------------------------------------------------------------
            // Nothing to do?
            //-----------------------------------------------------------------
            if (objDownloadSettings.writeProgram == false && objDownloadSettings.writeEEPROM == false && objDownloadSettings.writeConfigs == false)
            {
                Console.WriteLine("Nothing to do.");
                return;
            }


            //-----------------------------------------------------------------
            // Parse
            //-----------------------------------------------------------------
            objParseSettings.device = objDevice;
            DoParse(objParseSettings, objDownloadSettings);


            //-----------------------------------------------------------------
            // Create port
            //-----------------------------------------------------------------
            objPort = new clsSerialPort();
            objPort.Setup(strPort, iBaudrate);


            //-----------------------------------------------------------------
            // Increase process priority if polltime is low
            //-----------------------------------------------------------------
            if (objDownloadSettings.polltime < 100)
            {
                try {
                    System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.AboveNormal;
                } catch {
                    clsDebugTextbox.OutputInfo("Setting proccess priority failed.");
                }
            }


            //-----------------------------------------------------------------
            // Print settings
            //-----------------------------------------------------------------
            Console.WriteLine("");
            Console.WriteLine("");
            Console.WriteLine("{0,-10} {1, -8}", "File:", strFile);
            Console.WriteLine("{0,-10} {1, -8}", "Port:", strPort);
            Console.WriteLine("{0,-10} {1, -8}", "Baudrate:", iBaudrate.ToString());
            Console.WriteLine("{0,-10} {1, -8}", "Device:", objDevice.name);


            //-----------------------------------------------------------------
            //
            //-----------------------------------------------------------------
            Console.WriteLine("");
            Console.WriteLine("");
            if (bNonInteractive == false)
            {
                Console.WriteLine("Press any key to begin download");
                Console.WriteLine("");
                Console.ReadKey();
            }


            //-----------------------------------------------------------------
            // Download
            //-----------------------------------------------------------------
            bool bDownloadResult = false;
            int  iStartTime      = Environment.TickCount;

            clsds30Loader.Download(objDevice, objPort, objHex, objDownloadSettings, 0, ref bDownloadResult);
            int iEndTime = Environment.TickCount;


            //-----------------------------------------------------------------
            // Restore process priority
            //-----------------------------------------------------------------
            if (objDownloadSettings.polltime < 100)
            {
                try {
                    System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal;
                } catch {
                    clsDebugTextbox.OutputInfo("Setting proccess priority failed.");
                }
            }

            //-----------------------------------------------------------------
            // Download finished
            //-----------------------------------------------------------------
            objPort.Close();
            if (clsds30Loader.debugMode)
            {
                clsDebugTextbox.OutputInfo("Elapsed time: " + String.Format("{0:0.#}", Convert.ToSingle(iEndTime - iStartTime) / 1000.0) + " seconds", 1);
            }
            pbResult = bDownloadResult;
        }// DoMagic()
        //---------------------------------------------------------------------
        // ProcessWriteResponse()
        //---------------------------------------------------------------------
        private static void ProcessWriteResponse( clsSerialPort pobjPort, ref int piRetries, int piTabLevel, string pstrWriteType, ref bool pbRetry, ref bool pbResult )
        {
            int iResponse = -1;
            pbResult = false;

            // Get response
            bool bGetResponseResult = false;
            iResponse = GetResponse( pobjPort, ref bGetResponseResult );
            if ( bGetResponseResult == false ) {
                return;
            }

            // Check response
            if ( iResponse != c*K ) {
                if ( ++piRetries == 3 ) {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "download failed", -1) );
                    return;
                } else {
                    if ( iResponse == cChecksumErr ) {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "checksum error," + piRetries.ToString() + " try", -1) );
                        pbRetry = true;
                    } else if ( iResponse == cVerifyErr ) {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "verify error," + piRetries.ToString() + " try", -1) );
                        pbRetry = true;
                    } else {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "unknown response," + piRetries.ToString() + " try", -1) );
                        pbRetry = true;
                    }
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing flash...", piTabLevel) );
                }
            } else {
                pbRetry = false;
            }

            pbResult = true;
        }
        //---------------------------------------------------------------------
        // ResetDevice()
        //---------------------------------------------------------------------
        private static void ResetDevice( clsSerialPort pobjPort, clsDownloadSettings pobjSettings, int iTabLevel, ref bool pbResult )
        {
            pbResult = false;

            //--------------------------------------------------------------------------
            // Reset - command
            //--------------------------------------------------------------------------
            if ( pobjSettings.resetCommand == true ) {
                // Inform user
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Sending reset command", iTabLevel) );

                // Parse resetcommand
                bool bSplitResult = false;
                byte[] bBytes = pobjPort.SplitHexStringToBytes( pobjSettings.resetCommandSequence, ref bSplitResult );
                if ( bSplitResult == false ) {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Couldn't parse reset command sequence", iTabLevel) );
                    return;
                }
                /*string[] strBytes = pobjSettings.resetCommandSequence.Split( ';' );
                byte[] bBytes = new byte[ strBytes.Length ];
                int iIndex = 0;
                foreach ( string strByte in strBytes ) {
                    bBytes[iIndex] = byte.Parse( strByte, System.Globalization.NumberStyles.HexNumber );
                    ++iIndex;
                }*/

                // Open port
                int iOldBaudrate = pobjPort.baudrate;
                pobjPort.baudrate = pobjSettings.resetBaudrate;
                bool bOpenPortResult = false;
                PortOpen( pobjPort, pobjSettings, ref bOpenPortResult );

                // Send reset command and close port
                pobjPort.SendBytes( ref bBytes, bBytes.Length );
                while ( pobjPort.outBufferCount > 0 );
                pobjPort.Close();

                // Restore baudrate
                pobjPort.baudrate = iOldBaudrate;

                SleepResponsive( pobjSettings.resetTime );

            //--------------------------------------------------------------------------
            // Reset - dtr
            //--------------------------------------------------------------------------
            } else if ( pobjSettings.resetDtr == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Resetting by dtr", iTabLevel) );
                pobjPort.dtrEnable = true;
                SleepResponsive( pobjSettings.resetTime );
                pobjPort.dtrEnable = false;

            //--------------------------------------------------------------------------
            // Reset - rts
            //--------------------------------------------------------------------------
            } else if ( pobjSettings.resetRts == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Resetting by rts", iTabLevel) );
                pobjPort.rtsEnable = true;
                SleepResponsive( pobjSettings.resetTime );
                pobjPort.rtsEnable = false;
            }

            pbResult = true;
        }
 //---------------------------------------------------------------------
 // PortClose()
 //---------------------------------------------------------------------
 private static void PortClose( clsSerialPort pobjPort )
 {
     pobjPort.Close();
 }
        //---------------------------------------------------------------------
        // PortOpen()
        //---------------------------------------------------------------------
        private static void PortOpen( clsSerialPort pobjPort, clsDownloadSettings pobjSettings, ref bool pbResult )
        {
            pbResult = false;

            // Activate device when we open port
            try {
                pobjPort.objPort.DtrEnable = pobjSettings.activateDTR;
                pobjPort.objPort.RtsEnable = pobjSettings.activateRTS;
            } catch {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "failed setting dtr & rts", -1) );
            }

            // Allready open?
            if ( pobjPort.isOpen == true ) {
                pbResult = true;
                return;
            }

            try {
                pobjPort.Open();
            } catch {
            }

            if ( pobjPort.isOpen == false ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "failed to open port", -1) );
            }

            pbResult = pobjPort.isOpen;
        }
        //---------------------------------------------------------------------
        // FindLoader()
        //---------------------------------------------------------------------
        public static void FindLoader( clsDevice pobjDevice, clsSerialPort pobjPort , clsDownloadSettings pobjSettings, int iTabLevel, ref bool pbResult )
        {
            int iDeviceIdFound = -1;
            bool bGetResponseResult = false;
            bool bPortWasOpened = false;

            pbResult = false;

            //-----------------------------------------------------------------
            // Test-mode
            //-----------------------------------------------------------------
            if ( bTestMode == true ) {
                iFWVerMaj = iTestVerMaj;
                iFWVerMin = iTestVerMin;
                iFWVerRev = iTestVerRev;
                iDeviceIdFound = iTestDeviceID;
                //return true;

            //-----------------------------------------------------------------
            // Real-mode
            //-----------------------------------------------------------------
            } else {

                int iVerMaj = 0, iVerMinRev = 0;
                int iTimeIdReceived = 0;

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Searching for bl ", iTabLevel) );

                //--------------------------------------------------------------------------
                // Open port if not open
                //--------------------------------------------------------------------------
                if ( pobjPort.isOpen == false ) {
                    pobjPort.Open();
                    if ( pobjPort.isOpen == false ) {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Failed to open port", iTabLevel) );
                        return;
                    }
                    bPortWasOpened = true;
                }

                // Empty buffers prior to hello command incase there's some crap
                pobjPort.EmptyBuffers( true, false );

                //--------------------------------------------------------------------------
                // Send hello to bootloader
                //--------------------------------------------------------------------------
                bool bDeviceIDReceived = false;
                {
                    int iLastSend = Environment.TickCount - pobjSettings.polltime;
                    int iLastPoll = Environment.TickCount - pobjSettings.polltime;
                    int iStartTime = Environment.TickCount;

                    bool bByteReceived = false;

                    bool bTimedOut = false;

                    do {
                        // Check first byte, discard if null
                        if ( Environment.TickCount - iLastPoll >= pobjSettings.polltime/10) {
                            iLastPoll = Environment.TickCount;

                            if ( bByteReceived == false && pobjPort.inBufferCount > 0 ) {
                                bByteReceived = true;
                                iDeviceIdFound = GetResponse( pobjPort, ref bGetResponseResult );
                                if ( bGetResponseResult == false ) {
                                    if ( bPortWasOpened == true ) pobjPort.Close();
                                    return;
                                }
                                if ( iDeviceIdFound == 0 ) {
                                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "(discarded null byte)", -1) );
                                } else {
                                    bDeviceIDReceived = true;
                                    iTimeIdReceived = Environment.TickCount;
                                    break;
                                }

                            }
                        }

                        // Send hello
                       if ( Environment.TickCount - iLastSend >= pobjSettings.polltime ) {
                            iLastSend = Environment.TickCount;
                            pobjPort.SendByte( cHello );
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, ". ", -1) );
                        }

                        // Check for timeout
                        bTimedOut = ( Environment.TickCount - iStartTime >= pobjSettings.timeout );

                        // Handle message queue
                        Application.DoEvents();
                    } while (
                        bAbort == false &&
                        bTimedOut == false &&
                        (bByteReceived == false || pobjPort.inBufferCount == 0)
                    );

                    if ( bAbort == true  ) {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted", -1) );
                        bAbort = false;
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    } else if ( bTimedOut == true ) {
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "timed out", -1) );
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    }
                }

                //--------------------------------------------------------------------------
                // Read device id
                //--------------------------------------------------------------------------
                if ( bDeviceIDReceived == false ) {
                    iDeviceIdFound = GetResponse( pobjPort, ref bGetResponseResult );
                    if ( bGetResponseResult == false ) {
                        iTimeIdReceived = Environment.TickCount;
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    }
                }

                //--------------------------------------------------------------------------
                // Delay to receive firmware version if any
                //--------------------------------------------------------------------------
                int iTime = 1 + 30000 / pobjPort.baudrate;
                while ( Environment.TickCount - iTimeIdReceived < iTime && pobjPort.inBufferCount < 3 ) {
                }

                //--------------------------------------------------------------------------
                // Firmware doesn´t send version, assume 0.9.4
                //--------------------------------------------------------------------------
                if ( pobjPort.inBufferCount == 1 ) {
                        iFWVerMaj = 0;
                        iFWVerMin = 9;
                        iFWVerRev = 4;

                //--------------------------------------------------------------------------
                // Firmware that sends major and minor
                //--------------------------------------------------------------------------
                } else if ( pobjPort.inBufferCount == 2 ) {
                    iVerMaj = GetResponse( pobjPort, ref bGetResponseResult );
                    if ( bGetResponseResult == false ) {
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    }
                    iFWVerMaj = ( (iVerMaj & 0x70) >> 4 );
                    iFWVerMin = ( iVerMaj & 0xF );
                    iFWVerRev = 0;

                //--------------------------------------------------------------------------
                // Firmware that sends major, minor and revision
                //--------------------------------------------------------------------------
                } else if ( pobjPort.inBufferCount == 3 ) {
                    iVerMaj = GetResponse( pobjPort, ref bGetResponseResult );
                    if ( bGetResponseResult == false ) {
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    }
                    iVerMinRev = GetResponse( pobjPort, ref bGetResponseResult );
                    if ( bGetResponseResult == false ) {
                        if ( bPortWasOpened == true ) pobjPort.Close();
                        return;
                    }

                    iFWVerMaj = ( iVerMaj & 0x7F );
                    iFWVerMin = ( (iVerMinRev & 0xF0) >> 4 );
                    iFWVerRev = ( iVerMinRev & 0xF );
                }

                //--------------------------------------------------------------------------
                // PIC18 indicated by msb in fw ver major
                //--------------------------------------------------------------------------
                if ( (iVerMaj & 0x80) > 0 ) {
                    iDeviceIdFound += 300;
                }
            }//Test-/real-mode

            //--------------------------------------------------------------------------
            // Find device from device id
            //--------------------------------------------------------------------------
            clsDevice objFoundDevice = clsDevices.DeviceGet( iDeviceIdFound );

            //--------------------------------------------------------------------------
            // Invalid ID returned
            //--------------------------------------------------------------------------
            if ( objFoundDevice == null ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Found unknown device id(" + iDeviceIdFound.ToString() + ") fw ver. " + iFWVerMaj.ToString() + "." + iFWVerMin.ToString() + "." + iFWVerRev.ToString(), iTabLevel) );
                if ( bPortWasOpened == true ) pobjPort.Close();
                return;
            }

            //--------------------------------------------------------------------------
            // Bootloader found
            //--------------------------------------------------------------------------
            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "Found " + objFoundDevice.name + " fw ver. " + iFWVerMaj.ToString() + "." + iFWVerMin.ToString() + "." + iFWVerRev.ToString(), iTabLevel) );

            //--------------------------------------------------------------------------
            // Different device found from choosen
            //--------------------------------------------------------------------------
            if ( objFoundDevice.id != pobjDevice.id ) {
                OnDownloading(new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Wrong pic detected(" + objFoundDevice.id.ToString() + ")/selected(" + pobjDevice.id.ToString() + "), aborting", iTabLevel));
                if ( bPortWasOpened == true ) pobjPort.Close();
                return;
            }

            pbResult = true;

            // Close port if it was openeed
            if ( bPortWasOpened == true ) {
                pobjPort.Close();
            }
        }
        //---------------------------------------------------------------------
        // GetResponse()
        //---------------------------------------------------------------------
        private static int GetResponse( clsSerialPort pobjPort, ref bool pbResult )
        {
            int iResponse = -1;
            pbResult = false;

            // Test-mode
            if ( bTestMode == true ) {
                pbResult = true;
                return c*K;
            }

            //
            int iStartTime = System.Environment.TickCount;
            while ( pobjPort.inBufferCount < 1 && System.Environment.TickCount - iStartTime < 2000 && bAbort == false ) {
                Application.DoEvents();
            }

            // Abort
            if ( bAbort == true ) {
                return -1;
            }

            // Timeout
            if ( pobjPort.inBufferCount < 1 ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "response timed out", -1) );
                return -1;
            }

            pobjPort.ReadByte( ref iResponse );
            pbResult = true;
            return iResponse;
        }
        //---------------------------------------------------------------------
        // WriteFlash33_1_0_0()
        //---------------------------------------------------------------------
        private static bool WriteFlash33_1_0_0(clsSerialPort pobjPort, clsDevice pobjDevice, clsHex33FJ pobjHex, bool pbWriteProgram, bool pbWriteConfigs, int iTabLevel)
        {
            //--------------------------------------------------------------------------
            // Variables
            //--------------------------------------------------------------------------
            int iChecksum;
            int iSum;
            int iAddrP;
            int iRetries;
            byte[] bBuffer = new byte[256];
            int iBufferIndx;
            byte bAddrU, bAddrH, bAddrL, bSize, bProg;
            bool bRetry = false;
            int iByteToWrite = pobjHex.BytesToWrite( pobjDevice, pbWriteProgram, false, pbWriteConfigs );
            int iBytesWritten = 0;
            bool bProcessWriteResponseResult = false;

            //--------------------------------------------------------------------------
            // Write flash
            //--------------------------------------------------------------------------
            int iRow;

            if ( pbWriteProgram == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing flash...", iTabLevel) );

                //-------------------------------------------------------------
                // Iterate pages
                //-------------------------------------------------------------
                for ( int iPage = 0; iPage < clsHex33FJ.iProgPageUsedBufferSize; iPage++ ) {
                    if ( pobjHex.bProgPageUsed[iPage] == true ) {
                        iRetries = 0;
                        do {
                            if ( clsds30Loader.debugMode ) {
                                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Erasing page " + iPage.ToString(), iTabLevel) );
                            }

                            //---------------------------------------------------------
                            // Erase page
                            //---------------------------------------------------------
                            iSum = 0;
                            iBufferIndx = 0;

                            // Calculate
                            iAddrP = iPage * pobjDevice.pageSizeR * pobjDevice.rowsizeW * 2;	//24-bit address in memory to write to
                            bAddrU = Convert.ToByte((iAddrP & 0xff0000) >> 16);				//address upper byte
                            bAddrH = Convert.ToByte((iAddrP & 0x00ff00) >> 8);				//address high byte
                            bAddrL = Convert.ToByte((iAddrP & 0x0000ff) >> 0);				//address low byte
                            bSize = Convert.ToByte(1/*checksum*/ );

                            //
                            bBuffer[iBufferIndx++] = bAddrU; iSum += bAddrU;
                            bBuffer[iBufferIndx++] = bAddrH; iSum += bAddrH;
                            bBuffer[iBufferIndx++] = bAddrL; iSum += bAddrL;
                            bBuffer[iBufferIndx++] = cCmdErasePage; iSum += cCmdErasePage;
                            bBuffer[iBufferIndx++] = bSize; iSum += bSize;

                            // Calculate checksum and add to buffer
                            iSum %= 256;
                            iChecksum = Convert.ToInt16((256 - iSum) % 256);
                            bBuffer[iBufferIndx++] = Convert.ToByte(iChecksum);

                            // Send address, command, packetsize & checksum
                            pobjPort.SendBytes(ref bBuffer, iBufferIndx);

                            // Get response, checksum ok
                            ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                            if ( bProcessWriteResponseResult == false ) {
                                return false;
                            }

                            //
                            Application.DoEvents();
                        } while (bRetry == true && bAbort == false);

                        //---------------------------------------------------------
                        // Iterate rows, write all rows in page even if not in hex-file
                        //---------------------------------------------------------
                        for ( iRow = iPage * pobjDevice.pageSizeR; iRow < iPage * pobjDevice.pageSizeR + pobjDevice.pageSizeR; iRow++ ) {
                            iRetries = 0;
                            do {
                                if ( clsds30Loader.debugMode ) {
                                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing row " + iRow.ToString(), iTabLevel) );
                                }

                                iBufferIndx = 0;
                                iSum = 0;

                                // Calculate
                                iAddrP = iRow * (pobjDevice.rowsizeW * 2);				//24-bit address in memory to write to
                                bAddrU = Convert.ToByte((iAddrP & 0xff0000) >> 16);	    //address upper byte
                                bAddrH = Convert.ToByte((iAddrP & 0x00ff00) >> 8);	    //address high byte
                                bAddrL = Convert.ToByte((iAddrP & 0x0000ff));			//address low byte
                                bSize = Convert.ToByte(pobjDevice.rowsizeW * 3 + 1/*checksum*/ );

                                //
                                bBuffer[iBufferIndx++] = bAddrU; iSum += bAddrU;
                                bBuffer[iBufferIndx++] = bAddrH; iSum += bAddrH;
                                bBuffer[iBufferIndx++] = bAddrL; iSum += bAddrL;
                                bBuffer[iBufferIndx++] = cCmdWriteRow; iSum += cCmdWriteRow;
                                bBuffer[iBufferIndx++] = bSize; iSum += bSize;

                                // Calculate startindex in hex-buffer
                                iAddrP = iRow * pobjDevice.rowsizeW * 3;

                                // Buffer row, upper-low-high, ordered in ParseHex()
                                for ( int iByte = 0; iByte < pobjDevice.rowsizeW * 3; iByte++ ) {
                                    bProg = Convert.ToByte( pobjHex.iProgMem[iAddrP + iByte] );
                                    bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;
                                }

                                // Calculate checksum and add to buffer
                                iSum %= 256;
                                iChecksum = Convert.ToInt16((256 - iSum) % 256);
                                bBuffer[iBufferIndx++] = Convert.ToByte(iChecksum);

                                // Send address, command, packetsize, row & checksum
                                pobjPort.SendBytes(ref bBuffer, iBufferIndx);

                                // Get response, checksum ok
                                ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                                if ( bProcessWriteResponseResult == false ) {
                                    return false;
                                }

                                //
                                Application.DoEvents();
                            } while ( bRetry == true && bAbort == false );

                            //
                            if (bAbort == true) {
                                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted by user", -1) );
                                return false;
                            }

                            //
                            iBytesWritten += pobjDevice.rowsizeW * 3;
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progress, "", (100 * iBytesWritten) / iByteToWrite ) );

                        }//for ( iRow = 0; iRow < iRowUsedBufferSize; iRow++ ) {

                    } //if ( bPageUsed[iIter] == true ) {

                }//for ( iPage = 0; iPage < iPageUsedBufferSize; iPage++ ) {

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            }//if ( pbWriteProgram == true ) {

            //--------------------------------------------------------------------------
            // Write Config Bits
            //--------------------------------------------------------------------------
            if ( pbWriteConfigs == true ) {
                int iConfig;
                int iByte;
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing configs...", iTabLevel) );
                iRetries = 0;

                for ( iConfig = 0; iConfig < clsHex33FJ.iConfigWordsUsedBufferSize; iConfig++ ) {
                    if ( pobjHex.bConfigWordUsed[iConfig] == true ) {
                        iRetries = 0;
                        do {
                            for ( iByte = 0; iByte < 2; iByte++ ) {
                                if ( clsds30Loader.debugMode ) {
                                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing config byte " + (iConfig*2 + iByte).ToString(), iTabLevel) );
                                }

                                iBufferIndx = 0;
                                iSum = 0;

                                // Calculate
                                iAddrP = 0xF80000 + iConfig * 2 + iByte;				//24-bit address in memory to write to
                                bAddrU = Convert.ToByte( (iAddrP & 0xff0000) >> 16 );	//address upper byte
                                bAddrH = Convert.ToByte( (iAddrP & 0x00ff00) >> 8 );	//address high byte
                                bAddrL = Convert.ToByte( (iAddrP & 0x0000ff) );			//address low byte
                                bSize = Convert.ToByte( 1 + 1/*checksum*/ );

                                //
                                bBuffer[ iBufferIndx++ ] = bAddrU;	iSum += bAddrU;
                                bBuffer[ iBufferIndx++ ] = bAddrH;	iSum += bAddrH;
                                bBuffer[ iBufferIndx++ ] = bAddrL;	iSum += bAddrL;
                                bBuffer[ iBufferIndx++ ] = cCmdWriteConfig;iSum += cCmdWriteConfig;
                                bBuffer[ iBufferIndx++ ] = bSize;	iSum += bSize;

                                // Buffer config word
                                bProg = Convert.ToByte( pobjHex.iConfigMem[ iConfig * 2 + iByte ] );
                                bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;

                                // Calculate checksum and add to buffer
                                iSum %= 256;
                                iChecksum = Convert.ToInt16( (256 - iSum) % 256 );
                                bBuffer[ iBufferIndx++ ] = Convert.ToByte(iChecksum);

                                // Send row+checksum
                                pobjPort.SendBytes( ref bBuffer, iBufferIndx );

                                // Get response, checksum ok
                                ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                                if ( bProcessWriteResponseResult == false ) {
                                    return false;
                                }
                            }
                            Application.DoEvents();
                        } while ( bRetry == true && bAbort == false );

                        //
                        if ( bAbort == true ) {
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted by user", -1) );
                            return false;
                        }

                        //
                        iBytesWritten += 2;
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progress, "", (100 * iBytesWritten) / iByteToWrite ) );
                    }//if ( bConfigUsed[iIter] == true ) {

                }//for ( iIter = 0;  iIter < iConfigUsedBufferSize; iIter++ ) {

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            }//if ( bWriteConfigs == true )

            //--------------------------------------------------------------------------
            // Write completed
            //--------------------------------------------------------------------------
            return true;
        }
        //---------------------------------------------------------------------
        // WriteFlash30_1_0_1()
        //---------------------------------------------------------------------
        private static bool WriteFlash30_1_0_1( clsSerialPort pobjPort, clsDevice pobjDevice, clsHex30F pobjHex, bool pbWriteProgram, bool pbWriteEEPROM, bool pbWriteConfigs, int iTabLevel )
        {
            //--------------------------------------------------------------------------
            // Variables
            //--------------------------------------------------------------------------
            int iIter2;
            int iChecksum;
            int iSum;
            int iAddrP;
            int iRetries;
            byte [] bBuffer = new byte [256];
            int iBufferIndx;
            byte bAddrU, bAddrH, bAddrL, bSize, bProg;
            bool bRetry = false;
            int iByteToWrite = pobjHex.BytesToWrite( pobjDevice, pbWriteProgram, pbWriteEEPROM, pbWriteConfigs );
            int iBytesWritten = 0;
            bool bProcessWriteResponseResult = false;

            //--------------------------------------------------------------------------
            // Write flash
            //--------------------------------------------------------------------------
            if ( pbWriteProgram == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing flash...", iTabLevel) );

                //-------------------------------------------------------------
                // Iterate rows
                //-------------------------------------------------------------
                for ( int iRow = 0; iRow < clsHex30F.iProgRowsUsedBufferSize; iRow++ ) {
                    if ( pobjHex.bProgRowUsed[iRow] == true ) {
                        iRetries = 0;
                        do {
                            if ( clsds30Loader.debugMode ) {
                                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing row " + iRow.ToString(), iTabLevel) );
                            }

                            iBufferIndx = 0;
                            iSum = 0;

                            // Calculate
                            iAddrP = iRow * (pobjDevice.rowsizeW * 2);				//24-bit address in memory to write to
                            bAddrU = Convert.ToByte( (iAddrP & 0xff0000) >> 16 );	//address upper byte
                            bAddrH = Convert.ToByte( (iAddrP & 0x00ff00) >> 8 );	//address high byte
                            bAddrL = Convert.ToByte( (iAddrP & 0x0000ff) );			//address low byte
                            bSize = Convert.ToByte( pobjDevice.rowsizeW * 3 + 1/*checksum*/ );

                            //
                            bBuffer[ iBufferIndx++ ] = bAddrU;	iSum += bAddrU;
                            bBuffer[ iBufferIndx++ ] = bAddrH;	iSum += bAddrH;
                            bBuffer[ iBufferIndx++ ] = bAddrL;	iSum += bAddrL;
                            bBuffer[ iBufferIndx++ ] = bSize;	iSum += bSize;

                            // Calculate startindex in hex-buffer
                            iAddrP = iRow * pobjDevice.rowsizeW * 3;

                            // Buffer row, upper-low-high, ordered in ParseHex()
                            for ( int iByte = 0; iByte < pobjDevice.rowsizeW*3; iByte++ ) {
                                bProg = Convert.ToByte( pobjHex.iProgMem[iAddrP + iByte] );
                                bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;
                            }

                            // Calculate checksum and add to buffer
                            iSum %= 256;
                            iChecksum = Convert.ToInt16( (256 - iSum) % 256 );
                            bBuffer[ iBufferIndx++ ] = Convert.ToByte(iChecksum);

                            // Send address, command, packetsize, row & checksum
                            pobjPort.SendBytes( ref bBuffer, iBufferIndx );

                            // Get response, checksum ok
                            ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                            if ( bProcessWriteResponseResult == false ) {
                                return false;
                            }

                            //
                            Application.DoEvents();
                        } while ( bRetry == true && bAbort == false );

                        //
                        if ( bAbort == true ) {
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted by user", -1) );
                            return false;
                        }

                        //
                        iBytesWritten += pobjDevice.rowsizeW * 3;
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progress, "", (100 * iBytesWritten) / iByteToWrite ) );

                    } //if ( bProgRowUsed[iIter] == true ) {
                }//for ( iRow = 0; iRow < iProgRowUsedBufferSize; iRow++ ) {

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            }//if ( pbWriteProgram == true ) {

            //--------------------------------------------------------------------------
            // Write EEPROM
            //--------------------------------------------------------------------------
            if ( pbWriteEEPROM == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing eeprom...", iTabLevel) );

                for ( int iEEPROMWord = 0; iEEPROMWord < pobjDevice.eepromSizeB/2; iEEPROMWord++ ) {
                    if (  pobjHex.bEEWordUsed[iEEPROMWord] == true ) {
                        iRetries = 0;

                        do {
                            if ( clsds30Loader.debugMode ) {
                                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing eeprom word " + iEEPROMWord.ToString(), iTabLevel) );
                            }

                            iBufferIndx = 0;
                            iSum = 0;

                            // Calculate
                            iAddrP = pobjDevice.eepromStartAddress + iEEPROMWord * 2;		//24-bit address in memory to write to
                            bAddrU = Convert.ToByte( (iAddrP & 0xff0000) >> 16 );	//address upper byte
                            bAddrH = Convert.ToByte( (iAddrP & 0x00ff00) >> 8 );	//address high byte
                            bAddrL = Convert.ToByte( (iAddrP & 0x0000ff) );			//address low byte
                            bSize = Convert.ToByte( 2 + 1/*checksum*/ );

                            //
                            bBuffer[ iBufferIndx++ ] = bAddrU;	iSum += bAddrU;
                            bBuffer[ iBufferIndx++ ] = bAddrH;	iSum += bAddrH;
                            bBuffer[ iBufferIndx++ ] = bAddrL;	iSum += bAddrL;
                            bBuffer[ iBufferIndx++ ] = bSize;	iSum += bSize;

                            // Low byte
                            bProg = Convert.ToByte( pobjHex.iEEMem[iEEPROMWord*2 + 0] );
                            bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;

                            // High byte
                            bProg = Convert.ToByte( pobjHex.iEEMem[iEEPROMWord*2 + 1] );
                            bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;

                            // Calculate checksum and add to buffer
                            iSum %= 256;
                            iChecksum = Convert.ToInt16( (256 - iSum) % 256 );
                            bBuffer[ iBufferIndx++ ] = Convert.ToByte(iChecksum);

                            // Send row+checksum
                            pobjPort.SendBytes( ref bBuffer, iBufferIndx );

                            // Get response, checksum ok
                            ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                            if ( bProcessWriteResponseResult == false ) {
                                return false;
                            }

                            //
                            Application.DoEvents();
                        } while ( bRetry == true && bAbort == false );

                        //
                        if ( bAbort == true ) {
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted by user", -1) );
                            return false;
                        }

                        //
                        iBytesWritten += 2;
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progress, "", (100 * iBytesWritten) / iByteToWrite ) );
                     }//if (  bEEWordUsed[iEEPROMWord] == true ) {

                }//for ( iIter = 0; iIter < pobjDevice.eepromSizeB/2; iIter++ ) {

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            }//if ( pbWriteEEPROM == true ) {

            //--------------------------------------------------------------------------
            // Write Config Bits
            //--------------------------------------------------------------------------
            if ( pbWriteConfigs == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing configs...", iTabLevel) );

                for ( int iConfig = 0;  iConfig < clsHex30F.iConfigWordsUsedBufferSize; iConfig++ ) {
                    if ( pobjHex.bConfigWordUsed[iConfig] == true ) {
                        iRetries = 0;

                        do {
                            if ( clsds30Loader.debugMode ) {
                                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Writing config word " + iConfig.ToString(), iTabLevel) );
                            }

                            iBufferIndx = 0;
                            iSum = 0;

                            // Calculate
                            iAddrP = 0xF80000 + iConfig * 2;						//24-bit address in memory to write to
                            bAddrU = Convert.ToByte( (iAddrP & 0xff0000) >> 16 );	//address upper byte
                            bAddrH = Convert.ToByte( (iAddrP & 0x00ff00) >> 8 );	//address high byte
                            bAddrL = Convert.ToByte( (iAddrP & 0x0000ff) );			//address low byte
                            bSize = Convert.ToByte( 2 + 1/*checksum*/ );

                            //
                            bBuffer[ iBufferIndx++ ] = bAddrU;	iSum += bAddrU;
                            bBuffer[ iBufferIndx++ ] = bAddrH;	iSum += bAddrH;
                            bBuffer[ iBufferIndx++ ] = bAddrL;	iSum += bAddrL;
                            bBuffer[ iBufferIndx++ ] = bSize;	iSum += bSize;

                            // Buffer config word
                            for ( iIter2 = 0; iIter2 < 2; iIter2++ ) {
                                bProg = Convert.ToByte( pobjHex.iConfigMem[ iConfig * 2 + iIter2 ] );
                                bBuffer[ iBufferIndx++ ] = bProg; iSum = (iSum + bProg) % 256;
                            }

                            // Calculate checksum and add to buffer
                            iSum %= 256;
                            iChecksum = Convert.ToInt16( (256 - iSum) % 256 );
                            bBuffer[ iBufferIndx++ ] = Convert.ToByte(iChecksum);

                            // Send row+checksum
                            pobjPort.SendBytes( ref bBuffer, iBufferIndx );

                            // Get response, checksum ok
                            ProcessWriteResponse( pobjPort, ref iRetries, iTabLevel, "flash", ref bRetry, ref bProcessWriteResponseResult );
                            if ( bProcessWriteResponseResult == false ) {
                                return false;
                            }

                            //
                            Application.DoEvents();
                        } while ( bRetry == true && bAbort == false );

                        //
                        if ( bAbort == true ) {
                            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "aborted by user", -1) );
                            return false;
                        }

                        //
                        iBytesWritten += 2;
                        OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progress, "", (100 * iBytesWritten) / iByteToWrite ) );
                    }//if ( bConfigWordUsed[iIter] == true ) {

                }//for ( iIter = 0;  iIter < iConfigUsedBufferSize; iIter++ ) {

                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            }//if ( bWriteConfigs == true )

            //--------------------------------------------------------------------------
            // Write completed
            //--------------------------------------------------------------------------
            return true;
        }
        //---------------------------------------------------------------------
        // Download()
        //---------------------------------------------------------------------
        public static void Download( clsDevice pobjDevice, clsSerialPort pobjPort, clsHex pobjHex, clsDownloadSettings pobjSettings, int iTabLevel, ref bool pbResult )
        {
            //
            bool bWriteSuccess = false;
            bool bParseResult = false;

            pbResult = false;
            bAbort = false;
            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.started, "Initiating download...", iTabLevel++) );

            // Test-mode
            if ( bTestMode == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.warning, "Test-mode is active", iTabLevel) );
            }

            //--------------------------------------------------------------------------
            // Reset device
            //--------------------------------------------------------------------------
            bool bResetResult = false;
            ResetDevice( pobjPort, pobjSettings, iTabLevel, ref bResetResult );
            if ( bResetResult == false ) {
                return;
            }

            //--------------------------------------------------------------------------
            // Open port
            //--------------------------------------------------------------------------
            bool bOpenPortResult = false;
            PortOpen( pobjPort, pobjSettings, ref bOpenPortResult );

            //--------------------------------------------------------------------------
            // Find loader
            //--------------------------------------------------------------------------
            bool bFindLoaderResult = false;
            FindLoader( pobjDevice, pobjPort, pobjSettings, iTabLevel, ref bFindLoaderResult );
            if ( bFindLoaderResult == false ) {
                PortClose( pobjPort );
                return;
            }

            //--------------------------------------------------------------------------
            // Init progressbar
            //--------------------------------------------------------------------------
            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progressStarted, "", 0) );

            //--------------------------------------------------------------------------
            // Determine size of the bootloader found
            //--------------------------------------------------------------------------
            bool bGetBLSizeResult = false;
            iBootloaderSizeR = GetBLSize( pobjDevice, ref bGetBLSizeResult );
            if ( bGetBLSizeResult == false ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                PortClose( pobjPort );
                return;
            }

            //--------------------------------------------------------------------------
            //
            //--------------------------------------------------------------------------
            bool WaitBLReadyResponseResult = false;
            WaitBLReadyResponse( pobjPort, iTabLevel, ref WaitBLReadyResponseResult );
            if ( WaitBLReadyResponseResult == false ) {
                PortClose( pobjPort );
                return;
            }

            //--------------------------------------------------------------------------
            // Setup parse settings
            //--------------------------------------------------------------------------
            clsParseSettings objParseSettings = new clsParseSettings( iBootloaderSizeR, pobjDevice, false, pobjSettings.noGoto );

            //--------------------------------------------------------------------------
            // PIC18F
            //--------------------------------------------------------------------------
            if ( pobjDevice.family.name == "PIC18F" ) {
                clsHex18F objHex18F = (clsHex18F)pobjHex;

                // Parse
                objHex18F.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.0 - 1.0.0
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 2 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 1 )
                ) {
                    bWriteSuccess = WriteFlash18F_0_9_0( pobjPort, pobjDevice, objHex18F, pobjSettings.writeProgram, pobjSettings.writeEEPROM, pobjSettings.writeConfigs, iTabLevel );

                    // Write versions 1.5
                } else if (
                    ( iFWVerMaj == 1 && iFWVerMin == 5 )
                ) {
                    bWriteSuccess = WriteFlash18F_0_9_0( pobjPort, pobjDevice, objHex18F, pobjSettings.writeProgram, false, false, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // PIC18FJ
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "PIC18FJ" ) {
                clsHex18FJ objHex18FJ = (clsHex18FJ)pobjHex;

                // Parse
                objHex18FJ.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.0 - 0.9.1
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 )
                ) {
                    bWriteSuccess = WriteFlash18FJ_0_9_0( pobjPort, pobjDevice, objHex18FJ, pobjSettings.writeProgram, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // PIC24F
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "PIC24F" ) {
                clsHex24F objHex24F = (clsHex24F)pobjHex;

                // Parse
                objHex24F.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.0 - 0.9.0
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 1 )
                ) {
                    bWriteSuccess = WriteFlash24F_0_9_0( pobjPort, pobjDevice, objHex24F, pobjSettings.writeProgram, pobjSettings.writeEEPROM, pobjSettings.writeConfigs, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // PIC24FJ
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "PIC24FJ" ) {
                clsHex24FJ objHex24FJ = (clsHex24FJ)pobjHex;

                // Parse
                objHex24FJ.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.0 - 1.0.1
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 2 )
                ) {
                    bWriteSuccess = WriteFlash24FJ_1_0_0( pobjPort, pobjDevice, objHex24FJ, pobjSettings.writeProgram, pobjSettings.writeEEPROM, pobjSettings.writeConfigs, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // PIC24H
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "PIC24H" ) {
                clsHex24H objHex24H = (clsHex24H)pobjHex;

                // Parse
                objHex24H.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.0 - 0.9.1
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 )
                ) {
                    bWriteSuccess = WriteFlash24H_0_9_0( pobjPort, pobjDevice, objHex24H, pobjSettings.writeProgram, pobjSettings.writeConfigs, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // dsPIC30F
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "dsPIC30F" ) {
                clsHex30F objHex30F = (clsHex30F)pobjHex;

                // Parse
                objHex30F.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write versions 0.9.4 - 1.0.1
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 4 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 1 )
                ) {
                    bWriteSuccess = WriteFlash30_1_0_1( pobjPort, pobjDevice, objHex30F, pobjSettings.writeProgram, pobjSettings.writeEEPROM, pobjSettings.writeConfigs, iTabLevel );

                // Versions 2.0.0 - 2.0.2
                } else if (
                    ( iFWVerMaj == 2 && iFWVerMin == 0 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 2 && iFWVerMin == 0 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 2 && iFWVerMin == 0 && iFWVerRev == 2 )
                ) {
                    bWriteSuccess = WriteFlash30_2_0_0( pobjPort, pobjDevice, objHex30F, pobjSettings.writeProgram, pobjSettings.writeEEPROM, pobjSettings.writeConfigs, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }

            //--------------------------------------------------------------------------
            // dsPIC33F
            //--------------------------------------------------------------------------
            } else if ( pobjDevice.family.name == "dsPIC33FJ" ) {
                clsHex33FJ objHex33F = (clsHex33FJ)pobjHex;

                // Parse
                objHex33F.ParseHexFile( objParseSettings, iTabLevel, ref bParseResult );
                if ( bParseResult == false ) {
                    PortClose( pobjPort );
                    return;
                }

                // Write vrsions 0.9.0 - 1.0.0
                if (
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 2 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 3 ) ||
                    ( iFWVerMaj == 0 && iFWVerMin == 9 && iFWVerRev == 4 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 0 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 1 ) ||
                    ( iFWVerMaj == 1 && iFWVerMin == 0 && iFWVerRev == 2 )
                ) {
                    bWriteSuccess = WriteFlash33_1_0_0( pobjPort, pobjDevice, objHex33F, pobjSettings.writeProgram, pobjSettings.writeConfigs, iTabLevel );

                // Unkown version
                } else {
                    OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "Unknown firmware version", iTabLevel) );
                    PortClose( pobjPort );
                    return;
                }
            }

            //--------------------------------------------------------------------------
            // Download completed
            //--------------------------------------------------------------------------
            pobjPort.Close();

            if ( bWriteSuccess == true ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.completed, "Download finished", iTabLevel) );
            }

            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.progressEnded, "", 0) );
            pbResult = bWriteSuccess;
        }
        //---------------------------------------------------------------------
        // WaitBLReadyResponse()
        //---------------------------------------------------------------------
        private static void WaitBLReadyResponse( clsSerialPort pobjPort, int iTabLevel, ref bool pbResult )
        {
            int iResponse = -1;
            pbResult = false;

            //--------------------------------------------------------------------------
            // Get bootloader ready response
            //--------------------------------------------------------------------------
            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.info, "Waiting for bootloader to be ready...", iTabLevel) );
            bool bGetResponseResult = false;
            iResponse = GetResponse( pobjPort, ref bGetResponseResult);
            if ( bGetResponseResult == false ) {
                return;
            }

            if ( iResponse != c*K ) {
                OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.error, "unknown response, aborting", -1) );
                return;
            }
            OnDownloading( new clsDownloadingEventArgs(clsDownloadingEventArgs.EventType.success, "ok", -1) );
            pbResult = true;
        }
		//---------------------------------------------------------------------
		// Constructor()
		//---------------------------------------------------------------------	
		public frmDS30Loader()
		{
			bStartup = true;
            InitializeComponent();

            //---------------------------------------------------------------------	
            // Create objects
            //---------------------------------------------------------------------	
            verGUI = new Version( strVersion );            
            sizeBeforeMicro = new Size();
			objPort = new clsSerialPort();	
		    objds30LSettings = new clsDownloadSettings();
            
            
            //---------------------------------------------------------------------	
            // Init
            //---------------------------------------------------------------------	
            ResetSettingsToDefault();
            clsDebugTextbox.SetTextbox( this.txtInfo );            
            progressBar.Visible = false;
            toolStrip1.Visible = false;			
            progressBar.Minimum = 0;
            progressBar.Maximum = 100;
            lblVersion.Text = clsds30Loader.strVersion + " / " + verGUI.ToString();
            

            //---------------------------------------------------------------------	
			// Enum comports
            //---------------------------------------------------------------------	
			string[] ports = System.IO.Ports.SerialPort.GetPortNames();
			foreach ( string strPort in ports ) {
				cboCOMPort.Items.Add( strPort );
			}
			
			// If no comports were found, add a few default
			if ( cboCOMPort.Items.Count == 0 ) {
				for ( int iIter = 1; iIter <= 4; iIter++ ) {
					cboCOMPort.Items.Add( "COM" + iIter.ToString() );
				}
			}
			if ( cboCOMPort.Items.Count > 0 ) {
				cboCOMPort.SelectedIndex = 0;
			} else {
				cboCOMPort.Text = "COM1";
			}
			
			cboBaudrate.SelectedIndex = 0;
            cboResetBaudrate.SelectedIndex = 0;
            cboTermBaudrate.SelectedIndex = 0;
			

            //---------------------------------------------------------------------	
			// Add device families to combobox
            //---------------------------------------------------------------------	
			clsDevices.Init();
            Hashtable htDeviceFamilys = clsDevices.DeviceFamiliesGet();
			foreach ( clsDeviceFamily objDeviceFamily in htDeviceFamilys.Values ) {
				cboFamily.Items.Add( objDeviceFamily.name );
			}
			
			//
			if ( cboFamily.Items.Count > 0 ) cboFamily.SelectedIndex = 0;
			
            
            //---------------------------------------------------------------------	
            // Load setttings
			//---------------------------------------------------------------------	
            LoadSettings();			


            //---------------------------------------------------------------------	
            // 
			//---------------------------------------------------------------------	            
            clsds30Loader.Downloading += new clsds30Loader.DownloadingDelegate( ds30L_Downloading );


            //---------------------------------------------------------------------	
            // Startup finished
            //---------------------------------------------------------------------	
			bStartup = false;
			DoParse();
		}//Constructor