;**************************************************************************************** ;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 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 (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 ;************************************************************