;Tic-Tac-Toe Logic
;;***************************************
;;***** Final Project on 8515 *************
;;***************************************
;Fully interrupt driven
;Strings can come from flash or RAM.
.include "c:\users\ca\4414def.inc"
.device AT90S4414
.def save =r1 ;saves the SREG in ISRs
.def reload =r2 ;timer 0 interval
.def lcdstat =r3
.def key =r4
.def temp =r16 ;temporary register
.def charcnt =r17 ;a counter to use in message
.def savSREG =r8 ;save the status register
.def TXbusy =r19 ;transmit busy flag
.def RXchar =r20 ;a received character
.def TXflash =r21 ;text to be sent is in flash if <>0
.def TXram =r22 ;recieved counter
.def timeout =r23
.def temp2 =r24
.def butnum =r25 ;input number in hex
.def temp3 =r26
;-------------------------------------------------
;tic tac toe registers
;-------------------------------------------------
.def Xreg1 =r27
.def Xreg2 =r28
.def Yreg1 =r29
.def Yreg2 =r18
.def currentmove=r20
.def moves =r17
.def valid =r26
;-------------------------------------------------
;Chess Registers
;-------------------------------------------------
.def startrow=r27
.def endrow =r28
.def startcol=r29
.def endcol =r18
.def type =r20
.def color =r26
;***** Other equates
.equ lcdrs =PD6 ;LCD rs pin connected to PD6
.equ lcdrw =PD5 ;LCD r/w pin connected to PD5
.equ lcde =PD4 ;LCD e pin connected to PD4
.equ baud96 =25 ;9600 baud constant for 4Mhz crystal
.equ white ='w'
.equ black ='b'
.equ pawn ='P'
.equ rook ='R'
.equ knight ='K'
.equ bishop ='B'
.equ king ='U'
.equ queen ='Q'
;**************************************
.dseg
;define variable strings to be tranmitted from RAM
board: .byte 3 ;board counter
tic0: .byte 2 ;boardnumber
tic1: .byte 6 ;first tic row + a zero terminate
tic2: .byte 6 ;second tic row + a zero terminate
tic3: .byte 6 ;third tic row + a zero terminate
chess1: .byte 26 ;1 row chess
chess2: .byte 26 ;2 row chess
chess3: .byte 26 ;3 row chess
chess4: .byte 30 ;4 row chess
chess5: .byte 30 ;5 row chess
chess6: .byte 30 ;6 row chess
chess7: .byte 30 ;7 row chess
chess8: .byte 30 ;8 chess
;**************************************
.cseg
.org $0000
rjmp RESET ;reset entry vector
reti
reti
reti
reti
reti
reti
rjmp t0int
reti
rjmp RXdone ;UART receive done
rjmp TXempty ;UART buffer empty
rjmp TXdone ;UART transmit done
reti
;define fixed strings to be tranmitted from flash- zero terminated
ticln: .db "-----", 0x00
chln: .db "------------------------", 0x00
crlf: .db 0x0d, 0x0a, 0x00 ;carrage return/line feed
;The following table is used to convert raw button-press high/low
;values to a sequence number. Invalid codes caused by multiple
;button presses are ignored.
keytbl: .db 0b11101110, 0b11101101, 0b11101011, 0b11100111
.db 0b11011110, 0b11011101, 0b11011011, 0b11010111
.db 0b10111110, 0b10111101, 0b10111011, 0b10110111
.db 0b01111110, 0b01111101, 0b01111011, 0b01110111
asciikey:
.db "123A456B789C*0#D"
welcome:
.db " A-Tic B-Chess",0x00
invalid:
.db "Not a valid move-",0x00
xmove: .db "X make a move",0x00
ymove: .db "O make a move",0x00
cats: .db " Tie - Cats Game",0x00
xwin: .db "X WINS!", 0x00
ywin: .db "O WINS!", 0x00
RESET: ldi temp, LOW(RAMEND) ;setup stack pointer
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
ser Temp
out DDRB, Temp
ldi Temp,0x00
out PortB, Temp
;set up timer 0 for 1
mSec ticks
ldi
Temp, 3 ;prescale timer
by 64
out
TCCR0, Temp
ldi
Temp,256-62 ;preload timer since
out
TCNT0, Temp ;62.5 x (64x.25) microSec = 1.0 mSec.
ldi Temp, 0b00000010
out TIMSK, Temp
;initial conditions
clr TXbusy ;start out not busy on TX
;setup UART -- enable TXempty & RXdone int, and RX, TX pins
ldi temp, 0b10111000
out UCR, temp
;set baud rate to 9600
ldi temp, baud96
out UBRR, temp
;intialize text pointer BEFORE turning on interrupts
;because RESET causes the TX empty flag to be SET
ldi ZL, LOW(ticln<<1) ;do shift to convert word-addr
to byte
ldi ZH, HIGH(ticln<<1)
;---------------------------------------------------------------------------------------
;initial tic-tac-toe board and chess board
;---------------------------------------------------------------------------------------
.include "c:\users\ca\initial.asm"
sei
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
;----------------------------------------------------------------------------------------
;this is where we start
;----------------------------------------------------------------------------------------
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
Begin: ldi ZL, LOW(welcome<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(welcome<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
choose: rcall getkey
ldi timeout, 255
rcall delay
ldi timeout, 255
rcall delay
cpi RXchar,'A'
breq TicTacToeinit
cpi RXchar,'B'
;breq Chessinit
rjmp choose
TicTacToeinit:
clr moves
clr Xreg1
clr Xreg2
clr Yreg1
clr Yreg2
clr currentmove
rcall PrTicBd
Xturn:
ldi ZL, LOW(xmove<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(xmove<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
rcall getkey
ldi timeout, 255
rcall delay
ldi timeout, 255
rcall delay
mov currentmove,RXchar
subi currentmove,0x30
rcall TicValid
cpi Valid, 0
brne illegalx
inc moves
ldi ZL,LOW(tic0) ;store move number
ldi ZH,HIGH(tic0)
mov temp, moves
subi temp, -48
st z,temp
rcall setXreg1 ;gives control of piece to X
chkwinX:ldi temp,'X'
rcall TicBdUpdate
rcall winX
cpi Xreg1,255
breq newgame
rjmp Yturn
setXreg1:
cpi currentmove,1
breq set1
cpi currentmove,2
breq set2
cpi currentmove,3
breq set3
cpi currentmove,4
breq set4
cpi currentmove,5
breq set5
cpi currentmove,6
breq set6
cpi currentmove,7
breq set7
cpi currentmove,8
breq set8
cpi currentmove,9
breq set9
set1: ori Xreg1,0b10000000
ret
set2: ori Xreg1,0b01000000
ret
set3: ori Xreg1,0b00100000
ret
set4: ori Xreg1,0b00010000
ret
set5: ori Xreg1,0b00001000
ret
set6: ori Xreg1,0b00000100
ret
set7: ori Xreg1,0b00000010
ret
set8: ori Xreg1,0b00000001
ret
set9: ori Xreg2,0b11111111
ret
illegalx:ldi ZL, LOW(invalid<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(invalid<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi timeout,255
rcall delay
ldi timeout, 255
rcall delay
rjmp Xturn
illegaly:ldi ZL, LOW(invalid<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(invalid<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi timeout,255
rcall delay
ldi timeout, 255
rcall delay
rjmp Yturn
newgame:rjmp reset
Yturn:
ldi ZL, LOW(ymove<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(ymove<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
rcall getkey
ldi timeout, 255
rcall delay
ldi timeout, 255
rcall delay
mov currentmove,RXchar
subi currentmove,0x30
rcall TicValid
cpi Valid, 0
brne illegaly
inc moves
ldi ZL,LOW(tic0) ;store move number
ldi ZH,HIGH(tic0)
mov temp, moves
subi temp, -48
st z,temp
rcall setYreg1 ;gives control of piece to Y
chkwinY:ldi temp,'O'
rcall TicBdUpdate
rcall winY
cpi Yreg1,255
breq newgame
rjmp Xturn
setYreg1:
cpi currentmove,1
breq yset1
cpi currentmove,2
breq yset2
cpi currentmove,3
breq yset3
cpi currentmove,4
breq yset4
cpi currentmove,5
breq yset5
cpi currentmove,6
breq yset6
cpi currentmove,7
breq yset7
cpi currentmove,8
breq yset8
cpi currentmove,9
breq yset9
yset1: ori Yreg1,0b10000000
ret
yset2: ori Yreg1,0b01000000
ret
yset3: ori Yreg1,0b00100000
ret
yset4: ori Yreg1,0b00010000
ret
yset5: ori Yreg1,0b00001000
ret
yset6: ori Yreg1,0b00000100
ret
yset7: ori Yreg1,0b00000010
ret
yset8: ori Yreg1,0b00000001
ret
yset9: ori Yreg2,0b11111111
ret
;---------------------------------------------------------------------------
;chech for winning conditions
;---------------------------------------------------------------------------
winX: mov temp, Xreg1
andi temp,0b11100000
cpi temp,0b11100000
breq Xmatch
mov temp, Xreg1
andi temp,0b00011100
cpi temp,0b00011100
breq Xmatch
mov temp, Xreg1
andi temp,0b10010010
cpi temp,0b10010010
breq Xmatch
mov temp, Xreg1
andi temp,0b01001001
cpi temp,0b01001001
breq Xmatch
mov temp, Xreg1
andi temp,0b00101010
cpi temp,0b00101010
breq Xmatch
cpi Xreg2, 255
brne Xend
mov temp,Xreg1
andi temp,0b00000011
cpi temp,0b00000011
breq Xmatch
mov temp, Xreg1
andi temp,0b00100100
cpi temp,0b00100100
breq Xmatch
mov temp,Xreg1
andi temp,0b10001000
cpi temp,0b10001000
breq Xmatch
cpi moves,9
breq catscase
Xend: cpi moves,9
breq catscase
ret
Xmatch: ser Xreg1
ser Xreg2
ldi ZL, LOW(xwin<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(xwin<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ret
catscase:
ser Xreg1
ser Xreg2
ldi ZL, LOW(cats<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(cats<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ret
winY: mov temp, Yreg1
andi temp,0b11100000
cpi temp,0b11100000
breq Ymatch
mov temp, Yreg1
andi temp,0b00011100
cpi temp,0b00011100
breq Ymatch
mov temp, Yreg1
andi temp,0b10010010
cpi temp,0b10010010
breq Ymatch
mov temp, Yreg1
andi temp,0b01001001
cpi temp,0b01001001
breq Ymatch
mov temp, Yreg1
andi temp,0b00101010
cpi temp,0b00101010
breq Ymatch
cpi Yreg2, 255
brne Yend
mov temp,Yreg1
andi temp,0b00000011
cpi temp,0b00000011
breq Ymatch
mov temp, Yreg1
andi temp,0b00100100
cpi temp,0b00100100
breq Ymatch
mov temp,Yreg1
andi temp,0b10001000
cpi temp,0b10001000
breq Ymatch
Yend: ret
Ymatch: ser Yreg1
ser Yreg2
ldi ZL, LOW(ywin<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(ywin<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ret
;------------------------------------------------------------------------
;Check for valid moves
;------------------------------------------------------------------------
TicValid:
clr Valid
cpi currentmove,1
breq valid1
cpi currentmove,2
breq valid2
cpi currentmove,3
breq valid3
cpi currentmove,4
breq valid4
cpi currentmove,5
breq valid5
cpi currentmove,6
breq valid6
cpi currentmove,7
breq valid7
cpi currentmove,8
breq valid8
cpi currentmove,9
breq valid9
cpi currentmove,1
brlo nogood
cpi currentmove,0xa
brge nogood
valid1: sbrc Yreg1,7
rjmp nogood
sbrc Xreg1,7
rjmp nogood
ret
valid2: sbrc Yreg1,6
rjmp nogood
sbrc Xreg1,6
rjmp nogood
ret
valid3: sbrc Yreg1,5
rjmp nogood
sbrc Xreg1,5
rjmp nogood
ret
valid4: sbrc Yreg1,4
rjmp nogood
sbrc Xreg1,4
rjmp nogood
ret
valid5: sbrc Yreg1,3
rjmp nogood
sbrc Xreg1,3
rjmp nogood
ret
valid6: sbrc Yreg1,2
rjmp nogood
sbrc Xreg1,2
rjmp nogood
ret
valid7: sbrc Yreg1,1
rjmp nogood
sbrc Xreg1,1
rjmp nogood
ret
valid8: sbrc Yreg1,0
rjmp nogood
sbrc Xreg1,0
rjmp nogood
ret
valid9: sbrc Yreg2,0
rjmp nogood
sbrc Xreg2,0
rjmp nogood
ret
nogood: ldi valid, 1
ret
;------------------------------------------------------------------------
;Update board
;------------------------------------------------------------------------
TicBdUpdate:
ldi ZL, LOW(tic1) ;shifted becuase pgm memory is words
ldi ZH, HIGH(tic1)
mov temp2,currentmove
subi temp2,1
lsl temp2
jumpto: cpi temp2,0
breq putit
dec temp2
ld temp3,z
st z+,temp3
rjmp jumpto
putit: st z,temp
rcall PrTicBd
ret
;----------------------------------------------------------------------------------------
;Print Board for Tic-Tac-Toe
;----------------------------------------------------------------------------------------
PrTicBd:
;print tic-tac-toe board
;setup ptr for <crlf> string
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
;line1
ldi ZL, LOW(tic0)
ldi ZH, HIGH(tic0)
ld r0,Z
out UDR, r0
clr TXflash
ser TXbusy
sbi UCR, UDRIE
rcall TXwait
;setup ptr for <crlf> string
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
;line1
ldi ZL, LOW(tic1)
ldi ZH, HIGH(tic1)
ld r0, Z
out UDR, r0
clr TXflash
ser TXbusy
sbi UCR, UDRIE
rcall TXwait
rcall Ticline
;line2
ldi ZL, LOW(tic2)
ldi ZH, HIGH(tic2)
ld r0, Z
out UDR, r0
clr TXflash
ser TXbusy
sbi UCR, UDRIE
rcall TXwait
rcall Ticline
;line3
ldi ZL, LOW(tic3)
ldi ZH, HIGH(tic3)
ld r0, Z
out UDR, r0
clr TXflash
ser TXbusy
sbi UCR, UDRIE
rcall TXwait
;setup ptr for <crlf> string
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ret
Ticline:
;setup ptr for <crlf> string
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
;setup ptr for <----> string
ldi ZL, LOW(ticln<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(ticln<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
;setup ptr for <crlf> string
ldi ZL, LOW(crlf<<1) ;shifted becuase pgm memory
is words
ldi ZH, HIGH(crlf<<1)
lpm
out UDR, r0 ;trigger the UART TX
ser TXflash ;text string in flash memory
ser TXbusy ;and set the TX busy flag
sbi UCR, UDRIE ;enable the TXempty interrupt
rcall TXwait
ret
;************************************************************************************************
;interrupt routines
;************************************************************************************************
sendTxt:
tst TXram
brne _sndRAM
lpm
rjmp _sndFLSH
_sndRAM: ld r0,Z
_sndFlsh:tst r0
breq _sndEND
cpi charcnt,8
brne _writit
ldi temp, 0xC0
;rcall lcdcmd
_writit:mov temp, r0
;rcall lcdput
inc charcnt
adiw ZL,1
rjmp sendTxt
_sndEND:ret
; UART needs a character
TXempty:in savSREG, SREG ;save processor status
tst TXflash ;Is the string in flash memory?
breq TXram ;If not, it is in RAM
inc ZL ;get the next char from flash
lpm ;and put it in r0
rjmp TXfls
TXram: inc ZL ;get the next char from RAM
ld r0,Z
TXfls: tst r0 ;if char is zero then exit
breq TXend
out UDR, r0 ;otherwise transmit it
rjmp TXexit ;exit until next char
TXend: clr TXbusy ;no more chars
cbi UCR, UDRIE ;clear the TXempty interrupt
TXexit: out SREG, savSREG ;restore proc status
reti ;back to pgm
; TX done -- buffer is empty -- unused here
TXdone: in savSREG, SREG ;save processor status
out SREG, savSREG ;restore proc status
reti ;back to pgm
; UART read a character
RXdone: in savSREG, SREG ;save processor status
in RXchar, UDR ;get the character
out SREG, savSREG ;restore proc status
reti ;back to pgm
;*****************************
;subroutine
TXwait: tst TXbusy ;now wait for the tranmission to finish
brne TXwait
ret
;****************getkey function*******************************
getkey:
push temp
push temp2
loop: clr temp2
ldi timeout,30
rcall delay
ldi temp, 0x0f ;set lower four lines to output
out DDRA, temp
ldi temp, 0xf0 ;and turn on the pullups on the inputs
out PORTA, temp
nop ;Need some time for the pullups to
nop ;charge the port pins
nop
nop
in temp, PINA ;read the high nibble
mov key, temp ;and store it (with zeros in the low nibble)
ldi temp, 0xf0 ;set upper four lines to outputs
out DDRA, temp
ldi temp, 0x0f ;and turn on pullups on the inputs
out PORTA, temp
nop ;As before wait for the pin to charge
nop
nop
nop
in temp, PINA ;read the low nibble
or key, temp ;combine to make key code
ldi temp,0xff
cp key,temp
breq illegal
;At the point the raw key code should have exactly one zero
each in
;the lower and upper nibbles. Any other number of zeros indicates
;either no-button pressed or multiple-button pressed.
;Now search the table for a match to the raw key code
;and exit with a button number
ldi ZL, low(keytbl*2) ;table pointer in FLASH
ldi ZH, high(keytbl*2) ;so convert from word to byte addr
ldi butnum, 0
tbllp: lpm ;get the table entry
cp key, r0 ;match?
breq foundit
inc butnum ;if not, have we exhaused the
cpi butnum, 0x10 ;table
breq illegal
adiw ZL, 1 ;if not, get the next table entry
rjmp tbllp
foundit:;now lookup from ascii table
ldi ZL, low(asciikey*2) ;table pointer in FLASH
ldi ZH, high(asciikey*2) ;so convert from word to byte addr
clr temp
add ZL,butnum
adc ZH,temp
lpm
mov RXchar,r0
out PORTB, butnum
pop temp2
pop temp
ret
illegal:;nothing found, return to waiting
tst temp2
brne _getdone
rjmp loop
_getdone:
pop temp2
pop temp
ret
;=============================================
; subroutine waits for time equal to value in register timeout
;the register 'timeout' should be loaded before the call
delay: tst timeout
brne delay
ret
;=============================================
;***** Timer 0 overflow interrupt handler
;timer 0 ISR (timer-zero overflow)
;Enters every 1.0 mSec
t0int: in save, SREG
push temp
ldi temp,256-62
out TCNT0, temp ; keeps clock ticking at 1 mSec
dec timeout ;subtract another mSec
out SREG, save
pop temp
reti ;back to backgound tasks