From: Martin Mares Date: Sat, 13 May 2023 22:29:34 +0000 (+0200) Subject: test-display2: Experiments with IR receiver X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=9f545c433a380389eb6ed78bdb47501c879ab192;p=home-hw.git test-display2: Experiments with IR receiver --- diff --git a/test-display2/config.h b/test-display2/config.h index fe39e28..50926f9 100644 --- a/test-display2/config.h +++ b/test-display2/config.h @@ -1,7 +1,7 @@ /* - * Test Gadget -- Configuration + * Workshop Clock -- Configuration * - * (c) 2020 Martin Mareš + * (c) 2020-2023 Martin Mareš */ // Processor clock diff --git a/test-display2/main.c b/test-display2/main.c index 4fb1590..3c80498 100644 --- a/test-display2/main.c +++ b/test-display2/main.c @@ -1,7 +1,7 @@ /* * Workshop Clock * - * (c) 2020 Martin Mareš + * (c) 2020-2023 Martin Mareš */ #include "util.h" @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -24,7 +25,7 @@ static void clock_init(void) { - rcc_clock_setup_in_hse_8mhz_out_72mhz(); + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOB); @@ -32,6 +33,7 @@ static void clock_init(void) rcc_periph_clock_enable(RCC_I2C1); rcc_periph_clock_enable(RCC_USART1); rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_TIM1); rcc_periph_reset_pulse(RST_GPIOA); rcc_periph_reset_pulse(RST_GPIOB); @@ -39,6 +41,7 @@ static void clock_init(void) rcc_periph_reset_pulse(RST_I2C1); rcc_periph_reset_pulse(RST_USART1); rcc_periph_reset_pulse(RST_USB); + rcc_periph_reset_pulse(RST_TIM1); } static void gpio_init(void) @@ -56,7 +59,7 @@ static void gpio_init(void) // PB6 = SCL for display controller gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO6 | GPIO7); - // PB8 = SFH5110 output (5V tolerant) + // PA8 = SFH5110 output (5V tolerant) connected to TIM1_CH1 gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO8); } @@ -121,7 +124,7 @@ static byte ctrl = 0x56; static void display_update(void) { - debug_puts("Display update\n"); + // debug_puts("Display update\n"); byte cmds[4]; cmds[0] = 0; cmds[1] = ctrl; @@ -133,7 +136,7 @@ static void display_update(void) cmds[3] = disp[2]; i2c_transfer7(I2C1, 0x70/2, (byte *) cmds, sizeof(cmds), NULL, 0); - debug_puts("Update done\n"); + // debug_puts("Update done\n"); } static void display_init(void) @@ -194,6 +197,76 @@ static const byte lcd_font[] = { [15] = 0x78, }; +/*** Infrared Remote Control ***/ + +static void ir_init(void) +{ + debug_puts("IR init\n"); + + timer_set_prescaler(TIM1, 71); // 72 MHz / 72 = 1 MHz + timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_period(TIM1, 65535); + timer_update_on_overflow(TIM1); + + // IC1 will trigger on TI1 (TIM1_CH1) falling edge + timer_ic_set_input(TIM1, TIM_IC1, TIM_IC_IN_TI1); + // timer_ic_set_filter(TIM1, TIM_IC1, TIM_IC_OFF); + timer_set_oc_polarity_low(TIM1, TIM_OC1); // OC functions affect IC, too + + // IC2 will trigger on TI1 (TIM1_CH1) rising edge + timer_ic_set_input(TIM1, TIM_IC2, TIM_IC_IN_TI1); + timer_set_oc_polarity_high(TIM1, TIM_OC2); + + // CH3 will trigger on a break longer than 50 ms + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_ACTIVE); + timer_set_oc_value(TIM1, TIM_OC3, 30000); + + // Program slave controller to reset the timer on IC1 + timer_slave_set_trigger(TIM1, TIM_SMCR_TS_TI1FP1); + timer_slave_set_mode(TIM1, TIM_SMCR_SMS_RM); + + // Request interrupts + timer_enable_irq(TIM1, TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE); + nvic_enable_irq(NVIC_TIM1_CC_IRQ); + + // Enable ICs and OCs + timer_enable_oc_output(TIM1, TIM_OC1); + timer_enable_oc_output(TIM1, TIM_OC2); + timer_enable_oc_output(TIM1, TIM_OC3); + + timer_enable_counter(TIM1); +} + +#define IR_MAX_PULSES 64 +static u16 ir_pulses[IR_MAX_PULSES]; +static uint ir_num_pulses; +static u16 ir_last_pulse; + +void tim1_cc_isr(void) +{ + if (TIM_SR(TIM1) & TIM_SR_CC1IF) { + TIM_SR(TIM1) &= ~TIM_SR_CC1IF; + u16 now = TIM_CCR1(TIM1); + if (ir_last_pulse) { + ir_pulses[ir_num_pulses++] = ir_last_pulse; + ir_pulses[ir_num_pulses++] = now - ir_last_pulse; + ir_last_pulse = 0; + } + } + if (TIM_SR(TIM1) & TIM_SR_CC2IF) { + TIM_SR(TIM1) &= ~TIM_SR_CC2IF; + ir_last_pulse = TIM_CCR2(TIM1); + } + if (TIM_SR(TIM1) & TIM_SR_CC3IF) { + TIM_SR(TIM1) &= ~TIM_SR_CC3IF; + if (ir_last_pulse) { + ir_pulses[ir_num_pulses++] = ir_last_pulse; + ir_pulses[ir_num_pulses++] = 0xffff; + } + ir_last_pulse = 0; + } +} + /*** USB ***/ static usbd_device *usbd_dev; @@ -393,88 +466,6 @@ static void usb_init(void) usb_event_pending = 1; } -/*** Testing of IR receiver ***/ - -#ifdef IR_TEST - -static u16 get_bit(void) -{ -#if 1 - return !gpio_get(GPIOB, GPIO8); -#else - int x = 0; - x += !gpio_get(GPIOB, GPIO8); - x += !gpio_get(GPIOB, GPIO8); - x += !gpio_get(GPIOB, GPIO8); - x += !gpio_get(GPIOB, GPIO8); - return x >= 2; -#endif -} - -#define MAX_SAMPLES 1024 -u32 samples[MAX_SAMPLES]; - -static void ir_test_loop(void) -{ - debug_puts("\n\n### Infrared Remote Control receiver ###\n\n"); - - systick_set_reload(0xffffff); - systick_counter_enable(); - systick_interrupt_disable(); - systick_clear(); - - for (;;) { - gpio_set(GPIOC, GPIO13); - - if (get_bit()) { - debug_puts("Waiting for silence\n"); - while (get_bit()) - ; - } - debug_puts("Ready..."); - - u16 last = 0; - uint nsamp = 0; - u32 start; - - do { - start = systick_get_value(); - last = get_bit(); - } while (!last); - - gpio_clear(GPIOC, GPIO13); - - for (;;) { - u32 now; - u16 curr; - uint len; - do { - now = systick_get_value(); - len = (start - now) & 0xffffff; - if (len > 5000000) { - samples[nsamp++] = len; - goto timeout; - } - curr = get_bit(); - } while (curr == last); - samples[nsamp++] = len; - if (nsamp >= MAX_SAMPLES) - break; - start = now; - last = curr; - } - - timeout: - for (uint i=0; i