aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_test.mk1
-rw-r--r--common_features.mk13
-rw-r--r--disable_features.mk1
-rw-r--r--docs/unit_testing.md4
-rw-r--r--doxygen-todo8
-rw-r--r--keyboards/ergodox_infinity/ergodox_infinity.c1
-rw-r--r--quantum/keyboard.c7
-rw-r--r--quantum/sequencer/tests/rules.mk2
-rw-r--r--quantum/serial_link/LICENSE19
-rw-r--r--quantum/serial_link/README.md1
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c135
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h34
-rw-r--r--quantum/serial_link/protocol/frame_router.c64
-rw-r--r--quantum/serial_link/protocol/frame_router.h35
-rw-r--r--quantum/serial_link/protocol/frame_validator.c57
-rw-r--r--quantum/serial_link/protocol/frame_validator.h31
-rw-r--r--quantum/serial_link/protocol/physical.h27
-rw-r--r--quantum/serial_link/protocol/transport.c121
-rw-r--r--quantum/serial_link/protocol/transport.h139
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.c77
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.h44
-rw-r--r--quantum/serial_link/system/serial_link.c250
-rw-r--r--quantum/serial_link/system/serial_link.h54
-rw-r--r--quantum/serial_link/tests/Makefile61
-rw-r--r--quantum/serial_link/tests/byte_stuffer_tests.cpp450
-rw-r--r--quantum/serial_link/tests/frame_router_tests.cpp204
-rw-r--r--quantum/serial_link/tests/frame_validator_tests.cpp100
-rw-r--r--quantum/serial_link/tests/rules.mk22
-rw-r--r--quantum/serial_link/tests/testlist.mk6
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp184
-rw-r--r--quantum/serial_link/tests/triple_buffered_object_tests.cpp80
-rw-r--r--show_options.mk1
-rw-r--r--testlist.mk1
-rw-r--r--tmk_core/common/sync_timer.c2
-rw-r--r--tmk_core/common/sync_timer.h2
-rw-r--r--tmk_core/protocol/chibios/chibios.c21
36 files changed, 7 insertions, 2252 deletions
diff --git a/build_test.mk b/build_test.mk
index 037577bf9..96487c01f 100644
--- a/build_test.mk
+++ b/build_test.mk
@@ -55,7 +55,6 @@ include common_features.mk
55include $(TMK_PATH)/common.mk 55include $(TMK_PATH)/common.mk
56include $(QUANTUM_PATH)/debounce/tests/rules.mk 56include $(QUANTUM_PATH)/debounce/tests/rules.mk
57include $(QUANTUM_PATH)/sequencer/tests/rules.mk 57include $(QUANTUM_PATH)/sequencer/tests/rules.mk
58include $(QUANTUM_PATH)/serial_link/tests/rules.mk
59include $(TMK_PATH)/common/test/rules.mk 58include $(TMK_PATH)/common/test/rules.mk
60ifneq ($(filter $(FULL_TESTS),$(TEST)),) 59ifneq ($(filter $(FULL_TESTS),$(TEST)),)
61include build_full_test.mk 60include build_full_test.mk
diff --git a/common_features.mk b/common_features.mk
index fc9595ddd..3c956b7aa 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -13,8 +13,6 @@
13# You should have received a copy of the GNU General Public License 13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>. 14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15 15
16SERIAL_PATH := $(QUANTUM_PATH)/serial_link
17
18QUANTUM_SRC += \ 16QUANTUM_SRC += \
19 $(QUANTUM_DIR)/quantum.c \ 17 $(QUANTUM_DIR)/quantum.c \
20 $(QUANTUM_DIR)/send_string.c \ 18 $(QUANTUM_DIR)/send_string.c \
@@ -363,17 +361,6 @@ ifeq ($(strip $(PRINTING_ENABLE)), yes)
363 SRC += $(TMK_DIR)/protocol/serial_uart.c 361 SRC += $(TMK_DIR)/protocol/serial_uart.c
364endif 362endif
365 363
366ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
367 SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
368 SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
369 SERIAL_DEFS += -DSERIAL_LINK_ENABLE
370 COMMON_VPATH += $(SERIAL_PATH)
371
372 SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
373 OPT_DEFS += $(SERIAL_DEFS)
374 VAPTH += $(SERIAL_PATH)
375endif
376
377VARIABLE_TRACE ?= no 364VARIABLE_TRACE ?= no
378ifneq ($(strip $(VARIABLE_TRACE)),no) 365ifneq ($(strip $(VARIABLE_TRACE)),no)
379 SRC += $(QUANTUM_DIR)/variable_trace.c 366 SRC += $(QUANTUM_DIR)/variable_trace.c
diff --git a/disable_features.mk b/disable_features.mk
index 6733e4e80..090a9b5a1 100644
--- a/disable_features.mk
+++ b/disable_features.mk
@@ -19,7 +19,6 @@ FEATURE_NAMES += PS2_MOUSE
19FEATURE_NAMES += RGBLIGHT 19FEATURE_NAMES += RGBLIGHT
20FEATURE_NAMES += RGB_MATRIX 20FEATURE_NAMES += RGB_MATRIX
21FEATURE_NAMES += SLEEP_LED 21FEATURE_NAMES += SLEEP_LED
22FEATURE_NAMES += SERIAL_LINK
23FEATURE_NAMES += STENO 22FEATURE_NAMES += STENO
24FEATURE_NAMES += SWAP_HANDS 23FEATURE_NAMES += SWAP_HANDS
25FEATURE_NAMES += WATCHDOG 24FEATURE_NAMES += WATCHDOG
diff --git a/docs/unit_testing.md b/docs/unit_testing.md
index 7310da8d0..47a105579 100644
--- a/docs/unit_testing.md
+++ b/docs/unit_testing.md
@@ -20,12 +20,12 @@ One thing to remember, is that you have to append `extern "C"` around all of you
20 20
21## Adding Tests for New or Existing Features 21## Adding Tests for New or Existing Features
22 22
23If you want to unit test some feature, then take a look at the existing serial_link tests, in the `quantum/serial_link/tests folder`, and follow the steps below to create a similar structure. 23If you want to unit test a feature, take a look at some of the existing tests, for example those in the `quantum/sequencer/tests` folder. Then follow the steps below to create a similar structure.
24 24
251. If it doesn't already exist, add a test subfolder to the folder containing the feature. 251. If it doesn't already exist, add a test subfolder to the folder containing the feature.
262. Create a `testlist.mk` and a `rules.mk` file in that folder. 262. Create a `testlist.mk` and a `rules.mk` file in that folder.
273. Include those files from the root folder `testlist.mk`and `build_test.mk` respectively. 273. Include those files from the root folder `testlist.mk`and `build_test.mk` respectively.
284. Add a new name for your testgroup to the `testlist.mk` file. Each group defined there will be a separate executable. And that's how you can support mocking out different parts. Note that it's worth adding some common prefix, just like it's done for the serial_link tests. The reason for that is that the make command allows substring filtering, so this way you can easily run a subset of the tests. 284. Add a new name for your testgroup to the `testlist.mk` file. Each group defined there will be a separate executable. And that's how you can support mocking out different parts. Note that it's worth adding some common prefix, just like it's done for the existing tests. The reason for that is that the make command allows substring filtering, so this way you can easily run a subset of the tests.
295. Define the source files and required options in the `rules.mk` file. 295. Define the source files and required options in the `rules.mk` file.
30 * `_SRC` for source files 30 * `_SRC` for source files
31 * `_DEFS` for additional defines 31 * `_DEFS` for additional defines
diff --git a/doxygen-todo b/doxygen-todo
index 54d7e9ef7..4151627e4 100644
--- a/doxygen-todo
+++ b/doxygen-todo
@@ -6,16 +6,8 @@ tmk_core/protocol/midi/bytequeue
6tmk_core/protocol/midi/Config 6tmk_core/protocol/midi/Config
7tmk_core/protocol/usb_hid 7tmk_core/protocol/usb_hid
8tmk_core/protocol/vusb 8tmk_core/protocol/vusb
9tmk_core/tool
10tmk_core/tool/chibios
11quantum 9quantum
12quantum/api
13quantum/audio 10quantum/audio
14quantum/keymap_extras 11quantum/keymap_extras
15quantum/process_keycode 12quantum/process_keycode
16quantum/serial_link
17quantum/serial_link/protocol
18quantum/serial_link/system
19quantum/serial_link/tests
20quantum/tools
21drivers 13drivers
diff --git a/keyboards/ergodox_infinity/ergodox_infinity.c b/keyboards/ergodox_infinity/ergodox_infinity.c
index d2a311ee8..88028d363 100644
--- a/keyboards/ergodox_infinity/ergodox_infinity.c
+++ b/keyboards/ergodox_infinity/ergodox_infinity.c
@@ -3,7 +3,6 @@
3#include <hal.h> 3#include <hal.h>
4#include <string.h> 4#include <string.h>
5#include "eeconfig.h" 5#include "eeconfig.h"
6#include "serial_link/system/serial_link.h"
7 6
8#define RED_PIN 1 7#define RED_PIN 1
9#define GREEN_PIN 2 8#define GREEN_PIN 2
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index c2e2234f9..ee7fa2bd4 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -61,9 +61,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
61#ifdef STENO_ENABLE 61#ifdef STENO_ENABLE
62# include "process_steno.h" 62# include "process_steno.h"
63#endif 63#endif
64#ifdef SERIAL_LINK_ENABLE
65# include "serial_link/system/serial_link.h"
66#endif
67#ifdef POINTING_DEVICE_ENABLE 64#ifdef POINTING_DEVICE_ENABLE
68# include "pointing_device.h" 65# include "pointing_device.h"
69#endif 66#endif
@@ -511,10 +508,6 @@ MATRIX_LOOP_END:
511 adb_mouse_task(); 508 adb_mouse_task();
512#endif 509#endif
513 510
514#ifdef SERIAL_LINK_ENABLE
515 serial_link_update();
516#endif
517
518#ifdef POINTING_DEVICE_ENABLE 511#ifdef POINTING_DEVICE_ENABLE
519 pointing_device_task(); 512 pointing_device_task();
520#endif 513#endif
diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk
index 76c221cf9..87a204669 100644
--- a/quantum/sequencer/tests/rules.mk
+++ b/quantum/sequencer/tests/rules.mk
@@ -1,5 +1,5 @@
1# The letter case of these variables might seem odd. However: 1# The letter case of these variables might seem odd. However:
2# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features) 2# - it is consistent with the example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features)
3# - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE 3# - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE
4 4
5sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED 5sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED
diff --git a/quantum/serial_link/LICENSE b/quantum/serial_link/LICENSE
deleted file mode 100644
index d13cc4b26..000000000
--- a/quantum/serial_link/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
1The MIT License (MIT)
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is
8furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/quantum/serial_link/README.md b/quantum/serial_link/README.md
deleted file mode 100644
index 05871dbdf..000000000
--- a/quantum/serial_link/README.md
+++ /dev/null
@@ -1 +0,0 @@
1# qmk_serial_link
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
deleted file mode 100644
index d3a91d828..000000000
--- a/quantum/serial_link/protocol/byte_stuffer.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/byte_stuffer.h"
26#include "serial_link/protocol/frame_validator.h"
27#include "serial_link/protocol/physical.h"
28#include <stdbool.h>
29
30// This implements the "Consistent overhead byte stuffing protocol"
31// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
32// http://www.stuartcheshire.org/papers/COBSforToN.pdf
33
34typedef struct byte_stuffer_state {
35 uint16_t next_zero;
36 uint16_t data_pos;
37 bool long_frame;
38 uint8_t data[MAX_FRAME_SIZE];
39} byte_stuffer_state_t;
40
41static byte_stuffer_state_t states[NUM_LINKS];
42
43void init_byte_stuffer_state(byte_stuffer_state_t* state) {
44 state->next_zero = 0;
45 state->data_pos = 0;
46 state->long_frame = false;
47}
48
49void init_byte_stuffer(void) {
50 int i;
51 for (i = 0; i < NUM_LINKS; i++) {
52 init_byte_stuffer_state(&states[i]);
53 }
54}
55
56void byte_stuffer_recv_byte(uint8_t link, uint8_t data) {
57 byte_stuffer_state_t* state = &states[link];
58 // Start of a new frame
59 if (state->next_zero == 0) {
60 state->next_zero = data;
61 state->long_frame = data == 0xFF;
62 state->data_pos = 0;
63 return;
64 }
65
66 state->next_zero--;
67 if (data == 0) {
68 if (state->next_zero == 0) {
69 // The frame is completed
70 if (state->data_pos > 0) {
71 validator_recv_frame(link, state->data, state->data_pos);
72 }
73 } else {
74 // The frame is invalid, so reset
75 init_byte_stuffer_state(state);
76 }
77 } else {
78 if (state->data_pos == MAX_FRAME_SIZE) {
79 // We exceeded our maximum frame size
80 // therefore there's nothing else to do than reset to a new frame
81 state->next_zero = data;
82 state->long_frame = data == 0xFF;
83 state->data_pos = 0;
84 } else if (state->next_zero == 0) {
85 if (state->long_frame) {
86 // This is part of a long frame, so continue
87 state->next_zero = data;
88 state->long_frame = data == 0xFF;
89 } else {
90 // Special case for zeroes
91 state->next_zero = data;
92 state->data[state->data_pos++] = 0;
93 }
94 } else {
95 state->data[state->data_pos++] = data;
96 }
97 }
98}
99
100static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) {
101 send_data(link, &num_non_zero, 1);
102 if (end > start) {
103 send_data(link, start, end - start);
104 }
105}
106
107void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
108 const uint8_t zero = 0;
109 if (size > 0) {
110 uint16_t num_non_zero = 1;
111 uint8_t* end = data + size;
112 uint8_t* start = data;
113 while (data < end) {
114 if (num_non_zero == 0xFF) {
115 // There's more data after big non-zero block
116 // So send it, and start a new block
117 send_block(link, start, data, num_non_zero);
118 start = data;
119 num_non_zero = 1;
120 } else {
121 if (*data == 0) {
122 // A zero encountered, so send the block
123 send_block(link, start, data, num_non_zero);
124 start = data + 1;
125 num_non_zero = 1;
126 } else {
127 num_non_zero++;
128 }
129 ++data;
130 }
131 }
132 send_block(link, start, data, num_non_zero);
133 send_data(link, &zero, 1);
134 }
135}
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
deleted file mode 100644
index 397ed3baa..000000000
--- a/quantum/serial_link/protocol/byte_stuffer.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include <stdint.h>
28
29#define MAX_FRAME_SIZE 1024
30#define NUM_LINKS 2
31
32void init_byte_stuffer(void);
33void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
34void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c
deleted file mode 100644
index 529267370..000000000
--- a/quantum/serial_link/protocol/frame_router.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/frame_router.h"
26#include "serial_link/protocol/transport.h"
27#include "serial_link/protocol/frame_validator.h"
28
29static bool is_master;
30
31void router_set_master(bool master) { is_master = master; }
32
33void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) {
34 if (is_master) {
35 if (link == DOWN_LINK) {
36 transport_recv_frame(data[size - 1], data, size - 1);
37 }
38 } else {
39 if (link == UP_LINK) {
40 if (data[size - 1] & 1) {
41 transport_recv_frame(0, data, size - 1);
42 }
43 data[size - 1] >>= 1;
44 validator_send_frame(DOWN_LINK, data, size);
45 } else {
46 data[size - 1]++;
47 validator_send_frame(UP_LINK, data, size);
48 }
49 }
50}
51
52void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
53 if (destination == 0) {
54 if (!is_master) {
55 data[size] = 1;
56 validator_send_frame(UP_LINK, data, size + 1);
57 }
58 } else {
59 if (is_master) {
60 data[size] = destination;
61 validator_send_frame(DOWN_LINK, data, size + 1);
62 }
63 }
64}
diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h
deleted file mode 100644
index 9325fe4ee..000000000
--- a/quantum/serial_link/protocol/frame_router.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include <stdint.h>
28#include <stdbool.h>
29
30#define UP_LINK 0
31#define DOWN_LINK 1
32
33void router_set_master(bool master);
34void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size);
35void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c
deleted file mode 100644
index bc9136f70..000000000
--- a/quantum/serial_link/protocol/frame_validator.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/frame_validator.h"
26#include "serial_link/protocol/frame_router.h"
27#include "serial_link/protocol/byte_stuffer.h"
28#include <string.h>
29
30const uint32_t poly8_lookup[256] = {0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
31 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
32 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
33 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
34
35static uint32_t crc32_byte(uint8_t* p, uint32_t bytelength) {
36 uint32_t crc = 0xffffffff;
37 while (bytelength-- != 0) crc = poly8_lookup[((uint8_t)crc ^ *(p++))] ^ (crc >> 8);
38 // return (~crc); also works
39 return (crc ^ 0xffffffff);
40}
41
42void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
43 if (size > 4) {
44 uint32_t frame_crc;
45 memcpy(&frame_crc, data + size - 4, 4);
46 uint32_t expected_crc = crc32_byte(data, size - 4);
47 if (frame_crc == expected_crc) {
48 route_incoming_frame(link, data, size - 4);
49 }
50 }
51}
52
53void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
54 uint32_t crc = crc32_byte(data, size);
55 memcpy(data + size, &crc, 4);
56 byte_stuffer_send_frame(link, data, size + 4);
57}
diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h
deleted file mode 100644
index 0f78768a0..000000000
--- a/quantum/serial_link/protocol/frame_validator.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include <stdint.h>
28
29void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size);
30// The buffer pointed to by the data needs 4 additional bytes
31void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h
deleted file mode 100644
index 399c9d1f7..000000000
--- a/quantum/serial_link/protocol/physical.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27void send_data(uint8_t link, const uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
deleted file mode 100644
index 73b8dc62e..000000000
--- a/quantum/serial_link/protocol/transport.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/transport.h"
26#include "serial_link/protocol/frame_router.h"
27#include "serial_link/protocol/triple_buffered_object.h"
28#include <string.h>
29
30#define MAX_REMOTE_OBJECTS 16
31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
32static uint32_t num_remote_objects = 0;
33
34void reinitialize_serial_link_transport(void) { num_remote_objects = 0; }
35
36void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
37 unsigned int i;
38 for (i = 0; i < _num_remote_objects; i++) {
39 remote_object_t* obj = _remote_objects[i];
40 remote_objects[num_remote_objects++] = obj;
41 if (obj->object_type == MASTER_TO_ALL_SLAVES) {
42 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
43 triple_buffer_init(tb);
44 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
45 tb = (triple_buffer_object_t*)start;
46 triple_buffer_init(tb);
47 } else if (obj->object_type == MASTER_TO_SINGLE_SLAVE) {
48 uint8_t* start = obj->buffer;
49 unsigned int j;
50 for (j = 0; j < NUM_SLAVES; j++) {
51 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
52 triple_buffer_init(tb);
53 start += LOCAL_OBJECT_SIZE(obj->object_size);
54 }
55 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
56 triple_buffer_init(tb);
57 } else {
58 uint8_t* start = obj->buffer;
59 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
60 triple_buffer_init(tb);
61 start += LOCAL_OBJECT_SIZE(obj->object_size);
62 unsigned int j;
63 for (j = 0; j < NUM_SLAVES; j++) {
64 tb = (triple_buffer_object_t*)start;
65 triple_buffer_init(tb);
66 start += REMOTE_OBJECT_SIZE(obj->object_size);
67 }
68 }
69 }
70}
71
72void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
73 uint8_t id = data[size - 1];
74 if (id < num_remote_objects) {
75 remote_object_t* obj = remote_objects[id];
76 if (obj->object_size == size - 1) {
77 uint8_t* start;
78 if (obj->object_type == MASTER_TO_ALL_SLAVES) {
79 start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
80 } else if (obj->object_type == SLAVE_TO_MASTER) {
81 start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
82 start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size);
83 } else {
84 start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);
85 }
86 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
87 void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb);
88 memcpy(ptr, data, size - 1);
89 triple_buffer_end_write_internal(tb);
90 }
91 }
92}
93
94void update_transport(void) {
95 unsigned int i;
96 for (i = 0; i < num_remote_objects; i++) {
97 remote_object_t* obj = remote_objects[i];
98 if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) {
99 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
100 uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
101 if (ptr) {
102 ptr[obj->object_size] = i;
103 uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0;
104 router_send_frame(dest, ptr, obj->object_size + 1);
105 }
106 } else {
107 uint8_t* start = obj->buffer;
108 unsigned int j;
109 for (j = 0; j < NUM_SLAVES; j++) {
110 triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
111 uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
112 if (ptr) {
113 ptr[obj->object_size] = i;
114 uint8_t dest = j + 1;
115 router_send_frame(dest, ptr, obj->object_size + 1);
116 }
117 start += LOCAL_OBJECT_SIZE(obj->object_size);
118 }
119 }
120 }
121}
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
deleted file mode 100644
index 3ce0c9fe4..000000000
--- a/quantum/serial_link/protocol/transport.h
+++ /dev/null
@@ -1,139 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include "serial_link/protocol/triple_buffered_object.h"
28#include "serial_link/system/serial_link.h"
29
30#define NUM_SLAVES 8
31#define LOCAL_OBJECT_EXTRA 16
32
33// master -> slave = 1 local(target all), 1 remote object
34// slave -> master = 1 local(target 0), multiple remote objects
35// master -> single slave (multiple local, target id), 1 remote object
36typedef enum {
37 MASTER_TO_ALL_SLAVES,
38 MASTER_TO_SINGLE_SLAVE,
39 SLAVE_TO_MASTER,
40} remote_object_type;
41
42typedef struct {
43 remote_object_type object_type;
44 uint16_t object_size;
45 uint8_t buffer[] __attribute__((aligned(4)));
46} remote_object_t;
47
48#define REMOTE_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + objectsize * 3)
49#define LOCAL_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3)
50
51#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \
52 typedef struct { \
53 remote_object_t object; \
54 uint8_t buffer[num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \
55 } remote_object_##name##_t;
56
57#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \
58 REMOTE_OBJECT_HELPER(name, type, 1, 1) \
59 remote_object_##name##_t remote_object_##name = {.object = { \
60 .object_type = MASTER_TO_ALL_SLAVES, \
61 .object_size = sizeof(type), \
62 }}; \
63 type* begin_write_##name(void) { \
64 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
65 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
66 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
67 } \
68 void end_write_##name(void) { \
69 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
70 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
71 triple_buffer_end_write_internal(tb); \
72 signal_data_written(); \
73 } \
74 type* read_##name(void) { \
75 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
76 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
77 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
78 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
79 }
80
81#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
82 REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \
83 remote_object_##name##_t remote_object_##name = {.object = { \
84 .object_type = MASTER_TO_SINGLE_SLAVE, \
85 .object_size = sizeof(type), \
86 }}; \
87 type* begin_write_##name(uint8_t slave) { \
88 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
89 uint8_t* start = obj->buffer; \
90 start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
91 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
92 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
93 } \
94 void end_write_##name(uint8_t slave) { \
95 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
96 uint8_t* start = obj->buffer; \
97 start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
98 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
99 triple_buffer_end_write_internal(tb); \
100 signal_data_written(); \
101 } \
102 type* read_##name() { \
103 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
104 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); \
105 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
106 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
107 }
108
109#define SLAVE_TO_MASTER_OBJECT(name, type) \
110 REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \
111 remote_object_##name##_t remote_object_##name = {.object = { \
112 .object_type = SLAVE_TO_MASTER, \
113 .object_size = sizeof(type), \
114 }}; \
115 type* begin_write_##name(void) { \
116 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
117 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
118 return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
119 } \
120 void end_write_##name(void) { \
121 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
122 triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
123 triple_buffer_end_write_internal(tb); \
124 signal_data_written(); \
125 } \
126 type* read_##name(uint8_t slave) { \
127 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
128 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
129 start += slave * REMOTE_OBJECT_SIZE(obj->object_size); \
130 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
131 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
132 }
133
134#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
135
136void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
137void reinitialize_serial_link_transport(void);
138void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
139void update_transport(void);
diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c
deleted file mode 100644
index e0c6d702a..000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.c
+++ /dev/null
@@ -1,77 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "serial_link/protocol/triple_buffered_object.h"
26#include "serial_link/system/serial_link.h"
27#include <stdbool.h>
28#include <stddef.h>
29
30#define GET_READ_INDEX() object->state & 3
31#define GET_WRITE_INDEX() (object->state >> 2) & 3
32#define GET_SHARED_INDEX() (object->state >> 4) & 3
33#define GET_DATA_AVAILABLE() (object->state >> 6) & 1
34
35#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i)
36#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2))
37#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4))
38#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6))
39
40void triple_buffer_init(triple_buffer_object_t* object) {
41 object->state = 0;
42 SET_WRITE_INDEX(0);
43 SET_READ_INDEX(1);
44 SET_SHARED_INDEX(2);
45 SET_DATA_AVAILABLE(0);
46}
47
48void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) {
49 serial_link_lock();
50 if (GET_DATA_AVAILABLE()) {
51 uint8_t shared_index = GET_SHARED_INDEX();
52 uint8_t read_index = GET_READ_INDEX();
53 SET_READ_INDEX(shared_index);
54 SET_SHARED_INDEX(read_index);
55 SET_DATA_AVAILABLE(false);
56 serial_link_unlock();
57 return object->buffer + object_size * shared_index;
58 } else {
59 serial_link_unlock();
60 return NULL;
61 }
62}
63
64void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) {
65 uint8_t write_index = GET_WRITE_INDEX();
66 return object->buffer + object_size * write_index;
67}
68
69void triple_buffer_end_write_internal(triple_buffer_object_t* object) {
70 serial_link_lock();
71 uint8_t shared_index = GET_SHARED_INDEX();
72 uint8_t write_index = GET_WRITE_INDEX();
73 SET_SHARED_INDEX(write_index);
74 SET_WRITE_INDEX(shared_index);
75 SET_DATA_AVAILABLE(true);
76 serial_link_unlock();
77}
diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h
deleted file mode 100644
index 717d6d7b8..000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.h
+++ /dev/null
@@ -1,44 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include <stdint.h>
28
29typedef struct {
30 uint8_t state;
31 uint8_t buffer[] __attribute__((aligned(4)));
32} triple_buffer_object_t;
33
34void triple_buffer_init(triple_buffer_object_t* object);
35
36#define triple_buffer_begin_write(object) (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
37
38#define triple_buffer_end_write(object) triple_buffer_end_write_internal((triple_buffer_object_t*)object)
39
40#define triple_buffer_read(object) (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
41
42void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object);
43void triple_buffer_end_write_internal(triple_buffer_object_t* object);
44void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object);
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
deleted file mode 100644
index 6363f8ff3..000000000
--- a/quantum/serial_link/system/serial_link.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24#include "report.h"
25#include "host_driver.h"
26#include "serial_link/system/serial_link.h"
27#include <hal.h>
28#include "serial_link/protocol/byte_stuffer.h"
29#include "serial_link/protocol/transport.h"
30#include "serial_link/protocol/frame_router.h"
31#include "matrix.h"
32#include "sync_timer.h"
33#include <stdbool.h>
34#include "print.h"
35#include "config.h"
36
37#define SYNC_TIMER_OFFSET 2
38
39static event_source_t new_data_event;
40static bool serial_link_connected;
41static bool is_master = false;
42
43static uint8_t keyboard_leds(void);
44static void send_keyboard(report_keyboard_t* report);
45static void send_mouse(report_mouse_t* report);
46static void send_system(uint16_t data);
47static void send_consumer(uint16_t data);
48
49host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
50
51// Define these in your Config.h file
52#ifndef SERIAL_LINK_BAUD
53# error "Serial link baud is not set"
54#endif
55
56#ifndef SERIAL_LINK_THREAD_PRIORITY
57# error "Serial link thread priority not set"
58#endif
59
60static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD};
61
62//#define DEBUG_LINK_ERRORS
63
64static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) {
65 const uint32_t buffer_size = 16;
66 uint8_t buffer[buffer_size];
67 uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size);
68 uint8_t* current = buffer;
69 uint8_t* end = current + bytes_read;
70 while (current < end) {
71 byte_stuffer_recv_byte(link, *current);
72 current++;
73 }
74 return bytes_read;
75}
76
77static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
78#ifdef DEBUG_LINK_ERRORS
79 if (flags & SD_PARITY_ERROR) {
80 print(str);
81 print(" Parity error\n");
82 }
83 if (flags & SD_FRAMING_ERROR) {
84 print(str);
85 print(" Framing error\n");
86 }
87 if (flags & SD_OVERRUN_ERROR) {
88 print(str);
89 uint32_t size = qSpaceI(&(driver->iqueue));
90 xprintf(" Overrun error, queue size %d\n", size);
91 }
92 if (flags & SD_NOISE_ERROR) {
93 print(str);
94 print(" Noise error\n");
95 }
96 if (flags & SD_BREAK_DETECTED) {
97 print(str);
98 print(" Break detected\n");
99 }
100#else
101 (void)str;
102 (void)flags;
103 (void)driver;
104#endif
105}
106
107bool is_serial_link_master(void) { return is_master; }
108
109// TODO: Optimize the stack size, this is probably way too big
110static THD_WORKING_AREA(serialThreadStack, 1024);
111static THD_FUNCTION(serialThread, arg) {
112 (void)arg;
113 event_listener_t new_data_listener;
114 event_listener_t sd1_listener;
115 event_listener_t sd2_listener;
116 chEvtRegister(&new_data_event, &new_data_listener, 0);
117 eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED;
118 chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events);
119 chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events);
120 bool need_wait = false;
121 while (true) {
122 eventflags_t flags1 = 0;
123 eventflags_t flags2 = 0;
124 if (need_wait) {
125 eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000));
126 if (mask & EVENT_MASK(1)) {
127 flags1 = chEvtGetAndClearFlags(&sd1_listener);
128 print_error("DOWNLINK", flags1, &SD1);
129 }
130 if (mask & EVENT_MASK(2)) {
131 flags2 = chEvtGetAndClearFlags(&sd2_listener);
132 print_error("UPLINK", flags2, &SD2);
133 }
134 }
135
136 // Always stay as master, even if the USB goes into sleep mode
137 is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE;
138 router_set_master(is_master);
139
140 need_wait = true;
141 need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
142 need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
143 update_transport();
144 }
145}
146
147void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
148 if (link == DOWN_LINK) {
149 sdWrite(&SD1, data, size);
150 } else {
151 sdWrite(&SD2, data, size);
152 }
153}
154
155static systime_t last_update = 0;
156
157typedef struct {
158 matrix_row_t rows[MATRIX_ROWS];
159} matrix_object_t;
160
161static matrix_object_t last_matrix = {};
162
163SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
164MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
165#ifndef DISABLE_SYNC_TIMER
166MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t);
167#endif
168
169static remote_object_t* remote_objects[] = {
170 REMOTE_OBJECT(serial_link_connected),
171 REMOTE_OBJECT(keyboard_matrix),
172#ifndef DISABLE_SYNC_TIMER
173 REMOTE_OBJECT(sync_timer),
174#endif
175};
176
177void init_serial_link(void) {
178 serial_link_connected = false;
179 init_serial_link_hal();
180 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
181 init_byte_stuffer();
182 sdStart(&SD1, &config);
183 sdStart(&SD2, &config);
184 chEvtObjectInit(&new_data_event);
185 (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL);
186}
187
188void matrix_set_remote(matrix_row_t* rows, uint8_t index);
189
190void serial_link_update(void) {
191 if (read_serial_link_connected()) {
192 serial_link_connected = true;
193 }
194
195 matrix_object_t matrix;
196 bool changed = false;
197 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
198 matrix.rows[i] = matrix_get_row(i);
199 changed |= matrix.rows[i] != last_matrix.rows[i];
200 }
201
202 systime_t current_time = chVTGetSystemTimeX();
203 systime_t delta = current_time - last_update;
204 if (changed || delta > TIME_US2I(5000)) {
205 last_update = current_time;
206 last_matrix = matrix;
207 matrix_object_t* m = begin_write_keyboard_matrix();
208 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
209 m->rows[i] = matrix.rows[i];
210 }
211 end_write_keyboard_matrix();
212
213 *begin_write_serial_link_connected() = true;
214 end_write_serial_link_connected();
215
216#ifndef DISABLE_SYNC_TIMER
217 *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET;
218 end_write_sync_timer();
219#endif
220 }
221
222 matrix_object_t* m = read_keyboard_matrix(0);
223 if (m) {
224 matrix_set_remote(m->rows, 0);
225 }
226
227#ifndef DISABLE_SYNC_TIMER
228 uint32_t* t = read_sync_timer();
229 if (t) {
230 sync_timer_update(*t);
231 }
232#endif
233}
234
235void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
236
237bool is_serial_link_connected(void) { return serial_link_connected; }
238
239host_driver_t* get_serial_link_driver(void) { return &serial_driver; }
240
241// NOTE: The driver does nothing, because the master handles everything
242uint8_t keyboard_leds(void) { return 0; }
243
244void send_keyboard(report_keyboard_t* report) { (void)report; }
245
246void send_mouse(report_mouse_t* report) { (void)report; }
247
248void send_system(uint16_t data) { (void)data; }
249
250void send_consumer(uint16_t data) { (void)data; }
diff --git a/quantum/serial_link/system/serial_link.h b/quantum/serial_link/system/serial_link.h
deleted file mode 100644
index adc1f6e93..000000000
--- a/quantum/serial_link/system/serial_link.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#pragma once
26
27#include "host_driver.h"
28#include <stdbool.h>
29
30void init_serial_link(void);
31void init_serial_link_hal(void);
32bool is_serial_link_connected(void);
33bool is_serial_link_master(void);
34host_driver_t* get_serial_link_driver(void);
35void serial_link_update(void);
36
37#if defined(PROTOCOL_CHIBIOS)
38# include <ch.h>
39
40static inline void serial_link_lock(void) { chSysLock(); }
41
42static inline void serial_link_unlock(void) { chSysUnlock(); }
43
44void signal_data_written(void);
45
46#else
47
48inline void serial_link_lock(void) {}
49
50inline void serial_link_unlock(void) {}
51
52void signal_data_written(void);
53
54#endif
diff --git a/quantum/serial_link/tests/Makefile b/quantum/serial_link/tests/Makefile
deleted file mode 100644
index 11dd355b2..000000000
--- a/quantum/serial_link/tests/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
1# The MIT License (MIT)
2#
3# Copyright (c) 2016 Fred Sundvik
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
22
23CC = gcc
24CFLAGS =
25INCLUDES = -I. -I../../
26LDFLAGS = -L$(BUILDDIR)/cgreen/build-c/src -shared
27LDLIBS = -lcgreen
28UNITOBJ = $(BUILDDIR)/serialtest/unitobj
29DEPDIR = $(BUILDDIR)/serialtest/unit.d
30UNITTESTS = $(BUILDDIR)/serialtest/unittests
31DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
32EXT = .so
33UNAME := $(shell uname)
34ifneq (, $(findstring MINGW, $(UNAME)))
35 EXT = .dll
36endif
37ifneq (, $(findstring CYGWIN, $(UNAME)))
38 EXT = .dll
39endif
40
41SRC = $(wildcard *.c)
42TESTFILES = $(patsubst %.c, $(UNITTESTS)/%$(EXT), $(SRC))
43$(shell mkdir -p $(DEPDIR) >/dev/null)
44
45test: $(TESTFILES)
46 @$(BUILDDIR)/cgreen/build-c/tools/cgreen-runner --color $(TESTFILES)
47
48$(UNITTESTS)/%$(EXT): $(UNITOBJ)/%.o
49 @mkdir -p $(UNITTESTS)
50 $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
51
52$(UNITOBJ)/%.o : %.c
53$(UNITOBJ)/%.o: %.c $(DEPDIR)/%.d
54 @mkdir -p $(UNITOBJ)
55 $(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDES) -c $< -o $@
56 @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
57
58$(DEPDIR)/%.d: ;
59.PRECIOUS: $(DEPDIR)/%.d
60
61-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC)))
diff --git a/quantum/serial_link/tests/byte_stuffer_tests.cpp b/quantum/serial_link/tests/byte_stuffer_tests.cpp
deleted file mode 100644
index 9e4e1768f..000000000
--- a/quantum/serial_link/tests/byte_stuffer_tests.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27#include <vector>
28#include <algorithm>
29extern "C" {
30#include "serial_link/protocol/byte_stuffer.h"
31#include "serial_link/protocol/frame_validator.h"
32#include "serial_link/protocol/physical.h"
33}
34
35using testing::_;
36using testing::Args;
37using testing::ElementsAreArray;
38
39class ByteStuffer : public ::testing::Test {
40 public:
41 ByteStuffer() {
42 Instance = this;
43 init_byte_stuffer();
44 }
45
46 ~ByteStuffer() { Instance = nullptr; }
47
48 MOCK_METHOD3(validator_recv_frame, void(uint8_t link, uint8_t* data, uint16_t size));
49
50 void send_data(uint8_t link, const uint8_t* data, uint16_t size) { std::copy(data, data + size, std::back_inserter(sent_data)); }
51 std::vector<uint8_t> sent_data;
52
53 static ByteStuffer* Instance;
54};
55
56ByteStuffer* ByteStuffer::Instance = nullptr;
57
58extern "C" {
59void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { ByteStuffer::Instance->validator_recv_frame(link, data, size); }
60
61void send_data(uint8_t link, const uint8_t* data, uint16_t size) { ByteStuffer::Instance->send_data(link, data, size); }
62}
63
64TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
65 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
66 byte_stuffer_recv_byte(0, 0);
67}
68
69TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
70 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
71 byte_stuffer_recv_byte(0, 0xFF);
72}
73
74TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
75 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
76 byte_stuffer_recv_byte(0, 0x4A);
77}
78
79TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
80 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
81 byte_stuffer_recv_byte(0, 1);
82 byte_stuffer_recv_byte(0, 0);
83}
84
85TEST_F(ByteStuffer, receives_single_byte_valid_frame) {
86 uint8_t expected[] = {0x37};
87 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
88 byte_stuffer_recv_byte(0, 2);
89 byte_stuffer_recv_byte(0, 0x37);
90 byte_stuffer_recv_byte(0, 0);
91}
92TEST_F(ByteStuffer, receives_three_bytes_valid_frame) {
93 uint8_t expected[] = {0x37, 0x99, 0xFF};
94 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
95 byte_stuffer_recv_byte(0, 4);
96 byte_stuffer_recv_byte(0, 0x37);
97 byte_stuffer_recv_byte(0, 0x99);
98 byte_stuffer_recv_byte(0, 0xFF);
99 byte_stuffer_recv_byte(0, 0);
100}
101
102TEST_F(ByteStuffer, receives_single_zero_valid_frame) {
103 uint8_t expected[] = {0};
104 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
105 byte_stuffer_recv_byte(0, 1);
106 byte_stuffer_recv_byte(0, 1);
107 byte_stuffer_recv_byte(0, 0);
108}
109
110TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) {
111 uint8_t expected[] = {5, 0, 3, 0};
112 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
113 byte_stuffer_recv_byte(0, 2);
114 byte_stuffer_recv_byte(0, 5);
115 byte_stuffer_recv_byte(0, 2);
116 byte_stuffer_recv_byte(0, 3);
117 byte_stuffer_recv_byte(0, 1);
118 byte_stuffer_recv_byte(0, 0);
119}
120
121TEST_F(ByteStuffer, receives_two_valid_frames) {
122 uint8_t expected1[] = {5, 0};
123 uint8_t expected2[] = {3};
124 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected1)));
125 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected2)));
126 byte_stuffer_recv_byte(1, 2);
127 byte_stuffer_recv_byte(1, 5);
128 byte_stuffer_recv_byte(1, 1);
129 byte_stuffer_recv_byte(1, 0);
130 byte_stuffer_recv_byte(1, 2);
131 byte_stuffer_recv_byte(1, 3);
132 byte_stuffer_recv_byte(1, 0);
133}
134
135TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
136 uint8_t expected[] = {5, 7};
137 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
138 byte_stuffer_recv_byte(1, 3);
139 byte_stuffer_recv_byte(1, 1);
140 byte_stuffer_recv_byte(1, 0);
141 byte_stuffer_recv_byte(1, 3);
142 byte_stuffer_recv_byte(1, 5);
143 byte_stuffer_recv_byte(1, 7);
144 byte_stuffer_recv_byte(1, 0);
145}
146
147TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
148 uint8_t expected[] = {5, 7};
149 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
150 byte_stuffer_recv_byte(0, 2);
151 byte_stuffer_recv_byte(0, 9);
152 byte_stuffer_recv_byte(0, 4); // This should have been zero
153 byte_stuffer_recv_byte(0, 0);
154 byte_stuffer_recv_byte(0, 3);
155 byte_stuffer_recv_byte(0, 5);
156 byte_stuffer_recv_byte(0, 7);
157 byte_stuffer_recv_byte(0, 0);
158}
159
160TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
161 uint8_t expected[254];
162 int i;
163 for (i = 0; i < 254; i++) {
164 expected[i] = i + 1;
165 }
166 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
167 byte_stuffer_recv_byte(0, 0xFF);
168 for (i = 0; i < 254; i++) {
169 byte_stuffer_recv_byte(0, i + 1);
170 }
171 byte_stuffer_recv_byte(0, 0);
172}
173
174TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
175 uint8_t expected[255];
176 int i;
177 for (i = 0; i < 254; i++) {
178 expected[i] = i + 1;
179 }
180 expected[254] = 7;
181 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
182 byte_stuffer_recv_byte(0, 0xFF);
183 for (i = 0; i < 254; i++) {
184 byte_stuffer_recv_byte(0, i + 1);
185 }
186 byte_stuffer_recv_byte(0, 2);
187 byte_stuffer_recv_byte(0, 7);
188 byte_stuffer_recv_byte(0, 0);
189}
190
191TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
192 uint8_t expected[255];
193 int i;
194 for (i = 0; i < 254; i++) {
195 expected[i] = i + 1;
196 }
197 expected[254] = 0;
198 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
199 byte_stuffer_recv_byte(0, 0xFF);
200 for (i = 0; i < 254; i++) {
201 byte_stuffer_recv_byte(0, i + 1);
202 }
203 byte_stuffer_recv_byte(0, 1);
204 byte_stuffer_recv_byte(0, 1);
205 byte_stuffer_recv_byte(0, 0);
206}
207
208TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) {
209 uint8_t expected[515];
210 int i;
211 int j;
212 for (j = 0; j < 2; j++) {
213 for (i = 0; i < 254; i++) {
214 expected[i + 254 * j] = i + 1;
215 }
216 }
217 for (i = 0; i < 7; i++) {
218 expected[254 * 2 + i] = i + 1;
219 }
220 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
221 byte_stuffer_recv_byte(0, 0xFF);
222 for (i = 0; i < 254; i++) {
223 byte_stuffer_recv_byte(0, i + 1);
224 }
225 byte_stuffer_recv_byte(0, 0xFF);
226 for (i = 0; i < 254; i++) {
227 byte_stuffer_recv_byte(0, i + 1);
228 }
229 byte_stuffer_recv_byte(0, 8);
230 byte_stuffer_recv_byte(0, 1);
231 byte_stuffer_recv_byte(0, 2);
232 byte_stuffer_recv_byte(0, 3);
233 byte_stuffer_recv_byte(0, 4);
234 byte_stuffer_recv_byte(0, 5);
235 byte_stuffer_recv_byte(0, 6);
236 byte_stuffer_recv_byte(0, 7);
237 byte_stuffer_recv_byte(0, 0);
238}
239
240TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
241 uint8_t expected[MAX_FRAME_SIZE] = {};
242 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
243 int i;
244 byte_stuffer_recv_byte(0, 1);
245 for (i = 0; i < MAX_FRAME_SIZE; i++) {
246 byte_stuffer_recv_byte(0, 1);
247 }
248 byte_stuffer_recv_byte(0, 0);
249}
250
251TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
252 uint8_t expected[1] = {0};
253 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
254 int i;
255 byte_stuffer_recv_byte(0, 1);
256 for (i = 0; i < MAX_FRAME_SIZE; i++) {
257 byte_stuffer_recv_byte(0, 1);
258 }
259 byte_stuffer_recv_byte(0, 1);
260 byte_stuffer_recv_byte(0, 0);
261}
262
263TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
264 uint8_t expected[1] = {1};
265 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
266 int i;
267 byte_stuffer_recv_byte(0, 1);
268 for (i = 0; i < MAX_FRAME_SIZE; i++) {
269 byte_stuffer_recv_byte(0, 1);
270 }
271 byte_stuffer_recv_byte(0, 2);
272 byte_stuffer_recv_byte(0, 1);
273 byte_stuffer_recv_byte(0, 0);
274}
275
276TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
277 EXPECT_EQ(sent_data.size(), 0);
278 byte_stuffer_send_frame(0, NULL, 0);
279}
280
281TEST_F(ByteStuffer, send_one_byte_frame) {
282 uint8_t data[] = {5};
283 byte_stuffer_send_frame(1, data, 1);
284 uint8_t expected[] = {2, 5, 0};
285 EXPECT_THAT(sent_data, ElementsAreArray(expected));
286}
287
288TEST_F(ByteStuffer, sends_two_byte_frame) {
289 uint8_t data[] = {5, 0x77};
290 byte_stuffer_send_frame(0, data, 2);
291 uint8_t expected[] = {3, 5, 0x77, 0};
292 EXPECT_THAT(sent_data, ElementsAreArray(expected));
293}
294
295TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) {
296 uint8_t data[] = {0};
297 byte_stuffer_send_frame(0, data, 1);
298 uint8_t expected[] = {1, 1, 0};
299 EXPECT_THAT(sent_data, ElementsAreArray(expected));
300}
301
302TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
303 uint8_t data[] = {0, 9};
304 byte_stuffer_send_frame(1, data, 2);
305 uint8_t expected[] = {1, 2, 9, 0};
306 EXPECT_THAT(sent_data, ElementsAreArray(expected));
307}
308
309TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
310 uint8_t data[] = {9, 0};
311 byte_stuffer_send_frame(1, data, 2);
312 uint8_t expected[] = {2, 9, 1, 0};
313 EXPECT_THAT(sent_data, ElementsAreArray(expected));
314}
315
316TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
317 uint8_t data[] = {9, 0, 0x68};
318 byte_stuffer_send_frame(0, data, 3);
319 uint8_t expected[] = {2, 9, 2, 0x68, 0};
320 EXPECT_THAT(sent_data, ElementsAreArray(expected));
321}
322
323TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
324 uint8_t data[] = {0, 0x55, 0};
325 byte_stuffer_send_frame(0, data, 3);
326 uint8_t expected[] = {1, 2, 0x55, 1, 0};
327 EXPECT_THAT(sent_data, ElementsAreArray(expected));
328}
329
330TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
331 uint8_t data[] = {0, 0, 0};
332 byte_stuffer_send_frame(0, data, 3);
333 uint8_t expected[] = {1, 1, 1, 1, 0};
334 EXPECT_THAT(sent_data, ElementsAreArray(expected));
335}
336
337TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) {
338 uint8_t data[254];
339 int i;
340 for (i = 0; i < 254; i++) {
341 data[i] = i + 1;
342 }
343 byte_stuffer_send_frame(0, data, 254);
344 uint8_t expected[256];
345 expected[0] = 0xFF;
346 for (i = 1; i < 255; i++) {
347 expected[i] = i;
348 }
349 expected[255] = 0;
350 EXPECT_THAT(sent_data, ElementsAreArray(expected));
351}
352
353TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) {
354 uint8_t data[255];
355 int i;
356 for (i = 0; i < 255; i++) {
357 data[i] = i + 1;
358 }
359 byte_stuffer_send_frame(0, data, 255);
360 uint8_t expected[258];
361 expected[0] = 0xFF;
362 for (i = 1; i < 255; i++) {
363 expected[i] = i;
364 }
365 expected[255] = 2;
366 expected[256] = 255;
367 expected[257] = 0;
368 EXPECT_THAT(sent_data, ElementsAreArray(expected));
369}
370
371TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
372 uint8_t data[255];
373 int i;
374 for (i = 0; i < 254; i++) {
375 data[i] = i + 1;
376 }
377 data[254] = 0;
378 byte_stuffer_send_frame(0, data, 255);
379 uint8_t expected[258];
380 expected[0] = 0xFF;
381 for (i = 1; i < 255; i++) {
382 expected[i] = i;
383 }
384 expected[255] = 1;
385 expected[256] = 1;
386 expected[257] = 0;
387 EXPECT_THAT(sent_data, ElementsAreArray(expected));
388}
389
390TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
391 uint8_t original_data[] = {1, 2, 3};
392 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
393 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
394 int i;
395 for (auto& d : sent_data) {
396 byte_stuffer_recv_byte(1, d);
397 }
398}
399
400TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
401 uint8_t original_data[] = {1, 0, 3, 0, 0, 9};
402 byte_stuffer_send_frame(1, original_data, sizeof(original_data));
403 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
404 int i;
405 for (auto& d : sent_data) {
406 byte_stuffer_recv_byte(1, d);
407 }
408}
409
410TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
411 uint8_t original_data[254];
412 int i;
413 for (i = 0; i < 254; i++) {
414 original_data[i] = i + 1;
415 }
416 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
417 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
418 for (auto& d : sent_data) {
419 byte_stuffer_recv_byte(1, d);
420 }
421}
422
423TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
424 uint8_t original_data[256];
425 int i;
426 for (i = 0; i < 254; i++) {
427 original_data[i] = i + 1;
428 }
429 original_data[254] = 22;
430 original_data[255] = 23;
431 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
432 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
433 for (auto& d : sent_data) {
434 byte_stuffer_recv_byte(1, d);
435 }
436}
437
438TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
439 uint8_t original_data[255];
440 int i;
441 for (i = 0; i < 254; i++) {
442 original_data[i] = i + 1;
443 }
444 original_data[254] = 0;
445 byte_stuffer_send_frame(0, original_data, sizeof(original_data));
446 EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
447 for (auto& d : sent_data) {
448 byte_stuffer_recv_byte(1, d);
449 }
450}
diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp
deleted file mode 100644
index f76dfb33d..000000000
--- a/quantum/serial_link/tests/frame_router_tests.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27#include <array>
28extern "C" {
29#include "serial_link/protocol/transport.h"
30#include "serial_link/protocol/byte_stuffer.h"
31#include "serial_link/protocol/frame_router.h"
32}
33
34using testing::_;
35using testing::Args;
36using testing::ElementsAreArray;
37
38class FrameRouter : public testing::Test {
39 public:
40 FrameRouter() : current_router_buffer(nullptr) {
41 Instance = this;
42 init_byte_stuffer();
43 }
44
45 ~FrameRouter() { Instance = nullptr; }
46
47 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
48 auto& buffer = current_router_buffer->send_buffers[link];
49 std::copy(data, data + size, std::back_inserter(buffer));
50 }
51
52 void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
53 int i;
54 for (i = 0; i < size; i++) {
55 byte_stuffer_recv_byte(link, data[i]);
56 }
57 }
58
59 void activate_router(uint8_t num) {
60 current_router_buffer = router_buffers + num;
61 router_set_master(num == 0);
62 }
63
64 void simulate_transport(uint8_t from, uint8_t to) {
65 activate_router(to);
66 if (from > to) {
67 receive_data(DOWN_LINK, router_buffers[from].send_buffers[UP_LINK].data(), router_buffers[from].send_buffers[UP_LINK].size());
68 } else if (to > from) {
69 receive_data(UP_LINK, router_buffers[from].send_buffers[DOWN_LINK].data(), router_buffers[from].send_buffers[DOWN_LINK].size());
70 }
71 }
72
73 MOCK_METHOD3(transport_recv_frame, void(uint8_t from, uint8_t* data, uint16_t size));
74
75 std::vector<uint8_t> received_data;
76
77 struct router_buffer {
78 std::vector<uint8_t> send_buffers[2];
79 };
80
81 router_buffer router_buffers[8];
82 router_buffer* current_router_buffer;
83
84 static FrameRouter* Instance;
85};
86
87FrameRouter* FrameRouter::Instance = nullptr;
88
89typedef struct {
90 std::array<uint8_t, 4> data;
91 uint8_t extra[16];
92} frame_buffer_t;
93
94extern "C" {
95void send_data(uint8_t link, const uint8_t* data, uint16_t size) { FrameRouter::Instance->send_data(link, data, size); }
96
97void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { FrameRouter::Instance->transport_recv_frame(from, data, size); }
98}
99
100TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) {
101 frame_buffer_t data;
102 data.data = {0xAB, 0x70, 0x55, 0xBB};
103 activate_router(0);
104 router_send_frame(0xFF, (uint8_t*)&data, 4);
105 EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
106 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
107 EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
108 simulate_transport(0, 1);
109 EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
110 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
111
112 EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
113 simulate_transport(1, 2);
114 EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
115 EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
116}
117
118TEST_F(FrameRouter, master_send_is_received_by_targets) {
119 frame_buffer_t data;
120 data.data = {0xAB, 0x70, 0x55, 0xBB};
121 activate_router(0);
122 router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
123 EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
124 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
125
126 simulate_transport(0, 1);
127 EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
128 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
129
130 EXPECT_CALL(*this, transport_recv_frame(0, _, _)).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 EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
136 simulate_transport(2, 3);
137 EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0);
138 EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0);
139}
140
141TEST_F(FrameRouter, first_link_sends_to_master) {
142 frame_buffer_t data;
143 data.data = {0xAB, 0x70, 0x55, 0xBB};
144 activate_router(1);
145 router_send_frame(0, (uint8_t*)&data, 4);
146 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
147 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
148
149 EXPECT_CALL(*this, transport_recv_frame(1, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
150 simulate_transport(1, 0);
151 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
152 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
153}
154
155TEST_F(FrameRouter, second_link_sends_to_master) {
156 frame_buffer_t data;
157 data.data = {0xAB, 0x70, 0x55, 0xBB};
158 activate_router(2);
159 router_send_frame(0, (uint8_t*)&data, 4);
160 EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0);
161 EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
162
163 simulate_transport(2, 1);
164 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
165 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
166
167 EXPECT_CALL(*this, transport_recv_frame(2, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
168 simulate_transport(1, 0);
169 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
170 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
171}
172
173TEST_F(FrameRouter, master_sends_to_master_does_nothing) {
174 frame_buffer_t data;
175 data.data = {0xAB, 0x70, 0x55, 0xBB};
176 activate_router(0);
177 router_send_frame(0, (uint8_t*)&data, 4);
178 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
179 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
180}
181
182TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) {
183 frame_buffer_t data;
184 data.data = {0xAB, 0x70, 0x55, 0xBB};
185 activate_router(1);
186 router_send_frame(2, (uint8_t*)&data, 4);
187 EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
188 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
189}
190
191TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) {
192 frame_buffer_t data;
193 data.data = {0xAB, 0x70, 0x55, 0xBB};
194 activate_router(1);
195 router_send_frame(0, (uint8_t*)&data, 4);
196 EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
197 EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
198
199 EXPECT_CALL(*this, transport_recv_frame(_, _, _)).Times(0);
200 activate_router(0);
201 receive_data(UP_LINK, router_buffers[1].send_buffers[UP_LINK].data(), router_buffers[1].send_buffers[UP_LINK].size());
202 EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
203 EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
204}
diff --git a/quantum/serial_link/tests/frame_validator_tests.cpp b/quantum/serial_link/tests/frame_validator_tests.cpp
deleted file mode 100644
index 43dc57b63..000000000
--- a/quantum/serial_link/tests/frame_validator_tests.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27extern "C" {
28#include "serial_link/protocol/frame_validator.h"
29}
30
31using testing::_;
32using testing::Args;
33using testing::ElementsAreArray;
34
35class FrameValidator : public testing::Test {
36 public:
37 FrameValidator() { Instance = this; }
38
39 ~FrameValidator() { Instance = nullptr; }
40
41 MOCK_METHOD3(route_incoming_frame, void(uint8_t link, uint8_t* data, uint16_t size));
42 MOCK_METHOD3(byte_stuffer_send_frame, void(uint8_t link, uint8_t* data, uint16_t size));
43
44 static FrameValidator* Instance;
45};
46
47FrameValidator* FrameValidator::Instance = nullptr;
48
49extern "C" {
50void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->route_incoming_frame(link, data, size); }
51
52void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->byte_stuffer_send_frame(link, data, size); }
53}
54
55TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) {
56 EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
57 uint8_t data[] = {1, 2};
58 validator_recv_frame(0, 0, 1);
59 validator_recv_frame(0, data, 2);
60 validator_recv_frame(0, data, 3);
61 validator_recv_frame(0, data, 4);
62}
63
64TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) {
65 uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
66 EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 1)));
67 validator_recv_frame(0, data, 5);
68}
69
70TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
71 uint8_t data[] = {0x44, 0, 0, 0, 0};
72 EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
73 validator_recv_frame(1, data, 5);
74}
75
76TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) {
77 uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA};
78 EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 4)));
79 validator_recv_frame(1, data, 8);
80}
81
82TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) {
83 uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
84 EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 5)));
85 validator_recv_frame(0, data, 9);
86}
87
88TEST_F(FrameValidator, sends_one_byte_with_correct_crc) {
89 uint8_t original[] = {0x44, 0, 0, 0, 0};
90 uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
91 EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
92 validator_send_frame(0, original, 1);
93}
94
95TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) {
96 uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
97 uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
98 EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
99 validator_send_frame(0, original, 5);
100}
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
deleted file mode 100644
index b81515bc5..000000000
--- a/quantum/serial_link/tests/rules.mk
+++ /dev/null
@@ -1,22 +0,0 @@
1serial_link_byte_stuffer_SRC :=\
2 $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \
3 $(SERIAL_PATH)/protocol/byte_stuffer.c
4
5serial_link_frame_validator_SRC := \
6 $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
7 $(SERIAL_PATH)/protocol/frame_validator.c
8
9serial_link_frame_router_SRC := \
10 $(SERIAL_PATH)/tests/frame_router_tests.cpp \
11 $(SERIAL_PATH)/protocol/byte_stuffer.c \
12 $(SERIAL_PATH)/protocol/frame_validator.c \
13 $(SERIAL_PATH)/protocol/frame_router.c
14
15serial_link_triple_buffered_object_SRC := \
16 $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \
17 $(SERIAL_PATH)/protocol/triple_buffered_object.c
18
19serial_link_transport_SRC := \
20 $(SERIAL_PATH)/tests/transport_tests.cpp \
21 $(SERIAL_PATH)/protocol/transport.c \
22 $(SERIAL_PATH)/protocol/triple_buffered_object.c
diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk
deleted file mode 100644
index c5edaf478..000000000
--- a/quantum/serial_link/tests/testlist.mk
+++ /dev/null
@@ -1,6 +0,0 @@
1TEST_LIST +=\
2 serial_link_byte_stuffer\
3 serial_link_frame_validator\
4 serial_link_frame_router\
5 serial_link_triple_buffered_object\
6 serial_link_transport
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
deleted file mode 100644
index cfd111046..000000000
--- a/quantum/serial_link/tests/transport_tests.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27
28using testing::_;
29using testing::Args;
30using testing::ElementsAreArray;
31
32extern "C" {
33#include "serial_link/protocol/transport.h"
34}
35
36struct test_object1 {
37 uint32_t test;
38};
39
40struct test_object2 {
41 uint32_t test1;
42 uint32_t test2;
43};
44
45MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
46MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
47SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
48
49static remote_object_t* test_remote_objects[] = {
50 REMOTE_OBJECT(master_to_slave),
51 REMOTE_OBJECT(master_to_single_slave),
52 REMOTE_OBJECT(slave_to_master),
53};
54
55class Transport : public testing::Test {
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
80Transport* Transport::Instance = nullptr;
81
82extern "C" {
83void signal_data_written(void) { Transport::Instance->signal_data_written(); }
84
85void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { Transport::Instance->router_send_frame(destination, data, size); }
86}
87
88TEST_F(Transport, write_to_local_signals_an_event) {
89 begin_write_master_to_slave();
90 EXPECT_CALL(*this, signal_data_written());
91 end_write_master_to_slave();
92 begin_write_slave_to_master();
93 EXPECT_CALL(*this, signal_data_written());
94 end_write_slave_to_master();
95 begin_write_master_to_single_slave(1);
96 EXPECT_CALL(*this, signal_data_written());
97 end_write_master_to_single_slave(1);
98}
99
100TEST_F(Transport, writes_from_master_to_all_slaves) {
101 update_transport();
102 test_object1* obj = begin_write_master_to_slave();
103 obj->test = 5;
104 EXPECT_CALL(*this, signal_data_written());
105 end_write_master_to_slave();
106 EXPECT_CALL(*this, router_send_frame(0xFF));
107 update_transport();
108 transport_recv_frame(0, sent_data.data(), sent_data.size());
109 test_object1* obj2 = read_master_to_slave();
110 EXPECT_NE(obj2, nullptr);
111 EXPECT_EQ(obj2->test, 5);
112}
113
114TEST_F(Transport, writes_from_slave_to_master) {
115 update_transport();
116 test_object1* obj = begin_write_slave_to_master();
117 obj->test = 7;
118 EXPECT_CALL(*this, signal_data_written());
119 end_write_slave_to_master();
120 EXPECT_CALL(*this, router_send_frame(0));
121 update_transport();
122 transport_recv_frame(3, sent_data.data(), sent_data.size());
123 test_object1* obj2 = read_slave_to_master(2);
124 EXPECT_EQ(read_slave_to_master(0), nullptr);
125 EXPECT_NE(obj2, nullptr);
126 EXPECT_EQ(obj2->test, 7);
127}
128
129TEST_F(Transport, writes_from_master_to_single_slave) {
130 update_transport();
131 test_object1* obj = begin_write_master_to_single_slave(3);
132 obj->test = 7;
133 EXPECT_CALL(*this, signal_data_written());
134 end_write_master_to_single_slave(3);
135 EXPECT_CALL(*this, router_send_frame(4));
136 update_transport();
137 transport_recv_frame(0, sent_data.data(), sent_data.size());
138 test_object1* obj2 = read_master_to_single_slave();
139 EXPECT_NE(obj2, nullptr);
140 EXPECT_EQ(obj2->test, 7);
141}
142
143TEST_F(Transport, ignores_object_with_invalid_id) {
144 update_transport();
145 test_object1* obj = begin_write_master_to_single_slave(3);
146 obj->test = 7;
147 EXPECT_CALL(*this, signal_data_written());
148 end_write_master_to_single_slave(3);
149 EXPECT_CALL(*this, router_send_frame(4));
150 update_transport();
151 sent_data[sent_data.size() - 1] = 44;
152 transport_recv_frame(0, sent_data.data(), sent_data.size());
153 test_object1* obj2 = read_master_to_single_slave();
154 EXPECT_EQ(obj2, nullptr);
155}
156
157TEST_F(Transport, ignores_object_with_size_too_small) {
158 update_transport();
159 test_object1* obj = begin_write_master_to_slave();
160 obj->test = 7;
161 EXPECT_CALL(*this, signal_data_written());
162 end_write_master_to_slave();
163 EXPECT_CALL(*this, router_send_frame(_));
164 update_transport();
165 sent_data[sent_data.size() - 2] = 0;
166 transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
167 test_object1* obj2 = read_master_to_slave();
168 EXPECT_EQ(obj2, nullptr);
169}
170
171TEST_F(Transport, ignores_object_with_size_too_big) {
172 update_transport();
173 test_object1* obj = begin_write_master_to_slave();
174 obj->test = 7;
175 EXPECT_CALL(*this, signal_data_written());
176 end_write_master_to_slave();
177 EXPECT_CALL(*this, router_send_frame(_));
178 update_transport();
179 sent_data.resize(sent_data.size() + 22);
180 sent_data[sent_data.size() - 1] = 0;
181 transport_recv_frame(0, sent_data.data(), sent_data.size());
182 test_object1* obj2 = read_master_to_slave();
183 EXPECT_EQ(obj2, nullptr);
184}
diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.cpp b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
deleted file mode 100644
index 8de9bfdeb..000000000
--- a/quantum/serial_link/tests/triple_buffered_object_tests.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26extern "C" {
27#include "serial_link/protocol/triple_buffered_object.h"
28}
29
30struct test_object {
31 uint8_t state;
32 uint32_t buffer[3];
33};
34
35test_object test_object;
36
37class TripleBufferedObject : public testing::Test {
38 public:
39 TripleBufferedObject() { triple_buffer_init((triple_buffer_object_t*)&test_object); }
40};
41
42TEST_F(TripleBufferedObject, writes_and_reads_object) {
43 *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
44 triple_buffer_end_write(&test_object);
45 EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC);
46}
47
48TEST_F(TripleBufferedObject, does_not_read_empty) { EXPECT_EQ(triple_buffer_read(&test_object), nullptr); }
49
50TEST_F(TripleBufferedObject, writes_twice_and_reads_object) {
51 *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
52 triple_buffer_end_write(&test_object);
53 *triple_buffer_begin_write(&test_object) = 0x44778899;
54 triple_buffer_end_write(&test_object);
55 EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899);
56}
57
58TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
59 *triple_buffer_begin_write(&test_object) = 1;
60 triple_buffer_end_write(&test_object);
61 uint32_t* read = triple_buffer_read(&test_object);
62 *triple_buffer_begin_write(&test_object) = 2;
63 triple_buffer_end_write(&test_object);
64 EXPECT_EQ(*read, 1);
65 EXPECT_EQ(*triple_buffer_read(&test_object), 2);
66 EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
67}
68
69TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
70 *triple_buffer_begin_write(&test_object) = 1;
71 triple_buffer_end_write(&test_object);
72 uint32_t* read = triple_buffer_read(&test_object);
73 *triple_buffer_begin_write(&test_object) = 2;
74 triple_buffer_end_write(&test_object);
75 *triple_buffer_begin_write(&test_object) = 3;
76 triple_buffer_end_write(&test_object);
77 EXPECT_EQ(*read, 1);
78 EXPECT_EQ(*triple_buffer_read(&test_object), 3);
79 EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
80}
diff --git a/show_options.mk b/show_options.mk
index 03008ccab..083106963 100644
--- a/show_options.mk
+++ b/show_options.mk
@@ -21,7 +21,6 @@ HARDWARE_OPTION_NAMES = \
21 RGBLIGHT_CUSTOM_DRIVER \ 21 RGBLIGHT_CUSTOM_DRIVER \
22 RGB_MATRIX_ENABLE \ 22 RGB_MATRIX_ENABLE \
23 RGB_MATRIX_DRIVER \ 23 RGB_MATRIX_DRIVER \
24 SERIAL_LINK_ENABLE \
25 CIE1931_CURVE \ 24 CIE1931_CURVE \
26 MIDI_ENABLE \ 25 MIDI_ENABLE \
27 BLUETOOTH_ENABLE \ 26 BLUETOOTH_ENABLE \
diff --git a/testlist.mk b/testlist.mk
index b66b93d29..364fb339c 100644
--- a/testlist.mk
+++ b/testlist.mk
@@ -3,7 +3,6 @@ FULL_TESTS := $(TEST_LIST)
3 3
4include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk 4include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk
5include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk 5include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk
6include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk
7include $(ROOT_DIR)/tmk_core/common/test/testlist.mk 6include $(ROOT_DIR)/tmk_core/common/test/testlist.mk
8 7
9define VALIDATE_TEST_LIST 8define VALIDATE_TEST_LIST
diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c
index 68b92d8b4..de24b463b 100644
--- a/tmk_core/common/sync_timer.c
+++ b/tmk_core/common/sync_timer.c
@@ -26,7 +26,7 @@ SOFTWARE.
26#include "sync_timer.h" 26#include "sync_timer.h"
27#include "keyboard.h" 27#include "keyboard.h"
28 28
29#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) 29#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
30volatile int32_t sync_timer_ms; 30volatile int32_t sync_timer_ms;
31 31
32void sync_timer_init(void) { sync_timer_ms = 0; } 32void sync_timer_init(void) { sync_timer_ms = 0; }
diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h
index 744e2b50d..9ddef45bb 100644
--- a/tmk_core/common/sync_timer.h
+++ b/tmk_core/common/sync_timer.h
@@ -32,7 +32,7 @@ SOFTWARE.
32extern "C" { 32extern "C" {
33#endif 33#endif
34 34
35#if (defined(SPLIT_KEYBOARD) || defined(SERIAL_LINK_ENABLE)) && !defined(DISABLE_SYNC_TIMER) 35#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
36void sync_timer_init(void); 36void sync_timer_init(void);
37void sync_timer_update(uint32_t time); 37void sync_timer_update(uint32_t time);
38uint16_t sync_timer_read(void); 38uint16_t sync_timer_read(void);
diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c
index 26181d8c7..c860328c8 100644
--- a/tmk_core/protocol/chibios/chibios.c
+++ b/tmk_core/protocol/chibios/chibios.c
@@ -43,9 +43,6 @@
43#ifdef SLEEP_LED_ENABLE 43#ifdef SLEEP_LED_ENABLE
44# include "sleep_led.h" 44# include "sleep_led.h"
45#endif 45#endif
46#ifdef SERIAL_LINK_ENABLE
47# include "serial_link/system/serial_link.h"
48#endif
49#ifdef MIDI_ENABLE 46#ifdef MIDI_ENABLE
50# include "qmk_midi.h" 47# include "qmk_midi.h"
51#endif 48#endif
@@ -154,15 +151,11 @@ void protocol_init(void) {
154 setup_midi(); 151 setup_midi();
155#endif 152#endif
156 153
157#ifdef SERIAL_LINK_ENABLE
158 init_serial_link();
159#endif
160
161 host_driver_t *driver = NULL; 154 host_driver_t *driver = NULL;
162 155
163 /* Wait until the USB or serial link is active */ 156 /* Wait until USB is active */
164 while (true) { 157 while (true) {
165#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE) 158#if defined(WAIT_FOR_USB)
166 if (USB_DRIVER.state == USB_ACTIVE) { 159 if (USB_DRIVER.state == USB_ACTIVE) {
167 driver = &chibios_driver; 160 driver = &chibios_driver;
168 break; 161 break;
@@ -171,13 +164,6 @@ void protocol_init(void) {
171 driver = &chibios_driver; 164 driver = &chibios_driver;
172 break; 165 break;
173#endif 166#endif
174#ifdef SERIAL_LINK_ENABLE
175 if (is_serial_link_connected()) {
176 driver = get_serial_link_driver();
177 break;
178 }
179 serial_link_update();
180#endif
181 wait_ms(50); 167 wait_ms(50);
182 } 168 }
183 169
@@ -209,9 +195,6 @@ void protocol_task(void) {
209 print("[s]"); 195 print("[s]");
210 while (USB_DRIVER.state == USB_SUSPENDED) { 196 while (USB_DRIVER.state == USB_SUSPENDED) {
211 /* Do this in the suspended state */ 197 /* Do this in the suspended state */
212# ifdef SERIAL_LINK_ENABLE
213 serial_link_update();
214# endif
215 suspend_power_down(); // on AVR this deep sleeps for 15ms 198 suspend_power_down(); // on AVR this deep sleeps for 15ms
216 /* Remote wakeup */ 199 /* Remote wakeup */
217 if (suspend_wakeup_condition()) { 200 if (suspend_wakeup_condition()) {