]> mj.ucw.cz Git - home-hw.git/blobdiff - dmx/firmware/main.c
Auto: Meditation mode turned off
[home-hw.git] / dmx / firmware / main.c
index cc0b82625b26af5152df4a9e69b206b015449fc8..47ff5d35e3cb7d34fa70e8c46552f2692626f997 100644 (file)
@@ -57,8 +57,12 @@ static void gpio_init(void)
 
        // PB10 = TXD3 for DMX
        // PB11 = RXD3 for DMX
-       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO10);
+       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO10);
        gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO11);
+
+       // PB1 = TX enable for DMX (always on)
+       gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
+       gpio_set(GPIOB, GPIO1);
 }
 
 static void usart_init(void)
@@ -98,11 +102,16 @@ static void delay_ms(uint ms)
 
 /*** DMX ***/
 
+#define DMX_MAX_PACKET_SIZE 64
+
 static volatile byte dmx_state;
-static byte dmx_packet[64];
+static byte dmx_packet[DMX_MAX_PACKET_SIZE];
 static byte dmx_pos, dmx_len;
 
-#define DEBUG_DMX
+static byte dmx_next_packet[DMX_MAX_PACKET_SIZE];
+static byte dmx_next_len;
+
+#undef DEBUG_DMX
 #ifdef DEBUG_DMX
 #define DMX_DEBUG(ch) debug_putc(ch)
 #else
@@ -122,7 +131,7 @@ static void dmx_init(void)
 {
        usart_set_baudrate(USART3, 250000);
        usart_set_databits(USART3, 8);
-       usart_set_stopbits(USART3, USART_STOPBITS_1);
+       usart_set_stopbits(USART3, USART_STOPBITS_2);
        usart_set_mode(USART3, USART_MODE_TX);
        usart_set_parity(USART3, USART_PARITY_NONE);
        usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
@@ -137,6 +146,10 @@ static void dmx_init(void)
        timer_one_shot_mode(TIM3);
        timer_enable_irq(TIM3, TIM_DIER_UIE);
        nvic_enable_irq(NVIC_TIM3_IRQ);
+
+       // Until we get data from USB, send "turn everything off" packets
+       memset(dmx_next_packet, 0, DMX_MAX_PACKET_SIZE);
+       dmx_next_len = DMX_MAX_PACKET_SIZE;
 }
 
 void tim3_isr(void)
@@ -189,9 +202,9 @@ void usart3_isr(void)
                // Transfer of the last byte is complete, but we have to wait
                // before the start of the next packet: minimum time between two
                // breaks must be at least 1204 μs. We already sent a 200μs break,
-               // 200μs mark, and dmx_len 40μs data slots.
+               // 200μs mark, and dmx_len 44μs data slots.
                USART_CR1(USART3) &= ~USART_CR1_TCIE;
-               uint sent = 200 + 200 + 40*dmx_len;
+               uint sent = 200 + 200 + 44*dmx_len;
                if (sent < 1300) {
                        DMX_DEBUG('g');
                        dmx_state = DMX_STATE_GAP;
@@ -210,13 +223,10 @@ static void dmx_send(void)
        if (dmx_state != DMX_STATE_IDLE)
                return;
 
-       dmx_packet[0] = 0;
-       dmx_packet[1] = 0xff;   // warm
-       dmx_packet[2] = 0xff;   // cold
-       dmx_packet[3] = 0;
-       dmx_packet[4] = 0;
+       if (!dmx_len)
+               return;
+
        dmx_pos = 0;
-       dmx_len = 5;
 
        // Send break for 200 μs
        DMX_DEBUG('<');
@@ -358,9 +368,9 @@ static enum usbd_request_return_codes dfu_control_cb(usbd_device *dev UNUSED,
 static void ep01_cb(usbd_device *dev, uint8_t ep UNUSED)
 {
        // We received a frame from the USB host
-       byte buf[64];
-       uint len = usbd_ep_read_packet(dev, 0x01, buf, sizeof(buf));
+       uint len = usbd_ep_read_packet(dev, 0x01, dmx_next_packet, DMX_MAX_PACKET_SIZE);
        debug_printf("USB: Host sent %u bytes\n", len);
+       dmx_next_len = len;
 }
 
 static void set_config_cb(usbd_device *dev, uint16_t wValue UNUSED)
@@ -433,6 +443,7 @@ int main(void)
        dmx_init();
 
        u32 last_blink = 0;
+       u32 last_send = 0;
 
        for (;;) {
                if (ms_ticks - last_blink >= 100) {
@@ -448,6 +459,23 @@ int main(void)
                        nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
                }
 
+               if (dmx_state == DMX_STATE_IDLE) {
+                       if (dmx_next_len) {
+                               // We have a new packet to send
+                               debug_printf("Sending new packet: %d bytes\n", dmx_next_len);
+                               memcpy(dmx_packet, dmx_next_packet, dmx_next_len);
+                               dmx_len = dmx_next_len;
+                               dmx_next_len = 0;
+                               dmx_send();
+                               last_send = ms_ticks;
+                       } else if (ms_ticks - last_send >= 100) {
+                               // Re-send every 100 ms
+                               // debug_printf("Re-send: %d bytes\n", dmx_len);
+                               dmx_send();
+                               last_send = ms_ticks;
+                       }
+               }
+
                wait_for_interrupt();
        }