Open source PBP bootloader
+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 41
  1. #1
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Open source PBP bootloader

    Ok guys, I read lots of stuff about how to change this or that with xyz bootloader. It seems to me this should not be a hard thing for us folks to create. So anybody up for this? Heck Walter even posted 1 in another thread, written in ASM. Now I suppose I could just reverse engineer it, but wheres the fun in that.

    I am thinking about something well commented with places pointed out clearly for things like "I want to use UART 2, not 1" or "I want to use I2C"

    What say you?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  2. #2
    Join Date
    Oct 2004
    Posts
    448

    Default Re: Open source PBP bootloader

    Quote Originally Posted by cncmachineguy View Post
    I am thinking about something well commented with places pointed out clearly for things like "I want to use UART 2, not 1" or "I want to use I2C"
    Reminds me of the first bootloader I used: Tony Nixon's ROMZAP. Besides a snazzy interface, it had options to use ANY pins, not just the UART, with or without inversion (could save you a MAX chip!), user-configurable speeds and more.

    Unfortunately Tony stopped development a long time ago, so its pretty much of no use today. A pity!

    Anand Dhuru

  3. #3
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    It does sould like exactly what I think we all need in our "tool box" So we have a very vauge goal now. What a shame he quit on it. any idea why he stopped?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  4. #4
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Ok, just got done reading AN851. This doesn't seem too hard to implement in PBP. Is anyone intrested? If so, what do you think of this as a starting point?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  5. #5
    Join Date
    Jan 2006
    Location
    Toronto
    Posts
    109

    Default Re: Open source PBP bootloader

    I was planning on making a PBP Serial/USB/I2C/SD/Ethernet Bootloader but never got around to starting it yet. I guess now is a good time

  6. #6
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    PJALM, That sounds pretty awesome, and aggressive!

    After doing some googling, There is at least 1 open source python interface out there to talk to AN851 BL. I like that approach, Python I mean, then we have multiplatform available.

    Ok, we have 2 responses so far. I have no idea how to tend to the logistics of this - meaning making it a group effort- or if we just contribuite code until we get something working. Baring any other suggestions, I will start to port AN851 to PBP.

    We will also need TESTERS!!!
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  7. #7
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    This is where I am so far. I am sure there are some errors, but what are friends for?
    Code:
    ' *****************************************************************************
    '        Software License Agreement				    
    '		 						    
    ' The software supplied herewith by PBP forum members 	    
    ' (the “Company”) for Microchip's PICmicro® Microcontroller's is 
    ' intended and supplied to you, the Company’s customer, for use     
    ' solely and exclusively on Microchip PICmicro Microcontroller	    
    ' products. The software is owned by the Company and/or its         
    ' supplier, and is protected under applicable copyright laws. All   
    ' rights are reserved. Any use in violation of the foregoing 	     
    ' restrictions may subject the user to criminal sanctions under	    
    ' applicable laws, as well as to civil liability for the breach of  
    ' the terms and conditions of this license.			    
    '								    
    ' THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, 
    ' WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
    ' TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 	    
    ' PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
    ' IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 	    
    ' CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.		    
    '								    
    '					 			    
    ' This software has been ported from Microchip's AN851 bootloader
    ' Changes have been made and will be made as the company sees fit.
    ' This version is for 16F's, there is another version for 18F's
    '
    '
    ' Memory Map
    '	-----------------
    '	|    0x0000	|	Reset vector
    '	|        	|
    '   |    0x0004	|	Interrupt vector
    '	|    		|	
    '	|		    |
    '	|Boot Block |	(this program)
    ' 	|		    |
    '	|    0x0200	|	Re-mapped Reset Vector
    '	|    0x0204	|	Re-mapped High Priority Interrupt Vector
    '	|		    |
    '	|   	    |	
    '	|		    |
    '   |Code Space |	User program space
    '	|		    |
    '	|		    |
    '	|		    |
    '	|    0x3FFF |
    '	-----------------
    '
    ' Incomming data format:
    '
    '       <STX><STX><DATA><CHKSUM><ETX>
    '                               /    \
    '	 ________/      \____________________________
    '	/	                                         \
    '	<COMMAND><DLEN><ADDRL><ADDRH><ADDRU><DATA>...
    '
    ' Definitions:
    '
    ' 	STX  	-	Start of packet indicator
    '	ETX 	-	End of packet indicator
    ' 	LEN 	-	Length of incomming packet
    ' 	DATA	-	General data up to 255 bytes
    ' 	CHKSUM 	- 	The 8-bit two's compliment sum of LEN & DATA
    ' 	COMMAND - 	Base command
    ' 	DLEN	-	Length of data associated to the command
    ' 	ADDR	-	Address up to 24 bits
    ' 	DATA 	-	Data (if any)
    '
    '
    ' Commands:
    '
    ' 	RD_VER		0x00	Read Version Information
    ' 	RD_MEM		0x01	Read Program Memory
    ' 	WR_MEM		0x02	Write Program Memory
    ' 	ER_MEM		0x03	Erase Program Memory (NOT supported by PIC16)
    ' 	RD_EE		0x04	Read EEDATA Memory 
    ' 	WR_EE		0x05	Write EEDATA Memory 
    ' 	RD_CONFIG	0x06	Read Config Memory (NOT supported by PIC16)
    ' 	WT_CONFIG	0x07	Write Config Memory (NOT supported by PIC16)
    '
    ' ****************************************************************************
    
    ' *****************************************************************************
    CHKSUM		VAR	BYTE		' Checksum accumulator
    COUNTER		VAR	BYTE		' General counter
    ABTIME		VAR	BYTE
    RXDATA		VAR	BYTE
    TXDATA		VAR	BYTE
    TEMP		VAR	BYTE
    
    PCLATH_TEMP	VAR	BYTE		' Interrupt context
    STATUS_TEMP	VAR	BYTE		' save/restore registers
    W_TEMP		VAR	BYTE
    
    ' Frame Format
    '
    '  <STX><STX>[<COMMAND><DATALEN><ADDRL><ADDRH><ADDRU><...DATA...>]<CHKSUM><ETX>
    
    DATA_BUFF	VAR	BYTE		' Start of receive buffer SAME ADDRESS AS COMMAND
    	
    COMMAND		VAR	BYTE		' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT	VAR	BYTE	
    ADDRESS_L	VAR	BYTE
    ADDRESS_H	VAR	BYTE
    ADDRESS_U	VAR	BYTE
    PACKET_DATA	VAR	BYTE	     'THIS SHOULD BE AN ARRAY I THINK**************
    ' *****************************************************************************
    
    
    '  This is the remapping section, note the interrupt also saves context
    ' *****************************************************************************
    @	ORG	0x0000			' Re-map Reset vector **Not sure how to set the address to start at
    VReset:
    	PCLATH = 0
    	goto	Setup								
    
    @	ORG	0x0004			'standard interrupt vector **again not sure of the PBP equal for ORG
    VInt:
    	W_TEMP = W			   'I am assuming this will be the "W" register			
    	STATUS_TEMP = STATUS   'We may have trouble here. ASM uses SWAP so as not to affect the status
    	STATUS = 0
    	PCLATH_TEMP = PCLATH
    	PCLATH = 0
    	goto	RVInt	    ' Re-map Interrupt vector		
    
    ; *****************************************************************************
     *****************************************************************************
    ; Setup the appropriate registers.
    Setup:
    	clrwdt
    	READ $ff,temp		         'get the value of last EEPROM location
    	IF temp = $ff then goto SRX  'BL startup
    	goto	RVReset			     ' If not 0xFF then normal reset	
    
    SRX:
    	RCSTA = b'10000000'		' Setup rx and tx, CREN disabled
    	TRISC.6 = 0 			' Setup tx pin		
    	TXSTA = b'00100110'			
    	STATUS.IRP = 1
    ; *****************************************************************************

    Well it formats much better in notepad++. well I tried to attach the code, but had some issues there. but for now, the code is as I wrote it, just the comments are messed up.
    Last edited by cncmachineguy; - 2nd March 2011 at 05:00.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  8. #8
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    This is pretty small help. I'll try to do better later..... I notice the GUI that Microchip includes includes the Visual Basic 6.0 source code. So in that case I may be able to do some simple stuff for the interface. I know this doesn't help our linux crowd though.

    Code:
    DATA_BUFF   VAR BYTE[6]        ' Start of receive buffer SAME ADDRESS AS COMMAND
        
    COMMAND     VAR DATA_BUFF[0]    ' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT1 VAR DATA_BUFF[1]    
    ADDRESS_L   VAR DATA_BUFF[2]
    ADDRESS_H   VAR DATA_BUFF[3]
    ADDRESS_U   VAR DATA_BUFF[4]
    PACKET_DATA VAR DATA_BUFF[5]    'THIS SHOULD BE AN ARRAY I THINK**************
    ' *****************************************************************************
    I may be off base on Packet_Data ; DATA - General data up to 255 bytes

    ASM source:
    Code:
    ; *****************************************************************************
    ;        Software License Agreement                    
    ;                                     
    ; The software supplied herewith by Microchip Technology         
    ; Incorporated (the “Company”) for its PICmicro® Microcontroller is 
    ; intended and supplied to you, the Company’s customer, for use     
    ; solely and exclusively on Microchip PICmicro Microcontroller        
    ; products. The software is owned by the Company and/or its         
    ; supplier, and is protected under applicable copyright laws. All   
    ; rights are reserved. Any use in violation of the foregoing          
    ; restrictions may subject the user to criminal sanctions under        
    ; applicable laws, as well as to civil liability for the breach of  
    ; the terms and conditions of this license.                
    ;                                    
    ; THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, 
    ; WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
    ; TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A         
    ; PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
    ; IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR         
    ; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.            
    ;                                    
    ;                                     
    ; Bootloader for PIC16F by Rodger Richey
    ; Adapted from PIC18F bootloader developed by Ross Fosler
    ; 03/18/2002    ... First full implementation
    ; 03/25/2002    Modified receive & parse engine to vector to autobaud on a checksum 
    ;        error since a checksum error could likely be a communications problem.
    ;         Modified the protocol to incorporate the autobaud as part of the 
    ;        first received <stx>. Doing this improves robustness by allowing
    ;        re-sync under any condition. Previously it was possible to enter a 
    ;        state where only a hard reset would allow re-syncing.
    ; 04/09/2002    Fixed bugs: 1) clear carry before shifting ABTIME in Autobaud
    ;                    2) Increment address in program memory write
    ;                    3) Increment address in program memory read
    ; 06/07/2002    Fixed bug in read, byte counter in code is word counter.  Needed
    ;               to multiply by 2 to get bytes.
    ;
    ; Memory Map
    ;    -----------------
    ;    |    0x0000    |    Reset vector
    ;    |            |
    ;       |    0x0004    |    Interrupt vector
    ;    |            |    
    ;    |        |
    ;    |  Boot Block     |    (this program)
    ;     |        |
    ;    |    0x0200    |    Re-mapped Reset Vector
    ;    |    0x0204    |    Re-mapped High Priority Interrupt Vector
    ;    |        |
    ;    |    |    |
    ;    |        |
    ;        |  Code Space     |    User program space
    ;    |        |
    ;    |    |    |
    ;    |        |
    ;    |    0x3FFF     |
    ;    -----------------
    ;
    ;
    ; Incomming data format:
    ;
    ;    <stx><stx><data><chksum><etx>
    ;          /    \
    ;     ________/      \____________________________
    ;    /                                         \
    ;    <command></command><dlen><addrl><addrh><addru><data>...
    ;
    ; Definitions:
    ;
    ;     STX    -    Start of packet indicator
    ;    ETX    -    End of packet indicator
    ;     LEN     -    Length of incomming packet
    ;     DATA    -    General data up to 255 bytes
    ;     CHKSUM     -     The 8-bit two's compliment sum of LEN & DATA
    ;     COMMAND -     Base command
    ;     DLEN    -    Length of data associated to the command
    ;     ADDR    -    Address up to 24 bits
    ;     DATA     -    Data (if any)
    ;
    ;
    ; Commands:
    ;
    ;     RD_VER        0x00    Read Version Information
    ;     RD_MEM        0x01    Read Program Memory
    ;     WR_MEM        0x02    Write Program Memory
    ;     ER_MEM        0x03    Erase Program Memory (NOT supported by PIC16)
    ;     RD_EE        0x04    Read EEDATA Memory 
    ;     WR_EE        0x05    Write EEDATA Memory 
    ;     RD_CONFIG    0x06    Read Config Memory (NOT supported by PIC16)
    ;     WT_CONFIG    0x07    Write Config Memory (NOT supported by PIC16)
    ;
    ; *****************************************************************************
    
     
    
    ; *****************************************************************************
        #include P16F877A.INC        ; Standard include
    ; *****************************************************************************
    
        errorlevel -302            ; Do not show any banking warnings
    
    ; *****************************************************************************
    #define    MINOR_VERSION    0x03        ; Version
    #define    MAJOR_VERSION    0x00
    
    #define    RC_DLE        0x01
    #define    RC_STX        0x02
    
    #define    STX        0x0F
    #define    ETX        0x04
    #define    DLE        0x05
    
    ;#define DEBUGGING            ; Debugging enabled with ICD
    ; *****************************************************************************
    
    
    
    ; *****************************************************************************
    CHKSUM        equ    0x71        ; Checksum accumulator
    COUNTER        equ    0x72        ; General counter
    ABTIME        equ    0x73
    RXDATA        equ    0x74
    TXDATA        equ    0x75
    TEMP        equ    0x76
    
    PCLATH_TEMP    equ    0x7D        ; Interrupt context
    STATUS_TEMP    equ    0x7E        ; save/restore registers
    W_TEMP        equ    0x7F
    
    ; Frame Format
    ;
    ;  <stx><stx>[<command></command><datalen><addrl><addrh><addru><...DATA...>]<chksum><etx>
    
    DATA_BUFF    equ    0x10        ; Start of receive buffer
        
    COMMAND        equ    0x10        ; Data mapped in receive buffer
    DATA_COUNT    equ    0x11    
    ADDRESS_L    equ    0x12
    ADDRESS_H    equ    0x13
    ADDRESS_U    equ    0x14
    PACKET_DATA    equ    0x15    
    ; *****************************************************************************
    
    
     
    ; *****************************************************************************
        ORG    0x0000            ; Re-map Reset vector
    VReset
        bcf    STATUS,RP0                            ; B0/B2
        bsf    STATUS,RP1                            ; B2
        clrf    PCLATH                                ; B2
        goto    Setup                                ; B2
    
        ORG    0x0004
    VInt
        movwf    W_TEMP                                ; ?
        swapf    STATUS,W                            ; ?
        movwf    STATUS_TEMP                            ; ?
        clrf    STATUS                                ; B0
        movf    PCLATH,W                            ; B0
        movwf    PCLATH_TEMP                            ; B0
        clrf    PCLATH                                ; B0
        goto    RVInt            ; Re-map Interrupt vector        ; B0
    
    ; *****************************************************************************
    
    
    
    ; *****************************************************************************
    ; Setup the appropriate registers.
    Setup    clrwdt
        movlw    0xFF                                ; B2
        movwf    EEADR            ; Point to last location        ; B2
        bsf    STATUS,RP0                            ; B3
        clrf    EECON1                                ; B3
        bsf    EECON1,RD        ; Read the control code            ; B3
        bcf    STATUS,RP0                            ; B2
        incf    EEDATA,W                            ; B2
        btfsc    STATUS,Z                            ; B2
        goto    SRX                                ; B2
    
        bcf    STATUS,RP1                            ; B0
        goto    RVReset            ; If not 0xFF then normal reset        ; B0
    
    SRX    bcf    STATUS,RP1                            ; B0
        movlw    b'10000000'        ; Setup rx and tx, CREN disabled    ; B0
        movwf    RCSTA                                ; B0
        bsf    STATUS,RP0                            ; B1
        bcf    TRISC,6            ; Setup tx pin                ; B1
        movlw    b'00100110'                            ; B1
        movwf    TXSTA                                ; B1
        bsf    STATUS,IRP                            ; B1
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    Autobaud
    ;
    ; ___     __________            ________
    ;    \__/       \__________/
    ;       |                     |
    ;       |-------- p ----------|
    ;
    ;    p = The number of instructions between the first and last
    ;           rising edge of the RS232 control sequence 0x0F. Other 
    ;        possible control sequences are 0x01, 0x03, 0x07, 0x1F, 
    ;         0x3F, 0x7F.
    ;
    ;    SPBRG = (p / 32) - 1      BRGH = 1
                                            ; B0/B1/B2
        bcf    STATUS,RP1                            ; B0/B1
        bsf    STATUS,RP0                            ; B1
        movlw    b'00000011'                            ; B1
        movwf    OPTION_REG                            ; B1
        bcf    STATUS,RP0                            ; B0
        bcf    RCSTA,CREN                            ; B0
    
        call    WaitForRise                            ; B0
     
        clrf    TMR0            ; Start counting            ; B0
    
        call    WaitForRise                            ; B0
    
        movf    TMR0,W            ; Read the timer            ; B0
        movwf    ABTIME                                ; B0
    
        bcf    STATUS,C
        rrf    ABTIME,W                            ; B0
        btfss    STATUS,C        ; Rounding                ; B0
        addlw    0xFF                                ; B0
    
        bsf    STATUS,RP0                            ; B1
        movwf    SPBRG                                ; B1
        bcf    STATUS,RP0                            ; B0
        bsf    RCSTA,CREN        ; Enable receive            ; B0
    
        movf    RCREG,W                                ; B0
        movf    RCREG,W                                ; B0
    
        bsf    STATUS,RP0                            ; B1
        movlw    b'11111111'                            ; B1
        movwf    OPTION_REG                            ; B1
    ; *****************************************************************************
    
    
    
    ; *****************************************************************************
    ; Read and parse the data.
    StartOfLine                                    ; B1/B2/B0
        bcf    STATUS,RP0                            ; B0/B2
        bcf    STATUS,RP1                            ; B0
        call    RdRS232            ; Look for a start of line        ; B0
        xorlw    STX            ; <stx><stx>                ; B0
        btfss    STATUS,Z                            ; B0
        goto    Autobaud        ;was StartOfline            ; B0
    
        movlw    DATA_BUFF        ; Point to the buffer            ; B0
        movwf    FSR                                ; B0
    
        clrf    CHKSUM            ; Reset checksum            ; B0
            
    GetNextDat                
        call    RdRS232            ; Get the data                ; B0
        xorlw    STX            ; Check for a STX            ; B0
        btfsc    STATUS,Z                            ; B0
        goto    StartOfLine        ; Yes, start over            ; B0
    
    NoSTX    movf    RXDATA,W                            ; B0
        xorlw    ETX            ; Check for a ETX            ; B0
        btfsc    STATUS,Z                            ; B0
        goto    CheckSum        ; Yes, examine checksum            ; B0
    
    NoETX    movf    RXDATA,W                            ; B0
        xorlw    DLE            ; Check for a DLE            ; B0
        btfss    STATUS,Z                            ; B0
        goto    NoDLE            ; Check for a DLE            ; B0
    
        call    RdRS232            ; Yes, Get the next byte        ; B0
        
    NoDLE    movf    RXDATA,W                            ; B0
        movwf    INDF            ; Store the data            ; B0
        addwf    CHKSUM,F        ; Get sum                ; B0
        incf    FSR,F                                ; B0
    
        goto    GetNextDat                            ; B0
    
    CheckSum    
        movf    CHKSUM,F        ; Checksum test                ; B0
        btfss    STATUS,Z                            ; B0
        goto    Autobaud                            ; B0
    ; ***********************************************
    
    
    
    ; ***********************************************
    ; Pre-setup, common to all commands.                        ; B0
        bsf    STATUS,RP1                            ; B2
        movf    ADDRESS_L,W        ; Set all possible pointers        ; B2
        movwf    EEADR                                ; B2
        movf    ADDRESS_H,W                            ; B2
        movwf    EEADRH                                ; B2
    
        movlw    PACKET_DATA                            ; B2
        movwf    FSR                                ; B2
    
        movf    DATA_COUNT,W         ; Setup counter                ; B2
        movwf    COUNTER                                ; B2
        btfsc    STATUS,Z                            ; B2
        goto    VReset            ; Non valid count (Special Command)    ; B2
    ; ***********************************************
    
     
    
    ; ***********************************************
    ; Test the command field and sub-command.                    ; B2
    CheckCommand
        movf    COMMAND,W        ; Test for a valid command        ; B2
        sublw    d'7'                                ; B2
        btfss    STATUS,C                            ; B2
        goto    Autobaud                            ; B2
    
        movf    COMMAND,W        ; Perform calculated jump        ; B2
        addwf    PCL,F                                ; B2
        
        goto    ReadVersion        ; 0                    ; B2
        goto    ReadProgMem        ; 1                    ; B2
        goto    WriteProgMem        ; 2                    ; B2
        goto    StartOfLine        ; 3                    ; B2
        goto    ReadEE            ; 4                    ; B2
        goto    WriteEE            ; 5                    ; B2
        goto    StartOfLine        ; 6                    ; B2
        goto    StartOfLine        ; 7                    ; B2
    ;maybe add jump to reset vector in this table
    ; ***********************************************
    
    
    
    ; ***********************************************
    ; Commands
    ; 
    ; In:    <stx><stx>[<0x00><0x02>]<0xFF><etx>
    ; OUT:    <stx><stx>[<0x00><verl><verh>]<chksum><etx>
    ReadVersion                                    ; B2
        movlw    MINOR_VERSION                            ; B2
        movwf    DATA_BUFF + 2                            ; B2
        movlw    MAJOR_VERSION                            ; B2
        movwf    DATA_BUFF + 3                            ; B2
    
        movlw    0x04                                ; B2
        goto    WritePacket                            ; B2
    
    
    ; In:    <stx><stx>[<0x01><dlen><addrl><addrh><addru>]<chksum><etx>
    ; OUT:    <stx><stx>[<0x01><dlen><addrl><addrh><addru><data>...]<chksum><etx>
    ReadProgMem                                    ; B2
    RPM1    bsf    STATUS,RP0                            ; B3
        bsf    EECON1,EEPGD                            ; B3
        bsf    EECON1,RD                            ; B3
        nop                                    ; B3
        nop                                    ; B3
        bcf    STATUS,RP0                            ; B2
        movf    EEDATA,W                            ; B2
        movwf    INDF                                ; B2
        incf    FSR,F                                ; B2
        movf    EEDATH,W                            ; B2
        movwf    INDF                                ; B2
        incf    FSR,F                                ; B2
    
        incf    EEADR,F                                ; B2
        btfsc    STATUS,Z                            ; B2
        incf    EEADRH,F                            ; B2
    
        decfsz    COUNTER,F                            ; B2
        goto    RPM1            ; Not finished then repeat        ; B2
    
        rlf    DATA_COUNT,W        ; Setup packet length            ; B2
        addlw    0x05                                ; B2
                    
        goto    WritePacket                            ; B2
    
    
    ; In:    <stx><stx>[<0x02><dlenblock><addrl><addrh><addru><data>...]<chksum><etx>
    ; OUT:    <stx><stx>[<0x02>]<chksum><etx>
    WriteProgMem                                    ; B2
        bsf    STATUS,RP0                            ; B3
        movlw    b'10000100'        ; Setup writes                ; B3
        movwf    EECON1                                ; B3
        bcf    STATUS,RP0                            ; B2
        movlw    b'11111100'        ; Force a boundry            ; B2
        andwf    EEADR,F                                ; B2
     
        movlw    0x04                                ; B2
        movwf    TEMP                                ; B2
    
    Lp1    
        movf    INDF,W                                ; B2
        movwf    EEDATA                                ; B2
        incf    FSR,F                                ; B2
        movf    INDF,W                                ; B2
        movwf    EEDATH                                ; B2
        incf    FSR,F                                ; B2
        call    StartWrite                            ; B2
    
        incf    EEADR,F                                ; B2
        btfsc    STATUS,Z                            ; B2
        incf    EEADRH,F                            ; B2
    
        decfsz    TEMP,F                                ; B2
        goto    Lp1                                ; B2
    
        decfsz    COUNTER,F                            ; B2
        goto    WriteProgMem        ; Not finished then repeat        ; B2
    
        goto    SendAcknowledge        ; Send acknowledge            ; B2
    
    
    ; In:    <stx><stx>[<0x04><dlen><addrl><addrh><0x00>]<chksum><etx>
    ; OUT:    <stx><stx>[<0x04><dlen><addrl><addrh><0x00><data>...]<chksum><etx>
    ReadEE                                        ; B2
        bsf    STATUS,RP0                            ; B3
        clrf    EECON1                                 ; B3
    
        bsf    EECON1,RD        ; Read the data                ; B3
        bcf    STATUS,RP0                            ; B2
        movf    EEDATA,W                            ; B2
        movwf    INDF                                ; B2
        incf    FSR,F                                ; B2
        
        incf    EEADR,F            ; Adjust EEDATA pointer            ; B2
    
        decfsz    COUNTER,F                            ; B2
        goto    ReadEE            ; Not finished then repeat        ; B2
    
        movf    DATA_COUNT,W        ; Setup packet length            ; B2
        addlw    0x05                                ; B2
                    
        goto    WritePacket                            ; B2
    
    
    ; In:    <stx><stx>[<0x05><dlen><addrl><addrh><0x00><data>...]<chksum><etx>
    ; OUT:    <stx><stx>[<0x05>]<chksum><etx>
    WriteEE                                        ; B2
        movf    INDF,W                                ; B2
        movwf    EEDATA                                ; B2
        incf    FSR,F                                ; B2
        call    WriteWaitEEData        ; Write data                ; B2
    
        incf    EEADR,F            ; Adjust EEDATA pointer            ; B2
    
        decfsz    COUNTER,F                            ; B2
        goto    WriteEE            ; Not finished then repeat        ; B2
    
        goto    SendAcknowledge        ; Send acknowledge            ; B2
    ; ***********************************************
    
    
    
    ; ***********************************************
    ; Send the data buffer back.
    ;
    ; <stx><stx>[<data>...]<chksum><etx>
    
    SendAcknowledge                                    ; B2
        movlw    0x01            ; Send acknowledge            ; B2
                                            ; B2
    WritePacket
        movwf    COUNTER                                ; B2
    
        movlw    STX            ; Send start condition            ; B2
        call    WrRS232                                ; B2
        call    WrRS232                                ; B0
    
        clrf    CHKSUM            ; Reset checksum            ; B0
    
        movlw    DATA_BUFF        ; Setup pointer to buffer area        ; B0
        movwf    FSR                                ; B0
        
    SendNext                ; Send DATA
        movf    INDF,W                                ; B0
        addwf    CHKSUM,F                            ; B0
        incf    FSR,F                                ; B0
        call    WrData                                ; B0
        decfsz    COUNTER,F                            ; B0
        goto    SendNext                            ; B0
    
        comf    CHKSUM,W        ; Send checksum                ; B0
        addlw    0x01                                ; B0
        call    WrData                                ; B0
    
        movlw    ETX            ; Send stop condition            ; B0
        call    WrRS232                                ; B0
    
        goto    Autobaud                            ; B0
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    ; Write a byte to the serial port.
    
    WrData                                        ; B0
        movwf    TXDATA            ; Save the data                ; B0
    
        xorlw    STX            ; Check for a STX            ; B0
        btfsc    STATUS,Z                            ; B0
        goto    WrDLE            ; No, continue WrNext            ; B0
    
        movf    TXDATA,W                            ; B0
        xorlw    ETX            ; Check for a ETX            ; B0
        btfsc    STATUS,Z                            ; B0
        goto    WrDLE            ; No, continue WrNext            ; B0
    
        movf    TXDATA,W                            ; B0
        xorlw    DLE            ; Check for a DLE            ; B0
        btfss    STATUS,Z                            ; B0
        goto    WrNext            ; No, continue WrNext            ; B0
    
    WrDLE
        movlw    DLE            ; Yes, send DLE first            ; B0
        call    WrRS232                                ; B0
    
    WrNext
        movf    TXDATA,W        ; Then send STX                ; DC
    
    WrRS232                                        ; B2/B0
        clrwdt                                    ; B2
        bcf    STATUS,RP1                            ; B0
        btfss    PIR1,TXIF        ; Write only if TXREG is ready        ; B0
        goto    $ - 1                                ; B0
        
        movwf    TXREG            ; Start sending                ; B0
    
        return                                    ; B0
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    RdRS232                                        ; B0
        clrwdt                                    ; B0
    
        btfsc    RCSTA,OERR        ; Reset on overun            ; B0
        goto    VReset                                ; B0
    
        btfss    PIR1,RCIF        ; Wait for data from RS232        ; B0
        goto    $ - 1                                ; B0
    
        movf    RCREG,W            ; Save the data                ; B0
        movwf    RXDATA                                ; B0
     
        return                                    ; B0
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    WaitForRise                                    ; B0
        btfsc    PORTC,7            ; Wait for a falling edge        ; B0
        goto    WaitForRise                            ; B0
        clrwdt                ;;; Do we need this?            ; B0
    WtSR    btfss    PORTC,7            ; Wait for starting edge        ; B0
        goto    WtSR                                ; B0
        return                                    ; B0
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    ; Unlock and start the write or erase sequence.
    
    StartWrite                                    ; B3
        clrwdt                                    ; B2
        bsf    STATUS,RP0                            ; B3
        movlw    0x55            ; Unlock                ; B3
        movwf    EECON2                                ; B3
        movlw    0xAA                                ; B3
        movwf    EECON2                                ; B3
        bsf    EECON1,WR        ; Start the write            ; B3
        nop                                    ; B3
        nop                                    ; B3
        bcf    STATUS,RP0                            ; B2
        return                                    ; B2
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    WriteWaitEEData                                    ; B2
        bsf    STATUS,RP0                            ; B3
        movlw    b'00000100'        ; Setup for EEData            ; B3
        movwf    EECON1                                ; B3
        call    StartWrite                            ; B3
        btfsc    EECON1,WR        ; Write and wait            ; B3
        goto    $ - 1                                ; B3
        bcf    STATUS,RP0                            ; B2
        return                                    ; B2
    ; *****************************************************************************
    
    
    ; *****************************************************************************
        ORG    0x100
    RVReset                    
    
        ORG    0x104
    RVInt
    
    ; *****************************************************************************
    
    
        END
    </etx></chksum></data></stx></stx></etx></chksum></stx></stx></etx></chksum></data></addrh></addrl></dlen></stx></stx></etx></chksum></data></addrh></addrl></dlen></stx></stx></etx></chksum></addrh></addrl></dlen></stx></stx></etx></chksum></stx></stx></etx></chksum></data></addru></addrh></addrl></dlenblock></stx></stx></etx></chksum></data></addru></addrh></addrl></dlen></stx></stx></etx></chksum></addru></addrh></addrl></dlen></stx></stx></etx></chksum></verh></verl></stx></stx></etx></stx></stx></stx></stx></etx></chksum></addru></addrh></addrl></datalen></stx></stx></data></addru></addrh></addrl></dlen></etx></chksum></data></stx></stx></stx>
    Last edited by ScaleRobotics; - 2nd March 2011 at 09:25.

  9. #9
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Thanks Walter, any help is great!

    Question is does data_packet want to be 5 bytes with data being it's own array, or do we want to keep it 1 big array (261 bytes)?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  10. #10
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Now that I am at work, I have read my PBP bible. I see we are limited to 96 bytes for an array in 16F devices, maybe less depending on the device. So I need some help here. How do we deal with this limitation?

    The most elegant thing that comes to mind is if at compile time we can determine the array size for the device we want to use, store this as a constant in the BL, then the PC side can query this value and adjust the packets accordingly.

    Short of that, I guess we either limit the max size to the biggest available in the smallest package, or have many BL's for the different PIC's. Now this is not an issue for the 18f's. Then how do we change the packet size in the GUI? - walter does this fall within the limited changes you can make?

    I assume the array size will only somewhat alter our overall loading speed. I don't feel like this will be a big issue, after all, we have to transmit ALL of the data at some point. A smaller array will just have us checking the packet header more often. - Will we really care? Must we be able to D/L the program in under 1 sec instead of 2?

    Also, I don't think it makes a lot of difference if DATA_PACKET is part of the DATA array.

    Code:
    ;         {STX}{STX}{DATA}{CHKSUM}{ETX}
    ;                   /    \
    ;           _______/      \________________________
    ;          /                                       \
    ;         {COMMAND}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...
    Last edited by cncmachineguy; - 2nd March 2011 at 13:42. Reason: Added current packet format
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  11. #11
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    Assembly normally confuses me, but I am more confused than normal. I do not see anywhere that they are changing the size of the array in the Microchip code.

    In the Tiny Bootloader assembly code, I see:
    Code:
        cblock 0x20
        buffer:80
        endc
    And that looks like an array of 80 to me. Where does Microchip set the array size for the data?

  12. #12
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    They don't. Microchip assumes 255 bytes of ram will be available to store the data in. They start at address 0x10 (command byte) then if you look at No_DLE they store the data (this all happens after comparing the byte to STX,ETX,COMMAND, and DLE. (doing this from memory, so if I left any out, sry) The MOVLF INDF command stores the byte at 0x10 + FSR. at the end of the No_DLE routine, they have INCF FSR. this is how they are incrementing the ram address. They are using indirect addressing for all of this.

    I am not sure if we have a simiular thing in PBP. Lookup does it, but that finds stuff, not store it.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  13. #13
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    Thanks Bert, that clears it up. I will check the GUI and see how they handle the data, and try to see if I can figure out what would need to be changed, if this data array is made small enough for PBP to handle easily.

    I know this is for 16F, but if we made the buffer about 50 bytes, it could be made to bootload to a 8 pin 12F1822, which would be pretty cute. I don't think it would take too much longer to program, as it would just need a quick checksum and response from the PC.

    Walter

  14. #14
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    I have run into a snag in my brain. Here is the ASM:
    Code:
    rrf    ABTIME,W                            ; B0
        btfss    STATUS,C        ; Rounding                ; B0
        addlw    0xFF
    Now I understand what it is doing, but I don't get why. The first line shifts ABTIME right 1 bit. This also clears bit 7. Because RRF rotates through the carry bit, ABTIME.0 gets put into the carry flag. So what is happening is this:
    Shift right 1 bit
    If the original (before shift) ABTIME.0=0 then add $FF to ABTIME. this seems to just clear the new ABTIME.0

    So why not just do this:
    Code:
    tempflag = ABTIME.0
    ABTIME = ABTIME >>1
    IF TEMPFLAG THEN ABTIME.0 = 0
    I guess my problem is did I evaluate what they are doing correctly?
    Last edited by ScaleRobotics; - 3rd March 2011 at 01:18.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  15. #15
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Walter, I am happy to make the data array any size we want. If smaller makes it more portable, then by all means I feel like thats the thing to do. I already think 96 is too big, just cuz PBP will want some bank 0 ram, and on the '887, I think thats the only bank big enough for 96 bytes. So we would prolly have compile errors right off!

    The question I can't answer is so far I don't see where they are switching banks to get the next block of ram. But it may be built into the inderect addressing. I have never used it before.
    Last edited by cncmachineguy; - 2nd March 2011 at 18:16.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  16. #16
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    I need to edit post 14 but can't. I have my logic reversed. If ABTIME.0=0 then add $FF.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  17. #17
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Made a little more progress, also fixed some thing in what I already had. Any questions, comments, or suggestions ask away!

    Code:
    ' *****************************************************************************
    '        Software License Agreement				    
    '		 						    
    ' The software supplied herewith by PBP forum members 	    
    ' (the “Company”) for Microchip's PICmicro® Microcontroller's is 
    ' intended and supplied to you, the Company’s customer, for use     
    ' solely and exclusively on Microchip PICmicro Microcontroller	    
    ' products. The software is owned by the Company and/or its         
    ' supplier, and is protected under applicable copyright laws. All   
    ' rights are reserved. Any use in violation of the foregoing 	     
    ' restrictions may subject the user to criminal sanctions under	    
    ' applicable laws, as well as to civil liability for the breach of  
    ' the terms and conditions of this license.			    
    '								    
    ' THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, 
    ' WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
    ' TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 	    
    ' PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
    ' IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 	    
    ' CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.		    
    '								    
    '					 			    
    ' This software has been ported from Microchip's AN851 bootloader
    ' Changes have been made and will be made as the company sees fit.
    ' This version is for 16F's, there is another version for 18F's
    '
    '
    ' Memory Map
    '	-----------------
    '	|    0x0000	|	Reset vector
    '	|        	|
    '                |   0x0004	|	Interrupt vector
    '	|    	|	
    '	|	    |
    '	|Boot Block |	(this program)
    ' 	|		    |
    '	|    0x0200	|	Re-mapped Reset Vector
    '	|    0x0204	|	Re-mapped High Priority Interrupt Vector
    '	|		    |
    '	|   	    |	
    '	|		    |
    '               |Code Space |	User program space
    '	|		    |
    '	|		    |
    '	|		    |
    '	|    0x3FFF |
    '	-----------------
    '
    ' Incomming data format:
    '
    '   {STX}{STX}{DATA}{CHKSUM}{ETX}
    '	      /    \
    '	 ________/      \__________________________
    '	/	                                         \
    '	{COMMAND}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...
    '
    ' Definitions:
    '
    ' 	STX  	-	Start of packet indicator
    '	ETX 	-	End of packet indicator
    ' 	LEN 	-	Length of incomming packet
    ' 	DATA	-	General data up to 255 bytes
    ' 	CHKSUM 	- 	The 8-bit two's compliment sum of LEN & DATA
    ' 	COMMAND - 	Base command
    ' 	DLEN	-	Length of data associated to the command
    ' 	ADDR	-	Address up to 24 bits
    ' 	DATA 	-	Data (if any)
    '
    '
    ' Commands:
    '
    ' 	RD_VER		00	Read Version Information
    ' 	RD_MEM		01	Read Program Memory
    ' 	WR_MEM		02	Write Program Memory
    ' 	ER_MEM		03	Erase Program Memory (NOT supported by PIC16)
    ' 	RD_EE		04	Read EEDATA Memory 
    ' 	WR_EE		05	Write EEDATA Memory 
    ' 	RD_CONFIG	06	Read Config Memory (NOT supported by PIC16)
    ' 	WT_CONFIG	07	Write Config Memory (NOT supported by PIC16)
    '
    ' ****************************************************************************
    
    ' *****************************************************************************
    CHKSUM		VAR	BYTE		' Checksum accumulator
    COUNTER		VAR	BYTE		' General counter
    ABTIME		VAR	BYTE
    RXDATA		VAR	BYTE
    TXDATA		VAR	BYTE
    TEMP		VAR	BYTE
    ARRAYPOINTER VAR BYTE
    
    TEMPFLAG    VAR BIT
    
    PCLATH_TEMP	VAR	BYTE		' Interrupt context
    STATUS_TEMP	VAR	BYTE		' save/restore registers
    W_TEMP		VAR	BYTE
    
    ' Frame Format
    '
    '  {STX}{STX}[{COMMAND}{DATALEN}{ADDRL}{ADDRH}{ADDRU}{...DATA...}]{CHKSUM}{ETX}
    
    DATA_BUFF	VAR	BYTE[50]		' Start of receive buffer SAME ADDRESS AS COMMAND
    	
    COMMAND		VAR	DATA_BUFF[0]		' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT	VAR	DATA_BUFF[1]
    ADDRESS_L	VAR	DATA_BUFF[2]
    ADDRESS_H	VAR	DATA_BUFF[3]
    ADDRESS_U	VAR	DATA_BUFF[4]
      'PACKET_DATA	VAR	DATA_BUFF[5-49]	'Maybe we don't need this line?**************
    ' *****************************************************************************
    
    
    '  This is the remapping section, note the interrupt also saves context
    ' *****************************************************************************
    @	ORG	0x0000			' Re-map Reset vector **Not sure how to set the address to start at
    VReset:
    	PCLATH = 0
    	goto	Setup								
    
    @	ORG	0x0004			'standard interrupt vector **again not sure of the PBP equal for ORG
    VInt:
    	W_TEMP = W			   'I am assuming this will be the "W" register			
    	STATUS_TEMP = STATUS   'We may have trouble here. ASM uses SWAP so as not to affect the status
    	STATUS = 0
    	PCLATH_TEMP = PCLATH
    	PCLATH = 0
    	goto	RVInt	    ' Re-map Interrupt vector		
    
    ' *****************************************************************************
     *****************************************************************************
    ' Setup the appropriate registers.
    Setup:
    	clrwdt
    	READ $ff,temp		         'get the value of last EEPROM location
    	IF temp = $ff then goto SRX  'BL startup
    	goto	RVReset			     ' If not 0xFF then normal reset	
    
    SRX:
    	RCSTA = %10000000		' Setup rx and tx, CREN disabled
    	TRISC.6 = 0 			' Setup tx pin		
    	TXSTA = %00100110			
    	STATUS.IRP = 1
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    Autobaud:
    '
    ' ___	 __________            ________
    '    \__/	       \__________/
    '       |                     |
    '       |-------- p ----------|
    '
    '	p = The number of instructions between the first and last
    '           rising edge of the RS232 control sequence 0x0F. Other 
    '	    possible control sequences are 0x01, 0x03, 0x07, 0x1F, 
    ' 	    0x3F, 0x7F.
    '
    '	SPBRG = (p / 32) - 1  	BRGH = 1
    										
    
    	OPTION_REG = %00000011	'sets tmr0 to 1:16 prescale
    	STATUS.RP0	= 0						
    	RCSTA.CREN = 0							
    
    	gosub	WaitForRise							
    	 
    	TMR0 = 0		     ' Start counting			
    
    	gosub	WaitForRise							
    
    	ABTIME = TMR0		 ' Read the timer		
    	TEMPFLAG = ABTIME.0
    	ABTIME = ABTIME >>1							
    	IF !TEMPFLAG THEN ABTIME.0 = 0 'Rounding	
    	SPBRG = ABTIME
    	RCSTA.CREN = 1		 ' Enable receive	
    
    	TEMP = RCREG		' To clear the Rx buffer					
    	TEMP = RCREG		' Both of them						
    						
    	OPTION_REG = %11111111 'Return Option Reg to reset state							
    							
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    ' Read and parse the data.
    StartOfLine:						
    	GOSUB	RdRS232			' Look for a start of line	
    	IF RXDATA != STX THEN Autobaud	    '{STX}{STX}				
                     		
                    ARRAYPOINTER = 0		' Point to the beginning of Array						
    
    	CHKSUM	= 0     		' Reset checksum		
    		
    GetNextDat:			
    	GOSUB	RdRS232			' Get the data			
    	IF RXDATA = STX	THEN StartOfLine    ' Check for a STX			
    	                		' Yes, start over			
    
    NoSTX:
    	IF RXDATA = ETX  THEN CheckSum    ' Check for a ETX			
    								' Yes, examine checksum		
    
    NoETX:
    	IF RXDATA = DLE THEN GOSUB RdRS232 ' Check for a DLE
    	                                   ' Yes, Get the next byte	
    	
    NoDLE:
    	DATA_BUFF[ARRAYPOINTER] = RXDATA   ' Store the data		
    	CHKSUM = CHKSUM + RXDATA           ' Get sum				
    	ARRAYPOINTER = ARRAYPOINTER + 1								
    
    	goto	GetNextDat						
    
    CheckSum:
    	IF CHKSUM = 0 THEN Autobaud  ' Checksum test					
    ' ***********************************************
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  18. #18
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Just wanted to say, I am sorry this is taking me so long to convert. It is a simple matter to just change the ASM to PBP, but I am making sure I understand everything as I convert. That way when it doesn't work, I can at least have half a chance to find the problem. Also this will make it easier when we try to start making this do different things like I2C, or have it pass the program to another uP.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  19. #19
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    Learned a little more about the Microchip bootloader GUI. It reads a P1618qp.ini file which contains information about each chip. The dropdown menu is built from this ini file. So you can add chips if you enter the right information. I tried adding a chip, and was successful in seeing it appear int the dropdown menu of the GUI.

    They have two subroutines for reading and two for writing to the code space, depending on whether it is a 16 or an 18 chip.

    Here are a couple pic definition samples of the .ini file:
    Code:
    [PIC18F67J11]
    writeblock=8
    readblock=1
    eraseblock=64
    devicetype=1
    maxpacketsize=128
    bytesperaddr=1
    pmrangelow="000400"
    pmrangehigh="01FBFF"
    eerangelow="000000"
    eerangehigh="000000"
    usrrangelow="200000"
    usrrangehigh="20000F"
    cfgrangelow="300000"
    cfgrangehigh="30000F"
    300001="CONFIG1H"            
    300002="CONFIG2L"
    300003="CONFIG2H"
    300005="CONFIG3H"
    300006="CONFIG4L"
    300008="CONFIG5L"
    300009="CONFIG5H"
    30000A="CONFIG6L"
    30000B="CONFIG6H"
    30000C="CONFIG7L"
    30000D="CONFIG7H"
    
    
    
    [PIC16F877]
    writeblock=8
    readblock=2
    devicetype=0
    maxpacketsize=32
    bytesperaddr=2
    pmrangelow="000200"
    pmrangehigh="001FFF"
    eerangelow="000000"
    eerangehigh="0000FF"
    And for the 18F devices, they have a menu that lets you configure the fuses. But it looks like you have to enter the value for them. Would be nice to make it read from the device file C:\Program Files\Microchip\MPLAB IDE\Device and populate the dropdown list. But that would definitely be down the road, because now I am having trouble seeing where they size the data field!

    I do see a:
    Code:
            'limit the packet size
            If (AddrH + 1) - BootAddr > PicBootS.MaxPacketSize Then
                picA.BootDatLen = PicBootS.MaxPacketSize
            Else
                picA.BootDatLen = (AddrH + 1) - BootAddr
            End If
    But I am having trouble figuring out where they use it. Might take a couple cups of coffee ... or more.

  20. #20
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    So if I understand this, for the 16f877 it says MAXPACKETSIZE=32. So thats how big the arreay should be for DATA_BUFF? I put in 50 for now, but can clearly make that 32. I think as a down the road desire, this value should be a variable that will get set at compile time or maybe the GUI can tell the PIC.

    Good stuff Walter!!
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  21. #21
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    Might be too early to say this, but it looks like it already does pull it from the ini file, and "tell" the pic. (I just don't see where it tells it yet) One of the parts that confuses me is that all I see is 32 as the maxdatasize for pic16, and 128 for what I think are all PIC18's. So where does 255 come in?

    I have a lot more work to do.

  22. #22
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Don't quote me on this just yet, but I think the 18's use a word for the data, so then it would make sense. Also for the ASM program they can get away with just letting it be whatever size because the compiler doesn't care if its too big. No such luck with PBP.
    Last edited by cncmachineguy; - 3rd March 2011 at 15:34.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  23. #23
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Re: Open source PBP bootloader

    Quote Originally Posted by cncmachineguy View Post
    Don't quote me on this just yet, but I think the 18's use a word for the data, so then it would make sense.
    Oops, just quoted you .....

    If that is true, then we should be good with the standard 32 bytes (if it is in bytes for 16F's) of data, then adding the 5 bytes for:
    Code:
    DATA_BUFF   VAR BYTE[37]        ' Start of receive buffer SAME ADDRESS AS COMMAND
    COMMAND     VAR DATA_BUFF[0]    ' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE 
    DATA_COUNT1 VAR DATA_BUFF[1]     
    ADDRESS_L   VAR DATA_BUFF[2] 
    ADDRESS_H   VAR DATA_BUFF[3] 
    ADDRESS_U   VAR DATA_BUFF[4]
    PACKET_DATA VAR DATA_BUFF[5-36]    'THIS SHOULD BE AN ARRAY I THINK**************
    would be 37 bytes for 12F and 16F devices, leaving more room for variables in case we want more PBP bells and whistles later. Then for the 18F's, they all use the 128 words (maybe).
    Last edited by ScaleRobotics; - 3rd March 2011 at 16:56.

  24. #24
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Newest update, includes Walter's last post regarding Array size. I have to stop here to think about what I am doing. I DON'T like the Read Program Memory at the end. I think it will work as is, but it really looks like ASM to me. I think I need to utilize the READCODE command, just not sure yet how to deal with the address and data. I assume maybe the address needs to be a word, comprised of EEADRH,EEADR. Then I guess the data is also a word. then I guess I just add 2 to the ARRAYPOINTER?

    IF anyone wants to chime in on this, now is a good time

    As a side note, IF anyone wants to help with this conversion, clearly I am working from the top down. If someone were to work from the bottom up, It would be easy for me to add it to what I have. Then when we meet in the middle, we will be done. No Biggie either way.

    ANY testers out there? Still looking for some. I will be able to test compile, but don't feel comfy trying to test the code as I have never used a bootloader so I won't know if problems are with my setup or the code.

    Code:
    ' *****************************************************************************
    '        Software License Agreement                    
    '                                     
    ' The software supplied herewith by PBP forum members         
    ' (the “Company”) for Microchip's PICmicro® Microcontroller's is 
    ' intended and supplied to you, the Company’s customer, for use     
    ' solely and exclusively on Microchip PICmicro Microcontroller        
    ' products. The software is owned by the Company and/or its         
    ' supplier, and is protected under applicable copyright laws. All   
    ' rights are reserved. Any use in violation of the foregoing          
    ' restrictions may subject the user to criminal sanctions under        
    ' applicable laws, as well as to civil liability for the breach of  
    ' the terms and conditions of this license.                
    '                                    
    ' THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, 
    ' WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
    ' TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A         
    ' PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
    ' IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR         
    ' CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.            
    '                                    
    '                                     
    ' This software has been ported from Microchip's AN851 bootloader
    ' Changes have been made and will be made as the company sees fit.
    ' This version is for 16F's, there is another version for 18F's
    '
    '
    ' Memory Map
    '    -----------------
    '    |    0x0000    |    Reset vector
    '    |            |
    '   |    0x0004    |    Interrupt vector
    '    |            |    
    '    |            |
    '    |Boot Block |    (this program)
    '     |            |
    '    |    0x0200    |    Re-mapped Reset Vector
    '    |    0x0204    |    Re-mapped High Priority Interrupt Vector
    '    |            |
    '    |           |    
    '    |            |
    '   |Code Space |    User program space
    '    |            |
    '    |            |
    '    |            |
    '    |    0x3FFF |
    '    -----------------
    '
    ' Incomming data format:
    '
    '   {STX}{STX}{DATA}{CHKSUM}{ETX}
    '              /    \
    '     ________/      \____________________________
    '    /                                             \
    '    {COMMAND}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...
    '
    ' Definitions:
    '
    '     STX      -    Start of packet indicator
    '    ETX     -    End of packet indicator
    '     LEN     -    Length of incomming packet
    '     DATA    -    General data up to 255 bytes
    '     CHKSUM     -     The 8-bit two's compliment sum of LEN & DATA
    '     COMMAND -     Base command
    '     DLEN    -    Length of data associated to the command
    '     ADDR    -    Address up to 24 bits
    '     DATA     -    Data (if any)
    '
    '
    ' Commands:
    '
    '     RD_VER        00    Read Version Information
    '     RD_MEM        01    Read Program Memory
    '     WR_MEM        02    Write Program Memory
    '     ER_MEM        03    Erase Program Memory (NOT supported by PIC16)
    '     RD_EE        04    Read EEDATA Memory 
    '     WR_EE        05    Write EEDATA Memory 
    '     RD_CONFIG    06    Read Config Memory (NOT supported by PIC16)
    '     WT_CONFIG    07    Write Config Memory (NOT supported by PIC16)
    '
    ' ****************************************************************************
    
    ' *****************************************************************************
    CHKSUM        VAR    BYTE        ' Checksum accumulator
    COUNTER        VAR    BYTE        ' General counter
    ABTIME        VAR    BYTE
    RXDATA        VAR    BYTE
    TXDATA        VAR    BYTE
    TEMP        VAR    BYTE
    ARRAYPOINTER VAR BYTE
    FAKEW        VAR BYTE
    
    TEMPFLAG    VAR BIT
    
    PCLATH_TEMP    VAR    BYTE        ' Interrupt context
    STATUS_TEMP    VAR    BYTE        ' save/restore registers
    W_TEMP        VAR    BYTE
    
    ' Frame Format
    '
    '  {STX}{STX}[{COMMAND}{DATALEN}{ADDRL}{ADDRH}{ADDRU}{...DATA...}]{CHKSUM}{ETX}
    
    DATA_BUFF    VAR    BYTE[37]        ' Start of receive buffer SAME ADDRESS AS COMMAND
        
    COMMAND        VAR    DATA_BUFF[0]        ' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT    VAR    DATA_BUFF[1]
    ADDRESS_L    VAR    DATA_BUFF[2]
    ADDRESS_H    VAR    DATA_BUFF[3]
    ADDRESS_U    VAR    DATA_BUFF[4]
    PACKET_DATA    VAR    DATA_BUFF[5]    'Is this Valid? It is now!
    ' *****************************************************************************
    
    
    '  This is the remapping section, note the interrupt also saves context
    ' *****************************************************************************
    @    ORG    0x0000            ' Re-map Reset vector **Not sure how to set the address to start at
    VReset:
        PCLATH = 0
        goto    Setup                                
    
    @    ORG    0x0004            'standard interrupt vector **again not sure of the PBP equal for ORG
    VInt:
        W_TEMP = W               'I am assuming this will be the "W" register            
        STATUS_TEMP = STATUS   'We may have trouble here. ASM uses SWAP so as not to affect the status
        STATUS = 0
        PCLATH_TEMP = PCLATH
        PCLATH = 0
        goto    RVInt        ' Re-map Interrupt vector        
    
    ' *****************************************************************************
     *****************************************************************************
    ' Setup the appropriate registers.
    Setup:
        clrwdt
        READ $ff,temp                 'get the value of last EEPROM location
        IF temp = $ff then goto SRX  'BL startup
        goto    RVReset                 ' If not 0xFF then normal reset    
    
    SRX:
        RCSTA = %10000000        ' Setup rx and tx, CREN disabled
        TRISC.6 = 0             ' Setup tx pin        
        TXSTA = %00100110            
        STATUS.IRP = 1
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    Autobaud:
    '
    ' ___     __________            ________
    '    \__/           \__________/
    '       |                     |
    '       |-------- p ----------|
    '
    '    p = The number of instructions between the first and last
    '           rising edge of the RS232 control sequence 0x0F. Other 
    '        possible control sequences are 0x01, 0x03, 0x07, 0x1F, 
    '         0x3F, 0x7F.
    '
    '    SPBRG = (p / 32) - 1      BRGH = 1
                                            
    
        OPTION_REG = %00000011    'sets tmr0 to 1:16 prescale
        STATUS.RP0    = 0                        
        RCSTA.CREN = 0                            
    
        gosub    WaitForRise                            
         
        TMR0 = 0             ' Start counting            
    
        gosub    WaitForRise                            
    
        ABTIME = TMR0         ' Read the timer        
        TEMPFLAG = ABTIME.0
        ABTIME = ABTIME }}1                            
        IF !TEMPFLAG THEN ABTIME.0 = 0 'Rounding    
        SPBRG = ABTIME
        RCSTA.CREN = 1         ' Enable receive    
    
        TEMP = RCREG        ' To clear the Rx buffer                    
        TEMP = RCREG        ' Both of them                        
                            
        OPTION_REG = %11111111 'Return Option Reg to reset state                            
                                
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    ' Read and parse the data.
    StartOfLine:                        
        GOSUB    RdRS232            ' Look for a start of line    
        IF RXDATA != STX THEN Autobaud        '{STX}{STX}                
                             
        ARRAYPOINTER = 0        ' Point to the beginning of Array                        
    
        CHKSUM    = 0             ' Reset checksum        
            
    GetNextDat:            
        GOSUB    RdRS232            ' Get the data            
        IF RXDATA = STX    THEN StartOfLine    ' Check for a STX            
                                ' Yes, start over            
    
    NoSTX:
        IF RXDATA = ETX THEN CheckSum    ' Check for a ETX            
                                    ' Yes, examine checksum        
    
    NoETX:
        IF RXDATA = DLE THEN GOSUB RdRS232 ' Check for a DLE
                                           ' Yes, Get the next byte    
        
    NoDLE:
        DATA_BUFF[ARRAYPOINTER] = RXDATA   ' Store the data        
        CHKSUM = CHKSUM + RXDATA           ' Get sum                
        ARRAYPOINTER = ARRAYPOINTER + 1                                
    
        goto    GetNextDat                        
    
    CheckSum:
        IF CHKSUM = 0 THEN Autobaud  ' Checksum test                    
    ' ***********************************************
    
    
    ' ***********************************************
    ' Pre-setup, common to all commands.                                    
        EEADR = ADDRESS_L        'Set all possible pointers                                
        EEADRH = ADDRESS_H                                                        
    
        ARRAYPOINTER = 5        'start of data in array                            
    
        COUNTER = DATA_COUNT     'Setup counter                                        
        IF COUNTER = 0 THEN VReset    'Non valid count (Special Command)    
    ' ***********************************************
    
    ' ***********************************************
    ' Test the command field and sub-command.                    
    CheckCommand
        IF COMMAND } 7 THEN Autobaud ' Test for a valid command                                    
        SELECT CASE COMMAND          ' Perform calculated jump        
            CASE 0
                goto    ReadVersion        ' 0                    
            CASE 1
                goto    ReadProgMem        ' 1                    
            CASE 2
                goto    WriteProgMem    ' 2                    
            CASE 3
                goto    StartOfLine        ' 3                    
            CASE 4
                goto    ReadEE            ' 4                    
            CASE 5
                goto    WriteEE            ' 5                    
            CASE 6
                goto    StartOfLine        ' 6                    
            CASE 7
                goto    StartOfLine        ' 7                    
        'maybe add jump to reset vector in this table
    '***********************************************
    
    
    
    ' ***********************************************
    ' Commands
    ' ************* Read Version
    ' In:    {STX}{STX}[{0x00}{0x02}]{0xFF}{ETX}
    ' OUT:    {STX}{STX}[{0x00}{VERL}{VERH}]{CHKSUM}{ETX}
    ReadVersion:                                
        DATA_BUFF[2] = MINOR_VERSION                                                        
        DATA_BUFF[3] = MAJOR_VERSION                                                        
    
        FAKEW = 4                                
        goto    WritePacket                            
    
    '*************Read Program Memory
        
    ' In:    {STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}]{CHKSUM}{ETX}
    ' OUT:    {STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...]{CHKSUM}{ETX} 
    ReadProgMem:                                
    RPM1:                                
        EECON1.EEPGD = 1                        
        EECON1.RD = 1                        
        @nop                'not sure how to convert this to PBP                    
        @nop                                                                
        DATA_BUFF[ARRAYPOINTER] = EEDATA                            
        ARRAYPOINTER = ARRAYPOINTER + 1                                
        DATA_BUFF[ARRAYPOINTER] = EEDATH                            
        ARRAYPOINTER = ARRAYPOINTER + 1                                
        EEADR = EEADR + 1
        IF EEADR = 0 then                            
           EEADRH = EEADRH + 1                            
        ENDIF
        COUNTER = COUNTER - 1                            
        IF COUNTER > 0 THEN RPM1            ' Not finished then repeat    
    
        DATA_COUNT = (DATA_COUNT << 1) + 5    ' Setup packet length        
                        
        goto    WritePacket                        
    
    '************* Write Program Memory
    Last edited by ScaleRobotics; - 4th March 2011 at 17:21. Reason: declared PACKET_DATA to [5]
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  25. #25
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default Oops

    Sorry my earlier post won't work that way, PBP takes 5-36 as subtraction. Probably the closest to the assembly example like this. Then you could specify the address in assembly if need be in a similar PACKET_DATA + x manner. I took the liberty of editing your previous post with that one change. [5-36] to [5]

    Code:
    DATA_BUFF   VAR BYTE[37]        ' Start of receive buffer SAME ADDRESS AS COMMAND
        
    COMMAND     VAR DATA_BUFF[0]    ' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT1 VAR DATA_BUFF[1]    
    ADDRESS_L   VAR DATA_BUFF[2]
    ADDRESS_H   VAR DATA_BUFF[3]
    ADDRESS_U   VAR DATA_BUFF[4]
    PACKET_DATA VAR DATA_BUFF[5]    ' DATA_BUFF[5] through DATA_BUFF[36] (32 bytes)
    Last edited by ScaleRobotics; - 4th March 2011 at 17:35.

  26. #26
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Here is the final installment. I feel like there must be MANY errors, but maybe not. I have not tried to compile yet, I thought maybe you kind folks might give it a look over for glaring errors.
    Code:
    ' *****************************************************************************
    '        Software License Agreement				    
    '		 						    
    ' The software supplied herewith by PBP forum members 	    
    ' (the “Company”) for Microchip's PICmicro® Microcontroller's is 
    ' intended and supplied to you, the Company’s customer, for use     
    ' solely and exclusively on Microchip PICmicro Microcontroller	    
    ' products. The software is owned by the Company and/or its         
    ' supplier, and is protected under applicable copyright laws. All   
    ' rights are reserved. Any use in violation of the foregoing 	     
    ' restrictions may subject the user to criminal sanctions under	    
    ' applicable laws, as well as to civil liability for the breach of  
    ' the terms and conditions of this license.			    
    '								    
    ' THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, 
    ' WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
    ' TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 	    
    ' PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
    ' IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 	    
    ' CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.		    
    '								    
    '					 			    
    ' This software has been ported from Microchip's AN851 bootloader
    ' Changes have been made and will be made as the company sees fit.
    ' This version is for 16F's, there is another version for 18F's
    '
    '
    ' Memory Map
    '	-----------------
    '	|    0x0000	|	Reset vector
    '	|        	|
    '   |    0x0004	|	Interrupt vector
    '	|    		|	
    '	|		    |
    '	|Boot Block |	(this program)
    ' 	|		    |
    '	|    0x0200	|	Re-mapped Reset Vector
    '	|    0x0204	|	Re-mapped High Priority Interrupt Vector
    '	|		    |
    '	|   	    |	
    '	|		    |
    '   |Code Space |	User program space
    '	|		    |
    '	|		    |
    '	|		    |
    '	|    0x3FFF |
    '	-----------------
    '
    ' Incomming data format:
    '
    '   {STX}{STX}{DATA}{CHKSUM}{ETX}
    '		      /    \
    '	 ________/      \____________________________
    '	/	                                         \
    '	{COMMAND}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...
    '
    ' Definitions:
    '
    ' 	STX  	-	Start of packet indicator
    '	ETX 	-	End of packet indicator
    ' 	LEN 	-	Length of incomming packet
    ' 	DATA	-	General data up to 255 bytes
    ' 	CHKSUM 	- 	The 8-bit two's compliment sum of LEN & DATA
    ' 	COMMAND - 	Base command
    ' 	DLEN	-	Length of data associated to the command
    ' 	ADDR	-	Address up to 24 bits
    ' 	DATA 	-	Data (if any)
    '
    '
    ' Commands:
    '
    ' 	RD_VER		00	Read Version Information
    ' 	RD_MEM		01	Read Program Memory
    ' 	WR_MEM		02	Write Program Memory
    ' 	ER_MEM		03	Erase Program Memory (NOT supported by PIC16)
    ' 	RD_EE		04	Read EEDATA Memory 
    ' 	WR_EE		05	Write EEDATA Memory 
    ' 	RD_CONFIG	06	Read Config Memory (NOT supported by PIC16)
    ' 	WT_CONFIG	07	Write Config Memory (NOT supported by PIC16)
    '
    ' ****************************************************************************
    
    ' *****************************************************************************
    PRGADD		VAR WORD
    DATAWORD    VAR WORD
    
    PRGADDL		VAR PRGADD.LOWBYTE
    PRGADDH		VAR PRGADD.HIGHBYTE
    DATAWORDL	VAR DATAWORD.LOWBYTE
    DATAWORDH	VAR DATAWORD.HIGHBYTE
    
    CHKSUM		VAR	BYTE		' Checksum accumulator
    COUNTER		VAR	BYTE		' General counter
    ABTIME		VAR	BYTE
    RXDATA		VAR	BYTE
    TXDATA		VAR	BYTE
    TEMP		VAR	BYTE
    ARRAYPOINTER VAR BYTE
    FAKEW		VAR BYTE
    BIGLOOP 	VAR BYTE
    TEMPFLAG    VAR BIT
    
    PCLATH_TEMP	VAR	BYTE		' Interrupt context
    STATUS_TEMP	VAR	BYTE		' save/restore registers
    W_TEMP		VAR	BYTE
    
    ' Frame Format
    '
    '  {STX}{STX}[{COMMAND}{DATALEN}{ADDRL}{ADDRH}{ADDRU}{...DATA...}]{CHKSUM}{ETX}
    
    DATA_BUFF	VAR	BYTE[37]		' Start of receive buffer SAME ADDRESS AS COMMAND
    	
    COMMAND		VAR	DATA_BUFF[0]		' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE
    DATA_COUNT	VAR	DATA_BUFF[1]
    ADDRESS_L	VAR	DATA_BUFF[2]
    ADDRESS_H	VAR	DATA_BUFF[3]
    ADDRESS_U	VAR	DATA_BUFF[4]
    PACKET_DATA	VAR	DATA_BUFF[5]	
    ' *****************************************************************************
    
    
    '  This is the remapping section, note the interrupt also saves context
    ' *****************************************************************************
    @	ORG	0x0000			' Re-map Reset vector **Not sure how to set the address to start at
    VReset:
    	PCLATH = 0
    	goto	Setup								
    
    @	ORG	0x0004			'standard interrupt vector **again not sure of the PBP equal for ORG
    VInt:
    	W_TEMP = W			   'I am assuming this will be the "W" register			
    	STATUS_TEMP = STATUS   'We may have trouble here. ASM uses SWAP so as not to affect the status
    	STATUS = 0
    	PCLATH_TEMP = PCLATH
    	PCLATH = 0
    	goto	RVInt	    ' Re-map Interrupt vector		
    
    ' *****************************************************************************
     *****************************************************************************
    ' Setup the appropriate registers.
    Setup:
    	clrwdt
    	READ $ff,temp		         'get the value of last EEPROM location
    	IF temp = $ff then goto SRX  'BL startup
    	goto	RVReset			     ' If not 0xFF then normal reset	
    
    SRX:
    	RCSTA = %10000000		' Setup rx and tx, CREN disabled
    	TRISC.6 = 0 			' Setup tx pin		
    	TXSTA = %00100110			
    	STATUS.IRP = 1
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    Autobaud:
    '
    ' ___	 __________            ________
    '    \__/	       \__________/
    '       |                     |
    '       |-------- p ----------|
    '
    '	p = The number of instructions between the first and last
    '           rising edge of the RS232 control sequence 0x0F. Other 
    '	    possible control sequences are 0x01, 0x03, 0x07, 0x1F, 
    ' 	    0x3F, 0x7F.
    '
    '	SPBRG = (p / 32) - 1  	BRGH = 1
    										
    
    	OPTION_REG = %00000011	'sets tmr0 to 1:16 prescale
    	STATUS.RP0	= 0						
    	RCSTA.CREN = 0							
    
    	gosub	WaitForRise							
    	 
    	TMR0 = 0		     ' Start counting			
    
    	gosub	WaitForRise							
    
    	ABTIME = TMR0		 ' Read the timer		
    	TEMPFLAG = ABTIME.0
    	ABTIME = ABTIME >> 1							
    	IF !TEMPFLAG THEN ABTIME.0 = 0 'Rounding	
    	SPBRG = ABTIME
    	RCSTA.CREN = 1		 ' Enable receive	
    
    	TEMP = RCREG		' To clear the Rx buffer					
    	TEMP = RCREG		' Both of them						
    						
    	OPTION_REG = %11111111 'Return Option Reg to reset state							
    							
    ' *****************************************************************************
    
    
    ' *****************************************************************************
    ' Read and parse the data.
    StartOfLine:						
    	GOSUB	RdRS232			' Look for a start of line	
    	IF RXDATA != STX THEN Autobaud	    '{STX}{STX}				
                     		
        ARRAYPOINTER = 0		' Point to the beginning of Array						
    
    	CHKSUM	= 0     		' Reset checksum		
    		
    GetNextDat:			
    	GOSUB	RdRS232			' Get the data			
    	IF RXDATA = STX	THEN StartOfLine    ' Check for a STX			
    	                		' Yes, start over			
    
    NoSTX:
    	IF RXDATA = ETX THEN CheckSum    ' Check for a ETX			
    								' Yes, examine checksum		
    
    NoETX:
    	IF RXDATA = DLE THEN GOSUB RdRS232 ' Check for a DLE
    	                                   ' Yes, Get the next byte	
    	
    NoDLE:
    	DATA_BUFF[ARRAYPOINTER] = RXDATA   ' Store the data		
    	CHKSUM = CHKSUM + RXDATA           ' Get sum				
    	ARRAYPOINTER = ARRAYPOINTER + 1								
    
    	goto	GetNextDat						
    
    CheckSum:
    	IF CHKSUM = 0 THEN Autobaud  ' Checksum test					
    ' ***********************************************
    
    
    ' ***********************************************
    ' Pre-setup, common to all commands.									
    	PRGADDL = ADDRESS_L		'Set all possible pointers								
    	PRGADDH = ADDRESS_H														
    
    	ARRAYPOINTER = 5        'start of data in array							
    
    	COUNTER = DATA_COUNT 	'Setup counter										
    	IF COUNTER = 0 THEN VReset	'Non valid count (Special Command)	
    ' ***********************************************
    
    ' ***********************************************
    ' Test the command field and sub-command.					
    CheckCommand
    	IF COMMAND } 7 THEN Autobaud ' Test for a valid command									
    	SELECT CASE COMMAND          ' Perform calculated jump		
    		CASE 0
    			goto	ReadVersion		' 0					
    		CASE 1
    			goto	ReadProgMem		' 1					
    		CASE 2
    			goto	WriteProgMem	' 2					
    		CASE 3
    			goto	StartOfLine		' 3					
    		CASE 4
    			goto	ReadEE			' 4					
    		CASE 5
    			goto	WriteEE			' 5					
    		CASE 6
    			goto	StartOfLine		' 6					
    		CASE 7
    			goto	StartOfLine		' 7					
    	'maybe add jump to reset vector in this table
    '***********************************************
    
    
    
    ' ***********************************************
    ' Commands
    ' ************* Read Version
    ' In:	{STX}{STX}[{0x00}{0x02}]{0xFF}{ETX}
    ' OUT:	{STX}{STX}[{0x00}{VERL}{VERH}]{CHKSUM}{ETX}
    ReadVersion:								
    	DATA_BUFF[2] = MINOR_VERSION														
    	DATA_BUFF[3] = MAJOR_VERSION														
    
    	FAKEW = 4								
    	goto	WritePacket							
    
    '*************Read Program Memory
    	
    ' In:	{STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}]{CHKSUM}{ETX}
    ' OUT:	{STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...]{CHKSUM}{ETX} 
    ReadProgMem:								
    RPM1:
    	READCODE PRGADD,DATAWORD
    													
    	DATA_BUFF[ARRAYPOINTER] = DATAWORDL							
    	DATA_BUFF[ARRAYPOINTER + 1] = DATAWORDH							
    	ARRAYPOINTER = ARRAYPOINTER + 2								
    	PRGADD = PRGADD + 1
    
    	COUNTER = COUNTER - 1							
    	IF COUNTER } 0 THEN RPM1			' Not finished then repeat	
    
    	DATA_COUNT = (DATA_COUNT << 1) + 5	' Setup packet length		
    					
    	goto	WritePacket						
    
    '************* Write Program Memory
    
    
    ' In:	{STX}{STX}[{0x02}{DLENBLOCK}{ADDRL}{ADDRH}{ADDRU}{DATA}...]{CHKSUM}{ETX}
    ' OUT:	{STX}{STX}[{0x02}]{CHKSUM}{ETX}
    WriteProgMem:	
    	FOR BIGLOOP = COUNTER TO 0 STEP -1
    		EECON1 = %10000100				' Setup writes				
    		EEADR = EEADR & %11111100		' Force a boundry			' B2
    		FOR TEMP = 1 TO 4
    			WRITECODE PRGADD,DATAWORD[ARRAYPOINTER]
    			ARRAYPOINTER = ARRAYPOINTER + 2
    		NEXT 
    	
    	NEXT
    	goto	SendAcknowledge				' Send acknowledge			
    
    '************** Read EE
    
    
    ' In:	{STX}{STX}[{0x04}{DLEN}{ADDRL}{ADDRH}{0x00}]{CHKSUM}{ETX}
    ' OUT:	{STX}{STX}[{0x04}{DLEN}{ADDRL}{ADDRH}{0x00}{DATA}...]{CHKSUM}{ETX}
    ReadEE:			
    	FOR BIGLOOP = COUNTER TO 0 STEP -1
    		READ PRGADD,DATA_BUFF[ARRAYPOINTER]
    		ARRAYPOINTER = ARRAYPOINTER + 1
    		PRGADD = PRGADD + 1
    	NEXT
    	
    	FAKEW = DATA_COUNT + 5
    	GOTO WritePacket
    
    
    ' In:	<STX><STX>[<0x05><DLEN><ADDRL><ADDRH><0x00><DATA>...]<CHKSUM><ETX>
    ' OUT:	<STX><STX>[<0x05>]<CHKSUM><ETX>
    WriteEE:
    	FOR BIGLOOP = 0 TO COUNTER
    		WRITE PRGADD + BIGLOOP,DATA_BUFF[ARRAYPOINTER+BIGLOOP]
    	NEXT
    	goto	SendAcknowledge		; Send acknowledge			
    	
    ' ***********************************************
    
    ' ***********************************************
    ' Send the data buffer back.
    '
    ' {STX}{STX}[{DATA}...]{CHKSUM}{ETX}
    
    SendAcknowledge:								
    	FAKEW = 1			' Send acknowledge		
    	
    WritePacket:
    	COUNTER = FAKEW	
    
    	FAKEW = STX			' Send start condition	
    	GOSUB	WrRS232								
    	GOSUB	WrRS232								
    
    	CHKSUM = 0			' Reset checksum	
    	ARRAYPOINTER = 0
    	
    SendNext:				' Send DATA
    	FOR BIGLOOP = 1 TO COUNTER
    		FAKEW = DATA_BUFF[ARRAYPOINTER]
    		CHKSUM = CHKSUM + FAKEW 
    		GOSUB	WrData				
    	NEXT
    
    '********************************************
    	comf	CHKSUM,W		' Send checksum		
    	addlw	0x01	   ' NEEDS CONVERTING!!!!!
    '***********************************************	
    	GOSUB	WrData								
    
    	FAKEW =	ETX			' Send stop condition	
    	GOSUB	WrRS232								
    
    	goto	Autobaud							
    ' *****************************************************************************
    
    ' *****************************************************************************
    ' Write a byte to the serial port.
    
    WrData:										
    	TXDATA = FAKEW			' Save the data			
    	IF FAKEW = STX THEN WrDLE
    	IF FAKEW = ETX THEN WrDLE
    	IF FAKEW != DLE THEN WrNext
    	
    WrDLE:
    	GOSUB	WrRS232		'Send DLE					
    
    WrNext:
    	FAKEW =	TXDATA	' Then send DATA				
    
    WrRS232:										
    	clrwdt									
    	WHILE !PIR1.TXIF WEND ' Write only if TXREG is ready		
    
    	TXREG = FAKEW			' Start sending				
    
    	return									
    ' *****************************************************************************
    
    
    
    ' *****************************************************************************
    RdRS232:			
    	clrwdt
    
    	IF RCSTA.OERR THEN VReset		' Reset on overun	
    
    	WHILE !PIR1.RCIF WEND	' Wait for data from RS232
    	
    
    	RXDATA = RCREG		' Save the data		
    	return									
    ' *****************************************************************************
    
    
    
    
    ' *****************************************************************************
    WaitForRise:
    	WHILE PORTC.7 WEND   ' Wait for a falling edge	
    	clrwdt				 ' Do we need this?
    	WHILE !PORTC.7 WEND	 ' Wait for starting edge	
    	return				
    ' *****************************************************************************
    
    ' I DON'T THINK WE NEED THE NEXT 2 SECTIONS
    ' CAN ANYBODY TELL ME?
    
    
    ' *****************************************************************************
    ' Unlock and start the write or erase sequence.
    
    StartWrite									; B3
    	clrwdt									; B2
    	bsf	STATUS,RP0							; B3
    	movlw	0x55			; Unlock				; B3
    	movwf	EECON2								; B3
    	movlw	0xAA								; B3
    	movwf	EECON2								; B3
    	bsf	EECON1,WR		; Start the write			; B3
    	nop									; B3
    	nop									; B3
    	bcf	STATUS,RP0							; B2
    	return									; B2
    ; *****************************************************************************
    
    
    
    
    ; *****************************************************************************
    WriteWaitEEData									; B2
    	bsf	STATUS,RP0							; B3
    	movlw	b'00000100'		; Setup for EEData			; B3
    	movwf	EECON1								; B3
    	call	StartWrite							; B3
    	btfsc	EECON1,WR		; Write and wait			; B3
    	goto	$ - 1								; B3
    	bcf	STATUS,RP0							; B2
    	return									; B2
    ; *****************************************************************************
    
    
    ; *****************************************************************************
    RVReset:
    	@ORG	0x100
    					
    RVInt:
    	@ORG	0x104
    
    
    ; *****************************************************************************
    
    
    	END
    Attached Files Attached Files
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  27. #27
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    This one compiles up to MPASM part, then PLENTY of overwrite errors.


    BTW, is it odd we can't attach .PBP files?
    Attached Files Attached Files
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  28. #28
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default Re: Open source PBP bootloader

    Hint: ASM ORG & PBP (see mostcompilers) are poor bedfellows when you don't know why and how they interract.

    Plausible solution, compile without ORG, use the HEX to get the ASM code, then add some ORG & GOTO, recompile the asm and try to make it work

    Still Plausible: Hack a .LIB and or .INC to use Labels in your Bootloader code instead of ORG.

    Lots of possibilities, my favourites being 100% pure ASM.
    Last edited by mister_e; - 6th March 2011 at 21:17.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  29. #29
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    Quote Originally Posted by mister_e View Post
    Hint: ASM ORG & PBP (see mostcompilers) are poor bedfellows when you don't know why and how they interract.
    Well I must admit not knowing. I know it makes no sense to use it in this way, I know PBP won't be paying attention to it, therefore probable conflicts will arrise.
    Plausible solution, compile without ORG, use the HEX to get the ASM code, then add some ORG & GOTO, recompile the asm and try to make it work
    This sounds like a quick fix not in line with the intention of this project.
    Still Plausible: Hack a .LIB and or .INC to use Labels in your Bootloader code instead of ORG.
    If we can have the hack as part of the "package" maybe. Right now it seems more then too much to ask folks to rem out config lines

    Lots of possibilities, my favourites being 100% pure ASM.
    we already have that. The purpose here is to try and make a PBP bootloader, for all to use and abuse.

    Thanks for pointing in the direction of the first of many (maybe) problems. I feel like I saw something in the PBP bible about defining code locations, but it is at work
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  30. #30
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default Re: Open source PBP bootloader

    Well, there's an easy alternative. Compile your bootloader without ORG, see how much code space it needs. Once you know it, add an ORG at the END of your bootloader + Label. Your bootloader must jump to this Label when it exit.

    Code:
    'bootloader code here
    Goto GetOutOfHere
    
    @ ORG WhateverYouDecide 
    GetOutOfHere:
    Now when you want to use the bootloader, in your application code you need to use DEFINE RESET_ORG... and Period.

    Code:
    DEFINE RESET_ORG WhateverYouDecide
    ' and your application code goes there
    Now go figure how interrupt will work and how to integrate it, have fun!
    http://www.picbasic.co.uk/forum/show...1662#post31662

    Readme.txt:
    ORG Define

    It may sometimes be useful to move the start of the generated code to a
    location other than 0. This can be used to move the program code beyond
    a boot loader, for example. A Define has been added to the compiler to
    allow a different reset address to be specified for the 14-bit core PIC
    MCUs and the PIC18 parts.

    Define RESET_ORG 100h

    This Define moves the starting location of the program, the reset vector,
    to the specified address. The interrupt vector(s) follow at their usual
    offset, followed by the library and program code.

    For 14-bit core devices with more than 2K of code space, only interrupts
    in assembler may be used. On Interrupt will not work properly if the
    device has more than 2K of code space and RESET_ORG is not 0. For
    assembler interrupts in a device with more than 2K of code space and
    RESET_ORG something other than 0, the values of W, STATUS and PCLATH must
    be saved by whatever program now resides at the PIC MCU's fixed vector
    locations before the jump to the new vector location. In general, the
    save locations are named wsave, ssave and psave. The information on these
    save locations should be provided with the boot loader or whatever program
    requires the altered origination so that the register values may be restored
    at the end of interrupt processing.

    For 14-bit enhanced core devices with more than 2K of code space,
    On Interrupt may be used but the values of W, STATUS and PCLATH must not be
    changed to get to the interrupt vector as they will not be restored upon
    return from the interrupt. This usually means bra will be used to jump to
    the new interrupt vector location. Interrupts in assembler do not require
    any special treatment.

    Either 14-bit core PBP library must fit into the first 2K of code space.
    The PIC18 PBP library must fit into the first 32K of code space. It is best
    for RESET_ORG to start on an even 256 word boundary.
    Last edited by mister_e; - 7th March 2011 at 04:05. Reason: link
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  31. #31
    Join Date
    Jan 2006
    Location
    Toronto
    Posts
    109

    Default Re: Open source PBP bootloader

    Are you just converting the exsisting serial bootloader over to PBP? I had thought you were going to make a new bootloader from scratch in pure PBP.

  32. #32
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    The goal is a new one using pure PBP. To get me started, I am attempting to convert the existing Microchip serial one, AN851. For me this does 2 things, it has shown me just how the guts of the BL work, and I thought by starting there, we are able to test the GUI with it.

    To that end, I do have a much better feel for how they work, at least this one. So we can make this work and build onto it, or start over with a completly new one. No matter to me
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  33. #33
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869

    Default Re: Open source PBP bootloader

    If you want to get the code to compile, rem the first 2 @org's. change the last to to 800 and 808. These need to be changed anyway as I think they were not far enough in memory.

    I have been digesting what Steve has pointed to. My understanding is this: I need to let PBP take care of memory!! The first @ORG is un-needed as PBP will place the code at 00 anyway. So that just needs to be deleted. I think the for the interrupt redirect, we just need a
    Code:
     DEFINE INTHAND NewIntLocation
    then in our application code:

    Code:
    DEFINE RESET_ORG 800
       GOTO Start ' or whatever you favorite label is
    NewIntLocation:
       Do your Interrupt thing
    
    Start:
       Code till your hearts content, (or MEM is full)
    So if I am correct, the only thing left is context saving in the real interrupt vector before jumping.

    Now as for the rest of the code, I need some help here. I have a crazy mix of PBP commands and direct register addressing. I want to get rid of the direct addressing. This is really bad in the comm part. Do we want to use HSERIN/OUT or SERIN/OUT. I think using SER would be nicer in the aspect we can then use any pins to do this, and have control over true vs inverted signals. It will also be a trivial matter to use I2C instead of SER using the bit-bang approach.

    Let me just throw in my opinion here, speed is NOT the issue. This is a bootloader, It will not be used often once your app is done.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  34. #34
    Join Date
    Sep 2009
    Posts
    752

    Default Re: Open source PBP bootloader

    I need to create bootloader for PIC18F that program flash from external I2C memory, eg 24lc512.
    I'll probably write bootloader in pbp and asm.

    If I understand correctly how bootloader works, there is 2 ways to implement bootloader.
    -One is to make bootloader that sits on beginning of flash, then on address 4 and 8, need to be GOTO to new int vector. That will add one more GOTO before executing int, PBP already add one. I don't like that GOTO's.
    -Other option is that first instruction in flash is GOTO Bootloader, and to put bootloader on end of flash. Then there is no need to remap interrupt. When bootloader finish job, then GOTO 1
    In main program only need to remap reset vector to 1.
    Am I understand how it works?

    For now I'll create LED blink program, that use bootloader with reset vector at 1.
    And then try to make bootloader that will program that hex to flash. For start hex will be in LOOKUP2, until I get flesh erase and write to work, then comunication...

    Probably I should start with analyzing syntax of hex file.

    Is there anyone interested and willing to help?

  35. #35
    Join Date
    Sep 2009
    Posts
    752

    Default Re: Open source PBP bootloader

    Edit timeout...
    Address for int are 8 and 24, and GOTO takes 2 program word so, reset org should be 4.

  36. #36
    Join Date
    Sep 2009
    Posts
    752

    Default Re: Open source PBP bootloader

    Is there way to move RESET_ORG to other address, without moving interrupt vector?
    DEFINE RESET_ORG 004h also move vectors. In .LST file interrupt vector are defined as RESET_ORG+8h or 18h.
    DEFINE LOADER_USED 1 doesn't do anything. I'm looking in disassembled hex file...
    This is test code:
    Code:
        DEFINE NO_CLRWDT 1
        DEFINE LOADER_USED 1
        DEFINE INTHAND myint    ' Define interrupt handler
        DEFINE INTLHAND myint    ' Define interrupt handler
    
    Start:
        PORTD.6=1
        PORTD.6=0
    GOTO Start
    
    @myint bcf PORTB,1
    Name:  disasm.png
Views: 741
Size:  12.2 KB

    Also I noticed that with or without NO_CLRWDT 1, there is no CLRWDT in hex file.

  37. #37
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,254

    Default Re: Open source PBP bootloader

    I have VERY limitted knowledge in this area, but can't you set config fuses from the programmer?

    (NO_CLRWDT is a config fuse right?)

    If input to the programmer is the hex file, wouldn't that mean that fuses are handled separately than the hex file?

    Robert
    Last edited by Demon; - 10th March 2014 at 22:20.

  38. #38
    Join Date
    Sep 2009
    Posts
    752

    Default Re: Open source PBP bootloader

    PBP should put CLRWDT if there is no defined NO_CLRWDT 1. DEFINE NO_CLRWDT 1 isn't config, it is PBP's define.

  39. #39
    Join Date
    Sep 2009
    Posts
    752

    Default Re: Open source PBP bootloader


    This is exactly what I'm trying to do.

  40. #40
    Join Date
    Oct 2009
    Location
    Utah, USA
    Posts
    442

    Default Re: Open source PBP bootloader

    wayneandlayne.com have a pretty neat solution for a bootloader, it uses two LED's as light detectors to receive the code that is "flashed" or "blinked" to your PC's monitor screen. One LED light sensor is for clocking and one LED light sensor is for the data.


    I'm not sure if this is actually a boot loader... or more of just a way of changing the message that this little kit displays...
    but I would think it could be modified to act as a boot loader.

    It may even work from a smart phones browser (it does play from a phones browser)



    Here is their actual programming web page where you can scroll down and click on the "GO" button and see it in action.
    http://www.wayneandlayne.com/blinky_programmer/


    and a description of their bootloader...
    http://www.wayneandlayne.com/project...ign/#questions

    Their project is open source but I'm not sure if the programming web page code is available.
    Last edited by Heckler; - 22nd March 2014 at 14:40.
    Dwight
    These PIC's are like intricate puzzles just waiting for one to discover their secrets and MASTER their capabilities.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts