Difference between revisions of "Bemix PIC code"
From SlugWiki
Line 1: | Line 1: | ||
− | This is the first stable (2/4/05) version of the Bemix firmware. The latest version can be obtained from svn:// | + | This is the first stable (2/4/05) version of the Bemix firmware. The latest version can be obtained from [http://bemix.mit.edu/svn/fourtheast/browse/bemix-pic/touchswitch/ svn://bemix.mit.edu/var/svn/repos/bemix-pic/touchswitch]. |
The touch switches are polled in the main loop of the program. Each touch switch has a function that is called when it is touched. This makes it easy to change how each touch switch behaves (single shot, fast reapeat, slow repeat, etc). | The touch switches are polled in the main loop of the program. Each touch switch has a function that is called when it is touched. This makes it easy to change how each touch switch behaves (single shot, fast reapeat, slow repeat, etc). |
Revision as of 19:01, 7 June 2006
This is the first stable (2/4/05) version of the Bemix firmware. The latest version can be obtained from svn://bemix.mit.edu/var/svn/repos/bemix-pic/touchswitch.
The touch switches are polled in the main loop of the program. Each touch switch has a function that is called when it is touched. This makes it easy to change how each touch switch behaves (single shot, fast reapeat, slow repeat, etc).
The serial port is monitored by the interrupt. Each recieved byte is put in a buffer. The buffer is cleared whenever a packet header is recieved. Thus, when the end code is recieved, the buffer contains the entire packet (minus the header code). If the packet is addressed to this unit then rcvPacket is called to process the packet.
;;; ========================================= ;;; BEMIX 3.0 PIC CODE ;;; version 1.0 ;;; ========================================= LIST p=16f627 #include <P16F627.inc> errorlevel -302 __CONFIG _BODEN_OFF & _CP_OFF & _DATA_CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF & _MCLRE_ON & _INTRC_OSC_NOCLKOUT ;;------------------------------------------------------------------------------------------- ;; Touch switch variables ;; oldPortA equ 0x20 portATemp equ 0x21 portAChange equ 0x22 TS_ENABLE EQU 6 ; on PORTA CBLOCK 0x23 sw2count sw3count ; sw4count: 2 ; sw5count: 2 ENDC ;;------------------------------------------------------------------------------------------- ;; Serial port variables and constants ;; SPBRG_VAL EQU .25 ; 9600 at 4 MHz ESC_CHAR EQU '\\' HEADER_CHAR EQU 'H' END_CHAR EQU 'E' ADDRESS EQU 'b' SERVER_ADDRESS EQU 0x01 DEBUG_PORT EQU .31 PING_PORT EQU .32 BEMIX_PORT EQU .64 TX_ENABLE EQU 3 ; on PORTB RX_BUFFER_SIZE EQU .32 TX_BUFFER_SIZE EQU .32 CBLOCK 0x31 TxPtr TxEndPtr TxTemp TxHeader: 0x02 TxPort TxBuffer: TX_BUFFER_SIZE ENDC CBLOCK 0xA0 RxFlags RxPtr RxEndPtr RxTemp RxBuffer: RX_BUFFER_SIZE ENDC ; RxFlags escRcv equ 0 ;last character revieved was the esc char H equ 1 ;currently reading the header toMe equ 3 ;transmission addressed to this unit ;;------------------------------------------------------------------------------------------- ;; Interrupt context saving ;; CBLOCK 0x70 WREG_TEMP STATUS_TEMP PCLATH_TEMP FSR_TEMP ENDC ;; PUSH_MACRO ;; stores W, STATUS, PCLATH, FSR for context saving during interrupt PUSH_MACRO MACRO movwf WREG_TEMP movf STATUS,W clrf STATUS movwf STATUS_TEMP movf PCLATH,W movwf PCLATH_TEMP clrf PCLATH movf FSR,W movwf FSR_TEMP ENDM ;; POP_MACRO ;; restores W, STATUS, PCLATH, FSR for context restoration during interrupt POP_MACRO MACRO clrf STATUS movf FSR_TEMP,W movwf FSR movf PCLATH_TEMP,W movwf PCLATH movf STATUS_TEMP,W movwf STATUS swapf WREG_TEMP,F swapf WREG_TEMP,W ENDM ;;------------------------------------------------------------------------------------------- ;; Serial Macros ;; ; transmit_macro ; transmits the entire TxBuffer to the specified destination and port transmit_macro MACRO destination, port banksel TxBuffer movlw port movwf TxPort movlw destination call transmit ENDM ; transmitByte_macro ; transmits the argument, bypassing the TxBuffer transmitByte_macro MACRO byte movlw byte call transmitByte ENDM ; putTxBuffer_macro ; adds the argument to the end of the TxBuffer putTxBuffer_macro MACRO byte movlw byte call putTxBuffer ENDM ;;------------------------------------------------------------------------------------------- ;; ORGs ;; org 0x000 goto start org 0x004 goto interrupt ;;------------------------------------------------------------------------------------------- ;; Main Program ;; start: ; initialize PORTA banksel PORTA clrf PORTA banksel CMCON movlw 0x07 movwf CMCON banksel TRISA movlw B'00111111' movwf TRISA banksel PORTA clrf PORTA ; initialize PORTB banksel TRISB movlw B'11000111' movwf TRISB banksel PORTB movlw 0xff movwf PORTB ; initialize USART banksel SPBRG ; set baud rate movlw SPBRG_VAL movwf SPBRG banksel TXSTA ; enable transmission and high baud rate movlw 0x24 movwf TXSTA banksel RCSTA ; enable serial port and reception movlw 0x90 movwf RCSTA ; initialize interrupts movlw 0xc0 ; enable global and peripheral ints movwf INTCON banksel PIE1 ; enable Rx interrupt bsf PIE1, RCIE ; initilize touch switches banksel oldPortA clrf oldPortA clrf portAChange call enableTouchSwitch ; initialize Rx and Tx buffers call resetTxBuffer call resetRxBuffer banksel RxFlags clrf RxFlags ; send test packet putTxBuffer_macro 'B' putTxBuffer_macro 'e' putTxBuffer_macro 'm' putTxBuffer_macro 'i' putTxBuffer_macro 'x' putTxBuffer_macro ' ' putTxBuffer_macro 'v' putTxBuffer_macro '3' putTxBuffer_macro '.' putTxBuffer_macro '0' transmit_macro SERVER_ADDRESS, DEBUG_PORT mainLoop: ; poll touch switches banksel PORTA movfw PORTA movwf portATemp xorwf oldPortA, W andwf PORTA, W movwf portAChange movfw portATemp movwf oldPortA banksel PORTA btfsc PORTA,0 call btn1pushed banksel PORTA btfsc PORTA,1 call btn2pushed banksel PORTA btfsc PORTA,2 call btn3pushed banksel PORTA btfsc PORTA,3 call btn4pushed banksel PORTA btfsc PORTA,4 call btn5pushed goto mainLoop ;;------------------------------------------------------------------------------------------- ;; Touch Switchs ;; ;; Touch Switch 1 - on/off ;; no repeat btn1pushed: call resetTxBuffer ; clear Tx buffer banksel portAChange btfss portAChange, 0 ; test portAChange for switch 1 return ; if change, transmit '1' putTxBuffer_macro '1' transmit_macro SERVER_ADDRESS, BEMIX_PORT return ;; Touch Switch 2 - volume up ;; fast repeat btn2pushed: call resetTxBuffer ; clear Tx buffer banksel portAChange btfsc portAChange, 3 ; clear sw2count when first touched clrf sw2count incf sw2count, F ; increment sw2count btfss STATUS, Z ; if sw2count rolled over, transmit '2' return putTxBuffer_macro '2' transmit_macro SERVER_ADDRESS, BEMIX_PORT return ;; Touch Switch 3 - volume down ;; fast repeat btn3pushed: call resetTxBuffer banksel portAChange btfsc portAChange, 4 clrf sw3count incf sw3count, F btfss STATUS, Z return putTxBuffer_macro '3' transmit_macro SERVER_ADDRESS, BEMIX_PORT return ;; Touch Switch 4 ;; no repeat btn4pushed: call resetTxBuffer banksel portAChange btfss portAChange, 3 return putTxBuffer_macro '4' transmit_macro SERVER_ADDRESS, BEMIX_PORT return ;; Touch Switch 5 ;; no repeat btn5pushed: call resetTxBuffer banksel portAChange btfss portAChange, 4 return putTxBuffer_macro '5' transmit_macro SERVER_ADDRESS, BEMIX_PORT return ;;------------------------------------------------------------------------------------------- ;; Interrupt/Reception ;; ; resetRxBuffer ; sets RxPtr and RxEndPtr to their starting locations resetRxBuffer: banksel RxBuffer movlw RxBuffer movwf RxPtr movwf RxEndPtr return ; putRxBuffer ; adds contents of W to the end of RxBuffer and stores in RxTemp ; also handles RxPtr (increments, resets when out of range) putRxBuffer: banksel RxBuffer ; select memory bank bankisel RxBuffer movwf RxTemp ; save W to RxTemp movfw RxPtr ; load RxPtr to FSR movwf FSR movfw RxTemp ; copy RxTemp to INDF (RxBuffer at RxPtr) movwf INDF incf RxPtr, F ; increment RxPtr movfw RxPtr ; reset RxPtr if out of range sublw RxBuffer+RX_BUFFER_SIZE btfsc STATUS, Z call resetRxBuffer return ;; interrupt service routine ;; recieves data, stores in RxBuffer, calls rcvPacket when a packet has been recieved interrupt: PUSH_MACRO ; save context banksel PIR1 ; clear interrupt flag bcf PIR1, RCIF banksel RCREG ; read RCREG and buffer it movfw RCREG call putRxBuffer banksel RxBuffer ; if previous character was escape, goto handleEsc movfw RxTemp btfsc RxFlags,escRcv goto handleEsc btfsc RxFlags,H ; if this is the header, goto handleHdr goto handleHdr xorlw ESC_CHAR ; if current character is escape, set RxFlags, escRcv btfsc STATUS, Z bsf RxFlags, escRcv xorlw ESC_CHAR goto endInt handleEsc: banksel RxBuffer movfw RxTemp xorlw HEADER_CHAR ; header btfsc STATUS, Z bsf RxFlags, H btfsc STATUS, Z call resetRxBuffer xorlw HEADER_CHAR banksel RxBuffer movfw RxTemp xorlw END_CHAR ; end btfsc STATUS, Z goto endOfPacket xorlw END_CHAR banksel RxFlags bcf RxFlags, escRcv ; second escape goto endInt endOfPacket: banksel RxBuffer movfw RxPtr movwf RxEndPtr btfsc RxFlags, toMe call rcvPacket banksel RxFlags clrf RxFlags goto endInt handleHdr: banksel RxBuffer ; load RxTemp to W movfw RxTemp bcf RxFlags, H ; clear header flag xorlw ADDRESS btfsc STATUS, Z ; check if address matches bsf RxFlags, toMe xorlw ADDRESS goto endInt endInt: POP_MACRO retfie ;; rcvPacket ;; called when a packet addressed to this unit is recieved ;; determines packet type (by port number) and calls appropriate function ; ; BROKEN!!! (some of the time) ; rcvPacket: banksel RxBuffer movfw RxBuffer+2 ;port xorlw PING_PORT btfsc STATUS, Z call pingPacket xorlw PING_PORT xorlw BEMIX_PORT btfsc STATUS, Z call bemixPacket xorlw BEMIX_PORT return pingPacket: banksel TxBuffer movlw PING_PORT movwf TxPort banksel RxBuffer movfw RxBuffer+1 ; source address call transmit return bemixPacket: movfw RxBuffer+3 xorlw 'E' btfsc STATUS, Z call enableTouchSwitch xorlw 'E' xorlw 'D' btfsc STATUS, Z call disableTouchSwitch xorlw 'D' return enableTouchSwitch: banksel PORTA bcf PORTA, TS_ENABLE return disableTouchSwitch banksel PORTA bsf PORTA, TS_ENABLE return ;;------------------------------------------------------------------------------------------- ;; TX functions ;; ;; putTxBuffer ;; adds a byte to the back of the TxBuffer, increments TxPtr and TxEndPtr, ;; also deals with ESC_CHAR ;; changes W, bank putTxBuffer: banksel TxBuffer ; save value to be added in TxTemp bankisel TxBuffer movwf TxTemp movfw TxPtr ; move to end of TxBuffer movwf FSR movfw TxTemp ; load value and write to end of buffer movwf INDF incf TxPtr,F ; increment pointers incf TxEndPtr,F xorlw ESC_CHAR ; check if an escape character was written btfss STATUS, Z return ; if not, don't do anything else incf FSR, F ; otherwise, add a second escape character to TxBuffer movlw ESC_CHAR movwf INDF incf TxPtr,F incf TxEndPtr,F ; need to check if TxPtr is out of range return ; getTxData ; loads byte from the TxBuffer into W and increments TxPtr ; changes W and bank getTxData: MACRO banksel TxBuffer movfw TxPtr bankisel TxBuffer movwf FSR movfw INDF incf TxPtr,F ENDM ;; transmitxByte ;; transmits W transmitByte: banksel PIR1 btfss PIR1, TXIF goto $-1 ; wait until USART is ready for more TX data banksel TXREG movwf TXREG ; transmit W return ; resetTxBuffer ; sets TxPtr and TxEndPtr to their starting locations ; changes W, bank resetTxBuffer: banksel TxBuffer movlw TxBuffer movwf TxPtr movwf TxEndPtr return ;; transmit ;; adds a header and transmits contents of TxBuffer to address in W, on the port specified by TxPort ;; changes W, bank transmit: banksel PORTB ; RS485 out of tristate bsf PORTB, TX_ENABLE banksel TxBuffer ; prepare the header movwf TxHeader movlw ADDRESS movwf TxHeader+1 movfw TxPort movwf TxHeader+2 transmitByte_macro ESC_CHAR ; transmit header sequence transmitByte_macro HEADER_CHAR banksel TxBuffer movlw TxHeader ; set TxPointer to the beginning of the header movwf TxPtr TxLoop: getTxData ; load data at TxPtr into W call transmitByte ; transmit W banksel TxBuffer movfw TxEndPtr subwf TxPtr,W btfss STATUS, Z ; loop until TxBuffer is empty goto TxLoop transmitByte_macro ESC_CHAR ; transmit end sequence transmitByte_macro END_CHAR transmitByte_macro 0x0d ; transmit CR+LF transmitByte_macro 0x0a banksel PORTB ; RS485 into tristate bcf PORTB, TX_ENABLE call resetTxBuffer return end