diff options
author | Jason Janse van Rensburg <l33tjas.0n@gmail.com> | 2016-08-30 14:54:00 +0200 |
---|---|---|
committer | Jason Janse van Rensburg <l33tjas.0n@gmail.com> | 2016-08-30 14:54:00 +0200 |
commit | fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50 (patch) | |
tree | 59b2f2406f472a9fd2af4946420d1a1c880929c0 /quantum | |
parent | a41a7a9100b9f4c6bfdf49b39b05e626ffd95397 (diff) | |
parent | 8e00c464e6f488d86e0768a77a2ad5ee238dba6d (diff) | |
download | qmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.tar.gz qmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.zip |
Merge branch 'master'
Conflicts:
keyboards/planck/keymaps/bone2planck/keymap.c
Diffstat (limited to 'quantum')
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 | */ | ||
19 | enum 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. */ | ||
27 | void 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 | */ | ||
40 | void 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 | */ | ||
57 | void 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 | */ | ||
83 | void 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 | */ | ||
103 | void 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 | */ | ||
120 | bool 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 | * ¯o_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(¯o_pointer, macro_buffer); | ||
174 | macro_id = 1; | ||
175 | return false; | ||
176 | case DYN_REC_START2: | ||
177 | dynamic_macro_record_start(¯o_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, ¯o_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(¯o_pointer, r_macro_end, +1, record); | ||
213 | break; | ||
214 | case 2: | ||
215 | dynamic_macro_record_key(¯o_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 | ||
3 | static qk_tap_dance_state_t qk_tap_dance_state; | 4 | static uint16_t last_td; |
5 | static int8_t highest_td = -1; | ||
4 | 6 | ||
5 | void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { | 7 | void 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 | ||
25 | static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, | 27 | static 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 | ||
34 | static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action) | 36 | static 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 | ||
39 | static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action) | 41 | static 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 | ||
44 | static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action) | 49 | static 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 | ||
49 | bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { | 54 | bool 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 | ||
93 | void matrix_scan_tap_dance () { | 106 | void 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 | ||
104 | void reset_tap_dance (qk_tap_dance_state_t *state) { | 120 | void 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 | ||
51 | extern const qk_tap_dance_action_t tap_dance_actions[]; | 53 | extern 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 | ||
16 | void set_unicode_mode(uint8_t os_target) | 16 | void 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)) | ||
22 | void 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)) | ||
45 | void 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 | |||
58 | void 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 | |||
21 | bool process_unicode(uint16_t keycode, keyrecord_t *record) { | 66 | bool 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); | 77 | qk_ucis_state_t qk_ucis_state; |
33 | break; | 78 | |
34 | case UC_WIN: | 79 | void 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)) | ||
87 | void qk_ucis_start_user(void) { | ||
88 | unicode_input_start(); | ||
89 | register_hex(0x2328); | ||
90 | unicode_input_finish(); | ||
91 | } | ||
92 | |||
93 | static 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)) | ||
112 | void 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 | |||
121 | void 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); | 149 | bool 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 | |||
11 | void set_unicode_input_mode(uint8_t os_target); | 15 | void set_unicode_input_mode(uint8_t os_target); |
16 | void unicode_input_start(void); | ||
17 | void unicode_input_finish(void); | ||
18 | void register_hex(uint16_t hex); | ||
12 | 19 | ||
13 | bool process_unicode(uint16_t keycode, keyrecord_t *record); | 20 | bool 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 | |||
27 | typedef struct { | ||
28 | char *symbol; | ||
29 | char *code; | ||
30 | } qk_ucis_symbol_t; | ||
31 | |||
32 | typedef struct { | ||
33 | uint8_t count; | ||
34 | uint16_t codes[UCIS_MAX_SYMBOL_LENGTH]; | ||
35 | bool in_progress:1; | ||
36 | } qk_ucis_state_t; | ||
37 | |||
38 | extern 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 | |||
43 | extern const qk_ucis_symbol_t ucis_symbol_table[]; | ||
44 | |||
45 | void qk_ucis_start(void); | ||
46 | void qk_ucis_start_user(void); | ||
47 | void qk_ucis_symbol_fallback (void); | ||
48 | void register_ucis(const char *hex); | ||
49 | bool 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 | ||
3 | static 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 | |||
30 | void register_code16 (uint16_t code) { | ||
31 | do_code16 (code, register_code); | ||
32 | register_code (code); | ||
33 | } | ||
34 | |||
35 | void unregister_code16 (uint16_t code) { | ||
36 | unregister_code (code); | ||
37 | do_code16 (code, unregister_code); | ||
38 | } | ||
39 | |||
3 | __attribute__ ((weak)) | 40 | __attribute__ ((weak)) |
4 | bool process_action_kb(keyrecord_t *record) { | 41 | bool 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 | ||
30 | extern uint32_t default_layer_state; | 31 | extern uint32_t default_layer_state; |
@@ -82,6 +83,9 @@ void reset_keyboard(void); | |||
82 | void startup_user(void); | 83 | void startup_user(void); |
83 | void shutdown_user(void); | 84 | void shutdown_user(void); |
84 | 85 | ||
86 | void register_code16 (uint16_t code); | ||
87 | void unregister_code16 (uint16_t code); | ||
88 | |||
85 | #ifdef BACKLIGHT_ENABLE | 89 | #ifdef BACKLIGHT_ENABLE |
86 | void backlight_init_ports(void); | 90 | void 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 | ||
9 | const uint8_t DIM_CURVE[] PROGMEM = { | 9 | const 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 | }; | ||
27 | const 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 | }; |
27 | const 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}; | ||
28 | const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | 45 | const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; |
29 | const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; | 46 | const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; |
30 | const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; | 47 | const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; |
@@ -38,63 +55,56 @@ uint8_t rgblight_inited = 0; | |||
38 | 55 | ||
39 | 56 | ||
40 | void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) { | 57 | void 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 | ||
100 | void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) { | 110 | void 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 | } |
113 | void eeconfig_update_rgblight_default(void) { | 123 | void 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 | } |
122 | void eeconfig_debug_rgblight(void) { | 132 | void 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 | ||
131 | void rgblight_init(void) { | 141 | void 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 | ||
158 | void rgblight_increase(void) { | 168 | void 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 | |||
166 | void rgblight_decrease(void) { | 175 | void 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 | |||
174 | void rgblight_step(void) { | 183 | void 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 | ||
183 | void rgblight_mode(uint8_t mode) { | 192 | void 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 | ||
231 | void rgblight_increase_hue(void){ | 239 | void 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 | } |
236 | void rgblight_decrease_hue(void){ | 244 | void 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 | } |
245 | void rgblight_increase_sat(void) { | 253 | void 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 | } |
254 | void rgblight_decrease_sat(void){ | 262 | void 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 | } |
263 | void rgblight_increase_val(void){ | 271 | void 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 | } |
272 | void rgblight_decrease_val(void) { | 280 | void 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 | ||
282 | void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val){ | 290 | void 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 | } |
294 | void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val){ | 302 | void 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 | ||
317 | void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b){ | 325 | void 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 | ||
328 | void rgblight_set(void) { | 335 | void 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 |
345 | void rgblight_timer_init(void) { | 351 | void 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 | } |
361 | void rgblight_timer_enable(void) { | 367 | void rgblight_timer_enable(void) { |
362 | TIMSK3 |= _BV(OCIE3A); | 368 | TIMSK3 |= _BV(OCIE3A); |
363 | dprintf("TIMER3 enabled.\n"); | 369 | dprintf("TIMER3 enabled.\n"); |
364 | } | 370 | } |
365 | void rgblight_timer_disable(void) { | 371 | void rgblight_timer_disable(void) { |
366 | TIMSK3 &= ~_BV(OCIE3A); | 372 | TIMSK3 &= ~_BV(OCIE3A); |
367 | dprintf("TIMER3 disabled.\n"); | 373 | dprintf("TIMER3 disabled.\n"); |
368 | } | 374 | } |
369 | void rgblight_timer_toggle(void) { | 375 | void 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 | ||
374 | ISR(TIMER3_COMPA_vect) { | 380 | ISR(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 | ||
392 | void rgblight_effect_breathing(uint8_t interval) { | 401 | void 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 | |||
403 | void rgblight_effect_rainbow_mood(uint8_t interval) { | 413 | void 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 | |||
413 | void rgblight_effect_rainbow_swirl(uint8_t interval) { | 424 | void 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 | } |
437 | void rgblight_effect_snake(uint8_t interval) { | 449 | void 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 | |||
471 | void rgblight_effect_knight(uint8_t interval) { | 487 | void 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 | |||
37 | typedef struct byte_stuffer_state { | 34 | typedef 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 | |||
30 | void init_byte_stuffer(void); | 33 | void init_byte_stuffer(void); |
31 | void byte_stuffer_recv_byte(uint8_t link, uint8_t data); | 34 | void byte_stuffer_recv_byte(uint8_t link, uint8_t data); |
32 | void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size); | 35 | void 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. | |||
31 | static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; | 31 | static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; |
32 | static uint32_t num_remote_objects = 0; | 32 | static uint32_t num_remote_objects = 0; |
33 | 33 | ||
34 | void reinitialize_serial_link_transport(void) { | ||
35 | num_remote_objects = 0; | ||
36 | } | ||
37 | |||
34 | void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) { | 38 | void 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 | ||
147 | void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); | 147 | void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); |
148 | void reinitialize_serial_link_transport(void); | ||
148 | void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); | 149 | void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); |
149 | void update_transport(void); | 150 | void 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 | |||
22 | SOFTWARE. | 22 | SOFTWARE. |
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> | ||
29 | extern "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 | ||
32 | static uint8_t sent_data[MAX_FRAME_SIZE*2]; | 35 | using testing::_; |
33 | static uint16_t sent_data_size; | 36 | using testing::ElementsAreArray; |
37 | using testing::Args; | ||
34 | 38 | ||
35 | Describe(ByteStuffer); | 39 | class ByteStuffer : public ::testing::Test{ |
36 | BeforeEach(ByteStuffer) { | 40 | public: |
37 | init_byte_stuffer(); | 41 | ByteStuffer() { |
38 | sent_data_size = 0; | 42 | Instance = this; |
39 | } | 43 | init_byte_stuffer(); |
40 | AfterEach(ByteStuffer) {} | 44 | } |
41 | 45 | ||
42 | void 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 | ||
46 | void 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 | |
60 | ByteStuffer* ByteStuffer::Instance = nullptr; | ||
61 | |||
62 | extern "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 | ||
51 | Ensure(ByteStuffer, receives_no_frame_for_a_single_zero_byte) { | 72 | TEST_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 | ||
56 | Ensure(ByteStuffer, receives_no_frame_for_a_single_FF_byte) { | 78 | TEST_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 | ||
61 | Ensure(ByteStuffer, receives_no_frame_for_a_single_random_byte) { | 84 | TEST_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 | ||
66 | Ensure(ByteStuffer, receives_no_frame_for_a_zero_length_frame) { | 90 | TEST_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 | ||
72 | Ensure(ByteStuffer, receives_single_byte_valid_frame) { | 97 | TEST_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 | 105 | TEST_F(ByteStuffer, receives_three_bytes_valid_frame) { | |
83 | Ensure(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 | ||
96 | Ensure(ByteStuffer, receives_single_zero_valid_frame) { | 116 | TEST_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 | ||
107 | Ensure(ByteStuffer, receives_valid_frame_with_zeroes) { | 125 | TEST_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 | ||
121 | Ensure(ByteStuffer, receives_two_valid_frames) { | 137 | |
138 | TEST_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 | ||
141 | Ensure(ByteStuffer, receives_valid_frame_after_unexpected_zero) { | 154 | TEST_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 | ||
156 | Ensure(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) { | 167 | TEST_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 | ||
172 | Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) { | 181 | TEST_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 | ||
189 | Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) { | 196 | TEST_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 | ||
209 | Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) { | 214 | TEST_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 | ||
229 | Ensure(ByteStuffer, receives_two_long_frames_and_some_more) { | 232 | TEST_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 | ||
264 | Ensure(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) { | 265 | TEST_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 | ||
278 | Ensure(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) { | 277 | TEST_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 | ||
290 | Ensure(ByteStuffer, received_frame_is_aborted_when_its_too_long) { | 290 | TEST_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 | ||
306 | Ensure(ByteStuffer, does_nothing_when_sending_zero_size_frame) { | 304 | TEST_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 | ||
311 | Ensure(ByteStuffer, send_one_byte_frame) { | 309 | TEST_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 | ||
319 | Ensure(ByteStuffer, sends_two_byte_frame) { | 316 | TEST_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 | ||
327 | Ensure(ByteStuffer, sends_one_byte_frame_with_zero) { | 323 | TEST_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 | ||
335 | Ensure(ByteStuffer, sends_two_byte_frame_starting_with_zero) { | 330 | TEST_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 | ||
343 | Ensure(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) { | 337 | TEST_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 | ||
351 | Ensure(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) { | 344 | TEST_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 | ||
359 | Ensure(ByteStuffer, sends_three_byte_frame_data_in_the_middle) { | 351 | TEST_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 | ||
367 | Ensure(ByteStuffer, sends_three_byte_frame_with_all_zeroes) { | 358 | TEST_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 | ||
375 | Ensure(ByteStuffer, sends_frame_with_254_non_zeroes) { | 365 | TEST_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 | ||
392 | Ensure(ByteStuffer, sends_frame_with_255_non_zeroes) { | 381 | TEST_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 | ||
411 | Ensure(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) { | 399 | TEST_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 | ||
431 | Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) { | 418 | TEST_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 | ||
444 | Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) { | 429 | TEST_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 | ||
457 | Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) { | 440 | TEST_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 | ||
473 | Ensure(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) { | 454 | TEST_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 | ||
491 | Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) { | 470 | TEST_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 | /* | ||
2 | The MIT License (MIT) | ||
3 | |||
4 | Copyright (c) 2016 Fred Sundvik | ||
5 | |||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | of this software and associated documentation files (the "Software"), to deal | ||
8 | in the Software without restriction, including without limitation the rights | ||
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | copies of the Software, and to permit persons to whom the Software is | ||
11 | furnished to do so, subject to the following conditions: | ||
12 | |||
13 | The above copyright notice and this permission notice shall be included in all | ||
14 | copies or substantial portions of the Software. | ||
15 | |||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | SOFTWARE. | ||
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 | |||
32 | static uint8_t received_data[256]; | ||
33 | static uint16_t received_data_size; | ||
34 | |||
35 | typedef struct { | ||
36 | uint8_t sent_data[256]; | ||
37 | uint16_t sent_data_size; | ||
38 | } receive_buffer_t; | ||
39 | |||
40 | typedef struct { | ||
41 | receive_buffer_t send_buffers[2]; | ||
42 | } router_buffer_t; | ||
43 | |||
44 | router_buffer_t router_buffers[8]; | ||
45 | |||
46 | router_buffer_t* current_router_buffer; | ||
47 | |||
48 | |||
49 | Describe(FrameRouter); | ||
50 | BeforeEach(FrameRouter) { | ||
51 | init_byte_stuffer(); | ||
52 | memset(router_buffers, 0, sizeof(router_buffers)); | ||
53 | current_router_buffer = 0; | ||
54 | } | ||
55 | AfterEach(FrameRouter) {} | ||
56 | |||
57 | typedef struct { | ||
58 | uint32_t data; | ||
59 | uint8_t extra[16]; | ||
60 | } frame_buffer_t; | ||
61 | |||
62 | |||
63 | void send_data(uint8_t link, const uint8_t* data, uint16_t size) { | ||
64 | receive_buffer_t* buffer = ¤t_router_buffer->send_buffers[link]; | ||
65 | memcpy(buffer->sent_data + buffer->sent_data_size, data, size); | ||
66 | buffer->sent_data_size += size; | ||
67 | } | ||
68 | |||
69 | static 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 | |||
76 | static void activate_router(uint8_t num) { | ||
77 | current_router_buffer = router_buffers + num; | ||
78 | router_set_master(num==0); | ||
79 | } | ||
80 | |||
81 | static 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 | |||
95 | void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { | ||
96 | mock(from, data, size); | ||
97 | } | ||
98 | |||
99 | |||
100 | Ensure(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 | |||
127 | Ensure(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 | |||
158 | Ensure(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 | |||
176 | Ensure(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 | |||
198 | Ensure(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 | |||
207 | Ensure(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 | |||
216 | Ensure(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 | /* | ||
2 | The MIT License (MIT) | ||
3 | |||
4 | Copyright (c) 2016 Fred Sundvik | ||
5 | |||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | of this software and associated documentation files (the "Software"), to deal | ||
8 | in the Software without restriction, including without limitation the rights | ||
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | copies of the Software, and to permit persons to whom the Software is | ||
11 | furnished to do so, subject to the following conditions: | ||
12 | |||
13 | The above copyright notice and this permission notice shall be included in all | ||
14 | copies or substantial portions of the Software. | ||
15 | |||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | SOFTWARE. | ||
23 | */ | ||
24 | |||
25 | #include "gtest/gtest.h" | ||
26 | #include "gmock/gmock.h" | ||
27 | #include <array> | ||
28 | extern "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 | |||
34 | using testing::_; | ||
35 | using testing::ElementsAreArray; | ||
36 | using testing::Args; | ||
37 | |||
38 | class FrameRouter : public testing::Test { | ||
39 | public: | ||
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 | |||
96 | FrameRouter* FrameRouter::Instance = nullptr; | ||
97 | |||
98 | |||
99 | typedef struct { | ||
100 | std::array<uint8_t, 4> data; | ||
101 | uint8_t extra[16]; | ||
102 | } frame_buffer_t; | ||
103 | |||
104 | |||
105 | extern "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 | |||
116 | TEST_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 | |||
136 | TEST_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 | |||
161 | TEST_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 | |||
176 | TEST_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 | |||
195 | TEST_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 | |||
204 | TEST_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 | |||
213 | TEST_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 | |||
22 | SOFTWARE. | 22 | SOFTWARE. |
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" | 27 | extern "C" { |
28 | #include "serial_link/protocol/frame_validator.h" | ||
29 | } | ||
30 | |||
31 | using testing::_; | ||
32 | using testing::ElementsAreArray; | ||
33 | using testing::Args; | ||
34 | |||
35 | class FrameValidator : public testing::Test { | ||
36 | public: | ||
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 | |||
51 | FrameValidator* FrameValidator::Instance = nullptr; | ||
52 | |||
53 | extern "C" { | ||
29 | void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { | 54 | void 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 | ||
33 | void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { | 58 | void 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 | ||
37 | Describe(FrameValidator); | 63 | TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) { |
38 | BeforeEach(FrameValidator) {} | 64 | EXPECT_CALL(*this, route_incoming_frame(_, _, _)) |
39 | AfterEach(FrameValidator) {} | 65 | .Times(0); |
40 | |||
41 | Ensure(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 | ||
50 | Ensure(FrameValidator, validates_one_byte_frame_with_correct_crc) { | 73 | TEST_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 | ||
59 | Ensure(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) { | 80 | TEST_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 | ||
65 | Ensure(FrameValidator, validates_four_byte_frame_with_correct_crc) { | 87 | TEST_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 | ||
74 | Ensure(FrameValidator, validates_five_byte_frame_with_correct_crc) { | 94 | TEST_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 | ||
83 | Ensure(FrameValidator, sends_one_byte_with_correct_crc) { | 101 | TEST_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 | ||
93 | Ensure(FrameValidator, sends_five_bytes_with_correct_crc) { | 109 | TEST_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 @@ | |||
1 | serial_link_byte_stuffer_SRC :=\ | ||
2 | $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \ | ||
3 | $(SERIAL_PATH)/protocol/byte_stuffer.c | ||
4 | |||
5 | serial_link_frame_validator_SRC := \ | ||
6 | $(SERIAL_PATH)/tests/frame_validator_tests.cpp \ | ||
7 | $(SERIAL_PATH)/protocol/frame_validator.c | ||
8 | |||
9 | serial_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 | |||
15 | serial_link_triple_buffered_object_SRC := \ | ||
16 | $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \ | ||
17 | $(SERIAL_PATH)/protocol/triple_buffered_object.c | ||
18 | |||
19 | serial_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 @@ | |||
1 | TEST_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 | /* | ||
2 | The MIT License (MIT) | ||
3 | |||
4 | Copyright (c) 2016 Fred Sundvik | ||
5 | |||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | of this software and associated documentation files (the "Software"), to deal | ||
8 | in the Software without restriction, including without limitation the rights | ||
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | copies of the Software, and to permit persons to whom the Software is | ||
11 | furnished to do so, subject to the following conditions: | ||
12 | |||
13 | The above copyright notice and this permission notice shall be included in all | ||
14 | copies or substantial portions of the Software. | ||
15 | |||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | SOFTWARE. | ||
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 | |||
30 | void signal_data_written(void) { | ||
31 | mock(); | ||
32 | } | ||
33 | |||
34 | static uint8_t sent_data[2048]; | ||
35 | static uint16_t sent_data_size; | ||
36 | |||
37 | void 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 | |||
43 | typedef struct { | ||
44 | uint32_t test; | ||
45 | } test_object1_t; | ||
46 | |||
47 | typedef struct { | ||
48 | uint32_t test1; | ||
49 | uint32_t test2; | ||
50 | } test_object2_t; | ||
51 | |||
52 | MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1_t); | ||
53 | MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1_t); | ||
54 | SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1_t); | ||
55 | |||
56 | static 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 | |||
62 | Describe(Transport); | ||
63 | BeforeEach(Transport) { | ||
64 | add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*)); | ||
65 | sent_data_size = 0; | ||
66 | } | ||
67 | AfterEach(Transport) {} | ||
68 | |||
69 | Ensure(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 | |||
81 | Ensure(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 | |||
96 | Ensure(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 | |||
112 | Ensure(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 | |||
127 | Ensure(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 | |||
142 | Ensure(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 | |||
156 | Ensure(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 | /* | ||
2 | The MIT License (MIT) | ||
3 | |||
4 | Copyright (c) 2016 Fred Sundvik | ||
5 | |||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | of this software and associated documentation files (the "Software"), to deal | ||
8 | in the Software without restriction, including without limitation the rights | ||
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | copies of the Software, and to permit persons to whom the Software is | ||
11 | furnished to do so, subject to the following conditions: | ||
12 | |||
13 | The above copyright notice and this permission notice shall be included in all | ||
14 | copies or substantial portions of the Software. | ||
15 | |||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | SOFTWARE. | ||
23 | */ | ||
24 | |||
25 | #include "gtest/gtest.h" | ||
26 | #include "gmock/gmock.h" | ||
27 | |||
28 | using testing::_; | ||
29 | using testing::ElementsAreArray; | ||
30 | using testing::Args; | ||
31 | |||
32 | extern "C" { | ||
33 | #include "serial_link/protocol/transport.h" | ||
34 | } | ||
35 | |||
36 | struct test_object1 { | ||
37 | uint32_t test; | ||
38 | }; | ||
39 | |||
40 | struct test_object2 { | ||
41 | uint32_t test1; | ||
42 | uint32_t test2; | ||
43 | }; | ||
44 | |||
45 | MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1); | ||
46 | MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1); | ||
47 | SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1); | ||
48 | |||
49 | static 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 | |||
55 | class Transport : public testing::Test { | ||
56 | public: | ||
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 | |||
80 | Transport* Transport::Instance = nullptr; | ||
81 | |||
82 | extern "C" { | ||
83 | void signal_data_written(void) { | ||
84 | Transport::Instance->signal_data_written(); | ||
85 | } | ||
86 | |||
87 | void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { | ||
88 | Transport::Instance->router_send_frame(destination, data, size); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | TEST_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 | |||
104 | TEST_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 | |||
118 | TEST_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 | |||
133 | TEST_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 | |||
147 | TEST_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 | |||
161 | TEST_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 | |||
175 | TEST_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 | |||
22 | SOFTWARE. | 22 | SOFTWARE. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <cgreen/cgreen.h> | 25 | #include "gtest/gtest.h" |
26 | #include "serial_link/protocol/triple_buffered_object.c" | 26 | extern "C" { |
27 | #include "serial_link/protocol/triple_buffered_object.h" | ||
28 | } | ||
27 | 29 | ||
28 | typedef struct { | 30 | struct 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 | |||
33 | test_object_t test_object; | ||
34 | 34 | ||
35 | Describe(TripleBufferedObject); | 35 | test_object test_object; |
36 | BeforeEach(TripleBufferedObject) { | ||
37 | triple_buffer_init((triple_buffer_object_t*)&test_object); | ||
38 | } | ||
39 | AfterEach(TripleBufferedObject) {} | ||
40 | 36 | ||
37 | class TripleBufferedObject : public testing::Test { | ||
38 | public: | ||
39 | TripleBufferedObject() { | ||
40 | triple_buffer_init((triple_buffer_object_t*)&test_object); | ||
41 | } | ||
42 | }; | ||
41 | 43 | ||
42 | Ensure(TripleBufferedObject, writes_and_reads_object) { | 44 | TEST_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 | ||
48 | Ensure(TripleBufferedObject, does_not_read_empty) { | 50 | TEST_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 | ||
52 | Ensure(TripleBufferedObject, writes_twice_and_reads_object) { | 54 | TEST_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 | ||
60 | Ensure(TripleBufferedObject, performs_another_write_in_the_middle_of_read) { | 62 | TEST_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 | ||
71 | Ensure(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) { | 73 | TEST_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 | 1 | ifndef MAKEFILE_INCLUDED | |
2 | |||
3 | # MCU name | ||
4 | #MCU = at90usb1287 | ||
5 | MCU = 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. | ||
18 | F_CPU = 16000000 | ||
19 | |||
20 | |||
21 | # | ||
22 | # LUFA specific | ||
23 | # | ||
24 | # Target architecture (see library "Board Types" documentation). | ||
25 | ARCH = 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. | ||
38 | F_USB = $(F_CPU) | ||
39 | |||
40 | # Interrupt driven control endpoint task(+60) | ||
41 | OPT_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 | ||
50 | OPT_DEFS += -DBOOTLOADER_SIZE=512 | ||
51 | |||
52 | |||
53 | # Build Options | ||
54 | # change yes to no to disable | ||
55 | # | ||
56 | BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000) | ||
57 | MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700) | ||
58 | EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450) | ||
59 | CONSOLE_ENABLE ?= yes # Console for debug(+400) | ||
60 | COMMAND_ENABLE ?= yes # Commands for debug and configuration | ||
61 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | ||
62 | SLEEP_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 | ||
64 | NKRO_ENABLE ?= no # USB Nkey Rollover | ||
65 | BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default | ||
66 | MIDI_ENABLE ?= no # MIDI controls | ||
67 | UNICODE_ENABLE ?= no # Unicode | ||
68 | BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID | ||
69 | AUDIO_ENABLE ?= no # Audio output on port C6 | ||
70 | |||
71 | ifndef QUANTUM_DIR | ||
72 | include ../../Makefile | 2 | include ../../Makefile |
73 | endif | 3 | endif \ 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 | ||
6 | For the full Quantum feature list, see [the parent readme.md](/doc/readme.md). | 6 | For 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 | ||
16 | To build with the default keymap, simply run `make`. | 16 | To build with the default keymap, simply run `make default`. |
17 | 17 | ||
18 | ### Other Keymaps | 18 | ### Other Keymaps |
19 | 19 | ||
20 | Several 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. | 20 | Several 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 | ||
22 | To build the firmware binary hex file with a keymap just do `make` with `keymap` option like: | 22 | To 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 | ||
28 | Keymaps follow the format **__keymap.c__** and are stored in folders in the `keymaps` folder, eg `keymaps/my_keymap/` \ No newline at end of file | 28 | Keymaps 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 | ||
3 | MCU = 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. | ||
16 | F_CPU = 16000000 | ||
17 | |||
18 | |||
19 | # | ||
20 | # LUFA specific | ||
21 | # | ||
22 | # Target architecture (see library "Board Types" documentation). | ||
23 | ARCH = 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. | ||
36 | F_USB = $(F_CPU) | ||
37 | |||
38 | # Interrupt driven control endpoint task(+60) | ||
39 | OPT_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 | ||
48 | OPT_DEFS += -DBOOTLOADER_SIZE=512 | ||
49 | |||
50 | |||
51 | # Build Options | ||
52 | # change yes to no to disable | ||
53 | # | ||
54 | BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000) | ||
55 | MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700) | ||
56 | EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450) | ||
57 | CONSOLE_ENABLE ?= yes # Console for debug(+400) | ||
58 | COMMAND_ENABLE ?= yes # Commands for debug and configuration | ||
59 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | ||
60 | SLEEP_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 | ||
62 | NKRO_ENABLE ?= no # USB Nkey Rollover | ||
63 | BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default | ||
64 | MIDI_ENABLE ?= no # MIDI controls | ||
65 | UNICODE_ENABLE ?= no # Unicode | ||
66 | BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID | ||
67 | AUDIO_ENABLE ?= no # Audio output on port C6 | ||