Advertisement
creamygoat

Shutter Release / Latching Switch for PIC10

Jul 20th, 2011 (edited)
2,566
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pic 16 28.74 KB | None | 0 0
  1. ;-------------------------------------------------------------------------------
  2. ; Shutter release / latching switch
  3. ;
  4. ; Author:   Daniel Neville (Blancmange)
  5. ; Platform: PIC10F200/202/204/206
  6. ; Modified: 16 June 2010
  7. ; Licence:  Public domain
  8. ;
  9. ; This program causes one output pin to mirror an input pin (debounced) for
  10. ; short pulses but to latch high when a long pulse is received. Once latched,
  11. ; the leading edge of the next pulse releases the latch and if that pulse is
  12. ; short, the output will go low on the trailing edge of that pulse.
  13. ;
  14. ; If an input pulse that releases the latch is long, the latch will be
  15. ; reactivated and the output will remain high.
  16. ;
  17. ; As a bonus, two other outputs are provided. One output indicates that the
  18. ; latch is active, This could be wired to an LED to indicate to the user that
  19. ; it's no longer necessary to continue to hold down the button. The lit state
  20. ; of the LED would remind the user that the output is latched high even though
  21. ; the button is not pressed.
  22. ;
  23. ; The other output also indicates the latched state but when wired to an LED,
  24. ; causes the LED to blink rapidly from the moment the latch is activated to
  25. ; the time the button is released. Upon release, the LED remains steady to
  26. ; indicate that the latch is in effect even though the button is released.
  27. ;
  28. ; A tri-colour LED with a red LED and a green LED in the same package would
  29. ; provide nice visual feedback. One LED would be wired to mirror the state
  30. ; of the button, another would be wired to the blinker output.
  31. ;
  32. ; An example
  33. ;
  34. ;                  __   ___    ______________:___________          ______
  35. ; In:  ToggleIn  _|  |_|   |__|              :           |________|      |____
  36. ;                  __   ___   :______________:___________________________
  37. ; Out: ToggleOut _|  |_|   |__|              :                           |____
  38. ;                             :              :____________________
  39. ; Out: Latched   _____________:______________|                    |___________
  40. ;                             :              :_   _   _   ________
  41. ; Out: Blinker   _____________:______________| |_| |_| |_|        |___________
  42. ;                             :              :
  43. ;                             :<-- "Long" -->:
  44. ;
  45. ;-------------------------------------------------------------------------------
  46.  
  47. ;-------------------------------------------------------------------------------
  48. ; Index
  49. ;-------------------------------------------------------------------------------
  50.  
  51.  
  52. ; Listing Options
  53. ; Includes
  54. ; Chip configuration
  55. ; I/O Pin assignment
  56. ; Constants
  57. ; State names
  58. ;
  59. ; Subtraction and comparison on the PIC
  60. ;
  61. ; Reset
  62. ; SetOptionAndTriStateRegs
  63. ; ResetSWTimers
  64. ; UpdateSWTimers
  65. ; On_MillisecondTick
  66. ; On_CentisecondTick
  67. ; Do_DebounceTIn
  68. ; Do_Blinker
  69. ; Do_Toggle
  70. ; Main and WakeUp
  71. ;
  72. ; Unitialised variables
  73. ; Overlapping temporary variables
  74.  
  75.  
  76. ;-------------------------------------------------------------------------------
  77. ; Listing options
  78. ;-------------------------------------------------------------------------------
  79.  
  80.  
  81.   ; The p10f200.inc file requires the processor type to be declared in advance.
  82.  
  83.   list p=p10f200
  84.  
  85.   ; All numbers in this listing are to be interpreted as decimal except when
  86.   ; the radix is given.
  87.  
  88.   list r=dec
  89.  
  90.  
  91. ;-------------------------------------------------------------------------------
  92. ; Includes
  93. ;-------------------------------------------------------------------------------
  94.  
  95.  
  96.   #include <p10f200.inc>
  97.  
  98.  
  99. ;-------------------------------------------------------------------------------
  100. ; Chip configuration
  101. ;-------------------------------------------------------------------------------
  102.  
  103.  
  104. ; Internal oscillator used
  105. ; Watchdog timer on
  106. ; Content protection off
  107. ; Master clear-reset off
  108.  
  109.   __CONFIG _IntRC_OSC & _WDT_ON & _CP_OFF & _MCLRE_OFF
  110.  
  111.  
  112. ;-------------------------------------------------------------------------------
  113. ; I/O Pin assignment
  114. ;-------------------------------------------------------------------------------
  115.  
  116.  
  117. ; Bit positions
  118.  
  119. bToggleOut      equ 0   ; Mirrors ToggleIn except when Latched is high
  120. bLatched        equ 1   ; Long pulse sets Latched, short pulse resets it.
  121. bBlinker        equ 2   ; Blinks rapidly when latched mode is activated
  122. bToggleIn       equ 3
  123.  
  124. ; Masks
  125.  
  126. mToggleOut      equ 1 << bToggleOut
  127. mLatched        equ 1 << bLatched
  128. mBlinker        equ 1 << bBlinker
  129. mToggleIn       equ 1 << bToggleIn
  130.  
  131. ; GPIO masks
  132.  
  133. mInputs         equ mToggleIn
  134. mOutputs        equ mBlinker | mLatched | mToggleOut
  135.  
  136. ; Inverted inputs and outputs. If ToggleIn, say, is wired active low (perhaps
  137. ; with the help of the optional weak pull-ups feature of the PIC), mInverted
  138. ; should include the mToggleIn mask.
  139.  
  140. mInvertedIO     equ 0
  141.  
  142.  
  143. ;-------------------------------------------------------------------------------
  144. ; Constants
  145. ;-------------------------------------------------------------------------------
  146.  
  147.  
  148. ; By default, the prescaler is set to 1:2 so that TMR0 runs at half the rate
  149. ; of the instruction clock, which is a quarter of the rate of the internal
  150. ; 4MHz oscillator. HFTicksIn1ms is the value by which TMR0 would increase in
  151. ; an interval of one millisecond if TMR0 were unrestricted by the tiny word
  152. ; size of the register in which it is kept.
  153. ;
  154. ; HFTicksIn1ms must be less than 4096 and large enough so that the main loop
  155. ; of the program has no chance of allowing the unsigned 12-bit high frequency
  156. ; software counter to overflow or even reach twice the value of HFTicksIn1ms.
  157.  
  158. HFTicksIn1ms    equ 500 ; TMR0 counts
  159.  
  160.  
  161. ; The ToggleOut pin mirrors the ToggleIn pin except when Latched mode is
  162. ; activated, in which case ToggleOut is held high. Latched mode is activated
  163. ; by a long pulse on ToggleIn and deactivated by the rising edge of a
  164. ; a subsequent pulse. (If that pulse turns out to be a long one, Latched
  165. ; mode will be reactivated without disturbance to high state of ToggleOut.)
  166.  
  167. ToggleLatchTime equ 100 ; centiseconds
  168.  
  169.  
  170. ; The ToggleIn pin is debounced by this program. The debounced version of the
  171. ; input is kept high for a very shirt interval after the trailing edge of the
  172. ; original input. Good switches finish bouncing entirely in about 1ms. Most
  173. ; settle down in under 6ms. A maximum notch time of 3ms for each bounce should
  174. ; be ample for all but the very worst switches.
  175. ;
  176. ; See http://www.ganssle.com/debouncing.htm
  177. ;
  178. ; If an input is logically inverted because a normally closed switch is
  179. ; used or pull-ups are used and the input switch grounds the input pin,
  180. ; it's important to invert the logic again as soon as it's read from the
  181. ; GPIO word and cached in the idealised representation in which 0 means
  182. ; released and 1 means pushed.
  183.  
  184. DebounceTime equ 3 ; milliseconds (max. time of open state in bounce)
  185.  
  186.  
  187. ; A pretty feature is the Blinker output, which rapidly flashes when ToggleIn
  188. ; is held high long enough to activate the latch feature, alerting the user
  189. ; that continued pressure on the button is no longer necessary. When the
  190. ; buttin is released (and ToggleIn goes low), the Blinker output stays high
  191. ; until the moment the user presses the button again.
  192. ;
  193. ; An excellent way to indicate the latched condition is with a tri-colour LED
  194. ; consisting of a red LED and and a green LED in the same package. The red LED
  195. ; is wired to be on when the button is pressed and the green LED is wired to
  196. ; the Blinker output pin.
  197. ;
  198. ; For a short button press, the LED lights red for the duration of the pressing.
  199. ; When the button is depressed long enough for the latch to activate, the LED
  200. ; rapidly flashes yellow and red. When the button is released, the LED changes
  201. ; to green. A subsequent momentary press will cause the LED to light up red and
  202. ; then go out. (If that press is long, the LED will start blinking again.)
  203. ;
  204. ; An alternative arrangement is to have two LEDs (perhaps of differing colour
  205. ; side by side. As with the tri-colour LED, that any LED is lit means the
  206. ; output pin is set high. The colour or the position of the lit LED indicates
  207. ; the cause.
  208. ;
  209. ; The mark (lit) and space (unlit) times are independently adjustable.
  210.  
  211. BlinkMarkTime   equ 34 ; miliiseconds
  212. BlinkSpaceTime  equ 34 ; miliiseconds
  213.  
  214.  
  215. ; Set to 1 if weak pull-ups on input pins are desired, 0 otherwise.
  216.  
  217. UseWeakPullUps  equ 0
  218.  
  219.  
  220. ;-------------------------------------------------------------------------------
  221. ; State names
  222. ;
  223. ; Apart from the housekeeping code, the behaviour of this program is coded
  224. ; in the form of finite state machines.
  225. ;
  226. ;-------------------------------------------------------------------------------
  227.  
  228.  
  229. ; DebounceTIn, the debounce timer for the ToggleIn pin
  230.  
  231. DebounceTIn_Low         equ 0
  232. DebounceTIn_High        equ 1
  233. DebounceTIn_Sustained   equ 2
  234.  
  235.  
  236. ; Toggle, the latching switch feature
  237.  
  238. Toggle_Idle     equ 0
  239. Toggle_Short    equ 1
  240. Toggle_Long     equ 2
  241. Toggle_Latched  equ 3
  242.  
  243.  
  244. ; Blinker, a substate of Toggle
  245. Blinker_Space   equ 0
  246. Blinker_Mark    equ 1
  247.  
  248.  
  249. ;-------------------------------------------------------------------------------
  250. ; Subtraction and comparison on the PIC
  251. ;
  252. ; Like the 6502, the PIC uses the Borrow Convention when it comes to
  253. ; subtraction or comparison, clearing an initially set carry flag when
  254. ; the unsigned result underflows. This is in contrast to the Z80 and
  255. ; the AVR chips, which set an initially cleared carry flag when an
  256. ; unsigned result underflows.
  257. ;
  258. ;  Result of Operand - W
  259. ;
  260. ;  * C=1 Z=0  =>  Positive (Operand > W)
  261. ;  * C=1 Z=1  =>  Zero     (Operand = W)
  262. ;  * C=0 Z=0  =>  Negative (Operand < W)
  263. ;  * C=0 Z=1  Cannot occur
  264. ;
  265. ; Note that on the PIC, the W register is always the one that is subtracted
  266. ; from the other operand. Instead of thinking of W as the accumulator, it may
  267. ; be helpful to think of the File Registers as accumulators and the W register
  268. ; merely a storage register. If W is 20, "SUBLW 3" will cause W to become 239
  269. ; (unsigned) or -17 (signed).
  270. ;
  271. ;-------------------------------------------------------------------------------
  272.  
  273. ;-------------------------------------------------------------------------------
  274.   code h'000'
  275. ;-------------------------------------------------------------------------------
  276.  
  277.  
  278. ; Reset
  279.  
  280. ; On powering up, the PIC10 starts executing code at the last program address,
  281. ; the content of which is factory set to contain the MOVLW instruction that
  282. ; loads the W register with the oscillator calibration constant. The constant
  283. ; is a two's complement signed 8-bit word that indicates the deviation required
  284. ; to make the built-in oscillator accurate.
  285. ;
  286. ; When programming the PIC10, care must be taken not to overwrite the word
  287. ; at last address of program memory, as it is set at the factory for the
  288. ; individual chip. It's a good idea to read it first so it can be restored
  289. ; in the event it gets overwritten.
  290.  
  291. Reset
  292.         ; W is loaded by the factory-set MOVLW instruction at the end of
  293.         ; of program memory. Bits 7..1 contain the oscillator calibration.
  294.         ; Bit 0, if set, causes the instruction clock to appear on pin GPIO2.
  295.  
  296.         ; Make sure GPIO2 is free for general I/O.
  297.         andlw   ~(1 << FOSC4)
  298.         movwf   OSCCAL
  299.  
  300.         ; Identify the cause of the reset.
  301.         btfsc   STATUS, GPWUF
  302.           goto    WakeUp        ; Wake-up on I/O pin change
  303.         ;btfsc   STATUS, CWUF    ; pic10f202/206 feature
  304.         ;  goto    WakeUp        ; Wake-up on comparator change
  305.         btfsc   STATUS, NOT_TO
  306.           goto    Main          ; Power-up or NOT_MCLR pulled low
  307.         btfss   STATUS, NOT_PD
  308.           goto    WakeUp        ; Watchdog time-out during sleep
  309.         goto    Main            ; Watchdog time-out (not during sleep)
  310.  
  311.  
  312. ;-------------------------------------------------------------------------------
  313.  
  314.  
  315. ; SetOptionAndTriStateRegs
  316. ;
  317. ; The OPTION and TRIS registers are altered on wake-up and must be restored.
  318.  
  319. SetOptionAndTriStateRegs
  320.  
  321. ; Enable wake-up on I/O pin change (NOT_GPWU = 0)
  322. ; UseWeakPullUps decides if weak pull-up on I/O pins are used (NOT_GPPU)
  323. ; Use internal oscillator (T0CS = 0)
  324. ; [Not relevant] Use rising edge (T0SE = 0)
  325. ; Prescaler assigned to Timer 0 (PSA = 0)
  326. ; Prescaler set to 1:2 (PS2-0 = 000)
  327. SOTR_mNotGPPU equ ((!UseWeakPullUps) & 1) << NOT_GPPU
  328. SOTR_mHardCoded equ (0<<NOT_GPWU) | (0<<T0CS) | (0<<T0SE) | (b'000'<<PS0)
  329.  
  330.         movlw   SOTR_mHardCoded | SOTR_mNotGPPU
  331.         option
  332.  
  333.         ; Set the I/O direction bits. (0 = output, 1 = input)
  334.         movlw   mInputs
  335.         tris    GPIO
  336.  
  337.         retlw   0
  338.  
  339.  
  340. ;-------------------------------------------------------------------------------
  341.  
  342.  
  343. ; ResetSWTimers
  344. ;
  345. ; Clears all the software timers.
  346.  
  347. ResetSWTimers
  348.         movf    TMR0, W
  349.         movwf   LastTMR0
  350.         clrf    HFTimer_H
  351.         clrf    HFTimer_L
  352.         clrf    Timer_DebounceTIn
  353.         clrf    Timer_ToggleIn
  354.         clrf    Timer_Blinker
  355.         retlw   0
  356.  
  357.  
  358. ;-------------------------------------------------------------------------------
  359.  
  360.  
  361. ; UpdateSWTimers
  362. ;
  363. ; Reads the 8-bit TMR0 register and updates the high frequency software
  364. ; timer used to determine when to call the millisecond and centisecond
  365. ; event handlers On_MillisecondTick and On_CentisecondTick.
  366.  
  367. UpdateSWTimers
  368.         ; Find the delta time for this cycle.
  369.         movf    LastTMR0, W
  370.         movwf   TV_DeltaTMR0
  371.         movf    TMR0, W
  372.         movwf   LastTMR0
  373.         subwf   TV_DeltaTMR0, f
  374.         comf    TV_DeltaTMR0, f
  375.         incf    TV_DeltaTMR0, f
  376.         movf    TV_DeltaTMR0, W
  377.  
  378.         ; Increment the high frequency counter by this delta time.
  379.         addwf   HFTimer_L, f
  380.         btfsc   STATUS, C
  381.           incf    HFTimer_H, f
  382.  
  383. USWT_TestHFT
  384.         ; if HF_Timer:11-0 >= HFTicksIn1ms, a millisecond tick must occur.
  385. USWT_TestHFTH
  386.         ; Extract the high four bits of the 12-bit sub-ms timer field.
  387.         movf    HFTimer_H, W
  388.         andlw   h'0F'
  389.         movwf   TV_SMTimer_H
  390.  
  391.         movlw   high(HFTicksIn1ms)
  392.         subwf   TV_SMTimer_H, W
  393.         btfsc   STATUS, Z
  394.           goto    USWT_TestHFTL
  395.         btfsc   STATUS, C
  396.           goto    USWT_MillisecondTick
  397.         goto    USWT_Done
  398. USWT_TestHFTL
  399.         movlw   low(HFTicksIn1ms)
  400.         subwf   HFTimer_L, W
  401.         btfsc   STATUS, Z
  402.           goto    USWT_MillisecondTick
  403.         btfss   STATUS, C
  404.           goto    USWT_Done
  405.  
  406. USWT_MillisecondTick
  407.         ; Subtract HFTicksIn1ms from HF_Timer.
  408.         movlw   low(HFTicksIn1ms)
  409.         subwf   HFTimer_L, f
  410.         btfsc   STATUS, Z
  411.           goto    USWT_DoneMSLow
  412.         btfss   STATUS, C
  413.           decf    HFTimer_H, f
  414. USWT_DoneMSLow
  415.         movlw   high(HFTicksIn1ms)
  416.         subwf   HFTimer_H, f
  417.  
  418.         ; Increment the millisecond digit field of HFTimer.
  419.         movlw   1 << 4
  420.         addwf   HFTimer_H, f
  421.  
  422.         movlw   10 << 4
  423.         subwf   HFTimer_H, W
  424.         movlw   h'0F'
  425.         btfsc   STATUS, C
  426.           andwf   HFTimer_H, f
  427.  
  428.         call    On_MillisecondTick
  429.  
  430.         ; Call the centisecond event handler if the millisecond digit is zero.
  431.         movlw   h'F0'
  432.         andwf   HFTimer_H, W
  433.         btfsc   STATUS, Z
  434.           call    On_CentisecondTick
  435.         incf    Timer_ToggleIn, f
  436.  
  437. USWT_Done
  438.         retlw   0
  439.  
  440.  
  441. ;-------------------------------------------------------------------------------
  442.  
  443.  
  444. ; On_MillisecondTick
  445.  
  446. On_MillisecondTick:
  447.         ; Advance the debounce timer for the ToggleIn pin
  448.         incf    Timer_DebounceTIn, f
  449.  
  450.         ; The blinker timer counts downward.
  451.         movf    Timer_Blinker, W
  452.         btfss   STATUS, Z
  453.           decf    Timer_Blinker, f
  454.  
  455.         retlw   0
  456.  
  457.  
  458. ;-------------------------------------------------------------------------------
  459.  
  460.  
  461. ; On_CentisecondTick
  462.  
  463. On_CentisecondTick:
  464.         ; Update the state timer for Toggle FSM, in which states are timed in
  465.         ; the order of a few centiseconds to 2.5 seconds.
  466.         incf    Timer_ToggleIn, f
  467.  
  468.         retlw   0
  469.  
  470.  
  471. ;-------------------------------------------------------------------------------
  472.  
  473.  
  474. ; Do_DebounceTIn
  475.  
  476. ; The input fetched from GPIO is read once every program cycle and kept
  477. ; in CachedInput. For reliable operation, whatever input recorded in
  478. ; CachedInput is debounced and recorded in DebouncedInput.
  479. ;
  480. ; The debouncing of the signal at ToggleIn pin is performed by this
  481. ; subroutine, the behaviour of which can be described by the following
  482. ; Finite State Machine of the Moore kind.
  483. ;
  484. ; FSM DebounceTIn:
  485. ;   Low (initial):
  486. ;     E: Debounced := 0
  487. ;     Input = 1 --> High
  488. ;   High:
  489. ;     E: Debounced := 1
  490. ;     Input = 0 --> Sustained
  491. ;   Sustained:
  492. ;     E: Debounced := 1, Timer := 0
  493. ;     A: Timer increases by one for each millisecond that passes
  494. ;     Timer >= DebounceTime --> Low
  495. ;     Input = 1 --> High
  496. ; End
  497. ;
  498. ; "E:", "A:" and "X:" indicate entry actions, state activity and exit actions.
  499.  
  500. Do_DebounceTIn
  501.         movf    SV_DebounceTIn, W
  502.         addwf   PCL, f
  503.         goto    Do_DebounceTIn_Low
  504.         goto    Do_DebounceTIn_High
  505.         goto    Do_DebounceTIn_Sustained
  506.  
  507. Do_DebounceTIn_Outputs_Lookup
  508.         movf    SV_DebounceTIn, W
  509.         addwf   PCL, f
  510.         retlw   0
  511.         retlw   mToggleIn
  512.         retlw   mToggleIn
  513.  
  514. Go_DebounceTIn_Low
  515.         movlw   DebounceTIn_Low
  516.         movwf   SV_DebounceTIn
  517.         goto    Do_DebounceTIn_End
  518.  
  519. Do_DebounceTIn_Low
  520.         movlw   DebounceTIn_High
  521.         btfsc   CachedInput, bToggleIn
  522.           movwf   SV_DebounceTIn                ; ToggleIn = 1 --> High
  523.         goto    Do_DebounceTIn_End
  524.  
  525. Do_DebounceTIn_High
  526.         btfss   CachedInput, bToggleIn
  527.           goto    Go_DebounceTIn_Sustained      ; ToggleIn = 0 --> Sustained
  528.         goto    Do_DebounceTIn_End
  529.  
  530. Go_DebounceTIn_Sustained
  531.         movlw   DebounceTIn_Sustained
  532.         movwf   SV_DebounceTIn
  533.         clrf    Timer_DebounceTIn
  534.         goto    Do_DebounceTIn_End
  535.  
  536. Do_DebounceTIn_Sustained
  537.         ; Change back to DebounceTIn_High if the notch was not very long.
  538.         movlw   DebounceTIn_High
  539.         btfsc   CachedInput, bToggleIn
  540.           movwf   SV_DebounceTIn                ; ToggleIn = 1 --> High
  541.  
  542.         movlw   DebounceTime
  543.         subwf   Timer_DebounceTIn, W
  544.         btfsc  STATUS, C
  545.           goto    Go_DebounceTIn_Low            ; Timer >= DebounceTime --> Low
  546.         ;goto    Do_DebounceTIn_End
  547.  
  548. Do_DebounceTIn_End
  549.         call    Do_DebounceTIn_Outputs_Lookup
  550.         movwf   DebouncedInput
  551.         retlw   0
  552.  
  553.  
  554. ;-------------------------------------------------------------------------------
  555.  
  556.  
  557. ; Do_Blinker
  558.  
  559. ; This sub-FSM of Toggle is performed by a simple routine that makes no
  560. ; extra demands of the stack, which on the Pic10f200, can holds only two
  561. ; return addresses.
  562.  
  563. Do_Blinker
  564.         movf   Timer_Blinker, W
  565.         btfss   STATUS, Z
  566.           goto    Do_Blinker_End
  567.  
  568.         ; Flip the Mark/Space state
  569.         movlw   Blinker_Mark ^ Blinker_Space
  570.         xorwf   SV_Blinker, f
  571.  
  572.         ; Find the new value for the blinker's countdown timer.
  573.         movlw   Blinker_Space
  574.         xorwf   SV_Blinker, W
  575.         movlw   BlinkMarkTime
  576.         btfsc   STATUS, Z
  577.           movlw   BlinkSpaceTime
  578.         movwf   Timer_Blinker
  579.  
  580. Do_Blinker_End
  581.         retlw   0
  582.  
  583.  
  584. ;-------------------------------------------------------------------------------
  585.  
  586.  
  587. ; Do_Toggle
  588.  
  589. ; The basic function the PIC10 is required to perform is expressed in
  590. ; this subroutine. The rest of the program is mostly just housekeeping.
  591. ; The function is described roughly by the following Finite State Machine
  592. ; of the Moore kind.
  593. ;
  594. ; FSM Toggle:
  595. ;   Idle (initial):
  596. ;     E: ToggleOut := 0
  597. ;     ToggleIn = 1 --> Short
  598. ;   Short:
  599. ;     E: ToggleOut := 1, Timer := 0
  600. ;     A: Timer increases by one for each centisecond that passes
  601. ;     Timer >= ToggleLatchTime --> Long
  602. ;     ToggleIn = 0 --> Idle
  603. ;   Long:
  604. ;     E: ToggleOut := 1
  605. ;     ToggleIn = 0 --> Latched
  606. ;     FSM Blinker:
  607. ;       Blinker_Space:
  608. ;         E: Blinker := 0, Timer_BlinkTimer := BlinkSpaceTime
  609. ;         Timer_BlinkTimer = 0 --> Blinker_Mark
  610. ;       Blinker_Mark (initial):
  611. ;         E: Blinker := 1, Timer_BlinkTimer := BlinkMarkTime
  612. ;         A: Timer_BlinkTimer counts down by the millisecond
  613. ;         X: Blinker := 0
  614. ;         Timer_BlinkTimer = 0 --> Blinker_Space
  615. ;     End
  616. ;   Latched:
  617. ;     E: ToggleOut := 1
  618. ;     ToggleIn = 1 --> Short
  619. ; End
  620. ;
  621. ; "E:", "A:" and "X:" indicate entry actions, state activity and exit actions.
  622.  
  623. Do_Toggle
  624.         movf    SV_Toggle, W
  625.         addwf   PCL, f
  626.         goto    Do_Toggle_Idle
  627.         goto    Do_Toggle_Short
  628.         goto    Do_Toggle_Long
  629.         goto    Do_Toggle_Latched
  630.  
  631. Do_Toggle_Outputs_Lookup
  632.         movf    SV_Toggle, W
  633.         addwf   SV_Toggle, W
  634.         addwf   SV_Blinker, W
  635.         addwf   PCL, f
  636.         retlw   0                                 ; Idle, Space
  637.         retlw   0                                 ; Idle, Mark
  638.         retlw   mToggleOut                        ; Short, Space
  639.         retlw   mToggleOut                        ; Short, Mark
  640.         retlw   mLatched | mToggleOut             ; Long, Space
  641.         retlw   mBlinker | mLatched | mToggleOut  ; Long, Mark
  642.         retlw   mBlinker | mLatched | mToggleOut  ; Latched, Space
  643.         retlw   mBlinker | mLatched | mToggleOut  ; Latched, Mark
  644.  
  645. Go_Toggle_Idle
  646.         movlw   Toggle_Idle
  647.         movwf   SV_Toggle
  648.         goto    Do_Toggle_End
  649.  
  650. Do_Toggle_Idle
  651.         ; Change to Toggle_Short when ToggleIn goes high (and start the timer).
  652.         btfsc   DebouncedInput, bToggleIn
  653.           goto    Go_Toggle_Short       ; ToggleIn = 1 --> Short
  654.         goto    Do_Toggle_End
  655.  
  656. Go_Toggle_Short
  657.         movlw   Toggle_Short
  658.         movwf   SV_Toggle
  659.         clrf    Timer_ToggleIn
  660.         goto    Do_Toggle_End
  661.  
  662. Do_Toggle_Short
  663.         ; Change back to Toggle_Idle if the pulse was not very long.
  664.         movlw   ToggleLatchTime
  665.         subwf   Timer_ToggleIn, W
  666.         btfsc   STATUS, C
  667.           goto    Go_Toggle_Long        ; Timer >= ToggleLatchTime --> Long
  668.         btfss   DebouncedInput, bToggleIn
  669.           goto    Go_Toggle_Idle        ; ToggleIn = 0 --> Idle
  670.         goto    Do_Toggle_End
  671.  
  672. Go_Toggle_Long
  673.         movlw   Toggle_Long
  674.         movwf   SV_Toggle
  675.         movlw   Blinker_Mark
  676.         movwf   SV_Blinker
  677.         movlw   BlinkMarkTime
  678.         movwf   Timer_Blinker
  679.         call    Do_Blinker
  680.         goto    Do_Toggle_End
  681.  
  682. Do_Toggle_Long
  683.         ; Change to Toggle_Latched when ToggleIn goes low.
  684.         btfss   DebouncedInput, bToggleIn
  685.           goto    Go_Toggle_Latched     ; ToggleIn = 0 --> Latched
  686.         call    Do_Blinker
  687.         goto    Do_Toggle_End
  688.  
  689. Go_Toggle_Latched
  690.         movlw   Toggle_Latched
  691.         movwf   SV_Toggle
  692.         goto    Do_Toggle_End
  693.  
  694. Do_Toggle_Latched
  695.         ; Change to Toggle_Short when ToggleIn goes high. ToggleOut will
  696.         ; fall when ToggleIn does, unless ToggleIn is held high for another
  697.         ; long interval, activating the latch feature again.
  698.         btfsc   DebouncedInput, bToggleIn
  699.           goto    Go_Toggle_Short       ; ToggleIn = 1 --> Short
  700.         goto    Do_Toggle_End
  701.  
  702. Do_Toggle_End
  703.         call    Do_Toggle_Outputs_Lookup
  704.         movwf   ToggleOutputs
  705.         retlw   0
  706.  
  707.  
  708. ;-------------------------------------------------------------------------------
  709.  
  710.  
  711. ; Main
  712.  
  713. ; This part of the program as two entry points:
  714. ;
  715. ; * Main    - for power-up and true reset conditions and
  716. ; * WakeUp  - for continued operation after sleeping, preserving state.
  717. ;
  718. ; Except during sleep, the Finite State Machines are executed as fast as they
  719. ; possibly can while monitoring the inputs and the millisecond and centisecond
  720. ; software timers. The upshot of this is that the FSMs get to respond to input
  721. ; events very quickly, in the order of tens of microseconds. (The FSMs are not
  722. ; called from the millisecond and centisecond event handlers, but by the busy
  723. ; loop of the main program.)
  724.  
  725. Main
  726.         ; Reset output variables.
  727.         clrf    ToggleOutputs
  728.  
  729.         ; Set the toggle output to match the input.
  730.         movf    GPIO, W
  731.         xorlw   mInvertedIO
  732.         andlw   mInputs
  733.         movwf   TV_Input
  734.         btfsc   TV_Input, bToggleIn
  735.           bsf     TV_Input, bToggleOut
  736.         movf    TV_Input, W
  737.         andlw   mInputs
  738.         movwf   CachedInput
  739.         movwf   DebouncedInput
  740.         movf    TV_Input, W
  741.  
  742.         ; Set the output latches. Their states will appear
  743.         ; on the I/O pins when the tri-state IO direction
  744.         ; bits are reset.
  745.         xorlw   mInvertedIO
  746.         movwf   GPIO
  747.  
  748.         ; Determine the initial state of the DebounceTIn FSM, the machine
  749.         ; responsible for debouncing the ToggleIn input pin.
  750.         movlw   DebounceTIn_Low
  751.         btfsc   DebouncedInput, bToggleIn
  752.           movlw   DebounceTIn_High
  753.         movwf   SV_DebounceTIn
  754.  
  755.         ; Determine the initial state of the Toggle FSM.
  756.         ; This is to minimise the risk of a spurious change
  757.         ; in state of the output pin when the PIC10 resets.
  758.         movlw   Toggle_Idle
  759.         btfsc   DebouncedInput, bToggleIn
  760.           movlw   Toggle_Short
  761.         movwf   SV_Toggle
  762.  
  763.         ; The blinker state variable must be initialised in case the
  764.         ; implementation uses a jumptable.
  765.         movlw   Blinker_Space
  766.         movwf   SV_Blinker
  767.  
  768. WakeUp
  769.         call    SetOptionAndTriStateRegs
  770.         call    ResetSWTimers
  771.  
  772. MainLoop
  773.         clrwdt
  774.         call    UpdateSWTimers
  775.  
  776.         ; Iterate the finite state machines.
  777.         call    Do_DebounceTIn
  778.         call    Do_Toggle
  779.  
  780.         iorwf   ToggleOutputs, W
  781.         xorlw   mInvertedIO
  782.         movwf   GPIO
  783.  
  784.         ; Read the inputs. Sleep if they haven't changed since last time.
  785.         clrwdt
  786.         movf    CachedInput, W
  787.         movwf   TV_Input
  788.         movf    GPIO, W
  789.         xorlw   mInvertedIO
  790.         andlw   mInputs
  791.         movwf   CachedInput
  792.         xorwf   TV_Input, W
  793.         btfss   STATUS, Z
  794.           goto    MainLoop      ; The input has changed. Do something about it!
  795.  
  796.         ; Are we in a state that requires timing?
  797.         movf    SV_Toggle, W
  798.         xorlw   Toggle_Short
  799.         btfsc   STATUS, Z
  800.           goto    MainLoop      ; Yes, Toggle is Deciding between Short & Long.
  801.         movf    SV_Toggle, W
  802.         xorlw   Toggle_Long
  803.         btfsc   STATUS, Z
  804.           goto    MainLoop      ; Yes, Toggle is in Long, running Blinker
  805.         movf    SV_DebounceTIn, W
  806.         xorlw   DebounceTIn_Sustained
  807.         btfsc   STATUS, Z
  808.           goto    MainLoop      ; Yes, Debouncing in progress
  809.  
  810.         ; There's nothing to do but wait for the input to change state.
  811.  
  812.         ; Be careful how you interpret the advice given in section 9.9.2 of
  813.         ; the datasheet about reading the GPIO register just before the SLEEP
  814.         ; instruction. What is not stated is that you should something with
  815.         ; the information read from that register.
  816.         ;
  817.         ; If you just blindly read the GPIO before sleeping, any change of
  818.         ; input state between that reading and a previous reading will not
  819.         ; be noticed, and the PIC will sleep right through it until another
  820.         ; change occurs or the watchdog time resets the PIC. That would be
  821.         ; sure to be a cause of unreliable behaviour.
  822.  
  823.         sleep                   ; Sleep until I/O wake-up resets the PIC.
  824.  
  825.  
  826. ;-------------------------------------------------------------------------------
  827. ; Unitialised variables
  828. ;-------------------------------------------------------------------------------
  829.  
  830. ;-------------------------------------------------------------------------------
  831.   udata
  832. ;-------------------------------------------------------------------------------
  833.  
  834.  
  835. ; Finite State Machine variables
  836. SV_Toggle       res 1
  837. SV_DebounceTIn  res 1
  838. SV_Blinker      res 1
  839.  
  840. ; Input cached to avoid disturbing the I/O wake-up function
  841. CachedInput     res 1
  842. DebouncedInput  res 1
  843.  
  844. LastTMR0        res 1
  845. HFTimer         ; Milliseconds digit (bits 15-12), HF timer (bits 11-0)
  846. HFTimer_H       res 1   ; Bits 7-4: Millisecond digit, Bits 3-0: HF bits 11-8
  847. HFTimer_L       res 1   ; HF bits 7-0
  848. Timer_DebounceTIn       res 1   ; Debounce timer for ToggleIn (in milliseconds)
  849. Timer_ToggleIn          res 1   ; State timer for ToggleIn (in centiseconds)
  850. Timer_Blinker           res 1   ; Timer for Blinker (in milliseconds)
  851.  
  852. ToggleOutputs   res 1
  853.  
  854.  
  855. ;-------------------------------------------------------------------------------
  856. ; Overlapping temporary variables
  857. ;-------------------------------------------------------------------------------
  858.  
  859.   udata_ovr
  860.  
  861. TV_Input        res 1
  862.  
  863.   udata_ovr
  864.  
  865. TV_DeltaTMR0    res 1
  866.  
  867.   udata_ovr
  868.  
  869. TV_SMTimer_H    res 1
  870.  
  871.  
  872. ;-------------------------------------------------------------------------------
  873.   end
  874. ;-------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement