2 Copyright 2018 Massdrop Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "samd51j18a.h"
19 #include "tmk_core/common/keyboard.h"
23 #include "host_driver.h"
24 #include "keycode_config.h"
28 //From protocol directory
29 #include "arm_atsam_protocol.h"
31 //From keyboard's directory
32 #include "config_led.h"
34 void main_subtasks(void);
35 uint8_t keyboard_leds(void);
36 void send_keyboard(report_keyboard_t *report);
37 void send_mouse(report_mouse_t *report);
38 void send_system(uint16_t data);
39 void send_consumer(uint16_t data);
41 host_driver_t arm_atsam_driver = {
51 uint8_t keyboard_leds(void)
54 if (keymap_config.nkro)
55 return udi_hid_nkro_report_set;
58 return udi_hid_kbd_report_set;
61 void send_keyboard(report_keyboard_t *report)
66 if (!keymap_config.nkro)
69 while (udi_hid_kbd_b_report_trans_ongoing) { main_subtasks(); } //Run other tasks while waiting for USB to be free
71 irqflags = __get_PRIMASK();
75 memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE);
76 udi_hid_kbd_b_report_valid = 1;
77 udi_hid_kbd_send_report();
80 __set_PRIMASK(irqflags);
85 while (udi_hid_nkro_b_report_trans_ongoing) { main_subtasks(); } //Run other tasks while waiting for USB to be free
87 irqflags = __get_PRIMASK();
91 memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
92 udi_hid_nkro_b_report_valid = 1;
93 udi_hid_nkro_send_report();
96 __set_PRIMASK(irqflags);
101 void send_mouse(report_mouse_t *report)
103 #ifdef MOUSEKEY_ENABLE
106 irqflags = __get_PRIMASK();
110 memcpy(udi_hid_mou_report, report, UDI_HID_MOU_REPORT_SIZE);
111 udi_hid_mou_b_report_valid = 1;
112 udi_hid_mou_send_report();
115 __set_PRIMASK(irqflags);
116 #endif //MOUSEKEY_ENABLE
119 void send_system(uint16_t data)
121 #ifdef EXTRAKEY_ENABLE
124 irqflags = __get_PRIMASK();
128 udi_hid_exk_report.desc.report_id = REPORT_ID_SYSTEM;
129 if (data != 0) data = data - SYSTEM_POWER_DOWN + 1;
130 udi_hid_exk_report.desc.report_data = data;
131 udi_hid_exk_b_report_valid = 1;
132 udi_hid_exk_send_report();
135 __set_PRIMASK(irqflags);
136 #endif //EXTRAKEY_ENABLE
139 void send_consumer(uint16_t data)
141 #ifdef EXTRAKEY_ENABLE
144 irqflags = __get_PRIMASK();
148 udi_hid_exk_report.desc.report_id = REPORT_ID_CONSUMER;
149 udi_hid_exk_report.desc.report_data = data;
150 udi_hid_exk_b_report_valid = 1;
151 udi_hid_exk_send_report();
154 __set_PRIMASK(irqflags);
155 #endif //EXTRAKEY_ENABLE
160 void main_subtask_usb_state(void)
162 if (usb_state == USB_STATE_POWERDOWN)
164 uint32_t timer_led = timer_read32();
169 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
171 I2C3733_Control_Set(0);
174 while (usb_state == USB_STATE_POWERDOWN)
176 if (timer_read32() - timer_led > 1000) led_off; //Good to indicate went to sleep, but only for a second
180 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
182 I2C3733_Control_Set(1);
189 void main_subtask_led(void)
194 void main_subtask_power_check(void)
196 static uint64_t next_5v_checkup = 0;
198 if (CLK_get_ms() > next_5v_checkup)
200 next_5v_checkup = CLK_get_ms() + 5;
202 v_5v = adc_get(ADC_5V);
203 v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v;
209 void main_subtask_usb_extra_device(void)
211 static uint64_t next_usb_checkup = 0;
213 if (CLK_get_ms() > next_usb_checkup)
215 next_usb_checkup = CLK_get_ms() + 10;
217 USB_HandleExtraDevice();
221 void main_subtasks(void)
223 main_subtask_usb_state();
225 main_subtask_power_check();
226 main_subtask_usb_extra_device();
248 DBGC(DC_MAIN_UDC_START_BEGIN);
250 DBGC(DC_MAIN_UDC_START_COMPLETE);
252 DBGC(DC_MAIN_CDC_INIT_BEGIN);
254 DBGC(DC_MAIN_CDC_INIT_COMPLETE);
256 while (USB2422_Port_Detect_Init() == 0) {}
263 while (I2C3733_Init_Control() != 1) {}
264 while (I2C3733_Init_Drivers() != 1) {}
270 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
271 I2C_LED_Q_ONOFF(g_drvid); //Queue data
277 host_set_driver(&arm_atsam_driver);
279 #ifdef CONSOLE_ENABLE
280 uint64_t next_print = 0;
281 #endif //CONSOLE_ENABLE
283 v_5v_avg = adc_get(ADC_5V);
285 debug_code_disable();
291 main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
293 #ifdef CONSOLE_ENABLE
294 if (CLK_get_ms() > next_print)
296 next_print = CLK_get_ms() + 250;
297 //Add any debug information here that you want to see very often
298 //dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired);
300 #endif //CONSOLE_ENABLE