;****************************************************************************************
;SUBLIST.ASM                                                                            *
;Universal PIC micro subroutine/stucturing file                                         *
;Taylor Electronics Services common code base                                           *
;                                                                                       *
;REVISION HISTORY                                                                       *
;DATE       Affects     Description                                                     *
;---------------------------------------------------------------------------------------*
;2002/04/21 intadc drvr >fixed definition of adc registers in '876/'877 processors to   *
;                       include adcresl/adcresh.                                        *
;                       >added packing of lsb's into aal,aah for 10 bit conversions of  *
;                       multiple channels                                               *
;                       >added adcmask table to .adcint. block                          *
;                       >changed adcinit to inline code, same size as call was (save ~7)*
;                       >embedded channel select and clock select in same operation     *
;2001/12/25 p165x drvr  added p165x driver, single 74165 with split control lines       *
;2001/11/02 p1451 drvr  added ltc1451 driver                                            *
;2001/10/30 div16x8     added routine, note problem in win16x16 routine                 *
;2001/08/06 substart    if substart is 0, assemble code in contiguous block             *
;2001/05/15 cpuinit     turned off port b weak pull ups on init                         *
;2001/05/13 '876 proc   Stripped port d/e references for 876 and fixed cpuinit to accom *
;2000/12/13 isrpmode1   Added flag to vector isr into project resident handler          *
;           Various     Added/fixed some of the jumptext labels                         *
;2000/12/01 All         Initial release into the wild                                   *
;****************************************************************************************



;************************************************************
;highlight flag, [f3], [return], [esc]                      *
;************************************************************
;.macro.                                                    *
;.asmender.                                                 *
;************************************************************
;processor definitions                                      *
;.pic16c74.                                                 *
;.pic16f84.                                                 *
;.pic16f876.                                                *
;.pic16f877.                                                *
;************************************************************
;.memmode1.     16c74 large                                 *
;.memmode2.     16c74 small                                 *
;.memmode3.     16f877, 876 large                           *
;************************************************************
;.adc.                                                      *
;.adcinit.                                                  *
;.adcint.                                                   *
;.cpuinit.                                                  *
;.isr.                                                      *
;.isrpmode1.                                                *
;.isrmode1.                                                 *
;.meminit.                                                  *
;.pwmsetup.                                                 *
;.reset.                                                    *
;************************************************************
;.sciget.                                                   *
;.sciput.                                                   *
;.scisetup.                                                 *
;.sciutil.                                                  *
;.scmmd.                                                    *
;.scmmdlcmmd.                                               *
;************************************************************
;.m25.                                                      *
;.m25d.                                                     *
;.p0832.                                                    *
;.p1247.                                                    *
;.p1267.                                                    *
;.p1288.                                                    *
;.p1451.        12 bit spi vout dac                         *
;.p145170.                                                  *
;.p165.                                                     *
;.p165b.                                                    *
;.p165d.                                                    *
;.p165s.                                                    *
;.p165sb.                                                   *
;.p165x.                                                    *
;.p1801.                                                    *
;.p25600.                                                   *
;.p3100.                                                    *
;.p509.                                                     *
;.p534.                                                     *
;.p595.                                                     *
;.p5951.                                                    *
;.p595s.                                                    *
;.p6355.        njr real time clock                         *
;.spiutil.                                                  *
;************************************************************
;.i2cutil.                                                  *
;.lm75.                                                     *
;.p1721.                                                    *
;.p1803.                                                    *
;************************************************************
;.rtc72421.                                                 *
;************************************************************
;.lcdbar0.                                                  *
;.lcdbar1.                                                  *
;.lcdbar2.                                                  *
;.lcdbar3.                                                  *
;.lcddisp.                                                  *
;.mdisp.                                                    *
;.mxmit.                                                    *
;.mxmita.                                                   *
;************************************************************
;.beep.                                                     *
;.beepx.                                                    *
;.delayms.                                                  *
;.delayse.                                                  *
;.delayus.                                                  *
;.jsparse.                                                  *
;************************************************************
;.bin2dec.                                                  *
;.bin2decd.                                                 *
;.bin2hex.                                                  *
;.bin2hexd.                                                 *
;.bitmod.                                                   *
;.div16x16f.                                                *
;.div16x2.                                                  *
;.div16x2f.                                                 *
;.div16x8.                                                  *
;.div24x8.                                                  *
;.div32x8.                                                  *
;.div8x8.                                                   *
;.div8x8f.                                                  *
;.hex2bin.                                                  *
;.mpy16x16.                                                 *
;.mpy16x2.                                                  *
;.mpy16x8.                                                  *
;.mpy16x8f.                                                 *
;.mpy8x8f.                                                  *
;.sub16x16.                                                 *
;.sub16x16f.                                                *
;.sub16x16fs.                                               *
;.sub8x8f.                                                  *
;.sub8x8fs.                                                 *
;.win16x16.                                                 *
;.win8x8.                                                   *
;************************************************************














;************************************************************
            list n=0                ;no page breaks in list file
            list t=on               ;no wrap
;************************************************************
true        equ     0x01
false       equ     0x00
;************************************************************











;************************************************************
_initmode   set     0
_memmode    set     0
_isrpmode   set     0
_isrmode    set     0
_isrmain    set     0
_scimode    set     0
_scibmode   set     0
;************************************************************
;uart control logic                                         *
;************************************************************
_uartchksum set     false               ;do not compute checksums
_uarthandsh set     false               ;do not use hand shaking lines for com
_uartbctrl  set     false               ;bus control inactive
;************************************************************
;hardware access subroutine blocks                          *
;************************************************************
_adcint     set     false
_beep       set     false
_beepx      set     false
_jsparse    set     false
_lcdbar0    set     false
_lcdbar1    set     false
_lcdbar2    set     false
_lcdbar3    set     false
_lcddisp    set     false
_lm75       set     false
_m25        set     false
_m25d       set     false
_mdisp      set     false
_mpntr      set     false
_mxmit      set     false
_mxmita     set     false
_p0832      set     false
_p1247      set     false
_p1267      set     false
_p1288      set     false
_p1451      set     false
_p145170    set     false
_p165       set     false
_p165b      set     false
_p165d      set     false
_p165s      set     false
_p165sb     set     false
_p165x      set     false
_p1721      set     false
_p1801      set     false
_p1803      set     false
_p25600     set     false
_p3100      set     false
_p509       set     false
_p534       set     false
_p595       set     false
_p5951      set     false
_p595s      set     false
_p6355      set     false
_pwmsetup   set     false
_rtc72421   set     false
_spiutil    set     false
_i2cutil    set     false
;************************************************************
;math/conversion/delay subroutine blocks                    *
;************************************************************
_bin2dec    set     false
_bin2decd   set     false
_bin2hex    set     false
_bin2hexd   set     false
_bitmod     set     false
_delayms    set     false
_delayse    set     false
_delayus    set     false
_div8x8     set     false
_div8x8f    set     false
_div16x2    set     false
_div16x2f   set     false
_div16x16f  set     false
_div16x8    set     false
_div24x8    set     false
_div32x8    set     false
_hex2bin    set     false
_mpy8x8     set     false
_mpy8x8f    set     false
_mpy16x2    set     false
_mpy16x8    set     false
_mpy16x8f   set     false
_mpy16x16   set     false
_sub8x8f    set     false
_sub8x8fs   set     false
_sub16x16   set     false
_sub16x16f  set     false
_sub16x16s  set     false
_sub16x16fs set     false
_win8x8     set     false
_win16x16   set     false
;************************************************************
_scmmd      set     false
_scmmdcd    set     false
_remotemnu  set     false               ;undecoded remote menu, main block handles
;************************************************************








;************************************************************
 include seblock                        ;current sub enable block
;************************************************************









            errorlevel  0,-306
;************************************************************
;generic definitions                                        *
;************************************************************
;ascii equates
nul         equ     0                   ;null character
stx         equ     2                   ;start transmission
etx         equ     3                   ;end transmission
eot         equ     4                   ;end of transmission
enq         equ     5                   ;enquiry
ack         equ     6                   ;acknowledge
bel         equ     7                   ;bell
bs          equ     8                   ;back space
lf          equ     10                  ;line feed
ff          equ     12                  ;form feed
cr          equ     13                  ;carriage return
nak         equ     21                  ;not acknowledge
esc         equ     27                  ;escape
del         equ     127                 ;delete
;************************************************************
;logical operators/destination for rd-wr operations
w           equ     0
f           equ     1   
;************************************************************






;************************************************************
;.pic16c74.                                                 *
;************************************************************
 if (_proctype == 74)
;************************************************************
            list    p=16c74a
;************************************************************
_mpages     set     2
_rpages     set     2
lastramm0   set     0x020
lastramm1   set     0x0a0
lastramm2   set     0x800
lastramm3   set     0x800
lastrams0   set     0x07f
lastrams1   set     0x0ff
lastrams2   set     0x7ff
lastrams3   set     0x7ff
;************************************************************
indf        equ     0x00
tmr0        equ     0x01
pcl         equ     0x02
;************************************************************
status      equ     0x03
irp         equ     7
rp1         equ     6
rp0         equ     5
not_to      equ     4
not_pd      equ     3
z           equ     2
zero        equ     2
dc          equ     1
c           equ     0
;************************************************************
fsr         equ     0x04
porta       equ     0x05
portb       equ     0x06
portc       equ     0x07
portd       equ     0x08
porte       equ     0x09
pclath      equ     0x0a
;************************************************************
intcon      equ     0x0b
gie         equ     7
peie        equ     6
t0ie        equ     5
inte        equ     4
rbie        equ     3
t0if        equ     2
intf        equ     1
rbif        equ     0
;************************************************************
pir1        equ     0x0c
pspif       equ     7
adif        equ     6
rcif        equ     5
txif        equ     4
sspif       equ     3
ccp1if      equ     2
tmr2if      equ     1
tmr1if      equ     0
;************************************************************
pir2        equ     0x0d
ccp2if      equ     0
;************************************************************
tmr1l       equ     0x0e
tmr1h       equ     0x0f
;************************************************************
t1con       equ     0x10
t1ckps1     equ     5
t1ckps0     equ     4
t1oscen     equ     3
nt1sync     equ     2
t1insync    equ     2                   ; backward compatibility only
tmr1cs      equ     1
tmr1on      equ     0
;************************************************************
tmr2        equ     0x11
t2con       equ     0x12
toutps3     equ     6
toutps2     equ     5
toutps1     equ     4
toutps0     equ     3
tmr2on      equ     2
t2ckps1     equ     1
t2ckps0     equ     0
;************************************************************
sspbuf      equ     0x13
sspbuff     equ     0x13
;************************************************************
sspcon      equ     0x14
wcol        equ     7
sspov       equ     6
sspen       equ     5
ckp         equ     4
sspm3       equ     3
sspm2       equ     2
sspm1       equ     1
sspm0       equ     0
;************************************************************
ccpr1l      equ     0x15
ccpr1h      equ     0x16
;************************************************************
ccp1con     equ     0x17
ccp1x       equ     5
ccp1y       equ     4
ccp1m3      equ     3
ccp1m2      equ     2
ccp1m1      equ     1
ccp1m0      equ     0
;************************************************************
rcsta       equ     0x18
spen        equ     7
rx9         equ     6
rc9         equ     6                   ; backward compatibility only
not_rc8     equ     6                   ; backward compatibility only
rc8_9       equ     6                   ; backward compatibility only
sren        equ     5
cren        equ     4
ferr        equ     2
oerr        equ     1
rx9d        equ     0
rcd8        equ     0                   ; backward compatibility only
;************************************************************
txreg       equ     0x19
rcreg       equ     0x1a
ccpr2l      equ     0x1b
ccpr2h      equ     0x1c
;************************************************************
ccp2con     equ     0x1d
ccp2x       equ     5
ccp2y       equ     4
ccp2m3      equ     3
ccp2m2      equ     2
ccp2m1      equ     1
ccp2m0      equ     0
;************************************************************
adres       equ     0x1e
;************************************************************
adcon0      equ     0x1f
adcs1       equ     7
adcs0       equ     6
chs2        equ     5
chs1        equ     4
chs0        equ     3
go          equ     2
not_done    equ     2
go_done     equ     2
adon        equ     0
;************************************************************
option_reg  equ     0x81
not_rbpu    equ     7
intedg      equ     6
tocs        equ     5
tose        equ     4
psa         equ     3
ps2         equ     2
ps1         equ     1
ps0         equ     0
;************************************************************
trisa       equ     0x85
portadir    equ     0x85
trisb       equ     0x86
portbdir    equ     0x86
trisc       equ     0x87
portcdir    equ     0x87
trisd       equ     0x88
portddir    equ     0x88
;************************************************************
trise       equ     0x89
portedir    equ     0x89
ibf         equ     7
obf         equ     6
ibov        equ     5
pspmode     equ     4
;************************************************************
pie1        equ     0x8c
pspie       equ     7
adie        equ     6
rcie        equ     5
txie        equ     4
sspie       equ     3
ccp1ie      equ     2
tmr2ie      equ     1
tmr1ie      equ     0
;************************************************************
pie2        equ     0x8d 
ccp2ie      equ     0
;************************************************************
pcon        equ     0x8e
not_por     equ     1
not_bo      equ     0
not_bor     equ     0
;************************************************************
pr2         equ     0x92
sspadd      equ     0x93
;************************************************************
sspstat     equ     0x94
d           equ     5
i2c_data    equ     5
not_a       equ     5
not_address equ     5
d_a         equ     5
dat_address equ     5
p           equ     4
i2c_stop    equ     4
s           equ     3
i2c_start   equ     3
r           equ     2
i2c_read    equ     2
not_w       equ     2
not_write   equ     2
r_w         equ     2
read_write  equ     2
ua          equ     1
bf          equ     0
;************************************************************
txsta       equ     0x98
csrc        equ     7
tx9         equ     6
not_tx8     equ     6                   ; backward compatibility only
tx8_9       equ     6                   ; backward compatibility only
txen        equ     5
sync        equ     4
brgh        equ     2
trmt        equ     1
tx9d        equ     0
txd8        equ     0                   ; backward compatibility only
;************************************************************
spbrg       equ     0x99
;************************************************************
adcon1      equ     0x9f
pcfg2       equ     2
pcfg1       equ     1
pcfg0       equ     0
;************************************************************
;spi pin name definitions
#define     sck     rc3
#define     sdi     rc4
#define     sdo     rc5
;************************************************************
;port bit definitions
#define     ra0     porta,0
#define     ra1     porta,1
#define     ra2     porta,2
#define     ra3     porta,3
#define     ra4     porta,4
#define     ra5     porta,5
#define     rb0     portb,0
#define     rb1     portb,1
#define     rb2     portb,2
#define     rb3     portb,3
#define     rb4     portb,4
#define     rb5     portb,5
#define     rb6     portb,6
#define     rb7     portb,7
#define     rc0     portc,0
#define     rc1     portc,1
#define     rc2     portc,2
#define     rc3     portc,3
#define     rc4     portc,4
#define     rc5     portc,5
#define     rc6     portc,6
#define     rc7     portc,7
#define     rd0     portd,0
#define     rd1     portd,1
#define     rd2     portd,2
#define     rd3     portd,3
#define     rd4     portd,4
#define     rd5     portd,5
#define     rd6     portd,6
#define     rd7     portd,7
#define     re0     porte,0
#define     re1     porte,1
#define     re2     porte,2
;************************************************************
;alternate rd=psp, parallel slave port
#define     psp0    portd,0
#define     psp1    portd,1
#define     psp2    portd,2
#define     psp3    portd,3
#define     psp4    portd,4
#define     psp5    portd,5
#define     psp6    portd,6
#define     psp7    portd,7
#define     psp_rd  porte,0
#define     psp_wr  porte,1
#define     psp_cs  porte,2
;************************************************************
;port direction control bit definitions
;0=output
;1=input
#define     ra0dir  trisa,0
#define     ra1dir  trisa,1
#define     ra2dir  trisa,2
#define     ra3dir  trisa,3
#define     ra4dir  trisa,4
#define     ra5dir  trisa,5
#define     rb0dir  trisb,0
#define     rb1dir  trisb,1
#define     rb2dir  trisb,2
#define     rb3dir  trisb,3
#define     rb4dir  trisb,4
#define     rb5dir  trisb,5
#define     rb6dir  trisb,6
#define     rb7dir  trisb,7
#define     rc0dir  trisc,0
#define     rc1dir  trisc,1
#define     rc2dir  trisc,2
#define     rc3dir  trisc,3
#define     rc4dir  trisc,4
#define     rc5dir  trisc,5
#define     rc6dir  trisc,6
#define     rc7dir  trisc,7
#define     rd0dir  trisd,0
#define     rd1dir  trisd,1
#define     rd2dir  trisd,2
#define     rd3dir  trisd,3
#define     rd4dir  trisd,4
#define     rd5dir  trisd,5
#define     rd6dir  trisd,6
#define     rd7dir  trisd,7
#define     re0dir  trise,0
#define     re1dir  trise,1
#define     re2dir  trise,2
;************************************************************
;ram definition
            __maxram 0xff
            __badram 0x8f-0x91, 0x95-0x97, 0x9a-0x9e
;************************************************************
;configuration bits
_boden_on   equ     0x3fff
_boden_off  equ     0x3fbf
_cp_all     equ     0x00cf
_cp_75      equ     0x15df
_cp_50      equ     0x2aef
_cp_off     equ     0x3fff
_pwrte_off  equ     0x3fff
_pwrte_on   equ     0x3ff7
_wdt_on     equ     0x3fff
_wdt_off    equ     0x3ffb
_lp_osc     equ     0x3ffc
_xt_osc     equ     0x3ffd
_hs_osc     equ     0x3ffe
_rc_osc     equ     0x3fff
;************************************************************
 __config   _hs_osc & _wdt_off & _pwrte_off & _boden_off
;************************************************************
 endif
;************************************************************









;************************************************************
;.pic16f84.                                                 *
;************************************************************
 if (_proctype == 84)
;************************************************************
            list    p=16f84
;************************************************************
_mpages     set     1
_rpages     set     2
lastramm0   set     0x00c
lastramm1   set     0x800
lastramm2   set     0x800
lastramm3   set     0x800
lastrams0   set     0x04f
lastrams1   set     0x7ff
lastrams2   set     0x7ff
lastrams3   set     0x7ff
;************************************************************
;register files
indf        equ     0x00 
tmr0        equ     0x01 
pcl         equ     0x02 
;************************************************************
status      equ     0x03 
irp         equ     7 
rp1         equ     6 
rp0         equ     5 
not_to      equ     4 
not_pd      equ     3 
z           equ     2 
zero        equ     2
dc          equ     1 
c           equ     0 
;************************************************************
fsr         equ     0x04 
porta       equ     0x05 
portb       equ     0x06 
eedata      equ     0x08 
eeadr       equ     0x09 
pclath      equ     0x0a 
;************************************************************
intcon      equ     0x0b 
gie         equ     7 
eeie        equ     6 
t0ie        equ     5 
inte        equ     4 
rbie        equ     3 
t0if        equ     2 
intf        equ     1 
rbif        equ     0 
;************************************************************
option_reg  equ     0x81 
not_rbpu    equ     7 
intedg      equ     6 
t0cs        equ     5 
t0se        equ     4 
psa         equ     3 
ps2         equ     2 
ps1         equ     1 
ps0         equ     0 
;************************************************************
trisa       equ     0x85 
trisb       equ     0x86 
;************************************************************
eecon1      equ     0x88 
eeif        equ     4 
wrerr       equ     3 
wren        equ     2 
wr          equ     1 
rd          equ     0 
;************************************************************
eecon2      equ     0x89 
;************************************************************
;port bit definitions
#define     ra0     porta,0
#define     ra1     porta,1
#define     ra2     porta,2
#define     ra3     porta,3
#define     ra4     porta,4
#define     rb0     portb,0
#define     rb1     portb,1
#define     rb2     portb,2
#define     rb3     portb,3
#define     rb4     portb,4
#define     rb5     portb,5
#define     rb6     portb,6
#define     rb7     portb,7
;************************************************************
;port direction control bit definitions
;0=output
;1=input
#define     ra0dir  trisa,0
#define     ra1dir  trisa,1
#define     ra2dir  trisa,2
#define     ra3dir  trisa,3
#define     ra4dir  trisa,4
#define     rb0dir  trisb,0
#define     rb1dir  trisb,1
#define     rb2dir  trisb,2
#define     rb3dir  trisb,3
#define     rb4dir  trisb,4
#define     rb5dir  trisb,5
#define     rb6dir  trisb,6
#define     rb7dir  trisb,7
;************************************************************
;ram definition
            __maxram 0xcf 
            __badram 0x07,0x50-0x7f,0x87 
;************************************************************
;configuration bits
_cp_on      equ     0x000f 
_cp_off     equ     0x3fff 
_pwrte_on   equ     0x3ff7 
_pwrte_off  equ     0x3fff 
_wdt_on     equ     0x3fff 
_wdt_off    equ     0x3ffb 
_lp_osc     equ     0x3ffc 
_xt_osc     equ     0x3ffd 
_hs_osc     equ     0x3ffe 
_rc_osc     equ     0x3fff 
;************************************************************
 endif
;************************************************************






;************************************************************
;.pic16f876.                                                *
;************************************************************
 if (_proctype == 876)
;************************************************************
            list    p=16f876
;************************************************************
_mpages     set     4
_rpages     set     4
lastramm0   set     0x020
lastramm1   set     0x0a0
lastramm2   set     0x110
lastramm3   set     0x190
lastrams0   set     0x07f
lastrams1   set     0x0ef
lastrams2   set     0x16f
lastrams3   set     0x1ef
;************************************************************
;register files
indf        equ     0x00
tmr0        equ     0x01
pcl         equ     0x02
;************************************************************
status      equ     0x03
irp         equ     7
rp1         equ     6
rp0         equ     5
not_to      equ     4
not_pd      equ     3
z           equ     2
dc          equ     1
c           equ     0
;************************************************************
fsr         equ     0x04
porta       equ     0x05
portb       equ     0x06
portc       equ     0x07
;************************************************************
pclath      equ     0x0a
;************************************************************
intcon      equ     0x0b
gie         equ     7
peie        equ     6
t0ie        equ     5
inte        equ     4
rbie        equ     3
t0if        equ     2
intf        equ     1
rbif        equ     0
;************************************************************
pir1        equ     0x0c
pspif       equ     7
adif        equ     6
rcif        equ     5
txif        equ     4
sspif       equ     3
ccp1if      equ     2
tmr2if      equ     1
tmr1if      equ     0
;************************************************************
pir2        equ     0x0d
eeif        equ     4
bclif       equ     3
ccp2if      equ     0
;************************************************************
tmr1l       equ     0x0e
tmr1h       equ     0x0f
;************************************************************
t1con       equ     0x10
t1ckps1     equ     5
t1ckps0     equ     4
t1oscen     equ     3
not_t1sync  equ     2
t1insync    equ     2
tmr1cs      equ     1
tmr1on      equ     0
;************************************************************
tmr2        equ     0x11
;************************************************************
t2con       equ     0x12
toutps3     equ     6
toutps2     equ     5
toutps1     equ     4
toutps0     equ     3
tmr2on      equ     2
t2ckps1     equ     1
t2ckps0     equ     0
;************************************************************
sspbuf      equ     0x13
sspbuff     equ     0x13
;************************************************************
sspcon      equ     0x14
wcol        equ     7
sspov       equ     6
sspen       equ     5
ckp         equ     4
sspm3       equ     3
sspm2       equ     2
sspm1       equ     1
sspm0       equ     0
;************************************************************
ccpr1l      equ     0x15
ccpr1h      equ     0x16
;************************************************************
ccp1con     equ     0x17
ccp1x       equ     5
ccp1y       equ     4
ccp1m3      equ     3
ccp1m2      equ     2
ccp1m1      equ     1
ccp1m0      equ     0
;************************************************************
rcsta       equ     0x18
spen        equ     7
rx9         equ     6
rc9         equ     6
not_rc8     equ     6
rc8_9       equ     6
sren        equ     5
cren        equ     4
adden       equ     3
ferr        equ     2
oerr        equ     1
rx9d        equ     0
rcd8        equ     0
;************************************************************
txreg       equ     0x19
rcreg       equ     0x1a
ccpr2l      equ     0x1b
ccpr2h      equ     0x1c
;************************************************************
ccp2con     equ     0x1d
ccp2x       equ     5
ccp2y       equ     4
ccp2m3      equ     3
ccp2m2      equ     2
ccp2m1      equ     1
ccp2m0      equ     0
;************************************************************
adresh      equ     0x1e
adresl      equ     0x9e
adres       equ     0x1e                ;8 bit conversion backward comp (adfm=0)
;************************************************************
adcon0      equ     0x1f
adcs1       equ     7
adcs0       equ     6
chs2        equ     5
chs1        equ     4
chs0        equ     3
go          equ     2
not_done    equ     2
go_done     equ     2
chs3        equ     1
adon        equ     0
;************************************************************
option_reg  equ     0x81
not_rbpu    equ     7
intedg      equ     6
t0cs        equ     5
t0se        equ     4
psa         equ     3
ps2         equ     2
ps1         equ     1
ps0         equ     0
;************************************************************
trisa       equ     0x85
portadir    equ     0x85
trisb       equ     0x86
portbdir    equ     0x86
trisc       equ     0x87
portcdir    equ     0x87
;************************************************************
ibf         equ     7
obf         equ     6
ibov        equ     5
pspmode     equ     4
;************************************************************
pie1        equ     0x8c
pspie       equ     7
adie        equ     6
rcie        equ     5
txie        equ     4
sspie       equ     3
ccp1ie      equ     2
tmr2ie      equ     1
tmr1ie      equ     0
;*************************************************************
pie2        equ     0x8d
eeie        equ     4
bclie       equ     3
ccp2ie      equ     0
;************************************************************
pcon        equ     0x8e
not_por     equ     1
not_bo      equ     0
not_bor     equ     0
;************************************************************
sspcon2     equ     0x91
gcen        equ     7
ackstat     equ     6
ackdt       equ     5
acken       equ     4
rcen        equ     3
pen         equ     2
rsen        equ     1   
sen         equ     0   
;************************************************************
pr2         equ     0x92
sspadd      equ     0x93
;************************************************************
sspstat     equ     0x94
smp         equ     7
cke         equ     6
d           equ     5
i2c_data    equ     5
not_a       equ     5
not_address equ     5
d_a         equ     5
data_address equ    5
p           equ     4
i2c_stop    equ     4
s           equ     3
i2c_start   equ     3
r           equ     2
i2c_read    equ     2
not_w       equ     2
not_write   equ     2
r_w         equ     2
read_write  equ     2
ua          equ     1
bf          equ     0
;************************************************************
txsta       equ     0x98
csrc        equ     7
tx9         equ     6
not_tx8     equ     6
tx8_9       equ     6
txen        equ     5
sync        equ     4
brgh        equ     2
trmt        equ     1
tx9d        equ     0
txd8        equ     0
;************************************************************
spbrg       equ     0x99
adresl      equ     0x9e
adcon1      equ     0x9f
adfm        equ     5
pcfg3       equ     3
pcfg2       equ     2
pcfg1       equ     1
pcfg0       equ     0
;************************************************************
eedata      equ     0x10c
eeadr       equ     0x10d
eedath      equ     0x10e
eeadrh      equ     0x10f
;************************************************************
eecon1      equ     0x18c
eepgd       equ     7
wrerr       equ     3
wren        equ     2
wr          equ     1
rd          equ     0
;************************************************************
eecon2      equ     0x18d
;************************************************************
;spi pin name definitions
#define     sck     rc3
#define     sdi     rc4
#define     sdo     rc5
;************************************************************
;port bit definitions
#define     ra0     porta,0
#define     ra1     porta,1
#define     ra2     porta,2
#define     ra3     porta,3
#define     ra4     porta,4
#define     ra5     porta,5
#define     rb0     portb,0
#define     rb1     portb,1
#define     rb2     portb,2
#define     rb3     portb,3
#define     rb4     portb,4
#define     rb5     portb,5
#define     rb6     portb,6
#define     rb7     portb,7
#define     rc0     portc,0
#define     rc1     portc,1
#define     rc2     portc,2
#define     rc3     portc,3
#define     rc4     portc,4
#define     rc5     portc,5
#define     rc6     portc,6
#define     rc7     portc,7
;************************************************************
;port direction control bit definitions
;0=output
;1=input
#define     ra0dir  trisa,0
#define     ra1dir  trisa,1
#define     ra2dir  trisa,2
#define     ra3dir  trisa,3
#define     ra4dir  trisa,4
#define     ra5dir  trisa,5
#define     rb0dir  trisb,0
#define     rb1dir  trisb,1
#define     rb2dir  trisb,2
#define     rb3dir  trisb,3
#define     rb4dir  trisb,4
#define     rb5dir  trisb,5
#define     rb6dir  trisb,6
#define     rb7dir  trisb,7
#define     rc0dir  trisc,0
#define     rc1dir  trisc,1
#define     rc2dir  trisc,2
#define     rc3dir  trisc,3
#define     rc4dir  trisc,4
#define     rc5dir  trisc,5
#define     rc6dir  trisc,6
#define     rc7dir  trisc,7
;************************************************************
;ram definition
            __maxram h'1ff'
            __badram h'8f'-h'90', h'95'-h'97', h'9a'-h'9d'
            __badram h'105', h'107'-h'109'
            __badram h'185', h'187'-h'189', h'18e'-h'18f'
;************************************************************
;configuration bits
_boden_on   equ     0x3fff
_boden_off  equ     0x3fbf
_cp_all     equ     0x0fcf
_cp_half    equ     0x1fdf
_cp_upper_256 equ   0x2fef
_cp_off     equ     0x3fff
_wrt_enable_on equ  0x3fff
_wrt_enable_off equ 0x3dff
_pwrte_off  equ     0x3fff
_pwrte_on   equ     0x3ff7
_wdt_on     equ     0x3fff
_wdt_off    equ     0x3ffb
_lp_osc     equ     0x3ffc
_xt_osc     equ     0x3ffd
_hs_osc     equ     0x3ffe
_rc_osc     equ     0x3fff
_debug_on   equ     0x37ff
_debug_off  equ     0x3fff
_cpd_on     equ     0x3eff
_cpd_off    equ     0x3fff
_lvp_on     equ     0x3fff
_lvp_off    equ     0x3f7f
;************************************************************
 endif
;************************************************************




;************************************************************
;.pic16f877.                                                *
;************************************************************
 if (_proctype == 877)
;************************************************************
            list    p=16f877
;************************************************************
_mpages     set     4
_rpages     set     4
lastramm0   set     0x020
lastramm1   set     0x0a0
lastramm2   set     0x110
lastramm3   set     0x190
lastrams0   set     0x07f
lastrams1   set     0x0ef
lastrams2   set     0x16f
lastrams3   set     0x1ef
;************************************************************
;register files
indf        equ     0x00
tmr0        equ     0x01
pcl         equ     0x02
;************************************************************
status      equ     0x03
irp         equ     7
rp1         equ     6
rp0         equ     5
not_to      equ     4
not_pd      equ     3
z           equ     2
dc          equ     1
c           equ     0
;************************************************************
fsr         equ     0x04
porta       equ     0x05
portb       equ     0x06
portc       equ     0x07
portd       equ     0x08
porte       equ     0x09
;************************************************************
pclath      equ     0x0a
;************************************************************
intcon      equ     0x0b
gie         equ     7
peie        equ     6
t0ie        equ     5
inte        equ     4
rbie        equ     3
t0if        equ     2
intf        equ     1
rbif        equ     0
;************************************************************
pir1        equ     0x0c
pspif       equ     7
adif        equ     6
rcif        equ     5
txif        equ     4
sspif       equ     3
ccp1if      equ     2
tmr2if      equ     1
tmr1if      equ     0
;************************************************************
pir2        equ     0x0d
eeif        equ     4
bclif       equ     3
ccp2if      equ     0
;************************************************************
tmr1l       equ     0x0e
tmr1h       equ     0x0f
;************************************************************
t1con       equ     0x10
t1ckps1     equ     5
t1ckps0     equ     4
t1oscen     equ     3
not_t1sync  equ     2
t1insync    equ     2
tmr1cs      equ     1
tmr1on      equ     0
;************************************************************
tmr2        equ     0x11
;************************************************************
t2con       equ     0x12
toutps3     equ     6
toutps2     equ     5
toutps1     equ     4
toutps0     equ     3
tmr2on      equ     2
t2ckps1     equ     1
t2ckps0     equ     0
;************************************************************
sspbuf      equ     0x13
sspbuff     equ     0x13
;************************************************************
sspcon      equ     0x14
wcol        equ     7
sspov       equ     6
sspen       equ     5
ckp         equ     4
sspm3       equ     3
sspm2       equ     2
sspm1       equ     1
sspm0       equ     0
;************************************************************
ccpr1l      equ     0x15
ccpr1h      equ     0x16
;************************************************************
ccp1con     equ     0x17
ccp1x       equ     5
ccp1y       equ     4
ccp1m3      equ     3
ccp1m2      equ     2
ccp1m1      equ     1
ccp1m0      equ     0
;************************************************************
rcsta       equ     0x18
spen        equ     7
rx9         equ     6
rc9         equ     6
not_rc8     equ     6
rc8_9       equ     6
sren        equ     5
cren        equ     4
adden       equ     3
ferr        equ     2
oerr        equ     1
rx9d        equ     0
rcd8        equ     0
;************************************************************
txreg       equ     0x19
rcreg       equ     0x1a
ccpr2l      equ     0x1b
ccpr2h      equ     0x1c
;************************************************************
ccp2con     equ     0x1d
ccp2x       equ     5
ccp2y       equ     4
ccp2m3      equ     3
ccp2m2      equ     2
ccp2m1      equ     1
ccp2m0      equ     0
;************************************************************
adresh      equ     0x1e
adresl      equ     0x9e
adres       equ     0x1e                ;8 bit conversion backward comp (adfm=0)
;************************************************************
adcon0      equ     0x1f
adcs1       equ     7
adcs0       equ     6
chs2        equ     5
chs1        equ     4
chs0        equ     3
go          equ     2
not_done    equ     2
go_done     equ     2
chs3        equ     1
adon        equ     0
;************************************************************
option_reg  equ     0x81
not_rbpu    equ     7
intedg      equ     6
t0cs        equ     5
t0se        equ     4
psa         equ     3
ps2         equ     2
ps1         equ     1
ps0         equ     0
;************************************************************
trisa       equ     0x85
portadir    equ     0x85
trisb       equ     0x86
portbdir    equ     0x86
trisc       equ     0x87
portcdir    equ     0x87
trisd       equ     0x88
portddir    equ     0x88
trise       equ     0x89
portedir    equ     0x89
;************************************************************
ibf         equ     7
obf         equ     6
ibov        equ     5
pspmode     equ     4
;************************************************************
pie1        equ     0x8c
pspie       equ     7
adie        equ     6
rcie        equ     5
txie        equ     4
sspie       equ     3
ccp1ie      equ     2
tmr2ie      equ     1
tmr1ie      equ     0
;*************************************************************
pie2        equ     0x8d
eeie        equ     4
bclie       equ     3
ccp2ie      equ     0
;************************************************************
pcon        equ     0x8e
not_por     equ     1
not_bo      equ     0
not_bor     equ     0
;************************************************************
sspcon2     equ     0x91
gcen        equ     7
ackstat     equ     6
ackdt       equ     5
acken       equ     4
rcen        equ     3
pen         equ     2
rsen        equ     1   
sen         equ     0   
;************************************************************
pr2         equ     0x92
sspadd      equ     0x93
;************************************************************
sspstat     equ     0x94
smp         equ     7
cke         equ     6
d           equ     5
i2c_data    equ     5
not_a       equ     5
not_address equ     5
d_a         equ     5
data_address equ    5
p           equ     4
i2c_stop    equ     4
s           equ     3
i2c_start   equ     3
r           equ     2
i2c_read    equ     2
not_w       equ     2
not_write   equ     2
r_w         equ     2
read_write  equ     2
ua          equ     1
bf          equ     0
;************************************************************
txsta       equ     0x98
csrc        equ     7
tx9         equ     6
not_tx8     equ     6
tx8_9       equ     6
txen        equ     5
sync        equ     4
brgh        equ     2
trmt        equ     1
tx9d        equ     0
txd8        equ     0
;************************************************************
spbrg       equ     0x99
adresl      equ     0x9e
adcon1      equ     0x9f
adfm        equ     5
pcfg3       equ     3
pcfg2       equ     2
pcfg1       equ     1
pcfg0       equ     0
;************************************************************
eedata      equ     0x10c
eeadr       equ     0x10d
eedath      equ     0x10e
eeadrh      equ     0x10f
;************************************************************
eecon1      equ     0x18c
eepgd       equ     7
wrerr       equ     3
wren        equ     2
wr          equ     1
rd          equ     0
;************************************************************
eecon2      equ     0x18d
;************************************************************
;spi pin name definitions
#define     sck     rc3
#define     sdi     rc4
#define     sdo     rc5
;************************************************************
;port bit definitions
#define     ra0     porta,0
#define     ra1     porta,1
#define     ra2     porta,2
#define     ra3     porta,3
#define     ra4     porta,4
#define     ra5     porta,5
#define     rb0     portb,0
#define     rb1     portb,1
#define     rb2     portb,2
#define     rb3     portb,3
#define     rb4     portb,4
#define     rb5     portb,5
#define     rb6     portb,6
#define     rb7     portb,7
#define     rc0     portc,0
#define     rc1     portc,1
#define     rc2     portc,2
#define     rc3     portc,3
#define     rc4     portc,4
#define     rc5     portc,5
#define     rc6     portc,6
#define     rc7     portc,7
#define     rd0     portd,0
#define     rd1     portd,1
#define     rd2     portd,2
#define     rd3     portd,3
#define     rd4     portd,4
#define     rd5     portd,5
#define     rd6     portd,6
#define     rd7     portd,7
#define     re0     porte,0
#define     re1     porte,1
#define     re2     porte,2
;************************************************************
;alternate rd=psp, parallel slave port
#define     psp0    portd,0
#define     psp1    portd,1
#define     psp2    portd,2
#define     psp3    portd,3
#define     psp4    portd,4
#define     psp5    portd,5
#define     psp6    portd,6
#define     psp7    portd,7
#define     psp_rd  porte,0
#define     psp_wr  porte,1
#define     psp_cs  porte,2
;************************************************************
;port direction control bit definitions
;0=output
;1=input
#define     ra0dir  trisa,0
#define     ra1dir  trisa,1
#define     ra2dir  trisa,2
#define     ra3dir  trisa,3
#define     ra4dir  trisa,4
#define     ra5dir  trisa,5
#define     rb0dir  trisb,0
#define     rb1dir  trisb,1
#define     rb2dir  trisb,2
#define     rb3dir  trisb,3
#define     rb4dir  trisb,4
#define     rb5dir  trisb,5
#define     rb6dir  trisb,6
#define     rb7dir  trisb,7
#define     rc0dir  trisc,0
#define     rc1dir  trisc,1
#define     rc2dir  trisc,2
#define     rc3dir  trisc,3
#define     rc4dir  trisc,4
#define     rc5dir  trisc,5
#define     rc6dir  trisc,6
#define     rc7dir  trisc,7
#define     rd0dir  trisd,0
#define     rd1dir  trisd,1
#define     rd2dir  trisd,2
#define     rd3dir  trisd,3
#define     rd4dir  trisd,4
#define     rd5dir  trisd,5
#define     rd6dir  trisd,6
#define     rd7dir  trisd,7
#define     re0dir  trise,0
#define     re1dir  trise,1
#define     re2dir  trise,2
;************************************************************
;ram definition
            __maxram h'1ff'
            __badram h'8f'-h'90', h'95'-h'97', h'9a'-h'9d'
            __badram h'105', h'107'-h'109'
            __badram h'185', h'187'-h'189', h'18e'-h'18f'
;************************************************************
;configuration bits
_boden_on   equ     0x3fff
_boden_off  equ     0x3fbf
_cp_all     equ     0x0fcf
_cp_half    equ     0x1fdf
_cp_upper_256 equ   0x2fef
_cp_off     equ     0x3fff
_wrt_enable_on equ  0x3fff
_wrt_enable_off equ 0x3dff
_pwrte_off  equ     0x3fff
_pwrte_on   equ     0x3ff7
_wdt_on     equ     0x3fff
_wdt_off    equ     0x3ffb
_lp_osc     equ     0x3ffc
_xt_osc     equ     0x3ffd
_hs_osc     equ     0x3ffe
_rc_osc     equ     0x3fff
_debug_on   equ     0x37ff
_debug_off  equ     0x3fff
_cpd_on     equ     0x3eff
_cpd_off    equ     0x3fff
_lvp_on     equ     0x3fff
_lvp_off    equ     0x3f7f
;************************************************************
 endif
;************************************************************








;************************************************************
;.macro.                                                    *
;************************************************************
;opcode rename                                              *
;************************************************************
#define     subwl   sublw
;************************************************************
;register move                                              *
;************************************************************
movlf       macro   a,b
            movlw   b
            movwf   a
            endm

movff       macro   a,b                 ;register b >> register a
            movf    b,w
            movwf   a
            endm
;************************************************************
;logical operations                                         *
;************************************************************
andlf       macro   a,b
            movlw   b
            andwf   a,f
            endm

iorlf       macro   a,b
            movlw   b
            iorwf   a,f
            endm
;************************************************************
;bit test/set and skip                                      *
;************************************************************
scarry      macro
            bsf     status,c
            endm

ccarry      macro
            bcf     status,c
            endm

skipc       macro
            btfss   status,c
            endm

skipnc      macro
            btfsc   status,c
            endm

skipb       macro
            btfsc   status,c
            endm

skipnb      macro
            btfss   status,c
            endm

skipz       macro
            btfss   status,z
            endm

skipnz      macro
            btfsc   status,z
            endm

skipfz      macro   a
            movf    a,f
            btfss   status,z
            endm

skipfnz     macro   a
            movf    a,f
            btfsc   status,z
            endm

decfsnz     macro   a,b         
            decf    a,b
            btfsc   status,z
            endm            

decfsu      macro   a,b
            movlw   1
            subwf   a,b
            btfsc   status,c
            endm

decfgz      macro   a,b
            decf    a,f
            btfsc   status,z
            goto    b
            endm
;************************************************************
;bit test/set and skip, mathflag                            *
;************************************************************
skipmz      macro                       ;zero
            btfss   mflag,mzero
            endm

skipmnz     macro                       ;not zero
            btfsc   mflag,mzero
            endm

skipnmz     macro                       ;not zero, alternate use
            btfsc   mflag,mzero
            endm

skipmhz     macro                       ;high byte zero
            btfss   mflag,mhzero
            endm

skipnmhz    macro                       ;high byte not zero
            btfsc   mflag,mhzero
            endm

skipmrz     macro                       ;remainder zero
            btfss   mflag,mrzero
            endm

skipmnrz    macro                       ;remainder not zero
            btfsc   mflag,mrzero
            endm

skipmp      macro                       ;result positive
            btfss   mflag,mpos
            endm

skipmnp     macro
            btfsc   mflag,mpos          ;result not positive
            endm

skipmn      macro                       ;result negative
            btfss   mflag,mneg
            endm

skipmneg    macro                       ;result negative
            btfss   mflag,mneg
            endm

skipmnn     macro                       ;result not negative
            btfsc   mflag,mneg
            endm

skipmnneg   macro                       ;result not negative
            btfsc   mflag,mneg
            endm

skipme      macro                       ;result was error
            btfss   mflag,merr
            endm

skipmne     macro                       ;result was not error
            btfsc   mflag,merr
            endm

skipnme     macro                       ;result was not error, alternate
            btfsc   mflag,merr
            endm

skipmb      macro                       ;byte available
            btfss   mflag,mbyte
            endm

skipmnb     macro                       ;byte not available
            btfsc   mflag,mbyte
            endm
;************************************************************
;register compare and skip                                  *
;************************************************************
cflse       macro   a,b
            movlw   b
            xorwf   a,w
            btfss   status,z
            endm

cflsne      macro   a,b
            movlw   b
            xorwf   a,w
            btfsc   status,z
            endm

cffse       macro   a,b
            movf    b,w
            xorwf   a,w
            btfss   status,z
            endm

cffsne      macro   a,b
            movf    b,w
            xorwf   a,w
            btfsc   status,z
            endm

cflge       macro   a,b,c
            movlw   b
            xorwf   a,w
            btfsc   status,z
            goto    c
            endm
;************************************************************
;page control                                               *
;************************************************************
 if (_mpages == 2)
mpage0      macro
            bcf     pclath,3
            endm

mpage1      macro
            bsf     pclath,3
            endm
 endif
;------------------------------------------------------------
 if (_mpages > 2)
mpage0      macro
            bcf     pclath,3
            bcf     pclath,4
            endm

mpage1      macro
            bsf     pclath,3
            bcf     pclath,4
            endm

mpage2      macro
            bcf     pclath,3
            bsf     pclath,4
            endm

mpage3      macro
            bsf     pclath,3
            bsf     pclath,4
            endm
 endif
;************************************************************
 if (_rpages == 2)
rpage0      macro
            bcf     status,rp0
            endm

rpage1      macro
            bsf     status,rp0
            endm
 endif
;------------------------------------------------------------
 if (_rpages > 2)
rpage0      macro
            bcf     status,rp0
            bcf     status,rp1
            endm

rpage1      macro
            bsf     status,rp0
            bcf     status,rp1
            endm

rpage2      macro
            bcf     status,rp0
            bsf     status,rp1
            endm

rpage3      macro
            bsf     status,rp0
            bsf     status,rp1
            endm
 endif
;************************************************************
;.asmender.                                                 *
;assembly ender                                             *
;************************************************************
asmender    macro
;------------------------------------------------------------
lastromm    set     $
;------------------------------------------------------------
 if lastramm0 >= (lastrams0 + 2)
            messg   "--------------------------------------------"           
            messg   "Subroutine ram and main ram are over lapping"
            messg   "You must reduce the number of variables used"
            messg   "Page 0:  See lastramm0/lastrams0"
            messg   "--------------------------------------------"           
 endif
;------------------------------------------------------------
 if lastramm1 >= (lastrams1 + 2)
            messg   "--------------------------------------------"           
            messg   "Subroutine ram and main ram are over lapping"
            messg   "You must reduce the number of variables used"
            messg   "Page 1:  See lastramm1/lastrams1"
            messg   "--------------------------------------------"           
 endif
;------------------------------------------------------------
 if lastramm2 >= (lastrams2 + 2)
            messg   "--------------------------------------------"           
            messg   "Subroutine ram and main ram are over lapping"
            messg   "You must reduce the number of variables used"
            messg   "Page 2:  See lastramm2/lastrams2"
            messg   "--------------------------------------------"           
 endif
;------------------------------------------------------------
 if lastramm3 >= (lastrams3 + 2)
            messg   "--------------------------------------------"           
            messg   "Subroutine ram and main ram are over lapping"
            messg   "You must reduce the number of variables used"
            messg   "Page 3:  See lastramm3/lastrams3"
            messg   "--------------------------------------------"           
 endif
;------------------------------------------------------------
            end
            endm
;************************************************************
            errorlevel  0
;************************************************************


















            errorlevel  0,-302


;************************************************************
;.memmode1.                                                 *
;************************************************************
 if (_memmode == 1)                     ;large model 16c74
;************************************************************
;isr temp storage registers                                 *
;do not use 0x07f,0x0ff,0x17f,0x1ff as this references xw   *
;************************************************************
xw          equ     0x7f                ;temp reg:  w
xstatus     equ     0x7e                ;temp reg:  status
xfsr        equ     0x7d                ;           fsr
xpclath     equ     0x7c                ;           pclath
;************************************************************
;general registers
ddh         equ     0x7b                ;level 2 variables
ddl         equ     0x7a
cch         equ     0x79
ccl         equ     0x78
bbh         equ     0x77
bbl         equ     0x76
aah         equ     0x75
aal         equ     0x74
dh          equ     0x73                ;level 1 variables
dl          equ     0x72
ch          equ     0x71
cl          equ     0x70
bh          equ     0x6f
bl          equ     0x6e
ah          equ     0x6d
al          equ     0x6c
;************************************************************
xmflag      equ     0x6b                ;mathflag temp save
mflag       equ     0x6a                ;math result flags
mzero       equ     0                   ;result was zero
mhzero      equ     1                   ;high byte of 16 bit result is zero
mrzero      equ     2                   ;remainder from divide was zero
mpos        equ     3                   ;result was greater than zero
mneg        equ     4                   ;result was negative
merr        equ     5                   ;result was error
mbyte       equ     6                   ;byte available
;************************************************************
tmp0        equ     ddh
tmp1        equ     ddl
tmp2        equ     cch
tmp3        equ     ccl
tmp4        equ     bbh
tmp5        equ     bbl
tmp6        equ     aah
tmp7        equ     aal
;************************************************************
lastrams0   set     mflag-1
lastrams1   set     lastrams1-1
;************************************************************
 endif
;************************************************************







;************************************************************
;.memmode2.                                                 *
;************************************************************
 if (_memmode == 2)                     ;minimum use model 16c74
;************************************************************
;isr temp storage registers                                 *
;do not use 0x07f,0x0ff,0x17f,0x1ff as this references xw   *
;************************************************************
xw          equ     0x7f                ;temp reg:  w
xstatus     equ     0x7e                ;temp reg:  status
xfsr        equ     0x7d                ;           fsr
xpclath     equ     0x7c                ;           pclath
;************************************************************
bh          equ     0x7b
bl          equ     0x7a
ah          equ     0x79
al          equ     0x78
;************************************************************
xmflag      equ     0x77                ;temp math flag
mflag       equ     0x76                ;math result flags
mzero       equ     0                   ;result was zero
mhzero      equ     1                   ;high byte of 16 bit result is zero
mrzero      equ     2                   ;remainder from divide was zero
mpos        equ     3                   ;result was greater than zero
mneg        equ     4                   ;result was negative
merr        equ     5                   ;result was error
;************************************************************
tmp0        equ     bh                  ;temp registers are working registers
tmp1        equ     bl
tmp2        equ     ah
tmp3        equ     al
;************************************************************
lastrams0   set     mflag-1
lastrams1   set     lastrams1-1         ;xw across all pages
;************************************************************
 endif
;************************************************************





;************************************************************
;.memmode3.                                                 *
;************************************************************
 if (_memmode == 3)                     ;large model 16f877
;************************************************************
;ram allocation                                             *
;                                                           *
;0x020-0x06f                                                *
;0x0a0-0x0ef                                                *
;0x110-0x16f                                                *
;0x190-0x1ef                                                *
;                                                           *
;0x70-0x7f mapped across all 4 pages                        *
;0x70 used by icd debug mode                                *
;                                                           *
;0x71 to 0x7b mapped across all 4 pages, available for main *
;************************************************************
xw          equ     0x7f                ;temp reg:  w
xstatus     equ     0x7e                ;temp reg:  status
xfsr        equ     0x7d                ;           fsr
xpclath     equ     0x7c                ;           pclath
;************************************************************
;general registers
ddh         equ     0x6f                ;level 2 variables
ddl         equ     0x6e
cch         equ     0x6d
ccl         equ     0x6c
bbh         equ     0x6b
bbl         equ     0x6a
aah         equ     0x69
aal         equ     0x68
dh          equ     0x67                ;level 1 variables
dl          equ     0x66
ch          equ     0x65
cl          equ     0x64
bh          equ     0x63
bl          equ     0x62
ah          equ     0x61
al          equ     0x60
;************************************************************
xmflag      equ     0x5f                ;mathflag temp save
mflag       equ     0x5e                ;math result flags
mzero       equ     0                   ;result was zero
mhzero      equ     1                   ;high byte of 16 bit result is zero
mrzero      equ     2                   ;remainder from divide was zero
mpos        equ     3                   ;result was greater than zero
mneg        equ     4                   ;result was negative
merr        equ     5                   ;result was error
mbyte       equ     6                   ;byte available
;************************************************************
tmp0        equ     ddh
tmp1        equ     ddl
tmp2        equ     cch
tmp3        equ     ccl
tmp4        equ     bbh
tmp5        equ     bbl
tmp6        equ     aah
tmp7        equ     aal
;************************************************************
lastrams0   set     mflag-1
;************************************************************
 endif
;************************************************************














;************************************************************
 ifdef eqblock                          ;main program equates
            include eqblock
 endif
;************************************************************
 ifdef mablock                          ;main program macros
            include mablock
 endif
;************************************************************

 








;############################################################
;############################################################
;############################################################
;############################################################
;############################################################







;************************************************************
;.reset.                                                    *
;reset block                                                *
;this block always included                                 *
;************************************************************
            org     0x0000
;************************************************************
reset       nop                         ;nop for icd use
            nop
            clrf    intcon              ;all interrupts off
            goto    start
;************************************************************
lastromm    set     $
;************************************************************









;############################################################
;############################################################
;############################################################
;############################################################
;############################################################










;************************************************************
;.isr.                                                      *
;************************************************************
;this handler common to all processors, proctype determines *
;  location of temp storage registers                       *
;############################################################
;.isrpmode1.                                                *
;************************************************************
 if (_isrpmode == 1)
;************************************************************
            errorlevel 0,-307
            org     0x0004
;************************************************************
;interrupt service routine                                  *
;************************************************************
isrprep_    movwf   xw                  ;save w, in unknown current page
            swapf   status,w            ;save status, no flags
            rpage0                      ;switch to ram page 0
            movwf   xstatus
            movf    fsr,w               ;save fsr
            movwf   xfsr            
            movf    pclath,w            ;save pclath
            movwf   xpclath
;------------------------------------------------------------
;switch to memory page where handler lives, isr return is   -
;  always page 0.  keyed to sub start as it is initialized  -
;  prior to this code and also is where interrupt processor -
;  located                                                  -
;////////////////////////////////////////////////////////////
 if (_isrmain == false)
;............................................................
 if (_substart <= 0x07ff)
 endif
 if ((_substart >= 0x0800) && (_substart <= 0x0fff))
            mpage1  
 endif
 if ((_substart >= 0x1000) && (_substart <= 0x17ff))
            mpage2  
 endif
 if ((_substart >= 0x1800) && (_substart <= 0x1fff))
            mpage3  
 endif
;............................................................
            goto    isrbegin_           ;do interrupt service
 endif                                  ;  whereever it ended up
;////////////////////////////////////////////////////////////
 if (_isrmain == true)
            mpage0                      ;switch to page 0 (main system codespace)
            include isblock             ;main system isr block
 endif                                  ;  inserted here in page 0
;////////////////////////////////////////////////////////////
isrret_     rpage0                      ;restore registers
            movf    xpclath,w           ;pclath, this allows execution to
            movwf   pclath              ;  continue in page it was in!!
            movf    xfsr,w              ;fsr register
            movwf   fsr
            swapf   xstatus,w           ;status register and ram bank
            movwf   status              ; at interrupt restored
            swapf   xw,f                ;restore w register from unknown page
            swapf   xw,w                ;  without changing status
            retfie                      ;return
;************************************************************
lastromi    set     $
lastromm    set     $
;************************************************************
 endif
;############################################################










;############################################################
;############################################################
;############################################################
;############################################################
;############################################################





;************************************************************
 if (_substart > 0)                     ;if substart is zero, assemble entire 
            org     _substart           ;code in line from 0x0 on
 endif
;************************************************************








;************************************************************
;.isrmode1.                                                 *
;...........................................................*
;isr mode 1     16c74 interrupt mode                        *
;************************************************************
 if (_isrmode == 1)
;************************************************************
;interrupt service block 1                                  *
;************************************************************
isrbegin_
;************************************************************
;peripheral interrupts/individually set via pie1            *
;************************************************************
isr1_       btfss   intcon,peie         
            goto    isr2_
;************************************************************
isrpera_    btfss   pir1,rcif           ;uart receive interrupt
            goto    isrperb_
;************************************************************


;************************************************************
;uart receive interrupt handler                             *
;with n byte receive buffer                                 *
;scibmode_                                                  *
;...........................................................*
;mode 1     top     0xdf    64 bytes of sci input buffer    *
;            .                                              *
;            .                                              *
;            .                                              *
;           bottom  0xa0                                    *
;...........................................................*
;mode 2     top     0xf7    8 bytes of sci input buffer     *
;            .                                              *
;            .                                              *
;            .                                              *
;           bottom  0xf0                                    *
;...........................................................*
;mode 3     top     0xdf    32 bytes of sci input buffer    *
;            .                                              *
;            .                                              *
;            .                                              *
;           bottom  0xc0                                    *
;...........................................................*
;mode 4     top     0x15f   64 bytes of sci input buffer    *
;            .              page 3 ram (16f877)             *
;            .                                              *
;            .                                              *
;           bottom  0x120                                   *
;************************************************************
 if (_scibmode > 0)
;************************************************************
 if (_scibmode == 1)                    ;63 bytes at 0xa0
_bufftrim   equ     0x3f
_buffbottom equ     0xa0
_buffsize   equ     63
_bufflimit  equ     59
 endif
;............................................................
 if (_scibmode == 2)                    ;7 bytes at 0xf0
_bufftrim   equ     0x07
_buffbottom equ     0xf0
_buffsize   equ     7
_bufflimit  equ     4
 endif
;............................................................
 if (_scibmode == 3)                    ;31 bytes at 0xc0
_bufftrim   equ     0x1f
_buffbottom equ     0xc0
_buffsize   equ     31
_bufflimit  equ     27
 endif
;............................................................
 if (_scibmode == 4)                    ;63 bytes at 0x120
_bufftrim   equ     0x3f
_buffbottom equ     0x120
_buffsize   equ     63
_bufflimit  equ     59
 endif
;************************************************************
sciuartrx_  bcf     pir1,rcif           ;clear interrupt flag
            btfss   rcsta,ferr          ;toss out bytes with bad framing
            goto    sciuartrx0_
sciuartrxf_ movf    rcreg,w             ;throw away bad byte
            goto    sciuartexit_
sciuartrx0_ movf    scibuffe,w
            addlw   _buffbottom & 0xff
            movwf   fsr
            movf    rcreg,w
;............................................................
 if (_buffbottom > 0xff)
            bsf     status,irp          ;page 3/4 indf addressing
 endif
;............................................................ 
            movwf   indf                ;save to end of buffer
;............................................................
 if (_buffbottom > 0xff)
            bcf     status,irp          ;page 3/4 indf addressing
 endif
;............................................................ 
            incf    scibuffe,w          ;pointer=pointer+1
            andlw   _bufftrim           ;trim to n bits
            movwf   scibuffe
;............................................................
 if (_uarthandsh == true)
sciuartbs_  bcf     sciflag,scirxbf     ;test for buffer full
            movf    scibuffs,w          ;calculate bytes in buff
            subwf   scibuffe,w
            andlw   _buffsize           ;4 bytes open for rts delay
            sublw   _bufflimit
            skipnc                      ;no carry=over
            goto    sciuartort_
sciuartbs1_ bsf     sciflag,scirxbf
            bsf     scirts              ;flag buffer full
 endif
;............................................................
sciuartort_ movf    scibuffs,w          ;test for software buffer overrun
            xorwf   scibuffe,w
            skipnz
            bsf     sciflag,scirxbor
sciuartexit_ btfsc  rcsta,oerr          ;check for hardware overrun error
            bcf     rcsta,cren          ;clear hardware overrun error
            bsf     rcsta,cren
;************************************************************
 endif
;************************************************************



;************************************************************
isrperb_
;************************************************************



;************************************************************
;timer0 interrupt                                           *
;************************************************************
isr2_       btfss   intcon,t0ie         
            goto    isr3_
;************************************************************



;************************************************************
;rb0/int external interrupt                                 *
;************************************************************
isr3_       btfss   intcon,inte         
            goto    isr4_
;************************************************************





;************************************************************
;rb port change                                             *
;************************************************************
isr4_       btfss   intcon,rbie         
            goto    isrexit_
;************************************************************



;************************************************************
isrexit_    mpage0                      ;set mem page to zero to finish
            goto    isrret_
;************************************************************
 endif
;************************************************************















;************************************************************
;.sciutil.                                                  *
;...........................................................*
;mode 1         16c74a hardwar uart                         *
;************************************************************
 if (_scimode == 1)
;************************************************************
;sci output:    place character to send in w                *
;               call sciput                                 *
;               *test sciflag,scitxbusy to verify sending   *
;               *test sciflag,scitxto for time out status   *
;                                                           *
;sci input:     call sciget                                 *
;               character will be returned in w             *
;               test mflag,mzero if byte was available      *
;                 0=byte returned/1=no byte was avialable   *
;                 skipmnz=byte  skipmz=nobyte               *
;                                                           *
;rxbuff start   only sci_get may update                     *
;rxbuff end     only sci_uartrx may update (interrupt serv) *
;************************************************************
scisetup    macro
            call    scisetup_
            endm

sciput      macro   a
            movlw   a
            call    sciput_
            endm

sciputw     macro
            call    sciput_
            endm

sciputbe    macro
            call    sciputbe_
            endm

sciget      macro
            call    sciget_
            endm
;............................................................
scirxenable macro
            rpage1                      
            bsf     pie1,rcie           ;rx interrupt on
            rpage0
            bsf     rcsta,cren          ;turn hardware on
            endm

scirxdisable macro
            rpage1                      
            bcf     pie1,rcie           ;rx interrupt off
            rpage0
            bcf     rcsta,cren          ;turn hardware off
            endm
;............................................................
sciflush    macro
            movff   scibuffe,scibuffs   ;flush input buffer
            endm
;************************************************************
sciflag     equ     lastrams0
scitxto     equ     0                   ;1=timed out/0=data sent
scitxbusy   equ     1                   ;1=transmit busy/0=data sent
scirxbor    equ     2                   ;1=buffer overrun/0=no overrun
scirxbf     equ     3                   ;1=buffer full/0=not full
;............................................................
scigettmp   equ     sciflag-1
;............................................................
 if _uarthandsh == true
scitxtoc1   equ     scigettmp-1         ;transmit timeout counters
scitxtoc0   equ     scitxtoc1-1         ;  for handshaking mode
scibuffe    equ     scitxtoc0-1         ;buffer end pointer
 else
scibuffe    equ     scigettmp-1         ;or buffer end pointer
 endif
;------------------------------------------------------------
scibuffs    equ     scibuffe-1          ;buffer start pointer 
;------------------------------------------------------------
 if (_uartchksum == false)
lastrams0   set     scibuffs-1
 endif
 if (_uartchksum == true)
scitxcsum   equ     scibuffs-1          ;checksum accumulator
lastrams0   set     scitxcsum-1
 endif
;############################################################
;############################################################
;.scisetup.                                                 *
;************************************************************
;setup async serial io                                      *
;input buffer controlled at sciuart interrupt level         *
;serial parameters must be specified in equate block:       *
;   scitxsta    high/low baud, parameters                   *
;   scispbrg    baud rate divider                           *
;************************************************************
scisetup_
;............................................................
 if _uarthandsh == true
            clrf    scitxtoc0           ;reset tx timeout counter
            clrf    scitxtoc1
 endif
;............................................................
            rpage1
            movlw   _scitxsta           ;tx setup/tx enable
            movwf   txsta
            movlw   _scispbrg           ;baud rate divider
            movwf   spbrg
            rpage0
            bcf     rcsta,cren          ;disable internal rx
            movlw   0x80                ;setup rx/enable serial io
            movwf   rcsta
            bsf     rcsta,cren          ;enable internal rx
            rpage1                      
            bsf     pie1,rcie           ;rx interrupt on
            bsf     intcon,peie         ;peripheral interrupt on
            rpage0
;............................................................
 if _uarthandsh == true
            bcf     scirts
 endif
;............................................................
            return
;############################################################
;############################################################
;.sciput.                                                   *
;************************************************************
;byte transmit                                              *
;                                                           *
;byte in w will be sent as soon as buffer is empty          *
;************************************************************
 if _uarthandsh == true
;////////////////////////////////////////////////////////////
sciput_     btfss   scicts              ;check cts line
            goto    sciput1_
            movlw   1
            call    delayms_
            bsf     sciflag,scitxbusy   ;tx was busy
            incfsz  scitxtoc0,f         ;tx busy time out counter
            goto    sciputtx_
            incf    scitxtoc1,f
            skipnz
            bsf     sciflag,scitxto     ;timed out after 65535 cycles
sciputtx_   return                      ;  but not in this routine
sciput1_    clrf    scitxtoc0           ;blind transmit entry
            clrf    scitxtoc1           ;clear timeout counter
            bcf     sciflag,scitxbusy   ;tx was not busy
;------------------------------------------------------------
sciputl_    iopage1
sciputl0_   clrwdt
            btfss   txsta,trmt          ;wait till tx buffer empty
            goto    sciputl0_           ;  to transmit next byte
            iopage0
            movwf   txreg
   if (_uartchksum == true)
            addwf   scitxcsum,f         ;running accumulator
   endif
            return
;////////////////////////////////////////////////////////////
 else
;////////////////////////////////////////////////////////////
sciput_     
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 if (_uartbctrl == true)                ;enable tx for all transmit
   if ($ >= 0x0800)
            mpage0                      ;low level control must be in page 0
   endif
            movwf   scigettmp           ;save for later
            call    txenable            ;low routine handles logic
   if ($ >= 0x0800) && ($ <= 0x0fff)
            mpage1                      ;restore page of this routine
   endif
   if ($ >= 0x1000) && ($ <= 0x17ff)
            mpage2
   endif
   if ($ >= 0x1800) && ($ <= 0x1fff)
            mpage3
   endif
 endif
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            rpage1
sciputl0_   clrwdt
            btfss   txsta,trmt          ;wait till tx buffer empty
            goto    sciputl0_           ;  to transmit next byte
            rpage0
            movwf   txreg
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 if (_uartchksum == true)
            addwf   scitxcsum,f         ;running accumulator
 endif
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 if (_uartbctrl == true)                ;disable tx for last char was 'cr'
            movf    scigettmp,w
            xorlw   13
            skipz
            return                      ;was not cr so continue
            call    sciputbe_           ;was cr so wait till buffer empty
   if ($ >= 0x800)
            mpage0
   endif
            call    txdisable           ;low routine handles logic
   if ($ >= 0x0800) && ($ <= 0x0fff)
            mpage1                      ;restore page of this routine
   endif
   if ($ >= 0x1000) && ($ <= 0x17ff)
            mpage2
   endif
   if ($ >= 0x1800) && ($ <= 0x1fff)
            mpage3
   endif
 endif
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            return
;////////////////////////////////////////////////////////////
 endif
;############################################################
;############################################################
;return when output buffer is empty                         *
;-----------------------------------------------------------*
;buffer is empty 1 bit time after tx buffer flag is cleared *
;assuming 9600 baud minimum the wait time will be 108us     *
;  minimum.                                                 *
;at 3 instruction cycles per loop the formula will provide  *
;  the following delays:    32khz   1.12ms                  *
;                           200khz  540us                   *
;                           500khz  216us                   *
;                           1mhz    216us                   *
;                           10mhz   119us                   *
;                           20mhz   113us                   *
;************************************************************
sciputbe_   rpage1                      ;wait till tx buffer empty
sciputbel_  clrwdt
            btfss   txsta,trmt          ; and last bit gone
            goto    sciputbel_          ; to transmit next byte or
            rpage0                      ; control com hardware
;............................................................
            movlf   scigettmp,(((_clock/1000)+1)*9)
sciputbexl_ clrwdt
            decfsz  scigettmp,f
            goto    sciputbexl_
            return
;############################################################
;############################################################
;.sciget.                                                   *
;************************************************************
;byte retreive and overhead control for sci receiver        *
;setup buffers for enabled uart routine                     *
;                                                           *
;label      sciget                                          *
;           skipmb                                          *
;           goto    nobyte              ;no byte            *
;process    ...                         ;byte was availabe  *
;************************************************************
 if (_scibmode == 1)
uartbuffs   equ     0xa0                ;starts at 0xa0
uartbuffm   equ     0x3f                ;of 64 bytes length
 endif
 if (_scibmode == 2)
uartbuffs   equ     0xf0                ;starts at 0xf0
uartbuffm   equ     0x07                ;of 8 bytes length
 endif
 if (_scibmode == 3)                    
uartbuffs   equ     0xc0                ;starts at 0xc0
uartbuffm   equ     0x1f                ;of 32 btyes length
 endif
 if (_scibmode == 4)                    ;irp must be set to access indf for page 3
uartbuffs   equ     0x120               ;starts at 0x120
uartbuffm   equ     0x3f                ;of 64 bytes length
 endif
;************************************************************
sciget_     movf    scibuffe,w          ;get end of buffer pointer
            xorwf   scibuffs,w          ;test if end=start
            skipnz                      ;if equal than no bytes avail
            goto    scigetno_
scigetyes_  movf    scibuffs,w
            addlw   uartbuffs & 0xff    ;buffer offset in page 1
            movwf   fsr
;............................................................
 if (uartbuffs > 0xff)
            bsf     status,irp          ;9 bit indf addressing
 endif
;............................................................ 
            movf    indf,w              ;get byte from start of buffer
;............................................................
 if (uartbuffs > 0xff)
            bcf     status,irp          ;9 bit indf addressing
 endif
;............................................................ 
            movwf   scigettmp           ;save for later
            incf    scibuffs,w          ;pointer=pointer+1
            andlw   uartbuffm           ;trim to n bits
            movwf   scibuffs            ;save new pointer value
            movf    scigettmp,w
            bsf     mflag,mbyte         ;flag as available
            return
scigetno_   bcf     mflag,mbyte         ;no bytes available
;............................................................
 if (_uarthandsh == true)
            bcf     scirts
 endif
;............................................................
            return
;************************************************************
 endif
;************************************************************























;************************************************************
;.scmmd.                                                    *
;************************************************************
 if (_scmmd == true)
;************************************************************
;double click label, [f3], [return], [esc]                  *
; jump label    master  slave   description                 *
;-----------------------------------------------------------*
;.initblock.    x       x       system initialization block *
;.macros.       x       x       scmmd macro block           *
;.main.         x       x       main scmmd accumulator block*
;.string.               x       $ incoming command block    *
;.excl.         x               ! incoming response block   *
;.setup.        x       x       command clear and reset     *
;.scmmdlcode.   x       x       command code extractor      *
;.checksum.     x       x       checksum calc and test      *
;.framing.      x       x       framing test                *
;.addresstest.  x       x       address test                *
;.scmmdsack.            x       send ack                    *
;.scmmdsnak.            x       send nak                    *
;.scmmdschdr.   x               send command header         *
;.scmmdsrhdr.           x       send response header        *
;.scmmds4b.     x       x       translate and send: 4 bits  *
;.scmmds8b.     x       x                           8 bits  *
;.scmmds12b.    x       x                           12 bits *
;.scmmds16b.    x       x                           16 bits *
;.scmmdsendr.   x       x       calc cs(if mode), send w/cr *
;.scmmddxlte.   x       x       translate ascii hex to bin  *
;                                                           *
;.scmmdlcmmdx.  x               commands 00-07              *
;************************************************************
;.initblock.                                                *
;auto command buffering                                     *
;-----------------------------------------------------------*
;mflag,nb       ;no bytes were available to accumulate      *
;mflag,b        ;a byte was accumulated                     *
;-----------------------------------------------------------*
;scmmdbmode 0       31 bytes of sci command buffer at 0xe0  *
;cmmdbuff   0xfe    buffer top                              *
;            .                                              *
;            .                                              *
;            .                                              *
;cmmdbuff   0xe0    buffer bottom                           *
;...........................................................*
;scmmdbmode 1       32 bytes of sci command buffer at 0x1a0 *
;cmmdbuff   0x1bf   buffer top                              *
;            .                                              *
;            .                                              *
;            .                                              *
;cmmdbuff   0x1a0   buffer bottom                           *
;************************************************************
 if (_scmmdbmode == 0)
cmmdbuffo   equ     0xe0                ;command buffer offset address constants
cmmdbuffm   equ     0xfe                ;max address of buffer data
 endif
;............................................................
 if (_scmmdbmode == 1)                  ;irp must be set to access registers in page 4
cmmdbuffo   equ     0x1a0               ;command buffer offset address constants
cmmdbuffm   equ     0x1bf               ;max address of buffer data
 endif
;************************************************************
cmmdtype    equ     lastrams0           ;command or response code 00-ff
cmmdflag    equ     cmmdtype-1
cmmdrdy     equ     0   ;all            ;command/response ready in buffer
cmmdmode    equ     1   ;slave          ;local=0/remote=1
respack     equ     2   ;master         ;response was ack
respnak     equ     3   ;master         ;response was nack
;           equ     4   ;xxx            ;
cmmdlcmmd   equ     5   ;slave          ;low command was processed
cmmduser2   equ     6   ;all            ;user flag
cmmduser1   equ     7   ;all            ;user flag
cmmdbuffe   equ     cmmdflag-1          ;pointer to end of buffer
;............................................................
lastrams0   set     cmmdbuffe-1
;************************************************************
;.macros.                                                   *
;************************************************************
scmmdsu     macro
            call    scmmdsu_
            endm

scmmd       macro
            call    scmmd_
            endm

scmmdft     macro   a
            movlw   a
            call    scmmdft_
            endm

scmmdftw    macro
            call    scmmdft_
            endm

scmmdsack   macro
            call    scmmdsack_
            endm

scmmdsnak   macro
            call    scmmdsnak_
            endm
;............................................................
 if (_scmmdmode > 0x7f)
scmmdschdr  macro   a
            movlw   a
            call    scmmdschdr_
            endm

scmmdschdrw macro
            call    scmmdschdr_
            endm
 endif
;............................................................
 if (_scmmdmode < 0x80)
scmmdsrhdr  macro
            call    scmmdsrhdr_
            endm
 endif
;............................................................
scmmds4bw   macro
            call    scmmds4b_
            endm

scmmds4b    macro   a
            movlw   a
            call    scmmds4b_
            endm

scmmds8bw   macro
            call    scmmds8b_
            endm

scmmds8b    macro   a
            movlw   a
            call    scmmds8b_
            endm

scmmds12b   macro
            call    scmmds12b_
            endm

scmmds16b   macro
            call    scmmds16b_
            endm

scmmdsendr  macro
            call    scmmdsendr_
            endm

scmmddxltew macro
            call    scmmddxlte_
            endm

scmmddxlte  macro   a
            movlf   fsr,a
            call    scmmddxlte_
            endm
;************************************************************
;.main.                                                     *
;serial command accumulator/test/acknowledge                *
;************************************************************
scmmd_
;............................................................
;carrier detect mode switch for slave modes
 if ((_scmmdcd == true) && (_scmmdmode < 0x80))
            btfsc   scicts              ;local mode if connect lost
            bcf     cmmdflag,cmmdmode
 endif
;------------------------------------------------------------
scmmd01_    btfsc   cmmdflag,cmmdrdy    ;no new acc til
            return                      ;  last command cleared
;------------------------------------------------------------
            btfss   sciflag,scirxbor    ;test for input data over run
            goto    scmmd01b_
            bcf     sciflag,scirxbor    ;dump current accumulation for buff overrun
            goto    scmmdsu_            
scmmd01b_   call    sciget_     
            skipmb                      
            return                      ;return if no characters ready
            movwf   al                  ;save character
;////////////////////////////////////////////////////////////
            movf    cmmdbuffe,w         ;if pointer is not start then accumulate
            xorlw   (cmmdbuffo & 0xff) - 1
            skipz
            goto    scmmdacc_
;////////////////////////////////////////////////////////////
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01)
            movlw   '$'                 ;command
            xorwf   al,w
            skipz
            goto    scmmdsu_
 endif
 if (_scmmdmode == 0x80)
            movlw   '!'                 ;response
            xorwf   al,w
            skipz
            goto    scmmdsu_
 endif
;////////////////////////////////////////////////////////////
scmmdacc_   movlw   cr                  ;if cr then terminate
            xorwf   al,w
            skipnz
            goto    scmmdeoc_       
;------------------------------------------------------------
            incf    cmmdbuffe,f         ;pointer=pointer+1
            movf    cmmdbuffe,w         ;if max+1 then overflow and toss it
            xorlw   (cmmdbuffm & 0xff) + 1
            skipnz
            goto    scmmdsu_
;............................................................
            movff   fsr,cmmdbuffe       ;save new byte to buffer end
            movf    al,w
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf index
            bsf     status,irp
 endif
            movwf   indf
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf index
            bcf     status,irp      
 endif
            return                      ;was less than end, keep accumulating
;************************************************************




;************************************************************
;.string.                                                   *
;test and convert command type for all $ commands           *
;************************************************************
 if (_scmmdmode < 0x80)
;************************************************************
scmmdeoc_
scmmdstrg_  incf    cmmdbuffe,f         ;include cr in count
            call    scmmdat_            ;$ command handler
            skipmne
            goto    scmmdsu_            ;through away commands addressed elswhere
;------------------------------------------------------------
            call    scmmdccsi_          ;calculate checksum for incomming data
            skipmne
            goto    scmmdsnak_          ;nak bad checksums
;------------------------------------------------------------
scmmdstrg1_ call    scmmdlcode_         ;convert function code to binary 8 bit
            bsf     cmmdflag,cmmdrdy    ;flag as ready
;------------------------------------------------------------
            movlw   1                   ;wait 1 byte time on cmmd ready
            call    delayms_            ;  before any response (host turnaround delay)
;............................................................
            movlw   0xf8                ;test for commands $00-$07
            andwf   al,w
            skipnz
            goto    scmmdlcmmd_
;------------------------------------------------------------
 if (_remotemnu == true) || (_remotemnux == true)
            bsf     cmmdflag,cmmdrdy    ;normal return for all others
            return
 endif
 if (_remotemnu == false) && (_remotemnux == false)
            goto    scmmdsnak_          ;dump high commands if not available with nak
 endif
;************************************************************
 endif
;************************************************************




;************************************************************
;.excl.                                                     *
;master mode response accumulator                           *
;test and convert to type                                   *
;                                                           *
;flags set for  !GAa    ack                                 *
;               !GAn    nack                                *
;************************************************************
 if (_scmmdmode > 0x7f)
;************************************************************
scmmdeoc_
scmmdexcl_  incf    cmmdbuffe,f         include cr in count
            movlf   fsr,cmmdbuffo+3
            movlw   'a'                 ;test for ack
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            xorwf   indf,w

 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            skipnz
            goto    scmmdexcla_         ;was ack
            movlw   'n'                 ;test for nak
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            xorwf   indf,w
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            skipnz
            goto    scmmdexcln_         ;was nak
;------------------------------------------------------------
            call    scmmdccsi_          ;calculate checksum for incomming data
            skipmne
            goto    scmmdsu_            ;dump bad checksummed commands
;------------------------------------------------------------
            call    scmmdlcode_
            goto    scmmdexcly_
;------------------------------------------------------------
scmmdexcla_ bsf     cmmdflag,respack    ;was ack
            goto    scmmdexclx_
;............................................................
scmmdexcln_ bsf     cmmdflag,respnak    ;was nak
;------------------------------------------------------------
scmmdexclx_ clrf    cmmdtype            ;show ack/nak as 0
scmmdexcly_ bsf     cmmdflag,cmmdrdy
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;.setup.                                                    *
;************************************************************
;mode 0x00,0x01                                             *
;slave mode                                                 *
;seladdr set at powerup                                     *
;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01)
;************************************************************
scmmdsu_    movlf   fsr,cmmdbuffo & 0xff
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            clrf    indf
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            movlf   cmmdbuffe,(cmmdbuffo & 0xff) - 1
            bcf     cmmdflag,cmmdrdy        ;flag ready for new cmmd
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;0x80                                                       *
;master mode                                                *
;************************************************************
 if (_scmmdmode == 0x80)
;************************************************************
scmmdsu_    movlf   fsr,cmmdbuffo & 0xff
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            clrf    indf
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            movlf   cmmdbuffe,(cmmdbuffo & 0xff) - 1    ;reset end of buffer pointer
            bcf     cmmdflag,cmmdrdy    ;clear flags
            bcf     cmmdflag,respack
            bcf     cmmdflag,respnak
            return
;************************************************************
 endif
;************************************************************


;############################################################
;############################################################
;############################################################
;############################################################
;############################################################


;************************************************************
 if (_scmmdmode < 0x80)
;************************************************************
;.scmmdlcmmd. .scmmdlcmmdx.                                 *
;************************************************************
;commands 00-07 handled at this level                       *
;                                                           *
;$00    long firmware report                                *
;$01    set unit remote mode                                *
;$02    001 byte eeprom read                                *
;$03    001 byte eeprom write                               *
;$04    256 byte eeprom read                                *
;$05    008 byte eeprom write                               *
;$06    change unit address/write to eeprom                 *
;$07    system hard reset                                   *
;                                                           *
;cmmdtype used for temporary storage                        *
;************************************************************
 if (_scmmdmode == 0x00)                ;no check sums
rem00frame  equ     5
rem01frame  equ     6
rem02frame  equ     9
rem03frame  equ     11
rem04frame  equ     9
rem05frame  equ     25
rem06frame  equ     7
rem07frame  equ     5
;............................................................
remaddros   equ     5                   ;remote eeprom access address offset
remdataos   equ     9                   ;   "      "      "   data offset
 endif
;------------------------------------------------------------
 if (_scmmdmode == 0x01)                ;checksums, mode 00 frames + 2
rem00frame  equ     7
rem01frame  equ     8
rem02frame  equ     11
rem03frame  equ     13
rem04frame  equ     11
rem05frame  equ     27
rem06frame  equ     9
rem07frame  equ     7
;............................................................
remaddros   equ     5                   ;remote eeprom access address offset
remdataos   equ     9                   ;   "      "      "   data offset
 endif
;************************************************************
scmmdlcmmd_ incf    al,f
            bsf     cmmdflag,cmmdlcmmd  ;flag as called
;------------------------------------------------------------
            decfgz  al,remote00_
            decfgz  al,remote01_
            decfgz  al,remote02_
            decfgz  al,remote03_
            decfgz  al,remote04_
            decfgz  al,remote05_
            decfgz  al,remote06_
            goto    remote07_           ;test not needed since all others tried
;************************************************************
;long firmware report                                       *
;************************************************************
remote00_   movlw   rem00frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            call    scmmdsrhdr_
            movlf   ah,0x00             ;command code
            movlw   fcor1               ;software core
            call    sciput_
            movlw   fcor2
            call    sciput_
            movlw   fcor3
            call    sciput_
            movlw   fcor4
            call    sciput_
            movlw   fvar1               ;variation on that core
            call    sciput_
            movlw   fvar2
            call    sciput_
            movlw   frev1               ;revision of that variation
            call    sciput_
            movlw   frev2
            call    sciput_
            goto    scmmdsendr_
;************************************************************
;set unit remote mode and flag                              *
;system may ignore                                          *
;0=normal                                                   *
;1=remote active                                            *
;************************************************************
remote01_   movlw   rem01frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            movlf   fsr,(cmmdbuffo & 0xff) + 5
            bcf     cmmdflag,cmmdmode   ;preclear flag
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            btfsc   indf,0              ;test for bit high
            bsf     cmmdflag,cmmdmode   ;set flag
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            goto    scmmdsack_          ;done
;************************************************************
;02 read eeprom 1 byte                                      *
;************************************************************
remote02_   movlw   rem02frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            call    remoteat_           ;translate address
            movlf   m25cmmd,rdbyte
            call    scmmdsrhdr_
            movlw   0x02                ;command code
            call    scmmds8b_
            call    m25_                ;read byte
            movwf   al
            call    scmmds8b_
            goto    scmmdsendr_
;************************************************************
;03 write eeprom 1 byte                                     *
;************************************************************
remote03_   movlw   rem03frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            call    remoteat_           ;translate address
            movlf   fsr,(cmmdbuffo & 0xff) + remdataos
            call    scmmddxlte_
            movlf   m25cmmd,wrbyte
            movf    ah,w
            call    m25_                ;write
            goto    scmmdsack_          ;send ack
;************************************************************
;04 eeprom read 256 bytes                                   *
;************************************************************
remote04_   movlw   rem04frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            call    remoteat_           ;translate address
            movlf   m25cmmd,rdbyteinc
;............................................................
            call    scmmdsrhdr_
            movlw   0x04                ;command code
            call    scmmds8b_
            clrf    cmmdtype
remote04l_  call    m25_                ;read 256 bytes
            movwf   al
            call    scmmds8b_
            decfsz  cmmdtype,f
            goto    remote04l_
;............................................................
            goto    scmmdsendr_
;************************************************************
;05 eeprom write 8 bytes                                    *
;************************************************************
remote05_   movlw   rem05frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            call    remoteat_           ;translate address
            movlf   m25cmmd,wrblock
            movlf   m25size,0x08        ;8 byte block, page aligned
            movlf   cmmdtype,cmmdbuffo & 0xff   ;pointer for translated data
;............................................................
            movlf   fsr,(cmmdbuffo & 0xff) + remdataos  ;translate block 1
            call    remote05x_
            movlf   fsr,(cmmdbuffo & 0xff) + remdataos+4    ;translate block 2
            call    remote05x_
            movlf   fsr,(cmmdbuffo & 0xff) + remdataos+8    ;translate block 3
            call    remote05x_
            movlf   fsr,(cmmdbuffo & 0xff) + remdataos+12   ;translate block 4
            call    remote05x_
;------------------------------------------------------------
            movlw   cmmdbuffo & 0xff    ;pointer is buffer start
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            call    m25_
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            goto    scmmdsack_          ;send ack
;------------------------------------------------------------
remote05x_  call    scmmddxlte_         ;translate block
            movff   fsr,cmmdtype        ;get pointer
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movff   indf,ah
            incf    fsr,f
            movff   indf,al
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            incf    fsr,w
            movwf   cmmdtype            ;save current pointer value
            return
;************************************************************
;06 write new unit address                                  *
;************************************************************
remote06_   movlw   rem06frame
            call    scmmdft_
            skipmne
            goto    scmmdsnak_
;------------------------------------------------------------
            movlf   fsr,(cmmdbuffo & 0xff) + 5      ;translate new address to binary
            call    scmmddxlte_
            movlf   m25addrl,low(m_seladdr)
            movlf   m25addrh,high(m_seladdr)
            movlf   m25cmmd,wrbyte
            movf    ah,w
            movwf   seladdr             ;save in scmmd space
            call    m25_                ;write to eeprom
            goto    scmmdsack_          ;send ack
;************************************************************
;07 system hard reset                                       *
;************************************************************
remote07_   mpage0
            goto    reset
;************************************************************
;translate                                                  *
;************************************************************
remoteat_   movlf   fsr,(cmmdbuffo & 0xff) + remaddros  ;address translate for eeprom read/write
            call    scmmddxlte_
            movff   m25addrl,al
            movff   m25addrh,ah
            return
;************************************************************
 endif
;************************************************************





;############################################################
;############################################################
;############################################################
;############################################################
;############################################################




;************************************************************
;scmmd utility blocks                                       * 
;************************************************************
;.scmmdlcode.                                               *
;master & slave                                             *
;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01) || (_scmmdmode == 0x80)
;************************************************************
scmmdlcode_ movlf   fsr,(cmmdbuffo & 0xff) + 3      ;convert function code to binary 8 bit
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movff   bh,indf             ;used by both commands and responses
            incf    fsr,f
            movff   bl,indf
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            call    hex2bin_
            movff   cmmdtype,al
            return
;************************************************************
 endif
;************************************************************


;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x80)
;************************************************************
scmmdccsi_  bcf     mflag,merr          ;no test, always return a pass
            return
;************************************************************
 endif
;************************************************************


;************************************************************
 if (_scmmdmode == 0x01)
;************************************************************
;.checksum.                                                 *
;checksum calculator                                        *
;************************************************************
scmmdccsi_  movf    cmmdbuffe,w         ;count=last byte pointer-2
            addlw   -(0x02+(cmmdbuffo & 0xff))
            movwf   ah                  ;save counter
            movlf   fsr,cmmdbuffo & 0xff
;------------------------------------------------------------
            movlw   0x00                ;sum is now zero
scmmdccsil_
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            addwf   indf,w              ;add values of all bytes except cc+cr
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            incf    fsr,f               ;/---------\
            decfsz  ah,f                ;$..........CC[cr]
            goto    scmmdccsil_
;------------------------------------------------------------
            movwf   al                  ;convert to ascii
            call    bin2hex_
            bcf     mflag,merr
;------------------------------------------------------------
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movf    indf,w              ;test first byte
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            xorwf   bh,w
            skipz
            goto    scmmdccsie_         ;bad check sum
            incf    fsr,f               ;test second byte
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movf    indf,w
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            incf    fsr,f
            xorwf   bl,w
            skipnz
            return
;------------------------------------------------------------
scmmdccsie_ bsf     mflag,merr          ;set=error
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;.framing.                                                  *
;master & slave                                             *
;framing test calculator, w is bytes before cr              *
;************************************************************
scmmdft_    subwf   cmmdbuffe,w         ;test for correct framming, w characters
            sublw   cmmdbuffo & 0xff    ;end-w
            bcf     mflag,merr          ;w-offset
            skipz                       ;return merr for fail
            bsf     mflag,merr
            return
;************************************************************


;************************************************************
;.addresstest.                                              *
;slave                                                      *
;compare my address to the command address                  *
;                                                           *
;00 and ff always translate to 00                           *
;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01)
;************************************************************
scmmdat_    movlw   (cmmdbuffo & 0xff) + 3  ;less than 2 bytes can't be good
            subwf   cmmdbuffe,w
            bsf     mflag,merr
            skipnb
            return
;............................................................
            movlf   fsr,(cmmdbuffo & 0xff) + 1  ;translate command
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movff   bh,indf             ;msb first
            incf    fsr,f
            movff   bl,indf             ;lsb last
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
scmmdatt_   call    hex2bin_
            incf    al,w                ;if command is ff then make it 00
            skipnz
            movwf   al
            incf    seladdr,w           ;if seladdr is ff then make it 00
            skipnz
            movwf   seladdr
;............................................................
            movf    seladdr,w           ;test address in ram
            xorwf   al,w                ;compare to rs232 addresses
            bcf     mflag,merr
            skipz
            bsf     mflag,merr
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;.scmmdsack. .scmmdsnak.                                    *
;slave                                                      *
;send ack/nack                                              *
;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01)
;************************************************************
scmmdsack_  movlw   'a'
            goto    scmmdaknak_
scmmdsnak_  movlw   'n'
;------------------------------------------------------------
scmmdaknak_ movwf   tmp1
            movlw   '!'
            call    sciput_
            movf    seladdr,w
            call    scmmds8b_
            movf    tmp1,w              ;get saved a/n
            call    sciput_
            movlw   cr
            call    sciput_
            goto    scmmdsu_            ;clear for next command
;************************************************************
 endif
;************************************************************


;************************************************************
;.scmmdsrhdr.                                               *
;slave                                                      *
;transmit response header                                   *
;calling routine sends the rest                             *
;!aa        -seladdr converted to ascii hex                 *
;************************************************************
 if (_scmmdmode == 0x00) || (_scmmdmode == 0x01)
;************************************************************
scmmdsrhdr_
 if (_uartchksum == true)
            clrf    scitxcsum           ;start checksum (not used by 0x00)
 endif
            movlw   '!'
            call    sciput_
            movff   al,seladdr
            call    bin2hex_
            movf    bh,w
            call    sciput_
            movf    bl,w
            call    sciput_
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;.scmmdschdr.                                               *
;master                                                     *
;transmit command header + destination address              *
;calling routine sends the rest                             *
;$ww        -w converted to ascii hex                       *
;************************************************************
 if (_scmmdmode == 0x80) || (_scmmdmode == 0x81)
;************************************************************
scmmdschdr_
 if (_uartchksum == true)
            clrf    scitxcsum           ;not used by 0x80
 endif
            movwf   al                  ;save address for later
            movlw   '$'
            call    sciput_
            call    bin2hex_
            movf    bh,w
            call    sciput_
            movf    bl,w
            call    sciput_
            return
;************************************************************
 endif
;************************************************************


;************************************************************
;.scmmds4b.                                                 *
;translate w to 1 byte ascii and send                       *
;************************************************************
scmmds4b_   movwf   al
scmmds4bx_  call    bin2hex_
            goto    scmmds161_
;************************************************************
;.scmmds8b.                                                 *
;translate w to 2 bytes ascii and send                      *
;************************************************************
scmmds8b_   movwf   al
scmmds8bx_  call    bin2hex_
            goto    scmmds162_
;************************************************************
;.scmmds12b.                                                *
;translate al,ah to 3 bytes ascii and send                  *
;************************************************************
scmmds12b_  call    bin2hex_
            goto    scmmds163_
;************************************************************
;.scmmds16b.                                                *
;translate al,ah to 4 bytes ascii and send                  *
;************************************************************
scmmds16b_  call    bin2hex_
            movf    ch,w
            call    sciput_
scmmds163_  movf    cl,w
            call    sciput_
scmmds162_  movf    bh,w
            call    sciput_
scmmds161_  movf    bl,w
            call    sciput_
            return
;************************************************************


;************************************************************
;.scmmdsendr.                                               *   
;mode   actions                                             *
;-----------------------------------------------------------*
;0x00   send [cr]                                           *
;       clear for next remote command                       *
;-----------------------------------------------------------*
;0x40   convert checksum to ascii hex                       *
;       send ascii checksum                                 *
;       send [cr]                                           *
;       clear for next remote command                       *
;-----------------------------------------------------------*
;0x80   send [cr]                                           *
;************************************************************
 if (_scmmdmode == 0x00)                ;no check sum
scmmdsendr_ movlw   cr
            call    sciput_
            goto    scmmdsu_
 endif
;............................................................
 if (_scmmdmode == 0x01)                ;check summed ender
scmmdsendr_
 if (_uartchksum == true)
            movff   al,scitxcsum
            call    bin2hex_
            movf    bh,w
            call    sciput_
            movf    bl,w
            call    sciput_
 endif
            movlw   cr
            call    sciput_
            goto    scmmdsu_
 endif
;............................................................
 if (_scmmdmode == 0x80)                ;no check sum
scmmdsendr_ movlw   cr
            call    sciput_
            return
 endif
;************************************************************


;************************************************************
;.scmmddxlte.                                               *
;translate 4 bytes ascii hex to binary                      *
;fsr    ch  >> hex2bin (ah,al)                              *
;fsr+1  cl                                                  *
;fsr+2  bh                                                  *
;fsr+3  bl                                                  *
;                                                           *
;source 20  21  22  23          <for fsr = 0x20             *
;data   31  32  33  34          <register contents          *
;       |   |   |   |                                       *
;temp   ch  cl  bh  bl                                      *
;       31  32  33  34          <converted from ascii hex   *
;        \  /    \  /                                       *
;result   12      34            <converted to 8 bit binary  *
;dest    (ah)    (al)                                       *
;************************************************************
scmmddxlte_
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bsf     status,irp
 endif
            movff   ch,indf
            incf    fsr,f
            movff   cl,indf
            incf    fsr,f
            movff   bh,indf
            incf    fsr,f
            movff   bl,indf
 if (cmmdbuffo > 0xff)                  ;page 3/4 indf adjust
            bcf     status,irp
 endif
            call    hex2bin_
            return
;************************************************************

;************************************************************
 endif      ;end of block for entire scmmd code
;************************************************************

















;************************************************************
;.cpuinit.                                                  *
;************************************************************
;c74/f876/f877 ram initialize                               *
;************************************************************
 if (_initmode == 1) 
;************************************************************
;this code block performs initializaztion on reset and goto *
;0x0000 to give the same results whether a power on reset or*
;a software reset, and initializes all ram space to 0x00    *
;************************************************************
cpuinit     macro
            call    cpuinit_
            endm

meminit     macro
            call    meminit_
            endm
;************************************************************
;page 0 initialize
cpuinit_    rpage0
            clrf    ccp1con             ;pwm off/lsb's zeroed
            clrf    ccp2con
            clrf    ccpr1l              ;pwm duty cycles zeroed
            clrf    ccpr2l
            clrf    intcon              ;all interrupts off
            clrf    status              ;iopage 0
            clrf    pir1                ;slave port off
            clrf    pir2
            clrf    t1con               ;timer1 off
            clrf    t2con               ;timer2 off
            clrf    sspcon              ;sync serial port off-line
            clrf    rcsta               ;rx off
            clrf    adcon0              ;a/d converter off
            movlw   portadata           ;set initial data per equate file
            movwf   porta
            movlw   portbdata
            movwf   portb
            movlw   portcdata
            movwf   portc
;............................................................
 ifdef portd                            ;smaller processors don't have these ports
            movlw   portddata
            movwf   portd
 endif
 ifdef porte
            movlw   portedata
            movwf   porte
 endif
;************************************************************
;page 1 initialize
            rpage1
            clrf    option_reg
            bsf     option_reg,not_rbpu ;pull ups off
            clrf    pie1                ;peripheral interrupts off
            clrf    pie2                ;ccp2 int off
            movlw   0x03                ;reset power system interrupt flags
            movwf   pcon
            clrf    txsta               ;tx off
            movlw   0x06                ;all a/d config as digital i/o
            movwf   adcon1
            movlw   portamask           ;set port direction registers from
            movwf   portadir            ;  data set in equate file
            movlw   portbmask   
            movwf   portbdir
            movlw   portcmask
            movwf   portcdir
;............................................................
 ifdef portddir                         ;smaller processors don't have these ports
            movlw   portdmask
            movwf   portddir
 endif
 ifdef portedir
            movlw   portemask           ;0/1/2=input/psp=i/o
            andlw   0x07
            movwf   portedir
 endif
            rpage0
;************************************************************
;.meminit.                                                  *
;************************************************************
;memory initialize
meminit_
meminit01_  movlw   0x20                ;zero ram in page 0 and 1
            movwf   fsr
meminit01l_ bcf     fsr,7
            clrf    indf
            bsf     fsr,7
            clrf    indf
            incfsz  fsr,f               ;from skipz
            goto    meminit01l_
;............................................................
 if (_rpages == 4)
meminit23_  bsf     status,irp
            movlw   0x10                ;zero ram in page 2 and 3
            movwf   fsr
meminit23l_ bcf     fsr,7
            clrf    indf
            bsf     fsr,7
            clrf    indf
            incfsz  fsr,f               ;from skipz
            goto    meminit23l_
            bcf     status,irp
 endif
;............................................................
 if (_rpages == 1) || (_rpages == 3)
   error "Meminit configured for 2 or 4 pages of memory only"
 endif
            return
;************************************************************
 endif
;************************************************************












;************************************************************
 if (_initmode == 2)                    ;16f84 initialization
;************************************************************
 error "I really should do this some day"
;************************************************************
 endif
;************************************************************












;************************************************************
;.m25d.                                                     *
;************************************************************
 if (_m25d == true)
;************************************************************
;dummy 25cxxx code for systems without eeprom on spi but    *
;would still like to use the scmmd code block which has     *
;embeded eeprom command structures, will return w=0 for all *
;calls                                                      *
;************************************************************
m25         macro
            movlw   0x00
            endm

m25w        macro   
            movlw   0x00
            endm

m25c        macro   
            movlw   0x00
            endm

m25u        macro
            movlw   0x00
            endm

m25p        macro
            movlw   0x00
            endm

m25s        macro
            movlw   0x00
            endm
;************************************************************
m25addrh    equ     0x7f                ;high address 
m25addrl    equ     0x7f                ;low address
m25size     equ     0x7f                ;bytes to read/write for block operations
m25cmmd     equ     0x7f                ;command
;------------------------------------------------------------
wrbyte      equ     0x01                ;command translation
wrbyteinc   equ     0x81
wrbytedec   equ     0x41
rdbyte      equ     0x02
rdbyteinc   equ     0x82
rdbytedec   equ     0x42
wrblock     equ     0x04
rdblock     equ     0x08
unprotect   equ     0x10
protect     equ     0x50
rdstatus    equ     0xd0
;************************************************************
m25rdsr_                                ;all calls return w=0
m25protect_
m25uprotect_
m25control_
m25pagerdl_
m25pagerd_
m25pagewrl_
m25pagewr_
m25byterd_
m25bytewr_
m25parse_
m25wren_
m25busy_
m25_        movlw   0x00
            return
;************************************************************
 endif
;************************************************************








;************************************************************
;.m25.                                                      *
;************************************************************
 if (_m25 == true)
;************************************************************
;m25cmmd    w           command                             *
;-----------------------------------------------------------*
;0000 0000  xxxx xxxx   no command                          *
;ID00 0001  dddd dddd   wr w to (m25addrh-m25addrl) 10=incr *
;ID00 0010  dddd dddd   rd w fr (m25addrh-m25addrl) 01=decr *
;0000 0100  0ppp pppp   wr m25size bytes from (w)           *
;0000 1000  0ppp pppp   rd m25size bytes to (w)             *
;0001 0000  xxxx xxxx   unprotect entire array              *
;0101 0000  xxxx xxxx   protect entire array                *
;1101 0000  ssss ssss   rd status register to (w)           *
;                                                           *
;wrbyte                                                     *
;wrbyteinc                                                  *
;wrbytedec                                                  *
;rdbyte                                                     *
;rdbyteinc                                                  *
;rdbytedec                                                  *
;wrblock                                                    *
;rdblock                                                    *
;unprotect                                                  *
;protect                                                    *
;rdstatus                                                   *
;                                                           *
;block operations:                                          *
;   a block write must fall within the folowing address...  *
;   (xxxx xxxx xxxx 0000) to (xxxx xxxx xxxx 1111)          *
;   16 bytes at ...x 0001 = byte 1                          *
;               ...x 0010 = byte 2                          *
;                   .           .                           *
;                   .           .                           *
;                   .           .                           *
;               ...x 1111 = byte 15                         *
;               ...x 0000 = byte 16                         *
;                                                           *
;   a block read may cross page bounds without limit        *
;                                                           *
;pointer may be to either ram page, adjustment is automatic *
;  for both read and write                                  *
;************************************************************
m25         macro   a
            movlw   a
            call    m25_
            endm

m25w        macro   
            call    m25_
            endm

m25c        macro   a,b
            movlw   b
            movwf   m25cmmd
            movlw   a
            call    m25_
            endm

m25u        macro
            movlw   unprotect
            movwf   m25cmmd
            call    m25_
            endm

m25p        macro
            movlw   protect
            movwf   m25cmmd
            call    m25_
            endm

m25s        macro
            movlw   0xd0
            movwf   m25cmmd
            call    m25_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
m25addrh    equ     lastrams0           ;high address 
m25addrl    equ     m25addrh-1          ;low address
m25size     equ     m25addrl-1          ;bytes to read/write for block operations
m25cmmd     equ     m25size-1           ;command
lastrams0   set     m25cmmd-1
;------------------------------------------------------------
wrbyte      equ     0x01                ;command translation
wrbyteinc   equ     0x81
wrbytedec   equ     0x41
rdbyte      equ     0x02
rdbyteinc   equ     0x82
rdbytedec   equ     0x42
wrblock     equ     0x04
rdblock     equ     0x08
unprotect   equ     0x10
protect     equ     0x50
rdstatus    equ     0xd0
;************************************************************
m25_        clrwdt
            movwf   tmp1                ;save w for later
            movff   tmp0,m25size        ;save size for later
;............................................................
 if (_clock < 13000)
            call    spicon30_           ;fosc/4 to 12 mhz=3mhz max
 endif
 if (_clock >= 13000)
            call    spicon31_
 endif
;------------------------------------------------------------
m25busy_    bcf     m25cs               ;eeprom on, wait till done from last cycle
            movlw   0x05                ;read status register
            call    spioutin_
            call    spioutin_           ;dummy write to read data
            bsf     m25cs
            btfsc   sspbuff,0           ;wip=1=busy 
            goto    m25busy_            ;read status again until not busy
;------------------------------------------------------------
            btfsc   m25cmmd,0           ;decide whether or not to do a wren
            goto    m25wren_            ;write byte
            btfsc   m25cmmd,2
            goto    m25wren_            ;write block
            btfsc   m25cmmd,7
            goto    m25parse_           ;read status
            btfss   m25cmmd,4
            goto    m25parse_           ;protect/unprotect array
m25wren_    bcf     m25cs               ;eeprom on
            movlw   0x06                ;write enable command
            call    spioutin_
            bcf     sspcon,4
            nop
            bsf     m25cs
            nop
            bsf     sspcon,4
;------------------------------------------------------------
m25parse_   btfsc   m25cmmd,0           ;byte write
            goto    m25bytewr_
            btfsc   m25cmmd,1           ;byte read
            goto    m25byterd_
            btfsc   m25cmmd,2           ;page write
            goto    m25pagewr_
            btfsc   m25cmmd,3           ;page read
            goto    m25pagerd_
            btfsc   m25cmmd,4           ;memory control
            goto    m25control_
            return                      ;no valid commands/do nothing
;************************************************************
m25bytewr_  bcf     m25cs               ;eeprom on
            movlw   0x02                ;write data
            call    spioutin_
            movf    m25addrh,w          ;high address
            call    spioutin_
            movf    m25addrl,w          ;low address
            call    spioutin_
            movf    tmp1,w              ;data byte
            call    spioutin_
            bcf     sspcon,4
            nop
            bsf     m25cs               ;eeprom off to start write cycle
            nop
            bsf     sspcon,4
            goto    m25rdwrx_
;------------------------------------------------------------
m25byterd_  bcf     m25cs               ;eeprom on
            movlw   0x03                ;read command
            call    spioutin_
            movf    m25addrh,w          ;high address byte
            call    spioutin_
            movf    m25addrl,w          ;low address byte
            call    spioutin_
            call    spioutin_           ;dummy write to read data
            bsf     m25cs               ;eeprom off
;------------------------------------------------------------
m25rdwrx_   btfsc   m25cmmd,6           ;decrement address counter
            goto    m25rdwrxd_
            btfss   m25cmmd,7           ;increment address counter
            return                      ;no change to address counter
m25rdwrxi_  incf    m25addrl,f
            skipnz
            incf    m25addrh,f
            return
m25rdwrxd_  movf    m25addrl,f
            skipnz
            decf    m25addrh,f
            decf    m25addrl,f
            return
;************************************************************
m25pagewr_  bcf     m25cs               ;eeprom on
            movlw   0x02                ;write data
            call    spioutin_
            movf    m25addrh,w          ;high address
            call    spioutin_
            movf    m25addrl,w          ;low address
            call    spioutin_
            movf    tmp1,w              ;data pointer in ram, page 0
            movwf   fsr 
m25pagewrl_ clrwdt
            call    spifsrout_          ;write a byte
            incf    fsr,f               ;point to next byte
            decfsz  tmp0,f              ;loop till done
            goto    m25pagewrl_
            bcf     sspcon,4            ;clock = low
            nop
            bsf     m25cs               ;eeprom off to start write cycle
            nop
            bsf     sspcon,4
            return
;************************************************************
m25pagerd_  bcf     m25cs               ;eeprom on
            movlw   0x03                ;read command
            call    spioutin_
            movf    m25addrh,w          ;high address byte
            call    spioutin_
            movf    m25addrl,w          ;low address byte
            call    spioutin_
            movf    tmp1,w              ;data pointer in ram, page 0
            movwf   fsr             
m25pagerdl_ clrwdt
            call    spifsrin_           ;read and save a byte
            incf    fsr,f               ;point to next byte
            decfsz  tmp0,f              ;loop till done
            goto    m25pagerdl_
            bsf     m25cs               ;eeprom off
            return
;************************************************************
m25control_ btfsc   m25cmmd,7
            goto    m25rdsr_            ;read status register= 1101 xxxx
            btfsc   m25cmmd,6
            goto    m25protect_         ;protect entire array
;------------------------------------------------------------
m25uprotect_ bcf    m25cs               ;unprotect entire array/eeprom on
            movlw   0x01                ;write status register
            call    spioutin_
            movlw   0x00                ;all blocks unprotect
            call    spioutin_
            bcf     sspcon,4
            nop
            bsf     m25cs               ;start write cycle
            nop
            bsf     sspcon,4
            return
;------------------------------------------------------------
m25protect_ bcf     m25cs               ;eeprom on
            movlw   0x01                ;write status register
            call    spioutin_
            movlw   0x0c                ;all blocks protect
            call    spioutin_
            bcf     sspcon,4
            nop
            bsf     m25cs               ;start write cycle
            nop
            bsf     sspcon,4
            return
;------------------------------------------------------------
m25rdsr_    bcf     m25cs               ;eeprom on
            movlw   0x05                ;read status register
            call    spioutin_
            call    spioutin_           ;dummy write to read data
            bsf     m25cs               ;save status
            return
;************************************************************
 endif
;************************************************************










;************************************************************
;.p0832.                                                    *
;************************************************************
 if (_p0832 == true)
;************************************************************
p0832       macro
            call    p0832_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p0832_
;............................................................
 if (_clock <= 1000)
            call    spicon30_           ;fosc/4
 endif
 if (_clock > 1000) && (_clock <= 6000)
            call    spicon31_           ;fosc/16
 endif
 if (_clock > 6000)
            call    spicon32_           ;fosc/32
 endif
;............................................................
            movlw   0x06                ;start conversion, channel 0
            call    p0832c_
            movff   al,ah               ;save to ch0-high
            movlw   0x07                ;start conversion, channel 1
            call    p0832c_
            return
;************************************************************
p0832c_     bcf     p0832cs
            call    spioutin_           ;send channel address
            movlw   ((_clock/1000)+1)   ;delay before conversion s/h settle
            movwf   tmp0
p0832l1_    decfsz  tmp0,f
            goto    p0832l1_
            bcf     sspcon,4            ;1 clock for nul bit in
            movlw   ((_clock/1000)/2)+1
            movwf   tmp0
p0832l2_    decfsz  tmp0,f
            goto    p0832l2_
            bsf     sspcon,4
            call    spioutin_           ;dummy write to start read
            movwf   ah                  ;get 8 bit data and save
            bsf     p0832cs             ;cs=off
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.p1247.                                                    *
;************************************************************
 if (_p1247 == true)
;************************************************************
;single ended 4 channel conversion, 12 bits                 *
;                                                           *
;w          ch  dest                                        *
;xxxx xxx1  0   ah,al                                       *
;xxxx xx1x  1   bh,bl                                       *
;xxxx x1xx  2   ch,cl                                       *
;xxxx 1xxx  3   dh,dl                                       *
;************************************************************
p1247       macro   a
            movlw   a
            call    p1247_
            endm

p1247w      macro
            call    p1247_
            endm
;************************************************************
p1247_      movwf   tmp0                ;save conversion flag
;............................................................
;clock is 2mhx max on spi
 if (_clock <= 8000)    
            call    spicon30_           ;n/4  25us/conversion at 8mhz
 endif
 if (_clock > 8000)
            call    spicon31_           ;n/16
 endif
;............................................................
p1247ch0_   btfss   tmp0,0              ;convert channel 0?
            goto    p1247ch1_
            movlf   fsr,ah              ;point to save location
            movlw   0x9f
            call    p1247cnv_
p1247ch1_   btfss   tmp0,1              ;convert channel 1?
            goto    p1247ch2_
            movlf   fsr,bh              ;point to save location
            movlw   0xdf
            call    p1247cnv_
p1247ch2_   btfss   tmp0,2              ;convert channel 2?
            goto    p1247ch3_
            movlf   fsr,ch              ;point to save location
            movlw   0xaf
            call    p1247cnv_
p1247ch3_   btfss   tmp0,3              ;convert channel 3?
            goto    p1247chx_
            movlf   fsr,dh              ;point to save location
            movlw   0xef
            call    p1247cnv_
;............................................................
p1247chx_   movlf   tmp0,0x03           ;align bits
p1247l_     rrf     ah,f                ;shift right 3 to align bits
            rrf     al,f                ;3 instead of 4 due to clock polarity
            rrf     bh,f                ;  mismatch between pic spi and 1247
            rrf     bl,f
            rrf     ch,f
            rrf     cl,f
            rrf     dh,f
            rrf     dl,f
            decfsz  tmp0,f
            goto    p1247l_
            movlw   0x0f
            andwf   ah,f                ;mask out misc shifted in bits
            andwf   bh,f                ;  on all lsb's
            andwf   ch,f
            andwf   dh,f
            return
;************************************************************
p1247cnv_   bcf     p1247cs
            movwf   sspbuff             ;clock out control byte
            call    spiwait_
            clrf    sspbuff             ;clock out zeros
            call    spiwait_
            movff   indf,sspbuff        ;save msb to (reg)
            clrf    sspbuff
            call    spiwait_            
            decf    fsr,f               ;save lsb to (reg-1)
            movff   indf,sspbuff
            bsf     p1247cs
            return
;************************************************************
 endif
;************************************************************








;************************************************************
;.p1267.                                                    *
;************************************************************
 if (_p1267 == true)
;************************************************************
;write multiple ds1267's on spi port from data table in ram *
;                                                           *
;0x20   pot0                closest to spi port\            *
;0x21   pot1                                    >device 1   *
;0x22   stack select bit    0=pot0/1=pot1      /            *
;0x23   pot0                                   \            *
;0x24   pot1                                    >device 2   *
;0x25   stack select bit    0=pot0/1=pot1      /            *
;  *                                                        *
;  *                                                        *
;  *                                                        *
;0xnn-2 pot0                                   \            *
;0xnn-1 pot1                                    >device n   *
;0xnn   stack select bit    0=pot0/1=pot1      /            *
;                                                           *
;call with 0xnn in w, p1267chain=n                          *
;************************************************************
p1267       macro   a
            movlw   a
            call    p1267_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p1267_      addlw   (p1267chain*3)-1
            movwf   fsr                 ;pointer to last byte of pot data
            movlw   p1267chain          ;device counter
            movwf   tmp0
p1267ssbit_ movf    indf,w              ;get stack select bit and manually clock in
            movwf   tmp1
            bsf     sck                 ;clock=high
            bcf     sdo                 ;data=low
            clrf    sspcon              ;spi off
            bcf     p1267cs             ;1267 on, on from this point 
            bcf     sck
            btfsc   tmp1,0              ;stack select bit
            bsf     sdo
            bcf     sck                 ;manual clock
            bsf     sck
;............................................................
            call    spicon30_           ;normal spi mode
            decf    fsr,f
p1267pot1_  call    spifsrout_          ;write pot 1 of device n
            decf    fsr,f
p1267pot2_  call    spifsrout_          ;write pot 0 of device n
            decf    fsr,f
            decfsz  tmp0,f              ;do all devices in chain
            goto    p1267ssbit_
            bsf     p1267cs
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.p1288.                                                    *
;************************************************************
 if (_p1288 == true)
;************************************************************
;setup c/s direction register via cpuinit(portxmask)        *
;fosc/64 works up to 8mhz master clock                      *
;  use ltc1298 for operation to 12.8mhz master clock        *
;************************************************************
p1288       macro
            call    p1288_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p1288_                                  
;------------------------------------------------------------
 if (_clock <= 2000)                    ;clock polarity setup/clock source
            call    spicon31_           ;fosc/16
 else
            call    spicon32_           ;fosc/64
 endif
;------------------------------------------------------------
            movlw   0x0d                ;start conversion, channel 0
            call    p1288c_
            movff   ah,bh               ;save to ch0-high
            movff   al,bl               ;save to ch0-low
            movlw   0x0f                ;start conversion, channel 1
            call    p1288c_
            return
;************************************************************
p1288c_     bcf     p1288cs
            call    spioutin_           ;send channel address
            movlw   ((_clock/1000)+1)   ;delay before conversion s/h settle
            movwf   tmp0
p1288l1_    decfsz  tmp0,f
            goto    p1288l1_
            call    spioutin_           ;dummy write to start read
            movwf   bh                  ;get high 6 bits xxbb bbb and save
            call    spioutin_           ;dummy write to start read
            movwf   bl                  ;get low 6 bits bbbb bbxx and save
            bsf     p1288cs             ;cs=off
            rrf     bh,f                ;rotate out 3 crappy lsb
            rrf     bl,f
            rrf     bh,f
            rrf     bl,f
            rrf     bh,f
            rrf     bl,f
            movlw   0x0f
            andwf   bh,f                ;zero top nibble of high byte
            return
;************************************************************
 endif
;************************************************************














;************************************************************
;.p1451.                                                    *
;************************************************************
 if (_p1451 == true)
;************************************************************
;ah,al  msb,lsb 12 bits to write to dac                     *
;-----------------------------------------------------------*
;setup cs, ck, do direction via cpuinit(portxmask)          *
;provide the definitions below to operate                   *
;#define        p1451ck     rc3                             *
;#define        p1451do     rc5                             *
;#define        p1451cs     rc0                             *
;************************************************************
p1451       macro
            call    p1451_
            endm
;************************************************************
p1451_      clrf    sspcon              ;bit bang because 1451 does not like 16 bit
            bcf     p1451ck             ;transfers into 12 bit register
            nop                         ;clock must start low before cs
            bcf     p1451cs             ;enable part
;............................................................
            movlf   bl,4                ;4 msb bits
            swapf   ah,w                ;low 4 bits only
            call    p1451wr_
            movlf   bl,8
            movf    al,w
            call    p1451wr_
;............................................................
            bsf     p1451cs
            return
;------------------------------------------------------------
p1451wr_    movwf   bh                  ;save to temp register
p1451l_     bcf     p1451ck
            rlf     bh,f                ;rotate out bits
            skipc
            bcf     p1451do
            skipnc
            bsf     p1451do
            nop
            bsf     p1451ck
            decfsz  bl,f
            goto    p1451l_
            return
;************************************************************
 endif
;************************************************************














;************************************************************
;.p145170.                                                  *
;************************************************************
 if (_p145170 == true)
;************************************************************
;write all registers of mc145170 pll from ram indexed by w  *
;data in ascending consecutive ram addresses                *
;example, w=0x20                                            *
;0x20   r-h     r divider, 15 bits, 0x0001, 0x0005 to 0x7fff*
;0x21   r-l                                                 *
;0x22   n-h     n divider, 16 bits, 0x0028 to 0xffff        *
;0x23   n-l                                                 *
;0x24   c       control register                            *
;                                                           *
;1 line control:    p145170cs   standard chip select        *
;                                                           *
;chip select line pulled up                                 *
;************************************************************
p145170     macro   a
            movlw   a
            call    p145170_
            endm

p145170i    macro
            call    p145170i_
            endm
;************************************************************
p145170i_   bcf     sspcon,sspen        ;h/w spi off
            bcf     sdo
            nop
            bcf     sck
            nop
            bsf     p145170cs           ;low level reset
            movlw   1
            call    delayms_
            call    p145170ick_
            call    p145170ick_
            call    p145170ick_
            call    p145170ick_
            movlw   1
            call    delayms_
            bcf     p145170cs
            movlw   1
            call    delayms_
            call    p145170ick_
            call    p145170ick_
            call    p145170ick_
            bsf     sdo
            call    p145170ick_
            bcf     sdo
            call    p145170ick_
            movlw   1
            call    delayms_
            bsf     p145170cs
            return
;------------------------------------------------------------
p145170ick_ bsf     sck
            nop
            bcf     sck
            return
;************************************************************
p145170_    movwf   fsr                 ;save data pointer
            bcf     sspcon,sspen        ;h/w spi off
            call    p145170d_
;............................................................
            bcf     p145170cs           ;cs=low/write r register
            call    p145170d_
            call    p145170cd_          ;first byte is filler
            call    p145170cd_          ;8 msb of r register
            incf    fsr,f
            call    p145170cd_          ;8 lsb of r register
            bsf     p145170cs
;............................................................
            call    p145170d_
            bcf     p145170cs           ;cs=low/write n register            
            incf    fsr,f
            call    p145170cd_          ;8 msb of n register
            incf    fsr,f
            call    p145170cd_          ;8 lsb of n register
            bsf     p145170cs
;............................................................
            call    p145170d_
            bcf     p145170cs           ;cs=low/write c register            
            incf    fsr,f
            call    p145170cd_          ;8 bit c register
;............................................................
            call    p145170d_
            bsf     p145170cs
            call    p145170d_
            return
;************************************************************
p145170cd_  movlf   tmp1,8              ;8 bits
p145170cdl_ rlf     indf,f              ;bit out
            skipnc
            bsf     sdo
            skipc
            bcf     sdo
            nop
            bsf     sck
            nop
            bcf     sck
            decfsz  tmp1,f
            goto    p145170cdl_
            rlf     indf,f              ;return to original position
            return
;************************************************************
p145170d_   movlw   16
            movwf   tmp0
p145170l_   decfsz  tmp0,f
            goto    p145170l_
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.p165.                                                     *
;************************************************************
 if (_p165 == true)
;************************************************************
;read multiple 74165 parallel in/serial out ics in chain    *
;w is unit to read, value returned in w                     *
;primary i/o bus, on board peripherals                      *
;************************************************************
p165        macro   a
            movlw   a
            call    p165_
            endm

p165w       macro
            call    p165_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p165_       movwf   tmp0                ;read piso (w) and return value in w
            call    spicon30_
            bcf     p165cs
p165l_      call    spioutin_           ;read port closest to pic first (highest priority)
            decfsz  tmp0,f              ;return last byte read in w
            goto    p165l_
            bsf     p165cs
            return
;************************************************************
 endif
;************************************************************











;************************************************************
;.p165b.                                                    *
;************************************************************
 if (_p165b == true)
;************************************************************
;read block of 74165 parallel in/serial out ics in chain    *
;w is start address to read block into                      *
;primary i/o bus, on board peripherals                      *
;************************************************************
p165b       macro   a
            movlw   a
            call    p165b_
            endm

p165bw      macro
            call    p165b_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p165b_      movwf   fsr                 ;read piso chain and return values in (fsr)
            movlf   tmp0,p165chain
            call    spicon30_
            bcf     p165cs
p165bl_     call    spifsrin_
            incf    fsr,f
            decfsz  tmp0,f
            goto    p165bl_
            bsf     p165cs
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.p165s.                                                    *
;************************************************************
 if (_p165s == true)
;************************************************************
;read multiple 74165 parallel in/serial out ics in chain    *
;w is unit to read, value returned in w                     *
;secondary i/o bus, off board peripherals                   *
;************************************************************
p165s       macro   a
            movlw   a
            call    p165s_
            endm

p165sw      macro
            call    p165s_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p165s_      movwf   tmp0                ;read piso (w) and return value in w
            call    spicon30_
            bcf     p165scs
p165sl_     call    spioutin_           ;read port closest to pic first (highest priority)
            decfsz  tmp0,f              ;return last byte read in w
            goto    p165sl_
            bsf     p165scs
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.p165sb.                                                   *
;************************************************************
 if (_p165sb == true)
;************************************************************
;read block of 74165 parallel in/serial out ics in chain    *
;w is start address to read block into                      *
;secondary i/o bus, off board peripherals                   *
;************************************************************
p165sb      macro   a
            movlw   a
            call    p165sb_
            endm

p165sbw     macro
            call    p165sb_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p165sb_     movwf   fsr                 ;read piso chain and return values in (fsr)
            movlf   tmp0,p165schain
            call    spicon30_
            bcf     p165scs
p165sbl_    call    spifsrin_
            incf    fsr,f
            decfsz  tmp0,f
            goto    p165sbl_
            bsf     p165scs
            return
;************************************************************
 endif
;************************************************************














;************************************************************
;.p165x.                                                    *
;************************************************************
 if (_p165x == true)
;************************************************************
;read single 74165 parallel in/serial out ic                *
;value returned in w                                        *
;uses split control lines                                   *
;ckinh      initialize high                                 *
;shnld      initialize low                                  *
;...........................................................*
;#define    p165ckinh   rc1             ;pin 15 of 74165    *
;#define    p165shnld   rb5             ;pin 1 of 74165     *
;************************************************************
p165        macro
            call    p165_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p165_       call    spicon30_
;............................................................
            bcf     p165ckinh
            nop
            bsf     p165shnld
;............................................................
            call    spioutin_           ;read port
;............................................................
            bcf     p165shnld
            nop
            bsf     p165ckinh
            return
;************************************************************
 endif
;************************************************************








;************************************************************
;.p165d.                                                    *
;************************************************************
 if (_p165d == true)
;************************************************************
;dummy 74165, always returns 0 in w                         *
;************************************************************
p165        macro   a
            movlw   0x00
            endm

p165w       macro
            movlw   0x00
            endm
;************************************************************
p165_       movlw   0x00
            return
;************************************************************
 endif
;************************************************************











;************************************************************
;.p25600.                                                   *
;************************************************************
 if (_p25600 == true)
;************************************************************
;2025600 lens controller driver                             *
;                                                           *
;command in w                                               *
;data out in al,ah                                          *
;data in in al,ah                                           *
;                                                           *
;       data-send       data-read                           *
;cmmd   al      ah      al      ah      function            *
;---------------------------------------------------------- *
;00     --      --      focus   zoom    read absolute pos   *
;01     zoom    --      --      --      write zoom abs      *
;02     focus   --      --      --      write focus abs     *
;03     zoomspd focspd  --      --      write zoom/foc speed*
;04     --      --      --      --      stop zoom           *
;05     --      --      --      --      stop focus          *
;06     delay   --      --      --      write delay         *
;************************************************************
p25600      macro   a
            movlw   a
            call    p25600_
            endm

p25600w     macro
            call    p25600_
            endm
;************************************************************
p25600dly   equ     0x10
_spiutil    set     true
;************************************************************
p25600_     movwf   tmp0                ;save w for later, command
            call    p25600td_
            call    spicon32_
            bcf     p25600cs
            call    p25600td_           ;delay
;------------------------------------------------------------
            movf    tmp0,w              ;send command
            call    spioutin_
            call    p25600td_
;------------------------------------------------------------
            incf    tmp0,f              ;branch block
            decf    tmp0,f
            skipnz
            goto    p25600_0_           ;read absolute
            decf    tmp0,f
            skipnz
            goto    p25600_1_           ;write zoom abs
            decf    tmp0,f
            skipnz
            goto    p25600_2_           ;write focus abs
            decf    tmp0,f
            skipnz
            goto    p25600_3_           ;write zoom/focus speed
            decf    tmp0,f
            skipnz
            goto    p25600_4_           ;stop zoom
            decf    tmp0,f
            skipnz
            goto    p25600_5_           ;stop focus
            decf    tmp0,f
            skipnz
            goto    p25600_6_           ;write delay
            return
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx           
p25600_0_   movlw   0x00                ;read focus/zoom absolute
            call    spioutin_
            movwf   al
            movlw   0x00
            call    spioutin_
            movwf   ah
            goto    p25600x_
;------------------------------------------------------------
p25600_1_                               ;write zoom absolute
p25600_2_                               ;write focus absolute
p25600_6_   movf    al,w                ;write delay
            call    spioutin_
            goto    p25600x_
;------------------------------------------------------------
p25600_3_   movf    al,w                ;write zoom/focus speeds
            call    spioutin_
            call    p25600td_
            movf    ah,w
            call    spioutin_
            goto    p25600x_
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
p25600_4_                               ;zoom stop
p25600_5_                               ;focus stop
p25600x_    bsf     p25600cs            ;terminate process
            return
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
p25600td_   movlf   tmp1,p25600dly      ;10us time delay at 8mhz
p25600tdl_  decfsz  tmp1,f
            goto    p25600tdl_
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.p3100.                                                    *
;************************************************************
 if (_p3100 == true)
;************************************************************
;max3100 uart controller, manual spi only                   *
;           uart clock                                      *
;           14.7456/8    ---------                          *
;            7.3728/4    14.7456/4                          *
;            3.6864/2     7.3728/2                          *
;  baud      1.8432mhz    3.6864mhz                         *
;-----------------------------------------------------------*
;   300*        0x0f        ----    *standard baud rates    *
;   600*        0x0e        0x0f                            *
;   900         0x07        ----                            *
;  1200*        0x0d        0x0e                            *
;  1800         0x06        0x07                            *
;  2400*        0x0c        0x0d                            *
;  3600         0x05        0x06                            *
;  4800*        0x0b        0x0c                            *
;  7200         0x04        0x05                            *
;  9600*        0x0a        0x0b                            *
; 14400         0x03        0x04                            *
; 19200*        0x09        0x0a                            *
; 28800         0x02        0x03                            *
; 38400*        0x08        0x09                            *
; 57600*        0x01        0x02                            *
; 76800         ----        0x08                            *
;115200*        0x00        0x01                            *
;230400*        ----        0x00                            *
;************************************************************
p3100init   macro
            call    p3100init_
            endm

p3100get    macro
            call    p3100get_
            endm

p3100put    macro   a
            movlw   a
            call    p3100put_
            endm

p3100putw   macro
            call    p3100put_
            endm
;************************************************************
p3100init_  movlf   tmp0,0xc4           ;irq is receive not empty
            movlf   tmp1,p3100brg       ;uart is 9600 baud
            call    p3100xfer_          ;write data
;............................................................
p3100initl_ clrf    tmp0                ;loop til rx buff empty
            clrf    tmp1
            call    p3100xfer_          ;flush fifo
            btfsc   tmp0,7
            goto    p3100initl_
            movlf   tmp0,0x86           ;clear /rts pin
            clrf    tmp1
            call    p3100xfer_
            movlf   tmp0,0x82           ;transmit enable
            call    p3100xfer_
            return
;************************************************************
;byte returned in w if available                            *
;************************************************************
p3100get_   bsf     mflag,mzero         ;flag as no bytes avail
            clrf    tmp0                ; mnz=byte/mz=no byte
            clrf    tmp1
            call    p3100xfer_
            btfss   tmp0,7
            return
            bcf     mflag,mzero         ;flag as bytes avail
            movf    tmp1,w              ;return any byte in w
            return
;************************************************************
;w is byte to xmit                                          *
;tmp3, temp storage for byte to xmit                        *
;************************************************************
p3100put_   movwf   tmp3
p3100putl_  movlf   tmp0,0x40           ;read txbuff status and write when ready
            clrf    tmp1
            call    p3100xfer_
            btfss   tmp0,6              ;1=tx buffer ready
            goto    p3100putl_          ;loop til ready
            movlf   tmp0,0x82
            movff   tmp1,tmp3
            call    p3100xfer_
            return
;************************************************************
;write 2 bytes to spi/read 2 bytes                          *
;tmp0       msb to write, msb read                          *
;tmp1       lsb to write, lsb read                          *
;tmp2       bit counter                                     *
;************************************************************
p3100xfer_  bcf     sspcon,5            ;spi pins set as i/o
            bcf     sck                 ;initialize clock  low
            nop
            bcf     p3100cs             ;enable uart
            movlf   fsr,tmp0            ;write msb
            call    p3100byte_
            movlf   fsr,tmp1            ;write lsb
            call    p3100byte_
            bsf     p3100cs             ;disable uart
            return
;------------------------------------------------------------
p3100byte_  movlf   tmp2,8              ;bit counter
;............................................................
p3100bytel_ ccarry
            btfsc   sdi
            scarry
            rlf     indf,f
            bcf     sdo
            skipnc
            bsf     sdo
            nop
            bsf     sck
            nop
            bcf     sck
            decfsz  tmp2,f
            goto    p3100bytel_
            return
;************************************************************
 endif
;************************************************************












;************************************************************
;.p509.                                                     *
;************************************************************
 if (_p509 == true)
;************************************************************
;max509/max510 quad 8 bit dac                               *
;setup c/s direction register via cpuinit(portxmask)        *
;works up to 40mhz master clock                             *
;...........................................................*
;p509       dac,(data)                                      *
;...........................................................*
;p509w                                                      *
;fsr        ram address of dac data                         *
;w          dac to write, 00-03                             *
;...........................................................*
;p509a      data                                            *
;           write all dacs with data                        *
;...........................................................*
;p509aw                                                     *
;w          data to write into all dacs                     *
;...........................................................*
;p509c                                                      *
;(clear all dacs to 0x00)                                   *
;...........................................................*
;p509i      dac,data                                        *
;...........................................................*
;p509iw                                                     *
;tmp2       dac data                                        *
;w          dac to write, 00-03                             *
;************************************************************
p509        macro   a,b
            movlf   fsr,b
            movlw   a
            call    p509_
            endm

p509w       macro
            call    p509_
            endm

p509a       macro   a
            clrf    tmp0
            movlf   tmp1,a
            call    p509x_
            endm

p509aw      macro
            clrf    tmp0
            movwf   tmp1
            call    p509x_
            endm

p509c       macro
            clrf    tmp0
            clrf    tmp1
            call    p509x_
            endm

p509i       macro   a,b
            movlf   fsr,tmp2
            movlf   tmp2,b
            movlw   a
            call    p509_
            endm

p509iw      macro
            movwf   tmp0
            movlf   fsr,tmp2
            call    p509y_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p509_       movwf   tmp0                ;build control word
p509y_      ccarry  
            rlf     tmp0,f              ;shift address
            rlf     tmp0,f
            bsf     tmp0,0              ;add load and write bits
            bsf     tmp0,1
            movff   tmp1,indf           ;get data
;------------------------------------------------------------
p509x_      call    spicon30_           ;clock polarity setup/clock source
;------------------------------------------------------------
            bcf     p509cs              ;enable dac
;............................................................
            movf    tmp0,w              ;write control byte
            call    spioutin_
            movf    tmp1,w              ;write data
            call    spioutin_
;............................................................
            bsf     p509cs              ;disable dac
            return
;************************************************************
 endif
;************************************************************




;************************************************************
;.p534.                                                     *
;************************************************************
 if (_p534 == true)
;************************************************************
;max533/max534 quad 8 bit dac                               *
;setup c/s direction register via cpuinit(portxmask)        *
;works up to 40mhz master clock                             *
;...........................................................*
;p534       dac,(data)                      dac is 00 to 03 *
;...........................................................*
;p534w                                                      *
;fsr        ram address of dac data                         *
;w          dac to write, 00-03                             *
;...........................................................*
;p534a      data                                            *
;           write all dacs with data                        *
;...........................................................*
;p534aw                                                     *
;w          data to write into all dacs                     *
;...........................................................*
;p534c                                                      *
;(clear all dacs to 0x00)                                   *
;...........................................................*
;p534i      dac,data                                        *
;...........................................................*
;p534iw                                                     *
;tmp2       dac data                                        *
;w          dac to write, 00-03                             *
;...........................................................*
;p534ii                                                     *
;tmp2       dac data                                        *
;tmp3       dac to write, 00-03                             *
;************************************************************
p534        macro   a,b
            movlf   fsr,b
            movlw   a
            call    p534_
            endm

p534w       macro
            call    p534_
            endm

p534a       macro   a
            movlf   tmp1,a              ;data is immediate
            movlf   tmp0,0x08           ;control is all
            call    p534x_
            endm

p534aw      macro
            movwf   tmp1                ;data is w
            movlf   tmp0,0x08           ;control is all
            call    p534x_
            endm

p534c       macro
            clrf    tmp1                ;data is 0x00
            movlf   tmp0,0x08           ;control is all
            call    p534x_
            endm

p534i       macro   a,b
            movlf   fsr,tmp2
            movlf   tmp2,b
            movlw   a
            call    p534_
            endm

p534iw      macro
            movwf   tmp0
            movlf   fsr,tmp2
            call    p534y_
            endm

p534ii      macro
            movff   tmp0,tmp3
            movlf   fsr,tmp2
            call    p534y_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p534_       movwf   tmp0                ;build control word
p534y_      ccarry  
            rlf     tmp0,f              ;shift address
            rlf     tmp0,f
            bsf     tmp0,0              ;add load and write bits
            bsf     tmp0,1
            movff   tmp1,indf           ;get data
;------------------------------------------------------------
p534x_      call    spicon30_           ;clock polarity setup/clock source
;------------------------------------------------------------
            bcf     p534cs              ;enable dac
;............................................................
            movf    tmp0,w              ;write control byte
            call    spioutin_
            movf    tmp1,w              ;write data
            call    spioutin_
;............................................................
            bsf     p534cs              ;disable dac
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.p595.                                                     *
;************************************************************
 if (_p595 == true)
;************************************************************
;write multiple 74595 serial in/parallel out ics in chain   *
;primary i/o bus, on board peripherals                      *
;                                                           *
;chain written last unit first, memory index is lowest      *
;  ram address                                              *
;************************************************************
p595        macro   a
            movlw   a
            call    p595_           
            endm

p595w       macro
            call    p595_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p595_       addlw   p595chain-1         ;write all ports on sipo chain from data
            movwf   fsr                 ;  starting at (w)  
            call    spicon30_           ;all outputs are latched at same time   
            bcf     p595cs              ;  which appears as pio  
            movlw   p595chain           ;device counter
            movwf   tmp0
p595l_      call    spifsrout_          ;last byte of chain first
            decf    fsr,f
            decfsz  tmp0,f
            goto    p595l_
            bsf     p595cs
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.p595s.                                                    *
;************************************************************
 if (_p595s == true)
;************************************************************
;write multiple 74595 serial in/parallel out ics in chain   *
;secondary i/o bus, off board peripherals                   *
;************************************************************
p595s       macro   a
            movlw   a
            call    p595s_          
            endm

p595sw      macro
            call    p595s_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p595s_      addlw   p595schain-1        ;write all ports on sipo chain from data
            movwf   fsr                 ;  starting at (w)      
            call    spicon30_           ;all outputs are latched at same time   
            bcf     p595scs             ;  which appears as pio  
            movlw   p595schain          ;device counter
            movwf   tmp0
p595sl_     call    spifsrout_          ;last byte of chain first
            decf    fsr,f
            decfsz  tmp0,f
            goto    p595sl_
            bsf     p595scs
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.p5951.                                                    *
;************************************************************
 if (_p5951 == true)
;************************************************************
;write a single 74595 serial in/parallel out ic             *
;p5951      0x00    ;writes immediate value 0x00 to 74595   *
;p5951w             ;writes value in w to 74595             * 
;************************************************************
p5951       macro   a
            movlw   a
            call    p5951_          
            endm

p5951w      macro
            call    p5951_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p5951_      clrf    sspcon              ;write w to spi port
            bsf     sspcon,4            ;do port setup manually to preserve w
            bsf     sspcon,5
            bcf     p595cs
            call    spioutin_
            bsf     p595cs
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.p1801.                                                    *
;************************************************************
 if (_p1801 == true)
;************************************************************
;write dual audio pot                                       *
;al     pot 0 data                                          *
;ah     pot 1 data                                          *
;       xmdd dddd                                           *
;       x   dont care                                       *
;       m   mute    1=mute/0=normal                         *
;       dd  6 bit pot data                                  *
;chip select active high                                    *
;data out lsb first                                         *
;                                                           *
;00 sets pot to rmax                                        *
;3f sets pot to rmin                                        *
;40 sets pot to mute                                        *
;                                                           *
;al,ah,bl,bh,cl                                             *
;************************************************************
p1801w      macro
            call    p1801_          
            endm
;************************************************************
;_spiutil   set     true                ;enable spi utils
;************************************************************
p1801_      bcf     sspcon,5
            movff   bl,al               ;working copy, no al/ah change
            movff   bh,ah
            bcf     p1801ck
            nop
            bsf     p1801cs             ;chip select (high)
            nop
            movlf   cl,8
p1801l1_    rrf     bl,f                ;pot0
            call    p1801bit_
            decfsz  cl,f
            goto    p1801l1_
            movlf   cl,8
p1801l2_    rrf     bh,f                ;pot1
            call    p1801bit_
            decfsz  cl,f
            goto    p1801l2_
            nop
            bcf     p1801cs             ;
            return
;............................................................
p1801bit_   skipc
            bcf     p1801da
            skipnc
            bsf     p1801da
            nop
            bcf     p1801ck
            nop
            bsf     p1801ck
            return
;************************************************************
 endif
;************************************************************










;************************************************************
;.p6355.                                                    *
;************************************************************
 if (_p6355 == true)
;************************************************************
;njr real time clock                                        *
;                                                           *
;************************************************************
p6355rd     macro
            call    p6355rd_            
            endm

p6355wr     macro
            call    p6355wr_
            endm
;************************************************************
_spiutil    set     true                ;enable spi utils
;************************************************************
p6355rd_    movlf   fsr,al
            call    spicon31_           ;/16
            rpage1
            bsf     rc5dir
            rpage0  
            bsf     p6355cs
            nop
            bcf     p6355io
            movlf   tmp0,7  
p6355rdl_   call    spifsrin_
            incf    fsr,f
            decfsz  tmp0,f
            goto    p6355rdl_
            bcf     p6355cs
            nop
            bsf     p6355io
            return
;************************************************************
p6355wr_    movlf   fsr,al
            call    spicon31_           ;/16
            bsf     p6355cs
            movlf   tmp0,7  
p6355wrl_   call    spifsrout_
            incf    fsr,f
            decfsz  tmp0,f
            goto    p6355wrl_
            bcf     p6355cs
            return
;************************************************************
 endif
;************************************************************

















;************************************************************
;.spiutil.                                                  *
;************************************************************
 if (_spiutil == true)
;************************************************************
;spi interface utility subroutines                          *
;************************************************************
spioutin    macro
            call    spioutin_
            endm
            
spifsrin    macro
            call    spifsrin_
            endm

spifsrout   macro
            call    spifsrout_
            endm
;************************************************************
;write w to sspcon                                          *
;************************************************************
spicon30_   movlw   0x30                ;fosc/4
            goto    spiconx_
spicon31_   movlw   0x31                ;fosc/16
            goto    spiconx_
spicon32_   movlw   0x32                ;fosc/64
spiconx_    movwf   sspcon
            return
;************************************************************
;write w to ssp, wait till sent, return with data in        *
;************************************************************
spioutin_   movwf   sspbuff             ;write w to spi buffer
spiwait_    rpage1                      ;just wait entry point  
spioutinl_  btfss   sspstat,bf          ;loop till all bits in
            goto    spioutinl_
            rpage0
            movf    sspbuff,w           ;return with in data in w
            return
;************************************************************
;write indexed byte to ssp buffer and wait til transfered   *
;************************************************************
spifsrout_  movf    indf,w  
            movwf   sspbuff
            goto    spiwait_
;************************************************************
;read a byte from ssp buffer and save to indexed location   *
;************************************************************
spifsrin_   movwf   sspbuff             ;dummy write to read data
            rpage1  
spifsrinl_  btfss   sspstat,bf          ;loop till all bits in
            goto    spifsrinl_
            rpage0
            movf    sspbuff,w           ;save byte to indf pointer
            movwf   indf
            return
;************************************************************
 endif
;************************************************************















;************************************************************
;.p1721.                                                    *
;************************************************************
 if (_p1721 == true)
;************************************************************
;p1721iw    (initialize)                                    *
;--------------------------------------------------         *
;al         address of ds1721 to initialize                 *
;               xxxxxaaa                                    *
;               xxxxx   dont care                           *
;               aaa     device address, hardwired 0-7       *
;                                                           *
;ah         configuration byte                              *
;               xxxxrrpm                                    *
;               xxxx    dont care                           *
;               rr      resolution  00  9bit    (0.15s)     *
;                                   01  10bit   (0.30s)     *
;                                   10  11bit   (0.60s)     *
;                                   11  12bit   (1.20s)     *
;               p       thstat pol  0   active low          *
;                                   1   active high         *
;               m       convertmode 0   continuous          *
;                                   1   1 shot              *
;                                                           *
;p1721i a,b                                                 *
;--------------------------------------------------         *
;a          same as al                                      *
;b          same as bl                                      *
;                                                           *
;p1721w     (read)                                          *
;--------------------------------------------------         *
;w          address of ds1721 to read                       *
;               xxxxxaaa                                    *
;               xxxxx   dont care                           *
;               aaa     device address, hardwired 0-7       *
;                                                           *
;al         lsb of temp reading                             *
;ah         msb of temp reading                             *
;                                                           *
;p1721  a                                                   *
;---------------------------------------------------        *
;a          same as w                                       *
;                                                           *
;see i2cutil for port setup details                         *
;************************************************************
_i2cutil    set     true
;************************************************************
p1721iw     macro
            call    p1721i_
            endm

p1721i      macro   a,b
            movlf   al,a
            movlf   ah,b
            call    p1721i_
            endm

p1721w      macro
            call    p1721_
            endm

p1721       macro   a
            movlw   a
            call    p1721_
            endm
;************************************************************
p1721i_     ccarry                      ;build address
            rlf     al,w
            iorlw   0x90
            movwf   dh                  ;save address for later
            call    i2cstart_           ;initialize sensor
            movf    dh,w
            call    i2cwrite_
            movlw   0xac                ;write config
            call    i2cwrite_
            movf    ah,w                ;control byte
            call    i2cwrite_
            call    i2cstop_
            nop
            call    i2cstart_
            movf    dh,w
            call    i2cwrite_
            movlw   0x51                ;initiate conversions
            call    i2cwrite_
            call    i2cstop_
            return
;************************************************************
p1721_      ccarry                      ;build address
            iorlw   0x48                ;will be 0x90 after rotate
            movwf   dh
            rlf     dh,f
            call    i2cstart_
            movf    dh,w
            call    i2cwrite_
            movlw   0xaa                ;read temperature
            call    i2cwrite_
            call    i2cstop_
            nop
            call    i2cstart_           ;repeat start
            bsf     dh,0                ;set for read
            movf    dh,w
            call    i2cwrite_
            call    i2cread_            ;read msb
            movwf   ah                  
            call    i2cack_
            call    i2cread_            ;read lsb
            movwf   al
            call    i2cnak_
            call    i2cstop_
;............................................................
            movlf   dh,4                ;divide by 16
p1721l_     ccarry
            rrf     ah,f
            rrf     al,f
            decfsz  dh,f
            goto    p1721l_
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.p1803.                                                    *
;************************************************************
 if (_p1803 == true)
;************************************************************
;p1803w                                                     *
;--------------------------------------------------         *
;al         address of ds1803 to write                      *
;               cxxxxaaa                                    *
;               c       channel to write, 0 or 1            *
;               xxxx    dont care                           *
;               aaa     device address, hardwired 0-7       *
;ah         value to write to pot, 00-ff                    *
;                                                           *
;p1803  a,b                                                 *
;p1803  cxxxxaaa,value                                      *
;---------------------------------------------------        *
;a          same as al                                      *
;b          same as ah                                      *
;                                                           *
;see i2cutil for port setup details                         *
;************************************************************
_i2cutil    set     true
;************************************************************
p1803w      macro
            call    p1803_
            endm

p1803       macro   a,b
            movlf   al,a
            movlf   ah,b
            call    p1803_
            endm
;************************************************************
p1803_      call    i2cstart_
            rlf     al,w                ;build address
            andlw   0x0e                ;strip bits
            iorlw   0x50                ;add 1803 upper 4 + write bit
            call    i2cwrite_           ;write address
            movlw   0xaa
            btfss   al,7                ;select channel
            movlw   0xa9
            call    i2cwrite_
            movf    ah,w
            call    i2cwrite_
            call    i2cstop_
            return
;************************************************************
 endif
;************************************************************










;************************************************************
;.lm75.                                                     *
;************************************************************
 if (_lm75 == true)
;************************************************************
;temperture returned in ah,al                               *
;9 bits, 0.5 degree c/count                                 *
;-55 to +125 range                                          *
;                                                           *
;conversion time is 260us at 7.34mz clock                   *
;conversion time is scaleable from >0 to 20mhz              *
;                                                           *
;ah         AL                                              *
;0000 0000  1111 1010   +125.0                              *
;0000 0000  0011 0010   + 25.0                              *
;0000 0000  0000 0001   +  0.5                              *
;0000 0000  0000 0000      0.0                              *
;0000 0001  1111 1111   -  0.5                              *
;0000 0001  1100 1110   - 25.0                              *
;0000 0001  1001 0010   - 55.0                              *
;************************************************************
_i2cutil    set     true
;************************************************************
lm75p       macro   a
            movlw   a
            call    lm75p_
            endm

lm75pw      macro
            call    lm75p_
            endm

lm75r16     macro
            call    lm75r16_
            endm
;************************************************************
;shft addr lt 1/mask    1001aaad    aaa     3 bit address   *
;                                   d       1=read/0=write  *
;************************************************************
lm75rmask   equ     (0x91 | ((lm75addr << 1) & 0xe0))
lm75wmask   equ     (0x90 | ((lm75addr << 1) & 0xe0))
;************************************************************
lm75p_      movwf   al                  ;pointer in w, save for later
            call    i2cstart_
            movlw   lm75wmask           ;write unit address+write
            call    i2cwrite_
            movf    al,w                ;write pointer address
            call    i2cwrite_
            call    i2cnak_
            call    i2cstop_
            return
;************************************************************
lm75r16_    call    i2cstart_           ;read 16bit data from current pointer
            movlw   lm75rmask           ;write unit address+read
            call    i2cwrite_
            call    i2cread_            ;read msb (high 8 bits)
            movwf   al                  ;save msb
            call    i2cack_
            call    i2cread_            ;read lsb (low 1 bit)
            movwf   ah                  ;save lsb
            call    i2cnak_
            call    i2cstop_
            rlf     ah,f                ;rotate bits into correct locations
            rlf     al,f
            rlf     ah,f
            movlw   0x01
            andwf   ah,f
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.i2cutil.                                                  *
;************************************************************
 if (_i2cutil == true)
;************************************************************
;i2c routines, standard mode master                         *
;100khz max data rate                                       *
;                                                           *
;address/data sent and returned in w                        *
;sda    i2csda  must be ra4 output, defined here,           *
;               dir=0=output, data=1 in main setup          *
;                                                           *
;scl    i2cscl  any other pin, defined in setup block       *
;               dir=0=output, data=1                        *
;                                                           *
;i2cstart   start bit                                       *
;i2cstop    stop bit                                        *
;i2cwrite   write 8 bits                                    *
;i2cread    read 8 bits                                     *
;i2cack                                                     *
;i2cnak                                                     *
;************************************************************
#define     i2csda  ra4
;************************************************************
i2cwrite    macro   a
            movlw   a
            call    i2cwrite_
            endm

i2cwritew   macro   
            call    i2cwrite_
            endm

i2cread     macro
            call    i2cread_
            endm

i2cstart    macro
            call    i2cstart_
            endm

i2cstop     macro
            call    i2cstop_
            endm

i2cack      macro
            call    i2cack_
            endm

i2cnak      macro
            call    i2cnak_
            endm
;************************************************************
i2cwrite_   bcf     mflag,merr          ;flag no error
            movwf   aal                 ;save byte for later
            movlf   aah,8               ;bit counter
i2cwritel_  rlf     aal,f
            bsf     i2csda              ;clock bit
            skipc
            bcf     i2csda
            nop
            bsf     i2cscl              ;clock high
            call    i2c5us_
            bcf     i2cscl              ;clock low
            decfsz  aah,f               ;loop til done
            goto    i2cwritel_
;------------------------------------------------------------
            call    i2c5us_
            bsf     i2csda              ;data high to read input
            nop
            bsf     i2cscl              ;clock high, get ack
            call    i2c5us_
            btfsc   i2csda              ;low is ack
            goto    i2cwrerr_           ;return error
            bcf     i2cscl              ;clock is low
            return
i2cwrerr_   bsf     mflag,merr          ;flag as error
            return
;************************************************************
i2cread_    movlf   aah,8               ;bit counter
i2creadl_   call    i2c5us_
            bsf     i2cscl              ;clock high
            call    i2c5us_
            ccarry                      ;read bit
            btfsc   i2csda              ;bit is 0
            scarry                      ;bit is 1
            rlf     aal,f               ;build byte
            bcf     i2cscl
            decfsz  aah,f               ;loop til done
            goto    i2creadl_
            movf    aal,w
            return
;************************************************************
i2cstart_   call    i2cstop1_           ;init control lines
            bcf     i2csda              ;data is zero-begin start
            call    i2c5us_
            bcf     i2cscl              ;clock is zero-finish start
            call    i2c5us_
            return
;************************************************************
i2cstop_    bcf     i2csda              ;data begins zero
            call    i2c5us_
i2cstop1_   bsf     i2cscl              ;clock now high-begin stop
            call    i2c5us_
            bsf     i2csda              ;data now high-finish stop
            call    i2c5us_
            return
;************************************************************
i2cack_     bcf     i2csda
            nop
            bsf     i2cscl
            call    i2c5us_
            bcf     i2cscl
            nop
            bsf     i2csda
            return
;************************************************************
i2cnak_     bsf     i2csda
            nop
            bsf     i2cscl
            call    i2c5us_
            bcf     i2cscl
            nop
            return
;************************************************************
 if (_clock <= 3000)
i2c5us_     return                      ;just return is min 5.32us, max 16
 endif
;************************************************************
 if ((_clock > 3000) && (_clock <= 4000))
i2c5us_     nop                         ;5 us
            return
 endif
;************************************************************
 if ((_clock > 4000) && (_clock <= 5000))
i2c5us_     nop                         ;5 us
            nop
            nop
            return
 endif
;************************************************************
 if ((_clock > 5000) && (_clock <= 6000))
i2c5us_     nop                         ;5 us
            nop
            nop
            nop
            return
 endif
;************************************************************
 if (_clock > 6000)                     ;for > 6 mhz use loop
;------------------------------------------------------------
 if ((_clock > 6000) && (_clock <= 9000))       
i2cdly1     equ     1                   ;6us/5.3us
 endif
 if ((_clock > 9000) && (_clock <= 12000))  
i2cdly1     equ     2                   ;6.4us/5.3us
 endif
 if ((_clock > 12000) && (_clock <= 14000)) 
i2cdly1     equ     3                   ;5.5us/5.1us
 endif
 if ((_clock > 14000) && (_clock <= 16000)) 
i2cdly1     equ     4                   ;5.6us/5.2us
 endif
 if ((_clock > 16000) && (_clock <= 19000)) 
i2cdly1     equ     5                   ;5.6us/5.2us
 endif
 if (_clock > 19000)    
i2cdly1     equ     6                   ;5.2us
 endif
;------------------------------------------------------------
i2c5us_     movlf   bbl,i2cdly1         ;5 us delay loop
i2c5usl_    decfsz  bbl,f
            goto    i2c5usl_
            nop
            return
;------------------------------------------------------------
 endif
;************************************************************
 endif
;************************************************************












;************************************************************
;.pwmsetup.                                                 *
;************************************************************
 if (_pwmsetup == true)
;************************************************************
;pwm initialize                                             *
;                                                           *
;pwmsetup   dcconst,prescale                                *
;                                                           *
;dcconst    0   0%                                          *
;           n   100%                                        *
;prescale:  0   4                                           *
;           1   16                                          *
;           2/3 64                                          *
;                                                           *
;pwm frequency=sysclock/prescale/dcconst                    *
;************************************************************
pwmsetup    macro   a,b
            movlf   t2con,b             ;prescaler
            movlw   a                   ;max duty cycle constant
            call    pwmsetup_
            endm
;************************************************************
pwmsetup_   rpage1                      ;both pwm controlled by pr2
            movwf   pr2                 ;0-n=0-100%
            rpage0
            movlw   0x0c                ;setup pwm system
            movwf   ccp1con             ;rc2=pwm1
            movwf   ccp2con             ;rc1=pwm2
            bsf     t2con,2             ;timer 2 on/pwm on
            return
;************************************************************
 endif
;************************************************************















;************************************************************
;.rtc72421.                                                 *
;************************************************************
 if (_rtc72421 == true)
;************************************************************
;t1 t0  msk i/s stp clock   irqflag     std-p               *
;-----------------------------------------------------------*
;x  x   x   x   1   off     off         off                 *
;x  x   1   x   0   on      off         off                 *
;0  0   0   0   0   on      [1]64hz     [2]64hz             *
;0  1   0   0   0   on      [1]1hz      [2]1hz              *
;1  0   0   0   0   on      [1]1/60hz   [2]1/60hz           *
;1  1   0   0   0   on      [1]1/3600hz [2]1/3600hz         *
;0  0   0   1   0   on      [3]64hz     [4]                 *
;0  1   0   1   0   on      [3]1hz      [4]                 *
;1  0   0   1   0   on      [3]1/60hz   [4]                 *
;1  1   0   1   0   on      [3]1/3600hz [4]                 *
;                                                           *
;register   3           2           1           0           *
;-----------------------------------------------------------*
;   d       30sec_adj   irq_flag    busy        hold        *
;   e       t1          t0          i/s         mask        *
;   f       test(0)     24/12       stop        reset       *
;                                                           *
;note-1     duty cycle is high 1/128s, low remainder        *
;note-2     duty cycle is low 1/128s, high remainder        *
;note-3     set high at frequency, must be cleared by write *
;note-4     output low for 100us when irq_flag cleared      *
;note-4     24/12 must be set while reset bit=1             *
;note-5     busy is read only, effective only when hold=1   *
;note-6     irq_flag use 0 only to clear, otherwise use 1   *
;note-7     time counters updated only on 1 second interval *
;                                                           *
;          ________________         ________________        *
;cs1    __|                |__...__|                |__     *
;              _                        _                   *
;hold   ______| |_____________...______| |_____________     *
;                     _                                     *
;busy   _____________| |______...______________________     *
;               busy                    not busy            *
;hold may be test once per cs1 cycle                        *
;                                                           *
;address    range   function        variable                *
;-----------------------------------------------------------*
;   0       0-9     seconds 1       rtc_second              *
;   1       0-5     seconds 10                              *
;   2       0-9     minutes 1       rtc_minute              *
;   3       0-5     minutes 10                              *
;   4       0-9     hours 1         rtc_hour                *
;   5       0-2     hours 10                                *
;   6       0-9     days 1          rtc_day                 *
;   7       0-3     days 10                                 *
;   8       0-9     months 1        rtc_month               *
;   9       0-1     months 10                               *
;   a       0-9     years 1         rtc_year                *
;   b       0-9     years 10                                *
;   c       0-6     weeks 1         **not reported**        *
;************************************************************
rtcinit     macro
            call    rtcinit_
            endm

rtcgetstat  macro
            call    rtcgetstat_
            endm
            
rtcgettime  macro
            call    rtcgettime_
            endm

rtcsettime  macro
            call    rtcsettime_
            endm
;************************************************************
rtcyear     equ     lastrams0
rtcmonth    equ     rtcyear-1
rtcday      equ     rtcmonth-1
rtchour     equ     rtcday-1
rtcminute   equ     rtchour-1
rtcsecond   equ     rtcminute-1
;............................................................
lastrams0   set     rtcsecond-1
;************************************************************
rtcinit_    call    rtcenable_
;------------------------------------------------------------
            movlf   dh,0x0d             ;no hold/clear irq flag
            movlf   al,0x00
            call    rtcwrite_
;............................................................
            movlf   dh,0x0e             ;mask all, no output pulses
            movlf   al,0x01
            call    rtcwrite_
;............................................................
            movlf   dh,0x0f             ;reset on/24 hour mode
            movlf   al,0x05
            call    rtcwrite_
            movlf   al,0x04             ;reset off
            call    rtcwrite_
;............................................................
            call    rtcdisable_
            movlw   10
            call    delayms_
            return
;************************************************************
;status     d       bl                                      *
;           e       bh                                      *
;           f       cl                                      *
;************************************************************
rtcgetstat_ call    rtcenable_
            movlf   dh,0x0d
            call    rtcread_            ;status d
            movff   bl,al
            incf    dh,f
            call    rtcread_            ;status e
            movff   bh,al
            incf    dh,f
            call    rtcread_            ;status f
            movff   cl,al
            call    rtcdisable_
            return
;************************************************************
rtcgettime_ movlf   dh,0x0d             ;address=hold/busy
;............................................................
rtcgtbusyl_ call    rtcenable_
            movlf   al,0x01             ;flag as hold
            call    rtcwrite_
            call    rtcread_            ;get busy status
            btfss   al,2
            goto    rtcgtnbusy_         ;not busy
            call    rtcdisable_         ;wait till not busy
            goto    rtcgtbusyl_
;------------------------------------------------------------
rtcgtnbusy_ movlf   dh,0xff             ;point to rtc seconds-1
            movlf   dl,0x06             ;do for 6 bytes
            movlf   fsr,rtcsecond-1     ;point to ram seconds-1
;............................................................
rtcgtimel_  incf    fsr,f
            incf    dh,f
            call    rtcread_            ;lower 4 bits
            movff   indf,al
            incf    dh,f
            call    rtcread_            ;upper 4 bits
            movf    ah,w
            iorwf   indf,f
            decfsz  dl,f
            goto    rtcgtimel_
;------------------------------------------------------------
            goto    rtcdisable_
;************************************************************
rtcsettime_ movlf   dh,0x0d             ;address=hold/busy
;............................................................
rtcstbusyl_ call    rtcenable_
            movlf   al,0x01             ;flag as hold
            call    rtcwrite_
            call    rtcread_            ;get busy status
            btfss   al,2
            goto    rtcstnbusy_         ;not busy
            call    rtcdisable_         ;wait till not busy
            goto    rtcstbusyl_
;------------------------------------------------------------
rtcstnbusy_ movlf   dh,0xff             ;point to rtc seconds-1
            movlf   dl,0x06             ;do for 6 bytes
            movlf   fsr,rtcsecond-1     ;point to ram seconds-1
;............................................................
rtcstimel_  incf    fsr,f
            incf    dh,f
            movf    indf,w
            andlw   0x0f
            movwf   al
            call    rtcwrite_           ;lower 4 bits
            swapf   indf,w
            andlw   0x0f
            movwf   al
            incf    dh,f
            call    rtcwrite_           ;upper 4 bits
            decfsz  dl,f
            goto    rtcstimel_
;------------------------------------------------------------
            goto    rtcdisable_
;************************************************************
rtcenable_  bsf     rtccs1              ;minimum 1us cs to read/write
            goto    rtcena1_
rtcena1_    goto    rtcena2_
rtcena2_    return
;------------------------------------------------------------
rtcdisable_ goto    rtcdis1_            ;minimum 1us read/write to cs
rtcdis1_    goto    rtcdis2_
rtcdis2_    bcf     rtccs1
            return
;************************************************************
;address:   dh  xxxx aaaa                                   *
;return:    al  0000 dddd                                   *
;           ah  dddd 0000                                   *
;************************************************************
rtcread_    movf    dh,w
            call    p5951_              ;write address to latch
            bsf     rtccs0              ;enable controls
            bcf     rtcrd               ;enable read
            nop                 
            movf    rtcdata,w           ;read rtc data to w
            bsf     rtcrd               ;disable read
            bcf     rtccs0              ;disable controls
            andlw   0x0f                ;trim top 4 bits
            movwf   al                  ;save in al
            swapf   al,w                ;make shifted copy
            movwf   ah                  ;save in ah
            return
;************************************************************
;address:   dh  xxxx aaaa                                   *
;data:      al  xxxx dddd                                   *
;************************************************************
rtcwrite_   movf    dh,w
            call    p5951_              ;write address to latch 
            iopage1                     ;direction=output
            clrf    rtcdata
            iopage0
            movff   rtcdata,al          ;data to port
            nop
            bsf     rtccs0              ;enable controls
            bsf     rtcwr               ;enable write
            nop
            bcf     rtcwr               ;disable write
            bcf     rtccs0              ;disable controls
            iopage1
            movlf   rtcdata,0xff        ;direction=input
            iopage0
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.bin2decd.                                                 *
;************************************************************
 if (_bin2decd == true)
;************************************************************
;convert and display 16bit binary to lcd in decimal format  *
;                                                           *
;   ah,al   16bit binary number to convert/display          *   
;   w       cursor position to start display                *
;   dh      number of digits to display, lsb last           *
;   result  dl  ch  cl  bh  bl                              *
;           10k 1k  100 10  1                               *
;************************************************************
_bin2dec    set     true
;************************************************************
bin2decdw   macro   
            call    bin2decd_
            endm

bin2decd    macro   a,b                 ;a digits at cursor b
            movlw   a
            movwf   dh
            movlw   b
            call    bin2decd_
            endm
;************************************************************
bin2decd_   call    lcdcrsr_            ;set lcd cursor to w
            call    bin2dec_
            movlw   bl                  ;set data pointer to lsb
            movwf   fsr             
            decf    dh,w
            addwf   fsr,f               ;adjust pointer for number of digits
bin2decdl   movf    indf,w              ;get msb of this conversion
            call    lcdchar_            ;write to display
            decf    fsr,f
            decfsz  dh,f                ;do until all digits done
            goto    bin2decdl
            return  
;************************************************************
 endif
;************************************************************





;************************************************************
;.bin2dec.                                                  *
;************************************************************
 if (_bin2dec == true)
;************************************************************
;binary 16 bit to 5 digit ascii decimal conversion          *
;                                                           *
;input :    ah,al                                           *
;output:    dl  ch  cl  bh  bl                              *
;           10k 1k  100 10  1                               *
;************************************************************
bin2dec     macro
            call    bin2dec_
            endm
;************************************************************
bin2dec_    movff   aal,al              ;preserve input value
            movff   aah,ah
            ccarry
            movlf   bl,16               ;bit counter
            clrf    bbl                 ;lsb
            clrf    bbh
            clrf    ccl                 ;msb
            movf    al,f                ;test for zero
            skipnz
            movf    ah,f
            skipnz
            goto    bin2decx_
;------------------------------------------------------------
bin2decl_   rlf     aal,f
            rlf     aah,f
            rlf     bbl,f
            rlf     bbh,f
            rlf     ccl,f
            decf    bl,f                ;loop till all bits done
            skipnz
            goto    bin2decx_
bin2decad_  movlf   fsr,bbl             ;decimal adjust packed bytes
            call    bin2decab_
            incf    fsr,f
            call    bin2decab_
            incf    fsr,f
            call    bin2decab_
            goto    bin2decl_
;------------------------------------------------------------
bin2decab_  movlw   0x03
            addwf   indf,w
            movwf   bh
            btfsc   bh,3
            movwf   indf
            movlw   0x30
            addwf   indf,w
            movwf   bh
            btfsc   bh,7
            movwf   indf
            return
;------------------------------------------------------------
bin2decx_   movf    ccl,w               ;split digits and ascii adjust
            movwf   dl                  ;msb
            swapf   bbh,w
            andlw   0x0f
            movwf   ch
            movf    bbh,w
            andlw   0x0f
            movwf   cl
            swapf   bbl,w
            andlw   0x0f
            movwf   bh
            movf    bbl,w
            andlw   0x0f
            movwf   bl                  ;lsb
            movlw   0x30
            addwf   bl,f
            addwf   bh,f
            addwf   cl,f
            addwf   ch,f
            addwf   dl,f
            return
;************************************************************
 endif
;************************************************************








;************************************************************
;.bin2hexd.                                                 *
;************************************************************
 if (_bin2hexd == true)
;************************************************************
;convert and display 16bit binary to lcd in hexadecimal fmt *
;                                                           *
;   ah,al   16bit binary number to convert/display          *   
;   w       cursor position to start display                *
;   aal     number of digits to display, lsb last           *
;   result  ch  cl  bh  bl                                  *
;           msb         lsb                                 *
;************************************************************
bin2hexd    macro   a,b 
            movlw   a
            movwf   aal
            movlw   b
            call    bin2hexd_
            endm
;************************************************************
bin2hexd_   call    lcdcrsr_            ;set lcd cursor to w
            call    bin2hex_
            movlw   bl                  ;set data pointer to lsb
            movwf   fsr             
            decf    aal,w
            addwf   fsr,f               ;adjust pointer for number of digits
bin2hexdl_  movf    indf,w              ;get msb of this conversion
            call    lcdchar_            ;write to display
            decf    fsr,f
            decfsz  aal,f               ;do until all digits done
            goto    bin2hexdl_
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.bin2hex.                                                  *
;************************************************************
 if (_bin2hex == true)
;************************************************************
;binary 16 bit to 4 digit ascii hexadecimal conversion      *
;                                                           *
;input :    ah,al                                           *
;output:    ch  cl  bh  bl                                  *
;           msb         lsb                                 *
;dl,dh used and will change                                 *
;                                                           *
;source  (ah)    (al)                                       *
;data     12      34        <converted from 8 bit binary    *
;        /  \    /  \                                       *
;result 31  32  33  34      <converted to ascii hex         *
;dest   ch  cl  bh  bl                                      *
;************************************************************
bin2hex     macro
            call    bin2hex_
            endm
;************************************************************
bin2hex_    movff   dh,fsr              ;save fsr
            movf    al,w
            movwf   bl
            movwf   bh
            swapf   bh,f
            movf    ah,w
            movwf   cl
            movwf   ch
            swapf   ch,f
            movlw   0x04
            movwf   dl                  ;counter
            movlf   fsr,bl
bin2hexl_   movlw   0x0f
            andwf   indf,f
            movlw   0x0a
            subwf   indf,w
            movlw   48                  ;offset for 0 to 9
            skipb
            movlw   55                  ;offset for A-F
            addwf   indf,f
            incf    fsr,f
            decfsz  dl,f
            goto    bin2hexl_
            movff   fsr,dh              ;restore fsr
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.hex2bin.                                                  *
;************************************************************
 if (_hex2bin == true)
;************************************************************
;4 digit ascii hexadecimal to 2 byte binary conversion      *
;                                                           *
;input :    ch  cl  bh  bl                                  *
;           msb         lsb                                 *
;output:    ah,al                                           *
;dl,dh,bbl-cch used and will change                         *
;                                                           *
;source ch  cl  bh  bl                                      *
;data   31  32  33  34          <converted from ascii hex   *
;        \  /    \  /                                       *
;result   12      34            <converted to 8 bit binary  *
;dest    (ah)    (al)                                       *
;************************************************************
hex2bin     macro
            call    hex2bin_
            endm
;************************************************************
hex2bin_    movff   dh,fsr              ;save fsr
            movff   bbl,bl              ;save original
            movff   bbh,bh
            movff   ccl,cl
            movff   cch,ch
            movlf   dh,4                ;counter = 4 bytes
            movlf   fsr,bbl             ;offset
hex2binl1_  movlw   79                  ;convert lower case to upper case
            andwf   indf,f
            movlw   9                   ;offset for a-f
            btfss   indf,6              ;apply if 64 bit set
            movlw   0
            addwf   indf,f
            bcf     indf,6              ;strip off a-f flag
            incf    fsr,f
            decfsz  dh,f
            goto    hex2binl1_
            swapf   bbh,w               ;combine low byte
            addwf   bbl,w
            movwf   al
            swapf   cch,w               ;combine high byte
            addwf   ccl,w
            movwf   ah
            movff   fsr,dl              ;restore fsr
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.bitmod.                                                   *
;************************************************************
 if (_bitmod == true)
;************************************************************
;bit set/clear by software                                  *
;                                                           *
;w  mxxx xbbb                                               *
;bbb:   bit to modify, 0-7                                  *
;m  :   mode:   0   clear                                   *
;               1   set                                     *
;fsr: byte to modify                                        *
;************************************************************
bitmodw     macro
            call    bitmod_
            endm

bitmod      macro   a
            movlf   fsr,a
            call    bitmod_
            endm
;************************************************************
bitmod_     movwf   tmp2                ;mode   register
            andlw   0x07
            movwf   tmp0                ;bit to modify counter
            incf    tmp0,f
            movlf   tmp1,0x09           ;bit counter
;............................................................
bitmodl_    rrf     indf,f              ;rotate bit into carry
            decfsz  tmp0,f              ;test for bit
            goto    bitmodx_
            btfsc   tmp2,7              
            scarry                      ;set bit
            btfss   tmp2,7
            ccarry                      ;clear bit
bitmodx_    decfsz  tmp1,f              ;test for done
            goto    bitmodl_
            return
;************************************************************
 endif
;************************************************************












;************************************************************
;.jsparse.                                                  *
;************************************************************
 if (_jsparse == true)
;************************************************************
;test for adjusted analog within limits                     *
;input                                                      *
;------------------------------                             *
;w      pot value                                           *
;al     pot zero reference                                  *
;zero flag set if returning zero value                      *
;                                                           *
;output                                                     *
;------------------------------                             *
;w      adjusted pot value, 0-73 (+/-12 units of deadband)  *
;al     direction bit, 7                                    *
;************************************************************
jsparse     macro
            call    jsparse_
            endm
;************************************************************
jsdeadband  equ     0x0c
;************************************************************
jsparse_    movwf   ah                  ;save w to register
            movf    al,w                ;subtract out zero reference
            subwf   ah,w
            skipb
            goto    jsparse1_
;............................................................
jsparse0_   addlw   0x80                ;pot is less than zero reference
            skipnc
            goto    jsparsex_
            movlw   0x00                ;adjusted pot is less than 0x00
            goto    jsparsex_           ;  so make it 0x00
;............................................................
jsparse1_   addlw   0x80                ;pot is greater than zero reference
            skipc
            goto    jsparsex_           ;adjusted pot is greater than 0xff 
            movlw   0xff                ;  so make it 0xff
;............................................................
jsparsex_   movwf   ah                  ;determine direction and
            btfss   ah,7                ;  strip off speed info
            goto    jsparsen_
jsparsep_   bsf     al,7                ;positive
            bcf     ah,7
            goto    jsparsex1_
jsparsen_   bcf     al,7                ;negative
            movlw   0x7f
            xorwf   ah,f
;............................................................
jsparsex1_  movlw   jsdeadband          ;dead band
            subwf   ah,f
            skipnb
            clrf    ah
            movf    ah,w                ;return adjusted pot in w
            return
;************************************************************
 endif
;************************************************************










;************************************************************
;.win8x8.                                                   *
;************************************************************
 if (_win8x8 == true)
;************************************************************
;8 bit window comparator                                    *
;(bl) > (al) > (cl)                                         *
;(bl) = upper limit                                         *
;(cl) = lower limit                                         *
;(al) = target value                                        *
;flags: mpos    (a) above window                            *
;       mzero   (a) within window                           *
;       mneg    (a) below window                            *
;where (bl) >= (cl)                                         *
;************************************************************
win8x8      macro
            call    win8x8_
            endm
;************************************************************
win8x8_     movff   ccl,cl              ;high limit
            movff   bbl,bl
            call    sub8x8_
            skipnmp
            goto    win8x8x_
win8x8a_    movff   bl,ccl              ;low limit
            call    sub8x8_
            skipnmn
            goto    win8x8x_
            bcf     mflag,mpos
            bsf     mflag,mzero
win8x8x_    movff   bl,bbl
            movff   cl,ccl
            return
;************************************************************
 endif
;************************************************************




;************************************************************
;.win16x16.                                                 *
;************************************************************
 if (_win16x16 == true)
;************************************************************
;16 bit window comparator                                   *
;(bh,bl) > (ah,al) > (ch,cl)                                *
;(bh,bl) = upper limit                                      *
;(ch,cl) = lower limit                                      *
;(ah,al) = target value                                     *
;flags: mpos    (a) above window                            *
;       mzero   (a) within window                           *
;       mneg    (a) below window                            *
;where (bh,bl) >= (ch,cl)                                   *
;************************************************************
win16x16    macro
            call    win16x16_
            endm
;************************************************************
win16x16_   movff   ccl,cl              ;high limit
            movff   cch,ch
            movff   bbl,bl
            movff   bbh,bh
            call    sub16x16_
            skipnmp
            goto    win16x16x_
win16x16a_  movff   bl,ccl              ;low limit
            movff   bh,cch
            call    sub16x16_
            skipnmn
            goto    win16x16x_
            bcf     mflag,mpos
            bsf     mflag,mzero
win16x16x_  bcf     mflag,mhzero
            movff   cl,ccl
            movff   ch,cch
            movff   bl,bbl
            movff   bh,bbh
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.sub8x8fs.                                                 *
;************************************************************
 if (_sub8x8fs == true)
;************************************************************
;signed 8 x 8 subtraction                                   *
;(al) - (bl) >> (cl)                                        *
;flags: mzero   (a) = (b), (c) = 0                          *
;       mpos    (a) > (b), (c) positive                     *
;       mneg    (a) < (b), (c) negative                     *
;************************************************************
sub8x8s     macro
            call    sub8x8s_
            endm
;************************************************************
sub8x8s_    call    sub8x8_
            btfss   mflag,mneg
            return
sub8x8neg_  comf    cl,f
            incf    cl,f
            return
;************************************************************
 endif
;************************************************************



;************************************************************
;.sub8x8f.                                                  *
;************************************************************
 if (_sub8x8f == true)
;************************************************************
;8 x 8 subtraction                                          *
;(al) - (bl) >> (cl)                                        *
;flags: mzero   (a) = (b), (c) = 0                          *
;       mpos    (a) > (b), (c) positive                     *
;       mneg    (a) < (b), (c) negative                     *
;************************************************************
sub8x8      macro
            call    sub8x8_
            endm
;************************************************************
sub8x8_     bcf     mflag,mzero
            bcf     mflag,mpos
            bcf     mflag,mneg
            movf    bl,w
            subwf   al,w
            movwf   cl
            skipnz
            bsf     mflag,mzero
            skipc                       
            goto    sub8x8n_            ;no carry = negative
            skipz
            bsf     mflag,mpos
            return
sub8x8n_    bsf     mflag,mneg
            comf    cl,f
            incf    cl,f
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.sub16x16fs.                                               *
;************************************************************
 if (_sub16x16fs == true)
;************************************************************
;signed 16 x 16 subtraction                                 *
;(ah,al) - (bh,bl) >> (ch,cl)                               *
;flags: mzero   (a) = (b), (c) = 0                          *
;       mpos    (a) > (b), (c) positive                     *
;       mneg    (a) < (b), (c) negative                     *
;       mhzero  (ch) = 0                                    *
;************************************************************
sub16x16s   macro
            call    sub16x16s_
            endm
;************************************************************
sub16x16s_  call    sub16x16_           ;do 2's subtraction
            btfss   mflag,mneg
            return
sub16sneg_  comf    ch,f                ;invert high result
            comf    cl,f                ;invert low result
            incf    cl,f                ;add 1
            skipnz                      ;inc high if low+1>255
            incf    ch,f
            movf    ch,f                ;check for high byte zero
            skipnz                      ;after conversion
            bsf     mflag,mhzero
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.sub16x16.                                                 *
;************************************************************
 if (_sub16x16 == true)
;************************************************************
;16 x 16 subtraction                                        *
;(ah,al) - (bh,bl) >> (ch,cl)                               *
;************************************************************
sub16x16    macro
            call    sub16x16_
            endm
;************************************************************
sub16x16_   movf    al,w                ;cl=al-bl
            movwf   cl
            movf    ah,w
            movwf   ch
            movf    bl,w                ;low byte
            subwf   cl,f
            skipb                   
            goto    sub16c_             ;no borrow
            movlw   1
            subwf   ch,f                ;borrow from high byte
sub16c_     movf    bh,w                ;cch=aah-bbh-borrow
            subwf   ch,f
;------------------------------------------------------------
            return
;************************************************************
 endif
;************************************************************








;************************************************************
;.sub16x16f.                                                *
;************************************************************
 if (_sub16x16f == true)
;************************************************************
;16 x 16 subtraction                                        *
;(ah,al) - (bh,bl) >> (ch,cl)                               *
;flags: mzero   (a) = (b), (c) = 0                          *
;       mpos    (a) > (b), (c) positive                     *
;       mneg    (a) < (b), (c) negative                     *
;       mhzero  (ch) = 0                                    *
;************************************************************
sub16x16    macro
            call    sub16x16_
            endm
;************************************************************
sub16x16_   bcf     mflag,mzero
            bcf     mflag,mpos
            bcf     mflag,mneg
            bcf     mflag,mhzero
            movf    al,w                ;cl=al-bl
            movwf   cl
            movf    ah,w
            movwf   ch
            movf    bl,w                ;low byte
            subwf   cl,f
            skipb                   
            goto    sub16c_             ;no borrow
            movlw   1
            subwf   ch,f                ;borrow from high byte
            skipnb
            bsf     mflag,mneg
sub16c_     movf    bh,w                ;cch=aah-bbh-borrow
            subwf   ch,f
;------------------------------------------------------------
            skipnb                      ;test for negative
            bsf     mflag,mneg          
            movf    ch,f                ;test for high zero
            skipnz
            bsf     mflag,mhzero
            skipmnn                     ;if negative, no other flags apply
            return
            movf    cl,f                ;test for low zero
            skipz
            goto    sub16pos_
            skipnmhz
            bsf     mflag,mzero
sub16pos_   skipmz
            bsf     mflag,mpos
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.div8x8.                                                   *
;************************************************************
 if (_div8x8 == true)
;************************************************************
;8 x 8 division                                             *
;(al) / (bl) >> (cl), remainder in (dl)                     *
;************************************************************
div8x8      macro
            call    div8x8_
            endm
;************************************************************
div8x8_     clrf    cl                  ;clear result
            clrf    dl                  ;clear remainder
            movlf   dh,8                ;8 step counter
            movff   ah,al               ;preserve value of al
;------------------------------------------------------------
div8x8l_    ccarry
            rlf     ah,f
            rlf     dl,f
            movf    bl,w
            subwf   dl,w
div8x8nz_   skipc
            goto    div8x8ns_
            movf    bl,w
            subwf   dl,f
            scarry
div8x8ns_   rlf     cl,f
;------------------------------------------------------------
            decfsz  dh,f
            goto    div8x8l_
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.div8x8f.                                                  *
;************************************************************
 if (_div8x8f == true)
;************************************************************
;8 x 8 division                                             *
;(al) / (bl) >> (cl), remainder in (dl)                     *
;flags: mrzero  (dl) = remainder = 0                        *
;************************************************************
div8x8      macro
            call    div8x8_
            endm
;************************************************************
div8x8_     bsf     mflag,mrzero
            clrf    cl                  ;clear result
            clrf    dl                  ;clear remainder
            movlf   dh,8                ;8 step counter
            movff   ah,al               ;preserve value of al
;------------------------------------------------------------
div8x8l_    ccarry
            rlf     ah,f
            rlf     dl,f
            movf    bl,w
            subwf   dl,w
div8x8nz_   skipc
            goto    div8x8ns_
            movf    bl,w
            subwf   dl,f
            scarry
div8x8ns_   rlf     cl,f
;------------------------------------------------------------
            decfsz  dh,f
            goto    div8x8l_
            movf    dl,f                ;test for remainder of zero
            skipz
            bcf     mflag,mrzero
            return
;************************************************************
 endif
;************************************************************




;************************************************************
;.div16x2.                                                  *
;************************************************************
 if (_div16x2 == true)
;************************************************************
;16 bit divide by power of 2                                *
;(ah,al) / 2^n >> (ah,al), remainder in (bl)                *
;n = w                                                      *
;************************************************************
div16x2     macro   a
            movlw   a
            call    div16x2_
            endm
;************************************************************           
div16x2_    movwf   tmp0
            clrf    bl
div16x2l_   ccarry
            rrf     ah,f
            rrf     al,f
            rlf     bl,f
            decfsz  tmp0,f
            goto    div16x2l_
            return
;************************************************************
 endif
;************************************************************





;************************************************************
;.div16x2f.                                                 *
;************************************************************
 if (_div16x2f == true)
;************************************************************
;16 bit divide by power of 2                                *
;(ah,al) / 2^n >> (ah,al), remainder in (bl)                *
;n = w                                                      *
;flags: mrzero  (bl) = remainder = 0                        *
;       mhzero  (ah) = 0                                    *
;************************************************************
div16x2     macro   a
            movlw   a
            call    div16x2_
            endm
;************************************************************           
div16x2_    movwf   tmp0
            bsf     mflag,mrzero
            clrf    bl
div16x2l_   ccarry
            rrf     ah,f
            rrf     al,f
            rlf     bl,f
            decfsz  tmp0,f
            goto    div16x2l_
            movf    bl,f                ;test for remainder zero
            skipz
            bcf     mflag,mrzero
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.div16x16.                                                 *
;************************************************************
 if (_div16x16f == true)
;************************************************************
;16 x 16 division                                           *
;(ah,al) / (bh,bl) >> (ch,cl), remainder in (dh,dl)         *
;flags: mrzero  (dh,dl) = remainder = 0                     *
;       mhzero  (ch) = 0                                    *
;************************************************************
div16x16    macro
            call    div16x16_
            endm
;************************************************************
div16x16_   bsf     mflag,mhzero
            bsf     mflag,mrzero
            movlf   tmp0,16
            movff   aal,al
            movff   aah,ah
            clrf    cl
            clrf    ch
            clrf    dl
            clrf    dh
;............................................................
div16x16l_  ccarry
            rlf aal,f
            rlf aah,f
            rlf dl,f
            rlf dh,f
            movf    bh,w
            subwf   dh,w
            skipz
            goto    div16x16nz_
            movf    bl,w
            subwf   dl,w
div16x16nz_ skipc
            goto    div16x16ns_
            movf    bl,w
            subwf   dl,f
            movf    bh,w
            skipc                       ;subtract with borrow
            addlw   0x01
            subwf   dh,f
            scarry
div16x16ns_ rlf     cl,f
            rlf     ch,f
;............................................................
            decfsz  tmp0,f
            goto    div16x16l_
;------------------------------------------------------------
            movf    ch,f                ;test for high 8 of 16 zero
            skipz
            bcf     mflag,mhzero
            movf    dh,f                ;test for remainder of zero
            skipz
            bcf     mflag,mrzero
            movf    dl,f
            skipz
            bcf     mflag,mrzero
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.div16x8.                                                  *
;************************************************************
 if (_div16x8 == true)
;************************************************************
;70us worst case (0xffff)/(0x01) at 19.6608mhz              *
;16 x 8 division, minimum logic overhead                    *
;                                                           *
;div16x8r   copy previous result to (bl,ah,al) and divide   *
;                                                           *
;(ah,al) / (bl) >> (ch,cl), remainder in (dh)               *
;uses al-dh,aal,aah,bbl,tmp0                                *
;************************************************************
div16x8     macro
            call    div16x8_
            endm

div16x8r    macro
            call    div16x8r_
            endm
;************************************************************
div16x8r_   movff   al,cl           ;recycle previous result
            movff   ah,ch
div16x8_    movff   aal,al          ;save original
            movff   aah,ah
            clrf    cl              ;clear result
            clrf    ch
            clrf    ccl             ;clear 16 bit remainder
            clrf    cch
            movlf   ddh,16          ;24 bit counter
;------------------------------------------------------------
div16x8l_   ccarry                  ;rotate in 0 from left
            rlf     aal,f           ;rotate highest bit from (a) to carry
            rlf     aah,f
            rlf     ccl,f           ;rotate carry into remainder
            rlf     cch,f
;............................................................
            btfsc   cch,0           ;if 1xx then must be > bl
            goto    div16x8sub_     ;if so then do subtract
            movf    bl,w            
            subwf   ccl,w
            skipc                   ;if ccl < bl then no subtract yet
            goto    div16x8nsb_
div16x8sub_ movf    bl,w
            subwf   ccl,f
            bcf     cch,0
            scarry
div16x8nsb_ rlf     cl,f
            rlf     ch,f
            decfsz  ddh,f
            goto    div16x8l_
            movff   dh,ccl          ;ccl contained 8 bit remainder
;------------------------------------------------------------
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.div24x8.                                                  *
;************************************************************
 if (_div24x8 == true)
;************************************************************
;24 x 8 division, minimum logic overhead                    *
;                                                           *
;div24x8r   copy previous result to (bl,ah,al) and divide   *
;                                                           *
;(bl,ah,al) / (bh) >> (dl,ch,cl), remainder in (dh)         *
;uses al-dh,aal,aah,bbl,tmp0                                *
;************************************************************
div24x8     macro
            call    div24x8_
            endm

div24x8r    macro
            call    div24x8r_
            endm
;************************************************************
div24x8r_   movff   al,cl           ;recycle previous result
            movff   ah,ch
            movff   bl,dl
div24x8_    movff   aal,al          ;save original
            movff   aah,ah
            movff   bbl,bl
            clrf    cl              ;clear result
            clrf    ch
            clrf    dl
            clrf    ccl             ;clear 16 bit remainder
            clrf    cch
            movlf   ddh,24          ;24 bit counter
;------------------------------------------------------------
div24x8l_   ccarry                  ;rotate in 0 from left
            rlf     aal,f           ;rotate highest bit from (a) to carry
            rlf     aah,f
            rlf     bbl,f
            rlf     ccl,f           ;rotate carry into remainder
            rlf     cch,f
;............................................................
            btfsc   cch,0           ;if 1xx then must be > bh
            goto    div24x8sub_     ;if so then do subtract
            movf    bh,w            
            subwf   ccl,w
            skipc                   ;if ccl < bh then no subtract yet
            goto    div24x8nsb_
div24x8sub_ movf    bh,w
            subwf   ccl,f
            bcf     cch,0
            scarry
div24x8nsb_ rlf     cl,f
            rlf     ch,f
            rlf     dl,f
            decfsz  ddh,f
            goto    div24x8l_
            movff   dh,ccl          ;ccl contained 8 bit remainder
;------------------------------------------------------------
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.div32x8.                                                  *
;************************************************************
 if (_div32x8 == true)
;************************************************************
;32 x 8 division, minimum logic overhead                    *
;                                                           *
;div32x8r   copy previous result to (bh,bl,ah,al), redivide *
;                                                           *
;(bh,bl,ah,al) / (w) >> (dh,dl,ch,cl), remainder in (w)     *
;************************************************************
div32x8     macro
            call    div32x8_
            endm

div32x8r    macro
            call    div32x8r_
            endm
;************************************************************
div32x8r_   movwf   ddl
            movff   al,cl           ;recycle previous result
            movff   ah,ch
            movff   bl,dl
            movff   bh,dh
            goto    div32x80_
div32x8_    movwf   ddl             ;w used due to maxing out of variables
div32x80_   movff   aal,al          ;save original
            movff   aah,ah
            movff   bbl,bl
            movff   bbh,bh
            clrf    cl              ;clear result
            clrf    ch
            clrf    dl
            clrf    dh
            clrf    ccl             ;clear 16 bit remainder
            clrf    cch
            movlf   ddh,32          ;24 bit counter
;------------------------------------------------------------
div32x8l_   ccarry                  ;rotate in 0 from left
            rlf     aal,f           ;rotate highest bit from (a) to carry
            rlf     aah,f
            rlf     bbl,f
            rlf     bbh,f
            rlf     ccl,f           ;rotate carry into remainder
            rlf     cch,f
;............................................................
            btfsc   cch,0           ;if 1xx then must be > ddl
            goto    div32x8sub_     ;if so then do subtract
            movf    ddl,w           
            subwf   ccl,w
            skipc                   ;if ccl < bh then no subtract yet
            goto    div32x8nsb_
div32x8sub_ movf    ddl,w
            subwf   ccl,f
            bcf     cch,0
            scarry
div32x8nsb_ rlf     cl,f
            rlf     ch,f
            rlf     dl,f
            rlf     dh,f
            decfsz  ddh,f
            goto    div32x8l_
            movf    ccl,w           ;ccl contained 8 bit remainder
;------------------------------------------------------------
            return                  ;remainder returned in w
;************************************************************
 endif
;************************************************************









;************************************************************
;.mpy8x8f.                                                  *
;************************************************************
 if (_mpy8x8f == true)
;************************************************************
;8 x 8 multiply                                             *
;(al) * (bl) >> (ch,cl)                                     *
;flags: mhzero  (ch) = 0                                    *
;************************************************************
mpy8x8      macro
            call    mpy8x8_
            endm
;************************************************************
mpy8x8_     bcf     mflag,mhzero
            clrf    ch                  ;high result
            clrf    cl                  ;low result
            movff   aal,al              ;preserve value of al
            movlf   bbl,0x08            ;8 step counter
            movf    bl,w
            ccarry
;------------------------------------------------------------
mpy8x8l_    btfsc   aal,0               
            addwf   ch,f                ;carry from add in carry bit
            rrf     ch,f                ;to be rotated in
            rrf     cl,f
            rrf     aal,f
            ccarry
            decfsz  bbl,f
            goto    mpy8x8l_
            movf    ch,f                ;test for high 8 of 16 zero
            skipnz
            bsf     mflag,mhzero
            return
;************************************************************
 endif
;************************************************************




;************************************************************
;.mpy16x2.                                                  *
;************************************************************
 if (_mpy16x2 == true)
;************************************************************
;16 bit multiply by power of 2                              *
;(ah,al) * 2^n >> (bl,ah,al)                                *
;n = w                                                      *
;flags: mhzero  (bl,ah) = 0                                 *
;************************************************************
mpy16x2     macro   a
            movlw   a
            call    mpy16x2_
            endm
;************************************************************
mpy16x2_    movwf   tmp0
            bsf     mflag,mhzero
            clrf    bl
mpy16x2l_   ccarry
            rlf     al,f
            rlf     ah,f
            rlf     bl,f
            decfsz  tmp0,f
            goto    mpy16x2l_
            movf    bl,f                ;test for high zero
            skipz
            bcf     mflag,mhzero
            movf    ah,f
            skipz
            bcf     mflag,mhzero
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.mpy16x8.                                                  *
;************************************************************
 if (_mpy16x8 == true)
;************************************************************
;16 x 8 multiply                                            *
;(ah,al) * (bl) >> (dl,ch,cl)                               *
;************************************************************
mpy16x8     macro
            call    mpy16x8_
            endm
;************************************************************
mpy16x8_    clrf    dl                  ;result byte 3
            clrf    ch                  ;result byte 2
            clrf    cl                  ;result byte 1
            movff   aal,al              ;preserve value of al
            movff   aah,ah
            movlf   tmp0,0x10           ;16 step counter
            movf    bl,w
            ccarry
;------------------------------------------------------------
mpy16x8l_   btfsc   aal,0
            addwf   dl,f
            rrf     dl,f
            rrf     ch,f
            rrf     cl,f
            rrf     aah,f
            rrf     aal,f
            ccarry
            decfsz  tmp0,f
            goto    mpy16x8l_
            return
;************************************************************
 endif
;************************************************************







;************************************************************
;.mpy16x8f.                                                 *
;************************************************************
 if (_mpy16x8f == true)
;************************************************************
;16 x 8 multiply                                            *
;(ah,al) * (bl) >> (dl,ch,cl)                               *
;flags: mhzero  (dl,ch) = 0                                 *
;************************************************************
mpy16x8     macro
            call    mpy16x8_
            endm
;************************************************************
mpy16x8_    bcf     mflag,mhzero
            clrf    dl                  ;result byte 3
            clrf    ch                  ;result byte 2
            clrf    cl                  ;result byte 1
            movff   aal,al              ;preserve value of al
            movff   aah,ah
            movlf   tmp0,0x10           ;16 step counter
            movf    bl,w
            ccarry
;------------------------------------------------------------
mpy16x8l_   btfsc   aal,0
            addwf   dl,f
            rrf     dl,f
            rrf     ch,f
            rrf     cl,f
            rrf     aah,f
            rrf     aal,f
            ccarry
            decfsz  tmp0,f
            goto    mpy16x8l_
            movf    dl,f                ;test for high 16 of 24 zero
            skipnz
            movf    ch,f
            skipnz
            bsf     mflag,mhzero
            return
;************************************************************
 endif
;************************************************************









;************************************************************
;.mpy16x16.                                                 *
;************************************************************
 if (_mpy16x16 == true)
;************************************************************
;16 x 16 multiply                                           *
;(ah,al) * (bh,bl) >> (dh,dl,ch,cl)                         *
;************************************************************
mpy16x16    macro
            call    mpy16x16_
            endm
;************************************************************
mpy16x16_   clrf    dh                  ;result byte 4
            clrf    dl                  ;result byte 3
            clrf    ch                  ;result byte 2
            clrf    cl                  ;result byte 1
            movff   aal,al              ;preserve value of ah,al
            movff   aah,ah
            movlf   tmp0,16             ;16 step counter
;------------------------------------------------------------
mpy16x16l_  ccarry
            btfss   aal,0
            goto    mpy16x16a_          
            movf    bl,w
            addwf   dl,f
            movf    bh,w
            skipnc
            incf    bh,w
            addwf   dh,f
mpy16x16a_  rrf     dh,f
            rrf     dl,f
            rrf     ch,f
            rrf     cl,f
            rrf     aah,f
            rrf     aal,f
            decfsz  tmp0,f
            goto    mpy16x16l_
            return
;************************************************************
 endif
;************************************************************













;************************************************************
;.beepx.                                                    *
;************************************************************
 if (_beepx == true)
;************************************************************
;null beep                                                  *
;************************************************************
 beep       macro
            endm
;************************************************************
_beep       set     false
;************************************************************
 endif
;************************************************************




;************************************************************
;.beep.                                                     *
;************************************************************
 if (_beep == true)
;************************************************************
;pulse pin low at 500 hz for 100ms and then return high     *
;set pin direction in cpuinit routine                       *
;************************************************************
beep        macro
            call    beep_
            endm
;************************************************************
beepdelay   equ     ((_clock/1000)*12)
;************************************************************
beep_       movlw   255     
            movwf   tmp1
beepl_      bcf     beeppin
            movlw   beepdelay
            movwf   tmp0
beepl1_     decfsz  tmp0,f
            goto    beepl1_
            bsf     beeppin
            movlw   beepdelay
            movwf   tmp0
beepl2_     decfsz  tmp0,f
            goto    beepl2_
            decfsz  tmp1,f
            goto    beepl_
            return
;************************************************************
 endif
;************************************************************















;************************************************************
;.adcint.                                                   *
;************************************************************
 if (_adcint == true)
;************************************************************
;internal adc driver                                        *
;                                                           *
;setup variables 'adcmask' prior to call                    *
;  see adcsetup.txt for instructions                        *
;************************************************************
adc         macro   a
            movlw   a
            movwf   tmp1
            call    adc_
            endm

adcinit     macro
            call    adcinit_
            endm
;************************************************************
;.adcinit.                                                  *
;************************************************************
;select conversion clock                                    *
;************************************************************
 if (_clock <= 1000)    
adcclk      equ     0x00                ;fosc/2
 endif
;............................................................
 if ((_clock > 1000) && (_clock <= 5000))
adcclk      equ     0x40                ;fosc/8
 endif
;............................................................
 if (_clock > 5000)     
adcclk      equ     0x80                ;fosc/32        
 endif
;************************************************************
adcinit_    movlw   0x3f                ;select conversion clock
            andwf   adcon0,f
            movlw   adcclk
            iorwf   adcon0,f
            movlw   adcmask             ;select port configuration
            rpage1
            movwf   adcon1
            rpage0
            return
;************************************************************
;.adc.                                                      *
;************************************************************
;convert only channels flaged in adcreq                     *
;last channel converted will return in w                    *
;************************************************************
adc_        movwf   tmp1
            btfss   tmp1,0              ;channel 0 ?
            goto    adcint1_
            movlw   0xc7                ;select channel 0
            call    adccvrt_            
            movwf   al
adcint1_    btfss   tmp1,1              ;channel 1 ?
            goto    adcint2_
            movlw   0xcf                ;select channel 1
            call    adccvrt_            
            movwf   ah
adcint2_    btfss   tmp1,2              ;channel 2 ?
            goto    adcint3_
            movlw   0xd7                ;select channel 2
            call    adccvrt_            
            movwf   bl
adcint3_    btfss   tmp1,3              ;channel 3 ?
            goto    adcint4_
            movlw   0xdf                ;select channel 3
            call    adccvrt_            
            movwf   bh
adcint4_    btfss   tmp1,4              ;channel 4 ?
            goto    adcint5_
            movlw   0xe7                ;select channel 4
            call    adccvrt_            
            movwf   cl
adcint5_    btfss   tmp1,5              ;channel 5 ?
            goto    adcint6_
            movlw   0xef                ;select channel 5
            call    adccvrt_            
            movwf   ch
adcint6_    btfss   tmp1,6              ;channel 6 ?
            goto    adcint7_
            movlw   0xf7                ;select channel 6
            call    adccvrt_            
            movwf   dl
adcint7_    btfss   tmp1,7              ;channel 7 ?
            goto    adcnoreq_
            movlw   0xff                ;select channel 7
            call    adccvrt_            
            movwf   dh
adcnoreq_   return
;************************************************************
;convert a channel                                          *
;************************************************************
adccvrt_    bsf     adcon0,3            ;select channel
            bsf     adcon0,4
            bsf     adcon0,5
            andwf   adcon0,f
            bsf     adcon0,0            ;turn on adc
            movlw   ((_clock/1000)+1)   ;delay 12us before conversion
            movwf   tmp0
adcacql_    decfsz  tmp0,f              ;3 cycles per count=clock(mhz)*3
            goto    adcacql_
            bsf     adcon0,2            ;start conversion
adccvrtl_   btfsc   adcon0,2            ;wait till done
            goto    adccvrtl_
            movf    adres,w             ;return with result
            bcf     adcon0,0            ;turn off adc
            return
;************************************************************
 endif
;************************************************************

















;************************************************************
;.adcint.                                                   *
;************************************************************
 ifndef adres
_adcint     set     false
 endif  
_adcintxxx  set     false
;............................................................
 if (_adcintxxx == true)
;************************************************************
;internal adc driver                                        *
;-----------------------------------------------------------*
;'f876/'f877                                                *
;adcmask, adfm=0/1                                          *
;adcon1:    7     6     5     4     3     2     1     0     *
;          adfm   -     -     -    cfg3  cfg2  cfg1  cfg0   *
;                                                           *
;           re2 re1 re0 ra5 ra3 ra2 ra1 ra0             adc *
;cfg3:cfg0  an7 an6 an5 an4 an3 an2 an1 an0 vref+ vref- mask*
;  0000      a   a   a   a   a   a   a   a   vdd   vss  0x00*
;  0001      a   a   a   a ref+  a   a   a   ra3   vss  0x01*
;  0010      d   d   d   a   a   a   a   a   vdd   vss  0x02*
;  0011      d   d   d   a ref+  a   a   a   ra3   vss  0x03*
;  0100      d   d   d   d   a   d   a   a   vdd   vss  0x04*
;  0101      d   d   d   d ref+  d   a   a   ra3   vss  0x05*
;  0110      d   d   d   d   d   d   d   d   ---   ---  0x06*
;  0111      d   d   d   d   d   d   d   d   ---   ---  0x07*
;  1000      a   a   a   a ref+ ref- a   a   ra3   ra2  0x08*
;  1001      d   d   a   a   a   a   a   a   vdd   vss  0x09*
;  1010      d   d   a   a ref+  a   a   a   ra3   vss  0x0a*
;  1011      d   d   a   a ref+ ref- a   a   ra3   ra2  0x0b*
;  1100      d   d   d   a ref+ ref- a   a   ra3   ra2  0x0c*
;  1101      d   d   d   d ref+ ref- a   a   ra3   ra2  0x0d*
;  1110      d   d   d   d   d   d   d   a   vdd   vss  0x0e*
;  1111      d   d   d   d ref+ ref- d   a   ra3   ra2  0x0f*
;-----------------------------------------------------------*
;adfm (adcon1,7)    0   adresh      adresl                  *
;                       76543210    76543210                *
;                       m-------    -l000000                *
;                   1   000000m-    -------l                *
;-----------------------------------------------------------*
;for 10bit conversions (bits10=true):                       *
;adfm   0   bits 1,0 packed into aal,aah,bbl,bbh            *
;       1   bits 9,8 packed into aal,aah,bbl,bbh            *
;                                                           *
;register   aal         aah         bbl         bbh         *
;bits       76543210    76543210    76543210    76543210    *
;channel    --11--00    --33--22    --55--44    --77--66    *
;************************************************************
;adcmask    set     0x05
;adcbits10  set     true
;------------------------------------------------------------
adc         macro   a
            movlw   a
            call    adc_
            endm

adcinit     macro
            rpage1
            movlf   adcon1,adcmask
            rpage0
            endm
;************************************************************
;.adcinit.                                                  *
;************************************************************
;select conversion clock                                    *
;************************************************************
 if (_clock <= 1000)    
adcctl      equ     0x01                ;fosc/2
 endif
;............................................................
 if ((_clock > 1000) && (_clock <= 5000))
adcctl      equ     0x41                ;fosc/8
 endif
;............................................................
 if (_clock > 5000)     
adcctl      equ     0x81                ;fosc/32        
 endif
;************************************************************
;.adc.                                                      *
;************************************************************
;convert only channels flaged in adcreq (bitwise flag)      *
;last channel converted will return in w                    *
;************************************************************
adc_        movwf   tmp1                ;save conversion bitmask
            movlf   tmp2,8              ;8 channels
            movlf   adcon1,adcctl-0x08  ;channel 0-1/adc clock/adc=on
            movlf   fsr,al-1            ;point to first location to save
;------------------------------------------------------------
adcloop_    movlw   0x08                ;channel=channel+1
            addwf   adcon1,f
            incf    fsr,f               ;destination=destination+1
            rrf     tmp1,f              ;rotate enables into carry, 1=convert
            skipc
            goto    adcexittst_
;............................................................
            movlw   ((_clock/1000)+1)   ;delay 12us before conversion
            movwf   tmp0
adcacql_    decfsz  tmp0,f              ;3 cycles per count=clock(mhz)*3
            goto    adcacql_
;............................................................
            bsf     adcon0,2            ;start conversion
adccvrtl_   btfsc   adcon0,2            ;wait till done
            goto    adccvrtl_
;............................................................
            movff   indf,adres          ;return with last result in w, adres==adresh (msb 8)
;------------------------------------------------------------
adcexittst_ decfsz  tmp2,f              ;do 8 channels, only those flagged
            goto    adcloop_
            bcf     adcon0,0            ;turn off adc
            return
;************************************************************
 endif
;************************************************************
















;************************************************************
;.mdisp.                                                    *
;************************************************************
 if (_mdisp == true)
;************************************************************
;lcd message display from eeprom                            *
;                                                           *
;mdisppntr can be any 16 bit number                         *
;allocate memory bytes after pointer of (maxmessage * 2)    *
;                                                           *
;message control codes                                      *
;code       description                                     *
;-----------------------------------------------------      *
;0xff       end of message                                  *
;0xfe       set cursor to location in next byte             *
;0xfd       clear the lcd display                           *
;0xfc       display next character                          *
;0xfb       display the number of spaces in the next byte   *
;0xfa       send this block to cgram                        *
;************************************************************
mdisp       macro   a
            movlw   a
            call    mdisp_
            endm

mdispw      macro
            call    mdisp_
            endm
;************************************************************
_mpntr  set         true
;************************************************************
mdisp_      call    mpntr_              ;calculate pointer
            call    m25_
            movwf   al
            call    m25_
            movwf   ah
            movff   m25addrl,al
            movff   m25addrh,ah
;------------------------------------------------------------
mdispl_     call    m25_
            movwf   aal
;............................................................
            movlw   0xff                ;exit code
            xorwf   aal,w
            skipnz
            return
;............................................................
            movlw   0xfa                ;send to cgram
            xorwf   aal,w
            skipnz
            goto    mdispcg_
;............................................................
            movlw   0xfe                ;new cursor code
            xorwf   aal,w
            skipnz
            goto    mdispnc_
;............................................................
            movlw   0xfd                ;clear screen
            xorwf   aal,w
            skipnz
            goto    mdispcls_
;............................................................
            movlw   0xfb                ;print spaces
            xorwf   aal,w
            skipnz
            goto    mdispspc_
;............................................................
            movlw   0xfc                ;force display next character
            xorwf   aal,w
            skipz
;............................................................
            goto    mdispchar_
;------------------------------------------------------------
mdispfd_    call    m25_                ;display the next byte in eeprom
            movwf   aal
;............................................................
mdispchar_  movf    aal,w               ;display this character
            call    lcdchar_
            goto    mdispl_
;............................................................
mdispnc_    call    m25_                ;reset cursor position
            call    lcdcrsr_
            goto    mdispl_
;............................................................
mdispcls_   call    lcdcls_             ;clear the display
            goto    mdispl_
;............................................................
mdispspc_   call    m25_                ;display string of spaces
            movwf   dh
mdispspcl_  movlw   ' '                 ;loop till that many spaces displayed
            call    lcdchar_
            decfsz  dh,f
            goto    mdispspcl_
            goto    mdispl_
;............................................................
mdispcg_    movlw   0x40                ;send to cgram till 0xff
            call    lcdinst_            ;  cg data need never be > 0x1f
mdispcgl_   call    m25_                ;  due to 5 bit wide cg data
            movwf   aal                 ;save for test
            xorlw   0xff                ;terminate on 0xff
            skipnz
            goto    mdispcgx_
            movf    aal,w               ;restore
            call    lcdchar_            ;write byte to cgram
            goto    mdispcgl_                       
mdispcgx_   movlw   0x80                ;reset pointer to display area
            call    lcdinst_
            return
;************************************************************           
 endif
;************************************************************





;************************************************************
;.mxmit.                                                    *
;************************************************************
 if (_mxmit == true)
;************************************************************
;transmit raw binary data from eeprom to serial port        *
;                                                           *
;mdisppntr can be any 16 bit number                         *
;allocate memory bytes after pointer of (maxmessage * 2)    *
;                                                           *
;message control codes                                      *
;code       description                                     *
;-----------------------------------------------------      *
;0xff       end of data                                     *
;************************************************************
mxmit       macro   a
            movlw   a
            call    mxmit_
            endm

mxmitw      macro
            call    mxmit_
            endm
;************************************************************
_mpntr      set     true
;************************************************************
mxmit_      call    mpntr_              ;calculate pointer
            call    m25_
            movwf   al
            call    m25_
            movwf   ah
            movff   m25addrl,al
            movff   m25addrh,ah
;------------------------------------------------------------
mxmitl_     call    m25_
            movwf   aal
            movlw   0xff                ;exit code
            xorwf   aal,w
            skipnz
            return
mxmitchar_  movf    aal,w
            call    sciput_
            goto    mxmitl_
;************************************************************           
 endif
;************************************************************





;************************************************************
;.mxmita.                                                   *
;************************************************************
 if (_mxmita == true)
;************************************************************
;convert eeprom binary to two byte ascii and transmit       *
;to serial port, store checksum in al                       *
;                                                           *
;mdisppntr can be any 16 bit number                         *
;allocate memory bytes after pointer of (maxmessage * 2)    *
;                                                           *
;message control codes                                      *
;code       description                                     *
;-----------------------------------------------------      *
;0xff       end of message                                  *
;************************************************************
mxmita      macro   a
            movlw   a
            call    mxmita_
            endm

mxmitaw     macro
            call    mxmita_
            endm

mxmitaa     macro
            call    mxmitaa_
            endm
;************************************************************
_mpntr      set     true
;************************************************************
mxmitaa_    movlf   m25cmmd,rdbyteinc   ;absolute pointer
            goto    mxmital_
;------------------------------------------------------------
mxmita_     call    mpntr_              ;calculate pointer
            call    m25_
            movwf   al
            call    m25_
            movwf   ah
            movff   m25addrl,al
            movff   m25addrh,ah
;------------------------------------------------------------
mxmital_    call    m25_
            movwf   al
            movlw   0xff                ;exit code
            xorwf   al,w
            skipz
            goto    mxmitchar_
            movff   al,tmp1
            return
;............................................................           
mxmitachar_ call    bin2hex_            ;convert to ascii
            movf    bh,w
            call    sciput_
            movf    bl,w
            call    sciput_
;............................................................
            movf    bh,w                ;keep checksum
            addwf   bl,w
            addwf   tmp1,f
            goto    mxmital_
;************************************************************           
 endif
;************************************************************








;************************************************************
 if (_mpntr == true)
;************************************************************
;mdisplay index pointer calculator                          *
;mdisppntr      16 bit address of index                     *
;                                                           *
;pointer address is lowbyte,highbyte in index               *
;messages are indexed 0 to 255                              *
;************************************************************
mpntr_      movwf   m25addrl            ;build pointer address
            clrf    m25addrh
;............................................................
            ccarry                      ;multiply message number by 2
            rlf     m25addrl,f
            rlf     m25addrh,f
;............................................................
            movlw   low mdisppntr       ;add to pointer
            addwf   m25addrl,f
            skipnc
            incf    m25addrh,f
            movlw   high mdisppntr
            addwf   m25addrh,f
            movlf   m25cmmd,rdbyteinc   ;set to load message pointer
            return                      ;from index table
;************************************************************           
 endif
;************************************************************









;************************************************************
;shared register for 1 or all bar generators                *
;************************************************************
 if (_lcdbar0 == true) || (_lcdbar1 == true) || (_lcdbar2 == true)
;------------------------------------------------------------
_lcddisp    set     true
;------------------------------------------------------------
lcdbarflag  equ     lastrams0           ;flag for multiple bar generators
lastrams0   set     lcdbarflag-1        ;  flag is variation +1
;------------------------------------------------------------
 endif
;************************************************************
;flag   owner                                               *
;0      0           need to implement                       *
;1      1                                                   *
;2      2                                                   *
;3      3                                                   *
;4      3                                                   *
;5                                                          *
;############################################################
;############################################################
;.lcdbar0.                                                  *
;************************************************************
 if (_lcdbar0 == true)
;************************************************************
;solid bar, left to right                                   *
;character generator must be loaded first                   *
;                                                           *
;will draw a 5 character bar                                *
;one column at a time                                       *
;                                                           *
;0  [     ]                                                 *
;50 [x    ]                                                 *
;100[xx   ]                                                 *
;150[xxx  ]                                                 *
;200[xxxx ]                                                 *
;255[xxxxx]                                                 *
;************************************************************
lcdbar0     macro   a,b
            movlf   ch,a                ;temporary lcddisp reg use
            movlw   b
            call    lcdbar0_
            endm

lcdbar0w    macro
            call    lcdbar0_
            endm
;************************************************************
;fix cg loader tester for this mode
;lcdbar0_   movwf   al                  ;save value
            movf    ch,w
            call    lcdcrsr_
            movlf   bl,0x05             ;count for filler spaces at the end
            movf    al,w                ;if zero, just put spaces
            skipnz
            goto    lcdbarx0_
lcdbar0la_  movlw   51                  ;255/51=5 full bars
            subwf   al,f
            skipnb
            goto    lcdbar0b_
            movlw   0x05                ;full bar character
            call    lcdchar_
            decf    bl,f                ;filler=filler-1
            movf    al,w
            skipz
            goto    lcdbar0la_
            goto    lcdbar0x_
lcdbar0b_   movlf   ah,0x04             ;end bar from remainder of last subtract
            movlw   0xff
            xorwf   al,f
lcdbar0lb_  movlw   0x0a                ;50/10=size of last bar
            subwf   al,f
            skipnb
            goto    lcdbar0c_
            decf    ah,f
            goto    lcdbar0lb_
lcdbar0c_   movf    ah,w
            call    lcdchar_
            decf    bl,f                ;if end used, filler=filler-1
lcdbar0x_   movf    bl,w
            skipnz
            return
lcdbar0xl_  movlw   0x00                ;fill last spaces with empty bar
            call    lcdchar_
            decfsz  bl,f
            goto    lcdbar0xl_
            return
;************************************************************
 endif
;############################################################
;############################################################
;.lcdbar1.                                                  *
;************************************************************
 if (_lcdbar1 == true)
;************************************************************
;will draw a 13 character bar graph at 0x40                 *
;single line bar with fixed center point                    *
;processing time is approximately 1.5ms at 7.372 mhz        *
;                                                           *
;   -1111111111111+                                         *
;000[|     |      ]                                         *
;   [ |    |      ]                                         *
;   [  |   |      ]                                         *
;   [   |  |      ]                                         *
;   [    | |      ]                                         *
;127[     ||      ]                                         *
;128[      ||     ]                                         *
;   [      | |    ]                                         *
;   [      |  |   ]                                         *
;   [      |   |  ]                                         *
;   [      |    | ]                                         *
;255[      |     |]                                         *
;************************************************************
lcdbar1     macro   a
            movlw   a
            call    lcdbar1_
            endm

lcdbar1w    macro
            call    lcdbar1_
            endm
;************************************************************
lcdbar1_    movwf   cl                  ;save data to generate bar
            movf    lcdbarflag,w        ;test for cg data loaded (flag=1)
            xorlw   0x01
            movlw   _lcdbar1m           ;do i need to load my cg data?
            skipz
            call    mdisp_              ;yes i do!
            movlf   lcdbarflag,0x01     ;flag as having been done
;------------------------------------------------------------
            rrf     cl,f                ;divide by 4, bar is really 0 to 63
            rrf     cl,w
            andlw   0x3f
            movwf   cl
;------------------------------------------------------------
            movlw   30                  ;decide which half of bar is this
            subwf   cl,w                ;borrow is left (0-29)
            skipnb
            goto    lcdbar1l_
            movlw   34
            subwf   cl,w                ;no borrow is right (34 to 63)
            skipb
            goto    lcdbar1r_
;------------------------------------------------------------
lcdbar1c_   movlw   0x40                ;center of bar character
            call    lcdcrsr_            ;clear entire line
            movlf   bh,13
lcdbar1cl_  movlw   ' '                 ;fill with spaces
            call    lcdchar_
            decfsz  bh,f                ;loop til done
            goto    lcdbar1cl_
;............................................................
            movlw   6                   ;set cursor to center bar
            addwf   ch,w
            call    lcdcrsr_
            movlw   26                  ;character code = n-26
            subwf   cl,w                ;30-33 >> 4-7
            call    lcdchar_            ;draw proper center character
            return
;------------------------------------------------------------
lcdbar1l_   movf    ch,w                ;point to right side clear
            addlw   7                   ;value will be 0 - 29
            movwf   bl                  
            movff   bh,ch               ;point to active bar side
            goto    lcdbar1lr_
;............................................................
lcdbar1r_   movff   bl,ch               ;point to left side clear
            movf    ch,w                ;point to active bar side
            addlw   7                   
            movwf   bh              
            movlw   34                  ;adjust input value for side neutral
            subwf   cl,f                ;0 - 29
;............................................................
lcdbar1lr_  movlf   ah,6                ;left and right side common code
            movf    bl,w                ;clear side opposite active
            call    lcdcrsr_
lcdbar1lrl_ movlw   ' '                 ;six spaces here
            call    lcdchar_
            decfsz  ah,f
            goto    lcdbar1lrl_         ;loop till done
            movf    ch,w                ;write center as '|'
            addlw   6
            call    lcdcrsr_
            movlw   '|'
            call    lcdchar_
            movf    bh,w                ;set cursor for active bar start
            call    lcdcrsr_
            movlf   bl,5                ;filler counter
;............................................................
lcdbar1xl_  movlw   5                   ;draw the active bar
            subwf   cl,f                ;if no borrow then next bar
            skipnb
            goto    lcdbar1x_           ;finish
            movlw   ' '
            call    lcdchar_            ;draw leading fillers
            decf    bl,f
            goto    lcdbar1xl_          ;loop till done
;............................................................
lcdbar1x_   movlw   5                   ;determine character from result
            addwf   cl,f                ;  (-5 to -1) >> (0 to 4)
            movlw   2                   ;test for '|' needed
            xorwf   cl,w
            skipz
            goto    lcdbar1xy_          ;'|' called for
            movlw   '|'
            goto    lcdbar1xz_          ;write as others
lcdbar1xy_  movlw   2                   ;adjust 3/4 >> 2,3
            subwf   cl,w
            skipb                       ;borrow means no adjust
            decf    cl,f                ;make adjustment
            movf    cl,w
            nop
            nop
lcdbar1xz_  call    lcdchar_            ;write character
;------------------------------------------------------------
lcdbar1z_   movf    bl,f                ;test for need of trailing filler
            skipnz
            return
lcdbar1zl_  movlw   ' '                 ;fill remainder with ' '
            call    lcdchar_
            decfsz  bl,f                ;do till done
            goto    lcdbar1zl_
            return
;************************************************************
 endif
;############################################################
;############################################################
;.lcdbar2.                                                  *
;************************************************************
 if (_lcdbar2 == true)
;************************************************************
;will draw a 13 character bar graph at 0x40                 *
;solid bars from left to right                              *
;processing time is approximately 1.5ms at 7.372mhz         *
;                                                           *
;000[             ]                                         *
;   [*            ]                                         *
;   [**           ]                                         *
;   [***          ]                                         *
;   [****         ]                                         *
;   [*****        ]                                         *
;   [******       ]                                         *
;   [*******      ]                                         *
;   [********     ]                                         *
;   [*********    ]                                         *
;   [**********   ]                                         *
;   [***********  ]                                         *
;   [************ ]                                         *
;255[*************]                                         *
;************************************************************
lcdbar2     macro   a
            movlw   a
            call    lcdbar2_
            endm

lcdbar2w    macro
            call    lcdbar2_
            endm
;************************************************************
lcdbar2_    movwf   cl                  ;save data to generate bar
;............................................................
            movlw   0x0c                ;cursor off
            call    lcdinst_                
            movf    lcdbarflag,w        ;test for cg data loaded (flag=2)
            xorlw   0x02
            movlw   _lcdbar2m           ;do i need to load my cg data?
            skipz
            call    mdisp_              ;yes i do!
            movlf   lcdbarflag,0x02     ;flag as having been done
;............................................................
            movlw   0x40                ;set cursor for start of bar
            call    lcdcrsr_
;------------------------------------------------------------
            rrf     cl,f                ;divide by 4, bar is really 0 to 63
            rrf     cl,w
            andlw   0x3f
            movwf   cl
;------------------------------------------------------------
            movlf   bh,12               ;spacer bar count down
lcdbar2l_   movlw   0x05                ;if no borrow then make a full bar
            subwf   cl,f
            skipnb
            goto    lcdbar2x_           ;if borrow then this is last bar
;............................................................
            movlw   0xff                ;no borrow means this one filled
            call    lcdchar_
            decf    bh,f                ;count full bars
            goto    lcdbar2l_
;------------------------------------------------------------
lcdbar2x_   movf    bh,w                ;test for last bar handler
            skipz
            goto    lcdbar2xy_
;............................................................
            movlw   10                  ;last bar handler
            addwf   cl,f                ;adjust to character
            movlw   0x07
            subwf   cl,w
            skipb                       ;anything >= 62 is solid last bar
            goto    lcdbar2xw_          ;do solid
            movf    cl,w                ;do not solid
            call    lcdchar_
            return
lcdbar2xw_  movlw   0xff
            call    lcdchar_
            return
;............................................................
lcdbar2xy_  incf    cl,w                ;test for this bar full
            skipnz
            goto    lcdbar2xx_          ;this bar full
            movlw   0x06                ;pointer to correct filler character
            addwf   cl,w
            call    lcdchar_
            goto    lcdbar2y_
lcdbar2xx_  movlw   0xff
            call    lcdchar_
;------------------------------------------------------------
lcdbar2y_   movf    bh,w                ;exit if count is zero
            skipnz
            goto    lcdbar2yy_
            decf    bh,f                ;draw as many zero bars as needed
            skipnz
            goto    lcdbar2yy_
            movlw   0x00
            call    lcdchar_
            goto    lcdbar2y_
lcdbar2yy_  movlw   0x07                ;end cap if this bar not yet accessed
            call    lcdchar_
            return
;************************************************************
 endif
;############################################################
;############################################################
;.lcdbar3.                                                  *
;************************************************************
 if (_lcdbar3 == true)
;************************************************************
;will draw a 13 character bar graph at 0x40                 *
;single line bar with reference bar and data bar            *
;processing time is approximately 1.5ms at 7.372 mhz        *
;                                                           *
;uses flag 3 and 4                                          *
;reference in dh                                            *
;data in dl                                                 *
;                                                           *
;   -1111111111111+                                         *
;000[|            ]                                         *
;   [ |           ]                                         *
;   [  |          ]                                         *
;   [   |         ]                                         *
;   [    |        ]                                         *
;127[     |       ]                                         *
;128[      |      ]                                         *
;   [       |     ]                                         *
;   [        |    ]                                         *
;   [         |   ]                                         *
;   [          |  ]                                         *
;   [           | ]                                         *
;255[            |]                                         *
;************************************************************
lcdbar3w    macro
            call    lcdbar3_
            endm
;************************************************************
lcdbar3bl   equ     m25addrl            ;borrow registers
lcdbar3bh   equ     m25addrh
lcdbar3cl   equ     m25size
lcdbar3ch   equ     m25cmmd
lcdbar3dl   equ     lastrams0           ;make some new ones
lcdbar3dh   equ     lcdbar3dl-1
lastrams0   set     lcdbar3dh-1
;------------------------------------------------------------
lcdbar3_    movlw   0x0c                ;cursor off
            call    lcdinst_                
            movff   lcdbar3dl,dl        ;save for later: divide uses these
            movff   lcdbar3dh,dh
;------------------------------------------------------------
            movf    lcdbar3dl,w         ;divide by 4>>0-63
            call    lcdbar3d4_
            movwf   lcdbar3dl
            movwf   lcdbar3bl           ;save data line
;............................................................
            movf    lcdbar3dh,w         ;divide by 4>>0-63
            call    lcdbar3d4_
            movwf   lcdbar3dh
            movwf   lcdbar3bh           ;save ref line
;------------------------------------------------------------
            movf    lcdbar3dl,w         ;divide by 5
            call    lcdbar3d5_
            call    lcdbar3m5_          ;multiply by 5
            subwf   lcdbar3dl,w         ;subtact for remainder
            movwf   lcdbar3cl           ;save as index to char
;............................................................
            movf    lcdbar3dh,w         ;divide by 5
            call    lcdbar3d5_
            call    lcdbar3m5_          ;multiply by 5
            subwf   lcdbar3dh,w         ;subtact for remainder
            movwf   lcdbar3ch           ;save as index to char
;------------------------------------------------------------
            movf    lcdbar3dl,w         ;divide by 5
            call    lcdbar3d5_
            movwf   lcdbar3dl           ;save as character offset
;............................................................
            movf    lcdbar3dh,w         ;divide by 5
            call    lcdbar3d5_
            movwf   lcdbar3dh           ;save as character offset
;------------------------------------------------------------
            movff   dl,lcdbar3dl        ;restore to std registers
            movff   dh,lcdbar3dh
            movff   cl,lcdbar3cl
            movff   ch,lcdbar3ch
            movff   bl,lcdbar3bl
            movff   bh,lcdbar3bh
;------------------------------------------------------------
            movf    bh,w                ;if ref=data then cg block 1
            xorwf   bl,w
            skipnz
            goto    lcdbar3ld1_
            movf    dh,w                ;if ref-offset=data-offset
            xorwf   dl,w                ;then block 2 (in same character)
            skipz
            goto    lcdbar3ld1_
            movf    cl,w                ;but only if one index is 0 or 4
            skipnz                      ;otherwise use block1
            goto    lcdbar3ld2_
            movf    ch,w
            skipnz
            goto    lcdbar3ld2_
            btfsc   cl,2                ;test for '4'
            goto    lcdbar3ld2_
            btfsc   ch,2
            goto    lcdbar3ld2_
            incf    cl,f                ;insert offset of 2 
            incf    cl,f                ;(1/2) or (2/1) >> 3+2=5, (2/3) or (3/2) >> 5+2=7
            goto    lcdbar3ld1_         ;(1/3) or (3/1) >> 4+2=6 use block1
;************************************************************
lcdbar3ld2_ movf    lcdbarflag,w        ;test for cg data loaded (flag=4)
            xorlw   0x04
            skipnz
            goto    lcdbar3x0_
            movlw   _lcdbar3m2          ;do i need to load my cg data?
            call    mdisp_              ;yes i do!
            movlf   lcdbarflag,0x04     ;flag as having been done
            goto    lcdbar3x0_
;............................................................
lcdbar3ld1_ movf    lcdbarflag,w        ;test for load block 1 (flag=3)
            xorlw   0x03
            skipnz
            goto    lcdbar3x0_
            movlw   _lcdbar3m1          ;do i need to load my cg data?
            call    mdisp_              ;yes i do!
            movlf   lcdbarflag,0x03     ;flag as having been done
;************************************************************
lcdbar3x0_  movf    bl,w                ;if same data then
            xorwf   bh,w                ;write only 1 character
            skipz
            goto    lcdbar3x1_
            movlf   dh,0xff 
            goto    lcdbar3xx_
lcdbar3x1_  movf    dl,w                ;if same character then merge
            xorwf   dh,w                ;and write only 1 character
            skipz
            goto    lcdbar3xx_
            movf    ch,w                ;add indexes
            addwf   cl,f
            movlf   dh,0xff
lcdbar3xx_  movlw   0x40                ;write '-'
            call    lcdcrsr_
            movlw   '-'
            call    lcdchar_
            movlf   al,13               ;write 13 characters of bar data
            clrf    ah                  ;offset counter
lcdbar3l0_  movf    ah,w                ;any character this offset?
            xorwf   dl,w
            skipz   
            goto    lcdbar3l2_          ;no
            movf    cl,w                ;yes
            goto    lcdbar3l1_
lcdbar3l2_  movf    ah,w                ;any character this offset?
            xorwf   dh,w
            skipz   
            goto    lcdbar3l3_          ;no
            movf    ch,w                ;yes
            goto    lcdbar3l1_
lcdbar3l3_  movlw   ' '                 ;write space if no char this offset
lcdbar3l1_  call    lcdchar_
            incf    ah,f
            decfsz  al,f
            goto    lcdbar3l0_
            movlw   '+'
            call    lcdchar_
            return
;************************************************************
lcdbar3d4_  movwf   al                  ;divide by 4 and return
            rrf     al,f
            rrf     al,w
            andlw   0x3f                ;mask to 6 bits (0-63)
            return
;************************************************************
lcdbar3d5_  movwf   al                  ;divide w by 5 and return
            clrf    ah
            clrf    bl
            clrf    bh
            movlw   5
            call    div32x8_
            movf    cl,w
            return
;************************************************************
lcdbar3m5_  movwf   al                  ;multiply by 5 and return
            clrf    ah
            movlf   bl,5
            clrf    bh
            call    mpy16x16_
            movf    cl,w
            return
;************************************************************
 endif
;************************************************************










;************************************************************
;.lcddisp.                                                  *
;************************************************************
 if (_lcddisp == true)
;************************************************************
;lcd display contoller and interface subroutines            *
;************************************************************
;must define port/control lines in xxxs.asm block           *
;#define    lcddata portd                                   *
;#define    lcden   re0                                     *
;#define    lcdrs   re1                                     *
;#define    lcdrw   re2                                     *
;************************************************************
;minimum setup delays:                                      *
;   r/w-chg         to  enable-high         140ns   ok 20mhz*
;   enable-high     to  data-valid(read)    320ns   ok 20mhz*
;   data-valid      to  enable-low(write)   195ns   ok 20mhz*
;   enable pulse width                                      *
;       ___                                                 *
;     >|   |<  450ns                                        *
;   ---     ---                                             *
;   enable cycle                                            *
;       ___     ___                                         *
;     >|   |   |< 1000ns                                    *
;   ---     ---                                             *
;************************************************************
lcdcharw    macro
            call    lcdchar_
            endm

lcdchar     macro   a
            movlw   a
            call    lcdchar_
            endm

lcdcls      macro
            call    lcdcls_
            endm

lcdcrsrw    macro
            call    lcdcrsr_
            endm

lcdcrsr     macro   a
            movlw   a
            call    lcdcrsr_
            endm

lcdinit     macro
            call    lcdinit_
            endm

lcdinst     macro   a
            movlw   a
            call    lcdinst_
            endm

lcdinstw    macro
            call    lcdinst_
            endm

lcdpoke     macro   a,b                 ;a is position, b is data
            movlw   b
            movwf   tmp5
            movlw   a
            call    lcdpoke_
            endm

lcdpokew    macro
            call    lcdpoke_
            endm
;************************************************************
;tmp0,1,2   used for delayms which is called here
;tmp3
;tmp4
;tmp5       used in poke macro to store data to be written
;tmp6       used in busy for timeout
;************************************************************
lcdcrsr_    iorlw   0x80
            goto    lcdinst_
;************************************************************
lcdpoke_    iorlw   0x80                ;write address = 80h+w
            call    lcdinst_
            movf    tmp5,w              ;get character from temp reg
            goto    lcdchar_
;************************************************************
lcdcls_     movlw   0x01                ;clear display ram
            goto    lcdinst_
;************************************************************
lcdinst_    movwf   tmp3                ;instruction write to lcd
            call    lcdbusy_
            bcf     lcdrs               ;mode=instruction
            goto    lcdwrite_
;............................................................
lcdchar_    movwf   tmp3                ;character write to lcd
            call    lcdbusy_
            bsf     lcdrs               ;mode=data
;------------------------------------------------------------
lcdwrite_   swapf   tmp3,w              ;send high nibble
            movwf   tmp4            
            movlw   0xf0                ;remove bottom 4 bits of data port
            andwf   lcddata,f
            movlw   0x0f                ;remove top 4 bits of data
            andwf   tmp4,w              ;merge port with data
            iorwf   lcddata,f
            call    lcdclkf_
            movf    tmp3,w              ;send low nibble
            movwf   tmp4            
            movlw   0xf0                ;remove bottom 4 bits of data port
            andwf   lcddata,f
            movlw   0x0f                ;remove top 4 bits of data
            andwf   tmp4,w              ;merge port with data
            iorwf   lcddata,f
            call    lcdclkf_
            return
;************************************************************
lcdinit_    movlw   3                   ;low level initialization
            movwf   tmp3                ;all data and control set
lcdinitl_   movlw   20                  ;  to zero in setup file
            call    delayms_            ;for cpu init
            movlw   3               
            call    lcdidat_
            decfsz  tmp3,f
            goto    lcdinitl_
            movlw   0x2
            call    lcdidat_
;------------------------------------------------------------
;high level initialization
            movlw   0x28                ;001d nf00  d1=8bit/d0=4bit n1=2line/n0=1line f1=5x10/f0=5x7
            call    lcdinst_
            movlw   0x06                ;0000 01ds  d1=incr/d0=decr s1=display shift
            call    lcdinst_        
            movlw   0x0c                ;0000 1dcb  d1=dispon/c1=cursoron/b1=cursor blinks
            call    lcdinst_
            movlw   0x1c                ;0001 md00  m1=dispshift/m0=cursorshift d1=right/d0=left
            call    lcdinst_
            movlw   0x28                ;001d nf00  d1=8bit/d0=4bit n1=2line/n0=1line f1=5x10/f0=5x7
            call    lcdinst_
            movlw   0x01                ;clear and home
            call    lcdinst_
            movlw   20                  ;wait 20 ms after first clear, do not need
            call    delayms_            ;delay for future calls to lcdcls
            return
;************************************************************
lcdidat_    movwf   tmp4                ;save w
            movlw   0xf0                ;remove bottom 4 bits of data port
            andwf   lcddata,f
            movf    tmp4,w
            iorwf   lcddata,f           ;merge port with data
            goto    lcdclkf_
;************************************************************
lcdbusy_    rpage1                      ;set port as input
            movlw   0x0f
            iorwf   lcddata,f
            rpage0
            bcf     lcdrs
            nop                         ;no consec write to same port
            bsf     lcdrw               
            clrf    tmp6
;------------------------------------------------------------
lcdbusyl_   nop                         ;400ns (600 with enable)
            nop
            bsf     lcden               ;enable high
            nop
            nop
            movf    lcddata,w           ;get high nibble
            bcf     lcden               ;enable low
            nop                         ;400ns (600 with enable)
            nop
            bsf     lcden               ;enable high for low nibble
            nop                         ;400ns (600 with enable)
            nop
            bcf     lcden               ;enable low
            movwf   tmp4                ;save high nibble for test
            btfss   tmp4,3              ;bit3(7)=0=not busy
            goto    lcdbusyx_
            decfsz  tmp6,f              ;if 256 tries then bail
            goto    lcdbusyl_
;------------------------------------------------------------
lcdbusyx_   bcf     lcdrw               ;r/w=0=write
            rpage1
            movlw   0xf0                ;lcd port=output again
            andwf   lcddata,f
            rpage0
            return
;************************************************************
lcdclkf_    nop                         ;400ns (600 with enable)
            nop                         ;fast enable toggle
            bsf     lcden               ;enable high
            nop                         ;400ns (600 with enable)
            nop
            bcf     lcden               ;enable low
            nop                         ;200ns (800 with return)
            return
;************************************************************
 endif
;************************************************************












;************************************************************
;.delayse.                                                  *
;************************************************************
 if (_delayse == true)
;************************************************************
;delayse    delay 'w' seconds and return                    *
;  63 seconds max                                           *
;************************************************************
delayse     macro   a
            movlw   a
            call    delayse_
            endm

delaysew    macro
            call    delayse_
            endm
;************************************************************
_delayms    set     true
;************************************************************
delayse_    movwf   tmp3
            movf    tmp3,f              ;if zero then return now
            skipnz
            return
            ccarry
            rlf     tmp3,f
            rlf     tmp3,f
delaysesl_  movlw   250                 ;4 * 250ms
            call    delayms_
            decfsz  tmp3,f
            goto    delaysesl_
            return
;************************************************************
 endif
;************************************************************






;************************************************************
;.delayms.                                                  *
;************************************************************
 if (_delayms == true)
;************************************************************
; delayms   delay 'w' miliseconds and return                *
;-----------------------------------------------------------*
;for clock from 1 to 20 mhz:                                *
;accuracy is +(((256-w)/255)*4)%                            *
;w      error                                               *
;---------------                                            *
;1      +4.000%                                             *
;255    +0.016%                                             *
;-----------------------------------------------------------*
;for clock from 32khz                                       *
;accuracy is +(((                                           *
;w      error                                               *
;---------------                                            *
;1      +100%                                               *
;255    +0.4%                                               *
;************************************************************
delayms     macro   a
            movlw   a
            call    delayms_
            endm

delaymsw    macro
            call    delayms_
            endm
;************************************************************
delayms_    movwf   tmp2
delaymsl1_  clrwdt                          ;1 reset per msec
            movlf   tmp1,high((_clock/32)-2) ;~16 bytes of overhead
            movlf   tmp0,low((_clock/32)-2)
;------------------------------------------------------------
delaymsl0_  movlw   1                       ;8 instructions/cycle
            subwf   tmp0,f
            skipb
            goto    delaymsl0a_
            subwf   tmp1,f
            skipb
            goto    delaymsl0_
;------------------------------------------------------------
            decfsz  tmp2,f
            goto    delaymsl1_
            return
delaymsl0a_ nop                             ;loop balancer
            goto    delaymsl0_
;************************************************************
 endif
;************************************************************








;************************************************************
;.delayus.                                                  *
;************************************************************
 if (_delayus == true)
;************************************************************
;delayus    delay 'w' * 50 microseconds and return          *
;************************************************************
delayus     macro   a
            movlw   a
            call    delayus_
            endm

delayusw    macro
            call    delayus_
            endm
;************************************************************
delayus_    movwf   tmp0                ;us*50 counter
delayusl0_  movlf   tmp1,~(((_clock/1000)*130)/37)
delayusl1_  incfsz  tmp1,f
            goto    delayusl1_
            decfsz  tmp0,f
            goto    delayusl0_
            return
;************************************************************
 endif
;************************************************************














;************************************************************
lastroms    set     $
;............................................................
 if (_substart == 0x0)                  ;compile main block after sub block
 endif                                  ;if substart was set to 0x0
;............................................................
 if (_substart > 0)                     ;otherwise sub block was some
            org     lastromm            ;non-zero absolute address
 endif
;************************************************************


