TITLE "xyz stepper motor controller" LIST p=16F88 ERRORLEVEL 0, -302 ; File: cnc.asm; Created: Sep-2004, Paddy Strebel ; Oscillator and reset circuit are internal to the PIC16F88. ; ********** ********** ; * *** * ; SXB A2 ** 1 18 ** A1 SYA ; * * ; SXA A3 ** 2 17 ** A0 SYB ; * * ; DRL A4 ** 3 16 ** A7 SZA ; * * ; EMG A5 ** 4 15 ** A6 SZB ; * * ; GND GND ** 5 14 ** VCC 5V ; * * ; CSX B0 ** 6 13 ** B7 SCK ; * * ; CSY B1 ** 7 12 ** B6 SDI ; * * ; RXD B2 ** 8 11 ** B5 TXD ; * * ; CSZ B3 ** 9 10 ** B4 SDO ; * PIC16F88 * ; *********************** ; ; Switch inputs have 10k pullups and 10nF to GND (all PORTA except DRL) ; Trinamic TMC246 smart power microstepping pwm driver with SPI interface: ; The low RDS_on of the two integrated power H-bridges active cooling is ; is not necessary. Stall detection did not work reliable and there was ; no improvement when using mixed decay for decreasing phase currents. ; ; GND GND GND GND---220n--24V--+---+ ; | | | | 100u | 0R1 ; 10K | | 220n | +-----------> VSA, VSB ; A | | | | | 100R ; G S I I V G | | ; N L N N C N V V ; VCC D P A B C D x x S T x ; | | | | | | | | | | | | ; 10K ---------------------------------------------- ; | | 44 43 42 41 40 39 38 37 36 35 34 | ; ANN --|01 33|-- BL2 -- GND ; | | ; --|02 32|-- ; + OA1 | | | | OB1 + ; | --|03 31|-- | ; | | | | ; | VSA --|04 30|-- VSB | ; | | | | ; | --|05 29|-- | ; + | OA2 | | | | OB2 | + ; | | --|06 TMC246A 28|-- | | ; | | | | | | ; | | --|07 27|-- | | ; | + OA1 | | | | OB1 + | ; | --|08 26|-- | ; | | | | ; | BRA --|09 25|-- BRB | ; | | | | ; | --|10 24|-- | ; + OA2 | | | | OB2 + ; --|11 23|-- ; | 12 13 14 15 16 17 18 19 20 21 22 | ; ---------------------------------------------- ; | | | | | | | | | | | ; S O S S S G C E S B S ; R S D D C N S N P L R ; A C O I K D N N E 1 B ; BRA <--+--100R--+ | | | | | | | | +--100R--+--> BRB ; 0R5 1n0 P P P P | 10K 10K 0R5 ; | | I I I I | | | | ; GND GND C C C C GND VCC VCC GND ; Nanotec stepper motor ST2818M1006, bipolar with two coils, 200 steps/rot: ; In fullstep mode 1000 steps/s are possible but resonance problems occure ; around 220 steps/s. Microstepping is used to overcome resonance problems. ; 1/4 microstepping also enhances the resolution of my cnc drive to 1.25um. ; Coil A: +0 +6 +11 +14 +15 +14 +11 +6 -0 -6 -11 -14 -15 -14 -11 -6 ; Coil B: +15 +14 +11 +6 -0 -6 -11 -14 -15 -14 -11 -6 +0 +6 +11 +14 ; Commands: (asynchronous serial 9600bps,8,N,1) ; ; 'h' help (list of available commands) ; '-4194303' .. '4194303' decimal number ; 'x' set destination x absolute to origin ; 'y' set destination y absolute to origin ; 'z' set destination z absolute to origin ; 'X' set destination x relative to current pos ; 'Y' set destination y relative to current pos ; 'Z' set destination z relative to current pos ; 'm' move to destination (x,y) then (z) ; 's' set current position (position = destination) ; 'o' set origin (position = destination = 0,0,0) ; 't' translate (t=dst-pos, dst=pos, pos=pos-t) ; 'i' initialize (search switches SZB, SYA, SXA) ; 'r' release (turn off motors) ; 'n' turn drill motor oN ; 'f' turn drill motor ofF ; 'p' print coordinates: position (destination) ; 'q' query tmc246 driver status ; 'H' high speed 4000usteps/s (300rpm) ; 'M' medium speed 2000usteps/s (150rpm) ; 'L' low speed 1000usteps/s (75rpm) ; 'c' clear error flag ; ; Undefined characters are ignored. The receive buffer is 256 bytes. ; An escape D'27' immediately resets the controller and sets an error flag. __IDLOCS H'CCCC' __CONFIG H'2007', H'3F14' ; PWRT on, BOR off, WDT on, INTRC A7/A6 __CONFIG H'2008', H'3FFC' ; IE switch off, fail-save off INDF EQU 0 ; indirect file access TMR0 EQU 1 ; real time clock counter PCL EQU 2 ; program counter lsb STATUS EQU 3 ; program status FSR EQU 4 ; file selection register PORTA EQU 5 ; i/o port PORTB EQU 6 ; i/o port PCLATH EQU H'0A' ; program counter msb (CALL, GOTO > H'800') INTCON EQU H'0B' ; interrupt control PIR1 EQU H'0C' ; peripheral interrupt flags TMR1L EQU H'0E' ; timer 1 register TMR1H EQU H'0F' ; timer 1 register T1CON EQU H'10' ; timer 1 control RCSTA EQU H'18' ; USART receiver control and status TXREG EQU H'19' ; USART transmit data RCREG EQU H'1A' ; USART receive data ADRESH EQU H'1E' ; ADC result register upper two bits ADCON0 EQU H'1F' ; ADC control register 0 _OPTION EQU H'81' ; OPTION register in bank 1 _TRISA EQU H'85' ; tristate register in bank 1 _TRISB EQU H'86' ; tristate register in bank 1 _PIE1 EQU H'8C' ; peripheral interrupt enable _OSCCON EQU H'8F' ; oscillator control _OSCTUNE EQU H'90' ; oscillator tuning _TXSTA EQU H'98' ; USART transmitter control and status _SPBRG EQU H'99' ; USART baud rate _ANSEL EQU H'9B' ; analog select for porta _ADRESL EQU H'9E' ; ADC result register lsb _ADCON1 EQU H'9F' ; ADC control register 1 _EEDATA EQU H'10C' ; EE data byte _EEADR EQU H'10D' ; EE address pointer _EEDATH EQU H'10E' ; flash high data byte _EEADRH EQU H'10F' ; flash high address pointer _EECON1 EQU H'18C' ; EE control register 1 _EECON2 EQU H'18D' ; EE control register 2 C EQU 0 ; carry DC EQU 1 ; digit carry Z EQU 2 ; zero PD EQU 3 ; power down TO EQU 4 ; watch dog time out RP0 EQU 5 ; register bank select RP1 EQU 6 ; register bank select IRP EQU 7 ; register bank select (indirect) BRAM EQU H'20' ; start of ram for bootloader CSX EQU 0 ; chip select Z CSY EQU 1 ; chip select Y CSZ EQU 3 ; chip select X SDI EQU 6 ; SCI data in to SDO on TMC246 SDO EQU 4 ; SCI data out to SDI on TMC246 SCK EQU 7 ; SCI clock SXA EQU 3 ; end switch SXB EQU 2 ; end switch SYA EQU 1 ; end switch SYB EQU 0 ; end switch SZA EQU 7 ; end switch SZB EQU 6 ; end switch DRL EQU 4 ; drill motor output EMG EQU 5 ; emergency switch CBLOCK H'020' ; (start of RAM) buf :D'64' ; receive buffer 256 bytes in banks 0,1,2,3 ENDC CBLOCK H'070' ; variables (16 bytes common to all pages) savw :1 ; interrupt context save savs :1 savf :1 savp :1 tmp0 :1 ; temporary storage tmp1 :1 tmp2 :1 cmnd :1 ; command flgs :1 ; sign,ends,lz,err,skp,decz,decy,decx stim :1 ; step timer rptr :1 ; receive buffer read pointer wptr :1 ; receive buffer write pointer drva :1 ; drive A: mixed decay, phase, current 0..F drvb :1 ; drive B: mixed decay, phase, current 0..F lind :1 ; load indicator LD2,LD1,LD0 dsta :1 ; err status OT,OTPW,UV,OCHS,OLB,OLA,OCB,OCA ENDC CBLOCK H'060' ; variables (16 bytes page 0) posx :3 ; position -8388608..8388607 usteps posy :3 ; position -8388608..8388607 usteps posz :3 ; position -8388608..8388607 usteps rmdr :3 ; reminder numb :3 ; input number ENDC CBLOCK H'0E0' ; variables (16 bytes page 1) dstx :3 ; destination -8388608..8388607 dsty :3 ; destination -8388608..8388607 dstz :3 ; destination -8388608..8388607 fact :3 ; factor ENDC CBLOCK H'160' ; variables (16 bytes page 2) dltx :3 ; delta (dst-pos) dlty :3 ; delta (dst-pos) dltz :3 ; delta (dst-pos) incl :3 ; inclination ENDC ; CBLOCK H'110' ; variables (16 bytes page 2) ; CBLOCK H'1E0' ; variables (16 bytes page 3) ; CBLOCK H'190' ; variables (16 bytes page 3) ORG H'0000' ; reset GOTO main ORG H'0004' ; interrupt intserv MOVWF savw ; save W SWAPF STATUS,W ; status to W CLRF STATUS ; bank 0 MOVWF savs ; save STATUS MOVF FSR,W ; save FSR MOVWF savf ; MOVF PCLATH,W ; save PCLATH MOVWF savp ; CLRF PCLATH ; PCLATH to page 0 MOVF wptr,W ; write rx data to buf ANDLW H'3F' ; ADDLW buf ; BTFSC wptr,6 ; banks 1,3 ? ADDLW H'80' ; MOVWF FSR ; MOVF RCREG,W ; clears PIR1,5 XORLW D'27' ; ESC received? BTFSC STATUS,Z ; GOTO ferr ; yes: emergency exit XORLW D'27' ; restore W BTFSC wptr,7 ; banks 2,3 ? BSF STATUS,IRP ; MOVWF INDF ; received byte to buf BCF STATUS,IRP ; INCF wptr,F ; MOVF savp,W ; restore PCLATH MOVWF PCLATH ; MOVF savf,W ; restore FSR MOVWF FSR ; SWAPF savs,W ; restore STATUS MOVWF STATUS ; SWAPF savw,F ; restore W SWAPF savw,W ; RETFIE ; ORG H'0040' ; main BTFSC STATUS,4 ; power up reset clears error flag CLRF flgs ; escape CLRF STATUS ; bank 0 (direct and indexed) CLRWDT ; wdt:128 = ca 2.3s CLRF INTCON ; clear all flags, disable interrupts MOVLW B'00000000' ; port A off MOVWF PORTA ; MOVLW B'11111111' ; port B (chip selects, sdo, sck high) MOVWF PORTB ; BSF STATUS,RP0 ; bank 1 MOVLW B'11101111' ; switch inputs MOVWF _TRISA MOVLW B'01000100' ; RXD, SDI inputs MOVWF _TRISB MOVLW B'01011111' ; pu, risint, iclk, rise, wdt, :128 MOVWF _OPTION ; MOVLW B'01110000' ; 8 MHz MOVWF _OSCCON MOVLW B'00000000' ; all ANx pins digital MOVWF _ANSEL MOVLW D'51' ; baud rate 9600 MOVWF _SPBRG MOVLW B'00100100' ; TXEN, BRGH MOVWF _TXSTA CLRF STATUS ; bank 0 (direct and indexed) MOVLW B'10010000' ; SPEN, CREN MOVWF RCSTA ; BTFSS flgs,4 ; if error flag set wait for 'c' GOTO errclr errset CALL boloc XORLW 'c' BTFSS STATUS,Z GOTO errset errclr CLRF flgs MOVLW H'60' ; begin reset vars MOVWF FSR initvar CLRF INDF INCF FSR,F MOVLW H'80' XORWF FSR,W BTFSS STATUS,Z GOTO initvar ; end reset vars MOVLW B'00110001' ; timer1 2Mhz/8=250kHz MOVWF T1CON ; CALL speedh ; fastest speed CALL origin ; reset pos, reset dst CALL relall ; motors off MOVLW H'06' ; PCLATH to rom tables MOVWF PCLATH MOVLW '*' ; say hello CALL txbyte CALL bolo ; check first rx byte for boot load XORLW 'U' ; boot loader not entered: restore W MOVWF buf ; and store to receive buffer INCF wptr,F BSF STATUS,RP0 ; bank 1 BSF _PIE1,5 ; enable rx interrupt BCF STATUS,RP0 ; bank 0 BSF INTCON,6 ; PEIE BSF INTCON,7 ; GIE loop CLRWDT ; at idle time we loop here BTFSS PORTA,EMG ; emergency switch? GOTO ferr MOVF rptr,W ; blocking read data from buf XORWF wptr,W BTFSC STATUS,Z GOTO loop CALL rdbuf MOVWF cmnd CALL txbyte ; echo input MOVLW '-' ; sign must not clear numb XORWF cmnd,W BTFSS STATUS,Z GOTO numck BSF flgs,7 GOTO loop numck MOVF cmnd,W SUBLW '9' ; cmnd > '9' ? BTFSS STATUS,C GOTO nonum MOVLW '0' ; cmnd < '0' ? SUBWF cmnd,W BTFSS STATUS,C GOTO nonum MOVLW numb MOVWF FSR CALL tmp24 ; tmp = numb*10 MOVF tmp2,W ; overflow already > 1M ANDLW H'F0' BTFSS STATUS,Z GOTO ferr CALL mul10 MOVF cmnd,W ; tmp += digit ANDLW H'0F' MOVWF numb CLRF numb+1 CLRF numb+2 CALL addnum CALL fsr24 MOVF tmp2,W ; overflow if > 4194303 ANDLW H'C0' BTFSS STATUS,Z GOTO ferr GOTO loop nonum MOVF cmnd,W ; ignore if not alpha ANDLW H'DF' ; a..z -> A..Z SUBLW 'Z' BTFSS STATUS,C GOTO loop SUBLW 'Z'-'A' BTFSS STATUS,C GOTO loop MOVLW 'x' ; regular commands: XORWF cmnd,W BTFSC STATUS,Z CALL stox MOVLW 'y' XORWF cmnd,W BTFSC STATUS,Z CALL stoy MOVLW 'z' XORWF cmnd,W BTFSC STATUS,Z CALL stoz MOVLW 'X' XORWF cmnd,W BTFSC STATUS,Z CALL addx MOVLW 'Y' XORWF cmnd,W BTFSC STATUS,Z CALL addy MOVLW 'Z' XORWF cmnd,W BTFSC STATUS,Z CALL addz MOVLW 'H' XORWF cmnd,W BTFSC STATUS,Z CALL speedh MOVLW 'M' XORWF cmnd,W BTFSC STATUS,Z CALL speedm MOVLW 'L' XORWF cmnd,W BTFSC STATUS,Z CALL speedl MOVLW 'm' XORWF cmnd,W BTFSC STATUS,Z CALL line MOVLW 's' XORWF cmnd,W BTFSC STATUS,Z CALL setpos MOVLW 'o' XORWF cmnd,W BTFSC STATUS,Z CALL origin MOVLW 't' XORWF cmnd,W BTFSC STATUS,Z CALL xlate MOVLW 'i' XORWF cmnd,W BTFSC STATUS,Z CALL iniseek MOVLW 'n' XORWF cmnd,W BTFSC STATUS,Z BSF PORTA,DRL MOVLW 'f' XORWF cmnd,W BTFSC STATUS,Z BCF PORTA,DRL MOVLW 'p' XORWF cmnd,W BTFSC STATUS,Z CALL prpos MOVLW 'q' XORWF cmnd,W BTFSC STATUS,Z CALL drsta MOVLW 'r' XORWF cmnd,W BTFSC STATUS,Z CALL relall MOVLW 'h' XORWF cmnd,W BTFSC STATUS,Z CALL help BCF flgs,7 ; clear sign and numb CLRF numb CLRF numb+1 CLRF numb+2 GOTO loop rdbuf MOVF rptr,W ; read data from buf, inc rptr ANDLW H'3F' ADDLW buf BTFSC rptr,6 ; banks 1,3 ? ADDLW H'80' MOVWF FSR BTFSC rptr,7 ; banks 2,3 ? BSF STATUS,IRP INCF rptr,F MOVF INDF,W BCF STATUS,IRP RETURN txbyte BSF STATUS,RP0 ; bank 1 txbytw BTFSS _TXSTA,1 ; wait for transmitter empty GOTO txbytw BCF STATUS,RP0 ; bank 0 MOVWF TXREG ; yes: transmit RETURN txhex MOVWF tmp1 ; display as two hex chars SWAPF tmp1,W CALL hexchr CALL txbyte MOVF tmp1,W CALL hexchr CALL txbyte MOVF tmp1,W ; restore W RETURN hexchr ANDLW H'0F' ; 0..15 to '0'..'F' MOVWF tmp0 ; store SUBLW D'09' ; check if >= 10 (carry clr) MOVLW D'48' BTFSS STATUS,C ; add 7 if carry clr ADDLW D'07' ADDWF tmp0,W RETURN txstr MOVWF tmp0 ; string output (W is offset from msg0) MOVLW B'00110' ; PCLATH to messages segment MOVWF PCLATH txstr0 MOVF tmp0,W CALL message ; get char XORLW 0 ; end of string? BTFSC STATUS,Z RETURN ; return if char is 0 CALL txbyte ; display INCF tmp0,F ; next char GOTO txstr0 ferr BSF flgs,4 ; set error flag MOVLW '!' CALL txbyte CALL relall GOTO escape endsw BTFSS flgs,6 ; terminate if endswitch touched RETLW 0 GOTO ferr stox CALL tmpnum ; dstx = numb MOVLW dstx MOVWF FSR GOTO fsr24 addx CALL tmpnum ; dstx = posx + numb MOVLW posx MOVWF FSR CALL add24 MOVLW dstx MOVWF FSR GOTO fsr24 stoy CALL tmpnum ; dsty = numb MOVLW dsty MOVWF FSR GOTO fsr24 addy CALL tmpnum ; dsty = posy + numb MOVLW posy MOVWF FSR CALL add24 MOVLW dsty MOVWF FSR GOTO fsr24 stoz CALL tmpnum ; dstz = numb MOVLW dstz MOVWF FSR GOTO fsr24 addz CALL tmpnum ; dstz = posz + numb MOVLW posz MOVWF FSR CALL add24 MOVLW dstz MOVWF FSR GOTO fsr24 setpos MOVLW D'9' ; set pos = dst MOVWF tmp0 MOVLW posx MOVWF FSR setps0 BSF FSR,7 ; page 1 MOVF INDF,W ; dst BCF FSR,7 ; page 0 MOVWF INDF ; pos INCF FSR,F DECFSZ tmp0,F GOTO setps0 RETLW 0 origin MOVLW D'9' ; set pos and dst to (0,0,0) MOVWF tmp0 MOVLW posx MOVWF FSR orig0 BSF FSR,7 ; page 1 CLRF INDF ; dst BCF FSR,7 ; page 0 CLRF INDF ; pos INCF FSR,F DECFSZ tmp0,F GOTO orig0 RETLW 0 xlate MOVLW posx ; dlt = dst - pos MOVWF FSR xlat0 BSF FSR,7 ; page 1 CALL tmp24 ; dst to tmp BCF FSR,7 ; page 0 CALL sub24 BSF STATUS,IRP ; page 2 CALL fsr24 ; save dltx BCF STATUS,IRP ; page 0 CALL tmp24 ; pos to tmp BSF FSR,7 ; page 1 CALL fsr24 ; save dst BCF FSR,7 ; page 0 BSF STATUS,IRP ; page 2 CALL sub24 ; -dlt BCF STATUS,IRP ; page 0 CALL fsr24 ; save pos MOVLW 3 ADDWF FSR,F MOVF FSR,W XORLW posx+9 BTFSS STATUS,Z GOTO xlat0 RETLW 0 iniseek CALL origin ; pos to (0,0,0) CALL holdall MOVLW H'00' ; timeout to dstz MOVWF tmp2 MOVLW H'BB' MOVWF tmp1 CLRF tmp0 MOVLW dstz MOVWF FSR CALL fsr24 MOVLW H'01' ; timeout to dsty MOVWF tmp2 MOVLW H'F4' MOVWF tmp1 CLRF tmp0 CALL neg24 MOVLW dsty MOVWF FSR CALL fsr24 MOVLW H'02' ; timeout to dstx MOVWF tmp2 MOVLW H'AF' MOVWF tmp1 CLRF tmp0 CALL neg24 MOVLW dstx MOVWF FSR CALL fsr24 BCF flgs,6 inisz MOVLW posz ; timeout if (pos == dst) CALL cmp24 BTFSC STATUS,Z GOTO iniserr CALL incz BTFSS flgs,6 GOTO inisz CALL holdall BCF flgs,6 inisy MOVLW posy ; timeout if (pos == dst) CALL cmp24 BTFSC STATUS,Z GOTO iniserr CALL decy BTFSS flgs,6 GOTO inisy CALL holdall BCF flgs,6 inisx MOVLW posx ; timeout if (pos == dst) CALL cmp24 BTFSC STATUS,Z GOTO iniserr CALL decx BTFSS flgs,6 GOTO inisx CALL holdall BCF flgs,6 CALL origin ; move 2mm away from endpoints MOVLW H'00' MOVWF tmp2 MOVLW H'06' MOVWF tmp1 MOVLW H'40' MOVWF tmp0 MOVLW dstx MOVWF FSR CALL fsr24 MOVLW dsty MOVWF FSR CALL fsr24 CALL neg24 MOVLW dstz MOVWF FSR CALL fsr24 CALL line GOTO origin iniserr GOTO relall help CLRW ; print list of available commands GOTO txstr prpos MOVLW posx ; x-position MOVWF FSR CALL tmp24 CALL txtmp MOVLW ',' CALL txbyte MOVLW posy ; y-position MOVWF FSR CALL tmp24 CALL txtmp MOVLW ',' CALL txbyte MOVLW posz ; z-position MOVWF FSR CALL tmp24 CALL txtmp MOVLW '(' CALL txbyte MOVLW dstx ; x-destination MOVWF FSR CALL tmp24 CALL txtmp MOVLW ',' CALL txbyte MOVLW dsty ; y-destination MOVWF FSR CALL tmp24 CALL txtmp MOVLW ',' CALL txbyte MOVLW dstz ; z-destination MOVWF FSR CALL tmp24 CALL txtmp MOVLW ')' CALL txbyte MOVLW ' ' CALL txbyte RETLW 0 drsta CALL hldx ; update status BCF PORTB,CSX ; read status CALL rele MOVF lind,W ; load indicator CALL hexchr CALL txbyte MOVF dsta,W ; driver status CALL txhex MOVLW ',' CALL txbyte CALL hldy ; update status BCF PORTB,CSY ; read status CALL rele MOVF lind,W ; load indicator CALL hexchr CALL txbyte MOVF dsta,W ; driver status CALL txhex MOVLW ',' CALL txbyte CALL hldz ; update status BCF PORTB,CSZ ; read status CALL rele MOVF lind,W ; load indicator CALL hexchr CALL txbyte MOVF dsta,W ; driver status CALL txhex MOVLW ',' CALL txbyte MOVF PORTA,W CALL txhex MOVLW ' ' CALL txbyte RETLW 0 holdall CALL sync ; power down motors CALL sync CALL sync CALL hldx CALL hldy CALL hldz RETLW 0 relall BCF PORTB,CSX ; chip select CALL rele BCF PORTB,CSY ; chip select CALL rele BCF PORTB,CSZ ; chip select CALL rele RETLW 0 speedh MOVLW D'63' ; 250k/63 = 4000usteps/s (300rpm) MOVWF stim RETLW 0 speedm MOVLW D'125' ; 250k/125 = 2000usteps/s (150rpm) MOVWF stim RETLW 0 speedl MOVLW D'250' ; 250k/250 = 1000usteps/s (75rpm) MOVWF stim RETLW 0 ; straight move from (posx,posy) to (dstx,dsty): bresenham algorithm line CLRF STATUS ; bank 0 CLRF rmdr ; rmdr = 0 CLRF rmdr+1 CLRF rmdr+2 linix MOVLW dstx ; dltx = dstx - posx MOVWF FSR CALL tmp24 BCF FSR,7 ; page 0 CALL sub24 BCF flgs,0 ; xi = 1 BTFSC tmp2,7 ; if (dltx < 0) BSF flgs,0 ; xi = -1 BTFSC tmp2,7 ; if (dltx < 0) CALL neg24 ; dltx = -dltx BSF STATUS,IRP ; page 2 CALL fsr24 ; save dltx BCF STATUS,IRP ; page 0 liniy MOVLW dsty ; dlty = dsty - posy MOVWF FSR CALL tmp24 BCF FSR,7 ; page 0 CALL sub24 BCF flgs,1 ; yi = 1 BTFSC tmp2,7 ; if (dlty < 0) BSF flgs,1 ; yi = -1 BTFSC tmp2,7 ; if (dlty < 0) CALL neg24 ; dlty = -dlty BSF STATUS,IRP ; page 2 CALL fsr24 ; save dlty BCF STATUS,IRP ; page 0 linck CALL neg24 ; if (dltx-dlty < 0) liney; else linex; MOVLW posx MOVWF FSR BSF STATUS,IRP ; page 2 CALL add24 BCF STATUS,IRP ; page 0 BTFSC tmp2,7 GOTO liney linex MOVLW posx ; fact = 2 * dltx CALL dbl24 MOVLW fact MOVWF FSR CALL fsr24 ; save fact MOVLW posy ; incl = 2 * dlty CALL dbl24 MOVLW rmdr MOVWF FSR BSF STATUS,IRP ; page 2 CALL fsr24 ; save incl BCF STATUS,IRP ; page 0 loopx CALL endsw ; stop if endswitch touched MOVLW posx ; if (pos == dst) done CALL cmp24 BTFSC STATUS,Z GOTO linez BTFSS flgs,0 ; posx += xi CALL incx BTFSC flgs,0 CALL decx MOVLW rmdr ; rmdr += incl MOVWF FSR CALL tmp24 BSF STATUS,IRP ; page 2 CALL add24 BCF STATUS,IRP ; page 0 CALL fsr24 MOVLW posx ; tmp = rmdr - dltx MOVWF FSR BSF STATUS,IRP ; page 2 CALL sub24 ; BCF STATUS,IRP ; page 0 BTFSC tmp2,7 ; next if (rmdr < dltx) GOTO loopx BSF flgs,3 ; step without timer sync BTFSS flgs,1 ; posy += yi CALL incy BTFSC flgs,1 CALL decy BCF flgs,3 MOVLW fact ; rmdr -= fact MOVWF FSR CALL tmp24 CALL neg24 MOVLW rmdr MOVWF FSR CALL add24 CALL fsr24 GOTO loopx liney MOVLW posy ; fact = 2 * dlty CALL dbl24 MOVLW fact MOVWF FSR CALL fsr24 ; save fact MOVLW posx ; incl = 2 * dltx CALL dbl24 MOVLW rmdr MOVWF FSR BSF STATUS,IRP ; page 2 CALL fsr24 ; save incl BCF STATUS,IRP ; page 0 loopy CALL endsw ; stop if endswitch touched MOVLW posy ; if (pos == dst) done CALL cmp24 BTFSC STATUS,Z GOTO linez BTFSS flgs,1 ; posy += yi CALL incy BTFSC flgs,1 CALL decy MOVLW rmdr ; rmdr += incl MOVWF FSR CALL tmp24 BSF STATUS,IRP ; page 2 CALL add24 BCF STATUS,IRP ; page 0 CALL fsr24 MOVLW posy ; tmp = rmdr - dlty MOVWF FSR BSF STATUS,IRP ; page 2 CALL sub24 ; BCF STATUS,IRP ; page 0 BTFSC tmp2,7 ; next if (rmdr < dlty) GOTO loopy BSF flgs,3 ; step without timer sync BTFSS flgs,0 ; posx += xi CALL incx BTFSC flgs,0 CALL decx BCF flgs,3 MOVLW fact ; rmdr -= fact MOVWF FSR CALL tmp24 CALL neg24 MOVLW rmdr MOVWF FSR CALL add24 CALL fsr24 GOTO loopy linez MOVLW dstz ; dltz = dstz - posz MOVWF FSR CALL tmp24 BCF FSR,7 ; page 0 CALL sub24 BCF flgs,2 ; zi = 1 BTFSC tmp2,7 ; if (dltz < 0) BSF flgs,2 ; zi = -1 loopz CALL endsw ; stop if endswitch touched MOVLW posz ; if (pos == dst) done CALL cmp24 BTFSC STATUS,Z GOTO holdall BTFSS flgs,2 ; posz += zi CALL incz BTFSC flgs,2 CALL decz GOTO loopz incx BTFSC PORTA,SXB ; check endswitch BSF flgs,6 INCF posx,F ; inc position BTFSC STATUS,Z INCF posx+1,F BTFSC STATUS,Z INCF posx+2,F GOTO curx decx BTFSC PORTA,SXA ; check endswitch BSF flgs,6 MOVLW 1 ; dec position SUBWF posx,F BTFSS STATUS,C SUBWF posx+1,F BTFSS STATUS,C SUBWF posx+2,F curx MOVF posx,W ; coil a CALL sin MOVWF drva MOVF posx,W ; coil b CALL cos MOVWF drvb BCF PORTB,CSX ; chip select GOTO mstep hldx MOVF posx,W ; coil a CALL sinh MOVWF drva MOVF posx,W ; coil b CALL cosh MOVWF drvb BCF PORTB,CSX ; chip select GOTO mstep incy BTFSC PORTA,SYB ; check endswitch BSF flgs,6 INCF posy,F ; inc position BTFSC STATUS,Z INCF posy+1,F BTFSC STATUS,Z INCF posy+2,F GOTO cury decy BTFSC PORTA,SYA ; check endswitch BSF flgs,6 MOVLW 1 ; dec position SUBWF posy,F BTFSS STATUS,C SUBWF posy+1,F BTFSS STATUS,C SUBWF posy+2,F cury MOVF posy,W ; coil a CALL sin MOVWF drva MOVF posy,W ; coil b CALL cos MOVWF drvb BCF PORTB,CSY ; chip select GOTO mstep hldy MOVF posy,W ; coil a CALL sinh MOVWF drva MOVF posy,W ; coil b CALL cosh MOVWF drvb BCF PORTB,CSY ; chip select GOTO mstep incz BTFSC PORTA,SZB ; check endswitch BSF flgs,6 INCF posz,F ; inc position BTFSC STATUS,Z INCF posz+1,F BTFSC STATUS,Z INCF posz+2,F GOTO curz decz BTFSC PORTA,SZA ; check endswitch BSF flgs,6 MOVLW 1 ; dec position SUBWF posz,F BTFSS STATUS,C SUBWF posz+1,F BTFSS STATUS,C SUBWF posz+2,F curz MOVF posz,W ; coil a CALL sin MOVWF drva MOVF posz,W ; coil b CALL cos MOVWF drvb BCF PORTB,CSZ ; chip select GOTO mstep hldz MOVF posz,W ; coil a CALL sinh MOVWF drva MOVF posz,W ; coil b CALL cosh MOVWF drvb BCF PORTB,CSZ ; chip select GOTO mstep sync BTFSC flgs,3 ; skp set: skip synch timer GOTO sync1 sync0 BTFSS PIR1,0 ; wait for timer1 GOTO sync0 MOVF stim,W ; set new timer SUBWF TMR1L,F MOVLW H'FF' MOVWF TMR1H BCF PIR1,0 CLRWDT sync1 MOVLW B'11111111' ; chip selects, sdo, sck high MOVWF PORTB RETURN mstep BCF PORTB,SCK ; mixed decay A BSF PORTB,SDO BTFSS drva,5 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current A.3 BSF PORTB,SDO BTFSS drva,3 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current A.2 BSF PORTB,SDO BTFSS drva,2 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current A.1 BSF PORTB,SDO BTFSS drva,1 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current A.0 BSF PORTB,SDO BTFSS drva,0 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; polarity A BSF PORTB,SDO BTFSS drva,4 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; mixed decay B BSF PORTB,SDO BTFSS drvb,5 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current B.3 BSF PORTB,SDO BTFSS drvb,3 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current B.2 BSF PORTB,SDO BTFSS drvb,2 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current B.1 BSF PORTB,SDO BTFSS drvb,1 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; current B.0 BSF PORTB,SDO BTFSS drvb,0 BCF PORTB,SDO BSF PORTB,SCK BCF PORTB,SCK ; polarity B BSF PORTB,SDO BTFSS drvb,4 BCF PORTB,SDO BSF PORTB,SCK GOTO sync rele CLRF lind ; release currents, read status CLRF dsta BCF PORTB,SCK ; mixed decay A BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check LD2 BSF lind,3 BCF PORTB,SCK ; current A.3 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check LD1 BSF lind,2 BCF PORTB,SCK ; current A.2 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check LD0 BSF lind,1 BCF PORTB,SCK ; current A.1 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check 1 BSF lind,0 BCF PORTB,SCK ; current A.0 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OT BSF dsta,7 BCF PORTB,SCK ; polarity A BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OTPW BSF dsta,6 BCF PORTB,SCK ; mixed decay B BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check UV BSF dsta,5 BCF PORTB,SCK ; current B.3 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OCHS BSF dsta,4 BCF PORTB,SCK ; current B.2 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OLB BSF dsta,3 BCF PORTB,SCK ; current B.1 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OLA BSF dsta,2 BCF PORTB,SCK ; current B.0 BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OCB BSF dsta,1 BCF PORTB,SCK ; polarity B BCF PORTB,SDO ; 0 BSF PORTB,SCK BTFSC PORTB,SDI ; check OCA BSF dsta,0 GOTO sync mul10 BCF STATUS,C ; tmp *= 10 RLF tmp0,F ; tmp *= 2; numb = tmp * 2; MOVF tmp0,W MOVWF numb RLF tmp1,F MOVF tmp1,W MOVWF numb+1 RLF tmp2,F MOVF tmp2,W MOVWF numb+2 RLF numb,F ; numb = tmp * 4; RLF numb+1,F RLF numb+2,F RLF numb,F ; numb = tmp * 8; RLF numb+1,F RLF numb+2,F addnum MOVF numb,W ; tmp += numb ADDWF tmp0,F MOVF numb+1,W BTFSC STATUS,C INCFSZ numb+1,W ADDWF tmp1,F MOVF numb+2,W BTFSC STATUS,C INCFSZ numb+2,W ADDWF tmp2,F RETLW 0 ; carry set at overflow txtmp MOVLW D'7' ; decimal tx of tmp (uses numb, rmdr) MOVWF rmdr ; digit counter BSF flgs,5 ; leading zero suppression MOVLW '-' ; tx sign if negative BTFSC tmp2,7 CALL txbyte BTFSC tmp2,7 ; |tmp| if negative CALL neg24 BTFSS flgs,5 ; skip mul10 first time nextdig CALL mul10 CLRF rmdr+1 ; digit counter MOVLW H'0F' ; numb = 1000000 MOVWF numb+2 MOVLW H'42' MOVWF numb+1 MOVLW H'40' MOVWF numb MOVLW numb ; FSR to numb MOVWF FSR loopsub INCF rmdr+1,F ; looped sub 1000000 CALL sub24 BTFSC STATUS,C ; until < 0 GOTO loopsub CALL add24 ; restore: add 1000000 DECF rmdr+1,W ; digit to W BTFSS STATUS,Z BCF flgs,5 ; leading zero supression off ADDLW '0' BTFSS flgs,5 ; output if lz flag off CALL txbyte DECFSZ rmdr,F ; next digit GOTO nextdig MOVLW '0' ; done: BTFSC flgs,5 ; tx '0' if lz flag still on CALL txbyte RETLW 0 tmpnum MOVF numb,W ; tmp2..tmp0 = sign*numb; numb = 0 MOVWF tmp0 MOVF numb+1,W MOVWF tmp1 MOVF numb+2,W MOVWF tmp2 BTFSC flgs,7 CALL neg24 RETLW 0 tmp24 MOVF INDF,W ; tmp2..tmp0 = FSR[2..0] MOVWF tmp0 INCF FSR,F MOVF INDF,W MOVWF tmp1 INCF FSR,F MOVF INDF,W MOVWF tmp2 DECF FSR,F DECF FSR,F RETLW 0 fsr24 MOVF tmp0,W ; FSR[2..0] = tmp2..tmp0 MOVWF INDF INCF FSR,F MOVF tmp1,W MOVWF INDF INCF FSR,F MOVF tmp2,W MOVWF INDF DECF FSR,F DECF FSR,F RETLW 0 neg24 COMF tmp0,F ; tmp2..tmp0 = -(tmp2..tmp0) COMF tmp1,F COMF tmp2,F INCF tmp0,F ; + 1 BTFSC STATUS,Z INCF tmp1,F BTFSC STATUS,Z INCF tmp2,F RETLW 0 cmp24 MOVWF FSR ; Z if pos == dst BSF FSR,7 ; page 1 MOVF INDF,W BCF FSR,7 ; page 0 XORWF INDF,W BTFSS STATUS,Z RETURN INCF FSR,F BSF FSR,7 ; page 1 MOVF INDF,W BCF FSR,7 ; page 0 XORWF INDF,W BTFSS STATUS,Z RETURN INCF FSR,F BSF FSR,7 ; page 1 MOVF INDF,W BCF FSR,7 ; page 0 XORWF INDF,W RETURN dbl24 MOVWF FSR ; tmp2..tmp0 = 2*dlt BSF STATUS,IRP ; page 2 BCF STATUS,C RLF INDF,W MOVWF tmp0 INCF FSR,F RLF INDF,W MOVWF tmp1 INCF FSR,F RLF INDF,W MOVWF tmp2 BCF STATUS,IRP ; page 0 RETLW 0 add24 MOVF INDF,W ; tmp2..tmp0 += FSR[2..0] ADDWF tmp0,F INCF FSR,F MOVF INDF,W BTFSC STATUS,C INCFSZ INDF,W ADDWF tmp1,F INCF FSR,F MOVF INDF,W BTFSC STATUS,C INCFSZ INDF,W ADDWF tmp2,F DECF FSR,F DECF FSR,F RETLW 0 ; carry set at overflow sub24 MOVF INDF,W ; tmp2..tmp0 -= FSR[2..0] SUBWF tmp0,F INCF FSR,F MOVF INDF,W BTFSS STATUS,C INCFSZ INDF,W SUBWF tmp1,F INCF FSR,F MOVF INDF,W BTFSS STATUS,C INCFSZ INDF,W SUBWF tmp2,F DECF FSR,F DECF FSR,F RETLW 0 ; carry cleared at underflow ORG H'0600' ; sine wave tables sin ANDLW H'0F' ; sinus for phase A ADDWF PCL,F ; return byte from table below RETLW H'00' ; sin(0) RETLW H'06' ; sin(22.5) RETLW H'0B' ; sin(45) RETLW H'0E' ; sin(67.5) RETLW H'0F' ; sin(90) RETLW H'0E' ; sin(112.5) RETLW H'0B' ; sin(135) RETLW H'06' ; sin(157.5) RETLW H'00' ; sin(180) RETLW H'16' ; sin(202.5) RETLW H'1B' ; sin(225) RETLW H'1E' ; sin(247.5) RETLW H'1F' ; sin(270) RETLW H'1E' ; sin(292.5) RETLW H'1B' ; sin(315) RETLW H'16' ; sin(337.5) cos ANDLW H'0F' ; cosinus for phase B ADDWF PCL,F ; return byte from table below RETLW H'0F' ; cos(0) RETLW H'0E' ; cos(22.5) RETLW H'0B' ; cos(45) RETLW H'06' ; cos(67.5) RETLW H'00' ; cos(90) RETLW H'16' ; cos(112.5) RETLW H'1B' ; cos(135) RETLW H'1E' ; cos(157.5) RETLW H'1F' ; cos(180) RETLW H'1E' ; cos(202.5) RETLW H'1B' ; cos(225) RETLW H'16' ; cos(247.5) RETLW H'00' ; cos(270) RETLW H'06' ; cos(292.5) RETLW H'0B' ; cos(315) RETLW H'0E' ; cos(337.5) sinh ANDLW H'0F' ; sinus, half currents ADDWF PCL,F ; return byte from table below RETLW H'00' ; sin(0) RETLW H'03' ; sin(22.5) RETLW H'05' ; sin(45) RETLW H'07' ; sin(67.5) RETLW H'08' ; sin(90) RETLW H'07' ; sin(112.5) RETLW H'05' ; sin(135) RETLW H'03' ; sin(157.5) RETLW H'00' ; sin(180) RETLW H'13' ; sin(202.5) RETLW H'15' ; sin(225) RETLW H'17' ; sin(247.5) RETLW H'18' ; sin(270) RETLW H'17' ; sin(292.5) RETLW H'15' ; sin(315) RETLW H'13' ; sin(337.5) cosh ANDLW H'0F' ; cosinus, half currents ADDWF PCL,F ; return byte from table below RETLW H'08' ; cos(0) RETLW H'07' ; cos(22.5) RETLW H'05' ; cos(45) RETLW H'03' ; cos(67.5) RETLW H'00' ; cos(90) RETLW H'13' ; cos(112.5) RETLW H'15' ; cos(135) RETLW H'17' ; cos(157.5) RETLW H'18' ; cos(180) RETLW H'17' ; cos(202.5) RETLW H'15' ; cos(225) RETLW H'13' ; cos(247.5) RETLW H'00' ; cos(270) RETLW H'03' ; cos(292.5) RETLW H'05' ; cos(315) RETLW H'07' ; cos(337.5) message ADDWF PCL,F ; return char from table below msg0 RETLW 'e' RETLW 'l' RETLW 'p' RETLW ',' RETLW ' ' RETLW '-' RETLW '4' RETLW '1' RETLW '9' RETLW '4' RETLW '3' RETLW '0' RETLW '3' RETLW '.' RETLW '.' RETLW '4' RETLW '1' RETLW '9' RETLW '4' RETLW '3' RETLW '0' RETLW '3' RETLW ' ' RETLW '(' RETLW '*' RETLW '1' RETLW '.' RETLW '2' RETLW '5' RETLW 'u' RETLW 'm' RETLW ')' RETLW ' ' RETLW 'x' RETLW '|' RETLW 'y' RETLW '|' RETLW 'z' RETLW ' ' RETLW 'a' RETLW 'b' RETLW 's' RETLW 'o' RETLW 'l' RETLW 'u' RETLW 't' RETLW 'e' RETLW ',' RETLW ' ' RETLW 'X' RETLW '|' RETLW 'Y' RETLW '|' RETLW 'Z' RETLW ' ' RETLW 'r' RETLW 'e' RETLW 'l' RETLW 'a' RETLW 't' RETLW 'i' RETLW 'v' RETLW 'e' RETLW ',' RETLW ' ' RETLW 'm' RETLW 'o' RETLW 'v' RETLW 'e' RETLW ',' RETLW ' ' RETLW 's' RETLW 'e' RETLW 't' RETLW ',' RETLW ' ' RETLW 'o' RETLW 'r' RETLW 'i' RETLW 'g' RETLW 'i' RETLW 'n' RETLW ',' RETLW ' ' RETLW 't' RETLW 'r' RETLW 'a' RETLW 'n' RETLW 's' RETLW 'l' RETLW 'a' RETLW 't' RETLW 'e' RETLW ',' RETLW ' ' RETLW 'i' RETLW 'n' RETLW 'i' RETLW 't' RETLW 'i' RETLW 'a' RETLW 'l' RETLW 'i' RETLW 'z' RETLW 'e' RETLW ',' RETLW ' ' RETLW 'r' RETLW 'e' RETLW 'l' RETLW 'e' RETLW 'a' RETLW 's' RETLW 'e' RETLW ',' RETLW ' ' RETLW 'p' RETLW 'r' RETLW 'i' RETLW 'n' RETLW 't' RETLW ',' RETLW ' ' RETLW 'q' RETLW 'u' RETLW 'e' RETLW 'r' RETLW 'y' RETLW ',' RETLW ' ' RETLW 'n' RETLW '|' RETLW 'f' RETLW ' ' RETLW 'o' RETLW 'n' RETLW ' ' RETLW 'o' RETLW 'f' RETLW 'f' RETLW ',' RETLW ' ' RETLW 'H' RETLW '|' RETLW 'M' RETLW '|' RETLW 'L' RETLW ' ' RETLW 's' RETLW 'p' RETLW 'e' RETLW 'e' RETLW 'd' RETLW ',' RETLW ' ' RETLW 'c' RETLW 'l' RETLW 'e' RETLW 'a' RETLW 'r' RETLW ',' RETLW ' ' RETLW 'E' RETLW 'S' RETLW 'C' RETLW ' ' RETLW 0 ; simple flash boot loader, write to program memory below 0x700 ; start with "UL", wait for erase, send hex record, wait ... ; upload can be done with this little perl script: ; ; #!/usr/bin/perl -w ; ($#ARGV >= 0) || die "usage: $0 hexfile > /dev/ttyS0\n"; ; $| = 1; sub wt {select(undef, undef, undef, shift);} ; print "UL"; wt(0.5); while (<>) {chomp; print; wt(0.1);} ORG H'0700' ; boot loader location bolo CALL boloc ; first char is 'U'? XORLW 'U' BTFSS STATUS,Z RETURN ; no: return bolon CALL boloc XORLW 'L' ; second char is 'L'? BTFSS STATUS,Z GOTO bolor ; no: reset BSF STATUS,RP1 ; bank 2 CLRF _EEADRH CLRF _EEADR boloe BSF STATUS,RP0 ; bank 3 BSF _EECON1,7 BSF _EECON1,2 BSF _EECON1,4 CALL bolow BCF STATUS,RP0 ; bank 2 MOVLW D'32' ADDWF _EEADR,F BTFSC STATUS,C INCF _EEADRH,F MOVLW H'7' ; done if at 0x700 XORWF _EEADRH,W BTFSS STATUS,Z GOTO boloe BSF STATUS,RP0 ; bank 3 CLRF _EECON1 CLRF STATUS ; bank 0 bolol CALL boloc ; wait for new hex record XORLW ':' BTFSS STATUS,Z GOTO bolol CLRF BRAM+2 ; checksum CALL bolox MOVWF BRAM+3 ; count CALL bolox MOVWF BRAM+4 ; address high byte CALL bolox MOVWF BRAM+5 ; address low byte ANDLW H'07' ; offset to FSR MOVWF FSR BCF STATUS,C ; addr/2 RRF BRAM+4,F RRF BRAM+5,F MOVLW H'FC' ; 4 word boundary ANDWF BRAM+5,F MOVLW H'07' ; address < 0x700 ? SUBWF BRAM+4,W BTFSC STATUS,C GOTO bolol CALL bolox MOVWF BRAM+6 DECF BRAM+6,W ; type == 01 ? (eof) BTFSC STATUS,Z GOTO bolor ; ok: reset MOVF BRAM+6,W ; type != 00 ? (unknown) BTFSS STATUS,Z GOTO bolol MOVF BRAM+3,W ; count == 00 ? BTFSC STATUS,Z GOTO bolol ADDWF FSR,W ; words = (count+offset+7)/8*4 ADDLW D'7' MOVWF BRAM+6 RRF BRAM+6,F MOVLW H'7C' ANDWF BRAM+6,F MOVLW BRAM+8 ; index to buffer start + offset ADDWF FSR,F bolod CALL bolox ; read count data bytes MOVWF INDF INCF FSR,F DECFSZ BRAM+3,F GOTO bolod CALL bolox ; read checksum MOVF BRAM+2,W BTFSS STATUS,Z GOTO bolol BSF STATUS,RP1 ; bank 2 BSF STATUS,RP0 ; bank 3 BSF _EECON1,7 BSF _EECON1,2 CLRF STATUS ; bank 0 MOVF BRAM+4,W BSF STATUS,RP1 ; bank 2 MOVWF _EEADRH BCF STATUS,RP1 ; bank 0 MOVF BRAM+5,W BSF STATUS,RP1 ; bank 2 MOVWF _EEADR BCF STATUS,RP1 ; bank 0 MOVLW BRAM+8 ; buffer start (no offset) MOVWF FSR BCF INTCON,7 ; disable interrupts bolof BSF STATUS,RP1 ; bank 2 MOVF INDF,W ; low byte MOVWF _EEDATA INCF FSR,F MOVF INDF,W ; high byte MOVWF _EEDATH INCF FSR,F BSF STATUS,RP0 ; bank 3 CALL bolow BCF STATUS,RP0 ; bank 2 INCF _EEADR,F CLRF STATUS ; bank 0 DECFSZ BRAM+6,F ; all words done? GOTO bolof ; next word BSF STATUS,RP1 ; bank 2 BSF STATUS,RP0 ; bank 3 BCF _EECON1,2 CLRF STATUS ; bank 0 NOP ; enable interrupts? GOTO bolol ; next record bolor CLRF PCLATH ; reset GOTO 0 bolow MOVLW H'55' ; flash sequence (in bank 3) MOVWF _EECON2 MOVLW H'AA' MOVWF _EECON2 BSF _EECON1,1 NOP NOP RETURN bolox CALL boloh ; receive two digit hex byte MOVWF BRAM+1 SWAPF BRAM+1,F CALL boloh IORWF BRAM+1,W ADDWF BRAM+2,F ; update checksum RETURN boloh CALL boloc ; receive hex char MOVWF BRAM+0 BTFSC BRAM+0,6 ADDLW H'09' ANDLW H'0F' RETURN boloc CLRWDT BTFSS PIR1,5 ; receive char GOTO boloc MOVF RCREG,W RETURN END;