Note this code appears to work but the printer rejects chips it can't write too. I'm sure I could work around this but I have other things to do.
AVRASM ver. 2.1.9 E:\avr\mega8inkchip\ROchip.asm Sat Sep 20 12:57:29 2008
Copyright Eddie Matejowsky.
Free for non-commercial use only.
E:\avr\mega8inkchip\ROchip.asm(2): Including file 'E:\avr\mega8inkchip\m8def.inc'
.list
.CSEG
; working registers for the program.
//.def EEdata = r13
//.def EEPending = r14
.def chipId = r15
.def temp = r16
.def counter1 = r17 ; counters for various routines.
.def EEcount = r18
.def counter2 = r19
.def counter0 = r20
.def count = r21 ; Bit counter
.def serbyte = r22
.def work1 = r23
.def EEindex = r24
.def SyncFlag = r25
.MACRO led1on
cbi PORTC,PB2 ; LED ON
.ENDMACRO
.MACRO led1off
sbi portc,PB2 ; LED OFF
.ENDMACRO
.MACRO led2on
sbi PORTD,PB2 ; LED ON
.ENDMACRO
.MACRO led2off
cbi portD,PB2 ; LED OFF
.ENDMACRO
;Reset vector (must be the first code generated)
000000 c00b rjmp RESET ; Reset Handler
000001 9518 reti ; Ext Interrupt 0 Handler (not used)
000002 9518 reti ; Ext Interrupt 1 Handler (not used)
000003 9518 reti ; Timer1 Capture Handler
000004 9518 reti ; Timer1 Compare Handler
000005 9518 reti ; Timer1-B compare Handler (not used)
000006 9518 reti ; Timer1 Overflow Handler (not used)
000007 9518 reti ; Timer0 Overflow Handler
000008 9518 reti
000009 9518 reti
00000a 9518 reti
00000b 9518 reti
;-----------------------------------------------------------------
; code starts executing here on reset
RESET:
00000c 98a4 cbi dataddr,data0bit;
00000d 98a5 cbi dataddr,data1bit;
00000e 98ac cbi dataport,data0bit;
00000f 98ad cbi dataport,data1bit;
000010 e50f ldi temp,LOW(RAMEND) ; set the stack pointer
000011 bf0d out SPL, temp
000012 e004 ldi temp,HIGH(RAMEND)
000013 bf0e out SPH, temp
000014 9aa2 sbi DDRC,PB2 ; Enable led driver.
000015 9a8a sbi DDRD,PB2 ; Enable led driver.
000016 9aaa led1off
000017 9892 led2off
; Work out chip ID from EEPROM data.
000018 e38f ldi EEindex,$3f // the ID bits are in eeprom cell x3f
000019 d07d rcall readee // read the eeprom.
00001a 9506 lsr temp // move the ID bit into the bottom 3 bits.
00001b 9506 lsr temp
00001c 9506 lsr temp
00001d 9506 lsr temp
00001e 7007 andi temp,7 // this shouldn't be needed.
00001f 2ef0 mov chipId,temp // mov the ID into another register where it stays forever.
wait4sync:
000020 d06e rcall waitsyncPL // if sync is low wait.
// led1on
000021 d03d rcall getnib // get the three ID bits and the R/W bit.
000022 2399 tst SyncFlag // see if sync went low before nib was recieved.
000023 f421 brne waitchip2 // sync was low back to start
000024 2d7f mov work1,chipId // get chip ID from low register to working register.
000025 1707 cp temp,work1 // compare - will be equal if ID matches and R/W = read mode.
000026 f409 brne waitchip2 // if not equal we jump to test for write mode.
000027 d002 dosend: rcall senddata // The ID etc match so we call the rountine to dump the EEPROM data to the printer.
waitchip2:
000028 d06a rcall waitsyncNL // wait for sync to go low (if it isn't already) before looping back.
000029 cff6 rjmp wait4sync
;--------------------------------------------------------------------------------------------------------
senddata: // Send EEPROM data to the printer.
00002a 9a92 led2on
00002b e280 ldi EEindex,$20 // This is where the data lives in the EEPROM.
00002c e220 ldi EEcount,$20 // This is the maximum number of bytes to fetch and send.
// rcall waitclkhilo
00002d d03e rcall waitclkNL // we wait a 1/2 bit cycle
00002e 9aa4 sbi dataddr,data0bit; // make the data pin an output.
EEDumpLoop:
00002f d067 rcall readee // read a byte
000030 d051 rcall SendByte // send a byte
000031 2399 tst SyncFlag // see if sync became low
000032 f419 brne dumpret // if so exit.
000033 9583 inc EEindex // inc address
000034 952a dec EEcount // dec counter
000035 f7c9 brne EEDumpLoop // repeat if non-zero
dumpret:
000036 98a4 cbi dataddr,data0bit; // make the data pin and input again.
000037 98ac cbi dataport,data0bit; // zero the databit so there is no pullup
000038 9892 led2off
000039 9508 ret
;--------------------------------------------------------------------------------------------------------
waitstrt: ; look for positive edge of "start" line - not the clock.
00003a b300 in temp,syncpin // read the io port
00003b 7400 andi temp,1<<syncbit // extract the wanted sync bit
00003c f7e9 brne waitstrt // if pin was high repeat loop
waitclkhi:
00003d b300 in temp,syncpin // read the io port
00003e 7400 andi temp,1<<syncbit // extract the wanted sync bit
00003f f3e9 breq waitclkhi // if pin was low repeat loop fall through if high
000040 9508 ret
;--------------------------------------------------------------------------------------------------------
; note sync and clock are on different ports. Code for pins on same port could be shorter.
; clock and data are on the same port so data can be returned in temp.
waitclkPE: // wait for rising clk edge
000041 2799 clr SyncFlag
wtclklo:
000042 b300 in temp,syncpin // read the io port
000043 7400 andi temp,1<<syncbit // extract the wanted sync bit
000044 f059 breq noclk // if low exit and flag it
000045 b303 in temp,clockpin // read the io port
000046 7002 andi temp,1<<clockbit // extract the wanted clock bit
000047 f7d1 brne wtclklo // repeat if clock high
wtclkhi:
000048 b300 in temp,syncpin // read the io port
000049 7400 andi temp,1<<syncbit // extract the wanted sync bit
00004a f029 breq noclk // if low exit and flag it
00004b b373 in work1,clockpin // read the io port
00004c 2f07 mov temp,work1 // move to work to preserve data bit in temp
00004d 7072 andi work1,1<<clockbit // extract the wanted clock bit
00004e f3c9 breq wtclkhi // repeat if clock low
00004f 9508 ret
noclk: // if we are here sync was low.
000050 ef9f ser SyncFlag // flag sync as invalid
000051 9508 ret
;--------------------------------------------------------------------------------------------------------
getbyte: ; get byte from serial stream return type in temp or ff in temp if timeout etc
000052 2766 clr serbyte // clear sync flag register
000053 e038 ldi counter2,8 // set counter for 8
byteloop:
000054 dfec rcall waitclkPE // wait for clk high edge, data bit in temp and sync flag returned
000055 2399 tst SyncFlag // test for sync low.
000056 f439 brne abortGB // if low return.
000057 9566 lsr serbyte // shift the shifter
// andi temp,1<<data0bit|1<<data1bit
000058 7100 andi temp,1<<data0bit // extract the data bit
000059 f009 breq cntloop2 // if zero skip to loop counting
00005a 6860 ori serbyte,$80 // if databit is one - make msb bit a one
cntloop2:
00005b 953a dec counter2 // dec counter
00005c f7b9 brne byteloop // loop repeat if not zero.
00005d 2f06 mov temp,serbyte // byte received move to temp.
00005e 9508 abortGB: ret
;--------------------------------------------------------------------------------------------------------
getnib: ; get nibble from serial stream, return nibble in temp, ret if timeout etc
00005f 2766 clr serbyte // clear sync flag register
000060 e034 ldi counter2,4 // set counter for 4
nibloop:
000061 dfdf rcall waitclkPE // wait for clk high edge, data bit in temp and sync flag returned
000062 2399 tst SyncFlag // test for sync low.
000063 f439 brne nonib // if low return.
000064 9566 lsr serbyte // shift the shifter
// andi temp,1<<data0bit|1<<data1bit
000065 7100 andi temp,1<<data0bit // extract the data bit
000066 f009 breq cntloop // if zero skip to loop counting
000067 6068 ori serbyte,8 // make high bit a one
cntloop:
000068 953a dec counter2 // dec counter
000069 f7b9 brne nibloop // loop repeat if not zero.
00006a 2f06 mov temp,serbyte // byte received move to temp.
// ret
nonib:
// ldi temp,$f0
00006b 9508 ret
;--------------------------------------------------------------------------------------------------------
waitclkNL: // wait for clock line to go low. If sync goes low flag it and exit.
00006c 2799 clr SyncFlag // clear sync flag
wtclkhi3:
00006d b300 in temp,syncpin // read the io port
00006e 7400 andi temp,1<<syncbit // extract the wanted sync bit
00006f f301 breq noclk // if low exit and flag it
000070 b303 in temp,clockpin // read the io port
000071 7002 andi temp,1<<clockbit // extract the wanted clock bit
000072 f7d1 brne wtclkhi3 // if bit is high repeat loop
000073 9508 ret
;--------------------------------------------------------------------------------------------------------
waitclkNE: // wait for clock line to be high then low. If sync goes low flag it and exit.
000074 2799 clr SyncFlag // clear sync flag
wtclkhi2:
000075 b300 in temp,syncpin // read the io port
000076 7400 andi temp,1<<syncbit // extract the wanted sync bit
000077 f2c1 breq noclk // if low exit and flag it
000078 b373 in work1,clockpin // read the io port
000079 7072 andi work1,1<<clockbit // extract the wanted clock bit
00007a f3d1 breq wtclkhi2 // if bit is low repeat loop
wtclklo2:
00007b b300 in temp,syncpin // read the io port
00007c 7400 andi temp,1<<syncbit // extract the wanted sync bit
00007d f291 breq noclk // if sync low exit and flag it
00007e b303 in temp,clockpin // read the io port
00007f 7002 andi temp,1<<clockbit // extract the wanted clock bit
000080 f7d1 brne wtclklo2 // if bit is high repeat loop
000081 9508 ret
;--------------------------------------------------------------------------------------------------------
SendByte: ; send byte in temp to printer/chip reader - this rouintine does not set the pin direction.
000082 e038 ldi counter2,8 // set up to count 8 bits
000083 2f60 mov serbyte,temp // mov char into shifter
OutLoop:
000084 9566 lsr serbyte // shift byte = low > carry
000085 f410 brcc OutLow // if carry clear jump to "output a low"
000086 9aac sbi dataport,data0bit // we are sending a one so set output pin high.
000087 c001 rjmp DecOutCount // go to loop counting code.
OutLow:
000088 98ac cbi dataport,data0bit // output a low - set pin low.
DecOutCount:
000089 dfea rcall waitclkNE // wait for a clock edge or sync low.
00008a 2399 tst SyncFlag // was sync low.
00008b f411 brne abort // yes it was low leave loop and return.
00008c 953a dec counter2 // dec counter
00008d f7b1 brne OutLoop // if non-zero repeat loop
00008e 9508 abort: ret // either the byte was sent or sync went low - return.
;--------------------------------------------------------------------------------------------------------
waitsyncPL: ; look for positive LEVEL of "sync" line - not the clock.
00008f b300 in temp,syncpin
000090 7400 andi temp,1<<syncbit
000091 f3e9 breq waitsyncPL // wait for sync high level
000092 9508 ret
;--------------------------------------------------------------------------------------------------------
waitsyncNL: ; look for negative LEVEL of "sync" line - not the clock.
000093 b300 in temp,syncpin
000094 7400 andi temp,1<<syncbit
000095 f7e9 brne waitsyncNL // wait for sync high level
000096 9508 ret
;--------------------------------------------------------------------------------------------------------
; look in atmel data sheet for epprom programming info.
readee:
000097 2700 clr temp
000098 bb0f out eearh,temp
000099 bb8e out eearl,EEindex
00009a e001 ldi temp,1<<eere
00009b bb0c out eecr,temp
00009c b30d in temp,eedr
00009d 9508 ret
RESOURCE USE INFORMATION
------------------------
Notice:
The register and instruction counts are symbol table hit counts,
and hence implicitly used resources are not counted, eg, the
'lpm' instruction without operands implicitly uses r0 and z,
none of which are counted.
x,y,z are separate entities in the symbol table and are
counted separately from r26..r31 here.
.dseg memory usage only counts static data declared with .byte
ATmega8 register use summary:
r0 : 0 r1 : 0 r2 : 0 r3 : 0 r4 : 0 r5 : 0 r6 : 0 r7 : 0
r8 : 0 r9 : 0 r10: 0 r11: 0 r12: 0 r13: 0 r14: 0 r15: 2
r16: 46 r17: 0 r18: 2 r19: 6 r20: 0 r21: 0 r22: 10 r23: 7
r24: 4 r25: 9 r26: 0 r27: 0 r28: 0 r29: 0 r30: 0 r31: 0
x : 0 y : 0 z : 0
Registers used: 8 out of 35 (22.9%)
ATmega8 instruction use summary:
adc : 0 add : 0 adiw : 0 and : 0 andi : 17 asr : 0
bclr : 0 bld : 0 brbc : 0 brbs : 0 brcc : 1 brcs : 0
break : 0 breq : 11 brge : 0 brhc : 0 brhs : 0 brid : 0
brie : 0 brlo : 0 brlt : 0 brmi : 0 brne : 15 brpl : 0
brsh : 0 brtc : 0 brts : 0 brvc : 0 brvs : 0 bset : 0
bst : 0 call : 0 cbi : 9 cbr : 0 clc : 0 clh : 0
cli : 0 cln : 0 clr : 6 cls : 0 clt : 0 clv : 0
clz : 0 com : 0 cp : 1 cpc : 0 cpi : 0 cpse : 0
dec : 4 eicall: 0 eijmp : 0 elpm : 0 eor : 0 fmul : 0
fmuls : 0 fmulsu: 0 icall : 0 ijmp : 0 in : 15 inc : 1
jmp : 0 ld : 0 ldd : 0 ldi : 9 lds : 0 lpm : 0
lsl : 0 lsr : 7 mov : 6 movw : 0 mul : 0 muls : 0
mulsu : 0 neg : 0 nop : 0 or : 0 ori : 2 out : 5
pop : 0 push : 0 rcall : 11 ret : 12 reti : 11 rjmp : 3
rol : 0 ror : 0 sbc : 0 sbci : 0 sbi : 6 sbic : 0
sbis : 0 sbiw : 0 sbr : 0 sbrc : 0 sbrs : 0 sec : 0
seh : 0 sei : 0 sen : 0 ser : 1 ses : 0 set : 0
sev : 0 sez : 0 sleep : 0 spm : 0 st : 0 std : 0
sts : 0 sub : 0 subi : 0 swap : 0 tst : 5 wdr : 0
Instructions used: 22 out of 114 (19.3%)
ATmega8 memory use summary [bytes]:
Segment Begin End Code Data Used Size Use%
---------------------------------------------------------------
[.cseg] 0x000000 0x00013c 316 0 316 9999999 0.0%
[.dseg] 0x000060 0x000060 0 0 0 9999999 0.0%
[.eseg] 0x000000 0x000000 0 0 0 9999999 0.0%
Assembly complete, 0 errors, 0 warnings
eddie