TITLE "Accessory encoder PC interface" ; filename Ace_PC1.asm ; By Mike Bolton ; Started 03/07/04 ; Tested and working 14/07/04. Uses PCB Ace_PC1 ; ; Interfaces a serial data connection to the MERG accessory encoder ; Accessory encoder is unmodified ; Interface has a jumper / switch to change between PC and control panel ; Serial at 9600B. No handshake, 9 way D connector ; Command with ASCII string ; S and point number sets point one way. (S = straigth) ; T and point number sets the other way. (T = turn) ; Point numbers 1 to 128 ; 1 to 4 is decoder address 0, 5 to 8 is address 1 etc. ; Used PIC 18F4220 with internal clock at 8 MHz ; Assembly options LIST P=18F4220,r=hex,N=75,C=120,T=ON include "p18f4220.inc" ;set config registers __CONFIG _CONFIG1H, B'00001000' ;oscillator internal, RA6, RA7 as I/O __CONFIG _CONFIG2L, B'00000010' ;brown out on voltage = 4.5, and PWT on __CONFIG _CONFIG2H, B'00000000' ;watchdog time and enable. WDT is off __CONFIG _CONFIG3H, B'10000001' ;MCLR enable, PB as digital I/O __CONFIG _CONFIG4L, B'10000001' ;B'10000001' for no debug __CONFIG _CONFIG5L, B'00001111' ;code protection (off) __CONFIG _CONFIG5H, B'11000000' ;code protection (off) __CONFIG _CONFIG6L, B'00001111' ;write protection (off) __CONFIG _CONFIG6H, B'11100000' ;write protection (off) __CONFIG _CONFIG7L, B'00001111' ;table read protection (off) __CONFIG _CONFIG7H, B'01000000' ;boot block protection (off) ; processor uses 8 MHz internal clock ;******************************************************************************** MOD equ 4 ;Mode pin RC4 (CP is hi, PC is lo) EN equ 0 ;RC0 is matrix enable, lo is matrix, hi is PC RXD equ 7 ;RXD on port c pin 7 Baudrate equ .51 ;for 9600 Baud ;**************************************************************** ; define RAM storage CBLOCK 0 ;file registers Mode ;mode 0 is no PC, mode 1 is PC enabled Colcnt ;column counter Point ;pointer for data stack Col_a ;column read from port A Col_b ;column read from port B Bitcnt ;bit pattern for columns Rmode ;mode for serial input Chr_tmp ;temp for serial char input Chr_cnt ;count number of chars Set_dir ;point direction Number ;point number Dely ;delay counter Bit ;bit to set / clear in stack register Temp ;temp store Stack ;array of point positions Stack1 ;full list for debugging purposes Stack2 Stack3 Stack4 Stack5 Stack6 Stack7 Stack8 Stack9 Stack10 Stack11 Stack12 Stack13 Stack14 Stack15 String ;ASCII digits for point number (1 to 128) String1 String2 ENDC ;Stack res .16 ;stack for output data for each column ;String res 3 ;hold ascii number CBLOCK h'80' ENDC ;**************************************************************** ; ; start of program code ORG 0000h nop ;for debug goto setup ORG 0008h goto hpint ;high priority interrupt ORG 0018h goto hpint ;low priority interrupt ;******************************************************************* ORG 0020h ;start of program ; high priority interrupt. ; ; hpint movf RCREG,W ;get serial byte movwf Chr_tmp tstfsz Rmode ;what mode? bra ser1 movlw 'S' ;straight? cpfseq Chr_tmp bra next clrf Set_dir int2 incf Rmode clrf Chr_cnt retfie 1 ;not a valid char next movlw 'T' cpfseq Chr_tmp retfie 1 incf Set_dir bra int2 ser1 movlw 0x0D ;?carraige return cpfseq Chr_tmp bra num tstfsz Chr_cnt ;no chars? bra parse bra back parse movlw 4 cpfslt Chr_cnt ;no more than 3 chars bra back movf POSTDEC1,W ;dummy to decrement FSR1 decf Chr_cnt,F rlncf Chr_cnt,W ;double the jump addwf PCL ;convert number to binary bra one bra two movf POSTDEC1,W ;get last char movwf Number movlw .10 mulwf POSTDEC1 movf PRODL,W addwf Number,F movlw 1 subwf INDF1,W bnz back ;can't be other than one movlw .100 addwf Number,F bra putin two movf POSTDEC1,W ;get last char movwf Number movlw .10 mulwf POSTDEC1 movf PRODL,W addwf Number,F bra putin one movf POSTDEC1,W ;get last char movwf Number putin movf Number,F ;is it zero? btfsc STATUS,Z bra back ;abort decf Number,F ;point 1 = 0 btfsc Number,7 ;127 max bra back clrf Point rrcf Number,F rrcf Point,F rrcf Number,F rrcf Point,F rrcf Number,F ;Number now has stack register rrcf Point,F rrncf Point,F swapf Point,F ;Point has the bit number in the register (0 to 7) incf Point,F movlw B'00001111' andwf Number,F ;mask movlw 1 movwf Bit nxtbit decf Point,F ;this sets a bit in Bit corresponding to the point bz done rlncf Bit,F bra nxtbit done tstfsz Set_dir ;is it straight or turn? bra turn comf Bit movf Number,W movf PLUSW0,W andwf Bit,F ;clear bit movf Number,W movff Bit,PLUSW0 bra back turn movf Number,W movf PLUSW0,W iorwf Bit,F ;set bit movf Number,W movff Bit,PLUSW0 bra back num movf Chr_tmp,W rcall ascii bnc back ;not a number movwf POSTINC1 incf Chr_cnt retfie 1 back clrf Rmode clrf Chr_cnt lfsr 1,String ;reset pointer retfie 1 ascii addlw 0xC6 ;check for number bc over ;not a number addlw 0x0A bnc over return over bcf STATUS,C return ;************************************************************** ; ; lpint retfie ;********************************************************************* setup movlw B'01110011' ;set oscillator movwf OSCCON ;8 MHz internal clrf LATA ;set port A movlw B'11111111' ;A is all inputs movwf TRISA clrf LATB ;set port B movlw B'11111111' ;B is all inputs movwf TRISB clrf LATC ;set port C movlw B'10010000' ;C serial, RC7 is RXD, RC0 is matrix enable, RC4 is mode detect movwf TRISC clrf LATD ;set port D movlw B'11111111' ;D is all inputs on reset movwf TRISD clrf LATE ;set port E movlw B'00000000' ;E is all outputs (port not used) movwf TRISE clrf ADCON0 ;A/D off movlw 0x0F movwf ADCON1 ;A/D all digital inputs bsf RCON, IPEN ;enable high priority interrupts movlw 7 movwf CMCON ;turn off comparator clrf EECON1 ;ensure data EEPROM movlw B'00000100' ;set USART, baud rate range high movwf TXSTA movlw Baudrate ;set baud rate to 9600 movwf SPBRG bsf RCSTA,SPEN bsf PIE1,RCIE ;enable RXD interrupt bsf IPR1,RCIP ;RXD is high priority bsf RCSTA,CREN clrf Rmode clrf Mode clrf Col_a clrf Col_b movlw .16 movwf Point lfsr 0,Stack ;set stack pointer in FSR0 clear clrf POSTINC0 ;clear stack decfsz Point bra clear lfsr 0,Stack ;reset stack pointer lfsr 1,String ;set string pointer in FSR1 clrf PIR1 ;clear USART movlw B'11000000' movwf INTCON ;set interrupt enable ; main scan loop loop_a btfss PORTC,MOD ;what mode? bra pc1 tstfsz Mode ;if mode is 0 already set to CP bra pc2 ;otherwise set port to CP loop_a0 comf PORTA,W ;get port A data bz loop_b ;no cols. in port A set cpfseq Col_a ;any change from last time? bra loop_a1 ;yes so continue bra loop_a ;try again loop_a1 rcall delay ;delay for edges comf PORTA,W ;read again movwf Col_a ;new data to Col_a clrf Colcnt ;which column is it? clrf Bitcnt incf Bitcnt ;Bit count starts at one loop_a2 cpfseq Bitcnt ;Is it this bit? bra loop_a3 ;no movf Colcnt,W ;get raw column bit (0 to 15) movwf EEADR ;mapping in EEPROM bcf EECON1,EEPGD bsf EECON1,RD movf EEDATA,W comf PLUSW0,W ;get byte from stack and invert movwf Temp rlncf Temp,F ;adjust for pinout rlncf Temp,W movwf PORTD ;put out bra loop_a ;repeat loop_a3 incf Colcnt,F ;try next column bit rlncf Bitcnt bra loop_a2 loop_b clrf Col_a comf PORTB,W ;get B input ; andlw B'00111111' ;for debugger which uses PB6 and PB7 cpfseq Col_b ;any change from last time? bra loop_b1 ;yes so continue bra loop_a ;try again loop_b1 rcall delay comf PORTB,W ; andlw B'00111111' ;debug movwf Col_b ;new data to Col_b clrf Colcnt ;which column is it? clrf Bitcnt incf Bitcnt ;Bit count starts at one loop_b2 cpfseq Bitcnt ;Is it this bit? bra loop_b3 ;no movf Colcnt,W ;get raw column bit (0 to 15) addlw 8 ;offset movwf EEADR ;mapping in EEPROM nop bsf EECON1,RD movf EEDATA,W comf PLUSW0,W ;get byte from stack movwf Temp rlncf Temp,F ;adjust for pinout rlncf Temp,W movwf PORTD ;put out bra loop_a ;repeat loop_b3 incf Colcnt,F ;try next column bit btfsc Colcnt,3 ;limit to 7 bra loop_a ;as above rlncf Bitcnt bra loop_b2 pc1 movf Mode,F ;is mode set? bnz loop_a0 ;is in PC mode rcall pcset bra loop_a0 ;back pc2 rcall pcunset bra loop_a0 ;back delay movlw .20 movwf Dely del1 decfsz Dely bra del1 return pcset bsf PORTC,EN ;CP buffer to tri-state clrf TRISD ;PORTD to output incf Mode,F ;set mode to PC return pcunset setf TRISD ;port to inputs bcf PORTC,EN ;CP buffer on clrf Mode ;set to CP return ORG 0xF00000 ;EEPROM data. Column translation table de .10,.11 de .8,.9 de .14,.15 de .13,.12 de .0,.2 de .1,.3 de .4,.5 de .6,.7 end