; ;****************************************************************************** ; ; ME218C TREAT ; based on Wyatt Node D for Lab 10 ; author: George ; UART Receiver ; ;****************************************************************************** REQUIRED - specify processor for assembler with list HIGHLY RECOMMENDED - include file for standard definitions specify configuration options with _CONFIG ; ;****************************************************************************** ; Constants/Origins ;****************************************************************************** ; W_TEMP equ 0x70 ;these need to be visible in all banks, STATUS_TEMP equ 0x71 ;so they need stored in 0x70-0x7f PCLATH_TEMP equ 0x72 ; ;variables and constants from our comm protocol: BIT_TIME equ 0x1A ;time for a bit HALF_BIT_TIME equ 0x0D ;half of the time for a bit RX_NUM_OF_BITS equ 0x09 ;1 byte+stop bit (no need to store starting bit) RX_COUNTER equ 0x73 ;tracks bit # when receiving UART byte RX_SHIFTREG equ 0x74 ;stores data while receiving UART byte RX_DATA equ 0x75 ;stores data after transmission finishes ;RX_DATA bit definitions: FAN_ON_OFF_BIT equ 0x00 ;signals whether we turn the lift fan on or off RX_STATUS equ 0x76 ;RX_STATUS bit definitions: RX_STARTING_FLAG equ 0x00 ;receiving is starting RX_FRAME_ERROR_FLAG equ 0x01 ;framing error (stop bit was 0) RX_DATA_READY_FLAG equ 0x02 ;received data ready RX_ACTIVE_FLAG equ 0x03 ;"currently receiving" flag org 0 goto MAIN ;(starts at MAIN block) org 4 goto ISR org 5 ;skip past interrupt vector ; ;****************************************************************************** ; Main Block ;****************************************************************************** ; MAIN: call INIT EMPTY_LOOP: ;wait for an interrupt in an endless loop NOP goto EMPTY_LOOP ; ;****************************************************************************** ; Initialization ;****************************************************************************** ; INIT: INIT_PINS: disable analog select for digital I/O initialize RA0 to lo,this one is for the fan set RA3 to input; rest are LED/testing outputs INIT_IOC: ;Interrupt On Change initialization enable IOC interrupt set IOC negative (falling) edge trigger for UART on RA3 INIT_HLTMR1: ;Hardware Limit Timer 1 initialization set HLTMR1 prescaler to 16, postscaler to 4, keep turned off set timer compare value as 1/2 period of a UART bit enable HLTMR1 interrupt in periph. int. enable reg. enable peripheral interrupts (for HLTMR1) enable interrupts globally INIT_VARIABLES: clear the RX_DATA return to main ; ;****************************************************************************** ; Interrupt Response ;****************************************************************************** ; ISR: PUSH: backup W to W_TEMP swapf STATUS and W b/c it preserves STATUS bits backup STATUS to STATUS_TEMP backup PCLATH to PCLATH_TEMP clear PCLATH ISR_BODY: CHECK_IOC: ;Falling edge on UART pin if IOC interrupt flag for pin RA3 is set: then call the subroutine for UART TX start CHECK_HLTIMER: ;time to read the next UART data bit? if HLTMR1 interrupt flag is set: then call the subroutine for HLTIMER timeouts CLEAR_INT_FLAGS: clear HLTMR1 interrupt source/flag clear IOC interrupt flag for pin RA3 clear global IOC interrupt flag as well POP: restore PCLATH restore STATUS restore W (using swapf b/c movf might modify STATUS) return from ISR, and re-enables interrupts ; ;****************************************************************************** ; Interrupt Subroutines ; UART_START: set HLTMR1 timer compare value to half period of UART bit turn on the HLTMR1 for timing between UART bits clear HLTMR set the "starting" flag in our status reg. initialize the bit counter with 9, the total # bits make sure shift reg and data are clear: make sure data storage is clear disable IOC negative (falling) edge trigger for UART on RA3 RETURN HLTIMER_TIMEOUT: if this is NOT the first UART bit: then go to DATA_BITs block FIRST_BIT: ;else, this is the first bit clear starting-bit flag clear HLTMR if first bit high: then first bit was bad, go to BAD_FIRST_BIT block GOOD_FIRST_BIT: ;else, first bit was valid (low) set HLTMR1 timer compare value to full period of UART bit go to HLTIMER_END BAD_FIRST_BIT: bre-set IOC negative (falling) edge trigger for UART on RA3 go to HLTIMER_END DATA_BITS: decrement the bit counter if counter has reached zero: then go to TX_END block to handle end of transmission. TX_ONGOING: ;else, TX is ongoing shift previous data in shift reg. to right if pin RA3 is high: then go to RA3_HI block RA3_LO: clear MSB in shift reg go to RA3_TEST_END RA3_HI: set MSB in shift reg RA3_TEST_END: go to HLTIMER_END TX_END: store received data into RX_DATA register if last bit in UART TX is low (bad stop bit): set RX_FRAME_ERROR_FLAG set RX_STATUS,RX_DATA_READY_FLAG turn off the HLTMR; time to look for new packets re-set IOC negative (falling) edge trigger for UART on RA3 call SET_FAN HLTIMER_END: clear HLTMR RETURN ; ;****************************************************************************** ; FAN INTERACTING FUNCTIONS ;****************************************************************************** ; SET_FAN: if the FAN_ON_OFF_BIT is set go to TURN_ON_FAN TURN_OFF_FAN: write RA0 low, use RA0 as the output to the lower circuitry goto DONE_SETTING_FAN TURN_ON_FAN: write RA0 hi DONE_SETTING_FAN: RETURN END