]> mj.ucw.cz Git - home-hw.git/blobdiff - ir-send/test.c
FIXME'd
[home-hw.git] / ir-send / test.c
index db52d8cc87b70fca8fbb1f7dc5ae6d4418132dfa..defdd22d9427271da1cd3360c4ace61ef318601d 100644 (file)
@@ -8,6 +8,8 @@
 #include <libopencm3/stm32/usart.h>
 #include <libopencm3/stm32/timer.h>
 
+#include <string.h>
+
 static void clock_setup(void)
 {
        rcc_clock_setup_in_hse_8mhz_out_72mhz();
@@ -16,14 +18,16 @@ static void clock_setup(void)
        rcc_periph_clock_enable(RCC_GPIOB);
        rcc_periph_clock_enable(RCC_GPIOC);
        rcc_periph_clock_enable(RCC_USART1);
-       rcc_periph_clock_enable(RCC_TIM2);
+       rcc_periph_clock_enable(RCC_TIM1);
+       rcc_periph_clock_enable(RCC_TIM4);
        rcc_periph_clock_enable(RCC_AFIO);
 
        rcc_periph_reset_pulse(RST_GPIOA);
        rcc_periph_reset_pulse(RST_GPIOB);
        rcc_periph_reset_pulse(RST_GPIOC);
        rcc_periph_reset_pulse(RST_USART1);
-       rcc_periph_reset_pulse(RST_TIM2);
+       rcc_periph_reset_pulse(RST_TIM1);
+       rcc_periph_reset_pulse(RST_TIM4);
 }
 
 static void gpio_setup(void)
@@ -32,9 +36,18 @@ static void gpio_setup(void)
        gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
        gpio_clear(GPIOC, GPIO13);
 
-       // Remap TIM2
+       // Switch JTAG off to free up pins
+       gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 0);
        // gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, AFIO_MAPR_TIM2_REMAP_FULL_REMAP);
-       AFIO_MAPR = 0x04000300;
+
+       // TIM2_CH3 on PB3 (remapped)
+       // gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO10);
+
+       // TIM4_CH1 on PB6: PWM for fan control
+       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO6);
+
+       // TIM4_CH2 on PB7: PWM for IR LED
+       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO7);
 }
 
 static volatile u32 ms_ticks;
@@ -51,7 +64,7 @@ static void tick_setup(void)
        systick_interrupt_enable();
 }
 
-static void delay_ms(uint ms)
+static void UNUSED delay_ms(uint ms)
 {
        u32 start_ticks = ms_ticks;
        while (ms_ticks - start_ticks < ms)
@@ -61,6 +74,7 @@ static void delay_ms(uint ms)
 static void usart_setup(void)
 {
        gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+       gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
 
        usart_set_baudrate(USART1, 115200);
        usart_set_databits(USART1, 8);
@@ -72,40 +86,167 @@ static void usart_setup(void)
        usart_enable(USART1);
 }
 
+enum rc_keys {
+       RC_AUTO,
+       RC_TEMP_UP,
+       RC_FUNC,
+       RC_HI,
+       RC_TIMER,
+       RC_MID,
+       RC_TEMP_DOWN,
+       RC_SLEEP,
+       RC_LOW,
+       RC_POWER,
+       RC_XXX_A,
+       RC_XXX_B,
+       RC_MAX
+};
+
+static const char * const rc_patterns[RC_MAX] = {
+       [RC_AUTO]       = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*B*A*B*A*A*B*B*A*A*B*A*B*B*A*",
+       [RC_TEMP_UP]    = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*A*B*A*B*A*A*B*B*B*A*B*A*B*B*A*",
+       [RC_FUNC]       = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*B*B*B*A*A*B*A*B*A*A*A*B*B*A*",
+       [RC_HI]         = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*A*B*B*A*A*B*A*B*B*A*A*B*B*A*",
+       [RC_TIMER]      = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*B*B*B*A*A*B*B*A*A*A*A*B*B*A*",
+       [RC_MID]        = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*B*A*B*B*A*A*B*A*A*B*A*A*B*B*A*",
+       [RC_TEMP_DOWN]  = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*B*A*B*A*A*B*A*B*A*B*A*B*B*A*",
+       [RC_SLEEP]      = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*B*B*B*B*A*A*B*A*A*A*A*A*B*B*A*",
+       [RC_LOW]        = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*A*B*B*A*A*B*B*A*B*A*A*B*B*A*",
+       [RC_POWER]      = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*A*B*B*B*A*A*B*B*B*A*A*A*B*B*A*",
+       [RC_XXX_A]      = "^#*A*B*A*A*B*A*B*B*A*A*B*A*A*A*A*A*A*B*B*B*B*A*A*A*B*A*A*A*A*B*B*B*",
+       [RC_XXX_B]      = "^#*A*B*A*A*B*A*B*B*A*A*B*A*A*A*A*A*B*B*B*B*B*A*A*A*A*A*A*A*A*B*B*B*",
+};
+
+// FIXME
+static const char rc_keys[] = "aufhtmdslp12";
+
+// TIM4 will run on CPU clock, it will overflow with frequency 38 kHz (IR modulation frequency)
+#define T4_CYCLE ((CPU_CLOCK_MHZ * 1000000 + 37999) / 38000)
+
+static void rc_setup(void)
+{
+       timer_set_prescaler(TIM4, 0);
+       timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
+       timer_disable_preload(TIM4);
+       timer_set_period(TIM4, T4_CYCLE - 1);
+
+       // 50% PWM for the IR LED
+       timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1);
+       timer_set_oc_value(TIM4, TIM_OC2, T4_CYCLE / 2);
+       timer_set_oc_polarity_high(TIM4, TIM_OC2);
+       timer_enable_oc_output(TIM4, TIM_OC2);
+
+       // PWM for controlling fan
+       timer_set_oc_mode(TIM4, TIM_OC1, TIM_OCM_PWM1);
+       timer_set_oc_value(TIM4, TIM_OC1, T4_CYCLE / 4);
+       timer_set_oc_polarity_high(TIM4, TIM_OC1);
+       timer_enable_oc_output(TIM4, TIM_OC1);
+
+       timer_enable_counter(TIM4);
+
+       // TIM1 runs at 1 MHz and it is used for timing of RC pulses
+       timer_set_prescaler(TIM1, CPU_CLOCK_MHZ - 1);
+       timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
+       timer_update_on_overflow(TIM1);
+       timer_disable_preload(TIM1);
+       timer_one_shot_mode(TIM1);
+       timer_enable_irq(TIM1, TIM_DIER_UIE);
+       nvic_enable_irq(NVIC_TIM1_UP_IRQ);
+}
+
+static const char *rc_pattern_pos;
+
+void tim1_up_isr(void)
+{
+       if (TIM_SR(TIM1) & TIM_SR_UIF) {
+               TIM_SR(TIM1) &= ~TIM_SR_UIF;
+
+               if (!rc_pattern_pos)    // Just to be sure
+                       return;
+
+               bool val;       // 1=pulse, 0=break
+               uint duration;  // in μs
+
+               switch (*rc_pattern_pos++) {
+                       case '^':
+                               val = 1;
+                               duration = 9032;
+                               break;
+                       case '#':
+                               val = 0;
+                               duration = 4457;
+                               break;
+                       case '*':
+                               val = 1;
+                               duration = 619;
+                               break;
+                       case 'A':
+                               val = 0;
+                               duration = 514;
+                               break;
+                       case 'B':
+                               val = 0;
+                               duration = 1617;
+                               break;
+                       default:
+                               // End of transmission
+                               gpio_set(GPIOC, GPIO13);        // FIXME
+                               rc_pattern_pos = NULL;
+                               val = 0;
+                               duration = 10000;
+               }
+
+               if (val)
+                       timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1);
+               else
+                       timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_FORCE_HIGH);
+
+               timer_set_period(TIM1, duration - 1);
+               timer_generate_event(TIM1, TIM_EGR_UG);
+               timer_enable_counter(TIM1);
+       }
+}
+
+static void rc_send(uint key)
+{
+       rc_pattern_pos = rc_patterns[key];
+
+       gpio_clear(GPIOC, GPIO13);
+
+       timer_set_period(TIM1, 1);
+       timer_generate_event(TIM1, TIM_EGR_UG);
+       timer_enable_counter(TIM1);
+}
+
 int main(void)
 {
        clock_setup();
        gpio_setup();
        tick_setup();
        usart_setup();
+       rc_setup();
 
-       // cm_enable_interrupts();
-       debug_puts("Hello!\n");
-
-#if 1
-       timer_set_prescaler(TIM2, 3);
-       timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
-       timer_disable_preload(TIM2);
-       timer_set_period(TIM2, 65535);
-       timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_PWM1);
-       timer_set_oc_value(TIM2, TIM_OC3, 32768);
-       timer_set_oc_polarity_high(TIM2, TIM_OC3);
-       timer_enable_counter(TIM2);
-       timer_enable_oc_output(TIM2, TIM_OC3);
-#endif
-
-       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO10);
-       // gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO10);
-       gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
+       debug_puts("Hello world!\n");
+       gpio_set(GPIOC, GPIO13);
 
        for (;;) {
+#if 0
                gpio_toggle(GPIOC, GPIO13);
-               delay_ms(20);
-               gpio_toggle(GPIOA, GPIO15);
-               debug_putc('.');
-               timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_FORCE_LOW);
-               delay_ms(20);
-               timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_FORCE_HIGH);
+               delay_ms(1);
+               timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_FORCE_HIGH);
+               gpio_toggle(GPIOC, GPIO13);
+               delay_ms(1);
+               timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1);
+#else
+               if (usart_get_flag(USART1, USART_SR_RXNE)) {
+                       uint ch = usart_recv(USART1);
+                       const char *key = strchr(rc_keys, ch);
+                       if (key) {
+                               debug_putc(ch);
+                               rc_send(key - rc_keys);
+                       }
+               }
+#endif
        }
 
        return 0;