📄 input_module.asm
字号:
IntStart movwf SavedW ; Save W movf STATUS,w bcf STATUS,RP0 ; Make sure we're on Page 0 movwf SavedStatus ; Save STATUS movf FSR,w movwf SavedFSR ; Save FSR movf PCLATH,w movwf SavedPCLATH ; Save PCLATH clrf PCLATH ; Execution page 0 btfss INTCON,RBIF ; IR signal? goto NotIR ; Jump if interrupt source is not IR; IR signal movf PORTB,w ; Read Port B movwf PortBState ; and save the state of Port B bcf INTCON,RBIF ; Clear Port B interrupt flag bsf IRInterrupt,0; Check if we're already receiving from RF source.; If we are, and we're in state 1-3, override. movf RemoteReceiveState,f btfsc STATUS,Z goto HandleRemote ; No need to override state=0 movlw 4 subwf RemoteReceiveState,w btfsc STATUS,Z goto HandleRemote ; Don't override state=4 movlw 5 subwf RemoteReceiveState,w btfsc STATUS,Z goto HandleRemote ; Don't override state=5 btfss RemoteReceiveMask,0 ; RF or IR? goto HandleRemote ; IR; At this point, we've established that we're in the middle of receiving ; an RF packet (or RF noise). movlw 0x0F0 andwf PortBState,w xorlw 0x0F0 btfsc STATUS,Z goto HandleRemote ; IR bits all high -no need to override RF; IR low signal seen - IR overrides RF remote clrf RemoteReceiveState ; Go back to state 0 bcf INTCON,T0IE ; Disable timer interruptHandleRemote movf RemoteReceiveState,w addwf PCL, f ; Jump according to value in wIrJumpTable goto AwaitingLeaderStart ; RemoteReceiveState = 0 goto AwaitingIRLeaderEnd ; RemoteReceiveState = 1 goto AwaitingIRSyncBit ; RemoteReceiveState = 2 goto AwaitingIRDataBit ; RemoteReceiveState = 3 goto AwaitingScanCodeTx ; RemoteReceiveState = 4 goto AwaitingIRStop ; RemoteReceiveState = 5 IF ((HIGH($)) != (HIGH(IrJumpTable))) ERROR("IR Jump Table crosses page boundary!") ENDIFAwaitingLeaderStart ; State = 0 movf PortBState,w btfsc PortBState,0 ; RF In leader? goto NotRFIn; RF In Leader started movf IRInterrupt,f btfss STATUS,Z goto NotRFIn ; Servicing IR interrupt - ignore bit 0 of port B movlw 0x01 ; Only look at bit 0 goto LeaderStartedNotRFIn movf IRInterrupt,f btfsc STATUS,Z goto FinishISR ; Servicing RF interrupt - nothing more to do btfsc PortBState,4 ; IR detector # 1 leader? goto NotIR1 ; Jump if no leader detected on IR # 1; IR # 1 Leader started movlw 0x10 ; Only look at bit 4 goto LeaderStartedNotIR1 btfsc PortBState,5 ; IR detector # 2 leader? goto NotIR2; IR # 2 Leader started movlw 0x20 ; Only look at bit 5 goto LeaderStartedNotIR2 btfsc PortBState,6 ; IR detector # 3 leader? goto NotIR3; IR # 3 Leader started movlw 0x40 ; Only look at bit 6 goto LeaderStartedNotIR3 btfsc PortBState,7 ; IR detector # 4 leader? goto NotIR4; IR # 4 Leader started movlw 0x80 ; Only look at bit 7 goto LeaderStartedNotIR4; All 4 IR detector signals high; remain in state 0 goto FinishISRLeaderStarted movwf RemoteReceiveMask btfsc RemoteReceiveMask,0 ; RF or IR? goto Leader2 ; RF; IR bcf INTCON,INTE ; Disable RF interruptsLeader2 movlw 8 ; Each frame has 12 bits, but we only want 1st 8 movwf RemoteReceiveBitCount clrf RemoteReceiveByte movlw 1 movwf RemoteReceiveState ; Next state is 1 movlw 0x100 - (ONE_MS_DELAY * 3) movwf TMR0 ; Set timeout to 3ms bcf INTCON,T0IF bsf INTCON,T0IE ; Enable timer interrupt goto FinishISRAwaitingIRLeaderEnd ; State = 1 movf PortBState,w andwf RemoteReceiveMask,w ; Only interested in one remote signal btfsc STATUS,Z ; signal gone high?; Signal low goto FinishISR ; ignore signals from other sensors; Signal high movlw 0x100 - (ONE_MS_DELAY * 3) + (ONE_MS_DELAY * 15/10) subwf TMR0,w btfss STATUS,C goto CodeNotRecognised ; Start bit too short (<1.5ms) - abort packetNextStateSync movlw 2 movwf RemoteReceiveState ; Next state is 2 (wait for end of sync) movlw 0x100 - (ONE_MS_DELAY * 1) movwf TMR0 ; Set timeout to 1ms bcf INTCON,T0IF bsf INTCON,T0IE ; Enable timer interrupt goto FinishISRAwaitingIRSyncBit ; State = 2 movf PortBState,w andwf RemoteReceiveMask,w ; Only interested in one remote signal btfss STATUS,Z ; signal gone low?; Signal high goto FinishISR ; ignore signals from other sensors; Signal Low movlw 0x100 - (ONE_MS_DELAY * 1) + (ONE_MS_DELAY/2) subwf TMR0,w btfss STATUS,C goto CodeNotRecognised ; Sync too short (< 0.5ms) - abort packet movlw 3 movwf RemoteReceiveState ; Next state is 3 (wait for end of data bit) movlw 0x100 - (ONE_MS_DELAY * 2) movwf TMR0 ; Set timeout to 2ms bcf INTCON,T0IF bsf INTCON,T0IE ; Enable timer interrupt goto FinishISRAwaitingIRDataBit ; State = 3 movf PortBState,w andwf RemoteReceiveMask,w ; Only interested in one remote signal btfsc STATUS,Z ; signal gone high?; Signal low goto FinishISR ; ignore signals from other sensors; Signal high movlw 0x100 - (ONE_MS_DELAY * 2) + (ONE_MS_DELAY/2) subwf TMR0,w btfss STATUS,C goto CodeNotRecognised ; data bit too short (< 0.5ms) - abort packet movlw 0x100 - (ONE_MS_DELAY * 2) + (ONE_MS_DELAY) subwf TMR0,w; At this point, the Carry flag is set for data=1 and clear for data=0 rrf RemoteReceiveByte,f ; Shift Carry flag into received byte register decfsz RemoteReceiveBitCount,f goto NextStateSync; All bits received bcf INTCON,T0IE ; Disable timer interrupt btfss RemoteReceiveMask,0 ; RF or IR? goto CheckIRCode ; IR goto CheckRFCode ; RFCheckIRCode movf RemoteReceiveByte,w andlw 0x0E0 sublw 0x080 btfss STATUS,Z goto CodeNotRecognised ; Top 3 bits not correct in IR received byte goto CheckCommandCodeCheckRFCode; RF - check Robot ID Code movf RemoteReceiveByte,w andlw 0xE0 movwf ReceivedRobotCode call GetRobotCodeFromEEPROM subwf ReceivedRobotCode,w btfss STATUS,Z goto CodeNotRecognised ; Different Robot IDCheckCommandCode call IRScanCode2Table iorlw 0 btfsc STATUS,Z goto CodeNotRecognised; Valid IR codeValidCode movwf ScanCode2 call IRScanCode1Table movwf ScanCode1 goto RemoteDoneCodeNotRecognised; IR/RF Code not recognised, different RF Robot ID, or timing error. clrf RemoteReceiveState ; Set next state back to 0 bcf INTCON,T0IE ; Disable timer interrupt call IsRFEnabled btfsc STATUS,Z bsf INTCON,INTE ; Enable RB0/INT Pin interrupt goto FinishISRRemoteDone movlw 4 ; Next state is 4 (wait for scan code send) movwf RemoteReceiveState goto FinishISRAwaitingScanCodeTx ; State = 4 goto FinishISR ; Ignore remote signals until scan code sentAwaitingIRStop ; State = 5 movf PortBState,w andwf RemoteReceiveMask,w ; Only interested in one remote signal btfss STATUS,Z ; signal gone low?; Signal high goto FinishISR ; ignore signals from other sensors or going hi; Signal Low movlw REMOTE_STOP_DELAY movwf RemoteStopCounter ; IR activity sensed - reset counter movlw 0x100 - ONE_MS_DELAY movwf TMR0 ; Set timeout to 1ms goto FinishISRNotIR btfss INTCON,T0IF ; Timer timeout? goto NotTimer ; Jump if interrupt source is not Timer btfss INTCON,T0IE ; Is timer enabled? goto NotTimer ; No; Timer timeoutResetRemoteRx bcf INTCON,T0IF ; Clear Timer interrupt flag movf RemoteReceiveState,w sublw 5 btfss STATUS,Z goto NotAwaitingIRStop; Awaiting IR Stop decfsz RemoteStopCounter,f ; Have we seen 50ms of "silence" yet? goto ContinueIRStop ; NoNotAwaitingIRStop ; Yes clrf RemoteReceiveState ; Back to state 0 bcf INTCON,T0IE ; Disable timer interrupt call IsRFEnabled btfsc STATUS,Z bsf INTCON,INTE ; Enable RB0/INT Pin interrupt goto FinishISRContinueIRStop movlw 0x100 - ONE_MS_DELAY movwf TMR0 ; Set timeout to 1ms goto FinishISRNotTimer btfss INTCON,INTF ; RF signal? goto NotRF ; Jump if interrupt source is not RF btfss INTCON,INTE ; RF enabled? goto NotRF ; No; RF signal movf PORTB,w ; Read Port B movwf PortBState ; and save the state of Port B btfss PortBState,0 goto RFInLow; RF In is High bsf STATUS,RP0 bcf OPTION_REG^0x080,INTEDG ; Interrupt when RB0 goes High to Low bcf STATUS,RP0 goto RFInDoneRFInLow bsf STATUS,RP0 bsf OPTION_REG^0x080,INTEDG ; Interrupt when RB0 goes Low to High bcf STATUS,RP0RFInDone bcf INTCON,INTF ; Clear RF interrupt flag clrf IRInterrupt goto HandleRemoteNotRF; It should not be possible to reach here as we've tested for all possible; interrupt sources! FinishISR movf SavedPCLATH,w movwf PCLATH ; Restore PCLATH movf SavedFSR,w movwf FSR ; Restore FSR movf SavedStatus,w movwf STATUS ; Restore STATUS swapf SavedW,f swapf SavedW,w ; Restore W (without affecting Z,C flags,etc) retfie; ----------------------------------------------------------------------; Main Program start pointMainStart call CheckEEPROMSettings ; Check if nonvolatile settings are valid call InitIO ; Initialize IO ports clrf RemoteReceiveState ; Waiting for IR or RF remote leader call InitTimer ; Initialize Timer; Perform dummy "Basic Assurance Test" (BAT) to satisfy protocol call BAT call InitInterrupts ; Initialize interrupts; Look for keypad keypressWaitForKeyDownLoop bsf STATUS,RP0 bsf STROBE1_DIRECTION ; Strobe 1 Hi-Z bsf STROBE2_DIRECTION ; Strobe 2 Hi-Z bcf STATUS,RP0 ; Check for remote data movlw 4 subwf RemoteReceiveState,w btfss STATUS,Z ; Any remote scan codes to send? goto NoRemoteData; Send remote scan code bcf INTCON,GIE call SendScanCode movlw REMOTE_STOP_DELAY movwf RemoteStopCounter movlw 5 movwf RemoteReceiveState ; Change remote state to 5 movlw 0x100 - ONE_MS_DELAY movwf TMR0 ; Set timeout to 1ms bsf INTCON,T0IE ; Enable timer interrupt bsf INTCON,GIENoRemoteData call Delay10ms btfsc KEYBOARD_DATA ; Check if host wants to talk to us goto WaitDown1 bcf INTCON,GIE call ReceiveFromHost bsf INTCON,GIE addwf PCL, f ; Jump according to value in w; Next 3 instructions constitute a jump table goto WaitForKeyDownLoop ; w=0 goto WaitForKeyDownLoop ; w=1: Reset bcf INTCON,GIE ; w=2: Resend IF ((HIGH($)) != (HIGH($-3))) ERROR("Table crosses page boundary!") ENDIF call SendScanCode bsf INTCON,GIE goto WaitForKeyDownLoopWaitDown1 call Delay10ms btfsc KEYBOARD_DATA ; Check if host wants to talk to us goto WaitDown2 bcf INTCON,GIE call ReceiveFromHost bsf INTCON,GIE addwf PCL, f ; Jump according to value in w; Next 3 instructions constitute a jump table goto WaitForKeyDownLoop ; w=0 goto WaitForKeyDownLoop ; w=1: Reset bcf INTCON,GIE ; w=2: Resend IF ((HIGH($)) != (HIGH($-3))) ERROR("Table crosses page boundary!") ENDIF call SendScanCode bsf INTCON,GIE goto WaitForKeyDownLoopWaitDown2 bcf STROBE1 bsf STATUS,RP0 bcf STROBE1_DIRECTION ; Energize Strobe 1 bcf STATUS,RP0 btfsc KEYPAD_COL1 goto KeyWaitCol2A movlw ESCAPE_SCAN_CODE1 movwf ScanCode1 movlw ESCAPE_SCAN_CODE2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -