hello-lkm: more complicated control buttons
authorTero Marttila <terom@paivola.fi>
Sat, 05 Apr 2014 02:53:17 +0300
changeset 61 a960cf5981f7
parent 60 b9648067e9d7
child 62 2d68a76322cb
hello-lkm: more complicated control buttons
src/hello-lkm.c
--- a/src/hello-lkm.c	Sat Apr 05 02:19:36 2014 +0300
+++ b/src/hello-lkm.c	Sat Apr 05 02:53:17 2014 +0300
@@ -415,6 +415,12 @@
 
     // start
     byte channels[4] = { };
+    enum channel_state {
+        CHANNEL_IDLE    = 0,
+        CHANNEL_INC,
+        CHANNEL_DEC,
+    } channel_state[4] = { };
+    byte channel_count[4] = { };
     char c;
         
     while (true) {
@@ -422,26 +428,57 @@
         byte buttons = lkm_buttons();
         
         for (c = 0; c < 4; c++) {
+            enum channel_state state = channel_state[c], next;
+            byte count = channel_count[c];
+
+            // decode buttons -> state
             if (buttons & 0b1) {
-                channels[c]++;
-                lkm_led(c * 2 + 0, LKM_LED_GREEN);
-                lkm_led(c * 2 + 1, LKM_LED_OFF);
+                next = CHANNEL_INC;
             } else if (buttons & 0b10) {
-                channels[c]--;
-                lkm_led(c * 2 + 0, LKM_LED_OFF);
-                lkm_led(c * 2 + 1, LKM_LED_RED);
+                next = CHANNEL_DEC;
             } else {
-                lkm_led(c * 2 + 0, LKM_LED_OFF);
-                lkm_led(c * 2 + 1, LKM_LED_OFF);
+                next = CHANNEL_IDLE;
             }
             
             buttons >>= 2;
             
+            // feedback
+            if (state == CHANNEL_INC || next == CHANNEL_INC)
+                lkm_led(c * 2 + 0, LKM_LED_GREEN);
+            else if (state == CHANNEL_DEC && next == CHANNEL_DEC)
+                lkm_led(c * 2 + 0, LKM_LED_RED);
+            else
+                lkm_led(c * 2 + 0, LKM_LED_OFF);
+
+            if (state == CHANNEL_DEC || next == CHANNEL_DEC)
+                lkm_led(c * 2 + 1, LKM_LED_RED);
+            else if (state == CHANNEL_INC && next == CHANNEL_INC)
+                lkm_led(c * 2 + 1, LKM_LED_GREEN);
+            else
+                lkm_led(c * 2 + 1, LKM_LED_OFF);
+
+            // counts
+            if ((channel_state[c] = next) != state)
+                channel_count[c] = 0;
+            else
+                count = ++channel_count[c];
+
+            // state transitions
+            if (next == CHANNEL_INC && count > 0) {
+                channels[c] += count;
+            } else if (next == CHANNEL_DEC && count > 0) {
+                channels[c] -= count;
+            } else if (state == CHANNEL_INC && !count) {
+                channels[c] = 0xff;
+            } else if (state == CHANNEL_DEC && !count) {
+                channels[c] = 0x00;
+            }
+
             lkm_display_hh(c * 2, channels[c]);
-            
+        
             xbi(&DEBUG_PORT, DEBUG_LED);
         }
 
-        timer_sleep(1000);
+        timer_sleep(8000);
     }
 }