;=============================================================================== ; Title: Infra Red Panel Timer ; ; Author: Rob Jansen, Copyright (c) 2017 .. 2017, all rights reserved. ; ; Revision: ; 2017-11-11 : Initial version ; ; Compiler: jalv24q6 ; ; Description: Programmable Timer for controlling an Infra Red Panel. ; ; Sources: - ; ;=============================================================================== ; Some compiler pragmas for optimizations Pragma warn all yes ; We want to know all compiler warnings Pragma opt variable_reduce yes ; Reduce variables. Note there seem to be a ; problem in the complier if this is set to no. include 12f615 ; target PICmicro ; This uses the 4 MHz internal oscillator. Pragma target clock 4_000_000 ; Oscillator frequency 4 MHz ; Configuration memory settings (fuses). These are only a selection, sufficient ; for this program. Pragma target OSC INTOSC_NOCLKOUT ; Internal Clock Pragma target IOSCFS F4MHZ ; 4 MHz Clock Pragma target WDT DISABLED ; No Watchdog Pragma target PWRTE ENABLED ; Power up timer enabled Pragma target BROWNOUT DISABLED ; No brownout reset Pragma target MCLR INTERNAL ; Reset internal enable_digital_io() ; Make all pins digital I/O ; Pin connections. All pins are used so no weak pull-up needed. Alias Switch Is Pin_GP3 ; Pin 4. This is the unused MCLR pin, active Low. Pin_GP3_Direction = Input Alias Relais Is Pin_GP0 ; Pin 7. Control the Relais, active High. Pin_GP0_Direction = Output Alias LED_1 Is Pin_GP5 ; Pin 2. Active High. Pin_GP5_Direction = Output Alias LED_2 Is Pin_GP4 ; Pin 3. Active High. Pin_GP4_Direction = Output Alias LED_3 Is Pin_GP2 ; Pin 5. Active High. Pin_GP2_Direction = Output Alias LED_4 Is Pin_GP1 ; Pin 6. Active High. Pin_GP1_Direction = Output ; ================== Constant and variable declarations ======================= ; Constants used for enabling and disabling the outputs. Const Bit RELAIS_ON = TRUE Const Bit RELAIS_OFF = FALSE Const Bit LED_ON = TRUE Const Bit LED_OFF = FALSE ; Constants and variables used for timing purposes. This is based on the ; setting of Timer 1. ;Const Word TIME_1 = 19 ; 19 * 262 ms = 5 seconds. For testing. Const Word TIME_1 = 6_866 ; 6866 * 262 ms = 30 minutes Const Word TIME_2 = 2 * TIME_1 Const Word TIME_3 = 3 * TIME_1 Const Word TIME_4 = 4 * TIME_1 Var Word On_Timer ; Constants and variables used for handling the switches. Const Word KEY_DEBOUNCE_TIME = 100_000 ; 100 ms (_usec_delay). Const Word LOOP_TIME = 10_000 ; 10 ms (_usec_delay). Const Byte KEY_DOWN_TIME = 100 ; 100 * 10 ms = 1 seconds. Var Byte Timer ; General purpose timer. ; ========================= Functions and Procedures ========================== Procedure Timer1_Interrupt Is Pragma interrupt ; This procedure handles the Timer 1 interrupt. It counts down the timer value ; and controls the Relais. This 16-bit timer overflows after: ; 65.536 * 4 us = 262 ms. ; The routine starts with updating the LEDs. If PIR1_TMR1IF Then PIR1_TMR1IF = FALSE ; Update the LEDs. If (On_Timer > 0) Then LED_1 = LED_ON Else LED_1 = LED_OFF End If If (On_Timer > TIME_1) Then LED_2 = LED_ON Else LED_2 = LED_OFF End If If (On_Timer > TIME_2) Then LED_3 = LED_ON Else LED_3 = LED_OFF End If If (On_Timer > TIME_3) Then LED_4 = LED_ON Else LED_4 = LED_OFF End If ; Adjust timer and control Relais. If (On_Timer == 0) Then Relais = RELAIS_OFF Else Relais = RELAIS_ON On_Timer = On_Timer - 1 End If ; On_Timer End If ; PIR1_TMR1IF End Procedure ; Timer1_Interrupt ; ========================= Main program starts here ========================== ; Switch off the relais and the LEDs. Relais = RELAIS_OFF LED_1 = LED_OFF LED_2 = LED_OFF LED_3 = LED_OFF LED_4 = LED_OFF On_Timer = 0 ; Give the switch input some time to settle to prevent a false start. _usec_delay(100_000) ; We use Timer 1 as general purpose timer. When selecting internal clock and a ; prescale of 8 we get 4.000.000 / 4 / 4 = 250 kHz or 4 us. T1CON_TMR1ON = FALSE ; Timer 1 off T1CON_TMR1GE = FALSE ; Disable gate enable. T1CON_T1OSCEN = FALSE ; No LP oscillator. T1CON_NT1SYNC = TRUE ; Do not synchronize external clock input. T1CON_TMR1CS = FALSE ; Use internal clock (Fosc/4). T1CON_T1CKPS = 0b10 ; Prescaler 1:4 so 250 kHz clock. TMR1 = 0 ; Reset Timer 1. PIR1_TMR1IF = FALSE ; Clear Timer 1 interrupt flag. PIE1_TMR1IE = TRUE ; Enable Timer 1 interrupt. T1CON_TMR1ON = TRUE ; Timer 1 on. INTCON_PEIE = TRUE ; Enable peripheral interrupt. INTCON_GIE = TRUE ; Globale interrupt enabled. Forever Loop ; Check if the switch was pressed. If !Switch Then ; Switch pressed, debounce. _usec_delay(KEY_DEBOUNCE_TIME) ; Continue if switch still pressed. If !Switch Then ; If switch is still active then either wait for key release or if it is ; still pressed after a certain time. The latter means 'switch off'. Timer = KEY_DOWN_TIME ; Value to detect long key press. While !Switch & (Timer != 0) Loop _usec_delay(LOOP_TIME) Timer = Timer - 1 End Loop ; !Switch ; If the key is still down then switch off the Relais. If (Timer == 0) Then ; Timeout so still pressed. Switch off which equals On_Timer to be 0. On_Timer = 0 ; Switch off is done by the timer interrupt. ; Wait for key release to prevent new start. While !Switch Loop End Loop Else ; Normal key press, increase timeer value, which turns the Relais on. If (On_Timer >= TIME_3) Then On_Timer = TIME_4 ; Maximum value. Else On_Timer = On_Timer + TIME_1 ; Add 1 extra timeslot. End If ; On_Timer End If ; Timer End If ; !Switch End If ; !Switch End Loop