"High" Voltage PWM Prototyping tool

By Jinx


NEW! 416028

This High Voltage PWM Prototyping tool generates a  6-bit PWM on 1 channel with a Duty Cycle of 0/64th to 64/64th, settable with pot at a Frequency of 100Hz to 279Hz, settable with pot and any Voltage from 1.25V - 32V, settable with pot.

A standard 2x16 LCD display shows the current Duty Cycle, Frequency and Voltage.

Although developed for a specific application (excitation of a particular sensor), the principle can be used to generate general low-frequency PWM for motor control and other high power applications. Could also be used as a LED dimmer. Even a mains dimmer if synched to the 60Hz/50Hz mains (eg run at 120 or 100Hz), with the IRQ count as the turn-on timer. See http://home.clear.net.nz/pages/joecolquitt/txless.html for a simple synch circuit.

Pot readings and LCD display are updated during TMR0 count and are transparent to the timing. 1 * IRQ may be long enough to separate LCD writes (40us), 2 * IRQ are allowed here (112us)

Several functions are currently de-activated, hence the unused "Burst Length", "Ext Trigger" and 4017 "interval/burst" display. When activated, and included into the pr_irq section, they will not affect timing at all because of above transparency. Again, this project is being published to share the commonly useful parts of a device that was developed for a specific application.

As only half the cycle of 64 TMR0 IRQs are used, it would be easy to add pots for more independently settable PWM outputs. Include in the pr_irq section. Also, the bin2bcd & ascii16 calls are short enough that the s/w could be re-arranged to make better use of IRQ time.

; HV_PWM_proto.asm
;
; 22nd October 2007, rev 07/08
;
;joecolquitt@clear.net.nz
;www.piclist.com

   list P = 18F2520
   include "P18F2520.inc"

;RAM_START        EQU  H'0000'
;START_VECTOR     EQU  H'00000'
;PROG_START       EQU  H'00020'
;LOW_IRQ_VECTOR   EQU  H'00018'
;
;add to P18F2520.inc or add to program

 errorlevel -305, -302, -306 ;MPLAB error suppression

;Program purpose -
;
;6-bit PWM, 1 channel
;Duty Cycle, 0/64th to 64/64th, settable with pot
;Frequency, 100Hz to 279Hz, settable with pot
;Voltage, 1.25V - 32V, settable with pot
;LCD display
;Output - logic level on LATC,7
;
;Although developed for a specific application, the principle
;can be used to generate general low-frequency PWM. Lower than
;that achievable by using the PIC's PWM hardware
;
;Pot readings and LCD display are updated during TMR0 count
;and are transparent to the timing. 1 * IRQ may be long enough
;to separate LCD writes (40us), 2 * IRQ are allowed here (112us)
;
;Several functions are currently de-activated. When activated,
;and included into the pr_irq section, they will not affect
;timing at all because of above transparency

;As only half the cycle of 64 TMR0 IRQs are used, it would be
;easy to add pots for more independently settable PWM outputs
;Include in the pr_irq section
;
;bin2bcd & ascii16 calls are short enough that the s/w could be
;re-arranged to make better use of IRQ time
;
;=================================================

         CONFIG OSC=HSPLL          ;10MHz * 4, IC = 100ns
         CONFIG BOREN=OFF, PWRT=ON
         CONFIG WDT=OFF
         CONFIG CCP2MX=PORTC
         CONFIG PBADEN = OFF
         CONFIG STVREN=ON, LVP=OFF, DEBUG=OFF
         CONFIG CP0=OFF, CP1=OFF, CP2=OFF, CP3=OFF
         CONFIG CPB=OFF, CPD=OFF
         CONFIG WRT0=OFF, WRT1=OFF, WRT2=OFF, WRT3=OFF
         CONFIG WRTC=OFF, WRTB=OFF,WRTD=OFF
         CONFIG EBTR0=OFF, EBTR1=OFF, EBTR2=OFF, EBTR3=OFF
         CONFIG EBTRB=OFF
         CONFIG MCLRE=ON

;=================

clrc     macro
         bcf     status,0
         endm

skpc     macro
         btfss   status,0
         endm

skpnc    macro
         btfsc   status,0
         endm

skpnz    macro
         btfsc   status,2
         endm

wr_space macro                ;write space to LCD
         movlw   0x20
         call    write_d      ;display data
         endm

clrscrn  macro                ;clear LCD
         movlw   0x01
         call    write_c      ;command data
         call    ms01         ;processing delay
         call    ms01
         endm

mov      macro   litval,file
         movlw   litval
         movwf   file
         endm

movfw    macro   litval
         movf    litval,w
         endm

lcd_pos  macro   litval       ;set print position
         movlw   litval-1
         call    address
         endm

disp     macro   litval       ;display character
         movlw   litval
         call    write_d
         endm

dispw    macro                ;display WREG contents
         call    write_d
         endm

display  macro   var          ;load TBLPTR with string address
         movlw   upper(var)
         movwf   tblptru
         movlw   high(var)
         movwf   tblptrh
         movlw   low(var)
         movwf   tblptrl
         tblrd*+
         call    get_txt
         endm

usec     macro                ;1us delay
         movff   temp0,temp0
         movff   temp0,temp0
         movff   temp0,temp0
         movff   temp0,temp0
         movff   temp0,temp0
         endm

;=================

;A2D channel selection + set go/done

anch0    macro
         movlw   b'00000001'
         movwf   adcon0
         endm

anch1    macro
         movlw   b'00000101'
         movwf   adcon0
         endm

anch2    macro
         movlw   b'00001001'
         movwf   adcon0
         endm

anch3    macro
         movlw   b'00001101'
         movwf   adcon0
         endm

anch4    macro
         movlw   b'00010001'
         movwf   adcon0
         endm

;=================

         cblock  ram_start

         dg1                  ;display
         dg2
         dg3
         dg4
         dg5
         d100
         d010
         d011
         kzero

         dl_cnt1              ;delay
         dl_cnt2

         lo                   ;scratch
         hi
         temp0
         temp1
         temp2
         w_temp
         s_temp
         b_temp
         flags
         char_lo
         char_hi

         adch_sel             ;ADC select
         irq_cnt              ;IRQ counter

         reload1_lo           ;timer reloads
         reload1_hi
         reload2_lo
         reload2_hi

         duty_on              ;duty cycle

         duty_lo              ;printable characters
         duty_hi
         freq_lo
         freq_hi
         burst_lo
         burst_hi
         ival_lo
         ival_hi
         rand_lo
         rand_hi

         div_in_hi            ;/5.7 division
         div_in_lo

         print_buffer:12      ;0 duty cycle print position
                              ;1-3 Duty Cycle %
                              ;4 frequency print position
                              ;5-7 Frequency
                              ;8 volt print position
                              ;9-11 Volts
         endc

;=================
;          1                      14
;LCD pins 0V V+ VO RS R/W En DB0-DB7

;PortB 0-7 - LCD data

#define  trig1    latc,0      ;trigger input 1 - de-activated
#define  trig2    latc,1      ;trigger input 2 - de-activated
#define  strobe   latc,2      ;strobe drive    - de-activated
#define  dr_4017  latc,3      ;4017 drive      - de-activated
#define  rs       latc,4      ;LCD
#define  rw       latc,5      ;LCD             - not strictly necessary
#define  en       latc,6      ;LCD
#define  pulse    latc,7      ;output

#define  dc      status,1

ln1       = 0x00              ;LCD line1 address
ln2       = 0x40              ;LCD line2 address
show_dc   = .2+ln1            ;duty cycle print position
show_hz   = .8+ln1            ;frequency print position
show_volt = .2+ln2            ;voltage display position
show_mode = .9+ln2            ;mode display position
ad_in_n   = -.5               ;number of ADC channels to read (-ve)
ad_in_p   = .5                ;number of ADC channels to read (+ve)
strings   = 0x800             ;display string storage address

;================================================

         org     start_vector
         goto    init

         org     low_irq_vector
         goto    isr

         org     prog_start

init     clrf    lata
         clrf    latb
         clrf    latc
         clrf    porta
         clrf    portb
         clrf    portc

         clrf    intcon
         clrf    intcon2
         clrf    intcon3
         call    clr_ram           ;clear all RAM

         mov     b'00111111',trisa
;                  --               OSC1/OSC2
;                    1              AN4 - volts
;                     1             random switch
;                      1            AN3 - duty
;                       1           AN2 - frequency
;                        1          AN1 - interval
;                         1         AN0 - burst

         mov     b'00000000',trisb ;LCD data

         mov     b'00000011',trisc
;                  0                LCD EN
;                   0               LCD RW
;                    0              LCD RS
;                     0             LED
;                      0            4017 drive
;                       0           strobe drive
;                        1          trigger2
;                         1         trigger1

         mov     b'00001010',adcon1
;                  --               n/a
;                    0              Vref- = Vss
;                     0             Vref+ = Vdd
;                      1010         AN0-AN4 as analogue i/p

         mov     b'10110110',adcon2
;                  1                right-justified
;                   -               n/a
;                    110            acquisition time select, 16 Tad
;                       110         clock select, Fosc/64 (40MHz max)

         mov     b'00000111',cmcon ;comparators off

         mov     b'00001000',t0con
;                  0                timer off
;                   0               16-bit
;                    0              internal clock
;                     0
;                      1            no pre-scaler
;                       000         pre-scaler division

         call    ms100             ;LCD power up delay

;----------------

         mov     ad_in_n,adch_sel   ;AD channel select index
         clrf    irq_cnt            ;IRQ counter
                                    ;update duty cycle every 64 IRQs

         mov     show_dc,print_buffer+.0 ;LCD print positions
         mov     show_hz,print_buffer+.4
         mov     show_volt,print_buffer+.8

         mov     0x00,reload1_lo   ;initial TMR0 re-load value
         mov     0xfd,reload1_hi

;----------------

         movff   reload1_hi,tmr0h
         movff   reload1_lo,tmr0l

         call    lcd_init
         call    ms100

;Title screen

         clrscrn
         display title1
         call    line2
         call    us100
         display title2
         call    one_sec

;Working screen

         clrscrn
         display working1
         call    line2
         call    us100
         display working2
         call    one_sec

         lfsr    fsr1,print_buffer ;initialise
         clrf    irq_cnt

         bcf     intcon,tmr0if
         bsf     intcon,tmr0ie     ;enable TMR0 IRQ
         bsf     intcon,gie
         bsf     t0con,tmr0on      ;TMR0 on
         bsf     adcon0,adon       ;ADC on

;================================================
;        Main loop
;================================================

main     nop
         bra     main

;================================================
;        Timer interrupt
;================================================

isr      bcf     intcon,tmr0if
         movwf   w_temp
         movff   status,s_temp
         movff   bsr,b_temp

         movff   reload1_hi,tmr0h  ;reload timer
         movff   reload1_lo,tmr0l

         incf    irq_cnt           ;update duty cycle if IRQ count = 64
         btfss   irq_cnt,6         ;if 64
         bra     tst_on            ;else update other channels

         clrf    irq_cnt           ;reset IRQ counter
         lfsr    fsr1,print_buffer ;reset display data pointer
         bra     duty              ;get duty pot reading

;test if this is an 'on' slice

tst_on   bcf     pulse             ;pin low default
         tstfsz  duty_on           ;keep off if not 'on' slice
         decf    duty_on           ;else decrement 'on' slices

         tstfsz  duty_on           ;skip if not 'on'
         bsf     pulse             ;o/p on

         btfsc   irq_cnt,0         ;no action at odd IRQs
         bra     isr_exit

         movlw   ad_in_p*2
         cpfslt  irq_cnt
         bra     pr_irq            ;if irq_cnt > pots*2, update LCD

inc_cnt  incfsz  adch_sel          ;increment ADC channel counter
         bra     test_ch
         mov     ad_in_n,adch_sel  ;reset if 0

;================================================
;        Read analogue inputs on rotation
;================================================

test_ch  movlw   ad_in_n+.0
         xorwf   adch_sel,w
         skpnz
         bra     volts             ;measure volts

         movlw   ad_in_n+.1
         xorwf   adch_sel,w
         bz      freq              ;check frequency pot

         movlw   ad_in_n+.2
         xorwf   adch_sel,w
         bz      brst              ;check burst length pot

         movlw   ad_in_n+.3
         xorwf   adch_sel,w
         skpnz
         goto    ival              ;check interval length pot

         movlw   ad_in_n+.4
         xorwf   adch_sel,w
         skpnz
         goto    random            ;check random interval pot

;update display
;
;eg if number of pots = 5
;
;IRQ10, set display position
;IRQ12,14,16 Duty Cycle characters. Could be just 00 - 64
;IRQ18, set display position
;IRQ20,22,24 Frequency characters
;IRQ26, set print position
;IRQ28,30,32 Voltage characters. 2 for whole volts < 100, more if DP added
;> 32, exit

pr_irq   movlw   (ad_in_p*2)+.0    ;= 10 if pots = 5
         xorwf   irq_cnt,w
         bnz     pirq12
         movfw   postinc1          ;set print position
         call    address
         bra     isr_exit

pirq12   movlw   (ad_in_p*2)+.2
         xorwf   irq_cnt,w
         bnz     pirq14
         movfw   postinc1          ;duty cycle characters
         dispw
         bra     isr_exit

pirq14   movlw   (ad_in_p*2)+.4
         xorwf   irq_cnt,w
         bnz     pirq16
         movfw   postinc1
         dispw
         bra     isr_exit

pirq16   movlw   (ad_in_p*2)+.6
         xorwf   irq_cnt,w
         bnz     pirq18
         movfw   postinc1
         dispw
         bra     isr_exit

pirq18   movlw   (ad_in_p*2)+.8
         xorwf   irq_cnt,w
         bnz     pirq20
         movfw   postinc1          ;IRQ#18, set print position
         call    address
         bra     isr_exit

pirq20   movlw   (ad_in_p*2)+.10
         xorwf   irq_cnt,w
         bnz     pirq22
         movfw   postinc1          ;frequency characters
         dispw
         bra     isr_exit

pirq22   movlw   (ad_in_p*2)+.12
         xorwf   irq_cnt,w
         bnz     pirq24
         movfw   postinc1
         dispw
         bra     isr_exit

pirq24   movlw   (ad_in_p*2)+.14
         xorwf   irq_cnt,w
         bnz     pirq26
         movfw   postinc1
         dispw
         bra     isr_exit

pirq26   movlw   (ad_in_p*2)+.16
         xorwf   irq_cnt,w
         bnz     pirq28
         movfw   postinc1          ;IRQ#26, set print position
         call    address
         bra     isr_exit

pirq28   movlw   (ad_in_p*2)+.18
         xorwf   irq_cnt,w
         bnz     pirq30
         movfw   postinc1          ;voltage characters
         dispw
         bra     isr_exit

pirq30   movlw   (ad_in_p*2)+.20
         xorwf   irq_cnt,w
         bnz     pirq32
         movfw   postinc1
         dispw
         bra     isr_exit

pirq32   movlw  (ad_in_p*2)+.22
         xorwf   irq_cnt,w
         bnz     isr_exit
         movfw   postinc1
         dispw
         bra     isr_exit

;==================
;Pot varies TMR0 IRQ from 56us to 156us
;
;156us * 64 = 9984 = 1000000/9984 = 100Hz
; 56us * 64 = 3584 = 1000000/3584 = 279Hz

;Set frequency

freq     anch2                     ;frequency pot
         bsf     adcon0,go_done
         btfsc   adcon0,go_done
         bra     $-2

         clrc
         movff   adresl,reload1_lo ;ADC result low -> timer low
         movlw   0xfa              ;TMR0H offset (ie minimum value)
         addwf   adresh,w          ;add
         movwf   reload1_hi        ;ADC result high -> timer high

;divide pot reading by 5.7, add 100, convert to ASCII
;conversion time 23us

         movff   adresl,div_in_lo
         movff   adresh,div_in_hi
         call    div5pt7
         movff   div_in_lo,lo
         movff   div_in_hi,hi
         call    ascii16             ;convert to 5-digit ASCII
         movff   dg3,print_buffer+.5 ;use 3 LSD (ignore leading '00')
         movff   dg4,print_buffer+.6
         movff   dg5,print_buffer+.7
         bra     isr_exit

;==================

brst     bra     isr_exit          ;burst length, de-activated
         anch0
         btfsc   adcon0,go_done
         bra     $-2
         movff   adresh,burst_lo
         movff   adresl,burst_hi
         bra     isr_exit

;==================

ival     bra     isr_exit          ;burst interval, de-activated
         anch1
         btfsc   adcon0,go_done
         bra     $-2
         movff   adresh,ival_lo
         movff   adresl,ival_hi
         bra     isr_exit

;==================

random   bra     isr_exit          ;random burst timing, de-activated
         anch4
         btfsc   adcon0,go_done
         bra     $-2
         movff   adresh,rand_lo
         movff   adresl,rand_hi
         bra     isr_exit

;==================

;Set on:off duty cycle

duty     anch3                     ;duty cycle pot
         bsf     adcon0,go_done
         btfsc   adcon0,go_done
         bra     $-2

;ADC/16 (= X 64ths on), result in duty_on
;execution time 6us

         movff   adresl,duty_on
         movff   adresh,temp2
         swapf   duty_on,w         ;low nybble temp2 + high nybble duty_on
         andlw   0x0f
         movwf   duty_on
         swapf   temp2,w
         iorwf   duty_on           ;number of slices on out of 64

         movff   duty_on,temp1     ;approximate * 1.5 -> percent display
         clrc
         rrcf    temp1,w
         addwf   duty_on,w
         call    bin2bcd              ;convert to 3-digit ASCII
         mov     "0",print_buffer+.1  ;digit1 always '0'
         movff   d010,print_buffer+.2 ;use 2 LSD (ignore leading '000')
         movff   d011,print_buffer+.3
         bra     isr_exit

;ADC result is the measured voltage, ascii16 routine converts
;it to ASCII
;Manipulate ADC result and ASCII string (eg insert decimal point)
;to get desired display output

;Maths here depends on resistor divider on high voltage and
;high voltage upper limit
;eg
;high voltage = 30.72V (30720mV)
;resistor divider = 5k:1k -> 5V max at PIC ADC
;ADC reading = 0x0200 (half-way to 0x03FF)
;* 3 = 0x0600
;Convert to ASCII = 01536 (dg1....dg5)
;Take dg2 and dg3 = 15
;Similarly 0x0100 -> 00768 (round up to 8 or insert DP)

volts    anch4
         bsf     adcon0,go_done
         btfsc   adcon0,go_done
         bra     $-2
         movff   adresl,lo
         movff   adresh,hi
         clrc
         rlcf    lo
         rlcf    hi
         movfw   adresl
         addwf   lo
         movfw   adresh
         addwfc  hi
         call    ascii16              ;convert to 5-digit ASCII
         mov     "0",print_buffer+.9  ;digit1 always '0'
         movff   dg2,print_buffer+.10 ;use only 2 digits for whole volts
         movff   dg3,print_buffer+.11

isr_exit movff   b_temp,bsr
         movfw   w_temp
         movff   s_temp,status
         retfie

;================================================
;        LCD commands (8-bit)
;================================================

line1    movlw  0x00          ;line 1, column 0
         call   address
         return

line2    movlw  0x40          ;line 2, column 0
         call   address
         return

address  addlw  0x80          ;set high bit of address command
         call   write_c
         return

write_c  bcf    rs            ;write command
         bra    d_out

write_d  bsf    rs            ;write data
         usec
d_out    movwf  latb          ;write to port, no Busy test
         usec                 ;separate writes with 2 * IRQs 
         bcf    rw            ;typical write completion time is 40us
         usec
         bsf    en
         usec
         bcf    en
         usec
         return

;================================================
;        Initialise LCD screen (8-bit)
;================================================

lcd_init bcf    rs            ;command
         usec
         call   write30
         call   ms01          ;delay > 4.1ms
         call   ms01
         call   ms01
         call   ms01
         call   ms01

         call   write30
         call   ms01          ;delay > 100us

         call   write30
         call   ms01          ;delay > 100us

         movlw  0x38
         call   wr_c_del      ;include 100us delay
         movlw  0x0c
         call   wr_c_del
         movlw  0x01
         call   wr_c_del
         movlw  0x06
         call   wr_c_del

         return

write30  movwf  latb
         usec
         bsf    en
         usec
         bcf    en
         usec
         return

wr_c_del call   write_c
         call   us100
         return

;================================================
;        Convert 8-bit data to ASCII for LCD
;================================================

;execution time 4us

;data in W

bin2bcd  movwf   temp1
         clrf    d100
         swapf   temp1,w
         addwf   temp1,w
         andlw   b'00001111'
         btfsc   dc
         addlw   0x16
         btfsc   dc
         addlw   0x06
         addlw   0x06
         btfss   dc
         addlw  -0x06

         btfsc   temp1,4
         addlw   0x16 - 1 + 0x06
         btfss   dc
         addlw  -0x06

         btfsc   temp1,5
         addlw   0x30

         btfsc   temp1,6
         addlw   0x60

         btfsc   temp1,7
         addlw   0x20

         addlw   0x60
         rlcf    d100
         btfss   d100,0
         addlw  -0x60

         movwf   d011
         btfsc   temp1,7
         incf    d100

         swapf   d011,w
         andlw   0x0f
         movwf   d010

         movlw   0x0f
         andwf   d011,w
         movwf   d011

         movlw   0x30         ;convert to ASCII
         addwf   d100
         addwf   d010
         addwf   d011
         return

;================================================
;        Convert 16-bit data to ASCII for LCD
;================================================

;execution time 18us

;data in hi:lo

ascii16 nop

 radix   dec                  ;base 10

         clrf    kzero
         clrf    temp0
         lfsr    fsr0,dg1

         bra     $+4
sub10k   incf    temp0
         movlw   10000 & 255
         subwf   lo

 IFNDEF  known_zero

         movlw   10000 >> 8
         skpc
         movlw   (10000>>8)+1
         subwf   hi
 ELSE
         rlcf    kzero,w
         sublw   (10000>>8)+1
         subwf   hi
 ENDIF
         bc      sub10k
         call    out_temp

         mov     10,temp0
add1K    decf    temp0
         movlw   1000 & 255
         addwf   lo

 IFNDEF  kzero
         movlw   1000 >> 8
         skpnc
         movlw   (1000>>8)+1
         addwf   hi
 ELSE
         rlcf    kzero,w
         addlw   1000 >> 8
         addwf   hi
 ENDIF
         bnc     add1k
         call    out_temp

         clrf    temp0
         movlw   100
         bra     $+4
sub100
         incf    temp0
         subwf   lo
         skpnc
         bra     sub100

         decf    hi
         btfss   hi,7
         bra     sub100

         call    out_temp

         mov     10,temp0
add10    decf    temp0
         addwf   lo
         bnc     add10
         call    out_temp     ;convert and store
         call    out_lo       ;convert and store

 radix hex

         return

;convert to ASCII and store

out_temp movfw   temp0
         addlw   0x30         ;add 0x30 to convert to ASCII
         movwf   postinc0
         return

out_lo   movfw   lo
         addlw   0x30
         movwf   indf0
         return

;================================================
;        Divide frequency pot by 5.7, add 100
;        to get 100Hz to 279Hz display reading
;================================================

;execution time 4.7us

div5pt7  movff   div_in_hi,temp0
         movf    div_in_lo,w
         movwf   temp1

         clrc
         rrcf    div_in_hi
         rrcf    div_in_lo
         clrc
         rrcf    div_in_hi
         rrcf    div_in_lo

         addwf   div_in_lo
         movf    temp0,w
         skpnc
         incfsz  temp0,w
         addwf   div_in_hi

         rrcf    div_in_hi
         rrcf    div_in_lo

         movf    temp1,w
         addwf   div_in_lo
         movf    temp0,w
         skpnc
         incfsz  temp0,w
         addwf   div_in_hi

         rrcf    div_in_hi
         rrcf    div_in_lo
         clrc
         rrcf    div_in_hi
         rrcf    div_in_lo

         movf    temp1,w
         addwf   div_in_lo
         movf    temp0,w
         skpnc
         incfsz  temp0,w
         addwf   div_in_hi

         rrcf    div_in_hi
         rrcf    div_in_lo
         clrc
         rrcf    div_in_hi
         rrcf    div_in_lo
         clrc
         rrcf    div_in_hi
         rrcf    div_in_lo

         movlw   .100
         addwf   div_in_lo
         clrf    wreg
         addwfc  div_in_hi

         return

;================================================
;        Fetch string for LCD
;================================================

; LCD text strings

get_txt  movfw   tablat       ;get characters until
         btfsc   wreg,7       ;W > 0x7f (ie FF terminator)
         return
         dispw                ;print W
         call    us100        ;processing time
         tblrd*+
         bra     get_txt

;================================================
;        Clear all RAM
;================================================

clr_ram  lfsr    fsr0,0x000
         lfsr    fsr1,0x100
         lfsr    fsr2,0x200
 
clear1   clrf    postinc0
         clrf    postinc1
         clrf    postinc2
         btfss   fsr0h,0
         bra     clear1

         lfsr    fsr0,0x300
         lfsr    fsr1,0x400
         lfsr    fsr2,0x500

clear2   clrf    postinc0
         clrf    postinc1
         clrf    postinc2
         btfss   fsr0h,2
         bra     clear2
         return

;================================================
;        Delays @ 40MHz
;================================================

one_sec  movlw   -.10         ;1 second delay (approx)
         movwf   temp1
seclp    call    ms100
         incfsz  temp1
         bra     seclp
         return

ms100    movlw   -.100        ;100ms delay (approx)
         movwf   temp0
ms100lp  call    ms01
         incfsz  temp0
         bra     ms100lp
         return

ms01     movlw   -.10         ;1ms delay
         movwf   dl_cnt1
ms01lp   call    us100
         incfsz  dl_cnt1
         bra     ms01lp
         return

us100    movlw   -.90         ;100us delay
         movwf   dl_cnt2
us100lp  movff   temp0,temp0
         movff   temp0,temp0
         movff   temp0,temp0
         movff   temp0,temp0
         incfsz  dl_cnt2
         bra     us100lp
         nop
         return

us10     movlw   .15
         movwf   temp0
         decfsz  temp0
         bra     $-2
         return

;================================================
;        LCD redefiniton data
;================================================

;CHR$ 0 - 7 reserved for redefined characters

;================================================
;        LCD text strings
;================================================

 org strings

title1   db "* t1---------- *",0xff
title2   db "* t2---------- *",0xff
working1 db "* 000%  000 Hz *",0xff
working2 db "* 000V   Cont  *",0xff

  end