home *** CD-ROM | disk | FTP | other *** search
/ TAP YIPL / TAP_and_YIPL_Collection_CD.iso / PHREAK / BOXES / DTMFPIC.ASM < prev    next >
Assembly Source File  |  1998-02-07  |  19KB  |  702 lines

  1. ; dtmf.asm:  PWM DTMF dialer
  2. ;
  3. ; Copyright 1992, 1995 Eric Smith
  4. ;
  5. ; dtmf.asm is free software; you can redistribute it and/or modify it under the
  6. ; terms of the GNU General Public License version 2 as published by the Free
  7. ; Software Foundation.  Note that I am not granting permission to redistribute
  8. ; or modify dtmf.asm under the terms of any later version of the General Public
  9. ; License.
  10. ;
  11. ; This program is distributed in the hope that it will be useful (or at least
  12. ; amusing), but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  14. ; Public License for more details.
  15. ;
  16. ; You should have received a copy of the GNU General Public License along with
  17. ; this program (in the file "COPYING"); if not, write to the Free Software
  18. ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ;
  20. ; $Header: /usr/home/kolwynia/eric/pic/dtmf/RCS/dtmf.asm,v 1.16 1995/06/06 18:07:48 eric Exp eric $
  21.  
  22.     device    PIC16C54,HS_OSC,WDT_OFF,PROTECT_OFF
  23.  
  24. f    equ    1               ; for destination argument
  25. w    equ    0               ; for destination argument
  26.  
  27. ind    equ     0               ; used for indirect through FSR
  28. rtcc    equ     1               ; real time clock/counter
  29. pc    equ     2               ; program counter
  30. fsr    equ     4               ; file select register (index register)
  31.  
  32. status    equ     3               ; status register:
  33. cf    equ     0               ;  bit 0 = carry flag
  34. dcf    equ     1               ;  bit 1 = digit carry flag
  35. zf    equ     2               ;  bit 2 = zero flag
  36. pdf    equ     3               ;  bit 3 = power down flag
  37. tof    equ     4               ;  bit 4 = time out flag
  38.                 ;  bits 5,6,7 do not apply to PIC16C54
  39.  
  40. nothing equ     0               ; used to return nothing from subroutines
  41.  
  42. porta    equ     5               ;I/O port RA:
  43. pabit0  equ     0               ;  bit 0 = unused
  44. led     equ     1               ;  bit 1 = low turns on LED
  45. pwm2    equ     2               ;  bit 2 = PWM speaker output 1
  46. pwm3    equ     3               ;  bit 3 = PWM speaker output 2
  47.  
  48. portb   equ     6               ;I/O port RB:
  49. colm0   equ     0               ;  bit 0 = keypad column 0
  50. colm1   equ     1               ;  bit 1 = keypad column 1
  51. colm2   equ     2               ;  bit 2 = keypad column 2
  52. colm3   equ     3               ;  bit 3 = keypad column 3
  53. row0    equ     4               ;  bit 4 = keypad row 0
  54. row1    equ     5               ;  bit 5 = keypad row 1
  55. row2    equ     6               ;  bit 6 = keypad row 2
  56. row3    equ     7               ;  bit 7 = keypad row 3
  57.  
  58. ;
  59. ; Where it's at...
  60. ;
  61. ram     equ     08h             ; start of usable RAM
  62. body    equ     000h            ; start of program memory
  63.  
  64. freep0  set     0               ; free words of page zero
  65. freep1  set     0               ; free words of page one
  66.  
  67.     org     ram             ; start of RAM
  68.  
  69. one:    ds      1               ; holds the value 1 for incrementing W
  70. zero:   ds      1               ; holds the value 0 for two's-complementing W
  71. c4f:    ds      1               ; holds the value 04fh for SIN scaling
  72.  
  73. row:    ds      2               ; row sine phase (fixed point)
  74. colm    ds      2               ; column sine phase (fixed point)
  75. rowfrq: ds      2               ; row increment (fixed point)
  76. colmfrq: ds     2               ; column increment (fixed point)
  77. iter:   ds      2               ; iteration count for DTMF burst in sample
  78.                 ;    periods
  79.  
  80. newsamp: ds      1               ; sample value being calculated
  81. oldsamp: ds      1               ; last sample (currently being output)
  82.  
  83. digidx: ds      1               ; index into phone number
  84. digit:  ds      1               ; current digit
  85. temp:   ds      1
  86.  
  87. kcol:    ds    1        ; key scan column
  88. krow:    ds    1        ; key scan row
  89.  
  90. freeram equ     020h-.
  91.  
  92.     org     body            ; start of ROM
  93.  
  94.     if      .-000h
  95.     error   "loop0 is not at 000h"
  96.     endif
  97.  
  98. loop0:   
  99.     call    incrow          ; 25
  100.     call    waste6          ; 6
  101.     call    inccol          ; 15
  102.     call    calccol         ; 18
  103.     call    pulse           ; 28
  104.  
  105. ; LOOP is the entry point to the DTMF burst generator.  LOOP1 falls into it.
  106. ; LOOP can't be called as a subroutine (main line only),
  107. ; outputs one DTMF burst.  The two's complement of the duration of the
  108. ; burst in sample intervals is stored in ITER.  When the loop completes,
  109. ; it jumps to NXTDIG (from INCPHAS, see the comments there).
  110.  
  111. loop0a: nop                     ; 1
  112. loop:   bsf     porta,pwm3      ; 1
  113.     bsf     porta,pwm2      ; 1
  114.     movf    newsamp,w       ; 1
  115.     movwf   oldsamp         ; 1
  116.     andlw   070h            ; 1
  117.     movwf   pc              ; 2
  118.  
  119. incrow: goto    incrowx
  120. inccol: goto    inccolx
  121.  
  122. flash:  goto    flashx
  123. pause:  goto    pausex
  124.  
  125.     ds      0
  126. freep0  set     freep0+0
  127.  
  128.     if      .-010h
  129.     error   "loop1 is not at 010h"
  130.     endif
  131.  
  132. loop1:  
  133.     call    incrow          ; 25
  134.     call    waste8          ; 8
  135.     call    inccol          ; 15
  136.     call    pulse           ; 28
  137. loop1b: nop                     ; 1
  138. loop1a: movf    colm+1,w        ; 1
  139.     btfsc   colm+1,6        ; 1 is it the 2nd half of a half cycle?
  140.     subwf   zero,w          ; 1 then complement to effect a subtract from 64
  141.     andlw   07fh            ; 1 reduce to 6 bits for 90 degrees     
  142.     call    sinetbl         ; 6  and get amplitude
  143.  
  144.     btfsc   colm+1,7        ; 1 is amplitude supposed to be negative?
  145.     subwf   c4f,w           ; 1 change polarity of sine amplitude
  146.     
  147.     addwf   newsamp         ; 1
  148.     rrf     newsamp         ; 1
  149.     goto    loop            ; 9
  150.  
  151.     ds      1
  152. freep0  set     freep0+1
  153.  
  154.     if      .-020h
  155.     error   "loop2 is not at 020h"
  156.     endif
  157.  
  158. loop2:  
  159.     call    incrow          ; 25
  160.     call    waste7          ; 7
  161.     call    pulse           ; 28
  162.     call    inccol          ; 15
  163.     goto    loop1a          ; 25
  164.  
  165. waste8: nop                     ; 1
  166. waste7: nop                     ; 1
  167. waste6: nop                     ; 1
  168. waste5: nop                     ; 1
  169. waste4: retlw   nothing         ; 4 (includes call)
  170.  
  171.     ds      6
  172. freep0  set     freep0+6
  173.  
  174.     if      .-030h
  175.     error   "loop3 is not at 030h"
  176.     endif
  177.  
  178. loop3: 
  179.     call    inccol          ; 15
  180.     nop                     ; 1
  181.     call    pulse           ; 28
  182.     call    incrow          ; 25
  183.     call    waste6          ; 6
  184.     goto    loop1a          ; 25
  185.  
  186.     ds      10
  187. freep0  set     freep0+10
  188.  
  189.     if      .-040h
  190.     error   "loop4 is not at 040h"
  191.     endif
  192.  
  193. loop4:  
  194.     call    pulse           ; 28
  195.     call    incrow          ; 25
  196.     call    waste6          ; 6
  197.     call    inccol          ; 15
  198.     goto    loop1b          ; 26
  199.  
  200. ;
  201. ; DTMF keypad frequency matrix:
  202. ;
  203. ;               :       :       :       :       :
  204. ;               : 1209  : 1336  : 1477  : 1633  :
  205. ;       ........!_______!_______!_______!_______!
  206. ;               !       !       !       !       !
  207. ;       697     !   1   !   2   !   3   !   A   !
  208. ;       ........!_______!_______!_______!_______!
  209. ;               !       !       !       !       !
  210. ;       770     !   4   !   5   !   6   !   B   !
  211. ;       ........!_______!_______!_______!_______!
  212. ;               !       !       !       !       !
  213. ;       852     !   7   !   8   !   9   !   C   !
  214. ;       ........!_______!_______!_______!_______!
  215. ;               !       !       !       !       !
  216. ;       941     !   *   !   0   !   #   !   D   !
  217. ;       ........!_______!_______!_______!_______!
  218.  
  219.  
  220.  
  221. ; These equates are used to make the row and column tables easier to read.
  222. ;
  223. ; These equates define the phase increments necessary to generate sine
  224. ; waves of the appropriate frequencies for DTMF tones.  The values are
  225. ; computed with the formula 256 * Tsamp * Freq.  The 256 accounts
  226. ; for the effective domain of the sine function (256 steps = 2 * PI
  227. ; radians).  Sure would be nice to have an assembler with floating point!
  228.  
  229. frq697  equ     2284    ; @int(65536.0*50e-6*697.0)
  230. frq770  equ     2523    ; @int(65536.0*50e-6*770.0)
  231. frq852  equ     2792    ; @int(65536.0*50e-6*852.0)
  232. frq941  equ     3084    ; @int(65536.0*50e-6*941.0)
  233. frq1209 equ     3962    ; @int(65536.0*50e-6*1209.0)
  234. frq1336 equ     4378    ; @int(65536.0*50e-6*1336.0)
  235. frq1477 equ     4840    ; @int(65536.0*50e-6*1477.0)
  236. frq1633 equ     5351    ; @int(65536.0*50e-6*1633.0)
  237.  
  238.  
  239. ; Tables to set the row and column frequencies for a key.
  240. ; The values in these tables are increment sizes for stepping through the
  241. ; sine table.
  242.  
  243. rowtabl: addwf   pc
  244.      retw    frq697&0ffh,frq770&0ffh,frq852&0ffh,frq941&0ffh
  245.  
  246. rowtabh: addwf   pc
  247.      retw    frq697>>8,frq770>>8,frq852>>8,frq941>>8
  248.  
  249. coltabl: addwf   pc
  250.      retw    frq1209&0ffh,frq1336&0ffh,frq1477&0ffh,frq1633&0ffh
  251.  
  252. coltabh: addwf   pc
  253.      retw    frq1209>>8,frq1336>>8,frq1477>>8,frq1633>>8
  254.  
  255.  
  256. ; Output a pulse of 0 to 15 cycles.
  257. ; Enter with the pulse width (in cycles) in W and with the PWM pin
  258. ; set to the high state.
  259. ;
  260. ; 28 cycles (including call)
  261. ;
  262. ; W=0 ends pulse on 22th cycle after beginning of call
  263. ; W=15 ends pulse on 7th cycle after beginning of call
  264.  
  265. pulse:
  266.     movf    oldsamp,w       ; 1
  267.     andlw   00fh            ; 1
  268.     addwf   pc              ; 2 calculate first half of delay
  269.     nop                     ;   delay...
  270.     nop
  271.     nop
  272.     nop
  273.     nop
  274.     nop
  275.     nop
  276.     nop
  277.     nop
  278.     nop
  279.     nop
  280.     nop
  281.     nop
  282.     nop
  283.     nop
  284.     bcf     porta,pwm2      ; 1 set PWM output to negative side
  285.     bcf     porta,pwm3      ; 1
  286.     xorlw   0fh             ; 1 compute remaining delay
  287.     addwf   pc              ; 2 calculate second half of delay
  288.     nop                     ;   delay...
  289.     nop
  290.     nop
  291.     nop
  292.     nop
  293.     nop
  294.     nop
  295.     nop
  296.     nop
  297.     nop
  298.     nop
  299.     nop
  300.     nop
  301.     nop
  302.     nop
  303.     retlw   nothing         ; 2
  304.  
  305.  
  306. ; This is a sine wave for 360 degrees per 256 table entries, scaled by
  307. ; 127, such that 1.0 = $7F hex.
  308. ;
  309. ; Only 65 locations (0 to 90 degrees in steps of 2pi/256) are used in order
  310. ; to save space, as a full sine table would take up all of zero page.
  311. ;
  312. ; The values are signed fractions, i.e., s.fffffff
  313. ; All values in the table are positive since it is for the first
  314. ; quadrant.
  315.  
  316. ; 6 cycles (including call)
  317.  
  318. ;sinetbl:        addwf   pc
  319. ;       retw    000h,003h,006h,009h,00ch,010h,013h,016h
  320. ;       retw    019h,01ch,01fh,022h,025h,028h,02bh,02eh
  321. ;       retw    031h,033h,036h,039h,03ch,03fh,041h,044h
  322. ;       retw    047h,049h,04ch,04eh,051h,053h,055h,058h
  323. ;       retw    05ah,05ch,05eh,060h,062h,064h,066h,068h
  324. ;       retw    06ah,06bh,06dh,06fh,070h,071h,073h,074h
  325. ;       retw    075h,076h,078h,079h,07ah,07ah,07bh,07ch
  326. ;       retw    07dh,07dh,07eh,07eh,07eh,07fh,07fh,07fh
  327. ;       retw    07fh
  328.  
  329. sinetbl: addwf   pc
  330.     retw    40,41,42,43,44,45,46,47
  331.     retw    48,49,49,50,51,52,53,54
  332.     retw    55,56,57,58,58,59,60,61
  333.     retw    62,62,63,64,65,65,66,67
  334.     retw    68,68,69,70,70,71,71,72
  335.     retw    72,73,73,74,74,75,75,76
  336.     retw    76,76,77,77,77,78,78,78
  337.     retw    78,78,79,79,79,79,79,79
  338.     retw    79
  339.  
  340.        if      0
  341. ; This is how we would do it if we had floating point and repeat:
  342. pi     equ     3.141592653
  343. sinetbl: addwf   pc
  344. angle  set     0
  345.        rept    65
  346.        retlw   _fix(127.0*_sin(_float(angle)*pi/128.0)+0.5)
  347. angle  set     angle+1
  348.        endm
  349.        endif
  350.  
  351.  
  352. ; GETDIG is the actual phone number we want to dial.
  353. ;
  354. ; If I'd get macros working we could have a nice macro to define a
  355. ; phone number.
  356. ;
  357. ; mapping:  0 1 2 3 4 5 6 7 8 9 * #
  358. ;           d 0 1 2 4 5 6 8 9 a c e
  359. ;
  360. ; f indicates the end of the number
  361. ;
  362. ; Currently the code assumes that phone numbers are four bytes each, which
  363. ; is long enough for seven digit local numbers.
  364.  
  365. getdig: addwf   pc
  366.     retw    04ah,0a8h,000h,00fh     ; 499-7111 (WWV)
  367.     retw    055h,050h,010h,01fh     ; 555-1212 (information)
  368.     retw    012h,045h,068h,09fh     ; 234-5678 (test)
  369.     retw    012h,045h,068h,09fh     ; 234-5678 (test)
  370.     retw    012h,045h,068h,09fh     ; 234-5678 (test)
  371.     retw    012h,045h,068h,09fh     ; 234-5678 (test)
  372. ;maxdig equ     2*((.-getdig)-1)
  373. maxdig  equ     7
  374.  
  375.  
  376. ; CALCCOL is the longest subroutine that doesn't have to entirely reside in
  377. ; page zero, so we position it to begin at 0ffh in order to free as much of
  378. ; page zero as possible.
  379.  
  380. freep0  set     freep0+(0ffh-.)
  381.     ds      0ffh-.
  382.     org     0ffh
  383.  
  384. ; CALCCOL computes the column tone sample, and adds in the previously
  385. ; computed row tone sample.
  386.  
  387. ; 18 cycles (including call)
  388.  
  389. calccol:
  390.     movf    colm+1,w        ; 1
  391.     btfsc   colm+1,6        ; 1 is it the 2nd half of a half cycle?
  392.     subwf   zero,w          ; 1 then complement to effect a subtract from 64
  393.     andlw   07fh            ; 1 reduce to 6 bits for 90 degrees     
  394.     call    sinetbl         ; 6  and get amplitude
  395.  
  396.     btfsc   colm+1,7        ; 1 is amplitude supposed to be negative?
  397.     subwf   c4f,w           ; 1 change polarity of sine amplitude
  398.     
  399.     addwf   newsamp         ; 1
  400.     rrf     newsamp         ; 1
  401.     retlw   nothing         ; 2
  402.  
  403. ; INCCOL updates the sine wave phase for the column tone, and tests
  404. ; for completion of the tone.
  405. ;
  406. ; There is a great ugliness in the way this subroutine deals with
  407. ; the tone completion.  INCCOL is called from the main line code
  408. ; in one of five places (LOOP0, LOOP1, LOOP2, LOOP3, or LOOP4).  Since we
  409. ; know we are called by main, if the tone is over we just jump to
  410. ; NXTDIG, disregarding the return address on the stack (and leaving
  411. ; it there).  This saves some cycles in the main line tone loop, to
  412. ; maximize the available range of PWM duty cycles.  Kudos to Howard!
  413.  
  414. ; 15 cycles (including call to extender)
  415.  
  416. inccolx:
  417.     movf    colmfrq,w       ; 1 add low byte of colmfrq to low byte of colm
  418.     addwf   colm            ; 1
  419.     movf    colmfrq+1,w     ; 1 add high byte of colmfrq to high byte of colm
  420.     btfsc   status,cf       ; 1
  421.     addwf   one,w           ; 1 alternate: incf colm+1
  422.     addwf   colm+1          ; 1
  423.     
  424.     incf    iter            ; 1 increment iteration count
  425.     btfsc   status,zf       ; 1
  426.     incfsz  iter+1          ; 1
  427.     retlw   nothing         ; 2
  428.     bcf     porta,pwm2      ;   turn off pwm outputs
  429.     bsf     porta,pwm3
  430.     goto    nxtdig          ;
  431.  
  432. ; INCROW is responsible for updating the sine wave phase for
  433. ; the row tone, and calculating the sample.
  434.  
  435. ; 25 cycles (including call to extender)
  436. ; We could add up to five additional cycles to INCROW and adjust the delays
  437. ; in LOOP[0-4].  This could be used to look for key press/release, etc.
  438.  
  439. incrowx:
  440.     movf    rowfrq,w        ; 1 add low byte of rowfrq to low byte of row
  441.     addwf   row             ; 1
  442.     movf    rowfrq+1,w      ; 1 add high byte of rowfrq to high byte of row
  443.     btfsc   status,cf       ; 1
  444.     addwf   one,w           ; 1 alternate: incf row+1
  445.     addwf   row+1           ; 1
  446.  
  447.     movf    row+1,w         ; 1
  448.     btfsc   row+1,6         ; 1 is it the 2nd half of a half cycle?
  449.     subwf   zero,w          ; 1 then complement to effect a subtract from 64
  450.     andlw   07fh            ; 1 reduce to 6 bits for 90 degrees     
  451.     call    sinetbl         ; 6  and get amplitude
  452.  
  453.     btfsc   row+1,7         ; 1 is amplitude supposed to be negative?
  454.     subwf   c4f,w           ; 1 change polarity of sine amplitude
  455.  
  456.     movwf   newsamp         ; 1
  457.     retlw   nothing         ; 2
  458.  
  459.  
  460. ;======================== PROGRAM ENTRY POINT =========================
  461.  
  462. ; Initialize the hardware
  463.  
  464. reset:
  465. ;       clrwdt                  ; reset watchdog timer
  466. ;       movlw   3fh             ; external edge to timer
  467. ;       option                  ; high to low edge for timer
  468.                 ; prescaler assigned to watchdog
  469.                 ; prescaler divide by 128 for now
  470.  
  471.     movlw   1               ; initialize the value of one to allow W to be
  472.     movwf   one             ; incremented by using "addwf one,w"
  473.     movlw   0               ; initialize the value of zero so we can
  474.     movwf   zero            ; calculate the two's complement of W using
  475.                 ; "subwf zero,w"
  476.     movlw   04fh
  477.     movwf   c4f
  478.  
  479.     bcf     porta,pwm2      ; turn off PWM output
  480.     bsf     porta,pwm3
  481.     bsf     porta,led       ; turn off LED
  482.  
  483.     movlw   0f0h            ;porta:
  484.     tris    porta           ;  bit 0 = output (unused)
  485.                 ;  bit 1 = output (LED)
  486.                 ;  bit 2 = output (PWM speaker)
  487.                 ;  bit 3 = output (sync pulse for debug***)
  488.                 ;  bits 4-7 = inputs (no pins on 16C54)
  489.  
  490.  
  491.     movlw   0ffh            ;drive port b output pins high
  492.     movwf   portb
  493.  
  494.     movlw   30h             ; portb:
  495.     tris    portb           ;  bit 0 = output (column 0) not used
  496.                 ;  bit 1 = output (column 1)
  497.                 ;  bit 2 = output (column 2)
  498.                 ;  bit 3 = output (column 3)
  499.                 ;  bit 4 = input  (row 0)
  500.                 ;  bit 5 = input  (row 1)
  501.                 ;  bit 6 = output (row 2) not used
  502.                 ;  bit 7 = output (row 3) not used
  503.  
  504.  
  505. ;======================== MAIN LOOP =========================
  506.  
  507. main:
  508.     movlw   0
  509.     call    flash
  510.  
  511.     if    0        ; should be ifdef    test
  512.  
  513.     clrf    colmfrq
  514.     clrf    colmfrq+1
  515.  
  516.     movlw    07h
  517. nxtdig:    incf    digit
  518.     movf    digit,w
  519.     andlw    07h
  520.     movwf    digit
  521.     btfsc    digit,2
  522.     goto    nxtd1
  523.     
  524.     call    rowtabl
  525.     movwf   rowfrq
  526.     movf    digit,w
  527.     call    rowtabh
  528.     movwf   rowfrq+1
  529.     goto    nxtd2
  530.  
  531. nxtd1:    andlw    03h
  532.     call    coltabl
  533.     movwf    rowfrq
  534.     movf    digit,w
  535.     andlw    03h
  536.     call    coltabh
  537.     movwf    rowfrq+1
  538.  
  539. dur1:   equ     65000    ; duration 3.25 S
  540. nxtd2:
  541.         movlw   (-dur1)&0ffh
  542.     movwf   iter
  543.         movlw   ((-dur1)>>8)&0ffh
  544.     movwf   iter+1
  545.  
  546.     goto    loop
  547.  
  548.     else
  549.  
  550. keyscan:
  551.     movlw   010h
  552.     movwf   krow
  553. ks1     movlw   002h
  554.     movwf   kcol
  555.  
  556. ks2     movf    kcol,w
  557.     xorlw    0ffh
  558.     movwf   portb
  559.     movf    krow,w
  560.     andwf   portb
  561.     btfsc   status,zf
  562.     goto    ks9
  563.  
  564.     bcf     status,cf
  565.     rlf     kcol,f
  566.     btfss   kcol,4
  567.     goto    ks2
  568.     
  569.     bcf     status,cf
  570.     rlf     krow,f
  571.     btfss   krow,6
  572.     goto    ks1
  573.  
  574.     goto    keyscan
  575.  
  576. ; at this point, row is 10h or 20h, and column is 2, 4, or 8
  577.  
  578. ks9:    movlw   10h
  579.     xorwf   krow,f          ; row is now 00h or 30h
  580.     rlf     kcol,f          ; col is now 04h, 08h, or 10h
  581.     rlf     kcol,f          ;    08h, 10h, or 20h
  582.     movlw   30h
  583.     andwf   kcol,w          ; col (in w) is 00h, 10h, or 20h
  584.     addwf   krow,w          ; now 00h, 10h, 20h, 30h, 40h, or 50h
  585.     movwf   digidx
  586.     decf    digidx,f
  587.  
  588. nxtdig:
  589.     clrf    rowfrq        ; assume we're going to generate a delay
  590.     clrf    rowfrq+1
  591.     clrf    colmfrq
  592.     clrf    colmfrq+1
  593.  
  594. ;    clrf    colm        ; set initial row and column phase
  595. ;    clrf    row
  596. ;    clrf    colm+1
  597. ;    clrf    row+1    
  598.  
  599.     incf    digidx
  600. ;    goto    nxtd1
  601. ;    goto    main
  602.  
  603. nxtd1:
  604.     bcf     status,cf
  605.     rrf     digidx,w        ; shift it right.  if it's odd, pause
  606.     btfsc   status,cf
  607.     goto    nxtd3
  608.  
  609.     movwf   temp
  610.     bcf     status,cf
  611.     rrf     temp,w
  612.  
  613.     call    getdig          ; get a pair of digits
  614.     movwf   digit
  615.  
  616.     btfss   digidx,1        ; get the particular digit
  617.     swapf   digit
  618.  
  619.     movf    digit,w         ; if it's an f, we're done
  620.     andlw   0fh
  621.     xorlw   0fh
  622.     btfsc   status,zf
  623.     goto    main
  624.  
  625. ;       movf    digit,w
  626. ;       andlw   00fh
  627. ;       call    flash
  628.  
  629.     movf    digit,w
  630.     andlw   3               ; get the column frequency
  631.     call    coltabl
  632.     movwf   colmfrq
  633.     movf    digit,w
  634.     andlw   3
  635.     call    coltabh
  636.     movwf   colmfrq+1
  637.  
  638.     rrf     digit           ; now shift digit right two bits
  639.     rrf     digit,w
  640.     andlw   3
  641.     movwf   digit
  642.  
  643.     call    rowtabl
  644.     movwf   rowfrq
  645.     movf    digit,w
  646.     call    rowtabh
  647.     movwf   rowfrq+1
  648.  
  649. dur1:   equ     3000    ; duration 150 mS
  650. nxtd2:
  651.         movlw   (-dur1)&0ffh
  652.     movwf   iter
  653.         movlw   ((-dur1)>>8)&0ffh
  654.     movwf   iter+1
  655.  
  656.     goto    loop
  657.  
  658. dur2:   equ     6000    ; duration 300 mS
  659. nxtd3:
  660.     movlw   (-dur2)&0ffh
  661.     movwf   iter
  662.     movlw   ((-dur2)>>8)&0ffh
  663.     movwf   iter+1
  664.  
  665.     goto    loop
  666.  
  667.     endif
  668.  
  669. flashx: andlw   0fh
  670.     addwf   one,w
  671.     movwf   temp
  672. flash1: bcf     porta,led
  673.     call    pause
  674.     bsf     porta,led
  675.     call    pause
  676.     decfsz  temp
  677.     goto    flash1
  678.  
  679.     movlw   8
  680.     movwf   temp
  681. flash2: call    pause
  682.     decfsz  temp
  683.     goto    flash2
  684.  
  685. pausex: movlw   0ffh
  686.     movwf   temp+1
  687.     movwf   temp+2
  688. pause1: decfsz  temp+1
  689.     goto    pause1
  690.     decfsz  temp+2
  691.     goto    pause1
  692.     retlw   nothing
  693.  
  694.  
  695. ;===================== HARDWARE VECTORS =====================
  696.  
  697. freep1  set     freep1+(01ffh-.)
  698.     org     01ffh           ; reset vector of PIC16C54
  699.     goto    reset           ; start of program
  700.  
  701.     end
  702.