trennfix/sw: Added smokefix, further modularized the mm decoder
[eisenbahn.git] / trennfix / sw / mm / include / mm / mm_decode.h
1 #ifndef __MM_DECODE_H
2 #define __MM_DECODE_H
3
4 /*
5 * Lookup trinary nibble
6 *
7 * This was implemented using a switch statement before.
8 * Changing the lookup to a table did only add two bytes
9 * of memory and saved ca. 50 bytes program memory.
10 */
11 static const uint8_t __mm_nibble_table[16]={
12 [0x0] = 0,
13 [0xc] = 1,
14 [0x8] = 2,
15 [0x3] = 3,
16 [0xf] = 4,
17 [0xb] = 5,
18 [0x2] = 6,
19 [0xe] = 7,
20 [0xa] = 8
21 };
22 #define __mm_lookup_nibble(nibble) __mm_nibble_table[nibble & 0xf]
23
24 static uint8_t __attribute__((unused)) mm_lookup_decoder(uint8_t mm_byte)
25 {
26 uint8_t low;
27 uint8_t high;
28 uint8_t retval;
29
30 if (mm_byte == 0)
31 return 80;
32 low = __mm_lookup_nibble(mm_byte >> 4);
33 high = __mm_lookup_nibble(mm_byte & 0xf);
34 if (!low)
35 return 0;
36
37 /* retval = 9 * high + low; */
38 retval = high << 3;
39 retval += high;
40 retval += low;
41 return retval;
42 }
43
44 static uint8_t __attribute__((unused)) mm_lookup_key(uint8_t mm_command)
45 {
46 uint8_t res;
47 /*
48 * Check for aabbccdd condition
49 *
50 * a a b b c c d d mm_command
51 * XOR a b b c c d d 0 mm_command << 1
52 * Mask 1 0 1 0 1 0 1 0 0xaa
53 *
54 * Must be zero!
55 *
56 */
57
58 if ((mm_command ^ (mm_command << 1)) & 0xaa)
59 return 0;
60 /*
61 * Protocol differences:
62 * =====================
63 *
64 * I have an old "central control" 6022 and a "control unit" 6021
65 * for measurements and test. It is assumed that the 6022 outputs
66 * old MM1 format while the 6021 definitively outputs MM2 telegrams.
67 *
68 * In MM1, switch commands are different from MM2 with respect what
69 * happens if you release a button.
70 *
71 * When you press a button, both protocols send
72 *
73 * <aaaaaaaa><00><aabbcc11>
74 *
75 * where a = 1, b = 2, c = 4 and the keys are numerated from 0 to 7
76 * in the order 1 red, 1 green, 2 red, 2 green and so on.
77 *
78 * The last two bits correspond to "on" state of the button/coil.
79 *
80 * When a key is released under MM1 protocol, the sequence sent is
81 * analogue to the button down sequence:
82 *
83 * <aaaaaaaa><00><aabbcc00> where abc again represents the button's
84 * address and the last bits now signal "off".
85 *
86 * MM2 handles this differently:
87 * Whenever any key from the addressed decoder is released, the sequence
88 * <aaaaaaaa>00<00000000> is sent - not only for key 0, but for all
89 * keys!
90 *
91 * While MM1 presents the theoretical possibility to press several keys
92 * independently and simultaneously (which my keyboard does NOT
93 * support), MM2 supports only one key at a time (besides strange
94 * sequences like "one down, another down, all up"...
95 *
96 * A decoder that strictly adheres to the MM1 standard would not work
97 * properly with MM2 control units. As far as I know all K83/K84
98 * decoders always worked with MM2 control units. That means that
99 * they reduce the commands to the possibilities of MM2 from the
100 * beginning.
101 *
102 * Possible use cases for the old protocol button release commands:
103 * - Determine if the protocol is MM1 or MM2
104 * - Implement hidden evil features into the controller which can
105 * only be summoned by old MM1 gear or selfmade control telegram
106 * generators.
107 *
108 * What this code now actually does:
109 * =================================
110 *
111 * When key pressed (aabbcc11), it will send out the key number in the
112 * range 1-8 and 0 if it gets any key up command and therefore ignore
113 * the key number if it is transmitted with the key up command.
114 *
115 */
116 if (!(mm_command & 0x01))
117 res = 0;
118 else
119 res = (mm_command & 0x80) * 1 + (mm_command & 0x20) * 0x02
120 + (mm_command & 0x08) * 0x04 + 1;
121 return res;
122 }
123
124 #endif