|  | 
                                    ;***************************************************************************
                                    ;*
                                    ;* Title	: AVR ISP (Auto adr inc, 19200bps)
                                    ;* Version	: 2.0
                                    ;* Last updated	: 1998.01.06 (mlund)
                                    ;* Target	: AT90S1200
                                    ;* File		: ispprog.asm
                                    ;* Author       : Atmel Norway
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	The firmware on all programmers now support a unified protocol for 
                                    ;*	program and data memory programming. The host computer do not need
                                    ;*	to know if the programmer operates in serial or parallel mode.
                                    ;*
                                    ;*	The following commands are supported. All commands start with a
                                    ;*	single letter. The programmer returns 13d (carriage return) or the
                                    ;*	data read after the command is finished.
                                    ;*
                                    ;*                                     +-------------+------------+------+
                                    ;*  Commands                           | Host writes | Host reads |      |
                                    ;*  --------                           +-----+-------+------+-----+      |
                                    ;*                                     | ID  | data  | data |     | Note |
                                    ;* +-----------------------------------+-----+-------+------+-----+------+
                                    ;* | Enter programming mode            | 'P' |       |      | 13d |   1  |
                                    ;* | Set address                       | 'A' | ah al |      | 13d |   2  |
                                    ;* | Write program memory, low byte    | 'c' |    dd |      | 13d |   3  |
                                    ;* | Write program memory, high byte   | 'C' |    dd |      | 13d |   3  |
                                    ;* | Issue Page Write                  | 'm' |       |      | 13d |      |
                                    ;* | Read program memory               | 'R' |       |dd(dd)|     |   4  |
                                    ;* | Write data memory                 | 'D' |    dd |      | 13d |      |
                                    ;* | Read data memory                  | 'd' |       |   dd |     |      |
                                    ;* | Chip erase                        | 'e' |       |      | 13d |      |
                                    ;* | Write lock bits                   | 'l' |    dd |      | 13d |      |
                                    ;* | Write fuse bits                   | 'f' |    dd |      | 13d |  11  |
                                    ;* | Read fuse and lock bits           | 'F' |       |   dd |     |  11  |
                                    ;* | Leave programming mode            | 'L' |       |      | 13d |   5  |
                                    ;* | Select device type                | 'T' |    dd |      | 13d |   6  |
                                    ;* | Read signature bytes              | 's' |       | 3*dd |     |      |
                                    ;* | Return supported device codes     | 't' |       | n*dd | 00d |   7  |
                                    ;* | Return software identifier        | 'S' |       | s[7] |     |   8  |
                                    ;* | Return sofware version            | 'V' |       |dd dd |     |   9  |
                                    ;* | Return hardware version           | 'v' |       |dd dd |     |   9  |
                                    ;* | Return programmer type            | 'p' |       |   dd |     |  10  |
                                    ;* | Set LED                           | 'x' |    dd |      | 13d |  12  |
                                    ;* | Clear LED                         | 'y' |    dd |      | 13d |  12  |
                                    ;* | Universial command                | ':' |  3*dd |   dd | 13d |      |
                                    ;* +-----------------------------------+-----+-------+------+-----+------+
                                    ;*
                                    ;* NOTE 1
                                    ;*	The Enter programming mode command MUST be sent one time prior to
                                    ;*	the other commands, with the exception of the 't', 'S', 'V', 'v'
                                    ;*	and 'T' commands. The 'T' command must be sent before this command
                                    ;*	(see note 6).
                                    ;*
                                    ;*	For programmers supporting both parallel and serial programming
                                    ;*	mode this command enters parallel programming mode. For programmers
                                    ;*	supporting only serial programming mode, this command enters serial
                                    ;*	programming mode.
                                    ;*
                                    ;* NOTE 2
                                    ;*	The ah and al are the high and low order bytes of the address. For
                                    ;*	parallel programmers this command issues the Load Address Low/High
                                    ;*	Byte command. For serial programmers the address byte is stored for
                                    ;*	use by the Read/Write commands.
                                    ;*
                                    ;* NOTE 3
                                    ;*	For parallel programmers this command issues the Program Flash
                                    ;*	command. For serial programmers this command iussues the Write
                                    ;*	Program Memory Command. For devices with byte-wide program memories
                                    ;*	only the low byte command should be used.
                                    ;*
                                    ;* NOTE 4
                                    ;*	The contents of the program memory at the address given by the 'A'
                                    ;*	command are written to the serial port in binary form. For byte
                                    ;*	wide memories one byte is written. For 16 bit memories two bytes
                                    ;*	are written,MSB first.
                                    ;*
                                    ;* NOTE 5
                                    ;*	This command must be executed after the programming is finished.
                                    ;*
                                    ;* NOTE 6
                                    ;*	The select device type command must be sent before the enter
                                    ;*	programming command
                                    ;*
                                    ;* NOTE 7
                                    ;*	The supported device codes are returned in binary form terminated
                                    ;*	by 0x00.
                                    ;*
                                    ;* NOTE 8
                                    ;*	This return a 7 character ASCII string identifying the programmer.
                                    ;*      For the in-system programmer it is "AVR ISP".
                                    ;*
                                    ;* NOTE 9
                                    ;*	The software/hardware version are returned as two ASCII numbers.
                                    ;*
                                    ;* NOTE 10
                                    ;*	This command should be used to identify the programmer type. The
                                    ;*	return value is 'S' for serial (or SPI) programmers or 'P' for
                                    ;*	parallel programmers.
                                    ;*
                                    ;* NOTE 11
                                    ;*	The write fuse bits command are available only on parallel
                                    ;*	programmers and only for AVR devices (device code < 0x80). The host
                                    ;*	should use the return programmer type command to determine the
                                    ;*	programmer type, do not use the  "AVR PPR" idenifier because other
                                    ;*	programmers may be available in the future.
                                    ;*
                                    ;* NOTE 12
                                    ;*	Currently only the AVR development board has LEDs. The other boards
                                    ;*	must implement this commands as NOPs.
                                    ;*
                                    ;* NOTE 13
                                    ;*      Devices using Page Mode Programming write one page of flash memory
                                    ;*      before issuing a Page Mode Write Pulse.
                                    ;***************************************************************************
                                    
                                    ;**** includes ****
                                    
                                    .include "1200def.inc"
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* CONSTANTS
                                    ;*	device codes
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	The following device codes must be used by the host computer. Note
                                    ;*	that the device codes are arbitrary selected, they do not have any
                                    ;*	thing in common with the signature bytes stored in the device.
                                    ;*
                                    ;*	The following devices are supported (make a new table for each
                                    ;*	software release):
                                    ;*
                                    ;*	SW_MAJOR=1, SW_MINOR=5	
                                    ;*	AT90S1200 rev. C (abbreviated S1200C)
                                    ;*	AT90S1200 rev. D (abbreviated S1200D)
                                    ;*	AT90S8515 rev. A (abbreviated S8515A)
                                    ;*	AT89S8252 (abbreviated S8252)
                                    ;*
                                    ;*	SW_MAJOR=1, SW_MINOR=6
                                    ;*	AT90S1200 rev. C (abbreviated S1200C)
                                    ;*	AT90S1200 rev. D (abbreviated S1200D)
                                    ;*	AT90S8515 rev. A (abbreviated S8515A)
                                    ;*	AT89S8252 (abbreviated S8252)
                                    ;*      ATmega103 rev. A (abbreviated S01838A)
                                    ;*
                                    ;***************************************************************************
                                    
                                    .equ	S1200C	= 0x12
                                    .equ	S1200D	= 0x13
                                    .equ	S2313A	= 0x20
                                    .equ	S4414A	= 0x28
                                    .equ	S8515A	= 0x38
                                    .equ	S8252	= 0x86
                                    .equ	S2323A	= 0x48
                                    
                                    .equ	S01838C	= 0x40
                                    .equ	S01838D	= 0x41
                                    
                                    ;**** Revision Codes ****
                                    
                                    .equ	SW_MAJOR = 2		; Major SW revision number
                                    .equ	SW_MINOR = 0		; Minor SW revision number
                                    .equ	HW_MAJOR = 1		; Major HW revision number
                                    .equ	HW_MINOR = 0		; Minor HW revision number
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* MACROS
                                    ;*	Program Macros
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Change the following four macros if the RESET pin to the
                                    ;*	target moves and/or if the SCK/MISO/MOSO moves.
                                    ;*
                                    ;***************************************************************************
                                    
                                    .macro	set_reset
                                    	sbi	portb,4
                                    .endm
                                    
                                    .macro	clr_reset
                                    	cbi	portb,4
                                    .endm
                                    
                                    .macro	ddrd_init
                                    	nop
                                    ;	sbi	ddrd,3
                                    .endm
                                    
                                    .macro	ddrb_init
                                    	ldi	temp1,0xdf
                                    	out	ddrb,temp1	; PB5 is input, the rest is output
                                    .endm
                                    
                                    .macro	ddrb_release
                                    	ldi	temp1,(1<<PB4)
                                    	out	ddrb,temp1	; PB4 (RESET) is output, the rest is input
                                    .endm
                                    
                                    .macro	pulse_sck
                                    	sbi	portb,SCK
                                    	ldi	temp2,6
                                    m0:	dec	temp2
                                    	brne	m0
                                    	cbi	portb,SCK
                                    	ldi	temp2,1		; 3
                                    m1:	dec	temp2
                                    	brne	m1
                                    .endm
                                    
                                    
                                    ;*****************
                                    ;* SPI Constants *
                                    ;*****************
                                    
                                    .equ	MOSI	= 6		; Bit number on PORTB
                                    .equ	MISO	= 5		; Bit number on PORTB
                                    .equ	SCK	= 7		; Bit number on PORTB
                                    
                                    
                                    ;******************
                                    ;* UART Constants *
                                    ;******************
                                    
                                    ;**** Constant declarations Data Rate ****
                                    
                                    ;.equ	N = 95			; 115200 BAUD when R=1 and XTAL=11.059MHz
                                    ;.equ	N = 31			; 57600 BAUD when R=2 and XTAL=11.059MHz
                                    ;.equ	N = 43			; 38400 BAUD when R=2 and XTAL=11.059MHz
                                    .equ	N = 33			; 19200 BAUD when R=2 and XTAL=4.00MHz
                                    ;.equ	N = 102			; 38400 BAUD when R=1 and XTAL=4.00MHz
                                    .equ	R = 2
                                    
                                    ;**** UART transmit pin in PORTD ****
                                    
                                    .equ	TXPIN = 1
                                    .equ	RXPIN = 0		; Receive pin must be external interrupt !!
                                    
                                    ;**** Bit positions in UART Status Register ****
                                    
                                    .equ	TXC = 0			; Transmit
                                    .equ	RXC = 1			; Receive
                                    
                                    
                                    ;*****************************
                                    ;* Global Register Variables *
                                    ;*****************************
                                    
                                    .def	device	= r16		; Device code
                                    .def	temp1	= r17
                                    .def	temp2	= r18
                                    .def	s_data	= r19		; SPI data
                                    .def	u_data	= r20		; UART data
                                    .def	addrl	= r21		; Low order byte of address
                                    .def	addrh	= r22		; High order byte of address
                                    .def	bit_cnt	= r23		; Bit count used by UART routine
                                    .def	u_stat	= r24		; Status byte used by UART routine
                                    .def	cmd	= r25		; Serial programming command
                                    .def	count	= r26		; Time out variable for "enter programming mode"
                                    .def	param1	= r27
                                    .def	cmd1	= r28
                                    .def	cmd2	= r29
                                    .def	cmd3	= r30
                                    
                                    ;*********************
                                    ;* Interrupt Vectors *
                                    ;*********************
                                    
                                    .CSEG
                                    	rjmp	RESET		; Reset Handle
                                    	reti			; IRQ0 Handle (not used)
                                    	rjmp	TIM0_OVF	; Timer0 Overflow Handle
                                    	reti			; Analog Comparator Handle (not used)
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* INTERRUPT
                                    ;*	TIM0_OVF - Software UART Service Routine
                                    ;*
                                    ;***************************************************************************
                                    
                                    TIM0_OVF:
                                    	in	r0,SREG		; store SREG
                                    	ldi	temp1,(256-N+8)
                                    	out	TCNT0,temp1	; reset T/C0 to one bit lenght
                                    	inc	bit_cnt		; increment bit counter
                                    	sbrs	u_stat,TXC	; if (transmit complete flag clear)
                                    	rjmp	transmit	;    goto transmit
                                    
                                    to_0:	sec			; set carry
                                    	sbis	PIND,RXPIN	; if (RxD == LOW)
                                    	clc			;	clear carry
                                    	ror	u_data		; shift carry into u_data
                                    
                                    	cpi	bit_cnt,8	; if (bit_cnt == 8)
                                    	brne	to_1		; {
                                    	clr	temp1		;    disable T/C0 Overflow Interrupt
                                    	out	TIMSK,temp1
                                    	sbr	u_stat,1<<RXC	;    set receive complete
                                    to_1:				; }
                                    	out	SREG,r0	        ; restore SREG
                                    	reti			; exit
                                    
                                    transmit:
                                    	cpi	bit_cnt,1	; if (bit_cnt == 1)	\\ start bit
                                    	brne	to_2		; {
                                    	cbi	PORTD,TXPIN	;	generate start bit
                                    	rjmp	to_1		;	exit
                                    to_2:				; }
                                    	cpi	bit_cnt,10	; if (bit_cnt == 10)	\\ stop bit
                                    	brne	to_3		; {
                                    	sbi	PORTD,TXPIN	;	generate stop bit
                                    	clr	temp1		;	disable TC0 overflow interrupt
                                    	out	TIMSK,temp1
                                    	sbr	u_stat,1<<TXC	;	set transmit complete bit
                                    	rjmp	to_1		;	exit
                                    to_3:				; }
                                    	sbrc	u_data,0	; if (LSB set)
                                    	sbi	PORTD,TXPIN	;	PD3 = HIGH
                                    	sbrs	u_data,0	; if (LSB clear)
                                    	cbi	PORTD,TXPIN	;	PD3 = LOW
                                    	lsr	u_data		; shift left u_data
                                    	rjmp	to_1		; exit
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	u_init
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Initialize UART.
                                    ;*
                                    ;***************************************************************************
                                    
                                    u_init:	ldi	u_stat,1<<TXC	; set TXC
                                    	ldi	temp1,R		; set clock rate
                                    	out	TCCR0,temp1
                                    	sbi	DDRD,TXPIN	; initialize UART pins
                                    	cbi	DDRD,RXPIN
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	putc
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Send a character on the UART Tx line.
                                    ;*
                                    ;***************************************************************************
                                    
                                    putc:	clr	u_stat		; clear UART status flags
                                    	clr	bit_cnt		; clear bit counter
                                    	ldi	temp1,1<<TOV0	; enable T/C0 overflow interrupt
                                    	out	TIMSK,temp1
                                    putc0:	sbrs	u_stat,TXC	; while (!(u_stat & TXC)); // Wait for TXC
                                    	rjmp	putc0
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	getc
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Wait for start bit and receive a character on the UART Rx line.
                                    ;*
                                    ;***************************************************************************
                                    
                                    getc:	sbis	PIND,RXPIN
                                    	rjmp	getc
                                    getc0:	sbic	PIND,RXPIN
                                    	rjmp	getc0
                                    	ldi	temp1,(256-(N+N/2)+8+12);
                                    	out	TCNT0,temp1 	; preset T/C0 to 1.5 bit lengths
                                    	ldi	temp1,1<<TOIE0
                                    	out	TIFR,temp1	; clear T/C0 overflow flag
                                    	out	TIMSK,temp1	; enable T/C0 overflow Interrupt
                                    	clr	bit_cnt		; clear bit counter
                                    getc1:	sbrs	u_stat,RXC	; wait for Receive Complete
                                    	rjmp	getc1
                                    	cbr	u_stat,1<<RXC	; clear RXC
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	delay
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	 Make a small delay.
                                    ;*
                                    ;***************************************************************************
                                    
                                    delay:	ldi	temp2,0xff
                                    dl:	dec	temp2
                                    	brne	dl
                                    	dec	temp1
                                    	brne	delay
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	wrser
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	 Write a byte to the SPI.
                                    ;*
                                    ;***************************************************************************
                                    
                                    wrser:	ldi	temp1,8
                                    wrs0:	rol	s_data
                                    	brcc	wrs1
                                    	sbi	portb,MOSI
                                    	rjmp	wrs2
                                    wrs1:	cbi	portb,MOSI
                                    wrs2:	pulse_sck
                                    	dec	temp1
                                    	brne	wrs0
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	rdser
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	 Read a byte from the SPI.
                                    ;*
                                    ;***************************************************************************
                                    
                                    rdser:	ldi	temp1,8
                                    	ldi	s_data,0
                                    rd0:	lsl	s_data
                                    	sbic	pinb,MISO
                                    	ori	s_data,1
                                    	pulse_sck
                                    	dec	temp1
                                    	brne	rd0
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	spiinit (Enter programming mode)
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Initialize SPI interface on AVR or 'AT89 device.
                                    ;*
                                    ;***************************************************************************
                                    
                                    spiinit:ddrd_init		; initialize port D
                                    	ddrb_init		; initialize port B
                                    	cbi	portb,SCK	; clear SCK
                                    	cpi	device,S8252	; if (device != S8252)
                                    	breq	s89		; {
                                    	set_reset		;	set RESET = 1
                                    	ldi	temp1,0xff	;	delay(0xff);
                                    	rcall	delay
                                    	clr_reset		;	set RESET = 0
                                    	rjmp	s0		; }
                                    				; else
                                    s89:				; {
                                    	clr_reset		; 	set RESET = 0
                                    	ldi	temp1,0xff	;	delay(0xff);
                                    	rcall	delay
                                    	set_reset		;	set RESET = 1
                                    s0:				; }
                                    	ldi	temp1,0xff	; delay(0xff);
                                    	rcall	delay
                                    
                                    	ldi	s_data,0xac	; wrser(0xac);		// SPI write (byte 1)
                                    	rcall	wrser
                                    	ldi	s_data,0x53	; wrser(0x53);		// SPI write (byte 2)
                                    	rcall	wrser
                                    
                                    				; // SPI Synchronization (fix!)
                                    	cpi	device,0x20	; if ( (device >= 0x20) && (device <= 0x7F) )
                                    	brlo	s2
                                    	tst	device
                                    	brmi	s2
                                    s0b:				; {
                                    	ldi	count,32	;	count = 32;
                                    s1:				;	do {
                                    	rcall	rdser		;		if (rdser == 0x53)	// SPI read (byte 3)
                                    	cpi	s_data,0x53
                                    	breq	s3		;			break;
                                    	ldi	s_data,0x00	;		wrser(0x00);		// SPI write (byte 4)
                                    	rcall	wrser
                                    	pulse_sck		;		pulse SCK
                                    	ldi	s_data,0xac	;		wrser(0xac);		// SPI write (byte 1)
                                    	rcall	wrser
                                    	ldi	s_data,0x53	;		wrser(0x53);		// SPI write (byte 2)
                                    	rcall	wrser
                                    	dec	count		;	} while(--count);
                                    	brne	s1
                                    	rjmp	s3		; }
                                    				; else
                                    s2:				; {
                                    	ldi	s_data,0x00	;	wrser(0x00);		// SPI write (byte 3)
                                    	rcall	wrser
                                    s3:				; }
                                    	cpi	device,S8252	; if (device != S8252)
                                    	breq	s4		; {
                                    	ldi	s_data,0x00	;	wrser(0x00);	// SPI write (byte 4)
                                    	rcall	wrser
                                    s4:				; }
                                    	ldi	temp1,0x10	; delay(0x10);
                                    	rcall	delay
                                    	ret
                                    
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* FUNCTION
                                    ;*	show_id
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Show our ID ("AVR ISP") on the serial line.
                                    ;*
                                    ;***************************************************************************
                                    
                                    show_id:ldi	u_data,0x41		; 'A'
                                    	rcall	putc
                                    	ldi	u_data,0x56		; 'V'
                                    	rcall	putc
                                    	ldi	u_data,0x52		; 'R'
                                    	rcall	putc
                                    	ldi	u_data,0x20		; ' '
                                    	rcall	putc
                                    	ldi	u_data,0x49		; 'I'
                                    	rcall	putc
                                    	ldi	u_data,0x53		; 'S'
                                    	rcall	putc
                                    	ldi	u_data,0x50		; 'P'
                                    	rcall	putc
                                    	ret
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* RESET
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Initialization
                                    ;*
                                    ;***************************************************************************
                                    
                                    RESET:	clr	temp1
                                    	out	GIMSK,temp1	; disable external interrupt
                                    	ser	temp1		; Initialize
                                    	out	PORTD,temp1
                                    	set_reset		; set RESET=1
                                    	out	PORTB,temp1
                                    	ddrb_release
                                    	rcall	u_init		; Initialize UART
                                    	sei			; Enable interrupts
                                    
                                    
                                    ;***************************************************************************
                                    ;*
                                    ;* PROGRAM
                                    ;*	waitcmd -> main
                                    ;*
                                    ;* DESCRIPTION
                                    ;*	Wait for and execute commands.
                                    ;*
                                    ;***************************************************************************
                                    
                                    waitcmd:rcall	getc		; while (getc() == ESC) {};
                                    	cpi	u_data,0x1b
                                    	breq	waitcmd
                                    
                                    ;**** Device Type ****
                                    
                                    	cpi	u_data,0x54     ; 'T' Device type
                                    	brne	w0
                                    	rcall	getc		; getc();	// dummy
                                    	mov	device,u_data	; putc(device);
                                    	rjmp	put_ret
                                    
                                    ;**** Return Software Identifier ****
                                    
                                    w0:	cpi	u_data,0x53	; 'S' Return software identifier
                                    	brne	w1
                                    	rcall	show_id		; show_id();
                                    	rjmp	waitcmd
                                    
                                    ;**** Return Software Version ****
                                    
                                    w1:	cpi	u_data,0x56	;'V' Return software version
                                    	brne	w2
                                    	ldi	u_data,0x30+SW_MAJOR ; putc(0x30+SW_MAJOR);
                                    	rcall	putc
                                    	ldi	u_data,0x30+SW_MINOR ; putc(0x30+SW_MINOR);
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** Return Hardware Version ****
                                    
                                    w2:	cpi	u_data,0x76	;'v' Return hardware version
                                    	brne	w3
                                    	ldi	u_data,0x30+HW_MAJOR ; putc(0x30+HW_MAJOR);
                                    	rcall	putc
                                    	ldi	u_data,0x30+HW_MINOR ; putc(0x30+HW_MINOR);
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** Show Supported Devices ****
                                    
                                    w3:	cpi	u_data,0x74	; 't' Show supported devices
                                    	brne	w4
                                    	ldi	u_data,S1200C	; putc(S1200C);
                                    	rcall	putc
                                    	ldi	u_data,S1200D	; putc(S1200D);
                                    	rcall	putc
                                    	ldi	u_data,S2313A	; putc(S2313A);
                                    	rcall	putc
                                    	ldi	u_data,S4414A	; putc(S4414A);
                                    	rcall	putc
                                    	ldi	u_data,S8515A	; putc(S8515A);
                                    	rcall	putc
                                    	ldi	u_data,S2323A	; putc(S2323A);
                                    	rcall	putc
                                    	ldi	u_data,S8252	; putc(S8252);
                                    	rcall	putc
                                    	ldi	u_data,0x00	; putc(0x00);	// end of device list
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** Return Programmer Type ****
                                    
                                    w4:	cpi	u_data,0x70     ; 'p' Return programmer type
                                    	brne	w5
                                    	ldi	u_data,0x53     ; putc('S');	// serial programmer
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** Set LED ****
                                    
                                    w5:	cpi	u_data,0x78	; 'x' Set LED (ignored)
                                    	brne	w6
                                    	rjmp	put_ret
                                    
                                    ;**** Clear LED ****
                                    
                                    w6:	cpi	u_data,0x79     ; 'y' Clear LED (ignored)
                                    	brne	w7
                                    	rjmp	put_ret
                                    
                                    ;**** Enter Programming Mode ****
                                    
                                    ; We require that the device code be selected before any of the other commands
                                    
                                    w7:
                                    	cpi	device,S1200C	; if ((device != S1200C) &&
                                    	breq	w72
                                    	cpi	device,S1200D	;     (device != S1200D) &&
                                    	breq	w72
                                    	cpi	device,S8515A	;     (device != S8515A) &&
                                    	breq	w72
                                    	cpi	device,S4414A	;     (device != S4414A) &&
                                    	breq	w72
                                    	cpi	device,S2313A	;     (device != S2313A) &&
                                    	breq	w72
                                    	cpi	device,S8252	;     (device != S8252) &&
                                    	breq	w72
                                    	cpi	device,S01838C	;     (device != S01838C) &&
                                    	breq	w72
                                    	cpi	device,S01838D	;     (device != S01838D) &&
                                    	breq	w72
                                    	cpi	device,S2323A	;     (device != S2323A))
                                    	breq	w72
                                    	rjmp	put_err		;	goto put_err();
                                    
                                    w72:	cpi	u_data,0x50	; 'P' Enter programming mode
                                    	brne	w8
                                    	rcall	spiinit		; spiinit();
                                    	rjmp	put_ret
                                    
                                    ;**** Wait Program Memory ****
                                    
                                    ;* USAGE
                                    ;*	wait_pm(byte cmd, byte c_data);
                                    ;*
                                    ;*	cmd :		0x28 - wait for high byte written
                                    ;*			0x20 - wait for low byte written
                                    ;*	u_data :	current data written
                                    
                                    ;wait_pm:			; do
                                    ;				; {
                                    ;	mov	s_data,cmd	;	wrser(cmd);		// SPI write (byte 1)
                                    ;	rcall	wrser
                                    ;	mov	s_data,addrh	;	wrser(addrh);		// SPI write (byte 2)
                                    ;	rcall	wrser
                                    ;	mov	s_data,addrl	;	wrser(addrl);		// SPI write (byte 3)
                                    ;	rcall	wrser
                                    ;	rcall	rdser		;	s_data = rdser();	// SPI read (byte 4)
                                    				; }
                                    ;	cp	s_data,u_data	; while(s_data != u_data);
                                    ;	brne	wait_pm
                                    ;	ret
                                    
                                    ;**** Write Program Memory, High Byte ****
                                    
                                    w8:	cpi	u_data,0x43	; 'C' Write program memory, high byte
                                    	brne	w9
                                    	rcall	getc
                                    	cpi	device,S8252	; if (device == S8252)
                                    	brne	w81		; {
                                    	rjmp	put_err		; 	goto err();
                                    				;	// (AT89 series have byte wide program memory !)
                                    				; }
                                    w81:	ldi	s_data,0x48	; wrser(0x48);		// SPI write (byte 1)
                                    	rcall	wrser
                                    	mov	s_data,addrh	; wrser(addrh);		// SPI write (byte 2)
                                    	rcall	wrser
                                    	mov	s_data,addrl	; wrser(addrl);		// SPI write (byte 3)
                                    	rcall	wrser
                                    	cpi	device,S01838C	; invert data on 01838 rev C!
                                    	brne	w81b
                                    	com	u_data
                                    w81b:
                                    	mov	s_data,u_data	; wrser(u_data);	// SPI write (byte 4)
                                    	rcall	wrser
                                    	cpi	device,S01838C	; no delay for S01838 (Uses Page Write Mode instead)
                                    	breq	w82
                                    	cpi	device,S01838D
                                    	breq	w82
                                    
                                    	ldi	temp1,0x20	; delay(0x20);		// 24585 cycles delay
                                    	rcall	delay		;			// Page mode requires no delay!
                                    w82:
                                    	ldi	temp1,0x01	; Auto increment address				!!!!
                                    	clr	temp2
                                    	add	addrl,temp1
                                    	adc	addrh,temp2
                                    	rjmp	put_ret		; goto reply();
                                    
                                    ;**** Write Program Memory, Low Byte ****
                                    
                                    w9:	cpi	u_data,0x63     ; 'c' Write program memory, low byte
                                    	brne	w12
                                    	rcall	getc
                                    
                                    	cpi	device,S8252	; if (device != S8252)
                                    	breq	w989		; {
                                    	ldi	s_data,0x40	;	wrser(0x40);	// SPI write (byte 1)
                                    	rcall	wrser
                                    	mov	s_data,addrh	;	s_data = addrh;
                                    	rjmp	w91		; }
                                    				; else
                                    w989:				; {
                                    	mov	s_data,addrh	;	s_data = (addrh << 3) | 0x02;
                                    	rcall	shift_s_data3
                                    	ori	s_data,0x02
                                    w91:				; }
                                    	rcall	wrser		; wrser(s_data);	// SPI write (byte 2)
                                    	mov	s_data,addrl	; wrser(addrl);		// SPI write (byte 3)
                                    	rcall	wrser
                                    	cpi	device,S01838C	; invert data on 01838 rev C!
                                    	brne	w91b
                                    	com	u_data
                                    w91b:
                                    	mov	s_data,u_data	; wrser(u_data);	// SPI write (byte 4)
                                    	rcall	wrser
                                    	cpi	device,S01838C	; no delay for S01838 (Uses Page Write Mode instead)
                                    	breq	w92
                                    	cpi	device,S01838D
                                    	breq	w92
                                    	ldi	temp1,0x20	; delay(0x20);		// 24585 cycles delay
                                    	rcall	delay		;			// Page mode requires no delay!
                                    w92:
                                    	rjmp	put_ret		; goto reply();
                                    
                                    ;**** Read Program Memory ****
                                    
                                    w12:	cpi	u_data,0x52	; 'R' Read program memory
                                    	brne	w10		;
                                    	cpi	device,S8252	; if (device != S8252)
                                    	breq	w1289		; {
                                    	ldi	s_data,0x28	;	wrser(0x28);	// SPI write (byte 1)
                                    	rcall	wrser
                                    	mov	s_data,addrh	;	s_data = addrh;
                                    	rjmp	w121		; }
                                    				; else
                                    w1289:				; {
                                    	mov	s_data,addrh	;	s_data = (addrh << 3) | 0x01;
                                    	rcall	shift_s_data3
                                    	ori	s_data,0x01
                                    w121:				; }
                                    	rcall	wrser		; wrser(s_data);	// SPI write (byte 2)
                                    	mov	s_data,addrl	; wrser(addrl);		// SPI write (byte 3)
                                    	rcall	wrser
                                    	rcall	rdser		; putc(rdser());	// Send data (byte 4)
                                    	mov	u_data,s_data
                                    	rcall	putc
                                    	cpi	device,S8252	; if (device == S8252)
                                    	brne	w122		; {
                                    	rjmp	waitcmd		;	goto waitcmd();
                                    				; }
                                    				; else
                                    w122:				; {
                                    	ldi	s_data,0x20	;	wrser(0x20);	// SPI write (byte 1)
                                    	rcall	wrser
                                    	mov	s_data,addrh	;	wrser(addrh);	// SPI write (byte 2)
                                    	rcall	wrser
                                    	mov	s_data,addrl	;	wrser(addrl);	// SPI write (byte 3)
                                    	rcall	wrser
                                    	rcall	rdser		;	putc(rdser());	// Send data (byte 4)
                                    	mov	u_data,s_data
                                    	rcall	putc
                                    
                                    	ldi	temp1,0x01	;	Auto increment address				!!!!
                                    	clr	temp2
                                    	add	addrl,temp1
                                    	adc	addrh,temp2
                                    
                                    	rjmp	waitcmd		;	goto waitcmd();
                                    				; }
                                    shift_s_data3:
                                    	lsl	s_data
                                    	lsl	s_data
                                    	lsl	s_data
                                    	ret
                                    
                                    ;**** Load Address ****
                                    
                                    w10:	cpi	u_data,0x41	; 'A' Load address
                                    	brne	w11
                                    	rcall	getc		; addrh = getc();
                                    	mov	addrh,u_data
                                    	rcall	getc		; addrl = getc();
                                    	mov	addrl,u_data
                                    	rjmp	put_ret		; goto reply();
                                    
                                    ;**** Write Data Memory ****
                                    
                                    w11:	cpi	u_data,0x44	; 'D' Write data memory
                                    	brne	w13
                                    	rcall	getc
                                    	cpi	device,S8252
                                    	breq	w1189
                                    
                                    	ldi	s_data,0xc0
                                    	rcall	wrser
                                    	mov	s_data,addrh
                                    	rjmp	w111
                                    
                                    w1189:	mov	s_data,addrh
                                    	rcall	shift_s_data3
                                    	ori	s_data,0x06
                                    
                                    w111:	rcall	wrser
                                    	mov	s_data,addrl
                                    	rcall	wrser
                                    	mov	s_data,u_data
                                    	rcall	wrser
                                    	ldi	temp1,0x20
                                    	rcall	delay
                                    	rjmp	put_ret
                                    
                                    ;;**** Read Data Memory ****
                                    
                                    w13:	cpi	u_data,0x64	; 'd' Read data memory
                                    	brne	w14
                                    	cpi	device,S8252	; if (device != S8252)
                                    	breq	w1389		; {
                                    	ldi	s_data,0xa0	;	wrser(0xA0);	// SPI write (byte 1)
                                    	rcall	wrser
                                    	mov	s_data,addrh	;	s_data = addrh;
                                    	rjmp	w131		; }
                                    				; else
                                    w1389:				; {
                                    	mov	s_data,addrh	;	s_data = (addrh << 3) | 0x05;
                                    	rcall	shift_s_data3
                                    	ori	s_data,0x05
                                    w131:				; }
                                    	rcall	wrser		; wrser(s_data);	// SPI write (byte 2)
                                    	mov	s_data,addrl	; wrser(addrl);		// SPI write (byte 3)
                                    	rcall	wrser
                                    	rcall	rdser		; putc(rdser());	// Send data (byte 4)
                                    	mov	u_data,s_data
                                    	rcall	putc
                                    	rjmp	waitcmd		; goto waitcmd();
                                    
                                    
                                    ;**** Leave Programming Mode ****
                                    
                                    w14:	cpi	u_data,0x4c	; 'L' Leave programming mode
                                    	brne	w15
                                    	ddrb_release
                                    	cpi	device,S8252
                                    	breq	w141
                                    	set_reset		; set RESET = 1
                                    	rjmp    put_ret
                                    w141:	clr_reset		; set RESET = 0
                                    	rjmp	put_ret
                                    
                                    ;**** Chip Erase ****
                                    
                                    w15:	cpi	u_data,0x65     ; 'e' Chip erase
                                            brne	w16
                                    	ldi	s_data,0xac
                                    	rcall	wrser
                                    	cpi	device,S8252
                                    	breq	w1589
                                    	ldi	s_data,0x80
                                    	rcall	wrser
                                    w1589:	ldi	s_data,0x04
                                    	rcall	wrser
                                    	ldi	s_data,0x00
                                    	rcall	wrser
                                    	ldi	temp1,0x30
                                    	rcall	delay
                                    	rjmp	put_ret
                                    
                                    ;**** Write Lock Bits ****
                                    
                                    w16:	cpi	u_data,0x6c	; 'l' Write lock bits
                                    	brne	w17
                                    	rcall	getc
                                    	ldi	s_data,0xac
                                    	rcall	wrser
                                    	mov	s_data,u_data
                                    	cpi	device,S8252
                                    	breq	w1689
                                    	andi	s_data,0x06
                                    	ori	s_data,0xe0
                                    	rcall	wrser
                                    	ldi	s_data,0x00
                                    	rcall	wrser
                                    	rjmp	w162
                                    
                                    w1689:	andi	s_data,0xe0
                                    	ori	s_data,0x07
                                    	rcall	wrser
                                    w162:	ldi	s_data,0x00
                                    	rcall	wrser
                                    	ldi	temp1,0x30
                                    	rcall	delay
                                    	rjmp	put_ret
                                    
                                    ;**** Read Signature Bytes ****
                                    
                                    w17:	cpi	u_data,0x73	; 's' Read signature bytes
                                    	brne	w18
                                    	cpi	device,S8252
                                    	brne	w17begin
                                    	rjmp	put_err
                                    w17begin:
                                    	ldi	param1,0x02
                                    	rcall	w17call
                                    	ldi	param1,0x01
                                    	rcall	w17call
                                    	ldi	param1,0x00
                                    	rcall	w17call
                                    	rjmp	waitcmd
                                    
                                    w17call:ldi	s_data,0x30
                                    	rcall	wrser
                                    	ldi	s_data,0x00
                                    	rcall	wrser
                                    	mov	s_data,param1
                                    	rcall	wrser
                                    	rcall	rdser
                                    	mov	u_data,s_data
                                    	rcall	putc
                                    	ret
                                    
                                    
                                    ;**** Write Program Memory Page ****
                                    
                                    w18:	cpi	u_data,0x6D	; 'm' Write Program Memory Page
                                    	brne	w19
                                    
                                    	ldi	s_data,0x4c	;	wrser(0x4c);	// SPI write (byte 1)
                                    	rcall	wrser
                                    
                                    	mov	s_data,addrh	;	wrser(addrh);	// SPI write (byte 2)
                                    	rcall	wrser
                                    	mov	s_data,addrl	;	wrser(addrl);	// SPI write (byte 3)
                                    	rcall	wrser
                                    
                                    	ldi	s_data,0x00	;	wrser(0x00);	// SPI write (byte 4)
                                    	rcall	wrser
                                    	ldi	temp1,0xff	; 	delay(0xFF);	// 0x20 = 24585 cycles delay
                                    	rcall	delay
                                    	rjmp	put_ret
                                    
                                    ;**** Universal Command ****
                                    
                                    w19:	cpi	u_data,0x3A	; ':' Universal Command
                                    	brne	w99
                                    
                                    	rcall	getc
                                    	mov	cmd1,u_data
                                    	rcall	getc
                                    	mov	cmd2,u_data
                                    	rcall	getc
                                    	mov	cmd3,u_data
                                    	rcall	universal
                                    	ldi	temp1,0xff	; 	delay(0xFF);	// 0x20 = 24585 cycles delay
                                    	rcall	delay
                                    	rjmp	put_ret
                                    
                                    universal:
                                    	mov	s_data,cmd1
                                    	rcall	wrser
                                    	mov	s_data,cmd2
                                    	rcall	wrser
                                    	mov	s_data,cmd3
                                    	rcall	wrser
                                    	rcall	rdser
                                    	mov	u_data,s_data
                                    	rcall	putc
                                    	ret
                                    
                                    w99:
                                    
                                    ;**** Command Error ****
                                    
                                    put_err:ldi	u_data,0x3f	; putc('?');	\\ send '?'
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** Reply Command ****
                                    
                                    put_ret:ldi	u_data,0x0d	; putc(0x0D);	\\ send CR
                                    	rcall	putc
                                    	rjmp	waitcmd
                                    
                                    ;**** End of File ****
                                    
                                    
 
                                    
                                    
                                     |  |