A better state machine.
authorMalte S. Stretz <mss@apache.org>
Tue, 10 Feb 2009 16:29:02 +0000 (16:29 +0000)
committerMalte S. Stretz <mss@apache.org>
Tue, 10 Feb 2009 16:29:02 +0000 (16:29 +0000)
src/buffer.c
src/dmx.c

index 862e0f5..b239b07 100644 (file)
@@ -2,63 +2,24 @@
 
 char gg_buffer_gs[512] = {
   /* R     G     B */
-   0x01, 0x01, 0x01,
-   0x00, 0x00, 0xFF,
-
-
-   0x00, 0x00, 0x00,
-   0xDD, 0xDD, 0xDD,
-   0xCC, 0xCC, 0xCC,
-   0xBB, 0xBB, 0xBB,
-   0xAA, 0xAA, 0xAA,
-   0x99, 0x99, 0x99,
-   0x88, 0x88, 0x88,
-   0x77, 0x77, 0x77,
-   0x66, 0x66, 0x66,
-   0x55, 0x55, 0x55,
-   0x44, 0x44, 0x44,
-   0x33, 0x33, 0x33,
-   0x22, 0x22, 0x22,
-
-   0xFF, 0x00, 0x00,
-
-
-
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00,
-
-
-
-   0xFF, 0xFF, 0xFF,
-   0xEE, 0xEE, 0xEE,
-   0xDD, 0xDD, 0xDD,
-   0xCC, 0xCC, 0xCC,
-   0xBB, 0xBB, 0xBB,
-   0xAA, 0xAA, 0xAA,
-   0x99, 0x99, 0x99,
-   0x88, 0x88, 0x88,
-   0x77, 0x77, 0x77,
-   0x66, 0x66, 0x66,
-   0x55, 0x55, 0x55,
-   0x44, 0x44, 0x44,
-   0x33, 0x33, 0x33,
-   0x22, 0x22, 0x22,
-   0x11, 0x11, 0x11,
-   0x01, 0x02, 0x03
+   0xFF, 0xFF, 0xFF,  // 01
+   0xFF, 0x00, 0xFF,  // 02
+   0x00, 0x00, 0x00,  // 03
+   0xDD, 0xDD, 0xDD,  // 04
+   0xCC, 0xCC, 0xCC,  // 05
+   0xBB, 0xBB, 0xBB,  // 06
+   0xAA, 0xAA, 0xAA,  // 07
+   0x99, 0x99, 0x99,  // 08
+   0x88, 0x88, 0x88,  // 09
+   0x77, 0x77, 0x77,  // 10
+   0x66, 0x66, 0x66,  // 11
+   0x55, 0x55, 0x55,  // 12
+   0x44, 0x44, 0x44,  // 13
+   0x33, 0x33, 0x33,  // 14
+   0x22, 0x22, 0x22,  // 15
+
+   0x33, 0x00, 0x33   // 16
+
 };
 
 char gg_buffer_dc[3]   = {
@@ -87,17 +48,20 @@ void reset_counter(void)
 
 void buffer_init(void)
 {
+#if 0
   #define BUFFER_INIT_KEEP 1
-
   #if BUFFER_INIT_KEEP == 0
   memset(gg_buffer_gs, 0x00, sizeof(gg_buffer_gs));
   #endif
+
   for (uint8_t i = 0; i < (TLC_N_CHANNELS / TLC_N_TLCS_PER_PAINTER - BUFFER_INIT_KEEP); i++)
     for (uint8_t rgb = 0; rgb < 3; rgb++)
-      gg_buffer_gs[i * 3 + rgb] = 0x00;// | (rgb + 1);
+      gg_buffer_gs[i * 3 + rgb] = 0xF0 | (rgb + 1);
    reset_counter();
+#endif
 }
 
+#if 0
 void buffer_next(void)
 {
   //sched_put(&buffer_test_next);
@@ -124,3 +88,4 @@ void buffer_do(void)
 {
   g_rgb--;
 }
+#endif
index 0ff3457..7db8f05 100644 (file)
--- a/src/dmx.c
+++ b/src/dmx.c
 #include "buffer.h"
 
 
-void set_timer(uint8_t count)
+
+
+void set_timer(int8_t ms)
 {
-  // Set timer.
-  TCNT0 = 0xFF - ((F_CPU / 1000000) * count);
+  // Set counter to trigger correct overflow.
+  TCNT0 = 0xFF - 2 * ms;
 
-  // Enable timer, no prescaling.
-  bits_mask_on(TCCR0, 1 << CS00);
+  // Enable timer interrupt (p72)
+  bits_on(TIMSK, TOIE0);
 }
 
 void set_timer_off(void)
 {
-  // Disable timer (p72)
-  bits_mask_off(TCCR0, (1 << CS02) | (1 << CS01) | (1 << CS00));
+  // Disable timer interrupt (p72).
+  bits_off(TIMSK, TOIE0);
 }
 
-void set_falling_edge_trigger(void)
+void set_trigger_rising(void)
 {
+  // Trigger on rising edge.
+  bits_on(MCUCR, ISC00);
+
+  // Enable interrupt.
+  bits_on(GICR, INT0);
+}
+
+void set_trigger_falling(void)
+{
+  // Trigger on falling edge.
   bits_off(MCUCR, ISC00);
+
+  // Enable interrupt.
+  bits_on(GICR, INT0);
 }
 
-void set_rising_edge_trigger(void)
+void set_trigger_off(void)
 {
-  bits_on(MCUCR, ISC00);
+  // Disable interrupt.
+  bits_off(GICR, INT0);
 }
 
+///////////////////////////////
 
 void dmx_init(void)
 {
+  // Use a frequency prescaler of 8 (p72).
+  bits_mask_on(TCCR0, 1 << CS01);
+
   // Configure as input.
   pin_in(PIN_DMX);
 
-  // To start, trigger INT0 on falling edge (p67),
-  // we'll keep this bit set and only toggle between
-  // falling and rising.
+  // Prepare INT0, set_trigger_* will toggle between edges.
+  set_trigger_off();
   bits_on(MCUCR, ISC01);
 
-  // Enable INT0
-  bits_on(GICR, INT0);
-
-  // Enable timer interrupt (p72)
-  bits_on(TIMSK, TOIE0);
+  // Enable interrupt after a short while.
+  set_timer(10);
 }
 
+///////////////////////////////
+
 enum state_enum {
   STATE_IDLE,
   STATE_WAIT,
   STATE_MARK,
   STATE_SYNC,
-  STATE_READ
+  STATE_READ,
+  STATE_STOR
 };
 
 uint8_t  g_package_buffer;
 uint8_t  g_package_mask;
-uint16_t g_package_index;
+int16_t  g_package_index;
 enum state_enum g_state = STATE_IDLE;
 
 void dmx_int_timer0_ovf(void)
 {
-  switch (g_state) {
-    case STATE_WAIT:
-      g_state = STATE_MARK;
+  // Disable this interrupt.
+  set_timer_off();
+
+  switch (g_state)
+  {
+    case STATE_IDLE: {
+      // The line must be High when idle.
+      if (pin_is_set(PIN_DMX)) {
+        // Wait for start of Reset.
+        set_trigger_falling();
+      }
+      else {
+        // Wait for High.
+        set_timer(10);
+      }
+      break;
+    }
+    
+    case STATE_WAIT: {
+      // Reset was held for 88 us, wait for end of Mark now.
+      mcu_debug();
+      set_trigger_falling();
       g_package_index = -1;
-      set_falling_edge_trigger();
+      g_state = STATE_MARK;
       break;
-      
-    case STATE_SYNC:
-      g_state = STATE_READ;
-      g_package_mask = bits_uint8(0, 0, 0, 0, 0, 0, 0, 1);
+    }
+
+    case STATE_SYNC: {
+      // Now read the data, LSB first.
       set_timer(4);
+      g_package_mask = bits_uint8(0, 0, 0, 0, 0, 0, 0, 1);
+      g_state = STATE_READ;
       break;
-      
-    case STATE_READ:
+    }
+
+    case STATE_READ: {
+      // Prepare next timer.
+      set_timer(4);
+
+      // Read bit.
       if (pin_is_set(PIN_DMX)) {
         bits_mask_on( g_package_buffer, g_package_mask);
       } else {
         bits_mask_off(g_package_buffer, g_package_mask);
       }
+
+      // Prepare next bit.
       g_package_mask <<= 1;
-      if (g_package_mask == 0)
-      {
+      if (g_package_mask == 0) {
+        // Got a full package, store it.
+        set_timer(1);
+        g_state = STATE_STOR;
+      }
+      break;
+    }
+
+    case STATE_STOR: {
+      // Store byte, but skip start byte.
+      if (g_package_index != -1) {
+        //gg_buffer_gs[g_package_index] = g_package_buffer;
+      }
+      // Next byte.
+      g_package_index++;
+
+      // Wait for next package or next frame.
+      if (g_package_index != 512) {
+        set_trigger_falling();
         g_state = STATE_MARK;
-        switch (g_package_index) {
-          case -1:
-            if (g_package_buffer != 0) {
-              g_state = STATE_WAIT;
-              set_falling_edge_trigger();
-              set_timer_off();
-            }
-            break;
-          case 511:
-            g_state = STATE_WAIT;
-            set_falling_edge_trigger();
-            set_timer_off();
-            /* FALL THROUGH */
-          default:
-            gg_buffer_gs[g_package_index] = g_package_buffer;
-        }
-        g_package_index++;
       }
+      else {
+        set_timer(20);
+        g_state = STATE_IDLE;
+      }
+      break;
+    }
 
-    default:
+    default: {
       break;
+    }
   }
 }
 
+
 void dmx_int_ext(void)
 {
-  switch (g_state) {
-    case STATE_IDLE:
-      g_state = STATE_WAIT;
+  // Disable this interrupt.
+  set_trigger_off();
+
+  switch (g_state)
+  {
+    case STATE_IDLE: {
+      // Wait for end of Reset.
       set_timer(88);
-      set_rising_edge_trigger();
+      set_trigger_rising();
+      g_state = STATE_WAIT;
       break;
-      
-    case STATE_WAIT:
+    }
+
+    case STATE_WAIT: {
+      // We got a stray edge before Reset timeout, back to IDLE.
+      set_timer(1);
       g_state = STATE_IDLE;
-      set_timer_off();
-      set_falling_edge_trigger();
       break;
-      
-    case STATE_MARK:
-      g_state = STATE_SYNC;
+    }
+
+    case STATE_MARK: {
+      // We got our start bit, sync to middle.
+      mcu_debug();
       set_timer(2);
-      //set_no_trigger();
+      g_state = STATE_SYNC;
       break;
-      
-    default:
+    }
+
+    default: {
       break;
+    }
   }
 }
+