;         *******  bitsc1  *****    ESC for toy car Rx

;        This design will work only when the "UP" and "DOWN"
;        inputs are connected to points on the Rx that are
;        positive when the Tx button is NOT pushed, and turn
;        negative WHEN the Tx button is pushed.

;        This version allows the user to set an automatic
;        motor cut off feature to the desired time delay in
;        increments of 15 sec. This is provided for safety
;        as the airplane can easily out fly the range of the
;        Tx.  Setting the delay is done as follows:

;        1-  When the Rx and wired in BitSC is powered
;        up, there will be aprox 1 sec delay after which
;        the motor will blip once for each 15 sec interval
;        that the BitSC is set for.

;        2- After the blipping has stopped there is a 2 sec
;        "window" wherein a new number of increments can be
;        entered by pushing the "down" button the number of
;        times equal to the number of 15 sec's desired.
;        The first press of the "down" button holds the
;        "window" open to gather the remaining presses.

;        3- After the desised number of intervals has been
;        entered, the "up" button is pressed and the unit is
;        ready for normal use.

;        4- In the event that the "up" button is pressed
;        before the 2 sec window is over the unit will hang
;        waiting for an additional "up" press to be ready.
;        This has the effect of reducing the number of 15
;        sec intervals to just one, but ONLY for that single
;        power up. Thus one can have several intervals of 15
;        sec stored for normal use, but can switch to just
;        a single 15 sec interval when desired.

;        The BitSC uses a reverse exponential lookup table
;        for motor speed control.



        maclib  'P12F629.inc'


        device  PIC12F629,intrc_osc,wdt_off,mclr_off,bod_off,pwrt_off,cpd_off,protect_off

        data
        org     32


tmp     ds      1               ;general purpose counter
cnt     ds      1               ;same
del1    ds      1
del2    ds      1
del3    ds      1
del4    ds      1
acc     ds      1               ;acumulator for motor channel
dty     ds      1               ;duty cycle for motor channel
speed   ds      1               ;motor speed for table lookup
delnum  ds      1

mtr     =       gpio.5          ;output for motor PWM
down    =       gpio.4          ;input for decrease speed
up      =       gpio.2          ;input for increase speed
inputs  =       010100b         ;inputs on gp4 and 2

        eeprom
        org     0

        db      1


        code
        org     0

        setb    rp0          ;switch to page 1
        call    03ffh        ;fetch osccal nomber (FOR 1ST TIME CHIP PRGMING)
        mov     osccal,w     ;move it into osccal (FOR 1ST TIME CHIP PRGMING)
;       mov     osccal,#112  ;move cal# previously found at 03FF into osccal
                             ;USE THIS METHOD AFTER 1ST TIME CHIP PROGRAMMING
        clrb    rp0          ;switch back to page 0
        jmp start

table   jmp     pc+w
        retw    0,0,45,64,78,91,101,111,120,129,137,145,152,159,166,172,178,184
        retw    190,195,200,205,210,215,220,225,230,235,240,245,250,255,255,255

start   clr     tmp
        clr     cnt
settle  jmp     $+1               ;wait aprox 1 sec
        jmp     $+1
        jmp     $+1
        jmp     $+1
        jmp     $+1
        jmp     $+1
        djnz    tmp,settle        ;for processor to settle
        djnz    cnt,settle
        setb    rp0               ;switch to page 1
        mov     trisio,#inputs    ;set inputs
        clr     option            ;enable global pullups
        mov     wpu,#010100b      ;enable gp2 & gp4 pullups
        clrb    rp0               ;back to page 0
        mov     cmcon,#00000111b  ;free gpio.0,1,2 (set comparator to off)
        clr     gpio
        clr     dty
        clr     w               ;set w to 1st eeprom memory location
        call    eread           ;read from eeprom, returning in w
        mov     delnum,w        ;transfer to delay number
        mov     cnt,w           ;and also to cnt
        jmp     strtblp         ;jump around delay
nxtblip call    dely5           ;wait about a sec
strtblp mov     del2,#100       ;blip motor once for each 15 sec delay
blip    setb    mtr             ;turn motor on
        djnz    del1,blip       ;1st delay loop
        djnz    del2,blip       ;2nd delay loop
        clrb    mtr             ;turn motor off
        djnz    cnt,nxtblip     ;decrement cnt and repeat if not zero
        mov     tmp,#10         ;setup 3rd delay element
chksetd jnb     up,setdel       ;check if up button pressed
        djnz    del1,chksetd    ;1st loop
        djnz    del2,chksetd    ;2nd loop
        djnz    tmp,chksetd     ;3rd loop
        setb    gpio.0          ;optional led at pin 7 can be used to
                                ;indicate programing window is over
setspd  mov     speed,#1        ;speed needs value other than zero
getsigs clr     del1            ;initialize delay values
        clr     del2
        mov     del4,delnum
setdel3 mov     del3,#11        ;this delay variable gets delnum
chksigs jnb     up,incrse       ;checking up button here, go if pushed
        jnb     down,decrse     ;checking down button here, go if pushed
        call    pwm             ;keep up pwm
        djnz    del1,chksigs    ;start of 15 sec timing
        djnz    del2,chksigs
        djnz    del3,chksigs
        djnz    del4,setdel3
nxtchk  jnb     up,incrse       ;button press here will leave delay loop
        jnb     down,decrse     ;same as above
        call    pwm             ;keep up pwm
        mov     w,speed
        call    table
        mov     dty,w
        call    dely30
        djnz    speed,nxtchk    ;dec speed and loop back to check buttons
        jmp     setspd          ;timed out, start over

incrse  inc     speed           ;inc speed index
        csb     speed,#33       ;compare & skip next if speed < 33
        dec     speed           ;if speed = 33 then dec speed
        jmp     getw            ;jump around decrease speed
decrse  dec     speed           ;dec speed index
        snz                     ;skip next if speed not down to zero
        inc     speed           ;if it is zero then inc it
getw    mov     w,speed         ;speed goes to w for table lookup
        call    table           ;get value from table
        mov     dty,w           ;and transfer to dty
        call    dely12          ;delay some
        jmp     getsigs         ;jump back to check buttons again


pwm     add     acc,dty         ;add duty to accumulator
        sc                      ;if add carried then
        clrb    mtr             ;skip clearing motor bit
        snc                     ;if add didn't carry then
        setb    mtr             ;skip setting motor bit
        nop                     ;add some time here
        nop
        nop
        nop
        ret


dely30  mov     cnt,#30         ;setup cnt for looping
        jmp     next            ;jump over next setup
dely12  mov     cnt,#12         ;setup cnt for looping
next    call    pwm             ;keep up pwm while looping here for
        djnz    tmp,next        ;about 3/4 sec to slow down constant
        djnz    cnt,next        ;repeating before going back to check
        ret

setdel  clr     tmp             ;always
        jnb     up,$            ;wait until signal is hi again
        djnz    cnt,$           ;debounce signal
getbtn  jnb     down,incdel     ;go if signal turns lo
        jnb     up,finish       ;go if signal turns lo
        jmp     getbtn          ;loop back for to check buttons
incdel  jnb     down,$          ;wait till signal hi again
        djnz    cnt,$           ;debounce signal
        inc     tmp             ;inc counter
        clr     w               ;set eeprom location
        call    ewrite          ;write tmp to eeprom memory
        jmp     getbtn          ;jump back to repeat
finish  mov     delnum,tmp      ;move counter to delay number for use
        snz                     ;skip next if not zero
        inc     delnum          ;inc it if it was zero
        jmp     setspd          ;jump back to get button presses

dely10  mov     tmp,#10
        jmp     nxtdely
dely5   mov     tmp,#5
nxtdely djnz    del1,nxtdely
        djnz    del2,nxtdely
        djnz    tmp,nxtdely
        ret


eread   setb    rp0             ;eeprom read for 12F629 here
        mov     eeadr,w
        setb    rd
        mov     w,eedata
        clrb    rp0
        ret


ewrite  setb    rp0             ;eeprom write for 12F629 here
        mov     eeadr,w
        mov     eedata,tmp
        setb    wren
        mov     eecon2,#55h
        mov     eecon2,#0AAh
        setb    wr
        jb      wr,$
        clrb    rp0
        ret
