aboutsummaryrefslogtreecommitdiff
path: root/quantum/serial_link/system/serial_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/serial_link/system/serial_link.c')
-rw-r--r--quantum/serial_link/system/serial_link.c250
1 files changed, 0 insertions, 250 deletions
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; }