hello-lkm: simple 4-channel control
authorTero Marttila <terom@paivola.fi>
Sat, 05 Apr 2014 02:19:36 +0300
changeset 60 b9648067e9d7
parent 59 7090f61e5e17
child 61 a960cf5981f7
hello-lkm: simple 4-channel control
src/hello-lkm.c
--- a/src/hello-lkm.c	Sat Apr 05 01:50:26 2014 +0300
+++ b/src/hello-lkm.c	Sat Apr 05 02:19:36 2014 +0300
@@ -61,13 +61,16 @@
 };
 
 enum {
-    LKM_DISPLAY_DOT     = 0b10000000,
+    LKM_DISPLAY_DECIMAL = 0b10000000,
 };
 
+/*
+ * XXX: RED/GREEN somehow swapped vs reference; bug in our write code?
+ */
 enum {
     LKM_LED_OFF     = 0b00,
-    LKM_LED_RED     = 0b01,
-    LKM_LED_GREEN   = 0b10,
+    LKM_LED_GREEN   = 0b01,
+    LKM_LED_RED     = 0b10,
     LKM_LED_ORANGE  = 0b11,
 };
 
@@ -293,6 +296,21 @@
     lkm_display(display, LKM_DISPLAY_FONT[hex]);
 }
 
+static inline void lkm_display_dec (byte display, byte dec, byte decimal)
+{
+    byte raw;
+
+    if (dec < 10)
+        raw = LKM_DISPLAY_FONT[dec];
+    else
+        raw = 0x00;
+
+    if (decimal)
+        raw |= LKM_DISPLAY_DECIMAL;
+
+    lkm_display(display, raw);
+}
+
 /*
  * Read the 8-bit key states
  */
@@ -332,9 +350,18 @@
 }
 
 /*
+ * Set 8-bit hexadecimal output on displays n..n+1
+ */
+void lkm_display_hh (byte display, byte hex)
+{
+    lkm_display_hex(display + 0, ((hex >> 4) & 0xF));
+    lkm_display_hex(display + 1, ((hex >> 0) & 0xF));
+}
+
+/*
  * Set 16-bit hexadecimal output on displays 4..7
  */
-void lkm_display_hex16 (short hex)
+void lkm_display_hhhh (short hex)
 {
     lkm_display_hex(7, ((hex >> 0) & 0xF));
     lkm_display_hex(6, ((hex >> 4) & 0xF));
@@ -342,6 +369,21 @@
     lkm_display_hex(4, ((hex >> 12) & 0xF));
 }
 
+/*
+ * Set 2-digit decimal output on displays n..n+1
+ */
+void lkm_display_dd (byte display, byte dec)
+{
+    byte d = dec / 10;
+    byte u = dec % 10;
+
+    byte c = d / 10;
+    d = d % 10;
+
+    lkm_display_dec(display + 0, d, c > 1);
+    lkm_display_dec(display + 1, u, c > 0);
+}
+
 // debug
 #define DEBUG_DDR   DDRB
 #define DEBUG_PORT  PORTB
@@ -361,29 +403,45 @@
     lkm_clear();
     lkm_control(LKM_CONTROL_DISPLAY_ON, LKM_CONTROL_INTENSITY_MAX);
 
+/*
+    // test
+    lkm_led(0, LKM_LED_OFF);
+    lkm_led(1, LKM_LED_RED);
+    lkm_led(2, LKM_LED_GREEN);
+    lkm_led(3, LKM_LED_ORANGE);
+
+    return 0;
+*/
+
     // start
-    byte state[8] = { };
-    char i;
+    byte channels[4] = { };
+    char c;
         
     while (true) {
         // scan input
         byte buttons = lkm_buttons();
         
-        for (i = 0; i < 8; i++) {
-            if (!(buttons & (1 << i))) {
-                continue;
-            } else if (state[i] >= 0xF) {
-                state[i] = 0;
+        for (c = 0; c < 4; c++) {
+            if (buttons & 0b1) {
+                channels[c]++;
+                lkm_led(c * 2 + 0, LKM_LED_GREEN);
+                lkm_led(c * 2 + 1, LKM_LED_OFF);
+            } else if (buttons & 0b10) {
+                channels[c]--;
+                lkm_led(c * 2 + 0, LKM_LED_OFF);
+                lkm_led(c * 2 + 1, LKM_LED_RED);
             } else {
-                state[i]++;
+                lkm_led(c * 2 + 0, LKM_LED_OFF);
+                lkm_led(c * 2 + 1, LKM_LED_OFF);
             }
-
-            lkm_display_hex(i, state[i]);
-            lkm_led(i, state[i]);
+            
+            buttons >>= 2;
+            
+            lkm_display_hh(c * 2, channels[c]);
             
             xbi(&DEBUG_PORT, DEBUG_LED);
         }
 
-        timer_sleep(16000);
+        timer_sleep(1000);
     }
 }