.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
	
	
	
	
	
	
	
	
	
