\ downloader.fs
\ ADuC812 and ADuC816 and ADuc841
0 [if]
Copyright (C) 1991-2004 by AM Research, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For LGPL information:   http://www.gnu.org/copyleft/lesser.txt
For application information:   http://www.amresearch.com

[then]
[
0 value twirler
: twirl   (  - )
        twirler 1+ 3 and dup to twirler
        dup 0=  if   drop [char] |  else
        dup 1 = if   drop [char] /  else
        dup 2 = if   drop [char] -  else
        dup 3 = if   drop [char] \
        then then then then
        emit 8 emit ;
: untwirl   (  - )   ( 8 emit)   bl emit ;

16 constant bytes/line-hex
0 value ADUCchecksum
: +checksum   ( n - )   ADUCchecksum + $ffff and to ADUCchecksum ;
: spit-hex-byte   ( c - )
        dup +checksum
        base @ >r hex   0 <# # # #> drop
        count ( dup emit) ( spit) emit-s   c@ ( dup emit) ( spit) emit-s
        r> base ! ;
: spit-hex-address   ( a - )
        dup $0ff and +checksum
        dup 0 256 um/mod nip $0ff and +checksum
        base @ >r hex   0 <# # # # # #> drop
        4 0 do   count ( dup emit) ( spit) emit-s   loop   drop
        r> base ! ;
: count-t   ( a1 - a2 c)   dup 1+ swap c@-t ;
: send-line-hex   ( a1 - a2)
        \ cr
        00 to ADUCchecksum
        [char] : ( dup emit) ( spit) emit-s
        bytes/line-hex spit-hex-byte
        dup spit-hex-address
        0 spit-hex-byte
        16 0 do   count-t spit-hex-byte   loop
        ADUCchecksum negate $00ff and spit-hex-byte
        ;
: wait-for-ack   (  - )
        ( byte) key-s ( space dup .) 6 - abort" dOWNLOAD eRROR" ;
: send-done   (  - )
        cr [char] ; ( dup emit) ( spit) emit-s
        $ff00 spit-hex-address ;
: old-download   (  - )
        0 ] HERE [ ( target-size)
		BYTES/LINE-HEX /MOD SWAP 0= NOT 1 AND + 0 DO
                SEND-LINE-HEX WAIT-FOR-ACK
                i 7 AND 0= IF   TWIRL   THEN
        LOOP    DROP UNTWIRL
        SEND-DONE ;
: check-spit   ( c - )   dup +checksum ( spit) emit-s ;	
: send-address   ( a - )
	0 check-spit	\ 16 bit address always.
	dup 8 rshift $FF and check-spit	\ High byte of address.
	$FF and check-spit		\ Low byte of address.
	;
: send-checksum   (  - )   
	aducChecksum negate $FF and ( spit) emit-s
	;
: send-packet-start-ID   (  - )
	0 to aducChecksum
	$07 ( spit) emit-s   $0E ( spit) emit-s	\ Packet start ID.
	;
: send-program-packet   ( a1 - a2)
	send-packet-start-ID
	bytes/line-hex 4 + check-spit	\ Number of data bytes to follow.
	[char] W check-spit		\ Write code memory command
	dup send-address
	bytes/line-hex 0 do
		count-t check-spit
	loop
	send-checksum
	wait-for-ack 
	;
: erase-program-memory   (  - )
	send-packet-start-ID
	1 check-spit		\ Byte count, including command.
	[char] C check-spit	\ The erase code memory command.
	send-checksum
	wait-for-ack
	;
: run-program-code   (  - )
	send-packet-start-ID
	4 check-spit
	[char] U check-spit
	0 send-address
	send-checksum
	wait-for-ack
	;
: new-download   (  - )
	cr ." Erasing Program Memory" 
	erase-program-memory
	cr ." Writing Program Memory"
	0 ] HERE [ ( target-size)
	bytes/line-hex /mod swap 0= not 1 and + 0 do
		send-program-packet
		i 7 and 0= if   twirl   then
	loop	drop untwirl
	run-program-code
	;

: echo  ( c - c)  dup emit ;

\ Decide which version of the downloader is being used.
\ Aborts if chip is neither new nor old.
: new-chip?   (  - flag)
	begin	( byte) key-s echo [char] A = dup if
			drop ( byte) key-s echo [char] D =
		then
	until	\ 'A' and 'D' have been received.
	9 ( byte) key-s echo dup [char] I = over [char] u = or 0= abort" Bad downloader"
	[char] I = tuck if   drop 22   then   \ 'I' or 'u'
	0 do   ( byte) key-s ( echo) drop   loop   \ Discard the rest of the ID string.
	;
nowarn	
: download   (  - )        
	0 to twirler
        CR ." Apply power to and/or reset the target board..." cr
	new-chip? cr if
		new-download
	else	old-download
	then cr ;
warn
