trennfix/sw: Added smokefix, further modularized the mm decoder
[eisenbahn.git] / trennfix / sw / mm / include / mm / mm_decode.h
diff --git a/trennfix/sw/mm/include/mm/mm_decode.h b/trennfix/sw/mm/include/mm/mm_decode.h
new file mode 100644 (file)
index 0000000..5b5b7b2
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef __MM_DECODE_H
+#define __MM_DECODE_H
+
+/*
+ * Lookup trinary nibble
+ *
+ * This was implemented using a switch statement before.
+ * Changing the lookup to a table did only add two bytes
+ * of memory and saved ca. 50 bytes program memory.
+ */
+static const uint8_t __mm_nibble_table[16]={
+       [0x0] = 0,
+       [0xc] = 1,
+       [0x8] = 2,
+       [0x3] = 3,
+       [0xf] = 4,
+       [0xb] = 5,
+       [0x2] = 6,
+       [0xe] = 7,
+       [0xa] = 8
+};
+#define __mm_lookup_nibble(nibble) __mm_nibble_table[nibble & 0xf]
+
+static uint8_t __attribute__((unused)) mm_lookup_decoder(uint8_t mm_byte)
+{
+       uint8_t low;
+       uint8_t high;
+       uint8_t retval;
+
+       if (mm_byte == 0)
+               return 80;
+       low  = __mm_lookup_nibble(mm_byte >> 4);
+       high = __mm_lookup_nibble(mm_byte & 0xf);
+       if (!low)
+               return 0;
+
+       /*      retval = 9 * high + low; */
+       retval = high << 3;
+       retval += high;
+       retval += low;
+       return retval;
+}
+
+static uint8_t __attribute__((unused)) mm_lookup_key(uint8_t mm_command)
+{
+       uint8_t res;
+       /*
+        * Check for aabbccdd condition
+        *
+        *        a  a  b  b  c  c  d  d   mm_command
+        *   XOR  a  b  b  c  c  d  d  0   mm_command << 1
+        * Mask   1  0  1  0  1  0  1  0   0xaa
+        *
+        * Must be zero!
+        *
+        */
+
+       if ((mm_command ^ (mm_command << 1)) & 0xaa)
+               return 0;
+       /*
+        * Protocol differences:
+        * =====================
+        *
+        * I have an old "central control" 6022 and a "control unit" 6021
+        * for measurements and test. It is assumed that the 6022 outputs
+        * old MM1 format while the 6021 definitively outputs MM2 telegrams.
+        *
+        * In MM1, switch commands are different from MM2 with respect what
+        * happens if you release a button.
+        *
+        * When you press a button, both protocols send
+        *
+        * <aaaaaaaa><00><aabbcc11>
+        *
+        * where a = 1, b = 2, c = 4 and the keys are numerated from 0 to 7
+        * in the order 1 red, 1 green, 2 red, 2 green and so on.
+        *
+        * The last two bits correspond to "on" state of the button/coil.
+        *
+        * When a key is released under MM1 protocol, the sequence sent is
+        * analogue to the button down sequence:
+        *
+        * <aaaaaaaa><00><aabbcc00> where abc again represents the button's
+        * address and the last bits now signal "off".
+        *
+        * MM2 handles this differently:
+        * Whenever any key from the addressed decoder is released, the sequence
+        * <aaaaaaaa>00<00000000> is sent - not only for key 0, but for all
+        * keys!
+        *
+        * While MM1 presents the theoretical possibility to press several keys
+        * independently and simultaneously (which my keyboard does NOT
+        * support), MM2 supports only one key at a time (besides strange
+        * sequences like "one down, another down, all up"...
+        *
+        * A decoder that strictly adheres to the MM1 standard would not work
+        * properly with MM2 control units. As far as I know all K83/K84
+        * decoders always worked with MM2 control units. That means that
+        * they reduce the commands to the possibilities of MM2 from the
+        * beginning.
+        *
+        * Possible use cases for the old protocol button release commands:
+        *   - Determine if the protocol is MM1 or MM2
+        *   - Implement hidden evil features into the controller which can
+        *     only be summoned by old MM1 gear or selfmade control telegram
+        *     generators.
+        *
+        * What this code now actually does:
+        * =================================
+        *
+        * When key pressed (aabbcc11), it will send out the key number in the
+        * range 1-8 and 0 if it gets any key up command and therefore ignore
+        * the key number if it is transmitted with the key up command.
+        *
+        */
+       if (!(mm_command & 0x01))
+               res = 0;
+       else
+               res = (mm_command & 0x80) * 1 + (mm_command & 0x20) * 0x02
+                       + (mm_command & 0x08) * 0x04 + 1;
+       return res;
+}
+
+#endif