	[const sreg $5f]
	[const spmcsr $57]

	[const eearl $3e][const eearh $3f][const eedr $3d]
	[const eecr $3c]
	  [const eere 0][const eepe 1][const eempe 2]

	[const pina $39][const ddra $3a][const porta $3b]
	  [const tx 1][const rx 0]

	[const vm-entry-addr $100]
	[const powerup-flag $60]

start	[rjmp init]
	[rjmp $101][rjmp $102][rjmp $103][rjmp $104]
	[rjmp $105][rjmp $106][rjmp $107][rjmp $108]
	[rjmp $109][rjmp $10a][rjmp $10b][rjmp $10c]
	[rjmp $10d][rjmp $10e]
.putc	[rjmp putc]
.getc	[rjmp getc]

init	[ldi d0 0][sts d0 powerup-flag]
	[sbi ddra tx]
	[sbi porta tx]
	[sbi porta rx]		; enable pullup
	[sbic pina rx][rjmp loop]
	[ldi d0 1][rcall vm-entry-addr]

loop	[rcall getc]
	[cpi d0 $ff][breq i'm-here]
	[cpi d0 $fe][breq read-data-byte]
	[cpi d0 $fd][breq write-data-bytes]
	[cpi d0 $fc][breq read-flash-word]
	[cpi d0 $fb][breq write-flash]
	[cpi d0 $fa][breq .read-ee-byte]
	[cpi d0 $f9][breq .write-ee-byte]
	[cpi d0 $f8][breq run-vm]
	[rjmp loop]

.write-ee-byte [rjmp write-ee-byte]
.read-ee-byte [rjmp read-ee-byte]

i'm-here
	[rcall bit-delay]
	[ldi d0 $23][rcall putc]
	[rjmp loop]

run-vm	[rcall getc]
	[rcall bit-delay]
	[rcall vm-entry-addr]
	[ldi d0 $8f][rcall putc]
	[rjmp loop]

read-data-byte
	[rcall getc][mov x d0]
	[rcall getc][mov xh d0]
	[rcall bit-delay]
	[ld@x d0]
	[rcall putc]
	[rjmp loop]

write-data-bytes
	[rcall getc][mov x d0]
	[rcall getc][mov xh d0]
	[rcall getc][mov t0 d0]
wdb20	[rcall getc][st@x+ d0]
	[dec t0][brne wdb20]
	[rjmp loop]

read-flash-word
	[rcall getc][mov z d0]
	[rcall getc][mov zh d0]
	[rcall bit-delay]
	[add z z][adc zh zh]
	[lpm][mov d0 r0][rcall putc]
	[inc z][lpm][mov d0 r0][rcall putc]
	[rjmp loop]

write-flash
	[rcall getc][mov x d0]
	[rcall getc][mov xh d0]
	[rcall getc][mov z d0]
	[rcall getc][mov zh d0]
	[add z z][adc zh zh]
	[cpi zh 0][breq wf90]
	[in t0 sreg][cli]
	[ldi d0 3][out d0 spmcsr][spm]		; page erase
wf10	[in d0 spmcsr][sbrc d0 0][rjmp wf10]
	[ldi d1 32]
wf20	[ld@x+ r0][ld@x+ r1]
	[ldi d0 1][out d0 spmcsr][spm]			
	[adiw z 2]
	[dec d1][brne wf20]
	[sbiw z 32][sbiw z 32]
	[ldi d0 5][out d0 spmcsr][spm]		; page write
wf40	[in d0 spmcsr][sbrc d0 0][rjmp wf40]
	[out t0 sreg]
	[ldi d0 $ef][rcall putc]
	[rjmp loop]
wf90	[rcall bit-delay]
	[ldi d0 $ee][rcall putc]
	[rjmp loop]

read-ee-byte
	[rcall getc][sts d0 eearl]
	[rcall getc][sts d0 eearh]
	[rcall bit-delay]
	[sbi eecr eere]
	[lds d0 eedr]
	[rcall putc]
	[rjmp loop]

write-ee-byte
	[rcall getc][sts d0 eearl]
	[rcall getc][sts d0 eearh]
	[rcall getc][sts d0 eedr]
	[rcall bit-delay]
	[sbi eecr eempe][sbi eecr eepe]
web20	[sbic eecr eepe][rjmp web20]
	[ldi d0 $9f][rcall putc]
	[rjmp loop]


getc	[sbic pina rx][rjmp getc]
	[ldi d3 25][rcall delay]	; wait 1/4 of a bit time
	[ldi d2 8]
getc20	[rcall bit-delay]
	[sec][sbis pina rx][clc]
	[ror d0]
	[dec d2][brne getc20]
	[rjmp bit-delay]

putc	[cbi porta tx]
	[rcall bit-delay]
	[ldi d2 8]
putc20	[sbrc d0 0][sbi porta tx]
	[sbrs d0 0][cbi porta tx]
	[lsr d0]
putc30	[rcall bit-delay]
	[dec d2][brne putc20]
	[sbi porta tx]
	[rcall bit-delay]
	[ret]	

bit-delay
	[ldi d3 103]
delay	[nop][nop][nop][nop][nop]
	[dec d3][brne delay]
	[nop]
	[ret]


end
