#include "tn13def.inc"
.device ATtiny13


.def		tbcd0	=r8
.def		tbcd1	=r9
.def		sdword	=r16
.def		sdword1	=r17
.def		mtime	=r18
.def		mrenc	=r19
.def		dlycnt0	=r20
.def		dotcnt	=r21
.def		temp	=r22
.def		dlycnt1	=r23
.def		count	=r24
.def		wutimer	=r25

.equ		atbcd0	=8
.equ		atbcd1	=9

.cseg
.org          	0x0000
              	rjmp 	reset           ; reset
              	reti 	;ext_int0       ; IRQ0
              	reti 	;pc_int0        ; PCINT0
              	reti 	;tim0_ovf       ; Timer0 overflow
              	reti 	;ee_rdy         ; EEPROM ready
              	reti 	;ana_comp       ; Analog Comp
              	rjmp 	tim0_compA      ; Timer0 Comp A
              	reti 	;tim0_compB     ; Timer0 Comp B
              	rjmp 	watchdog        ; Watchdog INT
              	reti 	;ad_conv        ; ADC conv

watchdog:		inc		wutimer			;advance wake up timer
				reti

tim0_compA: 	brtc	nost			;test for side tone on
				sbi		pinb,2			;toggle port if side tone on
nost:			dec		mtime			;decerment 1/3d dot time counter
				brne	text			;branch if not zero
				inc		dotcnt			;incerment dot counter
				ldi		mtime,40		;reload dot time counter
text:			reti					;return from interupt


reset:     	ldi 	r16,low(RAMEND)		;load ram end for stack pointer
           	out 	SPL,r16   
			ldi		temp,62				;set up timer 0 compare register
			out		ocr0a,temp
			ldi		temp,$02
			out		tccr0a,temp			;set for compare interupt
			ldi		temp,$03
			out		tccr0b,temp			;set prescaller value
			ldi		temp,$0e
			out		ddrb,temp			;setup port directions
			ldi		temp,$10
			out		portb,temp			;output initial port states
			ldi		temp,$04
			out		timsk0,temp			
			sbi		acsr,acd			;turn off analog comparator 
			ldi		temp,$18
			out		wdtcr,temp			
			ldi		temp,$61			;set up watch dog timer for 8 sec interupt
			out		wdtcr,temp
			clr		wutimer
			ldi		temp,$30			;set up power down mode to shut down
			out		mcucr,temp
			rjmp	gettemp				;get first conversion	
									;enable interupts
back2sleep:	sleep						;go to sleep
			cpi		wutimer,8			;check wake up timer value
			breq	gettemp				;do temp reading if 1 minute is up
			rjmp	back2sleep			;go back to sleep if not time yet


gettemp:	cli							;clear interupt enable
			sbi		portb,1				;turn power to sensor on
			rcall	sensint  			;reset sensor
			ldi		sdword,$cc			;issue skip ROM command
			rcall	SDout				;output word to sensor

			ldi		sdword,$44			;issue do conversion command
			rcall	SDout

cwt:		ldi		dlycnt0,100			;delay for a while
cwj1:		dec		dlycnt0
			brne	cwj1
			sbi		ddrb,0				;set port direction to output
			cbi		portb,0				;pluse port low
			nop							;nop delay for proper pluse width
			nop
			nop
			nop
			nop
			sbi		portb,0				;set port back high
			cbi		ddrb,0				;change port back to input
			ldi		dlycnt0,14			;delay for sensor responce
cwj5:		dec		dlycnt0
			brne	cwj5			
			sbis	pinb,0				;check for end of conversion, high
			rjmp	cwt					;check again if port was low

			rcall	delay500			;delay for 500 us before reading


rtest:		rcall	sensint				;reset sensor

			ldi		sdword,$cc			;issue skip ROM command
			rcall	SDout

			ldi		sdword,$be			;issue read scratch pad command
			rcall	SDout
		
			rcall	SDin				;read 1st byte of scratch pad
			mov		sdword1,sdword		;store temp low byte
			
			rcall	SDin				;read 2nd byte of scracth pad, temp high bype

			rcall	sensint				;reset sensor again to terminate scrach pad read


			sbrs	sdword,7			;check for negative number
			rjmp	positive			;jump if postive number

			com		sdword1				;1's complent if negative
			com		sdword
			set							;set t flag if negative

positive:	lsr		sdword				;rotate 4 bits of high word into low word
			ror		sdword1

			lsr		sdword
			ror		sdword1

			lsr		sdword
			ror		sdword1

			lsr		sdword
			ror		sdword1
			sbic	pinb,4				;check for C or F output
			rcall	c2f					;convert to F is F is selected

			rcall	bin2bcd16			;do binary to BCD conversion
		
			brtc	tempout				;branch if positive temp
			ldi		mrenc,$31			;send Morse '-' if negative temp
			clt							;clear t flag, as it is used in Morse output
			rcall	mrsout				;send Morse character
			rjmp	skip1				;skip 100's if neg, can't get that cold!

tempout:	mov		temp,tbcd1			;get 100's digit (F only)	
			swap	temp
			cbr		temp,$f0
			tst		temp				;test for 0
			breq	skip1				;branch if 0, no need to send
			rcall	gmk

skip1:		mov		temp,tbcd1			;10's F
			cbr		temp,$f0
			tst		temp				 
			breq	skip2				;branch if 0, no need to send
			rcall	gmk					;convert to Morse word and send if not 0
skip2:		mov		temp,tbcd0			;get 1's F 10's C
			swap	temp
			cbr		temp,$f0
			tst		temp				;branch if 0, no need to send
			breq	skip3
			rcall	gmk
			sbic	pinb,4				;test for F or C
			rjmp	Fdeg				;branch if F

skip3:		mov		temp,tbcd0			;1's digit for C
			cbr		temp,$f0
			rcall	gmk

			ldi		mrenc,$1a			;send 'C'
			rcall	mrsout
			rjmp	done


Fdeg: 		ldi		mrenc,$12			;send 'F'
			rcall	mrsout

done:		cbi		ddrb,0
			cbi		portb,1				;turn sensor off			
			clr		wutimer				;clr the wake up timer
			sei							;enable the interupts
			rjmp	back2sleep			;go back to sleep

;initialize sensor, rest
;set port low for 500 us and wait for presense responce from sensor

sensint:    sbi		ddrb,0				;set port to output
			cbi		portb,0				;pull pin low
			rcall	delay500			;call delay
			sbi		portb,0				;set port back high
			cbi		ddrb,0				;change port from output to input
			nop							;little delay
			nop
			nop
			nop
intwait1:	sbic	pinb,0				;wait for responce, sensor pull port low
			rjmp	intwait1
intwait2:   sbis	pinb,0				;wait for port to go back high
			rjmp	intwait2
			rcall	delay500			;call delay, let sensor initialize
			ret			 

;500 us delay timer

delay500:	ldi		dlycnt1,5	
dlyprg:		clr		dlycnt0
			
delay1:		dec		dlycnt0
			brne	delay1
			dec		dlycnt1
			brne	delay1
			ret

;serial data out to sensor
			  			  
SDout:		sbi		ddrb,0				;set port direction output
			ldi		temp,8				;load number of bits to send
sdj1:       ror		sdword				;rotate word to put bit in carry
			brcc	zero				;check for 0 or 1	
			cbi		portb,0				;gernerate write window
			nop
			nop
			nop
			nop
			nop
			nop
			sbi		portb,0				;set port 
			ldi		dlycnt0,100			;delay to allow sensor to read port
sdj3:		dec		dlycnt0		
			brne	sdj3			

sdj2:		nop							;inter bit write recovery time delay
			nop
			nop
			nop
			nop
			nop
			dec		temp				;decerment bit counter
			brne	sdj1				;not done? get next bit
			cbi		ddrb,0				;set port back to input
			ret
			
zero:		cbi		portb,0				;hold port low for write time
			ldi		dlycnt0,100
sdj4:		dec		dlycnt0
			brne	sdj4			
			sbi		portb,0				;set port high
			rjmp	sdj2				;go to inter bit recovery time delay
			
			
;read serial data from sensor

SDin:		clr		sdword				;clear the bit input register
			ldi		temp,8				;load bit counter
		

sdin1:		sbi		ddrb,0				;set port direction out
			cbi		portb,0				;generate read window
			nop	
			nop
			nop
			nop
			nop
			sbi		portb,0
			cbi		ddrb,0				;change port directio, input
			ldi		dlycnt0,14			;delay
sdj5:		dec		dlycnt0	
			brne	sdj5			
		
			sbis	pinb,0				;read port
			rjmp	inzero				;jump if zero
			sec							;set carry
			ror		sdword				;shift carry into bit data register
		
sdj7:		ldi		dlycnt0,100			;delay
sdj6:		dec		dlycnt0
			brne	sdj6						
			dec		temp				;decerment bit counter
			brne	sdin1				;get more bits if counter not zero
			ret
			

inzero:		clc		
			ror		sdword
			rjmp	sdj7
			

;convert bcd digit to Morse 

gmk:		ldi		zh,high(mrtbl*2) 	;load table location
			ldi		zl,low(mrtbl*2)
			add		zl,temp				;add offset for number
			clr		temp			
			adc		zh,temp				;adjust address if not even boundry
			lpm							;get morse character data
			mov		mrenc,r0			;move data to morse data register for output

;output Morse code
			
mrsout:		ldi		mtime,40 			;load code speed timer
			ldi		r28,$08	 			;load bit count
			sei							;enable interupts
mrs4:		rol		mrenc				;rotate Morse word to find start bit
			dec		r28					;decement bit count
			brcc	mrs4				;rotate until start bit is found

	
mrs2:		set							;enable sidetone output
			sbi		portb,3				;turn transmitter on
			clr		dotcnt				;clear the dot time counter
			rol		mrenc				;find next element to send
			brcs	mdsh				;branch if 1 to dah, fall through for 0, dit


mdot:		cpi		dotcnt,$03 			;time dit
			brne	mdot
			rjmp	mspace				;jump to space when dit is timed out

mdsh:		cpi		dotcnt,$09			;time dah
			brne	mdsh

mspace:		cbi		portb,3				;turn transmitter off
			clr		dotcnt				;clear dot counter 
			clt							;turn off side tone
msp1:		cpi		dotcnt,$03			;time intelement space, one dit time
			brne	msp1
mrs1:		dec		r28					;decerment bit counter
			brne	mrs2				;go get next element if not zero
			clr		dotcnt				;clear dot counter
mrs3:		cpi		dotcnt,12			;time for inter character space, 7 dot time
			brne	mrs3
			cli							;turn off interupts
			ret							;return

; degree C to F conversion
; F= C * 18 + 320
;divide result by 10 by discarding last digit after conversion to bcd

c2f:		ldi		temp,$12		;multiplier 18 (12h)
			clr		sdword			;clear result High byte
			ldi		count,8			;init loop counter
			lsr		sdword1			;rotate multiplier
	
m8u_1:		brcc	m8u_2			;carry set 
			add 	sdword,temp		;add multiplicand to result High byte
m8u_2:		ror		sdword			;rotate right result High byte
			ror		sdword1			;rotate right result L byte and multiplier
			dec		count			;decrement loop counter
			brne	m8u_1			;if not done, loop more
			ldi		temp,$40		;load 320 degree offset (32X10)
			ldi		count,$01
			brts	negtemp
			add		sdword1,temp	;add offset to result
			adc		sdword,count
			ret						;return

negtemp:   	sub		temp,sdword1	;subtract offset if neg
			sbc		count,sdword
			brmi	negF			;check for less than 0 
			mov		sdword1,temp	
			mov		sdword,count
		
			clt						;clear t flag for postive result
			ret

negF:       com		temp			;convert back to postive number
			com		count
			mov		sdword1,temp
			mov		sdword,count
			ret



;convert 16 bit binary word to 4 digits of packed BCD


bin2bcd16:
			ldi		count,16
			clr		tbcd1
			clr		tbcd0
	
bbcdx_1:	lsl		sdword1
			rol		sdword
			rol		tbcd0
			rol		tbcd1
			dec		count
			brne	bbcdx_2
			ret

bbcdx_2:	ldi		r30,atbcd1+1
			clr		zh
bbcdx_3:	ld		temp,-z
			subi	temp,-$03
			sbrc	temp,3
			st		z,temp
			ld		temp,z
			subi	temp,-$30
			sbrc	temp,7
			st		z,temp
			cpi		zl,atbcd0
			brne	bbcdx_3
			rjmp	bbcdx_1


;look up table to convert BCD number to Morse encoded word
	
mrtbl:	
			.db		$03,$2f
			.db		$27,$23		
			.db		$21,$20
			.db		$30,$38
			.db		$3c,$3e								    
