; IR trigger for Olympus camera
; Copyright (C) 2013 Stefan Schuermans <stefan@blinkenarea.org>
; Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
; a BlinkenArea project - http://www.blinkenarea.org/

; code for 8 MHz crystal osciallator

.INCLUDE        "tn2313def.inc"


.def    TMP                     =       r16
.def    CNT                     =       r17
.def    CNT2                    =       r18
.def    DATA                    =       r19


.equ    IR_PORT                 =       PORTB
.equ    IR_BIT                  =       0



.DSEG
.ORG    0x060



.CSEG
.ORG    0x000
        rjmp    ENTRY                   ; RESET
        reti                            ; INT0
        reti                            ; INT1
        reti                            ; TIMER1_CAPT
        reti                            ; TIMER1_COMPA
        reti                            ; TIMER1_OVF
        reti                            ; TIMER0_OVF
        reti                            ; USART0_RX
        reti                            ; USART0_UDRE
        reti                            ; USART0_TX
        reti                            ; ANALOG_COMP
        reti                            ; PC_INT0
        reti                            ; TIMER1_COMPB
        reti                            ; TIMER0_COMPA
        reti                            ; TIMER0_COMPB
        reti                            ; USI_START
        reti                            ; USI_OVERFLOW
        reti                            ; EE_READY
        reti                            ; WDT
        reti                            ; PC_INT1
        reti                            ; PC_INT2



; code entry point
ENTRY:
; set system clock prescaler to 1:1, i.e. run at 8 MHz
        ldi     TMP,1<<CLKPCE
        out     CLKPR,TMP
        ldi     TMP,0
        out     CLKPR,TMP
; initialize output ports
        ldi     TMP,0x00                ; PA[01] to output, low
        out     PORTA,TMP
        ldi     TMP,0x03
        out     DDRA,TMP
        ldi     TMP,0xA0                ; PB[0-46] to output, low - PB[57] to input, pull-up enabled
        out     PORTB,TMP
        ldi     TMP,0x5F
        out     DDRB,TMP
        ldi     TMP,0x00                ; PD[0-6] to output, low
        out     PORTD,TMP
        ldi     TMP,0x7F
        out     DDRD,TMP
; initialize stack pointer
        ldi     TMP,RAMEND
        out     SPL,TMP
; enable watchdog (64ms)
        wdr
        ldi     TMP,1<<WDCE|1<<WDE
        out     WDTCR,TMP
        ldi     TMP,1<<WDE|1<<WDP1
        out     WDTCR,TMP
        wdr
; disable analog comparator
        ldi     TMP,1<<ACD
        out     ACSR,TMP
; jump to main program
        rjmp    MAIN



; output CNT pulses with 38kHz, 1/4 duty-cycle
IR_PULSE:
        sbi     IR_PORT,IR_BIT          ; IR = 1, 2 cyc
        ldi     TMP,13                  ; 51 cyc
IR_PULSE_WAIT_1:
        wdr
        dec     TMP
        brne    IR_PULSE_WAIT_1
        cbi     IR_PORT,IR_BIT          ; IR = 0, 2 cyc
        ldi     TMP,38                  ; 155 cyc
IR_PULSE_WAIT_0:
        wdr
        dec     TMP
        brne    IR_PULSE_WAIT_0
        dec     CNT                     ; next pulse
        brne    IR_PULSE
        ret                             ; done



; wait 10us
WAIT_10US:
        ldi     TMP,18
WAIT_10US_LOOP:
        wdr
        dec     TMP
        brne    WAIT_10US_LOOP
        nop
        ret



; output a bit (DATA,0) over IR
IR_OUT_BIT:
        ldi     CNT,21                  ; ouput 560us pulses
        rcall   IR_PULSE
        ldi     CNT,56                  ; bit 0 -> wait 560us
        sbrc    DATA,0
        ldi     CNT,169                 ; bit 1 -> wait 1690us
IR_OUT_BIT_WAIT:
        rcall   WAIT_10US
        dec     CNT
        brne    IR_OUT_BIT_WAIT
        ret                             ; done



; output a byte (DATA)
IR_BYTE:
        push    DATA                    ; save data
        ldi     CNT2,8                  ; iterate 8 bit
IR_BYTE_LOOP:
        rcall   IR_OUT_BIT              ; output bit
        lsr     DATA                    ; next bit
        dec     CNT2
        brne    IR_BYTE_LOOP
        pop     DATA                    ; restore data
        ret                             ; done



; output IR start burst
IR_START:
        ldi     CNT,171                 ; ouput 9ms pulses
        rcall   IR_PULSE
        ldi     CNT,171
        rcall   IR_PULSE
        ldi     CNT,225                 ; wait 4.5ms
IR_START_LOOP:
        rcall   WAIT_10US
        rcall   WAIT_10US
        dec     CNT
        brne    IR_START_LOOP
        ret                             ; done



; output IR key hold burst
IR_HOLD:
        ldi     CNT,171                 ; ouput 9ms pulses
        rcall   IR_PULSE
        ldi     CNT,171
        rcall   IR_PULSE
        ldi     CNT,225                 ; wait 2.25ms
IR_HOLD_LOOP:
        rcall   WAIT_10US
        dec     CNT
        brne    IR_HOLD_LOOP
        ldi     CNT,1                   ; ouput 1 pulse
        rcall   IR_PULSE
        ret                             ; done



; main program
MAIN:
        wdr

; main loop
MAIN_LOOP:
        wdr

; shutter E-330 and E-620 reverse engineered
        rcall   IR_START
        ldi     DATA,0x86
        rcall   IR_BYTE
        ldi     DATA,0x3B
        rcall   IR_BYTE
        ldi     DATA,0x01
        rcall   IR_BYTE
        ldi     DATA,0xFE
        rcall   IR_BYTE
        clr     DATA
        rcall   IR_OUT_BIT

; key hold impulse
;        rcall   IR_START
;        clr     DATA
;        rcall   IR_OUT_BIT

; wait 1s
        clr     CNT2
        clr     CNT
MAIN_WAIT:
        rcall   WAIT_10US
        rcall   WAIT_10US
        dec     CNT
        brne    MAIN_WAIT
        dec     CNT2
        brne    MAIN_WAIT

; bottom of main loop
        rjmp     MAIN_LOOP

