
; read PPM signal of a RC receiver
; on input capture the current value of the free running counter is put out to the serial port
; since the serial line is a bit too slow the output may miss some pulses
;
; Achim Walther, www.voidpointer.de, 31.12.2004

.include "m8def.inc"	;definitions for Mega8

.def save = R14
.def regs = R15
.def temp = R16
.def flag = R17
.def char0 = R18
.def charA = R19
.def curL = R20
.def curH = R21
.def lastL = R22
.def lastH = R23
.def diffL = R24
.def diffH = R25

.equ CLOCK = 8000000
.equ BAUD = 38400
.equ UBRRVAL = CLOCK/(BAUD*16)-1

intvect:
	rjmp init		; RESET	
	reti			; INT0
	reti			; INT1
	reti			; T2 Compare
	reti			; T2 Overflow
	rjmp inticp		; T1 Capture
	reti			; T1 Compare A
	reti			; T1 Compare B
	reti			; T1 Overflow
	reti			; T0 Overflow
	reti			; SPI Transfer complete
	reti			; UART RX Complete
	reti			; UDR Empty
	reti			; UART TX Complete
	reti			; ADC complete
	reti			; EEPROM Ready
	reti			; Analog Comparator
	reti			; TWM
	reti			; SPM_RDY

init:	
	; init stack pointer
	ldi temp, LOW(RAMEND)
	out SPL, temp
	ldi temp, HIGH(RAMEND)
	out SPH, temp

	ldi char0, '0'
	ldi charA, 'A'-10

	ldi flag, 0x00		; reset flag

	ldi lastL, 0
	ldi lastH, 0

	; configure Port C to ouput
	ldi temp, 0b00001111
	out DDRC, temp

	in temp, TIMSK
	ori temp, (1<<TICIE1)	; enable interrupt on ICP1
	out TIMSK, temp

	;;ldi temp, 0b01011001	; no Prescaler
	ldi temp, 0b01000010	; free running timer
	;;ldi temp, 0b01011010	; overflow on input capture
				; input capture on rising edge
				; Timer Prescaler 8

	out TCCR1B, temp

	; init UART
	ldi temp, LOW(UBRRVAL)		; set baud rate
	out UBRRL, temp
	ldi temp, HIGH(UBRRVAL)
	out UBRRH, temp

	ldi temp, (1<<URSEL)|(3<<UCSZ0)	; Frame-Format: 8 Bit
	out UCSRC, temp

	sbi UCSRB,TXEN		; activate TX

	sei

loop:	
	; main loop
	sbrs flag, 0		; check flag if a new message was received
	brne loop

	mov temp, diffH
	rcall serout

	mov temp, diffL
	rcall serout

	sbrs flag, 7		; check flag if a new cycle has begun --> newline
	rjmp l1
	rcall newline
	rjmp l2

l1:	rcall comma

l2:	ldi flag, 0x00		; reset flag
	rjmp loop		; endless loop

; Input Capture Interrupt Rountine
inticp:	
	in regs, SREG

	in curL, ICR1L		; load current timer value
	in curH, ICR1H
	movw diffL, curL	; copy into diff

	sub diffL, lastL	; substract the last timer value to get the difference
	sbc diffH, lastH

	movw lastL, curL	; set the last value to the current

	ldi flag, 0x01		; set flag for new value

	cpi diffH, 0x13		; check if the diff is > 0x1300 (4864 us)
	brlo endint

	ldi lastL, 0		; reset last value
	ldi lastH, 0
	out TCNT1H, lastL	; reset the timer
	out TCNT1L, lastL

	ldi flag, 0xFF		; set flag for new cycle

endint:	out SREG, regs
	reti


; convert the content of temp to a readable hex string and output to the serial port
serout:
	; serial output of the high nibble
	mov save, temp
	lsr temp
	lsr temp
	lsr temp
	lsr temp
	cpi temp, 10
	brge adda1

	add temp, char0		; add ASCII value of '0'
	rjmp adden1
adda1:	add temp, charA		; add ASCII value of 'A'

adden1:	sbis UCSRA,UDRE		; wait for UDR ready
	rjmp adden1
	out UDR,temp		; serial output

	; serial output of the low nibble
	mov temp, save
	andi temp, 0b00001111
	cpi temp, 10
	brge adda2
	add temp, char0		; add ASCII value of '0'
	rjmp adden2
adda2:	add temp, charA		; add ASCII value of 'A'

adden2:	sbis UCSRA,UDRE		; wait for UDR ready
	rjmp adden2
	out UDR,temp		; serial output
	ret

comma:
	ldi temp, ','
c1:	sbis UCSRA,UDRE		; wait for UDR ready
	rjmp c1
	out UDR,temp		; serial output
	ret


newline:
	ldi temp, 10
ser1:	sbis UCSRA,UDRE		; wait for UDR ready
	rjmp ser1
	out UDR,temp		; serial output

	ldi temp, 13
ser2:	sbis UCSRA,UDRE		; wait for UDR ready
	rjmp ser2
	out UDR,temp		; serial output

	ret