]> mj.ucw.cz Git - home-hw.git/commitdiff
test-display2: Experiments with IR receiver
authorMartin Mares <mj@ucw.cz>
Sat, 13 May 2023 22:29:34 +0000 (00:29 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 13 May 2023 22:29:34 +0000 (00:29 +0200)
test-display2/config.h
test-display2/main.c

index fe39e28caa5bf33ab643ffbcdd5e1ce978ff10e1..50926f96373acfa91b4a038aead0b7f611a83ce0 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *     Test Gadget -- Configuration
+ *     Workshop Clock -- Configuration
  *
- *     (c) 2020 Martin Mareš <mj@ucw.cz>
+ *     (c) 2020-2023 Martin Mareš <mj@ucw.cz>
  */
 
 // Processor clock
index 4fb15906ac1e60139a00cee39bcdbfca19d39e38..3c8049869c7abefc182d595129327af8507d7f2c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Workshop Clock
  *
- *     (c) 2020 Martin Mareš <mj@ucw.cz>
+ *     (c) 2020-2023 Martin Mareš <mj@ucw.cz>
  */
 
 #include "util.h"
@@ -15,6 +15,7 @@
 #include <libopencm3/stm32/gpio.h>
 #include <libopencm3/stm32/usart.h>
 #include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/timer.h>
 #include <libopencm3/usb/dfu.h>
 #include <libopencm3/usb/usbd.h>
 
@@ -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<nsamp; i++) {
-                       debug_putc(i ? ' ' : '\n');
-                       debug_printf("%u", (unsigned int)((samples[i] + CPU_CLOCK_MHZ - 1) / CPU_CLOCK_MHZ));   // in μs
-               }
-               debug_putc('\n');
-       }
-}
-
-#endif
-
 /*** Main ***/
 
 int main(void)
@@ -483,10 +474,6 @@ int main(void)
        gpio_init();
        usart_init();
 
-#ifdef IR_TEST
-       ir_test_loop();
-#endif
-
        tick_init();
        desig_get_unique_id_as_dfu(usb_serial_number);
 
@@ -494,6 +481,7 @@ int main(void)
 
        usb_init();
        display_init();
+       ir_init();
 
        u32 last_blink = 0;
 
@@ -511,6 +499,22 @@ int main(void)
                        nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
                }
 
+               static u16 pulses[IR_MAX_PULSES];
+               uint np;
+
+               cm_disable_interrupts();
+               np = ir_num_pulses;
+               memcpy(pulses, ir_pulses, 2*np);
+               ir_num_pulses = 0;
+               cm_enable_interrupts();
+
+               if (np) {
+                       debug_printf("IR:");
+                       for (uint i=0; i < np; i++)
+                               debug_printf(" %u", pulses[i]);
+                       debug_putc('\n');
+               }
+
                wait_for_interrupt();
        }