aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorJason Janse van Rensburg <l33tjas.0n@gmail.com>2016-08-30 14:54:00 +0200
committerJason Janse van Rensburg <l33tjas.0n@gmail.com>2016-08-30 14:54:00 +0200
commitfc2ca62a3b9552175eb7c27cc11f3a5af6cfae50 (patch)
tree59b2f2406f472a9fd2af4946420d1a1c880929c0 /quantum
parenta41a7a9100b9f4c6bfdf49b39b05e626ffd95397 (diff)
parent8e00c464e6f488d86e0768a77a2ad5ee238dba6d (diff)
downloadqmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.tar.gz
qmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.zip
Merge branch 'master'
Conflicts: keyboards/planck/keymaps/bone2planck/keymap.c
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio/song_list.h8
-rw-r--r--quantum/config_common.h9
-rw-r--r--quantum/dynamic_macro.h226
-rw-r--r--quantum/keymap.h22
-rw-r--r--quantum/keymap_extras/keymap_russian.h77
-rw-r--r--quantum/keymap_extras/keymap_unicode_cyrillic.h163
-rw-r--r--quantum/process_keycode/process_tap_dance.c115
-rw-r--r--quantum/process_keycode/process_tap_dance.h8
-rw-r--r--quantum/process_keycode/process_unicode.c209
-rw-r--r--quantum/process_keycode/process_unicode.h40
-rw-r--r--quantum/quantum.c62
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/rgblight.c735
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c3
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h3
-rw-r--r--quantum/serial_link/protocol/transport.c4
-rw-r--r--quantum/serial_link/protocol/transport.h7
-rw-r--r--quantum/serial_link/tests/byte_stuffer_tests.cpp (renamed from quantum/serial_link/tests/byte_stuffer_tests.c)313
-rw-r--r--quantum/serial_link/tests/frame_router_tests.c231
-rw-r--r--quantum/serial_link/tests/frame_router_tests.cpp229
-rw-r--r--quantum/serial_link/tests/frame_validator_tests.cpp (renamed from quantum/serial_link/tests/frame_validator_tests.c)90
-rw-r--r--quantum/serial_link/tests/rules.mk22
-rw-r--r--quantum/serial_link/tests/testlist.mk6
-rw-r--r--quantum/serial_link/tests/transport_tests.c168
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp188
-rw-r--r--quantum/serial_link/tests/triple_buffered_object_tests.cpp (renamed from quantum/serial_link/tests/triple_buffered_object_tests.c)52
-rw-r--r--quantum/template/Makefile76
-rw-r--r--quantum/template/readme.md10
-rw-r--r--quantum/template/rules.mk67
29 files changed, 1972 insertions, 1175 deletions
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
index fc6fcdeef..8022ca672 100644
--- a/quantum/audio/song_list.h
+++ b/quantum/audio/song_list.h
@@ -28,6 +28,14 @@
28 Q__NOTE(_E4), Q__NOTE(_C4), \ 28 Q__NOTE(_E4), Q__NOTE(_C4), \
29 Q__NOTE(_E4), 29 Q__NOTE(_E4),
30 30
31/* Requires: PLAY_NOTE_ARRAY(..., ..., STACCATO); */
32#define IN_LIKE_FLINT \
33 E__NOTE(_AS4), E__NOTE(_AS4), QD_NOTE(_B4), \
34 E__NOTE(_AS4), E__NOTE(_B4), QD_NOTE(_CS4), \
35 E__NOTE(_B4), E__NOTE(_CS4), QD_NOTE(_DS4), \
36 E__NOTE(_CS4), E__NOTE(_B4), QD_NOTE(_AS4), \
37 E__NOTE(_AS4), E__NOTE(_AS4), QD_NOTE(_B4),
38
31#define GOODBYE_SOUND \ 39#define GOODBYE_SOUND \
32 E__NOTE(_E7), \ 40 E__NOTE(_E7), \
33 E__NOTE(_A6), \ 41 E__NOTE(_A6), \
diff --git a/quantum/config_common.h b/quantum/config_common.h
index 09a4fe701..8ed5f4a10 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -45,6 +45,15 @@
45#define F5 0xF5 45#define F5 0xF5
46#define F6 0xF6 46#define F6 0xF6
47#define F7 0xF7 47#define F7 0xF7
48#define A0 0x00
49#define A1 0x01
50#define A2 0x02
51#define A3 0x03
52#define A4 0x04
53#define A5 0x05
54#define A6 0x06
55#define A7 0x07
56
48 57
49/* USART configuration */ 58/* USART configuration */
50#ifdef BLUETOOTH_ENABLE 59#ifdef BLUETOOTH_ENABLE
diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h
new file mode 100644
index 000000000..a3ad61bc7
--- /dev/null
+++ b/quantum/dynamic_macro.h
@@ -0,0 +1,226 @@
1/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */
2#ifndef DYNAMIC_MACROS_H
3#define DYNAMIC_MACROS_H
4
5#include "action_layer.h"
6
7#ifndef DYNAMIC_MACRO_SIZE
8/* May be overridden with a custom value. Be aware that the effective
9 * macro length is half of this value: each keypress is recorded twice
10 * because of the down-event and up-event. This is not a bug, it's the
11 * intended behavior. */
12#define DYNAMIC_MACRO_SIZE 256
13#endif
14
15/* DYNAMIC_MACRO_RANGE must be set as the last element of user's
16 * "planck_keycodes" enum prior to including this header. This allows
17 * us to 'extend' it.
18 */
19enum dynamic_macro_keycodes {
20 DYN_REC_START1 = DYNAMIC_MACRO_RANGE,
21 DYN_REC_START2,
22 DYN_MACRO_PLAY1,
23 DYN_MACRO_PLAY2,
24};
25
26/* Blink the LEDs to notify the user about some event. */
27void dynamic_macro_led_blink(void)
28{
29 backlight_toggle();
30 _delay_ms(100);
31 backlight_toggle();
32}
33
34/**
35 * Start recording of the dynamic macro.
36 *
37 * @param[out] macro_pointer The new macro buffer iterator.
38 * @param[in] macro_buffer The macro buffer used to initialize macro_pointer.
39 */
40void dynamic_macro_record_start(
41 keyrecord_t **macro_pointer, keyrecord_t *macro_buffer)
42{
43 dynamic_macro_led_blink();
44
45 clear_keyboard();
46 layer_clear();
47 *macro_pointer = macro_buffer;
48}
49
50/**
51 * Play the dynamic macro.
52 *
53 * @param macro_buffer[in] The beginning of the macro buffer being played.
54 * @param macro_end[in] The element after the last macro buffer element.
55 * @param direction[in] Either +1 or -1, which way to iterate the buffer.
56 */
57void dynamic_macro_play(
58 keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction)
59{
60 uint32_t saved_layer_state = layer_state;
61
62 clear_keyboard();
63 layer_clear();
64
65 while (macro_buffer != macro_end) {
66 process_record(macro_buffer);
67 macro_buffer += direction;
68 }
69
70 clear_keyboard();
71
72 layer_state = saved_layer_state;
73}
74
75/**
76 * Record a single key in a dynamic macro.
77 *
78 * @param macro_pointer[in,out] The current buffer position.
79 * @param macro_end2[in] The end of the other macro which shouldn't be overwritten.
80 * @param direction[in] Either +1 or -1, which way to iterate the buffer.
81 * @param record[in] The current keypress.
82 */
83void dynamic_macro_record_key(
84 keyrecord_t **macro_pointer,
85 keyrecord_t *macro_end2,
86 int8_t direction,
87 keyrecord_t *record)
88{
89 if (*macro_pointer + direction != macro_end2) {
90 **macro_pointer = *record;
91 *macro_pointer += direction;
92 } else {
93 /* Notify about the end of buffer. The blinks are paired
94 * because they should happen on both down and up events. */
95 backlight_toggle();
96 }
97}
98
99/**
100 * End recording of the dynamic macro. Essentially just update the
101 * pointer to the end of the macro.
102 */
103void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end)
104{
105 dynamic_macro_led_blink();
106
107 *macro_end = macro_pointer;
108}
109
110/* Handle the key events related to the dynamic macros. Should be
111 * called from process_record_user() like this:
112 *
113 * bool process_record_user(uint16_t keycode, keyrecord_t *record) {
114 * if (!process_record_dynamic_macro(keycode, record)) {
115 * return false;
116 * }
117 * <...THE REST OF THE FUNCTION...>
118 * }
119 */
120bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
121{
122 /* Both macros use the same buffer but read/write on different
123 * ends of it.
124 *
125 * Macro1 is written left-to-right starting from the beginning of
126 * the buffer.
127 *
128 * Macro2 is written right-to-left starting from the end of the
129 * buffer.
130 *
131 * &macro_buffer macro_end
132 * v v
133 * +------------------------------------------------------------+
134 * |>>>>>> MACRO1 >>>>>>| |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<|
135 * +------------------------------------------------------------+
136 * ^ ^
137 * r_macro_end r_macro_buffer
138 *
139 * During the recording when one macro encounters the end of the
140 * other macro, the recording is stopped. Apart from this, there
141 * are no arbitrary limits for the macros' length in relation to
142 * each other: for example one can either have two medium sized
143 * macros or one long macro and one short macro. Or even one empty
144 * and one using the whole buffer.
145 */
146 static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE];
147
148 /* Pointer to the first buffer element after the first macro.
149 * Initially points to the very beginning of the buffer since the
150 * macro is empty. */
151 static keyrecord_t *macro_end = macro_buffer;
152
153 /* The other end of the macro buffer. Serves as the beginning of
154 * the second macro. */
155 static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1;
156
157 /* Like macro_end but for the second macro. */
158 static keyrecord_t *r_macro_end = r_macro_buffer;
159
160 /* A persistent pointer to the current macro position (iterator)
161 * used during the recording. */
162 static keyrecord_t *macro_pointer = NULL;
163
164 /* 0 - no macro is being recorded right now
165 * 1,2 - either macro 1 or 2 is being recorded */
166 static uint8_t macro_id = 0;
167
168 if (macro_id == 0) {
169 /* No macro recording in progress. */
170 if (!record->event.pressed) {
171 switch (keycode) {
172 case DYN_REC_START1:
173 dynamic_macro_record_start(&macro_pointer, macro_buffer);
174 macro_id = 1;
175 return false;
176 case DYN_REC_START2:
177 dynamic_macro_record_start(&macro_pointer, r_macro_buffer);
178 macro_id = 2;
179 return false;
180 case DYN_MACRO_PLAY1:
181 dynamic_macro_play(macro_buffer, macro_end, +1);
182 return false;
183 case DYN_MACRO_PLAY2:
184 dynamic_macro_play(r_macro_buffer, r_macro_end, -1);
185 return false;
186 }
187 }
188 } else {
189 /* A macro is being recorded right now. */
190 switch (keycode) {
191 case MO(_DYN):
192 /* Use the layer key used to access the macro recording as
193 * a stop button. */
194 if (record->event.pressed) { /* Ignore the initial release
195 * just after the recoding
196 * starts. */
197 switch (macro_id) {
198 case 1:
199 dynamic_macro_record_end(macro_pointer, &macro_end);
200 break;
201 case 2:
202 dynamic_macro_record_end(macro_pointer, &r_macro_end);
203 break;
204 }
205 macro_id = 0;
206 }
207 return false;
208 default:
209 /* Store the key in the macro buffer and process it normally. */
210 switch (macro_id) {
211 case 1:
212 dynamic_macro_record_key(&macro_pointer, r_macro_end, +1, record);
213 break;
214 case 2:
215 dynamic_macro_record_key(&macro_pointer, macro_end, -1, record);
216 break;
217 }
218 return true;
219 break;
220 }
221 }
222
223 return true;
224}
225
226#endif
diff --git a/quantum/keymap.h b/quantum/keymap.h
index a15865183..f2d94d75c 100644
--- a/quantum/keymap.h
+++ b/quantum/keymap.h
@@ -156,16 +156,16 @@ enum quantum_keycodes {
156 BL_INC, 156 BL_INC,
157 BL_TOGG, 157 BL_TOGG,
158 BL_STEP, 158 BL_STEP,
159 159
160 // RGB functionality 160 // RGB functionality
161 RGB_TOG, 161 RGB_TOG,
162 RGB_MOD, 162 RGB_MOD,
163 RGB_HUI, 163 RGB_HUI,
164 RGB_HUD, 164 RGB_HUD,
165 RGB_SAI, 165 RGB_SAI,
166 RGB_SAD, 166 RGB_SAD,
167 RGB_VAI, 167 RGB_VAI,
168 RGB_VAD, 168 RGB_VAD,
169 169
170 // Left shift, open paren 170 // Left shift, open paren
171 KC_LSPO, 171 KC_LSPO,
@@ -309,7 +309,7 @@ enum quantum_keycodes {
309#define OSL(layer) (layer | QK_ONE_SHOT_LAYER) 309#define OSL(layer) (layer | QK_ONE_SHOT_LAYER)
310 310
311// One-shot mod 311// One-shot mod
312#define OSM(layer) (layer | QK_ONE_SHOT_MOD) 312#define OSM(mod) (mod | QK_ONE_SHOT_MOD)
313 313
314// M-od, T-ap - 256 keycode max 314// M-od, T-ap - 256 keycode max
315#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8)) 315#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8))
diff --git a/quantum/keymap_extras/keymap_russian.h b/quantum/keymap_extras/keymap_russian.h
new file mode 100644
index 000000000..237e9abde
--- /dev/null
+++ b/quantum/keymap_extras/keymap_russian.h
@@ -0,0 +1,77 @@
1#ifndef KEYMAP_RUSSIAN_H
2#define KEYMAP_RUSSIAN_H
3
4#include "keymap.h"
5
6// Normal Chracters // reg SHIFT
7#define RU_A KC_F // а and А
8#define RU_BE KC_COMM // б and Б
9#define RU_VE KC_D // в and В
10#define RU_GHE KC_U // г and Г
11#define RU_DE KC_L // д and Д
12#define RU_IE KC_T // е and Е
13#define RU_IO KC_GRV // ё and Ё
14#define RU_ZHE KC_SCLN // ж and Ж
15#define RU_ZE KC_P // з and З
16#define RU_I KC_B // и and И
17#define RU_SRT_I KC_Q // й and Й
18#define RU_KA KC_R // к and К
19#define RU_EL KC_K // л and Л
20#define RU_EM KC_V // м and М
21#define RU_EN KC_Y // н and Н
22#define RU_O KC_J // о and О
23#define RU_PE KC_G // п and П
24#define RU_ER KC_H // р and Р
25#define RU_ES KC_C // с and С
26#define RU_TE KC_N // т and Т
27#define RU_U KC_E // у and У
28#define RU_EF KC_A // ф and Ф
29#define RU_HA KC_LBRC // х and Х
30#define RU_TSE KC_W // ц and Ц
31#define RU_CHE KC_X // ч and Ч
32#define RU_SHA KC_I // ш and Ш
33#define RU_SHCHA KC_O // щ and Щ
34#define RU_HSIGN KC_RBRC // ъ and Ъ
35#define RU_YERU KC_S // ы and Ы
36#define RU_SSIGN KC_M // ь and Ь
37#define RU_E KC_QUOT // э and Э
38#define RU_YU KC_DOT // ю and Ю
39#define RU_YA KC_Z // я and Я
40
41#define RU_1 KC_1 // 1 and !
42#define RU_2 KC_2 // 2 and "
43#define RU_3 KC_3 // 3 and №
44#define RU_4 KC_4 // 4 and ;
45#define RU_5 KC_5 // 5 and %
46#define RU_6 KC_6 // 6 and :
47#define RU_7 KC_7 // 7 and ?
48#define RU_8 KC_8 // 8 and *
49#define RU_9 KC_9 // 9 and (
50#define RU_0 KC_0 // 0 and )
51
52#define RU_MINS KC_MINS // - and _
53#define RU_EQL KC_EQL // = and +
54#define RU_BSLS KC_BSLS // \ and /
55#define RU_DOT KC_SLSH // . and ,
56
57// Shifted Chracters
58#define RU_EXLM LSFT(RU_1) // !
59#define RU_DQUT LSFT(RU_2) // "
60#define RU_NMRO LSFT(RU_3) // №
61#define RU_SCLN LSFT(RU_4) // ;
62#define RU_PERC LSFT(RU_5) // %
63#define RU_COLN LSFT(RU_6) // :
64#define RU_QUES LSFT(RU_7) // ?
65#define RU_ASTR LSFT(RU_8) // *
66#define RU_LPRN LSFT(RU_9) // (
67#define RU_RPRN LSFT(RU_0) // )
68
69#define RU_UNDR LSFT(RU_MINS) // _
70#define RU_PLUS LSFT(RU_EQL) // +
71#define RU_SLSH LSFT(RU_BSLS) // /
72#define RU_COMM LSFT(RU_DOT) // ,
73
74// Alt Gr-ed characters
75#define RU_RUBL RALT(RU_8) // ₽
76
77#endif
diff --git a/quantum/keymap_extras/keymap_unicode_cyrillic.h b/quantum/keymap_extras/keymap_unicode_cyrillic.h
new file mode 100644
index 000000000..a40626d91
--- /dev/null
+++ b/quantum/keymap_extras/keymap_unicode_cyrillic.h
@@ -0,0 +1,163 @@
1#ifndef KEYMAP_CYRILLIC_H
2#define KEYMAP_CYRILLIC_H
3
4#include "keymap.h"
5
6/*
7 * This is based off of
8 * https://en.wikipedia.org/wiki/Cyrillic_script
9 *
10 * Unicode is iffy, a software implementation is preferred
11 */
12
13// Capital Char russian/ukrainian/bulgarian
14#define CY_A UC(0x0410) // А rus ukr bul
15#define CY_BE UC(0x0411) // Б rus ukr bul
16#define CY_VE UC(0x0412) // В rus ukr bul
17#define CY_GHE UC(0x0413) // Г rus ukr bul
18#define CY_GHEUP UC(0x0490) // Ґ ukr
19#define CY_DE UC(0x0414) // Д rus ukr bul
20#define CY_DJE UC(0x0402) // Ђ
21#define CY_GJE UC(0x0403) // Ѓ
22#define CY_IE UC(0x0415) // Е rus ukr bul
23#define CY_IO UC(0x0401) // Ё rus
24#define CY_UIE UC(0x0404) // Є ukr
25#define CY_ZHE UC(0x0416) // Ж rus ukr bul
26#define CY_ZE UC(0x0417) // З rus ukr bul
27#define CY_DZE UC(0x0405) // Ѕ
28#define CY_I UC(0x0418) // И rus ukr bul
29#define CY_B_U_I UC(0x0406) // І ukr
30#define CY_YI UC(0x0407) // Ї ukr
31#define CY_SRT_I UC(0x0419) // Й rus ukr bul
32#define CY_JE UC(0x0408) // Ј
33#define CY_KA UC(0x041a) // К rus ukr bul
34#define CY_EL UC(0x041b) // Л rus ukr bul
35#define CY_LJE UC(0x0409) // Љ
36#define CY_EM UC(0x041c) // М rus ukr bul
37#define CY_EN UC(0x041d) // Н rus ukr bul
38#define CY_NJE UC(0x040a) // Њ
39#define CY_O UC(0x041e) // О rus ukr bul
40#define CY_PE UC(0x041f) // П rus ukr bul
41#define CY_ER UC(0x0420) // Р rus ukr bul
42#define CY_ES UC(0x0421) // С rus ukr bul
43#define CY_TE UC(0x0422) // Т rus ukr bul
44#define CY_TSHE UC(0x040b) // Ћ
45#define CY_KJE UC(0x040c) // Ќ
46#define CY_U UC(0x0423) // У rus ukr bul
47#define CY_SRT_U UC(0x040e) // Ў
48#define CY_EF UC(0x0424) // Ф rus ukr bul
49#define CY_HA UC(0x0425) // Х rus bul
50#define CY_TSE UC(0x0426) // Ц rus ukr bul
51#define CY_CHE UC(0x0427) // Ч rus ukr bul
52#define CY_DZHE UC(0x040f) // Џ
53#define CY_SHA UC(0x0428) // Ш rus ukr bul
54#define CY_SHCHA UC(0x0429) // Щ rus ukr bul
55#define CY_HSIGN UC(0x042a) // Ъ rus bul
56#define CY_YERU UC(0x042b) // Ы rus
57#define CY_SSIGN UC(0x042c) // Ь rus ukr bul
58#define CY_E UC(0x042d) // Э rus
59#define CY_YU UC(0x042e) // Ю rus ukr bul
60#define CY_YA UC(0x042f) // Я rus ukr bul
61// Important Cyrillic non-Slavic letters
62#define CY_PALOCHKA UC(0x04c0) // Ӏ
63#define CY_SCHWA UC(0x04d8) // Ә
64#define CY_GHE_S UC(0x0492) // Ғ
65#define CY_ZE_D UC(0x0498) // Ҙ
66#define CY_ES_D UC(0x04aa) // Ҫ
67#define CY_BR_KA UC(0x04a0) // Ҡ
68#define CY_ZHE_D UC(0x0496) // Җ
69#define CY_KA_D UC(0x049a) // Қ
70#define CY_EN_D UC(0x04a2) // Ң
71#define CY_ENGHE UC(0x04a4) // Ҥ
72#define CY_BRD_O UC(0x04e8) // Ө
73#define CY_STR_U UC(0x04ae) // Ү
74#define CY_S_U_S UC(0x04b0) // Ұ
75#define CY_SHHA UC(0x04ba) // Һ
76#define CY_HA_D UC(0x04b2) // Ҳ
77
78
79// Small
80#define CY_a UC(0x0430) // a rus ukr bul
81#define CY_be UC(0x0431) // б rus ukr bul
82#define CY_ve UC(0x0432) // в rus ukr bul
83#define CY_ghe UC(0x0433) // г rus ukr bul
84#define CY_gheup UC(0x0491) // ґ ukr
85#define CY_de UC(0x0434) // д rus ukr bul
86#define CY_dje UC(0x0452) // ђ
87#define CY_gje UC(0x0453) // ѓ
88#define CY_ie UC(0x0435) // е rus ukr bul
89#define CY_io UC(0x0451) // ё rus
90#define CY_uie UC(0x0454) // є ukr
91#define CY_zhe UC(0x0436) // ж rus ukr bul
92#define CY_ze UC(0x0437) // з rus ukr bul
93#define CY_dze UC(0x0455) // ѕ
94#define CY_i UC(0x0438) // и rus ukr bul
95#define CY_b_u_i UC(0x0456) // і ukr
96#define CY_yi UC(0x0457) // ї ukr
97#define CY_srt_i UC(0x0439) // й rus ukr bul
98#define CY_je UC(0x0458) // ј
99#define CY_ka UC(0x043a) // к rus ukr bul
100#define CY_el UC(0x043b) // л rus ukr bul
101#define CY_lje UC(0x0459) // љ
102#define CY_em UC(0x043c) // м rus ukr bul
103#define CY_en UC(0x043d) // н rus ukr bul
104#define CY_nje UC(0x045a) // њ
105#define CY_o UC(0x043e) // о rus ukr bul
106#define CY_pe UC(0x043f) // п rus ukr bul
107#define CY_er UC(0x0440) // р rus ukr bul
108#define CY_es UC(0x0441) // с rus ukr bul
109#define CY_te UC(0x0442) // т rus ukr bul
110#define CY_tshe UC(0x045b) // ћ
111#define CY_kje UC(0x045c) // ќ
112#define CY_u UC(0x0443) // у rus ukr bul
113#define CY_srt_u UC(0x045e) // ў
114#define CY_ef UC(0x0444) // ф rus ukr bul
115#define CY_ha UC(0x0445) // х rus ukr bul
116#define CY_tse UC(0x0446) // ц rus ukr bul
117#define CY_che UC(0x0447) // ч rus ukr bul
118#define CY_dzhe UC(0x045f) // џ
119#define CY_sha UC(0x0448) // ш rus ukr bul
120#define CY_shcha UC(0x0449) // щ rus ukr bul
121#define CY_hsign UC(0x044a) // ъ rus bul
122#define CY_yeru UC(0x044b) // ы rus
123#define CY_ssign UC(0x044c) // ь rus ukr bul
124#define CY_e UC(0x044d) // э rus
125#define CY_yu UC(0x044e) // ю rus ukr bul
126#define CY_ya UC(0x044f) // я rus ukr bul
127// Important Cyrillic non-Slavic letters
128#define CY_palochka UC(0x04cf) // ӏ
129#define CY_schwa UC(0x04d9) // ә
130#define CY_ghe_s UC(0x0493) // ғ
131#define CY_ze_d UC(0x0499) // ҙ
132#define CY_es_d UC(0x04ab) // ҫ
133#define CY_br_ka UC(0x04a1) // ҡ
134#define CY_zhe_d UC(0x0497) // җ
135#define CY_ka_d UC(0x049b) // қ
136#define CY_en_d UC(0x04a3) // ң
137#define CY_enghe UC(0x04a5) // ҥ
138#define CY_brd_o UC(0x04e9) // ө
139#define CY_str_u UC(0x04af) // ү
140#define CY_s_u_s UC(0x04b1) // ұ
141#define CY_shha UC(0x04bb) // һ
142#define CY_ha_d UC(0x04b3) // ҳ
143
144
145// Extra
146#define CY_slr_ve UC(0x1c80) // ᲀ CYRILLIC SMALL LETTER ROUNDED VE
147#define CY_ll_de UC(0x1c81) // ᲁ CYRILLIC SMALL LETTER LONG-LEGGED DE
148#define CY_ZEMLYA UC(0xa640) // Ꙁ CYRILLIC CAPITAL LETTER ZEMLYA
149#define CY_zemlya UC(0xa641) // ꙁ CYRILLIC SMALL LETTER ZEMLYA
150#define CY_RV_DZE UC(0xa644) // Ꙅ CYRILLIC CAPITAL LETTER REVERSED DZE
151#define CY_rv_DZE UC(0xa645) // ꙅ CYRILLIC SMALL LETTER REVERSED DZE
152#define CY_slw_es UC(0x1c83) // ᲃ CYRILLIC SMALL LETTER WIDE ES
153#define CY_st_te UC(0x1c84) // ᲄ CYRILLIC SMALL LETTER TALL TE
154#define CY_3l_te UC(0x1c85) // ᲅ CYRILLIC SMALL LETTER THREE-LEGGED TE
155#define CY_thsign UC(0x1c86) // ᲆ CYRILLIC SMALL LETTER TALL HARD SIGN
156#define CY_YERUBY UC(0xa650) // Ꙑ CYRILLIC CAPITAL LETTER YERU WITH BACK YER
157#define CY_yeruby UC(0xa651) // ꙑ CYRILLIC SMALL LETTER YERU WITH BACK YER
158#define CY_RUBL UC(0x20bd) // ₽
159#define CY_NMRO UC(0x2116) // №
160
161// The letters Zje and Sje are made for other letters and accent marks
162
163#endif
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index d240dc2e6..07de3ecb8 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -1,14 +1,16 @@
1#include "quantum.h" 1#include "quantum.h"
2#include "action_tapping.h"
2 3
3static qk_tap_dance_state_t qk_tap_dance_state; 4static uint16_t last_td;
5static int8_t highest_td = -1;
4 6
5void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { 7void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
6 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 8 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
7 9
8 if (state->count == 1) { 10 if (state->count == 1) {
9 register_code (pair->kc1); 11 register_code16 (pair->kc1);
10 } else if (state->count == 2) { 12 } else if (state->count == 2) {
11 register_code (pair->kc2); 13 register_code16 (pair->kc2);
12 } 14 }
13} 15}
14 16
@@ -16,102 +18,117 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
16 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 18 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
17 19
18 if (state->count == 1) { 20 if (state->count == 1) {
19 unregister_code (pair->kc1); 21 unregister_code16 (pair->kc1);
20 } else if (state->count == 2) { 22 } else if (state->count == 2) {
21 unregister_code (pair->kc2); 23 unregister_code16 (pair->kc2);
22 } 24 }
23} 25}
24 26
25static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, 27static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
26 void *user_data, 28 void *user_data,
27 qk_tap_dance_user_fn_t fn) 29 qk_tap_dance_user_fn_t fn)
28{ 30{
29 if (fn) { 31 if (fn) {
30 fn(state, user_data); 32 fn(state, user_data);
31 } 33 }
32} 34}
33 35
34static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action) 36static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
35{ 37{
36 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap); 38 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
37} 39}
38 40
39static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action) 41static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
40{ 42{
41 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished); 43 if (action->state.finished)
44 return;
45 action->state.finished = true;
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
42} 47}
43 48
44static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action) 49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
45{ 50{
46 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset); 51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
47} 52}
48 53
49bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
50 bool r = true;
51 uint16_t idx = keycode - QK_TAP_DANCE; 55 uint16_t idx = keycode - QK_TAP_DANCE;
52 qk_tap_dance_action_t action; 56 qk_tap_dance_action_t *action;
57
58 if (last_td && last_td != keycode) {
59 (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
60 }
53 61
54 switch(keycode) { 62 switch(keycode) {
55 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: 63 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
56 action = tap_dance_actions[idx]; 64 if ((int16_t)idx > highest_td)
65 highest_td = idx;
66 action = &tap_dance_actions[idx];
57 67
58 process_tap_dance_action_on_each_tap (action); 68 action->state.keycode = keycode;
59 if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) { 69 action->state.pressed = record->event.pressed;
60 process_tap_dance_action_on_dance_finished (action);
61 } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
62 reset_tap_dance (&qk_tap_dance_state);
63 } else {
64 r = false;
65 }
66
67 qk_tap_dance_state.active = true;
68 qk_tap_dance_state.pressed = record->event.pressed;
69 if (record->event.pressed) { 70 if (record->event.pressed) {
70 qk_tap_dance_state.keycode = keycode; 71 action->state.count++;
71 qk_tap_dance_state.timer = timer_read (); 72 action->state.timer = timer_read();
72 qk_tap_dance_state.count++; 73
74 if (last_td && last_td != keycode) {
75 qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
76 paction->state.interrupted = true;
77 process_tap_dance_action_on_dance_finished (paction);
78 reset_tap_dance (&paction->state);
79 }
73 } 80 }
81 last_td = keycode;
82
74 break; 83 break;
75 84
76 default: 85 default:
77 if (qk_tap_dance_state.keycode) { 86 if (!record->event.pressed)
78 // if we are here, the tap dance was interrupted by a different key 87 return true;
79 idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
80 action = tap_dance_actions[idx];
81 88
82 process_tap_dance_action_on_each_tap (action); 89 if (highest_td == -1)
90 return true;
91
92 for (int i = 0; i <= highest_td; i++) {
93 action = &tap_dance_actions[i];
94 if (action->state.count == 0)
95 continue;
96 action->state.interrupted = true;
83 process_tap_dance_action_on_dance_finished (action); 97 process_tap_dance_action_on_dance_finished (action);
84 reset_tap_dance (&qk_tap_dance_state); 98 reset_tap_dance (&action->state);
85 qk_tap_dance_state.active = false;
86 } 99 }
87 break; 100 break;
88 } 101 }
89 102
90 return r; 103 return true;
91} 104}
92 105
93void matrix_scan_tap_dance () { 106void matrix_scan_tap_dance () {
94 if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) { 107 if (highest_td == -1)
95 // if we are here, the tap dance was timed out 108 return;
96 uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; 109
97 qk_tap_dance_action_t action = tap_dance_actions[idx]; 110 for (int i = 0; i <= highest_td; i++) {
111 qk_tap_dance_action_t *action = &tap_dance_actions[i];
98 112
99 process_tap_dance_action_on_dance_finished (action); 113 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
100 reset_tap_dance (&qk_tap_dance_state); 114 process_tap_dance_action_on_dance_finished (action);
115 reset_tap_dance (&action->state);
116 }
101 } 117 }
102} 118}
103 119
104void reset_tap_dance (qk_tap_dance_state_t *state) { 120void reset_tap_dance (qk_tap_dance_state_t *state) {
105 uint16_t idx = state->keycode - QK_TAP_DANCE; 121 qk_tap_dance_action_t *action;
106 qk_tap_dance_action_t action;
107 122
108 if (state->pressed) 123 if (state->pressed)
109 return; 124 return;
110 125
111 action = tap_dance_actions[idx]; 126 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
127
112 process_tap_dance_action_on_reset (action); 128 process_tap_dance_action_on_reset (action);
113 129
114 state->keycode = 0;
115 state->count = 0; 130 state->count = 0;
116 state->active = false; 131 state->interrupted = false;
132 state->finished = false;
133 last_td = 0;
117} 134}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index e2c74efe9..d7b857bdc 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -11,8 +11,9 @@ typedef struct
11 uint8_t count; 11 uint8_t count;
12 uint16_t keycode; 12 uint16_t keycode;
13 uint16_t timer; 13 uint16_t timer;
14 bool active:1; 14 bool interrupted;
15 bool pressed:1; 15 bool pressed;
16 bool finished;
16} qk_tap_dance_state_t; 17} qk_tap_dance_state_t;
17 18
18#define TD(n) (QK_TAP_DANCE + n) 19#define TD(n) (QK_TAP_DANCE + n)
@@ -26,6 +27,7 @@ typedef struct
26 qk_tap_dance_user_fn_t on_dance_finished; 27 qk_tap_dance_user_fn_t on_dance_finished;
27 qk_tap_dance_user_fn_t on_reset; 28 qk_tap_dance_user_fn_t on_reset;
28 } fn; 29 } fn;
30 qk_tap_dance_state_t state;
29 void *user_data; 31 void *user_data;
30} qk_tap_dance_action_t; 32} qk_tap_dance_action_t;
31 33
@@ -48,7 +50,7 @@ typedef struct
48 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \ 50 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \
49 } 51 }
50 52
51extern const qk_tap_dance_action_t tap_dance_actions[]; 53extern qk_tap_dance_action_t tap_dance_actions[];
52 54
53/* To be used internally */ 55/* To be used internally */
54 56
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index ad5d7f86b..06c1694f2 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -13,45 +13,196 @@ uint16_t hex_to_keycode(uint8_t hex)
13 } 13 }
14} 14}
15 15
16void set_unicode_mode(uint8_t os_target) 16void set_unicode_input_mode(uint8_t os_target)
17{ 17{
18 input_mode = os_target; 18 input_mode = os_target;
19} 19}
20 20
21__attribute__((weak))
22void unicode_input_start (void) {
23 switch(input_mode) {
24 case UC_OSX:
25 register_code(KC_LALT);
26 break;
27 case UC_LNX:
28 register_code(KC_LCTL);
29 register_code(KC_LSFT);
30 register_code(KC_U);
31 unregister_code(KC_U);
32 unregister_code(KC_LSFT);
33 unregister_code(KC_LCTL);
34 break;
35 case UC_WIN:
36 register_code(KC_LALT);
37 register_code(KC_PPLS);
38 unregister_code(KC_PPLS);
39 break;
40 }
41 wait_ms(UNICODE_TYPE_DELAY);
42}
43
44__attribute__((weak))
45void unicode_input_finish (void) {
46 switch(input_mode) {
47 case UC_OSX:
48 case UC_WIN:
49 unregister_code(KC_LALT);
50 break;
51 case UC_LNX:
52 register_code(KC_SPC);
53 unregister_code(KC_SPC);
54 break;
55 }
56}
57
58void register_hex(uint16_t hex) {
59 for(int i = 3; i >= 0; i--) {
60 uint8_t digit = ((hex >> (i*4)) & 0xF);
61 register_code(hex_to_keycode(digit));
62 unregister_code(hex_to_keycode(digit));
63 }
64}
65
21bool process_unicode(uint16_t keycode, keyrecord_t *record) { 66bool process_unicode(uint16_t keycode, keyrecord_t *record) {
22 if (keycode > QK_UNICODE && record->event.pressed) { 67 if (keycode > QK_UNICODE && record->event.pressed) {
23 uint16_t unicode = keycode & 0x7FFF; 68 uint16_t unicode = keycode & 0x7FFF;
24 switch(input_mode) { 69 unicode_input_start();
25 case UC_OSX: 70 register_hex(unicode);
26 register_code(KC_LALT); 71 unicode_input_finish();
27 break; 72 }
28 case UC_LNX: 73 return true;
29 register_code(KC_LCTL); 74}
30 register_code(KC_LSFT); 75
31 register_code(KC_U); 76#ifdef UCIS_ENABLE
32 unregister_code(KC_U); 77qk_ucis_state_t qk_ucis_state;
33 break; 78
34 case UC_WIN: 79void qk_ucis_start(void) {
35 register_code(KC_LALT); 80 qk_ucis_state.count = 0;
36 register_code(KC_PPLS); 81 qk_ucis_state.in_progress = true;
37 unregister_code(KC_PPLS); 82
38 break; 83 qk_ucis_start_user();
84}
85
86__attribute__((weak))
87void qk_ucis_start_user(void) {
88 unicode_input_start();
89 register_hex(0x2328);
90 unicode_input_finish();
91}
92
93static bool is_uni_seq(char *seq) {
94 uint8_t i;
95
96 for (i = 0; seq[i]; i++) {
97 uint16_t code;
98 if (('1' <= seq[i]) && (seq[i] <= '0'))
99 code = seq[i] - '1' + KC_1;
100 else
101 code = seq[i] - 'a' + KC_A;
102
103 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
104 return false;
105 }
106
107 return (qk_ucis_state.codes[i] == KC_ENT ||
108 qk_ucis_state.codes[i] == KC_SPC);
109}
110
111__attribute__((weak))
112void qk_ucis_symbol_fallback (void) {
113 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
114 uint8_t code = qk_ucis_state.codes[i];
115 register_code(code);
116 unregister_code(code);
117 wait_ms(UNICODE_TYPE_DELAY);
118 }
119}
120
121void register_ucis(const char *hex) {
122 for(int i = 0; hex[i]; i++) {
123 uint8_t kc = 0;
124 char c = hex[i];
125
126 switch (c) {
127 case '0':
128 kc = KC_0;
129 break;
130 case '1' ... '9':
131 kc = c - '1' + KC_1;
132 break;
133 case 'a' ... 'f':
134 kc = c - 'a' + KC_A;
135 break;
136 case 'A' ... 'F':
137 kc = c - 'A' + KC_A;
138 break;
39 } 139 }
40 for(int i = 3; i >= 0; i--) { 140
41 uint8_t digit = ((unicode >> (i*4)) & 0xF); 141 if (kc) {
42 register_code(hex_to_keycode(digit)); 142 register_code (kc);
43 unregister_code(hex_to_keycode(digit)); 143 unregister_code (kc);
144 wait_ms (UNICODE_TYPE_DELAY);
44 } 145 }
45 switch(input_mode) { 146 }
46 case UC_OSX: 147}
47 case UC_WIN: 148
48 unregister_code(KC_LALT); 149bool process_ucis (uint16_t keycode, keyrecord_t *record) {
49 break; 150 uint8_t i;
50 case UC_LNX: 151
51 unregister_code(KC_LCTL); 152 if (!qk_ucis_state.in_progress)
52 unregister_code(KC_LSFT); 153 return true;
154
155 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
156 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
157 return false;
158 }
159
160 if (!record->event.pressed)
161 return true;
162
163 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
164 qk_ucis_state.count++;
165
166 if (keycode == KC_BSPC) {
167 if (qk_ucis_state.count >= 2) {
168 qk_ucis_state.count -= 2;
169 return true;
170 } else {
171 qk_ucis_state.count--;
172 return false;
173 }
174 }
175
176 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
177 bool symbol_found = false;
178
179 for (i = qk_ucis_state.count; i > 0; i--) {
180 register_code (KC_BSPC);
181 unregister_code (KC_BSPC);
182 wait_ms(UNICODE_TYPE_DELAY);
183 }
184
185 if (keycode == KC_ESC) {
186 qk_ucis_state.in_progress = false;
187 return false;
188 }
189
190 unicode_input_start();
191 for (i = 0; ucis_symbol_table[i].symbol; i++) {
192 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
193 symbol_found = true;
194 register_ucis(ucis_symbol_table[i].code + 2);
53 break; 195 break;
196 }
54 } 197 }
198 if (!symbol_found) {
199 qk_ucis_symbol_fallback();
200 }
201 unicode_input_finish();
202
203 qk_ucis_state.in_progress = false;
204 return false;
55 } 205 }
56 return true; 206 return true;
57} \ No newline at end of file 207}
208#endif
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index ca17f8f66..02ce3dd7e 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -8,10 +8,48 @@
8#define UC_WIN 2 8#define UC_WIN 2
9#define UC_BSD 3 9#define UC_BSD 3
10 10
11#ifndef UNICODE_TYPE_DELAY
12#define UNICODE_TYPE_DELAY 10
13#endif
14
11void set_unicode_input_mode(uint8_t os_target); 15void set_unicode_input_mode(uint8_t os_target);
16void unicode_input_start(void);
17void unicode_input_finish(void);
18void register_hex(uint16_t hex);
12 19
13bool process_unicode(uint16_t keycode, keyrecord_t *record); 20bool process_unicode(uint16_t keycode, keyrecord_t *record);
14 21
22#ifdef UCIS_ENABLE
23#ifndef UCIS_MAX_SYMBOL_LENGTH
24#define UCIS_MAX_SYMBOL_LENGTH 32
25#endif
26
27typedef struct {
28 char *symbol;
29 char *code;
30} qk_ucis_symbol_t;
31
32typedef struct {
33 uint8_t count;
34 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
35 bool in_progress:1;
36} qk_ucis_state_t;
37
38extern qk_ucis_state_t qk_ucis_state;
39
40#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
41#define UCIS_SYM(name, code) {name, #code}
42
43extern const qk_ucis_symbol_t ucis_symbol_table[];
44
45void qk_ucis_start(void);
46void qk_ucis_start_user(void);
47void qk_ucis_symbol_fallback (void);
48void register_ucis(const char *hex);
49bool process_ucis (uint16_t keycode, keyrecord_t *record);
50
51#endif
52
15#define UC_BSPC UC(0x0008) 53#define UC_BSPC UC(0x0008)
16 54
17#define UC_SPC UC(0x0020) 55#define UC_SPC UC(0x0020)
@@ -119,4 +157,4 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record);
119#define UC_TILD UC(0x007E) 157#define UC_TILD UC(0x007E)
120#define UC_DEL UC(0x007F) 158#define UC_DEL UC(0x007F)
121 159
122#endif \ No newline at end of file 160#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index bc2da510f..e3a20f43e 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -1,5 +1,42 @@
1#include "quantum.h" 1#include "quantum.h"
2 2
3static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
4 switch (code) {
5 case QK_MODS ... QK_MODS_MAX:
6 break;
7 default:
8 return;
9 }
10
11 if (code & QK_LCTL)
12 f(KC_LCTL);
13 if (code & QK_LSFT)
14 f(KC_LSFT);
15 if (code & QK_LALT)
16 f(KC_LALT);
17 if (code & QK_LGUI)
18 f(KC_LGUI);
19
20 if (code & QK_RCTL)
21 f(KC_RCTL);
22 if (code & QK_RSFT)
23 f(KC_RSFT);
24 if (code & QK_RALT)
25 f(KC_RALT);
26 if (code & QK_RGUI)
27 f(KC_RGUI);
28}
29
30void register_code16 (uint16_t code) {
31 do_code16 (code, register_code);
32 register_code (code);
33}
34
35void unregister_code16 (uint16_t code) {
36 unregister_code (code);
37 do_code16 (code, unregister_code);
38}
39
3__attribute__ ((weak)) 40__attribute__ ((weak))
4bool process_action_kb(keyrecord_t *record) { 41bool process_action_kb(keyrecord_t *record) {
5 return true; 42 return true;
@@ -46,18 +83,20 @@ bool process_record_quantum(keyrecord_t *record) {
46 uint16_t keycode; 83 uint16_t keycode;
47 84
48 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) 85 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
49 uint8_t layer; 86 /* TODO: Use store_or_get_action() or a similar function. */
87 if (!disable_action_cache) {
88 uint8_t layer;
50 89
51 if (record->event.pressed) { 90 if (record->event.pressed) {
52 layer = layer_switch_get_layer(key); 91 layer = layer_switch_get_layer(key);
53 update_source_layers_cache(key, layer); 92 update_source_layers_cache(key, layer);
54 } else { 93 } else {
55 layer = read_source_layers_cache(key); 94 layer = read_source_layers_cache(key);
56 } 95 }
57 keycode = keymap_key_to_keycode(layer, key); 96 keycode = keymap_key_to_keycode(layer, key);
58 #else 97 } else
59 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
60 #endif 98 #endif
99 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
61 100
62 // This is how you use actions here 101 // This is how you use actions here
63 // if (keycode == KC_LEAD) { 102 // if (keycode == KC_LEAD) {
@@ -87,6 +126,9 @@ bool process_record_quantum(keyrecord_t *record) {
87 #ifdef UNICODE_ENABLE 126 #ifdef UNICODE_ENABLE
88 process_unicode(keycode, record) && 127 process_unicode(keycode, record) &&
89 #endif 128 #endif
129 #ifdef UCIS_ENABLE
130 process_ucis(keycode, record) &&
131 #endif
90 true)) { 132 true)) {
91 return false; 133 return false;
92 } 134 }
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 7ebfb24e3..0c6046649 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -25,6 +25,7 @@
25#include "led.h" 25#include "led.h"
26#include "action_util.h" 26#include "action_util.h"
27#include <stdlib.h> 27#include <stdlib.h>
28#include "print.h"
28 29
29 30
30extern uint32_t default_layer_state; 31extern uint32_t default_layer_state;
@@ -82,6 +83,9 @@ void reset_keyboard(void);
82void startup_user(void); 83void startup_user(void);
83void shutdown_user(void); 84void shutdown_user(void);
84 85
86void register_code16 (uint16_t code);
87void unregister_code16 (uint16_t code);
88
85#ifdef BACKLIGHT_ENABLE 89#ifdef BACKLIGHT_ENABLE
86void backlight_init_ports(void); 90void backlight_init_ports(void);
87 91
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index b1b0f035d..f82e3ec55 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -7,24 +7,41 @@
7#include "debug.h" 7#include "debug.h"
8 8
9const uint8_t DIM_CURVE[] PROGMEM = { 9const uint8_t DIM_CURVE[] PROGMEM = {
10 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 10 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
11 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 11 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
12 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 12 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
13 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 13 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
14 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 14 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
15 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
16 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 16 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
17 20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, 17 20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
18 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35, 18 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35,
19 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47, 19 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47,
20 48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 20 48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
21 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82, 21 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82,
22 83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109, 22 83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109,
23 110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144, 23 110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
24 146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190, 24 146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
25 193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255, 25 193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255
26};
27const uint8_t RGBLED_BREATHING_TABLE[] PROGMEM = {
28 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
29 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
30 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
31 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
32 127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173,
33 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215,
34 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244,
35 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
36 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246,
37 245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220,
38 218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179,
39 176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131,
40 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82,
41 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
42 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
43 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0
26}; 44};
27const uint8_t RGBLED_BREATHING_TABLE[] PROGMEM = {0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,17,18,20,21,23,25,27,29,31,33,35,37,40,42,44,47,49,52,54,57,59,62,65,67,70,73,76,79,82,85,88,90,93,97,100,103,106,109,112,115,118,121,124,127,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,128,124,121,118,115,112,109,106,103,100,97,93,90,88,85,82,79,76,73,70,67,65,62,59,57,54,52,49,47,44,42,40,37,35,33,31,29,27,25,23,21,20,18,17,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0};
28const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; 45const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
29const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; 46const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
30const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; 47const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
@@ -38,63 +55,56 @@ uint8_t rgblight_inited = 0;
38 55
39 56
40void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) { 57void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
41 /* convert hue, saturation and brightness ( HSB/HSV ) to RGB 58 // Convert hue, saturation, and value (HSV/HSB) to RGB. DIM_CURVE is used only
42 The DIM_CURVE is used only on brightness/value and on saturation (inverted). 59 // on value and saturation (inverted). This looks the most natural.
43 This looks the most natural. 60 uint8_t r = 0, g = 0, b = 0, base, color;
44 */
45 uint8_t r = 0, g = 0, b = 0;
46 61
47 val = pgm_read_byte(&DIM_CURVE[val]); 62 val = pgm_read_byte(&DIM_CURVE[val]);
48 sat = 255 - pgm_read_byte(&DIM_CURVE[255 - sat]); 63 sat = 255 - pgm_read_byte(&DIM_CURVE[255 - sat]);
49 64
50 uint8_t base; 65 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
51 66 r = val;
52 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind. 67 g = val;
53 r = val; 68 b = val;
54 g = val; 69 } else {
55 b = val; 70 base = ((255 - sat) * val) >> 8;
56 } else { 71 color = (val - base) * (hue % 60) / 60;
57 base = ((255 - sat) * val) >> 8; 72
58 73 switch (hue / 60) {
59 switch (hue / 60) { 74 case 0:
60 case 0: 75 r = val;
61 r = val; 76 g = base + color;
62 g = (((val - base)*hue) / 60) + base; 77 b = base;
63 b = base; 78 break;
64 break; 79 case 1:
65 80 r = val - color;
66 case 1: 81 g = val;
67 r = (((val - base)*(60 - (hue % 60))) / 60) + base; 82 b = base;
68 g = val; 83 break;
69 b = base; 84 case 2:
70 break; 85 r = base;
71 86 g = val;
72 case 2: 87 b = base + color;
73 r = base; 88 break;
74 g = val; 89 case 3:
75 b = (((val - base)*(hue % 60)) / 60) + base; 90 r = base;
76 break; 91 g = val - color;
77 92 b = val;
78 case 3: 93 break;
79 r = base; 94 case 4:
80 g = (((val - base)*(60 - (hue % 60))) / 60) + base; 95 r = base + color;
81 b = val; 96 g = base;
82 break; 97 b = val;
83 98 break;
84 case 4: 99 case 5:
85 r = (((val - base)*(hue % 60)) / 60) + base; 100 r = val;
86 g = base; 101 g = base;
87 b = val; 102 b = val - color;
88 break; 103 break;
89 104 }
90 case 5: 105 }
91 r = val; 106
92 g = base; 107 setrgb(r, g, b, led1);
93 b = (((val - base)*(60 - (hue % 60))) / 60) + base;
94 break;
95 }
96 }
97 setrgb(r,g,b, led1);
98} 108}
99 109
100void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) { 110void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) {
@@ -111,44 +121,44 @@ void eeconfig_update_rgblight(uint32_t val) {
111 eeprom_update_dword(EECONFIG_RGBLIGHT, val); 121 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
112} 122}
113void eeconfig_update_rgblight_default(void) { 123void eeconfig_update_rgblight_default(void) {
114 dprintf("eeconfig_update_rgblight_default\n"); 124 dprintf("eeconfig_update_rgblight_default\n");
115 rgblight_config.enable = 1; 125 rgblight_config.enable = 1;
116 rgblight_config.mode = 1; 126 rgblight_config.mode = 1;
117 rgblight_config.hue = 200; 127 rgblight_config.hue = 200;
118 rgblight_config.sat = 204; 128 rgblight_config.sat = 204;
119 rgblight_config.val = 204; 129 rgblight_config.val = 204;
120 eeconfig_update_rgblight(rgblight_config.raw); 130 eeconfig_update_rgblight(rgblight_config.raw);
121} 131}
122void eeconfig_debug_rgblight(void) { 132void eeconfig_debug_rgblight(void) {
123 dprintf("rgblight_config eprom\n"); 133 dprintf("rgblight_config eprom\n");
124 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable); 134 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
125 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode); 135 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
126 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue); 136 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
127 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat); 137 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
128 dprintf("rgblight_config.val = %d\n", rgblight_config.val); 138 dprintf("rgblight_config.val = %d\n", rgblight_config.val);
129} 139}
130 140
131void rgblight_init(void) { 141void rgblight_init(void) {
132 debug_enable = 1; // Debug ON! 142 debug_enable = 1; // Debug ON!
133 dprintf("rgblight_init called.\n"); 143 dprintf("rgblight_init called.\n");
134 rgblight_inited = 1; 144 rgblight_inited = 1;
135 dprintf("rgblight_init start!\n"); 145 dprintf("rgblight_init start!\n");
136 if (!eeconfig_is_enabled()) { 146 if (!eeconfig_is_enabled()) {
137 dprintf("rgblight_init eeconfig is not enabled.\n"); 147 dprintf("rgblight_init eeconfig is not enabled.\n");
138 eeconfig_init(); 148 eeconfig_init();
139 eeconfig_update_rgblight_default(); 149 eeconfig_update_rgblight_default();
140 } 150 }
141 rgblight_config.raw = eeconfig_read_rgblight(); 151 rgblight_config.raw = eeconfig_read_rgblight();
142 if (!rgblight_config.mode) { 152 if (!rgblight_config.mode) {
143 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n"); 153 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
144 eeconfig_update_rgblight_default(); 154 eeconfig_update_rgblight_default();
145 rgblight_config.raw = eeconfig_read_rgblight(); 155 rgblight_config.raw = eeconfig_read_rgblight();
146 } 156 }
147 eeconfig_debug_rgblight(); // display current eeprom values 157 eeconfig_debug_rgblight(); // display current eeprom values
148 158
149 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 159 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
150 rgblight_timer_init(); // setup the timer 160 rgblight_timer_init(); // setup the timer
151 #endif 161 #endif
152 162
153 if (rgblight_config.enable) { 163 if (rgblight_config.enable) {
154 rgblight_mode(rgblight_config.mode); 164 rgblight_mode(rgblight_config.mode);
@@ -156,58 +166,57 @@ void rgblight_init(void) {
156} 166}
157 167
158void rgblight_increase(void) { 168void rgblight_increase(void) {
159 uint8_t mode = 0; 169 uint8_t mode = 0;
160 if (rgblight_config.mode < RGBLIGHT_MODES) { 170 if (rgblight_config.mode < RGBLIGHT_MODES) {
161 mode = rgblight_config.mode + 1; 171 mode = rgblight_config.mode + 1;
162 } 172 }
163 rgblight_mode(mode); 173 rgblight_mode(mode);
164} 174}
165
166void rgblight_decrease(void) { 175void rgblight_decrease(void) {
167 uint8_t mode = 0; 176 uint8_t mode = 0;
168 if (rgblight_config.mode > 1) { //mode will never < 1, if mode is less than 1, eeprom need to be initialized. 177 // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
169 mode = rgblight_config.mode-1; 178 if (rgblight_config.mode > 1) {
179 mode = rgblight_config.mode - 1;
170 } 180 }
171 rgblight_mode(mode); 181 rgblight_mode(mode);
172} 182}
173
174void rgblight_step(void) { 183void rgblight_step(void) {
175 uint8_t mode = 0; 184 uint8_t mode = 0;
176 mode = rgblight_config.mode + 1; 185 mode = rgblight_config.mode + 1;
177 if (mode > RGBLIGHT_MODES) { 186 if (mode > RGBLIGHT_MODES) {
178 mode = 1; 187 mode = 1;
179 } 188 }
180 rgblight_mode(mode); 189 rgblight_mode(mode);
181} 190}
182 191
183void rgblight_mode(uint8_t mode) { 192void rgblight_mode(uint8_t mode) {
184 if (!rgblight_config.enable) { 193 if (!rgblight_config.enable) {
185 return; 194 return;
186 } 195 }
187 if (mode<1) { 196 if (mode < 1) {
188 rgblight_config.mode = 1; 197 rgblight_config.mode = 1;
189 } else if (mode > RGBLIGHT_MODES) { 198 } else if (mode > RGBLIGHT_MODES) {
190 rgblight_config.mode = RGBLIGHT_MODES; 199 rgblight_config.mode = RGBLIGHT_MODES;
191 } else { 200 } else {
192 rgblight_config.mode = mode; 201 rgblight_config.mode = mode;
193 } 202 }
194 eeconfig_update_rgblight(rgblight_config.raw); 203 eeconfig_update_rgblight(rgblight_config.raw);
195 xprintf("rgblight mode: %u\n", rgblight_config.mode); 204 xprintf("rgblight mode: %u\n", rgblight_config.mode);
196 if (rgblight_config.mode == 1) { 205 if (rgblight_config.mode == 1) {
197 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 206 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
198 rgblight_timer_disable(); 207 rgblight_timer_disable();
199 #endif 208 #endif
200 } else if (rgblight_config.mode >=2 && rgblight_config.mode <=23) { 209 } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 23) {
201 // MODE 2-5, breathing 210 // MODE 2-5, breathing
202 // MODE 6-8, rainbow mood 211 // MODE 6-8, rainbow mood
203 // MODE 9-14, rainbow swirl 212 // MODE 9-14, rainbow swirl
204 // MODE 15-20, snake 213 // MODE 15-20, snake
205 // MODE 21-23, knight 214 // MODE 21-23, knight
206 215
207 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 216 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
208 rgblight_timer_enable(); 217 rgblight_timer_enable();
209 #endif 218 #endif
210 } 219 }
211 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); 220 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
212} 221}
213 222
@@ -215,306 +224,318 @@ void rgblight_toggle(void) {
215 rgblight_config.enable ^= 1; 224 rgblight_config.enable ^= 1;
216 eeconfig_update_rgblight(rgblight_config.raw); 225 eeconfig_update_rgblight(rgblight_config.raw);
217 xprintf("rgblight toggle: rgblight_config.enable = %u\n", rgblight_config.enable); 226 xprintf("rgblight toggle: rgblight_config.enable = %u\n", rgblight_config.enable);
218 if (rgblight_config.enable) { 227 if (rgblight_config.enable) {
219 rgblight_mode(rgblight_config.mode); 228 rgblight_mode(rgblight_config.mode);
220 } else { 229 } else {
221 230 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
222 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 231 rgblight_timer_disable();
223 rgblight_timer_disable(); 232 #endif
224 #endif 233 _delay_ms(50);
225 _delay_ms(50); 234 rgblight_set();
226 rgblight_set(); 235 }
227 }
228} 236}
229 237
230 238
231void rgblight_increase_hue(void){ 239void rgblight_increase_hue(void) {
232 uint16_t hue; 240 uint16_t hue;
233 hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360; 241 hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
234 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val); 242 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
235} 243}
236void rgblight_decrease_hue(void){ 244void rgblight_decrease_hue(void) {
237 uint16_t hue; 245 uint16_t hue;
238 if (rgblight_config.hue-RGBLIGHT_HUE_STEP <0 ) { 246 if (rgblight_config.hue-RGBLIGHT_HUE_STEP < 0) {
239 hue = (rgblight_config.hue+360-RGBLIGHT_HUE_STEP) % 360; 247 hue = (rgblight_config.hue + 360 - RGBLIGHT_HUE_STEP) % 360;
240 } else { 248 } else {
241 hue = (rgblight_config.hue-RGBLIGHT_HUE_STEP) % 360; 249 hue = (rgblight_config.hue - RGBLIGHT_HUE_STEP) % 360;
242 } 250 }
243 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val); 251 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
244} 252}
245void rgblight_increase_sat(void) { 253void rgblight_increase_sat(void) {
246 uint8_t sat; 254 uint8_t sat;
247 if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) { 255 if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
248 sat = 255; 256 sat = 255;
249 } else { 257 } else {
250 sat = rgblight_config.sat+RGBLIGHT_SAT_STEP; 258 sat = rgblight_config.sat + RGBLIGHT_SAT_STEP;
251 } 259 }
252 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val); 260 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
253} 261}
254void rgblight_decrease_sat(void){ 262void rgblight_decrease_sat(void) {
255 uint8_t sat; 263 uint8_t sat;
256 if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) { 264 if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
257 sat = 0; 265 sat = 0;
258 } else { 266 } else {
259 sat = rgblight_config.sat-RGBLIGHT_SAT_STEP; 267 sat = rgblight_config.sat - RGBLIGHT_SAT_STEP;
260 } 268 }
261 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val); 269 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
262} 270}
263void rgblight_increase_val(void){ 271void rgblight_increase_val(void) {
264 uint8_t val; 272 uint8_t val;
265 if (rgblight_config.val + RGBLIGHT_VAL_STEP > 255) { 273 if (rgblight_config.val + RGBLIGHT_VAL_STEP > 255) {
266 val = 255; 274 val = 255;
267 } else { 275 } else {
268 val = rgblight_config.val+RGBLIGHT_VAL_STEP; 276 val = rgblight_config.val + RGBLIGHT_VAL_STEP;
269 } 277 }
270 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val); 278 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
271} 279}
272void rgblight_decrease_val(void) { 280void rgblight_decrease_val(void) {
273 uint8_t val; 281 uint8_t val;
274 if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) { 282 if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
275 val = 0; 283 val = 0;
276 } else { 284 } else {
277 val = rgblight_config.val-RGBLIGHT_VAL_STEP; 285 val = rgblight_config.val - RGBLIGHT_VAL_STEP;
278 } 286 }
279 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val); 287 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
280} 288}
281 289
282void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val){ 290void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
283 inmem_config.raw = rgblight_config.raw; 291 inmem_config.raw = rgblight_config.raw;
284 if (rgblight_config.enable) { 292 if (rgblight_config.enable) {
285 struct cRGB tmp_led; 293 struct cRGB tmp_led;
286 sethsv(hue, sat, val, &tmp_led); 294 sethsv(hue, sat, val, &tmp_led);
287 inmem_config.hue = hue; 295 inmem_config.hue = hue;
288 inmem_config.sat = sat; 296 inmem_config.sat = sat;
289 inmem_config.val = val; 297 inmem_config.val = val;
290 // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val); 298 // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
291 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b); 299 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
292 } 300 }
293} 301}
294void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val){ 302void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
295 if (rgblight_config.enable) { 303 if (rgblight_config.enable) {
296 if (rgblight_config.mode == 1) { 304 if (rgblight_config.mode == 1) {
297 // same static color 305 // same static color
298 rgblight_sethsv_noeeprom(hue, sat, val); 306 rgblight_sethsv_noeeprom(hue, sat, val);
299 } else { 307 } else {
300 // all LEDs in same color 308 // all LEDs in same color
301 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { 309 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
302 // breathing mode, ignore the change of val, use in memory value instead 310 // breathing mode, ignore the change of val, use in memory value instead
303 val = rgblight_config.val; 311 val = rgblight_config.val;
304 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) { 312 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
305 // rainbow mood and rainbow swirl, ignore the change of hue 313 // rainbow mood and rainbow swirl, ignore the change of hue
306 hue = rgblight_config.hue; 314 hue = rgblight_config.hue;
307 } 315 }
308 } 316 }
309 rgblight_config.hue = hue; 317 rgblight_config.hue = hue;
310 rgblight_config.sat = sat; 318 rgblight_config.sat = sat;
311 rgblight_config.val = val; 319 rgblight_config.val = val;
312 eeconfig_update_rgblight(rgblight_config.raw); 320 eeconfig_update_rgblight(rgblight_config.raw);
313 xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); 321 xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
314 } 322 }
315} 323}
316 324
317void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b){ 325void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
318 // dprintf("rgblight set rgb: %u,%u,%u\n", r,g,b); 326 // dprintf("rgblight set rgb: %u,%u,%u\n", r,g,b);
319 for (uint8_t i=0;i<RGBLED_NUM;i++) { 327 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
320 led[i].r = r; 328 led[i].r = r;
321 led[i].g = g; 329 led[i].g = g;
322 led[i].b = b; 330 led[i].b = b;
323 } 331 }
324 rgblight_set(); 332 rgblight_set();
325
326} 333}
327 334
328void rgblight_set(void) { 335void rgblight_set(void) {
329 if (rgblight_config.enable) { 336 if (rgblight_config.enable) {
330 ws2812_setleds(led, RGBLED_NUM); 337 ws2812_setleds(led, RGBLED_NUM);
331 } else { 338 } else {
332 for (uint8_t i=0;i<RGBLED_NUM;i++) { 339 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
333 led[i].r = 0; 340 led[i].r = 0;
334 led[i].g = 0; 341 led[i].g = 0;
335 led[i].b = 0; 342 led[i].b = 0;
336 } 343 }
337 ws2812_setleds(led, RGBLED_NUM); 344 ws2812_setleds(led, RGBLED_NUM);
338 } 345 }
339} 346}
340 347
341
342#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 348#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
343 349
344// Animation timer -- AVR Timer3 350// Animation timer -- AVR Timer3
345void rgblight_timer_init(void) { 351void rgblight_timer_init(void) {
346 static uint8_t rgblight_timer_is_init = 0; 352 static uint8_t rgblight_timer_is_init = 0;
347 if (rgblight_timer_is_init) { 353 if (rgblight_timer_is_init) {
348 return; 354 return;
349 } 355 }
350 rgblight_timer_is_init = 1; 356 rgblight_timer_is_init = 1;
351 /* Timer 3 setup */ 357 /* Timer 3 setup */
352 TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP 358 TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP
353 | _BV(CS30); //Clock selelct: clk/1 359 | _BV(CS30); //Clock selelct: clk/1
354 /* Set TOP value */ 360 /* Set TOP value */
355 uint8_t sreg = SREG; 361 uint8_t sreg = SREG;
356 cli(); 362 cli();
357 OCR3AH = (RGBLED_TIMER_TOP>>8)&0xff; 363 OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
358 OCR3AL = RGBLED_TIMER_TOP&0xff; 364 OCR3AL = RGBLED_TIMER_TOP & 0xff;
359 SREG = sreg; 365 SREG = sreg;
360} 366}
361void rgblight_timer_enable(void) { 367void rgblight_timer_enable(void) {
362 TIMSK3 |= _BV(OCIE3A); 368 TIMSK3 |= _BV(OCIE3A);
363 dprintf("TIMER3 enabled.\n"); 369 dprintf("TIMER3 enabled.\n");
364} 370}
365void rgblight_timer_disable(void) { 371void rgblight_timer_disable(void) {
366 TIMSK3 &= ~_BV(OCIE3A); 372 TIMSK3 &= ~_BV(OCIE3A);
367 dprintf("TIMER3 disabled.\n"); 373 dprintf("TIMER3 disabled.\n");
368} 374}
369void rgblight_timer_toggle(void) { 375void rgblight_timer_toggle(void) {
370 TIMSK3 ^= _BV(OCIE3A); 376 TIMSK3 ^= _BV(OCIE3A);
371 dprintf("TIMER3 toggled.\n"); 377 dprintf("TIMER3 toggled.\n");
372} 378}
373 379
374ISR(TIMER3_COMPA_vect) { 380ISR(TIMER3_COMPA_vect) {
375 // Mode = 1, static light, do nothing here 381 // mode = 1, static light, do nothing here
376 if (rgblight_config.mode>=2 && rgblight_config.mode<=5) { 382 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
377 // mode = 2 to 5, breathing mode 383 // mode = 2 to 5, breathing mode
378 rgblight_effect_breathing(rgblight_config.mode-2); 384 rgblight_effect_breathing(rgblight_config.mode - 2);
379 385 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
380 } else if (rgblight_config.mode>=6 && rgblight_config.mode<=8) { 386 // mode = 6 to 8, rainbow mood mod
381 rgblight_effect_rainbow_mood(rgblight_config.mode-6); 387 rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
382 } else if (rgblight_config.mode>=9 && rgblight_config.mode<=14) { 388 } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
383 rgblight_effect_rainbow_swirl(rgblight_config.mode-9); 389 // mode = 9 to 14, rainbow swirl mode
384 } else if (rgblight_config.mode>=15 && rgblight_config.mode<=20) { 390 rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
385 rgblight_effect_snake(rgblight_config.mode-15); 391 } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
386 } else if (rgblight_config.mode>=21 && rgblight_config.mode<=23) { 392 // mode = 15 to 20, snake mode
387 rgblight_effect_knight(rgblight_config.mode-21); 393 rgblight_effect_snake(rgblight_config.mode - 15);
388 } 394 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
389} 395 // mode = 21 to 23, knight mode
390 396 rgblight_effect_knight(rgblight_config.mode - 21);
391// effects 397 }
398}
399
400// Effects
392void rgblight_effect_breathing(uint8_t interval) { 401void rgblight_effect_breathing(uint8_t interval) {
393 static uint8_t pos = 0; 402 static uint8_t pos = 0;
394 static uint16_t last_timer = 0; 403 static uint16_t last_timer = 0;
395 404
396 if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) return; 405 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) {
397 last_timer = timer_read(); 406 return;
407 }
408 last_timer = timer_read();
398 409
399 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&RGBLED_BREATHING_TABLE[pos])); 410 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&RGBLED_BREATHING_TABLE[pos]));
400 pos = (pos+1) % 256; 411 pos = (pos + 1) % 256;
401} 412}
402
403void rgblight_effect_rainbow_mood(uint8_t interval) { 413void rgblight_effect_rainbow_mood(uint8_t interval) {
404 static uint16_t current_hue=0; 414 static uint16_t current_hue = 0;
405 static uint16_t last_timer = 0; 415 static uint16_t last_timer = 0;
406 416
407 if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) return; 417 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) {
408 last_timer = timer_read(); 418 return;
409 rgblight_sethsv_noeeprom(current_hue, rgblight_config.sat, rgblight_config.val); 419 }
410 current_hue = (current_hue+1) % 360; 420 last_timer = timer_read();
421 rgblight_sethsv_noeeprom(current_hue, rgblight_config.sat, rgblight_config.val);
422 current_hue = (current_hue + 1) % 360;
411} 423}
412
413void rgblight_effect_rainbow_swirl(uint8_t interval) { 424void rgblight_effect_rainbow_swirl(uint8_t interval) {
414 static uint16_t current_hue=0; 425 static uint16_t current_hue = 0;
415 static uint16_t last_timer = 0; 426 static uint16_t last_timer = 0;
416 uint16_t hue; 427 uint16_t hue;
417 uint8_t i; 428 uint8_t i;
418 if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval/2])) return; 429 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval / 2])) {
419 last_timer = timer_read(); 430 return;
420 for (i=0; i<RGBLED_NUM; i++) { 431 }
421 hue = (360/RGBLED_NUM*i+current_hue)%360; 432 last_timer = timer_read();
422 sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]); 433 for (i = 0; i < RGBLED_NUM; i++) {
423 } 434 hue = (360 / RGBLED_NUM * i + current_hue) % 360;
424 rgblight_set(); 435 sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]);
425 436 }
426 if (interval % 2) { 437 rgblight_set();
427 current_hue = (current_hue+1) % 360; 438
428 } else { 439 if (interval % 2) {
429 if (current_hue -1 < 0) { 440 current_hue = (current_hue + 1) % 360;
430 current_hue = 359; 441 } else {
431 } else { 442 if (current_hue - 1 < 0) {
432 current_hue = current_hue - 1; 443 current_hue = 359;
433 } 444 } else {
434 445 current_hue = current_hue - 1;
435 } 446 }
447 }
436} 448}
437void rgblight_effect_snake(uint8_t interval) { 449void rgblight_effect_snake(uint8_t interval) {
438 static uint8_t pos=0; 450 static uint8_t pos = 0;
439 static uint16_t last_timer = 0; 451 static uint16_t last_timer = 0;
440 uint8_t i,j; 452 uint8_t i, j;
441 int8_t k; 453 int8_t k;
442 int8_t increament = 1; 454 int8_t increment = 1;
443 if (interval%2) increament = -1; 455 if (interval % 2) {
444 if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval/2])) return; 456 increment = -1;
445 last_timer = timer_read(); 457 }
446 for (i=0;i<RGBLED_NUM;i++) { 458 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval / 2])) {
447 led[i].r=0; 459 return;
448 led[i].g=0; 460 }
449 led[i].b=0; 461 last_timer = timer_read();
450 for (j=0;j<RGBLIGHT_EFFECT_SNAKE_LENGTH;j++) { 462 for (i = 0; i < RGBLED_NUM; i++) {
451 k = pos+j*increament; 463 led[i].r = 0;
452 if (k<0) k = k+RGBLED_NUM; 464 led[i].g = 0;
453 if (i==k) { 465 led[i].b = 0;
454 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]); 466 for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
455 } 467 k = pos + j * increment;
456 } 468 if (k < 0) {
457 } 469 k = k + RGBLED_NUM;
458 rgblight_set(); 470 }
459 if (increament == 1) { 471 if (i == k) {
460 if (pos - 1 < 0) { 472 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]);
461 pos = RGBLED_NUM-1; 473 }
462 } else { 474 }
463 pos -= 1; 475 }
464 } 476 rgblight_set();
465 } else { 477 if (increment == 1) {
466 pos = (pos+1)%RGBLED_NUM; 478 if (pos - 1 < 0) {
467 } 479 pos = RGBLED_NUM - 1;
468 480 } else {
481 pos -= 1;
482 }
483 } else {
484 pos = (pos + 1) % RGBLED_NUM;
485 }
469} 486}
470
471void rgblight_effect_knight(uint8_t interval) { 487void rgblight_effect_knight(uint8_t interval) {
472 static int8_t pos=0; 488 static int8_t pos = 0;
473 static uint16_t last_timer = 0; 489 static uint16_t last_timer = 0;
474 uint8_t i,j,cur; 490 uint8_t i, j, cur;
475 int8_t k; 491 int8_t k;
476 struct cRGB preled[RGBLED_NUM]; 492 struct cRGB preled[RGBLED_NUM];
477 static int8_t increament = -1; 493 static int8_t increment = -1;
478 if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) return; 494 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
479 last_timer = timer_read(); 495 return;
480 for (i=0;i<RGBLED_NUM;i++) { 496 }
481 preled[i].r=0; 497 last_timer = timer_read();
482 preled[i].g=0; 498 for (i = 0; i < RGBLED_NUM; i++) {
483 preled[i].b=0; 499 preled[i].r = 0;
484 for (j=0;j<RGBLIGHT_EFFECT_KNIGHT_LENGTH;j++) { 500 preled[i].g = 0;
485 k = pos+j*increament; 501 preled[i].b = 0;
486 if (k<0) k = 0; 502 for (j = 0; j < RGBLIGHT_EFFECT_KNIGHT_LENGTH; j++) {
487 if (k>=RGBLED_NUM) k=RGBLED_NUM-1; 503 k = pos + j * increment;
488 if (i==k) { 504 if (k < 0) {
489 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]); 505 k = 0;
490 } 506 }
491 } 507 if (k >= RGBLED_NUM) {
492 } 508 k = RGBLED_NUM - 1;
493 if (RGBLIGHT_EFFECT_KNIGHT_OFFSET) { 509 }
494 for (i=0;i<RGBLED_NUM;i++) { 510 if (i == k) {
495 cur = (i+RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM; 511 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]);
496 led[i].r = preled[cur].r; 512 }
497 led[i].g = preled[cur].g; 513 }
498 led[i].b = preled[cur].b; 514 }
499 } 515 if (RGBLIGHT_EFFECT_KNIGHT_OFFSET) {
500 } 516 for (i = 0; i < RGBLED_NUM; i++) {
501 rgblight_set(); 517 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
502 if (increament == 1) { 518 led[i].r = preled[cur].r;
503 if (pos - 1 < 0 - RGBLIGHT_EFFECT_KNIGHT_LENGTH) { 519 led[i].g = preled[cur].g;
504 pos = 0- RGBLIGHT_EFFECT_KNIGHT_LENGTH; 520 led[i].b = preled[cur].b;
505 increament = -1; 521 }
506 } else { 522 }
507 pos -= 1; 523 rgblight_set();
508 } 524 if (increment == 1) {
509 } else { 525 if (pos - 1 < 0 - RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
510 if (pos+1>RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH) { 526 pos = 0 - RGBLIGHT_EFFECT_KNIGHT_LENGTH;
511 pos = RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH-1; 527 increment = -1;
512 increament = 1; 528 } else {
513 } else { 529 pos -= 1;
514 pos += 1; 530 }
515 } 531 } else {
516 } 532 if (pos + 1 > RGBLED_NUM + RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
517 533 pos = RGBLED_NUM + RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
518} 534 increment = 1;
519 535 } else {
520#endif \ No newline at end of file 536 pos += 1;
537 }
538 }
539}
540
541#endif
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
index fb4c45a8d..2c87d64c2 100644
--- a/quantum/serial_link/protocol/byte_stuffer.c
+++ b/quantum/serial_link/protocol/byte_stuffer.c
@@ -31,9 +31,6 @@ SOFTWARE.
31// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing 31// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
32// http://www.stuartcheshire.org/papers/COBSforToN.pdf 32// http://www.stuartcheshire.org/papers/COBSforToN.pdf
33 33
34#define MAX_FRAME_SIZE 1024
35#define NUM_LINKS 2
36
37typedef struct byte_stuffer_state { 34typedef struct byte_stuffer_state {
38 uint16_t next_zero; 35 uint16_t next_zero;
39 uint16_t data_pos; 36 uint16_t data_pos;
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
index 2cc88beb4..97e896856 100644
--- a/quantum/serial_link/protocol/byte_stuffer.h
+++ b/quantum/serial_link/protocol/byte_stuffer.h
@@ -27,6 +27,9 @@ SOFTWARE.
27 27
28#include <stdint.h> 28#include <stdint.h>
29 29
30#define MAX_FRAME_SIZE 1024
31#define NUM_LINKS 2
32
30void init_byte_stuffer(void); 33void init_byte_stuffer(void);
31void byte_stuffer_recv_byte(uint8_t link, uint8_t data); 34void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
32void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size); 35void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
index f418d11ce..ff795fe20 100644
--- a/quantum/serial_link/protocol/transport.c
+++ b/quantum/serial_link/protocol/transport.c
@@ -31,6 +31,10 @@ SOFTWARE.
31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; 31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
32static uint32_t num_remote_objects = 0; 32static uint32_t num_remote_objects = 0;
33 33
34void reinitialize_serial_link_transport(void) {
35 num_remote_objects = 0;
36}
37
34void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) { 38void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
35 unsigned int i; 39 unsigned int i;
36 for(i=0;i<_num_remote_objects;i++) { 40 for(i=0;i<_num_remote_objects;i++) {
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
index 9a052d880..2c5d890b2 100644
--- a/quantum/serial_link/protocol/transport.h
+++ b/quantum/serial_link/protocol/transport.h
@@ -82,7 +82,7 @@ typedef struct { \
82 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ 82 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
83 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\ 83 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
84 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 84 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
85 return triple_buffer_read_internal(obj->object_size, tb); \ 85 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
86 } 86 }
87 87
88#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \ 88#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
@@ -112,7 +112,7 @@ typedef struct { \
112 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ 112 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
113 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\ 113 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\
114 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 114 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
115 return triple_buffer_read_internal(obj->object_size, tb); \ 115 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
116 } 116 }
117 117
118#define SLAVE_TO_MASTER_OBJECT(name, type) \ 118#define SLAVE_TO_MASTER_OBJECT(name, type) \
@@ -139,12 +139,13 @@ typedef struct { \
139 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\ 139 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
140 start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \ 140 start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \
141 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 141 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
142 return triple_buffer_read_internal(obj->object_size, tb); \ 142 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
143 } 143 }
144 144
145#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name 145#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
146 146
147void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); 147void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
148void reinitialize_serial_link_transport(void);
148void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); 149void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
149void update_transport(void); 150void update_transport(void);
150 151
diff --git a/quantum/serial_link/tests/byte_stuffer_tests.c b/quantum/serial_link/tests/byte_stuffer_tests.cpp
index 64b170e8c..ff49d727b 100644
--- a/quantum/serial_link/tests/byte_stuffer_tests.c
+++ b/quantum/serial_link/tests/byte_stuffer_tests.cpp
@@ -22,70 +22,90 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE. 22SOFTWARE.
23*/ 23*/
24 24
25#include <cgreen/cgreen.h> 25#include "gtest/gtest.h"
26#include <cgreen/mocks.h> 26#include "gmock/gmock.h"
27#include <vector>
28#include <algorithm>
29extern "C" {
27#include "serial_link/protocol/byte_stuffer.h" 30#include "serial_link/protocol/byte_stuffer.h"
28#include "serial_link/protocol/byte_stuffer.c"
29#include "serial_link/protocol/frame_validator.h" 31#include "serial_link/protocol/frame_validator.h"
30#include "serial_link/protocol/physical.h" 32#include "serial_link/protocol/physical.h"
33}
31 34
32static uint8_t sent_data[MAX_FRAME_SIZE*2]; 35using testing::_;
33static uint16_t sent_data_size; 36using testing::ElementsAreArray;
37using testing::Args;
34 38
35Describe(ByteStuffer); 39class ByteStuffer : public ::testing::Test{
36BeforeEach(ByteStuffer) { 40public:
37 init_byte_stuffer(); 41 ByteStuffer() {
38 sent_data_size = 0; 42 Instance = this;
39} 43 init_byte_stuffer();
40AfterEach(ByteStuffer) {} 44 }
41 45
42void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { 46 ~ByteStuffer() {
43 mock(data, size); 47 Instance = nullptr;
44} 48 }
49
50 MOCK_METHOD3(validator_recv_frame, void (uint8_t link, uint8_t* data, uint16_t size));
51
52 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
53 std::copy(data, data + size, std::back_inserter(sent_data));
54 }
55 std::vector<uint8_t> sent_data;
45 56
46void send_data(uint8_t link, const uint8_t* data, uint16_t size) { 57 static ByteStuffer* Instance;
47 memcpy(sent_data + sent_data_size, data, size); 58};
48 sent_data_size += size; 59
60ByteStuffer* ByteStuffer::Instance = nullptr;
61
62extern "C" {
63 void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
64 ByteStuffer::Instance->validator_recv_frame(link, data, size);
65 }
66
67 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
68 ByteStuffer::Instance->send_data(link, data, size);
69 }
49} 70}
50 71
51Ensure(ByteStuffer, receives_no_frame_for_a_single_zero_byte) { 72TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
52 never_expect(validator_recv_frame); 73 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
74 .Times(0);
53 byte_stuffer_recv_byte(0, 0); 75 byte_stuffer_recv_byte(0, 0);
54} 76}
55 77
56Ensure(ByteStuffer, receives_no_frame_for_a_single_FF_byte) { 78TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
57 never_expect(validator_recv_frame); 79 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
80 .Times(0);
58 byte_stuffer_recv_byte(0, 0xFF); 81 byte_stuffer_recv_byte(0, 0xFF);
59} 82}
60 83
61Ensure(ByteStuffer, receives_no_frame_for_a_single_random_byte) { 84TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
62 never_expect(validator_recv_frame); 85 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
86 .Times(0);
63 byte_stuffer_recv_byte(0, 0x4A); 87 byte_stuffer_recv_byte(0, 0x4A);
64} 88}
65 89
66Ensure(ByteStuffer, receives_no_frame_for_a_zero_length_frame) { 90TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
67 never_expect(validator_recv_frame); 91 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
92 .Times(0);
68 byte_stuffer_recv_byte(0, 1); 93 byte_stuffer_recv_byte(0, 1);
69 byte_stuffer_recv_byte(0, 0); 94 byte_stuffer_recv_byte(0, 0);
70} 95}
71 96
72Ensure(ByteStuffer, receives_single_byte_valid_frame) { 97TEST_F(ByteStuffer, receives_single_byte_valid_frame) {
73 uint8_t expected[] = {0x37}; 98 uint8_t expected[] = {0x37};
74 expect(validator_recv_frame, 99 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
75 when(size, is_equal_to(1)), 100 .With(Args<1, 2>(ElementsAreArray(expected)));
76 when(data, is_equal_to_contents_of(expected, 1))
77 );
78 byte_stuffer_recv_byte(0, 2); 101 byte_stuffer_recv_byte(0, 2);
79 byte_stuffer_recv_byte(0, 0x37); 102 byte_stuffer_recv_byte(0, 0x37);
80 byte_stuffer_recv_byte(0, 0); 103 byte_stuffer_recv_byte(0, 0);
81} 104}
82 105TEST_F(ByteStuffer, receives_three_bytes_valid_frame) {
83Ensure(ByteStuffer, receives_three_bytes_valid_frame) {
84 uint8_t expected[] = {0x37, 0x99, 0xFF}; 106 uint8_t expected[] = {0x37, 0x99, 0xFF};
85 expect(validator_recv_frame, 107 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
86 when(size, is_equal_to(3)), 108 .With(Args<1, 2>(ElementsAreArray(expected)));
87 when(data, is_equal_to_contents_of(expected, 3))
88 );
89 byte_stuffer_recv_byte(0, 4); 109 byte_stuffer_recv_byte(0, 4);
90 byte_stuffer_recv_byte(0, 0x37); 110 byte_stuffer_recv_byte(0, 0x37);
91 byte_stuffer_recv_byte(0, 0x99); 111 byte_stuffer_recv_byte(0, 0x99);
@@ -93,23 +113,19 @@ Ensure(ByteStuffer, receives_three_bytes_valid_frame) {
93 byte_stuffer_recv_byte(0, 0); 113 byte_stuffer_recv_byte(0, 0);
94} 114}
95 115
96Ensure(ByteStuffer, receives_single_zero_valid_frame) { 116TEST_F(ByteStuffer, receives_single_zero_valid_frame) {
97 uint8_t expected[] = {0}; 117 uint8_t expected[] = {0};
98 expect(validator_recv_frame, 118 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
99 when(size, is_equal_to(1)), 119 .With(Args<1, 2>(ElementsAreArray(expected)));
100 when(data, is_equal_to_contents_of(expected, 1))
101 );
102 byte_stuffer_recv_byte(0, 1); 120 byte_stuffer_recv_byte(0, 1);
103 byte_stuffer_recv_byte(0, 1); 121 byte_stuffer_recv_byte(0, 1);
104 byte_stuffer_recv_byte(0, 0); 122 byte_stuffer_recv_byte(0, 0);
105} 123}
106 124
107Ensure(ByteStuffer, receives_valid_frame_with_zeroes) { 125TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) {
108 uint8_t expected[] = {5, 0, 3, 0}; 126 uint8_t expected[] = {5, 0, 3, 0};
109 expect(validator_recv_frame, 127 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
110 when(size, is_equal_to(4)), 128 .With(Args<1, 2>(ElementsAreArray(expected)));
111 when(data, is_equal_to_contents_of(expected, 4))
112 );
113 byte_stuffer_recv_byte(0, 2); 129 byte_stuffer_recv_byte(0, 2);
114 byte_stuffer_recv_byte(0, 5); 130 byte_stuffer_recv_byte(0, 5);
115 byte_stuffer_recv_byte(0, 2); 131 byte_stuffer_recv_byte(0, 2);
@@ -118,17 +134,14 @@ Ensure(ByteStuffer, receives_valid_frame_with_zeroes) {
118 byte_stuffer_recv_byte(0, 0); 134 byte_stuffer_recv_byte(0, 0);
119} 135}
120 136
121Ensure(ByteStuffer, receives_two_valid_frames) { 137
138TEST_F(ByteStuffer, receives_two_valid_frames) {
122 uint8_t expected1[] = {5, 0}; 139 uint8_t expected1[] = {5, 0};
123 uint8_t expected2[] = {3}; 140 uint8_t expected2[] = {3};
124 expect(validator_recv_frame, 141 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
125 when(size, is_equal_to(2)), 142 .With(Args<1, 2>(ElementsAreArray(expected1)));
126 when(data, is_equal_to_contents_of(expected1, 2)) 143 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
127 ); 144 .With(Args<1, 2>(ElementsAreArray(expected2)));
128 expect(validator_recv_frame,
129 when(size, is_equal_to(1)),
130 when(data, is_equal_to_contents_of(expected2, 1))
131 );
132 byte_stuffer_recv_byte(1, 2); 145 byte_stuffer_recv_byte(1, 2);
133 byte_stuffer_recv_byte(1, 5); 146 byte_stuffer_recv_byte(1, 5);
134 byte_stuffer_recv_byte(1, 1); 147 byte_stuffer_recv_byte(1, 1);
@@ -138,12 +151,10 @@ Ensure(ByteStuffer, receives_two_valid_frames) {
138 byte_stuffer_recv_byte(1, 0); 151 byte_stuffer_recv_byte(1, 0);
139} 152}
140 153
141Ensure(ByteStuffer, receives_valid_frame_after_unexpected_zero) { 154TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
142 uint8_t expected[] = {5, 7}; 155 uint8_t expected[] = {5, 7};
143 expect(validator_recv_frame, 156 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
144 when(size, is_equal_to(2)), 157 .With(Args<1, 2>(ElementsAreArray(expected)));
145 when(data, is_equal_to_contents_of(expected, 2))
146 );
147 byte_stuffer_recv_byte(1, 3); 158 byte_stuffer_recv_byte(1, 3);
148 byte_stuffer_recv_byte(1, 1); 159 byte_stuffer_recv_byte(1, 1);
149 byte_stuffer_recv_byte(1, 0); 160 byte_stuffer_recv_byte(1, 0);
@@ -153,12 +164,10 @@ Ensure(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
153 byte_stuffer_recv_byte(1, 0); 164 byte_stuffer_recv_byte(1, 0);
154} 165}
155 166
156Ensure(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) { 167TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
157 uint8_t expected[] = {5, 7}; 168 uint8_t expected[] = {5, 7};
158 expect(validator_recv_frame, 169 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
159 when(size, is_equal_to(2)), 170 .With(Args<1, 2>(ElementsAreArray(expected)));
160 when(data, is_equal_to_contents_of(expected, 2))
161 );
162 byte_stuffer_recv_byte(0, 2); 171 byte_stuffer_recv_byte(0, 2);
163 byte_stuffer_recv_byte(0, 9); 172 byte_stuffer_recv_byte(0, 9);
164 byte_stuffer_recv_byte(0, 4); // This should have been zero 173 byte_stuffer_recv_byte(0, 4); // This should have been zero
@@ -169,16 +178,14 @@ Ensure(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
169 byte_stuffer_recv_byte(0, 0); 178 byte_stuffer_recv_byte(0, 0);
170} 179}
171 180
172Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) { 181TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
173 uint8_t expected[254]; 182 uint8_t expected[254];
174 int i; 183 int i;
175 for (i=0;i<254;i++) { 184 for (i=0;i<254;i++) {
176 expected[i] = i + 1; 185 expected[i] = i + 1;
177 } 186 }
178 expect(validator_recv_frame, 187 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
179 when(size, is_equal_to(254)), 188 .With(Args<1, 2>(ElementsAreArray(expected)));
180 when(data, is_equal_to_contents_of(expected, 254))
181 );
182 byte_stuffer_recv_byte(0, 0xFF); 189 byte_stuffer_recv_byte(0, 0xFF);
183 for (i=0;i<254;i++) { 190 for (i=0;i<254;i++) {
184 byte_stuffer_recv_byte(0, i+1); 191 byte_stuffer_recv_byte(0, i+1);
@@ -186,17 +193,15 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_
186 byte_stuffer_recv_byte(0, 0); 193 byte_stuffer_recv_byte(0, 0);
187} 194}
188 195
189Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) { 196TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
190 uint8_t expected[255]; 197 uint8_t expected[255];
191 int i; 198 int i;
192 for (i=0;i<254;i++) { 199 for (i=0;i<254;i++) {
193 expected[i] = i + 1; 200 expected[i] = i + 1;
194 } 201 }
195 expected[254] = 7; 202 expected[254] = 7;
196 expect(validator_recv_frame, 203 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
197 when(size, is_equal_to(255)), 204 .With(Args<1, 2>(ElementsAreArray(expected)));
198 when(data, is_equal_to_contents_of(expected, 255))
199 );
200 byte_stuffer_recv_byte(0, 0xFF); 205 byte_stuffer_recv_byte(0, 0xFF);
201 for (i=0;i<254;i++) { 206 for (i=0;i<254;i++) {
202 byte_stuffer_recv_byte(0, i+1); 207 byte_stuffer_recv_byte(0, i+1);
@@ -206,17 +211,15 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_
206 byte_stuffer_recv_byte(0, 0); 211 byte_stuffer_recv_byte(0, 0);
207} 212}
208 213
209Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) { 214TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
210 uint8_t expected[255]; 215 uint8_t expected[255];
211 int i; 216 int i;
212 for (i=0;i<254;i++) { 217 for (i=0;i<254;i++) {
213 expected[i] = i + 1; 218 expected[i] = i + 1;
214 } 219 }
215 expected[254] = 0; 220 expected[254] = 0;
216 expect(validator_recv_frame, 221 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
217 when(size, is_equal_to(255)), 222 .With(Args<1, 2>(ElementsAreArray(expected)));
218 when(data, is_equal_to_contents_of(expected, 255))
219 );
220 byte_stuffer_recv_byte(0, 0xFF); 223 byte_stuffer_recv_byte(0, 0xFF);
221 for (i=0;i<254;i++) { 224 for (i=0;i<254;i++) {
222 byte_stuffer_recv_byte(0, i+1); 225 byte_stuffer_recv_byte(0, i+1);
@@ -226,7 +229,7 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_
226 byte_stuffer_recv_byte(0, 0); 229 byte_stuffer_recv_byte(0, 0);
227} 230}
228 231
229Ensure(ByteStuffer, receives_two_long_frames_and_some_more) { 232TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) {
230 uint8_t expected[515]; 233 uint8_t expected[515];
231 int i; 234 int i;
232 int j; 235 int j;
@@ -238,10 +241,8 @@ Ensure(ByteStuffer, receives_two_long_frames_and_some_more) {
238 for (i=0;i<7;i++) { 241 for (i=0;i<7;i++) {
239 expected[254*2+i] = i + 1; 242 expected[254*2+i] = i + 1;
240 } 243 }
241 expect(validator_recv_frame, 244 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
242 when(size, is_equal_to(515)), 245 .With(Args<1, 2>(ElementsAreArray(expected)));
243 when(data, is_equal_to_contents_of(expected, 510))
244 );
245 byte_stuffer_recv_byte(0, 0xFF); 246 byte_stuffer_recv_byte(0, 0xFF);
246 for (i=0;i<254;i++) { 247 for (i=0;i<254;i++) {
247 byte_stuffer_recv_byte(0, i+1); 248 byte_stuffer_recv_byte(0, i+1);
@@ -261,12 +262,10 @@ Ensure(ByteStuffer, receives_two_long_frames_and_some_more) {
261 byte_stuffer_recv_byte(0, 0); 262 byte_stuffer_recv_byte(0, 0);
262} 263}
263 264
264Ensure(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) { 265TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
265 uint8_t expected[MAX_FRAME_SIZE] = {}; 266 uint8_t expected[MAX_FRAME_SIZE] = {};
266 expect(validator_recv_frame, 267 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
267 when(size, is_equal_to(MAX_FRAME_SIZE)), 268 .With(Args<1, 2>(ElementsAreArray(expected)));
268 when(data, is_equal_to_contents_of(expected, MAX_FRAME_SIZE))
269 );
270 int i; 269 int i;
271 byte_stuffer_recv_byte(0, 1); 270 byte_stuffer_recv_byte(0, 1);
272 for(i=0;i<MAX_FRAME_SIZE;i++) { 271 for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -275,9 +274,10 @@ Ensure(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
275 byte_stuffer_recv_byte(0, 0); 274 byte_stuffer_recv_byte(0, 0);
276} 275}
277 276
278Ensure(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) { 277TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
279 uint8_t expected[1] = {0}; 278 uint8_t expected[1] = {0};
280 never_expect(validator_recv_frame); 279 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
280 .Times(0);
281 int i; 281 int i;
282 byte_stuffer_recv_byte(0, 1); 282 byte_stuffer_recv_byte(0, 1);
283 for(i=0;i<MAX_FRAME_SIZE;i++) { 283 for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -287,12 +287,10 @@ Ensure(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
287 byte_stuffer_recv_byte(0, 0); 287 byte_stuffer_recv_byte(0, 0);
288} 288}
289 289
290Ensure(ByteStuffer, received_frame_is_aborted_when_its_too_long) { 290TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
291 uint8_t expected[1] = {1}; 291 uint8_t expected[1] = {1};
292 expect(validator_recv_frame, 292 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
293 when(size, is_equal_to(1)), 293 .With(Args<1, 2>(ElementsAreArray(expected)));
294 when(data, is_equal_to_contents_of(expected, 1))
295 );
296 int i; 294 int i;
297 byte_stuffer_recv_byte(0, 1); 295 byte_stuffer_recv_byte(0, 1);
298 for(i=0;i<MAX_FRAME_SIZE;i++) { 296 for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -303,76 +301,68 @@ Ensure(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
303 byte_stuffer_recv_byte(0, 0); 301 byte_stuffer_recv_byte(0, 0);
304} 302}
305 303
306Ensure(ByteStuffer, does_nothing_when_sending_zero_size_frame) { 304TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
307 assert_that(sent_data_size, is_equal_to(0)); 305 EXPECT_EQ(sent_data.size(), 0);
308 byte_stuffer_send_frame(0, NULL, 0); 306 byte_stuffer_send_frame(0, NULL, 0);
309} 307}
310 308
311Ensure(ByteStuffer, send_one_byte_frame) { 309TEST_F(ByteStuffer, send_one_byte_frame) {
312 uint8_t data[] = {5}; 310 uint8_t data[] = {5};
313 byte_stuffer_send_frame(1, data, 1); 311 byte_stuffer_send_frame(1, data, 1);
314 uint8_t expected[] = {2, 5, 0}; 312 uint8_t expected[] = {2, 5, 0};
315 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 313 EXPECT_THAT(sent_data, ElementsAreArray(expected));
316 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
317} 314}
318 315
319Ensure(ByteStuffer, sends_two_byte_frame) { 316TEST_F(ByteStuffer, sends_two_byte_frame) {
320 uint8_t data[] = {5, 0x77}; 317 uint8_t data[] = {5, 0x77};
321 byte_stuffer_send_frame(0, data, 2); 318 byte_stuffer_send_frame(0, data, 2);
322 uint8_t expected[] = {3, 5, 0x77, 0}; 319 uint8_t expected[] = {3, 5, 0x77, 0};
323 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 320 EXPECT_THAT(sent_data, ElementsAreArray(expected));
324 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
325} 321}
326 322
327Ensure(ByteStuffer, sends_one_byte_frame_with_zero) { 323TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) {
328 uint8_t data[] = {0}; 324 uint8_t data[] = {0};
329 byte_stuffer_send_frame(0, data, 1); 325 byte_stuffer_send_frame(0, data, 1);
330 uint8_t expected[] = {1, 1, 0}; 326 uint8_t expected[] = {1, 1, 0};
331 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 327 EXPECT_THAT(sent_data, ElementsAreArray(expected));
332 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
333} 328}
334 329
335Ensure(ByteStuffer, sends_two_byte_frame_starting_with_zero) { 330TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
336 uint8_t data[] = {0, 9}; 331 uint8_t data[] = {0, 9};
337 byte_stuffer_send_frame(1, data, 2); 332 byte_stuffer_send_frame(1, data, 2);
338 uint8_t expected[] = {1, 2, 9, 0}; 333 uint8_t expected[] = {1, 2, 9, 0};
339 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 334 EXPECT_THAT(sent_data, ElementsAreArray(expected));
340 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
341} 335}
342 336
343Ensure(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) { 337TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
344 uint8_t data[] = {9, 0}; 338 uint8_t data[] = {9, 0};
345 byte_stuffer_send_frame(1, data, 2); 339 byte_stuffer_send_frame(1, data, 2);
346 uint8_t expected[] = {2, 9, 1, 0}; 340 uint8_t expected[] = {2, 9, 1, 0};
347 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 341 EXPECT_THAT(sent_data, ElementsAreArray(expected));
348 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
349} 342}
350 343
351Ensure(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) { 344TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
352 uint8_t data[] = {9, 0, 0x68}; 345 uint8_t data[] = {9, 0, 0x68};
353 byte_stuffer_send_frame(0, data, 3); 346 byte_stuffer_send_frame(0, data, 3);
354 uint8_t expected[] = {2, 9, 2, 0x68, 0}; 347 uint8_t expected[] = {2, 9, 2, 0x68, 0};
355 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 348 EXPECT_THAT(sent_data, ElementsAreArray(expected));
356 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
357} 349}
358 350
359Ensure(ByteStuffer, sends_three_byte_frame_data_in_the_middle) { 351TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
360 uint8_t data[] = {0, 0x55, 0}; 352 uint8_t data[] = {0, 0x55, 0};
361 byte_stuffer_send_frame(0, data, 3); 353 byte_stuffer_send_frame(0, data, 3);
362 uint8_t expected[] = {1, 2, 0x55, 1, 0}; 354 uint8_t expected[] = {1, 2, 0x55, 1, 0};
363 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 355 EXPECT_THAT(sent_data, ElementsAreArray(expected));
364 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
365} 356}
366 357
367Ensure(ByteStuffer, sends_three_byte_frame_with_all_zeroes) { 358TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
368 uint8_t data[] = {0, 0, 0}; 359 uint8_t data[] = {0, 0, 0};
369 byte_stuffer_send_frame(0, data, 3); 360 byte_stuffer_send_frame(0, data, 3);
370 uint8_t expected[] = {1, 1, 1, 1, 0}; 361 uint8_t expected[] = {1, 1, 1, 1, 0};
371 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 362 EXPECT_THAT(sent_data, ElementsAreArray(expected));
372 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
373} 363}
374 364
375Ensure(ByteStuffer, sends_frame_with_254_non_zeroes) { 365TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) {
376 uint8_t data[254]; 366 uint8_t data[254];
377 int i; 367 int i;
378 for(i=0;i<254;i++) { 368 for(i=0;i<254;i++) {
@@ -385,11 +375,10 @@ Ensure(ByteStuffer, sends_frame_with_254_non_zeroes) {
385 expected[i] = i; 375 expected[i] = i;
386 } 376 }
387 expected[255] = 0; 377 expected[255] = 0;
388 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 378 EXPECT_THAT(sent_data, ElementsAreArray(expected));
389 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
390} 379}
391 380
392Ensure(ByteStuffer, sends_frame_with_255_non_zeroes) { 381TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) {
393 uint8_t data[255]; 382 uint8_t data[255];
394 int i; 383 int i;
395 for(i=0;i<255;i++) { 384 for(i=0;i<255;i++) {
@@ -404,17 +393,16 @@ Ensure(ByteStuffer, sends_frame_with_255_non_zeroes) {
404 expected[255] = 2; 393 expected[255] = 2;
405 expected[256] = 255; 394 expected[256] = 255;
406 expected[257] = 0; 395 expected[257] = 0;
407 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 396 EXPECT_THAT(sent_data, ElementsAreArray(expected));
408 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
409} 397}
410 398
411Ensure(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) { 399TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
412 uint8_t data[255]; 400 uint8_t data[255];
413 int i; 401 int i;
414 for(i=0;i<254;i++) { 402 for(i=0;i<254;i++) {
415 data[i] = i + 1; 403 data[i] = i + 1;
416 } 404 }
417 data[255] = 0; 405 data[254] = 0;
418 byte_stuffer_send_frame(0, data, 255); 406 byte_stuffer_send_frame(0, data, 255);
419 uint8_t expected[258]; 407 uint8_t expected[258];
420 expected[0] = 0xFF; 408 expected[0] = 0xFF;
@@ -424,53 +412,46 @@ Ensure(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
424 expected[255] = 1; 412 expected[255] = 1;
425 expected[256] = 1; 413 expected[256] = 1;
426 expected[257] = 0; 414 expected[257] = 0;
427 assert_that(sent_data_size, is_equal_to(sizeof(expected))); 415 EXPECT_THAT(sent_data, ElementsAreArray(expected));
428 assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
429} 416}
430 417
431Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) { 418TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
432 uint8_t original_data[] = { 1, 2, 3}; 419 uint8_t original_data[] = { 1, 2, 3};
433 byte_stuffer_send_frame(0, original_data, sizeof(original_data)); 420 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
434 expect(validator_recv_frame, 421 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
435 when(size, is_equal_to(sizeof(original_data))), 422 .With(Args<1, 2>(ElementsAreArray(original_data)));
436 when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
437 );
438 int i; 423 int i;
439 for(i=0;i<sent_data_size;i++) { 424 for(auto& d : sent_data) {
440 byte_stuffer_recv_byte(1, sent_data[i]); 425 byte_stuffer_recv_byte(1, d);
441 } 426 }
442} 427}
443 428
444Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) { 429TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
445 uint8_t original_data[] = { 1, 0, 3, 0, 0, 9}; 430 uint8_t original_data[] = { 1, 0, 3, 0, 0, 9};
446 byte_stuffer_send_frame(1, original_data, sizeof(original_data)); 431 byte_stuffer_send_frame(1, original_data, sizeof(original_data));
447 expect(validator_recv_frame, 432 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
448 when(size, is_equal_to(sizeof(original_data))), 433 .With(Args<1, 2>(ElementsAreArray(original_data)));
449 when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
450 );
451 int i; 434 int i;
452 for(i=0;i<sent_data_size;i++) { 435 for(auto& d : sent_data) {
453 byte_stuffer_recv_byte(0, sent_data[i]); 436 byte_stuffer_recv_byte(1, d);
454 } 437 }
455} 438}
456 439
457Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) { 440TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
458 uint8_t original_data[254]; 441 uint8_t original_data[254];
459 int i; 442 int i;
460 for(i=0;i<254;i++) { 443 for(i=0;i<254;i++) {
461 original_data[i] = i + 1; 444 original_data[i] = i + 1;
462 } 445 }
463 byte_stuffer_send_frame(0, original_data, sizeof(original_data)); 446 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
464 expect(validator_recv_frame, 447 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
465 when(size, is_equal_to(sizeof(original_data))), 448 .With(Args<1, 2>(ElementsAreArray(original_data)));
466 when(data, is_equal_to_contents_of(original_data, sizeof(original_data))) 449 for(auto& d : sent_data) {
467 ); 450 byte_stuffer_recv_byte(1, d);
468 for(i=0;i<sent_data_size;i++) {
469 byte_stuffer_recv_byte(1, sent_data[i]);
470 } 451 }
471} 452}
472 453
473Ensure(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) { 454TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
474 uint8_t original_data[256]; 455 uint8_t original_data[256];
475 int i; 456 int i;
476 for(i=0;i<254;i++) { 457 for(i=0;i<254;i++) {
@@ -479,16 +460,14 @@ Ensure(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
479 original_data[254] = 22; 460 original_data[254] = 22;
480 original_data[255] = 23; 461 original_data[255] = 23;
481 byte_stuffer_send_frame(0, original_data, sizeof(original_data)); 462 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
482 expect(validator_recv_frame, 463 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
483 when(size, is_equal_to(sizeof(original_data))), 464 .With(Args<1, 2>(ElementsAreArray(original_data)));
484 when(data, is_equal_to_contents_of(original_data, sizeof(original_data))) 465 for(auto& d : sent_data) {
485 ); 466 byte_stuffer_recv_byte(1, d);
486 for(i=0;i<sent_data_size;i++) {
487 byte_stuffer_recv_byte(1, sent_data[i]);
488 } 467 }
489} 468}
490 469
491Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) { 470TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
492 uint8_t original_data[255]; 471 uint8_t original_data[255];
493 int i; 472 int i;
494 for(i=0;i<254;i++) { 473 for(i=0;i<254;i++) {
@@ -496,11 +475,9 @@ Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
496 } 475 }
497 original_data[254] = 0; 476 original_data[254] = 0;
498 byte_stuffer_send_frame(0, original_data, sizeof(original_data)); 477 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
499 expect(validator_recv_frame, 478 EXPECT_CALL(*this, validator_recv_frame(_, _, _))
500 when(size, is_equal_to(sizeof(original_data))), 479 .With(Args<1, 2>(ElementsAreArray(original_data)));
501 when(data, is_equal_to_contents_of(original_data, sizeof(original_data))) 480 for(auto& d : sent_data) {
502 ); 481 byte_stuffer_recv_byte(1, d);
503 for(i=0;i<sent_data_size;i++) {
504 byte_stuffer_recv_byte(1, sent_data[i]);
505 } 482 }
506} 483}
diff --git a/quantum/serial_link/tests/frame_router_tests.c b/quantum/serial_link/tests/frame_router_tests.c
deleted file mode 100644
index 6c806fa93..000000000
--- a/quantum/serial_link/tests/frame_router_tests.c
+++ /dev/null
@@ -1,231 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include <cgreen/cgreen.h>
26#include <cgreen/mocks.h>
27#include "serial_link/protocol/byte_stuffer.c"
28#include "serial_link/protocol/frame_validator.c"
29#include "serial_link/protocol/frame_router.c"
30#include "serial_link/protocol/transport.h"
31
32static uint8_t received_data[256];
33static uint16_t received_data_size;
34
35typedef struct {
36 uint8_t sent_data[256];
37 uint16_t sent_data_size;
38} receive_buffer_t;
39
40typedef struct {
41 receive_buffer_t send_buffers[2];
42} router_buffer_t;
43
44router_buffer_t router_buffers[8];
45
46router_buffer_t* current_router_buffer;
47
48
49Describe(FrameRouter);
50BeforeEach(FrameRouter) {
51 init_byte_stuffer();
52 memset(router_buffers, 0, sizeof(router_buffers));
53 current_router_buffer = 0;
54}
55AfterEach(FrameRouter) {}
56
57typedef struct {
58 uint32_t data;
59 uint8_t extra[16];
60} frame_buffer_t;
61
62
63void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
64 receive_buffer_t* buffer = &current_router_buffer->send_buffers[link];
65 memcpy(buffer->sent_data + buffer->sent_data_size, data, size);
66 buffer->sent_data_size += size;
67}
68
69static void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
70 int i;
71 for(i=0;i<size;i++) {
72 byte_stuffer_recv_byte(link, data[i]);
73 }
74}
75
76static void activate_router(uint8_t num) {
77 current_router_buffer = router_buffers + num;
78 router_set_master(num==0);
79}
80
81static void simulate_transport(uint8_t from, uint8_t to) {
82 activate_router(to);
83 if (from > to) {
84 receive_data(DOWN_LINK,
85 router_buffers[from].send_buffers[UP_LINK].sent_data,
86 router_buffers[from].send_buffers[UP_LINK].sent_data_size);
87 }
88 else if(to > from) {
89 receive_data(UP_LINK,
90 router_buffers[from].send_buffers[DOWN_LINK].sent_data,
91 router_buffers[from].send_buffers[DOWN_LINK].sent_data_size);
92 }
93}
94
95void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
96 mock(from, data, size);
97}
98
99
100Ensure(FrameRouter, master_broadcast_is_received_by_everyone) {
101 frame_buffer_t data;
102 data.data = 0xAB7055BB;
103 activate_router(0);
104 router_send_frame(0xFF, (uint8_t*)&data, 4);
105 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
106 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
107
108 expect(transport_recv_frame,
109 when(from, is_equal_to(0)),
110 when(size, is_equal_to(4)),
111 when(data, is_equal_to_contents_of(&data.data, 4))
112 );
113 simulate_transport(0, 1);
114 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
115 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
116
117 expect(transport_recv_frame,
118 when(from, is_equal_to(0)),
119 when(size, is_equal_to(4)),
120 when(data, is_equal_to_contents_of(&data.data, 4))
121 );
122 simulate_transport(1, 2);
123 assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
124 assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
125}
126
127Ensure(FrameRouter, master_send_is_received_by_targets) {
128 frame_buffer_t data;
129 data.data = 0xAB7055BB;
130 activate_router(0);
131 router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
132 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
133 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
134
135 simulate_transport(0, 1);
136 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
137 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
138
139 expect(transport_recv_frame,
140 when(from, is_equal_to(0)),
141 when(size, is_equal_to(4)),
142 when(data, is_equal_to_contents_of(&data.data, 4))
143 );
144 simulate_transport(1, 2);
145 assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
146 assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
147
148 expect(transport_recv_frame,
149 when(from, is_equal_to(0)),
150 when(size, is_equal_to(4)),
151 when(data, is_equal_to_contents_of(&data.data, 4))
152 );
153 simulate_transport(2, 3);
154 assert_that(router_buffers[3].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
155 assert_that(router_buffers[3].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
156}
157
158Ensure(FrameRouter, first_link_sends_to_master) {
159 frame_buffer_t data;
160 data.data = 0xAB7055BB;
161 activate_router(1);
162 router_send_frame(0, (uint8_t*)&data, 4);
163 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
164 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
165
166 expect(transport_recv_frame,
167 when(from, is_equal_to(1)),
168 when(size, is_equal_to(4)),
169 when(data, is_equal_to_contents_of(&data.data, 4))
170 );
171 simulate_transport(1, 0);
172 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
173 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
174}
175
176Ensure(FrameRouter, second_link_sends_to_master) {
177 frame_buffer_t data;
178 data.data = 0xAB7055BB;
179 activate_router(2);
180 router_send_frame(0, (uint8_t*)&data, 4);
181 assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
182 assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
183
184 simulate_transport(2, 1);
185 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
186 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
187
188 expect(transport_recv_frame,
189 when(from, is_equal_to(2)),
190 when(size, is_equal_to(4)),
191 when(data, is_equal_to_contents_of(&data.data, 4))
192 );
193 simulate_transport(1, 0);
194 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
195 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
196}
197
198Ensure(FrameRouter, master_sends_to_master_does_nothing) {
199 frame_buffer_t data;
200 data.data = 0xAB7055BB;
201 activate_router(0);
202 router_send_frame(0, (uint8_t*)&data, 4);
203 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
204 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
205}
206
207Ensure(FrameRouter, link_sends_to_other_link_does_nothing) {
208 frame_buffer_t data;
209 data.data = 0xAB7055BB;
210 activate_router(1);
211 router_send_frame(2, (uint8_t*)&data, 4);
212 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
213 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
214}
215
216Ensure(FrameRouter, master_receives_on_uplink_does_nothing) {
217 frame_buffer_t data;
218 data.data = 0xAB7055BB;
219 activate_router(1);
220 router_send_frame(0, (uint8_t*)&data, 4);
221 assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
222 assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
223
224 never_expect(transport_recv_frame);
225 activate_router(0);
226 receive_data(UP_LINK,
227 router_buffers[1].send_buffers[UP_LINK].sent_data,
228 router_buffers[1].send_buffers[UP_LINK].sent_data_size);
229 assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
230 assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
231}
diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp
new file mode 100644
index 000000000..2bd5bf830
--- /dev/null
+++ b/quantum/serial_link/tests/frame_router_tests.cpp
@@ -0,0 +1,229 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27#include <array>
28extern "C" {
29 #include "serial_link/protocol/transport.h"
30 #include "serial_link/protocol/byte_stuffer.h"
31 #include "serial_link/protocol/frame_router.h"
32}
33
34using testing::_;
35using testing::ElementsAreArray;
36using testing::Args;
37
38class FrameRouter : public testing::Test {
39public:
40 FrameRouter() :
41 current_router_buffer(nullptr)
42 {
43 Instance = this;
44 init_byte_stuffer();
45 }
46
47 ~FrameRouter() {
48 Instance = nullptr;
49 }
50
51 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
52 auto& buffer = current_router_buffer->send_buffers[link];
53 std::copy(data, data + size, std::back_inserter(buffer));
54 }
55
56 void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
57 int i;
58 for(i=0;i<size;i++) {
59 byte_stuffer_recv_byte(link, data[i]);
60 }
61 }
62
63 void activate_router(uint8_t num) {
64 current_router_buffer = router_buffers + num;
65 router_set_master(num==0);
66 }
67
68 void simulate_transport(uint8_t from, uint8_t to) {
69 activate_router(to);
70 if (from > to) {
71 receive_data(DOWN_LINK,
72 router_buffers[from].send_buffers[UP_LINK].data(),
73 router_buffers[from].send_buffers[UP_LINK].size());
74 }
75 else if(to > from) {
76 receive_data(UP_LINK,
77 router_buffers[from].send_buffers[DOWN_LINK].data(),
78 router_buffers[from].send_buffers[DOWN_LINK].size());
79 }
80 }
81
82 MOCK_METHOD3(transport_recv_frame, void (uint8_t from, uint8_t* data, uint16_t size));
83
84 std::vector<uint8_t> received_data;
85
86 struct router_buffer {
87 std::vector<uint8_t> send_buffers[2];
88 };
89
90 router_buffer router_buffers[8];
91 router_buffer* current_router_buffer;
92
93 static FrameRouter* Instance;
94};
95
96FrameRouter* FrameRouter::Instance = nullptr;
97
98
99typedef struct {
100 std::array<uint8_t, 4> data;
101 uint8_t extra[16];
102} frame_buffer_t;
103
104
105extern "C" {
106 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
107 FrameRouter::Instance->send_data(link, data, size);
108 }
109
110
111 void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
112 FrameRouter::Instance->transport_recv_frame(from, data, size);
113 }
114}
115
116TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) {
117 frame_buffer_t data;
118 data.data = {0xAB, 0x70, 0x55, 0xBB};
119 activate_router(0);
120 router_send_frame(0xFF, (uint8_t*)&data, 4);
121 EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
122 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
123 EXPECT_CALL(*this, transport_recv_frame(0, _, _))
124 .With(Args<1, 2>(ElementsAreArray(data.data)));
125 simulate_transport(0, 1);
126 EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
127 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
128
129 EXPECT_CALL(*this, transport_recv_frame(0, _, _))
130 .With(Args<1, 2>(ElementsAreArray(data.data)));
131 simulate_transport(1, 2);
132 EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
133 EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
134}
135
136TEST_F(FrameRouter, master_send_is_received_by_targets) {
137 frame_buffer_t data;
138 data.data = {0xAB, 0x70, 0x55, 0xBB};
139 activate_router(0);
140 router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
141 EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
142 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
143
144 simulate_transport(0, 1);
145 EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
146 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
147
148 EXPECT_CALL(*this, transport_recv_frame(0, _, _))
149 .With(Args<1, 2>(ElementsAreArray(data.data)));
150 simulate_transport(1, 2);
151 EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
152 EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
153
154 EXPECT_CALL(*this, transport_recv_frame(0, _, _))
155 .With(Args<1, 2>(ElementsAreArray(data.data)));
156 simulate_transport(2, 3);
157 EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0);
158 EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0);
159}
160
161TEST_F(FrameRouter, first_link_sends_to_master) {
162 frame_buffer_t data;
163 data.data = {0xAB, 0x70, 0x55, 0xBB};
164 activate_router(1);
165 router_send_frame(0, (uint8_t*)&data, 4);
166 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
167 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
168
169 EXPECT_CALL(*this, transport_recv_frame(1, _, _))
170 .With(Args<1, 2>(ElementsAreArray(data.data)));
171 simulate_transport(1, 0);
172 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
173 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
174}
175
176TEST_F(FrameRouter, second_link_sends_to_master) {
177 frame_buffer_t data;
178 data.data = {0xAB, 0x70, 0x55, 0xBB};
179 activate_router(2);
180 router_send_frame(0, (uint8_t*)&data, 4);
181 EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0);
182 EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
183
184 simulate_transport(2, 1);
185 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
186 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
187
188 EXPECT_CALL(*this, transport_recv_frame(2, _, _))
189 .With(Args<1, 2>(ElementsAreArray(data.data)));
190 simulate_transport(1, 0);
191 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
192 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
193}
194
195TEST_F(FrameRouter, master_sends_to_master_does_nothing) {
196 frame_buffer_t data;
197 data.data = {0xAB, 0x70, 0x55, 0xBB};
198 activate_router(0);
199 router_send_frame(0, (uint8_t*)&data, 4);
200 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
201 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
202}
203
204TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) {
205 frame_buffer_t data;
206 data.data = {0xAB, 0x70, 0x55, 0xBB};
207 activate_router(1);
208 router_send_frame(2, (uint8_t*)&data, 4);
209 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
210 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
211}
212
213TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) {
214 frame_buffer_t data;
215 data.data = {0xAB, 0x70, 0x55, 0xBB};
216 activate_router(1);
217 router_send_frame(0, (uint8_t*)&data, 4);
218 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
219 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
220
221 EXPECT_CALL(*this, transport_recv_frame(_, _, _))
222 .Times(0);
223 activate_router(0);
224 receive_data(UP_LINK,
225 router_buffers[1].send_buffers[UP_LINK].data(),
226 router_buffers[1].send_buffers[UP_LINK].size());
227 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
228 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
229}
diff --git a/quantum/serial_link/tests/frame_validator_tests.c b/quantum/serial_link/tests/frame_validator_tests.cpp
index d20947e2c..9223af83b 100644
--- a/quantum/serial_link/tests/frame_validator_tests.c
+++ b/quantum/serial_link/tests/frame_validator_tests.cpp
@@ -22,24 +22,47 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE. 22SOFTWARE.
23*/ 23*/
24 24
25#include <cgreen/cgreen.h> 25#include "gtest/gtest.h"
26#include <cgreen/mocks.h> 26#include "gmock/gmock.h"
27#include "serial_link/protocol/frame_validator.c" 27extern "C" {
28#include "serial_link/protocol/frame_validator.h"
29}
30
31using testing::_;
32using testing::ElementsAreArray;
33using testing::Args;
34
35class FrameValidator : public testing::Test {
36public:
37 FrameValidator() {
38 Instance = this;
39 }
40
41 ~FrameValidator() {
42 Instance = nullptr;
43 }
44
45 MOCK_METHOD3(route_incoming_frame, void (uint8_t link, uint8_t* data, uint16_t size));
46 MOCK_METHOD3(byte_stuffer_send_frame, void (uint8_t link, uint8_t* data, uint16_t size));
28 47
48 static FrameValidator* Instance;
49};
50
51FrameValidator* FrameValidator::Instance = nullptr;
52
53extern "C" {
29void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { 54void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) {
30 mock(data, size); 55 FrameValidator::Instance->route_incoming_frame(link, data, size);
31} 56}
32 57
33void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { 58void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
34 mock(data, size); 59 FrameValidator::Instance->byte_stuffer_send_frame(link, data, size);
60}
35} 61}
36 62
37Describe(FrameValidator); 63TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) {
38BeforeEach(FrameValidator) {} 64 EXPECT_CALL(*this, route_incoming_frame(_, _, _))
39AfterEach(FrameValidator) {} 65 .Times(0);
40
41Ensure(FrameValidator, doesnt_validate_frames_under_5_bytes) {
42 never_expect(route_incoming_frame);
43 uint8_t data[] = {1, 2}; 66 uint8_t data[] = {1, 2};
44 validator_recv_frame(0, 0, 1); 67 validator_recv_frame(0, 0, 1);
45 validator_recv_frame(0, data, 2); 68 validator_recv_frame(0, data, 2);
@@ -47,55 +70,46 @@ Ensure(FrameValidator, doesnt_validate_frames_under_5_bytes) {
47 validator_recv_frame(0, data, 4); 70 validator_recv_frame(0, data, 4);
48} 71}
49 72
50Ensure(FrameValidator, validates_one_byte_frame_with_correct_crc) { 73TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) {
51 uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; 74 uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
52 expect(route_incoming_frame, 75 EXPECT_CALL(*this, route_incoming_frame(_, _, _))
53 when(size, is_equal_to(1)), 76 .With(Args<1, 2>(ElementsAreArray(data, 1)));
54 when(data, is_equal_to_contents_of(data, 1))
55 );
56 validator_recv_frame(0, data, 5); 77 validator_recv_frame(0, data, 5);
57} 78}
58 79
59Ensure(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) { 80TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
60 uint8_t data[] = {0x44, 0, 0, 0, 0}; 81 uint8_t data[] = {0x44, 0, 0, 0, 0};
61 never_expect(route_incoming_frame); 82 EXPECT_CALL(*this, route_incoming_frame(_, _, _))
83 .Times(0);
62 validator_recv_frame(1, data, 5); 84 validator_recv_frame(1, data, 5);
63} 85}
64 86
65Ensure(FrameValidator, validates_four_byte_frame_with_correct_crc) { 87TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) {
66 uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA}; 88 uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA};
67 expect(route_incoming_frame, 89 EXPECT_CALL(*this, route_incoming_frame(_, _, _))
68 when(size, is_equal_to(4)), 90 .With(Args<1, 2>(ElementsAreArray(data, 4)));
69 when(data, is_equal_to_contents_of(data, 4))
70 );
71 validator_recv_frame(1, data, 8); 91 validator_recv_frame(1, data, 8);
72} 92}
73 93
74Ensure(FrameValidator, validates_five_byte_frame_with_correct_crc) { 94TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) {
75 uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; 95 uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
76 expect(route_incoming_frame, 96 EXPECT_CALL(*this, route_incoming_frame(_, _, _))
77 when(size, is_equal_to(5)), 97 .With(Args<1, 2>(ElementsAreArray(data, 5)));
78 when(data, is_equal_to_contents_of(data, 5))
79 );
80 validator_recv_frame(0, data, 9); 98 validator_recv_frame(0, data, 9);
81} 99}
82 100
83Ensure(FrameValidator, sends_one_byte_with_correct_crc) { 101TEST_F(FrameValidator, sends_one_byte_with_correct_crc) {
84 uint8_t original[] = {0x44, 0, 0, 0, 0}; 102 uint8_t original[] = {0x44, 0, 0, 0, 0};
85 uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3}; 103 uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
86 expect(byte_stuffer_send_frame, 104 EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _))
87 when(size, is_equal_to(sizeof(expected))), 105 .With(Args<1, 2>(ElementsAreArray(expected)));
88 when(data, is_equal_to_contents_of(expected, sizeof(expected)))
89 );
90 validator_send_frame(0, original, 1); 106 validator_send_frame(0, original, 1);
91} 107}
92 108
93Ensure(FrameValidator, sends_five_bytes_with_correct_crc) { 109TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) {
94 uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0}; 110 uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
95 uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47}; 111 uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
96 expect(byte_stuffer_send_frame, 112 EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _))
97 when(size, is_equal_to(sizeof(expected))), 113 .With(Args<1, 2>(ElementsAreArray(expected)));
98 when(data, is_equal_to_contents_of(expected, sizeof(expected)))
99 );
100 validator_send_frame(0, original, 5); 114 validator_send_frame(0, original, 5);
101} 115}
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
new file mode 100644
index 000000000..b81515bc5
--- /dev/null
+++ b/quantum/serial_link/tests/rules.mk
@@ -0,0 +1,22 @@
1serial_link_byte_stuffer_SRC :=\
2 $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \
3 $(SERIAL_PATH)/protocol/byte_stuffer.c
4
5serial_link_frame_validator_SRC := \
6 $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
7 $(SERIAL_PATH)/protocol/frame_validator.c
8
9serial_link_frame_router_SRC := \
10 $(SERIAL_PATH)/tests/frame_router_tests.cpp \
11 $(SERIAL_PATH)/protocol/byte_stuffer.c \
12 $(SERIAL_PATH)/protocol/frame_validator.c \
13 $(SERIAL_PATH)/protocol/frame_router.c
14
15serial_link_triple_buffered_object_SRC := \
16 $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \
17 $(SERIAL_PATH)/protocol/triple_buffered_object.c
18
19serial_link_transport_SRC := \
20 $(SERIAL_PATH)/tests/transport_tests.cpp \
21 $(SERIAL_PATH)/protocol/transport.c \
22 $(SERIAL_PATH)/protocol/triple_buffered_object.c
diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk
new file mode 100644
index 000000000..a80e88884
--- /dev/null
+++ b/quantum/serial_link/tests/testlist.mk
@@ -0,0 +1,6 @@
1TEST_LIST +=\
2 serial_link_byte_stuffer\
3 serial_link_frame_validator\
4 serial_link_frame_router\
5 serial_link_triple_buffered_object\
6 serial_link_transport \ No newline at end of file
diff --git a/quantum/serial_link/tests/transport_tests.c b/quantum/serial_link/tests/transport_tests.c
deleted file mode 100644
index 358e1b9fd..000000000
--- a/quantum/serial_link/tests/transport_tests.c
+++ /dev/null
@@ -1,168 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include <cgreen/cgreen.h>
26#include <cgreen/mocks.h>
27#include "serial_link/protocol/transport.c"
28#include "serial_link/protocol/triple_buffered_object.c"
29
30void signal_data_written(void) {
31 mock();
32}
33
34static uint8_t sent_data[2048];
35static uint16_t sent_data_size;
36
37void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
38 mock(destination);
39 memcpy(sent_data + sent_data_size, data, size);
40 sent_data_size += size;
41}
42
43typedef struct {
44 uint32_t test;
45} test_object1_t;
46
47typedef struct {
48 uint32_t test1;
49 uint32_t test2;
50} test_object2_t;
51
52MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1_t);
53MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1_t);
54SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1_t);
55
56static remote_object_t* test_remote_objects[] = {
57 REMOTE_OBJECT(master_to_slave),
58 REMOTE_OBJECT(master_to_single_slave),
59 REMOTE_OBJECT(slave_to_master),
60};
61
62Describe(Transport);
63BeforeEach(Transport) {
64 add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
65 sent_data_size = 0;
66}
67AfterEach(Transport) {}
68
69Ensure(Transport, write_to_local_signals_an_event) {
70 begin_write_master_to_slave();
71 expect(signal_data_written);
72 end_write_master_to_slave();
73 begin_write_slave_to_master();
74 expect(signal_data_written);
75 end_write_slave_to_master();
76 begin_write_master_to_single_slave(1);
77 expect(signal_data_written);
78 end_write_master_to_single_slave(1);
79}
80
81Ensure(Transport, writes_from_master_to_all_slaves) {
82 update_transport();
83 test_object1_t* obj = begin_write_master_to_slave();
84 obj->test = 5;
85 expect(signal_data_written);
86 end_write_master_to_slave();
87 expect(router_send_frame,
88 when(destination, is_equal_to(0xFF)));
89 update_transport();
90 transport_recv_frame(0, sent_data, sent_data_size);
91 test_object1_t* obj2 = read_master_to_slave();
92 assert_that(obj2, is_not_equal_to(NULL));
93 assert_that(obj2->test, is_equal_to(5));
94}
95
96Ensure(Transport, writes_from_slave_to_master) {
97 update_transport();
98 test_object1_t* obj = begin_write_slave_to_master();
99 obj->test = 7;
100 expect(signal_data_written);
101 end_write_slave_to_master();
102 expect(router_send_frame,
103 when(destination, is_equal_to(0)));
104 update_transport();
105 transport_recv_frame(3, sent_data, sent_data_size);
106 test_object1_t* obj2 = read_slave_to_master(2);
107 assert_that(read_slave_to_master(0), is_equal_to(NULL));
108 assert_that(obj2, is_not_equal_to(NULL));
109 assert_that(obj2->test, is_equal_to(7));
110}
111
112Ensure(Transport, writes_from_master_to_single_slave) {
113 update_transport();
114 test_object1_t* obj = begin_write_master_to_single_slave(3);
115 obj->test = 7;
116 expect(signal_data_written);
117 end_write_master_to_single_slave(3);
118 expect(router_send_frame,
119 when(destination, is_equal_to(4)));
120 update_transport();
121 transport_recv_frame(0, sent_data, sent_data_size);
122 test_object1_t* obj2 = read_master_to_single_slave();
123 assert_that(obj2, is_not_equal_to(NULL));
124 assert_that(obj2->test, is_equal_to(7));
125}
126
127Ensure(Transport, ignores_object_with_invalid_id) {
128 update_transport();
129 test_object1_t* obj = begin_write_master_to_single_slave(3);
130 obj->test = 7;
131 expect(signal_data_written);
132 end_write_master_to_single_slave(3);
133 expect(router_send_frame,
134 when(destination, is_equal_to(4)));
135 update_transport();
136 sent_data[sent_data_size - 1] = 44;
137 transport_recv_frame(0, sent_data, sent_data_size);
138 test_object1_t* obj2 = read_master_to_single_slave();
139 assert_that(obj2, is_equal_to(NULL));
140}
141
142Ensure(Transport, ignores_object_with_size_too_small) {
143 update_transport();
144 test_object1_t* obj = begin_write_master_to_slave();
145 obj->test = 7;
146 expect(signal_data_written);
147 end_write_master_to_slave();
148 expect(router_send_frame);
149 update_transport();
150 sent_data[sent_data_size - 2] = 0;
151 transport_recv_frame(0, sent_data, sent_data_size - 1);
152 test_object1_t* obj2 = read_master_to_slave();
153 assert_that(obj2, is_equal_to(NULL));
154}
155
156Ensure(Transport, ignores_object_with_size_too_big) {
157 update_transport();
158 test_object1_t* obj = begin_write_master_to_slave();
159 obj->test = 7;
160 expect(signal_data_written);
161 end_write_master_to_slave();
162 expect(router_send_frame);
163 update_transport();
164 sent_data[sent_data_size + 21] = 0;
165 transport_recv_frame(0, sent_data, sent_data_size + 22);
166 test_object1_t* obj2 = read_master_to_slave();
167 assert_that(obj2, is_equal_to(NULL));
168}
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
new file mode 100644
index 000000000..21b7b165f
--- /dev/null
+++ b/quantum/serial_link/tests/transport_tests.cpp
@@ -0,0 +1,188 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27
28using testing::_;
29using testing::ElementsAreArray;
30using testing::Args;
31
32extern "C" {
33#include "serial_link/protocol/transport.h"
34}
35
36struct test_object1 {
37 uint32_t test;
38};
39
40struct test_object2 {
41 uint32_t test1;
42 uint32_t test2;
43};
44
45MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
46MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
47SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
48
49static remote_object_t* test_remote_objects[] = {
50 REMOTE_OBJECT(master_to_slave),
51 REMOTE_OBJECT(master_to_single_slave),
52 REMOTE_OBJECT(slave_to_master),
53};
54
55class Transport : public testing::Test {
56public:
57 Transport() {
58 Instance = this;
59 add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
60 }
61
62 ~Transport() {
63 Instance = nullptr;
64 reinitialize_serial_link_transport();
65 }
66
67 MOCK_METHOD0(signal_data_written, void ());
68 MOCK_METHOD1(router_send_frame, void (uint8_t destination));
69
70 void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
71 router_send_frame(destination);
72 std::copy(data, data + size, std::back_inserter(sent_data));
73 }
74
75 static Transport* Instance;
76
77 std::vector<uint8_t> sent_data;
78};
79
80Transport* Transport::Instance = nullptr;
81
82extern "C" {
83void signal_data_written(void) {
84 Transport::Instance->signal_data_written();
85}
86
87void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
88 Transport::Instance->router_send_frame(destination, data, size);
89}
90}
91
92TEST_F(Transport, write_to_local_signals_an_event) {
93 begin_write_master_to_slave();
94 EXPECT_CALL(*this, signal_data_written());
95 end_write_master_to_slave();
96 begin_write_slave_to_master();
97 EXPECT_CALL(*this, signal_data_written());
98 end_write_slave_to_master();
99 begin_write_master_to_single_slave(1);
100 EXPECT_CALL(*this, signal_data_written());
101 end_write_master_to_single_slave(1);
102}
103
104TEST_F(Transport, writes_from_master_to_all_slaves) {
105 update_transport();
106 test_object1* obj = begin_write_master_to_slave();
107 obj->test = 5;
108 EXPECT_CALL(*this, signal_data_written());
109 end_write_master_to_slave();
110 EXPECT_CALL(*this, router_send_frame(0xFF));
111 update_transport();
112 transport_recv_frame(0, sent_data.data(), sent_data.size());
113 test_object1* obj2 = read_master_to_slave();
114 EXPECT_NE(obj2, nullptr);
115 EXPECT_EQ(obj2->test, 5);
116}
117
118TEST_F(Transport, writes_from_slave_to_master) {
119 update_transport();
120 test_object1* obj = begin_write_slave_to_master();
121 obj->test = 7;
122 EXPECT_CALL(*this, signal_data_written());
123 end_write_slave_to_master();
124 EXPECT_CALL(*this, router_send_frame(0));
125 update_transport();
126 transport_recv_frame(3, sent_data.data(), sent_data.size());
127 test_object1* obj2 = read_slave_to_master(2);
128 EXPECT_EQ(read_slave_to_master(0), nullptr);
129 EXPECT_NE(obj2, nullptr);
130 EXPECT_EQ(obj2->test, 7);
131}
132
133TEST_F(Transport, writes_from_master_to_single_slave) {
134 update_transport();
135 test_object1* obj = begin_write_master_to_single_slave(3);
136 obj->test = 7;
137 EXPECT_CALL(*this, signal_data_written());
138 end_write_master_to_single_slave(3);
139 EXPECT_CALL(*this, router_send_frame(4));
140 update_transport();
141 transport_recv_frame(0, sent_data.data(), sent_data.size());
142 test_object1* obj2 = read_master_to_single_slave();
143 EXPECT_NE(obj2, nullptr);
144 EXPECT_EQ(obj2->test, 7);
145}
146
147TEST_F(Transport, ignores_object_with_invalid_id) {
148 update_transport();
149 test_object1* obj = begin_write_master_to_single_slave(3);
150 obj->test = 7;
151 EXPECT_CALL(*this, signal_data_written());
152 end_write_master_to_single_slave(3);
153 EXPECT_CALL(*this, router_send_frame(4));
154 update_transport();
155 sent_data[sent_data.size() - 1] = 44;
156 transport_recv_frame(0, sent_data.data(), sent_data.size());
157 test_object1* obj2 = read_master_to_single_slave();
158 EXPECT_EQ(obj2, nullptr);
159}
160
161TEST_F(Transport, ignores_object_with_size_too_small) {
162 update_transport();
163 test_object1* obj = begin_write_master_to_slave();
164 obj->test = 7;
165 EXPECT_CALL(*this, signal_data_written());
166 end_write_master_to_slave();
167 EXPECT_CALL(*this, router_send_frame(_));
168 update_transport();
169 sent_data[sent_data.size() - 2] = 0;
170 transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
171 test_object1* obj2 = read_master_to_slave();
172 EXPECT_EQ(obj2, nullptr);
173}
174
175TEST_F(Transport, ignores_object_with_size_too_big) {
176 update_transport();
177 test_object1* obj = begin_write_master_to_slave();
178 obj->test = 7;
179 EXPECT_CALL(*this, signal_data_written());
180 end_write_master_to_slave();
181 EXPECT_CALL(*this, router_send_frame(_));
182 update_transport();
183 sent_data.resize(sent_data.size() + 22);
184 sent_data[sent_data.size() - 1] = 0;
185 transport_recv_frame(0, sent_data.data(), sent_data.size());
186 test_object1* obj2 = read_master_to_slave();
187 EXPECT_EQ(obj2, nullptr);
188}
diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.c b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
index 6f7c82b46..7724bbee9 100644
--- a/quantum/serial_link/tests/triple_buffered_object_tests.c
+++ b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
@@ -22,53 +22,55 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE. 22SOFTWARE.
23*/ 23*/
24 24
25#include <cgreen/cgreen.h> 25#include "gtest/gtest.h"
26#include "serial_link/protocol/triple_buffered_object.c" 26extern "C" {
27#include "serial_link/protocol/triple_buffered_object.h"
28}
27 29
28typedef struct { 30struct test_object{
29 uint8_t state; 31 uint8_t state;
30 uint32_t buffer[3]; 32 uint32_t buffer[3];
31}test_object_t; 33};
32
33test_object_t test_object;
34 34
35Describe(TripleBufferedObject); 35test_object test_object;
36BeforeEach(TripleBufferedObject) {
37 triple_buffer_init((triple_buffer_object_t*)&test_object);
38}
39AfterEach(TripleBufferedObject) {}
40 36
37class TripleBufferedObject : public testing::Test {
38public:
39 TripleBufferedObject() {
40 triple_buffer_init((triple_buffer_object_t*)&test_object);
41 }
42};
41 43
42Ensure(TripleBufferedObject, writes_and_reads_object) { 44TEST_F(TripleBufferedObject, writes_and_reads_object) {
43 *triple_buffer_begin_write(&test_object) = 0x3456ABCC; 45 *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
44 triple_buffer_end_write(&test_object); 46 triple_buffer_end_write(&test_object);
45 assert_that(*triple_buffer_read(&test_object), is_equal_to(0x3456ABCC)); 47 EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC);
46} 48}
47 49
48Ensure(TripleBufferedObject, does_not_read_empty) { 50TEST_F(TripleBufferedObject, does_not_read_empty) {
49 assert_that(triple_buffer_read(&test_object), is_equal_to(NULL)); 51 EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
50} 52}
51 53
52Ensure(TripleBufferedObject, writes_twice_and_reads_object) { 54TEST_F(TripleBufferedObject, writes_twice_and_reads_object) {
53 *triple_buffer_begin_write(&test_object) = 0x3456ABCC; 55 *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
54 triple_buffer_end_write(&test_object); 56 triple_buffer_end_write(&test_object);
55 *triple_buffer_begin_write(&test_object) = 0x44778899; 57 *triple_buffer_begin_write(&test_object) = 0x44778899;
56 triple_buffer_end_write(&test_object); 58 triple_buffer_end_write(&test_object);
57 assert_that(*triple_buffer_read(&test_object), is_equal_to(0x44778899)); 59 EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899);
58} 60}
59 61
60Ensure(TripleBufferedObject, performs_another_write_in_the_middle_of_read) { 62TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
61 *triple_buffer_begin_write(&test_object) = 1; 63 *triple_buffer_begin_write(&test_object) = 1;
62 triple_buffer_end_write(&test_object); 64 triple_buffer_end_write(&test_object);
63 uint32_t* read = triple_buffer_read(&test_object); 65 uint32_t* read = triple_buffer_read(&test_object);
64 *triple_buffer_begin_write(&test_object) = 2; 66 *triple_buffer_begin_write(&test_object) = 2;
65 triple_buffer_end_write(&test_object); 67 triple_buffer_end_write(&test_object);
66 assert_that(*read, is_equal_to(1)); 68 EXPECT_EQ(*read, 1);
67 assert_that(*triple_buffer_read(&test_object), is_equal_to(2)); 69 EXPECT_EQ(*triple_buffer_read(&test_object), 2);
68 assert_that(triple_buffer_read(&test_object), is_equal_to(NULL)); 70 EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
69} 71}
70 72
71Ensure(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) { 73TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
72 *triple_buffer_begin_write(&test_object) = 1; 74 *triple_buffer_begin_write(&test_object) = 1;
73 triple_buffer_end_write(&test_object); 75 triple_buffer_end_write(&test_object);
74 uint32_t* read = triple_buffer_read(&test_object); 76 uint32_t* read = triple_buffer_read(&test_object);
@@ -76,7 +78,7 @@ Ensure(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
76 triple_buffer_end_write(&test_object); 78 triple_buffer_end_write(&test_object);
77 *triple_buffer_begin_write(&test_object) = 3; 79 *triple_buffer_begin_write(&test_object) = 3;
78 triple_buffer_end_write(&test_object); 80 triple_buffer_end_write(&test_object);
79 assert_that(*read, is_equal_to(1)); 81 EXPECT_EQ(*read, 1);
80 assert_that(*triple_buffer_read(&test_object), is_equal_to(3)); 82 EXPECT_EQ(*triple_buffer_read(&test_object), 3);
81 assert_that(triple_buffer_read(&test_object), is_equal_to(NULL)); 83 EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
82} 84}
diff --git a/quantum/template/Makefile b/quantum/template/Makefile
index 3f6d133c9..4e2a6f00f 100644
--- a/quantum/template/Makefile
+++ b/quantum/template/Makefile
@@ -1,75 +1,3 @@
1 1ifndef MAKEFILE_INCLUDED
2
3# MCU name
4#MCU = at90usb1287
5MCU = atmega32u4
6
7# Processor frequency.
8# This will define a symbol, F_CPU, in all source code files equal to the
9# processor frequency in Hz. You can then use this symbol in your source code to
10# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
11# automatically to create a 32-bit value in your source code.
12#
13# This will be an integer division of F_USB below, as it is sourced by
14# F_USB after it has run through any CPU prescalers. Note that this value
15# does not *change* the processor frequency - it should merely be updated to
16# reflect the processor speed set externally so that the code can use accurate
17# software delays.
18F_CPU = 16000000
19
20
21#
22# LUFA specific
23#
24# Target architecture (see library "Board Types" documentation).
25ARCH = AVR8
26
27# Input clock frequency.
28# This will define a symbol, F_USB, in all source code files equal to the
29# input clock frequency (before any prescaling is performed) in Hz. This value may
30# differ from F_CPU if prescaling is used on the latter, and is required as the
31# raw input clock is fed directly to the PLL sections of the AVR for high speed
32# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
33# at the end, this will be done automatically to create a 32-bit value in your
34# source code.
35#
36# If no clock division is performed on the input clock inside the AVR (via the
37# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
38F_USB = $(F_CPU)
39
40# Interrupt driven control endpoint task(+60)
41OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
42
43
44# Boot Section Size in *bytes*
45# Teensy halfKay 512
46# Teensy++ halfKay 1024
47# Atmel DFU loader 4096
48# LUFA bootloader 4096
49# USBaspLoader 2048
50OPT_DEFS += -DBOOTLOADER_SIZE=512
51
52
53# Build Options
54# change yes to no to disable
55#
56BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
57MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
58EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
59CONSOLE_ENABLE ?= yes # Console for debug(+400)
60COMMAND_ENABLE ?= yes # Commands for debug and configuration
61# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
62SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
63# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
64NKRO_ENABLE ?= no # USB Nkey Rollover
65BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
66MIDI_ENABLE ?= no # MIDI controls
67UNICODE_ENABLE ?= no # Unicode
68BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
69AUDIO_ENABLE ?= no # Audio output on port C6
70
71ifndef QUANTUM_DIR
72 include ../../Makefile 2 include ../../Makefile
73endif 3endif \ No newline at end of file
74
75
diff --git a/quantum/template/readme.md b/quantum/template/readme.md
index b2fb4dd98..b16f4cd76 100644
--- a/quantum/template/readme.md
+++ b/quantum/template/readme.md
@@ -3,7 +3,7 @@
3 3
4## Quantum MK Firmware 4## Quantum MK Firmware
5 5
6For the full Quantum feature list, see [the parent readme.md](/doc/readme.md). 6For the full Quantum feature list, see [the parent readme](/).
7 7
8## Building 8## Building
9 9
@@ -13,16 +13,16 @@ Depending on which keymap you would like to use, you will have to compile slight
13 13
14### Default 14### Default
15 15
16To build with the default keymap, simply run `make`. 16To build with the default keymap, simply run `make default`.
17 17
18### Other Keymaps 18### Other Keymaps
19 19
20Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a folder with the name of your keymap in the keymaps folder, and see keymap documentation (you can find in top readme.md) and existant keymap files. 20Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a folder with the name of your keymap in the keymaps folder, and see keymap documentation (you can find in top readme.md) and existant keymap files.
21 21
22To build the firmware binary hex file with a keymap just do `make` with `keymap` option like: 22To build the firmware binary hex file with a keymap just do `make` with a keymap like this:
23 23
24``` 24```
25$ make keymap=[default|jack|<name>] 25$ make [default|jack|<name>]
26``` 26```
27 27
28Keymaps follow the format **__keymap.c__** and are stored in folders in the `keymaps` folder, eg `keymaps/my_keymap/` \ No newline at end of file 28Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/quantum/template/rules.mk b/quantum/template/rules.mk
new file mode 100644
index 000000000..55898147d
--- /dev/null
+++ b/quantum/template/rules.mk
@@ -0,0 +1,67 @@
1# MCU name
2#MCU = at90usb1287
3MCU = atmega32u4
4
5# Processor frequency.
6# This will define a symbol, F_CPU, in all source code files equal to the
7# processor frequency in Hz. You can then use this symbol in your source code to
8# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
9# automatically to create a 32-bit value in your source code.
10#
11# This will be an integer division of F_USB below, as it is sourced by
12# F_USB after it has run through any CPU prescalers. Note that this value
13# does not *change* the processor frequency - it should merely be updated to
14# reflect the processor speed set externally so that the code can use accurate
15# software delays.
16F_CPU = 16000000
17
18
19#
20# LUFA specific
21#
22# Target architecture (see library "Board Types" documentation).
23ARCH = AVR8
24
25# Input clock frequency.
26# This will define a symbol, F_USB, in all source code files equal to the
27# input clock frequency (before any prescaling is performed) in Hz. This value may
28# differ from F_CPU if prescaling is used on the latter, and is required as the
29# raw input clock is fed directly to the PLL sections of the AVR for high speed
30# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
31# at the end, this will be done automatically to create a 32-bit value in your
32# source code.
33#
34# If no clock division is performed on the input clock inside the AVR (via the
35# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
36F_USB = $(F_CPU)
37
38# Interrupt driven control endpoint task(+60)
39OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
40
41
42# Boot Section Size in *bytes*
43# Teensy halfKay 512
44# Teensy++ halfKay 1024
45# Atmel DFU loader 4096
46# LUFA bootloader 4096
47# USBaspLoader 2048
48OPT_DEFS += -DBOOTLOADER_SIZE=512
49
50
51# Build Options
52# change yes to no to disable
53#
54BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
55MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
56EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
57CONSOLE_ENABLE ?= yes # Console for debug(+400)
58COMMAND_ENABLE ?= yes # Commands for debug and configuration
59# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
60SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
61# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
62NKRO_ENABLE ?= no # USB Nkey Rollover
63BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
64MIDI_ENABLE ?= no # MIDI controls
65UNICODE_ENABLE ?= no # Unicode
66BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
67AUDIO_ENABLE ?= no # Audio output on port C6