]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/serial_link/serial_link/system/serial_link.c
Remove CGreen make files
[qmk_firmware.git] / quantum / serial_link / serial_link / system / serial_link.c
1 /*
2 The MIT License (MIT)
3
4 Copyright (c) 2016 Fred Sundvik
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 #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 <stdbool.h>
33 #include "print.h"
34 #include "config.h"
35
36 static event_source_t new_data_event;
37 static bool serial_link_connected;
38 static bool is_master = false;
39
40 static uint8_t keyboard_leds(void);
41 static void send_keyboard(report_keyboard_t *report);
42 static void send_mouse(report_mouse_t *report);
43 static void send_system(uint16_t data);
44 static void send_consumer(uint16_t data);
45
46 host_driver_t serial_driver = {
47   keyboard_leds,
48   send_keyboard,
49   send_mouse,
50   send_system,
51   send_consumer
52 };
53
54 // Define these in your Config.h file
55 #ifndef SERIAL_LINK_BAUD
56 #error "Serial link baud is not set"
57 #endif
58
59 #ifndef SERIAL_LINK_THREAD_PRIORITY
60 #error "Serial link thread priority not set"
61 #endif
62
63 static SerialConfig config = {
64     .sc_speed = SERIAL_LINK_BAUD
65 };
66
67 //#define DEBUG_LINK_ERRORS
68
69 static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) {
70     const uint32_t buffer_size = 16;
71     uint8_t buffer[buffer_size];
72     uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size);
73     uint8_t* current = buffer;
74     uint8_t* end = current + bytes_read;
75     while(current < end) {
76         byte_stuffer_recv_byte(link, *current);
77         current++;
78     }
79     return bytes_read;
80 }
81
82 static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
83 #ifdef DEBUG_LINK_ERRORS
84     if (flags & SD_PARITY_ERROR) {
85         print(str);
86         print(" Parity error\n");
87     }
88     if (flags & SD_FRAMING_ERROR) {
89         print(str);
90         print(" Framing error\n");
91     }
92     if (flags & SD_OVERRUN_ERROR) {
93         print(str);
94         uint32_t size = qSpaceI(&(driver->iqueue));
95         xprintf(" Overrun error, queue size %d\n", size);
96
97     }
98     if (flags & SD_NOISE_ERROR) {
99         print(str);
100         print(" Noise error\n");
101     }
102     if (flags & SD_BREAK_DETECTED) {
103         print(str);
104         print(" Break detected\n");
105     }
106 #else
107     (void)str;
108     (void)flags;
109     (void)driver;
110 #endif
111 }
112
113 bool is_serial_link_master(void) {
114     return is_master;
115 }
116
117 // TODO: Optimize the stack size, this is probably way too big
118 static THD_WORKING_AREA(serialThreadStack, 1024);
119 static THD_FUNCTION(serialThread, arg) {
120     (void)arg;
121     event_listener_t new_data_listener;
122     event_listener_t sd1_listener;
123     event_listener_t sd2_listener;
124     chEvtRegister(&new_data_event, &new_data_listener, 0);
125     eventflags_t events = CHN_INPUT_AVAILABLE
126             | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED;
127     chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1),
128         &sd1_listener,
129         EVENT_MASK(1),
130         events);
131     chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2),
132         &sd2_listener,
133         EVENT_MASK(2),
134         events);
135     bool need_wait = false;
136     while(true) {
137         eventflags_t flags1 = 0;
138         eventflags_t flags2 = 0;
139         if (need_wait) {
140             eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000));
141             if (mask & EVENT_MASK(1)) {
142                 flags1 = chEvtGetAndClearFlags(&sd1_listener);
143                 print_error("DOWNLINK", flags1, &SD1);
144             }
145             if (mask & EVENT_MASK(2)) {
146                 flags2 = chEvtGetAndClearFlags(&sd2_listener);
147                 print_error("UPLINK", flags2, &SD2);
148             }
149         }
150
151         // Always stay as master, even if the USB goes into sleep mode
152         is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE;
153         router_set_master(is_master);
154
155         need_wait = true;
156         need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
157         need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
158         update_transport();
159     }
160 }
161
162 void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
163     if (link == DOWN_LINK) {
164         sdWrite(&SD1, data, size);
165     }
166     else {
167         sdWrite(&SD2, data, size);
168     }
169 }
170
171 static systime_t last_update = 0;
172
173 typedef struct {
174     matrix_row_t rows[MATRIX_ROWS];
175 } matrix_object_t;
176
177 static matrix_object_t last_matrix = {};
178
179 SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
180 MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
181
182 static remote_object_t* remote_objects[] = {
183     REMOTE_OBJECT(serial_link_connected),
184     REMOTE_OBJECT(keyboard_matrix),
185 };
186
187 void init_serial_link(void) {
188     serial_link_connected = false;
189     init_serial_link_hal();
190     add_remote_objects(remote_objects, sizeof(remote_objects)/sizeof(remote_object_t*));
191     init_byte_stuffer();
192     sdStart(&SD1, &config);
193     sdStart(&SD2, &config);
194     chEvtObjectInit(&new_data_event);
195     (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack),
196                               SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL);
197 }
198
199 void matrix_set_remote(matrix_row_t* rows, uint8_t index);
200
201 void serial_link_update(void) {
202     if (read_serial_link_connected()) {
203         serial_link_connected = true;
204     }
205
206     matrix_object_t matrix;
207     bool changed = false;
208     for(uint8_t i=0;i<MATRIX_ROWS;i++) {
209         matrix.rows[i] = matrix_get_row(i);
210         changed |= matrix.rows[i] != last_matrix.rows[i];
211     }
212
213     systime_t current_time = chVTGetSystemTimeX();
214     systime_t delta = current_time - last_update;
215     if (changed || delta > US2ST(1000)) {
216         last_update = current_time;
217         last_matrix = matrix;
218         matrix_object_t* m = begin_write_keyboard_matrix();
219         for(uint8_t i=0;i<MATRIX_ROWS;i++) {
220             m->rows[i] = matrix.rows[i];
221         }
222         end_write_keyboard_matrix();
223         *begin_write_serial_link_connected() = true;
224         end_write_serial_link_connected();
225     }
226
227     matrix_object_t* m = read_keyboard_matrix(0);
228     if (m) {
229         matrix_set_remote(m->rows, 0);
230     }
231 }
232
233 void signal_data_written(void) {
234     chEvtBroadcast(&new_data_event);
235 }
236
237 bool is_serial_link_connected(void) {
238     return serial_link_connected;
239 }
240
241 host_driver_t* get_serial_link_driver(void) {
242     return &serial_driver;
243 }
244
245 // NOTE: The driver does nothing, because the master handles everything
246 uint8_t keyboard_leds(void) {
247     return 0;
248 }
249
250 void send_keyboard(report_keyboard_t *report) {
251     (void)report;
252 }
253
254 void send_mouse(report_mouse_t *report) {
255     (void)report;
256 }
257
258 void send_system(uint16_t data) {
259     (void)data;
260 }
261
262 void send_consumer(uint16_t data) {
263     (void)data;
264 }
265