;********************************************************************** ; * ; Filename: 3chlrnrem2975.asm * ; Date: 15-09-2011 * ; File Version: 2 * ; * ; Author: Pete Griffiths * ; Company: http://picprojects.org.uk * ; * ; * ; 15-09-2011 Added code to clear ANSEL so it works with 12F675 * ; * ; * ;********************************************************************** ; * ; Files Required: P12F629.INC * ; * ;********************************************************************** ; * ; Notes: * ; * ; 3-channel (output) SIRC encoded IR remote relay controller * ; Each channel can be set to any 12-bit device/command code. * ; Each output can be individualy set to toggle or momentary * ; action. With momentary action, output is active only * ; while correct IR device/command code is being received. * ; * ; Features * ; Individual SIRC device/command code for eacg output * ; Individual Toggle / Momentary output operation select * ; Easy to use programming/learning mode * ; Watch Dog Timer reset * ; EEPROM data checksum * ; * ; To enter learning mode press and hold Sw1 until status * ; LED starts blinking slowly: * ; Rly1 LED will light - press desired remote key * ; Rly1 LED will turn off * ; Rly2 LED will light - press desired remote key * ; Rly2 LED will turn off * ; Rly3 LED will light - press desired remote key * ; * ; All Rly LEDs now turn off, Status LED blinks fast * ; Press remote key just programmed to toggle corresponding * ; Rly LED on/off * ; LED off - output is in toggle mode * ; LED on - output is in momentary mode * ; * ; When output modes have been set, press Sw1 to save codes * ; and mode settings. Controller returns to normal operation * ; * ; Note: since the relay LEDs are in series with the relay * ; drive transistors, the Relays will be switched during * ; learning so you should ensure any connected equipment is * ; safe to be switched on/off * ; * ;********************************************************************** ;list p=12f629 ; list directive to define processor ;#include ; processor specific variable definitions list p=12f675 ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;***** CONSTANT DEFINITIONS C.cmd.bitlength equ b'01000000' ; preset ir.command to use as shift counter ; If C.SIRC12 selects between 12-bit and 15-bit encoded SIRC data ; It is an either/or option, it can't receive both 12-bit and 15-bit at the same time ; Set C.SIRC12 here and then reassemble the code C.SIRC12 equ 1 ; 12 bit true 1 | 15 bit false 0 if C.SIRC12 C.dev.bitlength equ b'00010000' ; constant to use as shift counter 12 bit else C.dev.bitlength equ b'10000000' ; constant to use as shift counter 15 bit endif ;***** VARIABLE DEFINITIONS cblock 0x20 ; These variables must be in contiguous memory as they are ; block copied to/from EEPROM V.relay.action.mask ; toggle / momentary output action mask V.rly1.deviceid ; rly1 responds to this device id V.rly1.command ; rly1 responds to this command V.rly2.deviceid ; rly2 responds to this device id V.rly2.command ; rly2 responds to this command V.rly3.deviceid ; rly3 responds to this device id V.rly3.command ; rly3 responds to this command V.checksum ; checksum of EEPROM data ; / end of contiguos variables / V.flag ; flag bits V.timer ; ir receive holdoff timer V.irrx.state ; ir receiver function state variable V.ir.command ; received IR command bits V.ir.deviceid ; received IR device id bits V.ir.devlast V.ir.cmdlast V.gpio.copy ; GPIO working variable - all functions write to this V.led.flash ; status led flash control V.led.flash.tmr ; staus led flash rate timer V.led.flash.cmp V.sw.timer ; switch timer ; These variables must be in non-banked GPR ; not an issue for the 12F629 but will be if code is ported to another PIC variant V.w_temp ; variable used for context saving V.status_temp ; variable used for context saving V.checksum.calc ; variable used to calculate EEPROM data checksum endc ;***** FLAG BIT DEFINITIONS F.action.done equ 0 F.timer equ 1 F.iredge equ 2 F.irtimer equ 3 F.ready equ 4 F.irmatch equ 5 F.pwm equ 6 ;***** GPIO PORT BIT USE DEFINITIONS rly1 equ 0 ; Relay 1 on GPIO0 rly2 equ 1 ; Relay 2 on GPIO1 irrx equ 2 ; IR receiver input on GPIO2 sw1 equ 3 ; Switch 1 input on GPIO3 (MCLR off) rly3 equ 4 ; Relay 3 on GPIO4 led equ 5 ; Status LED on GPIO5 ;********************************************************************** ORG 0x000 ; processor reset vector goto startup ; go to beginning of program ;********************************************************************** ; Interrupt Service ORG 0x004 ; interrupt vector location movwf V.w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf V.status_temp ; save off contents of STATUS register banksel GPIO ; ensure GPR bank 0 selected btfsc INTCON, T0IF ; test Timer0 int flag goto int.tmr0 ; do Timer0 interrupt function ; Since it wasn't a Timer0 interrupt it can only be GP2 Edge or Timer1 ; If GP2 interrupt set F.iredge flag ; If Timer1 interrupt clear F.iredge flag bsf V.flag, F.iredge ; set F.iredge flag btfsc INTCON, INTF ; test GP2 int edge flag goto int.ir btfsc INTCON, T0IF ; test Timer0 int flag goto int.tmr0 ; do Timer0 interrupt function ; since it's not a GP2 edge, or Timer0 interrupt, the only other ; enabled interrupt is Timer1 bcf V.flag, F.iredge ; clear F.iredge flag int.ir btfss V.flag, F.ready ; if last data not processed, don't start new receive call ir.receiver ; run ir receive state code bcf PIR1, TMR1IF ; clear timer1 interrupt flag bcf INTCON, INTF ; clear GP2 edge interrupt flag int.exit movf V.status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf V.w_temp,f swapf V.w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt ;---------------------------------------------------------------------------- int.tmr0 bcf INTCON, T0IF ; clear timer0 interrupy flag clrwdt ; all functions operate on the V.gpio.copy variable. ; This is the only point that a physical write takes place on the GPIO register movfw V.gpio.copy ; transfer V.gpio.copy movwf GPIO ; to physical I/O port incf V.sw.timer,F ; General timer ; if timer == 0 then exit ; else decrement timer ; if timer == 0 then set flag F.timer movf V.timer,f ; test value in timer variable skpnz ; skip next if timer != 0 goto led.control ; else exit interrupt decf V.timer,f ; timer-- skpnz ; skip next if timer != 0 bsf V.flag, F.timer ; else set F.timer flag ;********************************************************************** ; LED control ; If led.flash == 0 LED is forced off ; If led.flash <1-254> LED is blinks at n x 8.192mS ; If led.flash == 255 LED is forced on ; led.control movf V.led.flash,f skpnz ; if reload value != 0 skip next goto led.control.off incf V.led.flash,W ; test if reload value == 255 skpnz ; skip next if it isn't goto led.control.on decfsz V.led.flash.tmr,F ; led.flash.tmr-- goto int.exit movlw 1<1 & <255 goto int.exit ;********************************************************************** ; Startup and Initialisation dt "3-Channel Relay Controller 12F629/675" dt "Copyright (C) Pete Griffiths 2010-2011 " dt "http://picprojects.org.uk " startup btfsc STATUS, RP0 ; if RP0 bit is set, the call to get the OSCCAL word goto bad.calword ; must have wrapped round so do bad.calword otherwise ; timings will be out and code won't work correctly movlw 1<