;Working on filein 'DC4CTRL.hex'

      list  p=pic12f629
      include "p12f629.inc"
      __idlocs 0x1020 ; Version 1.2

   __config  _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _BODEN_OFF & _MCLRE_OFF

; Timer 0 runs, but is not used.
; Watchdog Timer is not used.
; Indirect Data Memeory Addr. Ptr. is used only at POR.
; GP3 (RC signal) will wake up after sleep.
; weak pull-up does not show up in the simulator !!!
; If GIE is not set, wakeup from sleep is like 12F508
; Example is from www.rc-cam.com, Thomas Black
; 2007-02-26 Rudolf Reuter, www.rudisflugis.de, LOOP mode added
; 2007-04-18 V1.2, Loop time 4 s, Loop mode without jumper

VARBEG  equ    0x27       ; keep LOW digit addr
RF07    equ    0x27
RF08    equ    0x28
;RF29   equ    0x29
RF2A    equ    0x2A
;RF2B   equ    0x2B
RF2C    equ    0x2C
SigOld  equ    0x2D       ; time length of last signal
RF2E    equ    0x2E       ; copy of IO Status, not used
IOStat  equ    0x2F       ; IO bits of STATUS register
RF30    equ    0x30       ; LOW count of "no signal"
RF31    equ    0x31       ; HIGH count of "no signal"
RF32    equ    0x32
SigLen  equ    0x33       ; time length of signal
RF34    equ    0x34
RF35    equ    0x35
RF36    equ    0x36
RF37    equ    0x37
DlyTmp  equ    0x38
Cnt1ms  equ    0x39       ; counter for 1 ms delay
;0x1A   equ    0x3A
;0x1B   equ    0x3B
RF3C    equ    0x3C       ; copy of STATUS, nor used
;0x1D   equ    0x3D
;0x1E   equ    0x3E
CamStat equ    0x3F       ; Status bits for signal sequence

;main:    code   0x000     ; effective reset vector
         goto   PoRiniz
         nop
         nop
         nop
         nop              ; Interrupt vector

; subroutine 1ms delay multiplied by RF19
Dly1msT: movfw Cnt1ms     ; rf19 x 1 ms delay
         skpnz
         goto   DlyRet    ; nothing to do
Dly02:   movlw  0x01
         movwf  RF08      ; .1 in RF08
Dly04:   movlw  0xbf
         movwf  RF07      ; 191 in RF07
Dly06:   clrwdt           ; clear watchdog timer
         decfsz RF07,f    ; delay 4x191+1=765 us 
         goto   Dly06
         decfsz RF08,f    ; just skip (1>0)
         goto   Dly04
         movlw  0x48 
         movwf  RF07      ; .72 in rf07
Dly08:   decfsz RF07,f    ; delay 3x72+1=217 us
         goto   Dly08
         clrwdt
         decfsz Cnt1ms,f  ; decrement
         goto   Dly02     ; If not 0
DlyRet:  retlw  0x00      ; return sub

PoRiniz: bsf    STATUS, RP0 ;Bank 1
         call   3FFh      ;Get the cal value
         movwf  OSCCAL    ;Calibrate
         bsf    IOC, GP3  ; allow GP3 to interrupt
         bcf    OPTION_REG, NOT_GPPU ; enable pull-ups
; pull-up on GP2 will inhibit LOW signal & 100K pull down needed
         bcf    WPU, GP2  ; all IO weak pull-up, except GP2
         bcf    STATUS, RP0 ;Bank 0
         BSF    CMCON, CM0 ; no analog input!
         BSF    CMCON, CM1 ; no analog input!
         BSF    CMCON, CM2 ; no analog input!
         movlw  0x17      ; VAR count to clear
         movwf  RF07      ; .23
         movlw  VARBEG+1  ; RAM Addr. of variable begin
         movwf  FSR       ; Indirect Data Memeory Addr. Ptr.
         movlw  0x00
j01c:    movwf  INDF      ; Clear RAM
         incf   FSR,f     ; Indirect Data Memeory Addr. Ptr.
         decfsz RF07,f    ; up to 0x3F
         goto   j01c
         clrf   FSR       ; clear???
         clrf   RF2C      ; clear???
         clrf   SigOld    ; clear???
         clrf   RF30      ; clear???
         clrf   RF31      ; clear???
         bsf    INTCON, GPIE ; enable GP change wakeup
         movfw  STATUS    ; RF3C
         andlw  0x98      ; allow GPWUF, TO, PD
         movwf  IOStat    ; masked IO Status, 0x18
;         movlw  0xff
;         tris   GPIO      ; all bits Inputs
         movlw  0x03
         movwf  RF07      ; .3 in rf07
         btfss  RF07,3    ; Iniz Watchdog?
         goto   j032      ; No, Timer0
         movlw  0x07      ; .7 ???
         clrf   TMR0      ; clear
         movlw  0x0f      ; set PSA, PS2, PS1, PS0
         bsf    STATUS, RP0 ;Bank 1
         movwf  OPTION_REG ; Postscaler 1:128 to WDT ???
         bcf    STATUS, RP0 ;Bank 0
j032:    clrwdt           ; clear Watchdog Timer
         movfw  RF07      ; set PS1, PS0
; enable Weak pull-up and enable wake on change GP0, GP1, GP3
         bsf    STATUS, RP0 ;Bank 1
         movwf  OPTION_REG ; Prescaler 1:16 to Timer0, 16 us
         bcf    STATUS, RP0 ;Bank 0
         movfw  IOStat    ; masked Status to W
         movwf  RF07      ; copy to rs07
         movlw  0x90      ; .144
         subwf  RF07,w
         skpnz
         goto   j03c
         goto   j03f 
j03c:    clrf   RF31      ; clear
         clrf   RF30      ; clear
         goto   j043
j03f:    clrf   CamStat   ; clear
         clrf   RF31      ; clear
         clrf   RF30      ; clear
         goto   j043      ; fall into ???

; wakeup from RC signal edge (GP3) ???
j043:    clrwdt           ; clear Watchdog Timer
         clrf   SigLen    ; clear signal length
         clrf   RF36      ; clear
         clrf   RF37      ; clear
         bsf    CamStat,2 ; rf1F
         clrf   SigLen    ; clear signal length
         clrf   RF37      ; clear
         clrf   RF36      ; clear
; clear Interrupt condition
         movfw  GPIO
         bcf    INTCON, GPIF
; Output Test Signal for sleep check
         bcf    GPIO,1    ; ATV
         movlw  0xFD      ; Bit 1 Output = LOW
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0

; Look for incoming RS signal
; If no signal - Timeout at 3.1 ms
; 1,5 ms = 0x7C.124, 1,1 ms = 0x5A.90, 0.012 ms = 1
j04b:    movlw  0x07      ; .7
         subwf  RF37,w    ; RC ON time HIGH
         skpc
         goto   j057
         movlw  0x07      ; .7
         subwf  RF37,w    ; RC ON time HIGH
         skpz
         goto   j061
         movlw  0x9e      ; .158 = 1.93 ms
         subwf  RF36,w    ; RC ON time LOW
         skpnc
         goto   j061
j057:    nop
         nop
         btfss  GPIO,3    ; RC-SIGB
         goto   j05d      ; If RC signal LOW
         bcf    CamStat,2 ; Bit clear rf1F
         goto   j061
j05d:    incf   RF36,f    ; increment RC ON time LOW
         skpnz
         incf   RF37,f    ; increment RC ON time HIGH
         goto   j04b
j061:    btfsc  CamStat,2 ; rf1F
         goto   j071
         bsf    CamStat,2 ; Bit set rf1F
         clrf   SigLen    ; clear signal length
j065:    movlw  0xfa      ; .250 = 3.1 ms
         subwf  SigLen,w  ; signal length
         skpnc
         goto   j071      ; Timeout at 3.1 ms
         nop
         nop
         btfsc  GPIO,3    ; RC-SIGB
         goto   j06f      ; If RC signal HIGH
         bcf    CamStat,2 ; Bit clear RF1F
         goto   j071
j06f:    incf   SigLen,f  ; signal length
         goto   j065      ; Repeat Until RC-SIG is LOW

; RC signal pulse is received, now check
j071:   ; btfss  GPIO,1    ; ATV 
;         goto   j078      ; 100% are expected
         movlw  0x60      ; .96, 75% signal length are expected
         movwf  RF34      ; signal length Min. 1.17 ms
         movlw  0x73      ; .115
         movwf  RF35      ; signal length Max. 1.4 ms
         goto   j07c
j078:    movlw  0x66      ; .102, 100% signal length are expected
         movwf  RF34      ; signal length Min. 1.25 ms
         movlw  0x6e      ; .110
         movwf  RF35      ; signal length Max. 1.34 ms
j07c:    
; Test signal LENGTH
         movlw  0xff       ; ATV Bit high impedance TEST
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         movlw  0x42      ; .66 = 0.81 ms
         subwf  SigLen,w  ; signal length 
         skpc
         goto   j09f      ; If shorter as .66
         movlw  0xb9      ; .185
         subwf  SigLen,w  ; signal length
         skpnc
         goto   j09f      ; If longer as .185 = 2.26 ms
         bsf    CamStat,5 ; flag signal valid
;         btfsc  GPIO,0    ; REV - no longer used
         goto   j09f      ; If RC length is Normal
; reverse signal
         movlw  0x7d      ; .125 (center) 1.53 ms
         subwf  SigLen,w  ; signal length
         skpnc
         goto   j094
         movlw  0x7d      ; .125 (center) 1.53 ms
         movwf  RF07
         movfw  SigLen    ; signal length
         subwf  RF07,w
         movwf  RF07
         movlw  0x7d      ; .125 (center) 1.53 ms
         addwf  RF07,w
         movwf  SigLen    ; signal length
         goto   j09f
j094:    movlw  0x7e      ; .126 (center) 1.54 ms
         subwf  SigLen,w  ; signal length
         skpc
         goto   j09f
         movlw  0x7d      ; .125 (center) 1.53 ms
         subwf  SigLen,w  ; signal length
         movwf  RF08
         movlw  0x7d      ; .125 (center) 1.53 ms
         movwf  SigLen    ; signal length
         movfw  RF08
         subwf  SigLen,f  ; signal length
; signal is Normal (not reversed)
j09f:    movlw  0x42      ; .66 = 0.81 ms
         subwf  SigLen,w  ; signal length
         skpc             ; skip If longer as .66
         goto   j0ff      ; Signal too short
         movfw  RF34      ; signal length Min.
         subwf  SigLen,w  ; signal length
         skpnc            ; skip If shorter as 1.17 ms
         goto   SigPrc1   ; IF longer
; check if already armed
         btfss  CamStat,0 ; RF1F, skip if ARM_SHORT
         goto   j0ef      ; look for ARM_SHORT
         btfss  CamStat,1 ; RF1F, skip if ARM_LONG
         goto   j0ff      ; look for ARM_LONG
         goto   SigPrc4   ; ARM is OK

; long signal, test for LOOP mode, take picture IF:
; no timeout, ARM, 2 consecutive same signals
SigPrc1: btfss  GPIO,0    ; LOOP mode ?
         goto   j0ff      ; IF not proceed
         movlw  0xb9      ; .185
         subwf  SigLen,w  ; signal length
         skpnc            ; skip if no timeout
         goto   j0fb      ; If longer as .185 = 2.26 ms
; check if already armed
         btfss  CamStat,0 ; RF1F, skip if ARM_SHORT
         goto   j0ef
         btfss  CamStat,1 ; RF1F, skip if ARM_LONG
         goto   j0ff
; compare actual signal length with last signal length
; IF within bandwidth +/- 36 us THEN proceed, ELSE loop further
         movlw  0x03      ; .3 = 36 us
         subwf  SigOld,w  ; compare SMALLER
         subwf  SigLen,w  ; signal length
         skpnz            ; IF equal
         goto   j0ee
         skpc             ; skip if not smaller
         goto   j0ee
         movlw  0x03      ; .3 = 36 us
         addwf  SigOld,w  ; compare GREATER
         subwf  SigLen,w  ; signal length
         skpnc            ; skip if not greater
         goto   j0ee
; Delay 3 sec and actuate shutter in LOOP mode
; The camera does not go faster
         movlw  0x0C      ; .12 in rf18
         movwf  DlyTmp     
SigPrc2: movlw  0xfa
         movwf  Cnt1ms    ; .250 in rf19
         call   Dly1msT   ; delay 250 ms
         decfsz DlyTmp,f  ; delay x/4 sec
         goto   SigPrc2
         goto   Shutter

; compare actual signal length with last signal length
; IF within bandwidth +/- 36 us THEN proceed, ELSE loop further
SigPrc4: movlw  0x03      ; .3 = 36 us
         subwf  SigOld,w  ; compare SMALLER
         subwf  SigLen,w  ; signal length
         skpnz            ; IF equal
         goto   j0ee
         skpc             ; skip if not smaller
         goto   j0ee
         movlw  0x03      ; .3 = 36 us
         addwf  SigOld,w  ; compare GREATER
         subwf  SigLen,w  ; signal length
         skpnc            ; skip if not greater
         goto   j0ee
         btfsc  CamStat,4 ; RF1F, skip if camera READY
         goto   j0ee

; IF 2 consecutive short signals received - actuate Shutter
Shutter: btfsc  GPIO,2    ; AWAKE?
         goto   ShtTr6    ; If Yes, Shutter ON, wait 1 sec
; wake up camera, if asleep
         bcf    GPIO,5    ; WAKEUP
         movlw  0xdf      ; Bit 5 Output = LOW
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         movlw  0x64
         movwf  Cnt1ms    ; .100 in rf19
         call   Dly1msT   ; delay 100 ms
         clrf   RF32      ; clear rf12
; wait max. 2 sec for AWAKE
ShtTr0:  movlw  0x28      ; 40 x 50 ms = 2 sec
         subwf  RF32,w
         skpnc
         goto   ShtTr1
         movlw  0x32      ; .50
         movwf  Cnt1ms    ; .50 in rf19
         call   Dly1msT   ; delay 50 ms
         btfsc  GPIO,2    ; AWAKE?
         goto   ShtTr1    ; If Yes, trigger Shutter
         incf   RF32,f  
         goto   ShtTr0    ; No, wait longer
ShtTr1:  movlw  0xff      ; WAKEUP Bit high impedance
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         movlw  0x14      ; .20
         movwf  DlyTmp    ; .20 in rf18
ShtTr2:  movlw  0xfa
         movwf  Cnt1ms    ; .250 in rf19
         call   Dly1msT   ; delay 250 ms
         decfsz DlyTmp,f  ; delay 5 sec
         goto   ShtTr2
         bcf    GPIO,4    ; SHUTTER = ON
         movlw  0xef      ; Bit 4 Output
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         movlw  0x04      ; .4 in rf18
         movwf  DlyTmp     
ShtTr4:  movlw  0xfa
         movwf  Cnt1ms    ; .250 in rf19
         call   Dly1msT   ; delay 250 ms
         decfsz DlyTmp,f  ; delay 1 sec
         goto   ShtTr4
         goto   ShutEnd   ; 1 sec Shutter ON
ShtTr6:  bcf    GPIO,4    ; SHUTTER = ON
         movlw  0xef      ; Bit 4 Output
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         movlw  0x04
         movwf  DlyTmp    ; .4 in rf18
ShtTr8:  movlw  0xfa
         movwf  Cnt1ms    ; 250 in rf19
         call   Dly1msT   ; delay 250 ms
         decfsz DlyTmp,f  ; delay 1 sec
         goto   ShtTr8
ShutEnd: movlw  0xff      ; Shutter Bit high impedance
         bsf    STATUS, RP0 ;Bank 1
         movwf  TRISIO
         bcf    STATUS, RP0 ;Bank 0
         bsf    CamStat,4 ; picture taken
j0ee:    goto   j0fb

; compare actual signal length with last signal length
; IF within bandwidth +/- 36 us THEN proceed, ELSE loop further
; IF two consecutive signals are short, set ARM_SHORT
j0ef:    movlw  0x03       ; .3
         subwf  SigOld,w
         subwf  SigLen,w   ; signal length
         skpnz
         goto   j0fb
         skpc
         goto   j0fb
         movlw  0x03       ; .3
         addwf  SigOld,w
         subwf  SigLen,w   ; signal length
         skpc              ; skip if GREATER
         bsf    CamStat,0  ; set ARM_SHORT

j0fb:    clrf   RF2C       ; clear
         movfw  SigLen     ; signal length
         movwf  SigOld     ; copy to old
         goto   j11d

; check for signal length within valid range 1..2 ms
j0ff:    movlw  0x42       ; .66 = 0.81 ms
         subwf  SigLen,w   ; signal length
         skpc              ; If longer as 66
         goto   j11d
         movlw  0xb9       ; .185 = 2.26 ms
         subwf  SigLen,w   ; signal length
         skpnc             ; If shorter as 185
         goto   j11d       ; If longer as 185
         movfw  SigLen     ; signal length
         subwf  RF35,w     ; signal length max.
         skpnc
         goto   j11a

; compare actual signal length with last signal length
; IF within bandwidth +/- 36 us THEN proceed, ELSE loop further
; IF two consecutive signals are long, set ARM_LONG
         movlw  0x03       ; .3
         subwf  SigOld,w
         subwf  SigLen,w   ; signal length
         skpnz
         goto   j11a
         skpc
         goto   j11a
         movlw  0x03       ; .3
         addwf  SigOld,w
         subwf  SigLen,w   ; signal length
         skpnc             ; skip if not greater
         goto   j11a

         btfsc  CamStat,0  ; If no ARM_SHORT yet
         bsf    CamStat,1  ; set ARM_LONG
         bcf    CamStat,4  ; READY for picture taking

j11a:    clrf   RF2C       ; clear
         movfw  SigLen     ; signal length
         movwf  SigOld
j11d:    movfw  SigLen     ; signal length
         movwf  RF08
         btfss  CamStat,5  ; valid signal length?
         goto   j124       ; If yes
         clrf   RF31       ; Reset signal lost counter
         clrf   RF30       ; clear
         bcf    CamStat,5
j124:    movfw  RF31       ; cycle = 0x76DC = .30428 us
         movwf  RF2A
         movfw  RF30
         incf   RF30,f     ; inc. LOW, signal lost
         skpnz             ; RF10+RF11, 0xBFF = .3071
         incf   RF31,f     ; inc. HIGH, signal lost
         movwf  RF32       ; copy LOW count, no signal
         movfw  RF2A
         movwf  SigLen     ; signal length
         movlw  0x0c       ; .12
         subwf  SigLen,w   ; signal length
         skpnc
         goto   j139       ; sleep after 93.5 sec no signal
         movlw  0x0b       ; .11
         subwf  SigLen,w   ; signal length
         skpz              ; after 86.5 sec no signal
         goto   j13e       ; loop further
         movlw  0xb9       ; .185
         subwf  RF32,w     ; oxB9 = .185 x .3071 = 0.6 sec
         skpc
         goto   j13e       ; loop further
j139:    clrf   RF31       ; clear
         clrf   RF30       ; clear
         movfw  GPIO
         movwf  RF2E       ; save IO status
         sleep             ; wait for RC-Signal edge
j13e:    goto  j043        ; process RC-signal
         sleep
         end
