--- /dev/null
+#include "util.h"
+
+#include <libopencm3/cm3/cortex.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+
+static void clock_setup(void)
+{
+ rcc_clock_setup_in_hse_8mhz_out_72mhz();
+
+ rcc_periph_clock_enable(RCC_GPIOB);
+ rcc_periph_clock_enable(RCC_GPIOC);
+ rcc_periph_clock_enable(RCC_USART1);
+
+ rcc_periph_reset_pulse(RST_GPIOB);
+ rcc_periph_reset_pulse(RST_GPIOC);
+ rcc_periph_reset_pulse(RST_USART1);
+}
+
+static void gpio_setup(void)
+{
+ // PC13 = BluePill LED
+ gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
+ gpio_clear(GPIOC, GPIO13);
+
+ // PB9 = SFH5110 output (5V tolerant)
+ gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO9);
+}
+
+static void usart_setup(void)
+{
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+
+ usart_set_baudrate(USART1, 115200);
+ usart_set_databits(USART1, 8);
+ usart_set_stopbits(USART1, USART_STOPBITS_1);
+ usart_set_mode(USART1, USART_MODE_TX_RX);
+ usart_set_parity(USART1, USART_PARITY_NONE);
+ usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
+
+ usart_enable(USART1);
+}
+
+static void tick_setup(void)
+{
+ systick_set_reload(0xffffff);
+ systick_counter_enable();
+ systick_interrupt_disable();
+ systick_clear();
+}
+
+static u16 get_bit(void)
+{
+ return !gpio_get(GPIOB, GPIO9);
+}
+
+#define MAX_SAMPLES 1024
+u32 samples[MAX_SAMPLES];
+
+int main(void)
+{
+ clock_setup();
+ gpio_setup();
+ usart_setup();
+ tick_setup();
+
+ debug_puts("\n\n### Infrared Remote Control receiver ###\n\n");
+
+ 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", (samples[i] + CPU_CLOCK_MHZ - 1) / CPU_CLOCK_MHZ); // in μs
+ }
+ debug_putc('\n');
+ }
+
+ return 0;
+}