; Author:       Hans Summers G0UPL
; Update:       11-Oct-07
; Function:     Wind speed measurement
;
;                        .-------10k--------.
;      X = 5.0688 MHz    :                  :
;                        :   .----..----.   :
;                        `--1|RST :: V+ |20-+--+-< 3.3V reg
;                           2|RXD    PB7|19   10n
;      TXD <----------------3|TXD       |18   ///
;        .------------------4|          |17
;        +---X---+----------5|          |16           G0UPL
;       22p     22p      .--6|INT0      |15
;       ///     ///      :  7|          |14
;                        :  8|          |13
;      | o---------------'  9|       PB0|12-----1k0------.
;      | o-------+---------10|GND       |11            a :
;      Reed      :           `----------'               LED
;      Relay     :         Atmel ATtiny2313            k :
;                +---------------------------------------'
;               ///
;
      .include "tn2313def.inc"          ; Define chip particulars

        .def    wreg    = r16           ; General use working register
        .def    sensor  = r17           ; Holds state of the sensor
        .def    counter = r18
                                        ; zh/zl holds the wind speed count
        .cseg

        .org    $0000                   ; start of Code Segment

        rjmp    reset                   ; $0000 Reset
        reti                            ; $0001 External Interrupt0
        reti                            ; $0002 External Interrupt1
        reti                            ; $0003 Timer1 Capture
        rjmp    tc1                     ; $0004 Timerl CompareA
        reti                            ; $0005 Timer1 Overflow
        reti                            ; $0006 Timer0 Overflow
        reti                            ; $0007 USART0 RX Complete
        reti                            ; $0008 USART0 UDR Empty
        reti                            ; $0009 USART0 TX Complete
        reti                            ; $000A Analog Comparator
        reti                            ; $000B Pin Change Interrupt
        reti                            ; $000C Timerl Compare B
        rjmp    tc0                     ; $000D Timer0 Compare A
        reti                            ; $000E Timer0 Compare B
        reti                            ; $000F USI Start
        reti                            ; $0010 USI Overflow
        reti                            ; $0011 EEPROM Ready
        reti                            ; $0012 Watchdog Overflow


        .equ ASCII_DP = 46              ; Some required ASCII codes
        .equ ASCII_0  = 48
        .equ ASCII_9  = 57
        .equ ASCII_CR = 13
        .equ ASCII_LF = 10

reset:
        ldi    wreg, RAMEND
        out    SPL, wreg                ; Init Stack Pointer

        ldi    wreg, 0b00100000         ; enabled IDLE mode for sleep
        out    MCUCR, wreg

        ldi     wreg, 0                 ; 9600 bd for 5.0688 MHz Xtal
        out     UBRRH, wreg
        ldi     wreg, 32
        out     UBRRL, wreg

        ldi     wreg, 0b00001000        ; enable USART transmitter
        out     UCSRB, wreg

        ldi     wreg, 0b00000110;       ; Set frame format: 8N1
        out     UCSRC, wreg

        ldi     wreg, 0                 ; define port D as input
        out     DDRD, wreg

        ldi     wreg, 1                 ; define port B bit 0 as output
        out     DDRB, wreg

        ldi     wreg, 0b00000100        ; define pin PD2 as pulled high
        out     PORTD, wreg

        ldi     wreg, 20                ; Set top count of Timer0 CTC.
        out     OCR0A, wreg             ; Causes VR to poll the
                                        ; wind sensor at 3.96kHz

        ldi     wreg, 0b00000010        ; Set timer0 in CTC mode
        out     TCCR0A, wreg
        ldi     wreg, 0b00000011        ; start Timer0 with sys clock / 64
        out     TCCR0B, wreg

        ldi     wreg, 77                ; put 19800 in OCR1A
        out     OCR1AH, wreg            ; Output compare reg timer1, A
        ldi     wreg, 88                ; this causes the timer OC1RA int
        out     OCR1AL, wreg            ; to occur at 4 second intervals

        ldi     wreg, 0b01100101        ; enable interrupt
        out     TIMSK, wreg             ; when OC1RA is reached

        ldi     wreg, 0b00001101        ; Set CTC amd clock Timer1
        out     TCCR1B, wreg            ; with system clock / 1024

        ldi     counter, 0              ; reset interval counter at zero

        ldi     zl, 0                   ; reset wind counter at zero
        ldi     zh, 0

        SEI                             ; enable interrupts

;-----------------------------------------------------------------------------

;       IDLE WAITING STATE - All Interrupt Handles Return to here.

done:
        sleep                           ; go to sleep
        rjmp done

;-----------------------------------------------------------------------------

;       Handle TIMER0 interrupt from Wind Sensor Relay

tc0:
        ldi     wreg, 0                 ; get PORTD pin 2 (windsensor input)
        sbic    PIND, 2

        ldi     wreg, 1
        cp      sensor, wreg            ; compare with existing stored value.
        breq    tc0_r                   ; do nothing if they're the same

        mov     sensor, wreg            ; if different, set them the same
        cpi     sensor, 1
        brne    tc0_r                   ; and if it's zero, return

        adiw    zh:zl,1                 ; Otherwise (0 -> 1 transistion
        out     PORTB, zl               ; incrment wind counter!
tc0_r:
        reti

;-----------------------------------------------------------------------------

;       Handle TIMER1 interrupt for Operation Cycle Timing

tc1:
        inc     counter
        cpi     counter, 100            ; 100 x 4 sec intervals is 400 S
        brne    tc1_r
        ldi     counter, 0
                                        ; convert and send 10000's digit
        ldi     wreg, (ASCII_0 - 1)
tc1_4:  inc     wreg
        subi    zl,low(10000)
        sbci    zh,high(10000)
        brcc    tc1_4
        rcall   sendChar
                                        ; convert and send 1000's digit
        ldi     wreg, (ASCII_9 + 1)
tc1_3:  dec     wreg
        subi    zl,low(-1000)
        sbci    zh,high(-1000)
        brcs    tc1_3
        rcall   sendChar
                                        ; send decimal point
        ldi     wreg, ASCII_DP
        rcall   sendChar
                                        ; convert and send 100's digit
        ldi     wreg, (ASCII_0 - 1)
tc1_2:  inc     wreg
        subi    zl,low(100)
        sbci    zh,high(100)
        brcc    tc1_2
        rcall   sendChar
                                        ; convert and send 10's digit
        ldi     wreg, (ASCII_9 + 1)
tc1_1:  dec     wreg
        subi    zl,-10
        brcs    tc1_1
        rcall   sendChar

        ldi     wreg, ASCII_0           ; calculate 1's digit and send it
        add     wreg, zl
        rcall   sendChar
                                        ; send carriage return
        ldi     wreg, ASCII_CR
        rcall   sendChar
                                        ; send line feed
        ldi     wreg, ASCII_LF
        rcall   sendChar

        ldi     zl, 0                   ; reset wind counter at zero again
        ldi     zh, 0
tc1_r:
        reti

;-----------------------------------------------------------------------------

;       Send one ASCII character from UART to Data Logger -- SubRoutine

sendChar:
        out     UDR, wreg               ; send the character
sendChar0:
        SBIS    UCSRA, UDRE             ; wait for the send to complete
        rjmp    sendChar0
        ret

;-----------------------------------------------------------------------------