| CODE |
.include "tn12def.inc" ;When Programming the chip: ;1. Select the Low Freuqency Crystal oscillator 67ms + 32k clock ;2. Disable Reset to free up pin 1 as open drain output ;serial version major and minor revision leves. .equ version = $00;0 starting August 20, 2002 (cleaned up terms in notes 040407 ;.equ revision= 5;alarm sets output low ;.equ revision= 6;corrected error in cjump $0D ;.equ revision= 7;saved a byte ;.equ revision= 8;or and and with contreg instructions ;.equ revision= 9;reset alarm via ds port ;.equ revision= $A;consolidate "ACK by pulling attn line low" in receive byte; ;.equ revision= $B;timeout subroutine. ;;equ revision= $C;making attn continuously low not cause restarts ;.equ revision= $D;seems completely funcitonal settle time set to $02 ;.equ revision= $F;fast DS input response .equ revision= $11;Remove C2 and C3 commands, fix EEPROM checksum routines ;I/O pin descriptions .equ dataline= 0;B0 Data line .equ attline = 1;B1 Attention line .equ extinput= 2;B2 External Event Trigger .equ dout = 5;B5 Data output pin ; **** can use SBR instruction instead of oring with another register -save some bytes .equ initialddrb = $00; Inital value for DDRB (pin 1 default open) ;Contreg (Control Register) bit descriptions and associated constants .equ eepromok = 0;After EPROM checsum check, set to 1 if ok, otherwise 0 .equ eepromokorflag = 1;value ored with contreg to set flag .equ eepromokmask =$FE;used to clear flag by anding .equ readclockinh = 1;if 1, inhibits clock from being written to user buffer. Autocleared by write routine .equ readclockinhflag = 2;value ored with contreg to set flag .equ readclockinhmask=$FD;used to clear the falg when task completed .equ writeclock = 2;*if 1, commands user buffer to be written to clock. Autocleared by write routine .equ writelcockorflag= 4;value ored with contreg to set flag. .equ writeclockmask =$FB;used to clear the flag when task completed .equ disableclock = 3;if 1 disables clock and alarm maintenance during interrupt .equ disableclockorflag=8;value ored with contreg to set flag .equ disableclockmask=$F7;used to clear flag by anding with contreg ;note EEPROM Address 4= 4;bits 4 and 5 are used for page address in EEPROM. ;note EEPROM address 5= 5 .equ enablearlarm = 6;if 1 enables alarm maintenance during interrupt .equ enablealarmorflag=$40;value ored with contreg to set flag .equ enablealarmmask =$BF;used to clear flag by anding with contreg .equ eeprominhibit = 7;If 1 EEPROM interpreter will not execute EEPROM code .equ eeprominhibitor =$80;Ored to set bit .equ commandmask =$04;used to mask off bits that are not command request flags ; Bits marked with an asterisk, "*", are commands. ; **** note that command mask is not needed if write clock is the only interrupt time task ; commanded by one of these flags. ;intflags Internal Flags register bit assignments and associated constants .equ extint = 0;if 1, attention line filtered is disabled. Bit location in contreg. .equ extintorflag = 1;value ored with contreg to set flag .equ extintmask =$FE;used to clear flag by anding with contreg .equ execeealrm = 1;if 1, requests EEPROM code for alarm be exectued .equ execeealrmorflag= 2;value ored with contreg to set flag .equ execeealrmmask =$FD;used to clear the flag by anding .equ execextevent = 2;if 1, requests external event code be run in EEPROM .equ execexteventorflag=4;value ored with contreg to set flag. .equ execexteventmask=$FB;used to clear the flag when task completed .equ rbt = 3;if 1, readbyte has timed out .equ rbtorflag = 8;used to set bit .equ rbtandmask =$F7;used to clear bit .equ eepromstart = 4;if 1 idicates that startup code is in eeprom .equ alrmineeprom = 5;If 1, indicates that alarm handler code is in eeprom .equ alarmineepromor =$20;used to or with intflags to set flag hit (1=false) .equ alarmineepromand=$DF;used to and with intflags to clear flag bit (0=true) .equ extevpres = 6;if 0 indicates that external event eeprom code is present ;note that bits 0,1,2,3 are controlled by the firmware and ; bits 4,5,6,7, are copied from EEPROM ;EEPROM register assignments .equ eepromflags =00;address in EEPROM that EEPROM flags are kept at .equ startaddress =01;address in EEPROM that start of start up code is located at .equ alarmaddress =02;address in EEPROM that start of alarm code is located at .equ exteventaddress =03;address in EEPROM that start of external event code is located at .equ checksum =63;address in EEPROM that EEPROM checksum is kept at. this location not in calculation ;note EEPROM flags are low true because erased state of EEPROM is $FF ;note EEPROM flag bit 4 low indicates start up code is present ;note EEPROM flag bit 5 low indicates alarm code is present ;note EEPROM flag bit 6 low indicates external event code is present ;alamask (Alarm Mask Register) bit descriptions and associated constants ;function bit position description ;second mask 0 if zero, seconds ignored in testing for alarm condition ;minute mask 1 if zero, minutes ignored in testing for alarm condition ;hour mask 2 if zero, hours ignored in testing for alarm condition ;day mask 3 if zero, days ignored in testing for alarm condition ;month mask 4 if zero, months ignored in testing for alarm condition ;year mask 5 if zero, years ignored in testing for alarm condition .equ almaskinitial =$FF;Defaul value of alarm mask loaded at startup ;parameters .equ setltime =$01;How long to wait for data and I/O lines to settle .equ DStimeout =$02;How long to wait for DS Interface transaction to complete .def rectimer= r0;number of t0 interrupts within on second (used to filter attn line) .def sregtemp= r1;temporary storage of status register during interrupt time ;////start user accessible regisers: .def datareg = r2;data register user register .def regA = r3;(user accessible register 0) .def alamask = r4;alarm mask (user accessible reigster 1) .def uyear = r5;user accesible year user register 2 .def umonth = r6;user accessible month user register 3 .def uday = r7;user accessible day .def uhour = r8;user accessible hour .def uminute = r9;user accessible minute .def usecond = r10;user accessible second .def ayear = r11;alarm year (user accessible) .def amonth = r12;alarm month (user accessible) .def aday = r13;alarm day (user accessible) .def ahour = r14;alarm hour (user accessible) .def aminute = r15;alarm minute (user accessible) .def asecond = r16;alarm second (user accessible) .def contreg = r17;device control register, user register F ;/////end of user accessible registers .def intflags= r18;internal flags - not user accessible .def second = r19;second .def minute = r20;minute .def hour = r21;hour .def day = r22;day .def month = r23;month .def year = r24;year .def temp = r25;scratch .def tempi = r26;scratch for use during interrupt .def rxtxbyte= r27;byte to be sent -can be lower register .def delayc = r28;counter used for timing delay .def bitcount= r29;counter for number of bits transfered ;note that r30 and r31 used as Z register .ORG $0000 rjmp reset rjmp int0handler;external interrupt handler reti ;pin change interrupt -return rjmp tovflo ;timer overflow interrupt handler reset: ldi contreg,$00;Preload conreg flags sbis PINB,dout sbr contreg,eeprominhibitor;Inhibit eeprom execution if dout is low ldi temp,$80 out ACSR,temp ldi temp,$03 out TCCR0,temp;Set timer prescaler ldi temp,eepromflags out eear,temp;move to EEPROM address register sbi eecr,eere;Trigger the read in intflags,eedr;Get the data into temp andi intflags,$78 ;MAKE NORMAL STATE "BAILED", only bits 4,5,6 of EEPROM clr second clr minute clr hour clr day clr month clr year ldi temp,$FF;Pre-load second in user register with $FF so it can mov usecond,temp;be determined if the reigster was read before ;values are written by clock ldi asecond,$FF;Similarly, put $FF into the alarm seconds ;so alarm cab't fire until initialized. clr tempi ;presets 500 millisecond counter ldi temp,0 ;preload timer counter out TCNT0,temp ldi temp,$02;enable timer overflow interrupts out TIMSK,temp ldi temp,almaskinitial mov alamask,temp;Calculate EERPOM checksum at location 63 and set flag postreset: ;do some initialization here that can be redone to recover from send error ; ldi contreg,$00;Preload conreg flags ldi temp,initialddrb;load data direction value for PORTB out DDRB,temp;no pullups on B0 and B1 *** ; out PORTB,temp ; in intflags,eedr;Get the data into temp andi intflags,$78 ;MAKE NORMAL STATE "BAILED", only bits 4,5,6 of EEPROM ;Uses ZL,ZH,temp. Location 63 is not used in the calculation. clr ZH ;checksum kept here ldi ZL,checksum-1;pointer wratzD: sbic eecr,eewe; start new;Wait for EEPROM write to not be busy rjmp wratzD moretosum1: out eear,ZL ;move to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp add ZH,temp dec ZL cpi ZL,$FF brne moretosum1 ldi temp,checksum;Address of checksum stored in memory out eear,temp ;move to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp cp ZH,temp ;compare checksums and set flag if they match ;An unprogrammed eerpom (all FFs) will fail. brne nomatch ori contreg,eepromokorflag;Set EEPROM OK flag in internal flags register nomatch: ;DO NOT MOVE THIS ROUTINE -IT MUST BE THE LAST ROUTING IN INITIALIZATION ldi ZL,startaddress;Address of start code is stored in here move to ZL in case of execution ;Execute startup program from EEPROM of present and checksum ok sbrs contreg,eepromok; **** chance to reduce code by placing inside eeprom check rjmp nostartupcode sbrc intflags,eepromstart rjmp nostartupcode rjmp InterpretEEPROM;note that InterpretEEPROM returns to main nostartupcode: rjmp main Seteepromchecsum: ;Calculate EERPOM checksum and store in location 63. ;Uses ZL,ZH,temp. Locatoin 63 is not used in the calculation. clr ZH ;checksum kept here ldi ZL,checksum-1;pointer wratzB: sbic eecr,eewe; new;Wait for EEPROM write to not be busy rjmp wratzB moretosum: out eear,ZL ;move to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp add ZH,temp dec ZL cpi ZL,$FF brne moretosum ;Store checksum stored in ZH into EEPROM location 63 wrat1: sbic eecr,eewe;Wait for EEPROM write to not be busy rjmp wrat1 ldi ZL,checksum out eear,ZL out eedr,ZH ;Set up the write data cli ;Inhibit interrupts while triggering EPROM write sbi eecr,eemwe sbi eecr,eewe;Trigger the write sei ;re-enable interrupts now that EEPROM write has been triggered ori contreg,eepromokorflag;Set EEPROM ok flag true. rjmp main; ; end of new code ;**** set up a loop to wait until EEPROM is not busy before reading ReadEEPROM: ;Read contents of EEPROM register pointed to by ZL to datareg mov temp,contreg;Set up the write address andi temp,$30;Bits 4 and 5 of contreg select which of 4 pages are addressed add ZL,temp out eear,ZL ;move to EEPROM address register sbi eecr,eere;Trigger the read in rxtxbyte,eedr;Get the data into temp rcall SendByte rjmp main ;This rjmp instruction is being kept incase this routine is relocated main: sbrc intflags,$07 rjmp receivebyte ;//////Most routines return here//////// sbrs intflags,execeealrm;Check to see if flag is set requesting EEPROM alarm code be executed rjmp noalarmexec;If flag is set, reset flag then jump to execution routine andi intflags,execeealrmmask;Clear flag ldi ZL,alarmaddress;Load pointer to address of alarm routine rjmp InterpretEEPROM;Note InterpretEEPROM returns to main noalarmexec: ;See in an external even has occured and execute if code is present in EEPROM sbic PINB,extinput rjmp extpinishigh;If the external input is high,skip running code sbrc intflags,execextevent rjmp noexeventcode ori intflags,execexteventorflag sbrs contreg,eepromok;Execute startup program from EEPROM of present and checksum ok rjmp noexeventcode sbrc intflags,extevpres rjmp noexeventcode ldi ZL,exteventaddress;Load pointer to address of alarm routine rjmp InterpretEEPROM;Note InterpretEEPROM returns to main extpinishigh: andi intflags,execexteventmask;Set the flag to show input pin was high when looked at last noexeventcode: ldi temp,$22;enable sleep and set T0 to respond to falling edge out MCUCR,temp;enable sleep mode ldi temp,$40;enable external interrupt 0 out GIMSK,temp sei ;assure interrupts are enabled sleep ;good night. Wait for the attention line to go low (interrupt 0) sbrs intflags,extint rjmp main andi intflags,extintmask ; rjmp ReceiveByte recrtn: brcc CarryIsClear;if carry is not set, its data, so place in datareg. ; //////Interpret DataShake input as an instruction////// ;If carry is not set, interpret as an instruction. ;make lower nybble register pointer just in case its needed mov ZL,rxtxbyte;move pointer into ZL register andi ZL,$0F ;mask off upper nybble ldi ZH,$00 andi rxtxbyte,$F0;mask off lower nybble in rxtxbyte ;and interpret the command cpi rxtxbyte,$10;test for store instruction breq storereg cpi rxtxbyte,$20;test for read instruction breq readreg cpi rxtxbyte,$30;test for dump clock command breq DumpTimenow cpi rxtxbyte,$40;test for write EEPROM command breq WriteEEPROM cpi rxtxbyte,$50;test for read EEPROM command breq ReadEEPROM cpi rxtxbyte,$60 brne noeepromexec mov ZL,datareg;Put start address in ZL as pointer to first instruction rjmp continueeprom noeepromexec: cpi rxtxbyte,$70;test for generate and write EEPROM checksum and update EEPROM-realted flags brne dontsetchecksum;Extra byte is because of branch out of range. ldi temp,eepromflags out eear,temp;move to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp andi temp,$F0;Only upper 4 bits from EEPROM or intflags,temp rjmp Seteepromchecsum dontsetchecksum: cpi rxtxbyte,$80 brne noversionno ldi rxtxbyte,version;READ BYTE FROM REGISTER clc ;clear the carry becuase data is being sent rcall SendByte ldi rxtxbyte,revision rcall SendByte rjmp main noversionno: cpi rxtxbyte,$90;Check -reset alarm? brne noalarmoff cbi DDRB,dout rjmp main noalarmoff: rjmp main ;finished fetching and interpreting. go for another byte storereg: ;STORE INCOMING BYTE INTO DATAREG ldi temp,02 ; add ZL,temp ;point to registers 2 thrugh 17 st Z,datareg rjmp main readreg: ldi temp,02 ; add ZL,temp ;point to registers 2 thrugh 17 ld rxtxbyte,Z;READ BYTE FROM REGISTER clc ;clear the carry becuase data is being sent rcall SendByte rjmp main CarryIsClear: ;If carry is clear, its data -store in data register mov datareg,rxtxbyte rjmp main DumpTimenow: ;dump time over DS line mov ZH,contreg;save contreg to ZH ori contreg,$02;inhibit reads from clock to user registers during this process mov rxtxbyte,uyear;dump the data rcall SendByte mov rxtxbyte,umonth ; **** replace "ori contreg,$02 with equated value rcall SendByte mov rxtxbyte,uday rcall SendByte mov rxtxbyte,uhour rcall SendByte mov rxtxbyte,uminute rcall SendByte mov rxtxbyte,usecond rcall SendByte mov contreg,ZH rjmp main WriteEEPROM: ;Write contents of datareg into EEPROM register pointed to by ZL wrat: sbic eecr,eewe;Wait for EEPROM write to not be busy rjmp wrat mov temp,contreg;Set up the write address andi temp,$30;Bits 4 and 5 of contreg select which of 4 pages are addressed add ZL,temp out eear,ZL out eedr,datareg;Set up the write data cli ;Inhibit interrupts while triggering EPROM write sbi eecr,eemwe sbi eecr,eewe;Trigger the write sei ;re-enable interrupts now that EEPROM write has been triggered rjmp main ; //////Interpret EEPROM contents////// InterpretEEPROM: ;must enter with ZL set to vector out eear,ZL ;move to EEPROM address register sbi eecr,eere;Trigger the read in ZL,eedr ;Get the data into temp continueeprom: ;Alternative entry point with Z: already pointing to first instruction sbrc contreg,eeprominhibit rjmp eepromstop out eear,ZL ;move pointer to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp cpi temp,$01 breq resetclock cpi temp,$02 brne nodouthigh cbi DDRB,dout;Set that output pin high nodouthigh: cpi temp,$03 brne nodoutlow sbi DDRB,dout;Set that output pin low nodoutlow: cpi temp,$04;Test for "Or next byte with contreg". brne notor inc ZL ;Enter with ZL pointing to instruction, extits with ZL poiting to value out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get next byte into alamask (alarm mask register) or contreg,temp notor: cpi temp,$05;Test for "And next byte with contreg". brne notand inc ZL ;Enter with ZL pointing to instruction, extits with ZL poiting to value out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get next byte into alamask (alarm mask register) and contreg,temp notand: cpi temp,$0C breq Setalarm cpi temp,$0D brne not0D inc regA rjmp executioncomplete not0D: cpi temp,$FF;if its $FF, then its the end of the string of commands breq eepromstop rjmp continueinterpretation;Jump to another part of memory for more commands (branch limitation) continueinterpretationreturn: ;IF NOOP or unrecognized command, falls through to here. DO NOT MOVE executioncomplete: ;routines return here -rcall would use stack space inc ZL rjmp continueeprom eepromstop: rjmp main resetclock: ;Set clock to Y:M:D:H:M:S = 0:0:0:0:0:0 mov ZH,contreg;save contreg in ZH ori contreg,$02;disable clock updates to user resigers clr usecond clr uminute ; repalce "ori contreg,$02 with eauted value **** clr uhour clr uday clr umonth clr uyear ori contreg,writelcockorflag;request clock be written with user register values waitforclockwriting: sbrc contreg,writeclock; rjmp waitforclockwriting mov contreg,ZH ;restore contreg from ZH rjmp executioncomplete Setalarm: ;Set alarm to [next 6 bytes of EEPROM] ;format: [instruction code] [Y] [M] [D] [H] [M] [S] ;enters with ZL pointing to the instruction ;exits with ZL pointing to last parameter which is [S] ldi bitcount,11;bitcount indexes the registers continueawrite: inc ZL out eear,ZL ;move to EEPROM address register sbi eecr,eere;Trigger the read in temp,eedr;Get the data into temp mov delayc,ZL mov ZL,bitcount st Z,temp mov ZL,delayc inc bitcount cpi bitcount,17 brne continueawrite rjmp executioncomplete ;//////////SEND A BYTE ; Send carry bit as first bit, then send rxtxbyte bit-by-bit. rxtxbyte destroyed. SendByte: ldi bitcount,$09 ldi temp,DStimeout mov rectimer,temp andi intflags,rbtandmask S1: sbrc intflags,rbt rjmp cleanandgo sbis PINB,attline;Wait for Attention line to go high =--SEND A BIT rjmp S1 ;Put data on data line cbi DDRB,dataline brcs R1 cbi PORTB,dataline sbi DDRB,dataline R1: sbrc intflags,rbt rjmp cleanandgo cbi PORTB,attline;Set Attention line low sbi DDRB, attline rcall shortdelay ;Wait a short time so other chip can see Attnetion line is low cbi DDRB,attline;Release Attention line for a peak rcall shortdelay;Short delay to allow settling of lines sbic PINB,attline ;If Attention line isn't low, go back and put it low again, else continue rjmp R1 brcs szero ;Invert data line cbi DDRB,dataline rjmp R3 szero: cbi PORTB,dataline sbi DDRB,dataline R3: sbrc intflags,rbt rjmp cleanandgo sbis PINB,attline;Wait for Attention line to go high rjmp R3 cbi DDRB,dataline;Let data line float ;-finished sending a bit rol rxtxbyte;Shift rxtxbyte through carry dec bitcount brne S1 ;Continue until all bits sent ret cleanandgo: rjmp postreset;Reset a lot of things if send byte fails. ReceiveByte: ldi bitcount,$09 ldi temp,DStimeout mov rectimer,temp andi intflags,rbtandmask W3A:; ;Get a bit from the input into the carry W3: sbrc intflags,rbt rjmp bail ; rcall testtimeout sbic PINB,attline;Wait for Attention line to go low rjmp w3 cbi PORTB,attline;ACK by pulling attention line low sbi DDRB, attline ; ldi temp,$02 ; mov asecond,temp ; andi intflags,$F7 clc ;Latch dataline into carry bit sbis PINB,dataline rjmp NotaOne sec W1: sbrc intflags,rbt;Wait for data line to go low rjmp bail sbic PINB,dataline rjmp W1 rjmp RelesaseAttLineAndGo NotaOne: W2: sbrc intflags,rbt;Wait for data line to go high rjmp bail sbis PINB,dataline rjmp W2 RelesaseAttLineAndGo: ;Release attention line cbi DDRB, attline ;DONE RECEIVING BIT rol rxtxbyte;Shift rxtxbyte through carry dec bitcount brne W3A ;Continue until all bits received rjmp recrtn ;The reason this is looks like a subroutine is to make the ;code a little more readable. shortdelay: ldi delayc,setltime D1: dec delayc brne D1 ret bail: cbi DDRB, attline andi intflags,$7F rjmp main ;///////////////TIMER OVERFLOW SERVICE////////////////// tovflo: ;twice per second timer interrupt (assumes 32678 hz crystal) in sregtemp,SREG;save the status register contents tst tempi ;Since the interrupt is twice a second, tempi will be used brne even500ms;to divide by two ldi tempi,1 rjmp lateExit even500ms: tst rectimer breq notimeout dec rectimer brne notimeout ori intflags,rbtorflag andi intflags,$7F;**** possible savings of one word - is this redundant with flag clear in bail? notimeout: ;//////write to clock////// sbrs contreg,writeclock;write user time registers to clock rjmp nowrite mov second,usecond mov minute,uminute mov hour,uhour mov day,uday mov month,umonth mov year,uyear andi contreg,writeclockmask;clear write flag nowrite: ;/////begin clock/calendar maintenance///// ;Year counter runs to 255 years. Leap test year assumes ;that the year is a leap year if bits 0 and 1 are low. sbrc contreg,disableclock;Skip clock/alarm maintenance if flag is set rjmp skipclocktohere inc second cpi second,60 breq dominute rjmp doneclock dominute: clr second inc minute cpi minute,60 breq dohour rjmp doneclock dohour: clr minute inc hour cpi hour,24 breq doday rjmp doneclock doday: clr hour inc day cpi day,32 breq domonth cpi day,31 brne check30 cpi month,4 breq domonth cpi month,6 breq domonth cpi month,9 breq domonth cpi month,11 breq domonth check30: cpi month,2 brne doneclock cpi day,30 breq domonth cpi day,29 brne doneclock mov tempi,year andi tempi,$03 breq doneclock domonth: ldi day,1 inc month cpi month,13 brne doneclock ldi month,1 inc year doneclock: ;/////end clock/calendar maintenance///// ;//////read from clock////// sbrc contreg,readclockinh;read from clock to user time registers rjmp noread mov usecond,second mov uminute,minute mov uhour,hour mov uday,day mov umonth,month mov uyear,year noread: ;//////Test for alarm condition////// sbrs contreg,enablearlarm;If the alarm enable flag isnt' set, skip alarm maintenance rjmp noalarm mov tempi,alamask ror tempi brcc nosecond cp second,asecond;compare hours,minutes, seconds brne noalarm nosecond: ror tempi brcc nominute cp minute,aminute brne noalarm nominute: ror tempi brcc nohour cp hour,ahour brne noalarm nohour: ror tempi brcc noday cp day,aday brne noalarm noday: ror tempi brcc nomonth cp month,amonth brne noalarm nomonth: ror tempi brcc noyear cp year,ayear brne noalarm noyear: ; mov tempi,intflags;Execute alarm program from EEPROM if present and checksum ok ; andi tempi,$21 ; cpi tempi,$01 ; brne noalarmcode;set the flag requesting execution sbrs contreg,eepromok rjmp noalarmcode sbrc intflags,alrmineeprom rjmp noalarmcode ori intflags,execeealrmorflag rjmp noalarm ;skip ahead and don't set output pin high noalarmcode: sbi DDRB,dout;Set that output pin low noalarm: skipclocktohere: ;Just skipped the clock and alarm donecontrol: doneint: clr tempi lateExit: andi intflags,extintmask ; clr t0intcount;clear ext interrupt counter **** should move to before lateExit out SREG,sregtemp;restore the status register contents reti ;//////External interrupt handler int0handler: ;arrived here because attention line was pulled low ori intflags,extintorflag ; ldi temp,$00;disable external interrupt 0 ; out GIMSK,temp;* ori intflags,$80 reti continueinterpretation: cpi temp,$0E;Test for "Get next EEPROM byte into alarm mask register". brne noalarmaks inc ZL ;Enter with ZL pointing to instruction, extits with ZL poiting to value out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in alamask,eedr;Get next byte into alamask (alarm mask register) noalarmaks: cpi temp,$0F;Test for "Get next EEPROM byte into rega". brne nosetrega inc ZL ;Enter with ZL pointing to instruction, extits with ZL poiting to value out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in rega,eedr;Get next byte into alamask (alarm mask register) nosetrega: cpi temp,$10 brne dontdecrement dec rega dontdecrement: ;Conditional jumps within EEPROM space. If conditional jump condition ;is met the jump address is picked up from the byte following the ;instruction. The jump address is an absolute address, valid range is ;0..3F but there are not checks here, so illeagal values will warp around. ;Handle conditional jumps. sbrs temp,7 ;If bit 7 is set, its a conditionial jump rjmp nocjumps inc ZL ;Fetch jump address. Enter with ZL pointing to instruction. out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in rxtxbyte,eedr;Get jump address into rxtxbyte sbrs temp,6 ;If bit 6 is set, a constant is used in the instruction rjmp noconstant;If a constant is used, it is the third byte of the instructio inc ZL ;Fetch constant. Enter with ZL pointing to instruction. out eear,ZL ;Move pointer to EEPROM address register sbi eecr,eere;Trigger the read in bitcount,eedr;bitcount now contains the constant. noconstant: ;At this point, jump address is in rxtxbyte and constant is in bitcount cpi temp,$C0 brne notC0 ; $C0 If rega equals constant,jump cp rega,bitcount breq dothecjump notC0: cpi temp,$C1; $C1. If rega is not equal to the contstant (bitcount) jump brne notC1 cp rega,bitcount brne dothecjump notC1: cpi temp,$80; $80. Jump unconditionally brne not80 rjmp dothecjump not80: cpi temp,$81; $81. Jumps if rega equals datareg brne not81 cp rega,datareg breq dothecjump not81: cpi temp,$82; $82. Jumps if rega does not equal datareg brne not82 cp rega,datareg brne dothecjump not82: cpi temp,$83; $83. Jumps ext input is high brne not83 sbic PINB,extinput brpl dothecjump not83: cpi temp,$84; $84. Jumps ext input is low brne not84 sbis PINB,extinput brpl dothecjump not84: nocjumps: ;Skipped to here beacuse these aren't jump instructions rjmp continueinterpretationreturn dothecjump: ;rxtxbyte contains jump address mov ZL,rxtxbyte;Jump rjmp continueeprom ;end of assembly souce listing |