;------------------------------------------------------------------------------- ; Title: LED string switch. ; ; Author: Rob Jansen, Copyright (c) 2025..2025, all rights reserved. ; ; Revision: ; 2025-01-10 : Rev 1.0. Initial version. ; ; Compiler: 2.5r8 ; ; Description: Measures one of de driver signals to determine if the constant ; ON mode is selected for the LED string. If not the switch will be ; pressed until that mode is selected. ; ;------------------------------------------------------------------------------- ; include 12f617 ; Target PICmicro ; ; Use internal clock and internal reset. pragma target OSC INTOSC_NOCLKOUT ; Internal Clock pragma target PWRTE Enabled ; Power up timer pragma target MCLR Internal ; Reset internal pragma target WDT Disabled ; No watchdog pragma target BROWNOUT Disabled ; Disable to save power pragma target IOSCFS F4MHZ ; Set internal oscillator to 4 MHz pragma target clock 4_000_000 ; Oscillator frequency 4 MHz enable_digital_io() ; make all pins digital I/O ; Wait some time for the hardware to stabilize. _usec_delay(100_000) ; Pins definitions. The outputs drive a transistor. When the output is high, ; the transitor pull the connection to the series of LEDs to ground. alias switch is pin_GP4_direction switch = INPUT ; Switch not pressed. pin_GP4 = LOW ; When turned to output the switch will be presset. alias driver is pin_GP5 pin_GP5_direction = INPUT ; Driver input signal. alias test_pin is pin_GP2 pin_GP2_direction = OUTPUT ; Enable weak pull up ports for all pins. WPU = 0b0011_0111 ; Weak pull-up enabled for all pins OPTION_REG_NGPPU = FALSE ;------------------------------------- Constants ------------------------------- ; A clock of 200 Hz is used (5 ms periode time). We measure for 3 seconds. const word MEASUREMENT_TIME = 600 ; 5 ms * 600 = 3 seconds ; The minimum number of samples the signal has to be stable, equals 2 seconds. const word SAMPLES_OK = 400 ; 5 ms * 400 = 2 seconds. ; Measurement constants. The high and low time are around 2.5 ms but we take ; some margin. These are times in us. const word MEASUREMENT_MIN = 2000 const word MEASUREMENT_MAX = 3000 ;------------------------------------- Variables ------------------------------- var word measurement var word sample_time, sample_counter var bit overflow ;------------------------------------- Procedures ------------------------------- ; Wait until the driver signal is high. procedure wait_for_driver_high() is while !driver loop ; Wait for it. end loop end procedure ; Wait until the driver signal is low. procedure wait_for_driver_low() is while driver loop ; Wait for is. end loop end procedure procedure press_switch() is switch = OUTPUT ; Press it _usec_delay(300_000) switch = INPUT ; Release it. end procedure ; Start timer 1 from 0. procedure timer_1_start() is TMR1 = 0 overflow = FALSE T1CON_TMR1ON = TRUE end procedure ; Stop timer 1 and return the time value. If an ; overlow occured we return o. function timer_1_stop() return word is T1CON_TMR1ON = FALSE if overflow then return 0 else return TMR1 end if end function ; Interrupt procedure for timer 1, called when overflow. procedure timer_1_interrupt() is pragma interrupt if PIR1_TMR1IF then T1CON_TMR1ON = FALSE PIR1_TMR1IF = FALSE overflow = TRUE end if end procedure ;--------------------------- Main program starts here -------------------------- ; Initialize Timer 1. We let it run a 1 MHz so that we get measurements of 1 us. T1CON_TMR1ON = FALSE ; Set input to Fosc/4, that gives 1 MHz. CMCON1_T1ACS = FALSE T1CON_TMR1CS = FALSE T1CON_T1CKPS = 0b00 -- Prescaler 1:1, gives 1 MHz. ; Also enable the interrupt in case of timer overflow. overflow = FALSE PIR1_TMR1IF = FALSE PIE1_TMR1IE = TRUE INTCON_PEIE = TRUE INTCON_GIE = TRUE sample_counter = 0 sample_time = 0 ; Speed up this process by pressing the switch 7 times. This puts the string ; already in the continuous ON mode. for 7 loop press_switch() _usec_delay(500_000) end loop forever loop ; The driver signal has a frequency of 200 Hz or a cycle time of 5 ms. ; This determines the cycle time of this loop. ; Check the driver signal. Wait for driver high but make sure we are low. wait_for_driver_low() wait_for_driver_high() ; Signal is high, start measurement. timer_1_start() wait_for_driver_low() measurement = timer_1_stop() ; Start again to measure the low time. timer_1_start() ; Process the high time measurement. if (measurement > MEASUREMENT_MIN) & (measurement < MEASUREMENT_MAX) then ; OK, now wait for low to finish. wait_for_driver_high() measurement = timer_1_stop() ; Process the low time measurement if (measurement > MEASUREMENT_MIN) & (measurement < MEASUREMENT_MAX) then ; This seems to be continuous on. sample_counter = sample_counter + 1 else ; Low time not correct. if (sample_counter > 0) then sample_counter = sample_counter - 1 end if end if else ; High time not correct. if (sample_counter > 0) then sample_counter = sample_counter - 1 end if end if sample_time = sample_time + 1 ; If we measured long enough we look at the number of samples. if (sample_time == MEASUREMENT_TIME) then if (sample_counter < SAMPLES_OK) then ; Not enough correct samples, press the switch and restart. press_switch() else ; We are done. asm sleep end if ; Restart measurement. sample_counter = 0 sample_time = 0 end if end loop