--- /dev/null
+#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