📄 docking_station.asm
字号:
; $Id: docking_station.asm,v 1.8 2003/10/03 00:45:36 dwalters Exp $; Copyright (C) 2003 Dafydd Walters <dwalters@users.sourceforge.net>;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation; either version 2 of the License, or; (at your option) any later version.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program (COPYING.SOFTWARE); if not, write to the ; Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, ; MA 02111-1307 USA; ---------------------------------------------------------------------- title "docking_station.asm - OAP Docking Station" processor pic16f819 list r=dec ; set radix to decimal include "p16f819.inc"; ----------------------------------------------------------------------; Digital Inputs:; RB0 - IR detector digital input;; Digital Outputs:; RB2 - Charger power control; RB3 - External supply power control; RA2 - LED # 1 (green) - External supply active; RA4 - LED # 2 (yellow) - Charger active; ; Not Used:; RA0; RA1; RA3; RA5; RA6; RA7; RB1; RB4; RB5; RB6; RB7;; States:; 0 = ext supply and charger off (LEDs off); 1 = ext supply on, charger off (green LED on); 2 = ext supply on, charger pending (yellow LED flashing); 3 = ext supply on, charger on (yellow LED on);; The timers are used in this program as follows:; TMR0 - used for timing IR remote commands from PMM; TMR1 - used for timing the period since charger has been on; TMR2 - used for timing pings from PMM ;; ----------------------------------------------------------------------; Constants#define ONE_MS_DELAY 31 ; TMR0#define TMR1_ONE_SEC 4#define TMR2_ONE_SEC 1#define EXT_SUPPLY_LED PORTA,2 ; Green LED#define CHARGER_LED PORTA,4 ; Yellow LED#define CHARGER_RELAY PORTB,2#define EXT_SUPPLY_RELAY PORTB,3; Infrared Commands from Power Management Module.; The hexadecimal numbers in comments on the right are for testing with a; TV remote control (without the PMM), 0x080 represents the 1 key on the TV; remote, 0x081 corresponds to the 2 key, etc.#define TURN_ON_EXT_COMMAND b'11100001' ; TV remote test 1: 0x080#define TURN_ON_CHARGER_COMMAND b'11100010' ; TV remote test 2: 0x081#define PING_COMMAND b'11100100' ; TV remote test 3: 0x082#define TURN_OFF_CHARGER_COMMAND b'11100101' ; TV remote test 4: 0x083#define TURN_OFF_EXT_COMMAND b'11100110' ; TV remote test 5: 0x084; ----------------------------------------------------------------------; Variable Declarations (GPR) starting at data address 0x020 cblock 0x020DelayLoopCountHiCountSavedWSavedStatusSavedFSRSavedPCLATHStateTimer1Timer2Timer2tmpPortBStateRemoteReceiveStateRemoteReceiveBitCountRemoteReceiveByte endc; ----------------------------------------------------------------------; Configuration bits: ;; - Flash Code Protection off; - CCP1 on RB3; - In-circuit Debugger disabled; - Flash write enable off; - EE Code Protection off; - Low Voltage Programming Enable off, RB3 is I/O; - Brown-out Reset Enable on; - RA5/MCLR pin function is digital I/O; - Power-Up Timer on; - Watchdog Timer off; - Oscillator: INTRC, port I/O function of RA6 and RA7 __CONFIG _CP_OFF & _CCP1_RB3 & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO; ----------------------------------------------------------------------; Program entry point at device reset org 0 goto MainStart; ----------------------------------------------------------------------; Interrupt Handler entry point org 4 goto IntStart; ----------------------------------------------------------------------; Interrupt handler start pointIntStart movwf SavedW ; Save W movf STATUS,w bcf STATUS,RP0 ; Make sure we're on Page 0 bcf STATUS,RP1 movwf SavedStatus ; Save STATUS movf FSR,w movwf SavedFSR ; Save FSR movf PCLATH,w movwf SavedPCLATH ; Save PCLATH clrf PCLATH ; Execution page 0 btfss PIR1,TMR1IF goto NotTimer1; TMR1 bcf PIR1,TMR1IF ; Clear interrupt flag movf Timer1,f btfsc STATUS,Z goto FinishISR ; Timer1 was already zero decf Timer1,f goto FinishISRNotTimer1 btfss PIR1,TMR2IF goto NotTimer2; TMR2 bcf PIR1,TMR2IF decf Timer2tmp,f btfss STATUS,Z goto FinishISR; Timer2tmp has wrapped around to 0 movlw 15 movwf Timer2tmp ; Reset to 15 to get a 1 second period movf Timer2,f btfsc STATUS,Z goto FinishISR; Timer2 is not zero; decrement it. decf Timer2,f goto FinishISRNotTimer2 btfss INTCON,INTF ; IR signal? goto NotIR ; Jump if interrupt source is not RF; IR signal movf PORTB,w ; Read Port B movwf PortBState ; and save the state of Port B btfss PortBState,0 goto IRInLow; IR In is High bsf STATUS,RP0 bcf OPTION_REG^0x080,INTEDG ; Interrupt when RB0 goes High to Low bcf STATUS,RP0 goto IRInDoneIRInLow bsf STATUS,RP0 bsf OPTION_REG^0x080,INTEDG ; Interrupt when RB0 goes Low to High bcf STATUS,RP0IRInDone bcf INTCON,INTF ; Clear IR interrupt flag 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 AwaitingCommandDone ; RemoteReceiveState = 4 IF ((HIGH($)) != (HIGH(IrJumpTable))) ERROR("IR Jump Table crosses page boundary!") ENDIFAwaitingLeaderStart ; State = 0 movf PortBState,w btfsc PortBState,0 ; In leader? goto FinishISRLeaderStarted movlw 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,TMR0IF bsf INTCON,TMR0IE ; Enable timer interrupt goto FinishISRAwaitingIRLeaderEnd ; State = 1 movf PortBState,w andlw 1 btfsc STATUS,Z ; signal gone high?; Signal low goto FinishISR; 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,TMR0IF bsf INTCON,TMR0IE ; Enable timer interrupt goto FinishISRAwaitingIRSyncBit ; State = 2 movf PortBState,w andlw 1 btfss STATUS,Z ; signal gone low?; Signal high goto FinishISR; 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,TMR0IF bsf INTCON,TMR0IE ; Enable timer interrupt goto FinishISRAwaitingIRDataBit ; State = 3 movf PortBState,w andlw 1 btfsc STATUS,Z ; signal gone high?; Signal low goto FinishISR; 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,TMR0IE ; Disable timer interrupt movlw 4 movwf RemoteReceiveState goto FinishISRAwaitingCommandDone ; State = 4 goto FinishISRCodeNotRecognised bcf INTCON,TMR0IE ; Disable timer interrupt clrf RemoteReceiveState goto FinishISRNotIR; Look for TMR0 interrupts last, because we enable and disable this one, so; TMR0IF could be misleadingly set during an interrupt caused by another; source while TMR0 interrupts are disabled. btfss INTCON,TMR0IF goto FinishISR; TMR0 bcf INTCON,TMR0IF clrf RemoteReceiveState ; Back to state 0 bcf INTCON,TMR0IE ; Disable timer interrupt goto FinishISRFinishISR 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 InitClock ; Initialize internal clock oscillator call InitIO ; Initialize IO ports call InitTimer ; Initialize Timer clrf State movlw TMR1_ONE_SEC * 30 ; At least 30s from reset before charger can be on movwf Timer1 clrf RemoteReceiveState call InitInterrupts ; Enable interruptsMainLoop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -