aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action_tapping.c2
-rw-r--r--tmk_core/common/avr/sleep_led.c (renamed from tmk_core/common/sleep_led.c)0
-rw-r--r--tmk_core/common/bootmagic.c7
-rw-r--r--tmk_core/common/chibios/bootloader.c47
-rw-r--r--tmk_core/common/chibios/eeprom.c588
-rw-r--r--tmk_core/common/chibios/printf.c240
-rw-r--r--tmk_core/common/chibios/printf.h111
-rw-r--r--tmk_core/common/chibios/sleep_led.c226
-rw-r--r--tmk_core/common/chibios/suspend.c65
-rw-r--r--tmk_core/common/chibios/timer.c27
-rw-r--r--tmk_core/common/command.c23
-rw-r--r--tmk_core/common/eeconfig.c (renamed from tmk_core/common/avr/eeconfig.c)2
-rw-r--r--tmk_core/common/eeprom.h22
-rw-r--r--tmk_core/common/magic.c4
-rw-r--r--tmk_core/common/print.c8
-rw-r--r--tmk_core/common/print.h10
-rw-r--r--tmk_core/common/progmem.h4
-rw-r--r--tmk_core/common/report.h5
-rw-r--r--tmk_core/common/wait.h8
19 files changed, 1378 insertions, 21 deletions
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
index ff78d7f2a..e16e11be7 100644
--- a/tmk_core/common/action_tapping.c
+++ b/tmk_core/common/action_tapping.c
@@ -257,7 +257,7 @@ bool process_tapping(keyrecord_t *keyp)
257 return true; 257 return true;
258 } 258 }
259 } else { 259 } else {
260 if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); 260 if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n") {};
261 process_record(keyp); 261 process_record(keyp);
262 return true; 262 return true;
263 } 263 }
diff --git a/tmk_core/common/sleep_led.c b/tmk_core/common/avr/sleep_led.c
index dab3eb0f3..dab3eb0f3 100644
--- a/tmk_core/common/sleep_led.c
+++ b/tmk_core/common/avr/sleep_led.c
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
index 30e8a0f20..90275a18b 100644
--- a/tmk_core/common/bootmagic.c
+++ b/tmk_core/common/bootmagic.c
@@ -1,6 +1,6 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <stdbool.h> 2#include <stdbool.h>
3#include <util/delay.h> 3#include "wait.h"
4#include "matrix.h" 4#include "matrix.h"
5#include "bootloader.h" 5#include "bootloader.h"
6#include "debug.h" 6#include "debug.h"
@@ -10,6 +10,7 @@
10#include "eeconfig.h" 10#include "eeconfig.h"
11#include "bootmagic.h" 11#include "bootmagic.h"
12 12
13keymap_config_t keymap_config;
13 14
14void bootmagic(void) 15void bootmagic(void)
15{ 16{
@@ -19,9 +20,9 @@ void bootmagic(void)
19 } 20 }
20 21
21 /* do scans in case of bounce */ 22 /* do scans in case of bounce */
22 print("boogmagic scan: ... "); 23 print("bootmagic scan: ... ");
23 uint8_t scan = 100; 24 uint8_t scan = 100;
24 while (scan--) { matrix_scan(); _delay_ms(10); } 25 while (scan--) { matrix_scan(); wait_ms(10); }
25 print("done.\n"); 26 print("done.\n");
26 27
27 /* bootmagic skip */ 28 /* bootmagic skip */
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c
new file mode 100644
index 000000000..8a533ab6f
--- /dev/null
+++ b/tmk_core/common/chibios/bootloader.c
@@ -0,0 +1,47 @@
1#include "bootloader.h"
2
3#include "ch.h"
4#include "hal.h"
5
6#ifdef STM32_BOOTLOADER_ADDRESS
7/* STM32 */
8
9#if defined(STM32F0XX)
10/* This code should be checked whether it runs correctly on platforms */
11#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
12extern uint32_t __ram0_end__;
13
14void bootloader_jump(void) {
15 *((unsigned long *)(SYMVAL(__ram0_end__) - 4)) = 0xDEADBEEF; // set magic flag => reset handler will jump into boot loader
16 NVIC_SystemReset();
17}
18
19#else /* defined(STM32F0XX) */
20#error Check that the bootloader code works on your platform and add it to bootloader.c!
21#endif /* defined(STM32F0XX) */
22
23#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
24/* Kinetis */
25
26#if defined(KIIBOHD_BOOTLOADER)
27/* Kiibohd Bootloader (MCHCK and Infinity KB) */
28#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
29const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
30void bootloader_jump(void) {
31 __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
32 // request reset
33 SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
34}
35
36#else /* defined(KIIBOHD_BOOTLOADER) */
37/* Default for Kinetis - expecting an ARM Teensy */
38void bootloader_jump(void) {
39 chThdSleepMilliseconds(100);
40 __BKPT(0);
41}
42#endif /* defined(KIIBOHD_BOOTLOADER) */
43
44#else /* neither STM32 nor KINETIS */
45__attribute__((weak))
46void bootloader_jump(void) {}
47#endif \ No newline at end of file
diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom.c
new file mode 100644
index 000000000..5ff8ee86f
--- /dev/null
+++ b/tmk_core/common/chibios/eeprom.c
@@ -0,0 +1,588 @@
1#include "ch.h"
2#include "hal.h"
3
4#include "eeconfig.h"
5
6/*************************************/
7/* Hardware backend */
8/* */
9/* Code from PJRC/Teensyduino */
10/*************************************/
11
12/* Teensyduino Core Library
13 * http://www.pjrc.com/teensy/
14 * Copyright (c) 2013 PJRC.COM, LLC.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining
17 * a copy of this software and associated documentation files (the
18 * "Software"), to deal in the Software without restriction, including
19 * without limitation the rights to use, copy, modify, merge, publish,
20 * distribute, sublicense, and/or sell copies of the Software, and to
21 * permit persons to whom the Software is furnished to do so, subject to
22 * the following conditions:
23 *
24 * 1. The above copyright notice and this permission notice shall be
25 * included in all copies or substantial portions of the Software.
26 *
27 * 2. If the Software is incorporated into a build system that allows
28 * selection among a list of target devices, then similar target
29 * devices manufactured by PJRC.COM must be included in the list of
30 * target devices and selectable in the same manner.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
36 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
37 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
38 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 * SOFTWARE.
40 */
41
42
43#if defined(K20x) /* chip selection */
44/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
45
46// The EEPROM is really RAM with a hardware-based backup system to
47// flash memory. Selecting a smaller size EEPROM allows more wear
48// leveling, for higher write endurance. If you edit this file,
49// set this to the smallest size your application can use. Also,
50// due to Freescale's implementation, writing 16 or 32 bit words
51// (aligned to 2 or 4 byte boundaries) has twice the endurance
52// compared to writing 8 bit bytes.
53//
54#define EEPROM_SIZE 32
55
56// Writing unaligned 16 or 32 bit data is handled automatically when
57// this is defined, but at a cost of extra code size. Without this,
58// any unaligned write will cause a hard fault exception! If you're
59// absolutely sure all 16 and 32 bit writes will be aligned, you can
60// remove the extra unnecessary code.
61//
62#define HANDLE_UNALIGNED_WRITES
63
64// Minimum EEPROM Endurance
65// ------------------------
66#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
67 #define EEESIZE 0x33
68#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
69 #define EEESIZE 0x34
70#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
71 #define EEESIZE 0x35
72#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
73 #define EEESIZE 0x36
74#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
75 #define EEESIZE 0x37
76#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
77 #define EEESIZE 0x38
78#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
79 #define EEESIZE 0x39
80#endif
81
82void eeprom_initialize(void)
83{
84 uint32_t count=0;
85 uint16_t do_flash_cmd[] = {
86 0xf06f, 0x037f, 0x7003, 0x7803,
87 0xf013, 0x0f80, 0xd0fb, 0x4770};
88 uint8_t status;
89
90 if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
91 // FlexRAM is configured as traditional RAM
92 // We need to reconfigure for EEPROM usage
93 FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
94 FTFL->FCCOB4 = EEESIZE; // EEPROM Size
95 FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
96 __disable_irq();
97 // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
98 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
99 __enable_irq();
100 status = FTFL->FSTAT;
101 if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
102 FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
103 return; // error
104 }
105 }
106 // wait for eeprom to become ready (is this really necessary?)
107 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
108 if (++count > 20000) break;
109 }
110}
111
112#define FlexRAM ((uint8_t *)0x14000000)
113
114uint8_t eeprom_read_byte(const uint8_t *addr)
115{
116 uint32_t offset = (uint32_t)addr;
117 if (offset >= EEPROM_SIZE) return 0;
118 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
119 return FlexRAM[offset];
120}
121
122uint16_t eeprom_read_word(const uint16_t *addr)
123{
124 uint32_t offset = (uint32_t)addr;
125 if (offset >= EEPROM_SIZE-1) return 0;
126 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
127 return *(uint16_t *)(&FlexRAM[offset]);
128}
129
130uint32_t eeprom_read_dword(const uint32_t *addr)
131{
132 uint32_t offset = (uint32_t)addr;
133 if (offset >= EEPROM_SIZE-3) return 0;
134 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
135 return *(uint32_t *)(&FlexRAM[offset]);
136}
137
138void eeprom_read_block(void *buf, const void *addr, uint32_t len)
139{
140 uint32_t offset = (uint32_t)addr;
141 uint8_t *dest = (uint8_t *)buf;
142 uint32_t end = offset + len;
143
144 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
145 if (end > EEPROM_SIZE) end = EEPROM_SIZE;
146 while (offset < end) {
147 *dest++ = FlexRAM[offset++];
148 }
149}
150
151int eeprom_is_ready(void)
152{
153 return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
154}
155
156static void flexram_wait(void)
157{
158 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
159 // TODO: timeout
160 }
161}
162
163void eeprom_write_byte(uint8_t *addr, uint8_t value)
164{
165 uint32_t offset = (uint32_t)addr;
166
167 if (offset >= EEPROM_SIZE) return;
168 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
169 if (FlexRAM[offset] != value) {
170 FlexRAM[offset] = value;
171 flexram_wait();
172 }
173}
174
175void eeprom_write_word(uint16_t *addr, uint16_t value)
176{
177 uint32_t offset = (uint32_t)addr;
178
179 if (offset >= EEPROM_SIZE-1) return;
180 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
181#ifdef HANDLE_UNALIGNED_WRITES
182 if ((offset & 1) == 0) {
183#endif
184 if (*(uint16_t *)(&FlexRAM[offset]) != value) {
185 *(uint16_t *)(&FlexRAM[offset]) = value;
186 flexram_wait();
187 }
188#ifdef HANDLE_UNALIGNED_WRITES
189 } else {
190 if (FlexRAM[offset] != value) {
191 FlexRAM[offset] = value;
192 flexram_wait();
193 }
194 if (FlexRAM[offset + 1] != (value >> 8)) {
195 FlexRAM[offset + 1] = value >> 8;
196 flexram_wait();
197 }
198 }
199#endif
200}
201
202void eeprom_write_dword(uint32_t *addr, uint32_t value)
203{
204 uint32_t offset = (uint32_t)addr;
205
206 if (offset >= EEPROM_SIZE-3) return;
207 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
208#ifdef HANDLE_UNALIGNED_WRITES
209 switch (offset & 3) {
210 case 0:
211#endif
212 if (*(uint32_t *)(&FlexRAM[offset]) != value) {
213 *(uint32_t *)(&FlexRAM[offset]) = value;
214 flexram_wait();
215 }
216 return;
217#ifdef HANDLE_UNALIGNED_WRITES
218 case 2:
219 if (*(uint16_t *)(&FlexRAM[offset]) != value) {
220 *(uint16_t *)(&FlexRAM[offset]) = value;
221 flexram_wait();
222 }
223 if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
224 *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
225 flexram_wait();
226 }
227 return;
228 default:
229 if (FlexRAM[offset] != value) {
230 FlexRAM[offset] = value;
231 flexram_wait();
232 }
233 if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
234 *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
235 flexram_wait();
236 }
237 if (FlexRAM[offset + 3] != (value >> 24)) {
238 FlexRAM[offset + 3] = value >> 24;
239 flexram_wait();
240 }
241 }
242#endif
243}
244
245void eeprom_write_block(const void *buf, void *addr, uint32_t len)
246{
247 uint32_t offset = (uint32_t)addr;
248 const uint8_t *src = (const uint8_t *)buf;
249
250 if (offset >= EEPROM_SIZE) return;
251 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
252 if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
253 if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
254 while (len > 0) {
255 uint32_t lsb = offset & 3;
256 if (lsb == 0 && len >= 4) {
257 // write aligned 32 bits
258 uint32_t val32;
259 val32 = *src++;
260 val32 |= (*src++ << 8);
261 val32 |= (*src++ << 16);
262 val32 |= (*src++ << 24);
263 if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
264 *(uint32_t *)(&FlexRAM[offset]) = val32;
265 flexram_wait();
266 }
267 offset += 4;
268 len -= 4;
269 } else if ((lsb == 0 || lsb == 2) && len >= 2) {
270 // write aligned 16 bits
271 uint16_t val16;
272 val16 = *src++;
273 val16 |= (*src++ << 8);
274 if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
275 *(uint16_t *)(&FlexRAM[offset]) = val16;
276 flexram_wait();
277 }
278 offset += 2;
279 len -= 2;
280 } else {
281 // write 8 bits
282 uint8_t val8 = *src++;
283 if (FlexRAM[offset] != val8) {
284 FlexRAM[offset] = val8;
285 flexram_wait();
286 }
287 offset++;
288 len--;
289 }
290 }
291}
292
293/*
294void do_flash_cmd(volatile uint8_t *fstat)
295{
296 *fstat = 0x80;
297 while ((*fstat & 0x80) == 0) ; // wait
298}
29900000000 <do_flash_cmd>:
300 0: f06f 037f mvn.w r3, #127 ; 0x7f
301 4: 7003 strb r3, [r0, #0]
302 6: 7803 ldrb r3, [r0, #0]
303 8: f013 0f80 tst.w r3, #128 ; 0x80
304 c: d0fb beq.n 6 <do_flash_cmd+0x6>
305 e: 4770 bx lr
306*/
307
308#elif defined(KL2x) /* chip selection */
309/* Teensy LC (emulated) */
310
311#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
312
313extern uint32_t __eeprom_workarea_start__;
314extern uint32_t __eeprom_workarea_end__;
315
316#define EEPROM_SIZE 128
317
318static uint32_t flashend = 0;
319
320void eeprom_initialize(void)
321{
322 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
323
324 do {
325 if (*p++ == 0xFFFF) {
326 flashend = (uint32_t)(p - 2);
327 return;
328 }
329 } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
330 flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
331}
332
333uint8_t eeprom_read_byte(const uint8_t *addr)
334{
335 uint32_t offset = (uint32_t)addr;
336 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
337 const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
338 uint16_t val;
339 uint8_t data=0xFF;
340
341 if (!end) {
342 eeprom_initialize();
343 end = (const uint16_t *)((uint32_t)flashend);
344 }
345 if (offset < EEPROM_SIZE) {
346 while (p <= end) {
347 val = *p++;
348 if ((val & 255) == offset) data = val >> 8;
349 }
350 }
351 return data;
352}
353
354static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
355{
356 // with great power comes great responsibility....
357 uint32_t stat;
358 *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
359 *(uint32_t *)&(FTFA->FCCOB7) = data;
360 __disable_irq();
361 (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
362 __enable_irq();
363 stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
364 if (stat) {
365 FTFA->FSTAT = stat;
366 }
367 MCM->PLACR |= MCM_PLACR_CFCC;
368}
369
370void eeprom_write_byte(uint8_t *addr, uint8_t data)
371{
372 uint32_t offset = (uint32_t)addr;
373 const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
374 uint32_t i, val, flashaddr;
375 uint16_t do_flash_cmd[] = {
376 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
377 uint8_t buf[EEPROM_SIZE];
378
379 if (offset >= EEPROM_SIZE) return;
380 if (!end) {
381 eeprom_initialize();
382 end = (const uint16_t *)((uint32_t)flashend);
383 }
384 if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
385 val = (data << 8) | offset;
386 flashaddr = (uint32_t)end;
387 flashend = flashaddr;
388 if ((flashaddr & 2) == 0) {
389 val |= 0xFFFF0000;
390 } else {
391 val <<= 16;
392 val |= 0x0000FFFF;
393 }
394 flash_write(do_flash_cmd, flashaddr, val);
395 } else {
396 for (i=0; i < EEPROM_SIZE; i++) {
397 buf[i] = 0xFF;
398 }
399 val = 0;
400 for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
401 val = *p;
402 if ((val & 255) < EEPROM_SIZE) {
403 buf[val & 255] = val >> 8;
404 }
405 }
406 buf[offset] = data;
407 for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
408 *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
409 __disable_irq();
410 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
411 __enable_irq();
412 val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
413 if (val) FTFA->FSTAT = val;
414 MCM->PLACR |= MCM_PLACR_CFCC;
415 }
416 flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
417 for (i=0; i < EEPROM_SIZE; i++) {
418 if (buf[i] == 0xFF) continue;
419 if ((flashaddr & 2) == 0) {
420 val = (buf[i] << 8) | i;
421 } else {
422 val = val | (buf[i] << 24) | (i << 16);
423 flash_write(do_flash_cmd, flashaddr, val);
424 }
425 flashaddr += 2;
426 }
427 flashend = flashaddr;
428 if ((flashaddr & 2)) {
429 val |= 0xFFFF0000;
430 flash_write(do_flash_cmd, flashaddr, val);
431 }
432 }
433}
434
435/*
436void do_flash_cmd(volatile uint8_t *fstat)
437{
438 *fstat = 0x80;
439 while ((*fstat & 0x80) == 0) ; // wait
440}
44100000000 <do_flash_cmd>:
442 0: 2380 movs r3, #128 ; 0x80
443 2: 7003 strb r3, [r0, #0]
444 4: 7803 ldrb r3, [r0, #0]
445 6: b25b sxtb r3, r3
446 8: 2b00 cmp r3, #0
447 a: dafb bge.n 4 <do_flash_cmd+0x4>
448 c: 4770 bx lr
449*/
450
451
452uint16_t eeprom_read_word(const uint16_t *addr)
453{
454 const uint8_t *p = (const uint8_t *)addr;
455 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
456}
457
458uint32_t eeprom_read_dword(const uint32_t *addr)
459{
460 const uint8_t *p = (const uint8_t *)addr;
461 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
462 | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
463}
464
465void eeprom_read_block(void *buf, const void *addr, uint32_t len)
466{
467 const uint8_t *p = (const uint8_t *)addr;
468 uint8_t *dest = (uint8_t *)buf;
469 while (len--) {
470 *dest++ = eeprom_read_byte(p++);
471 }
472}
473
474int eeprom_is_ready(void)
475{
476 return 1;
477}
478
479void eeprom_write_word(uint16_t *addr, uint16_t value)
480{
481 uint8_t *p = (uint8_t *)addr;
482 eeprom_write_byte(p++, value);
483 eeprom_write_byte(p, value >> 8);
484}
485
486void eeprom_write_dword(uint32_t *addr, uint32_t value)
487{
488 uint8_t *p = (uint8_t *)addr;
489 eeprom_write_byte(p++, value);
490 eeprom_write_byte(p++, value >> 8);
491 eeprom_write_byte(p++, value >> 16);
492 eeprom_write_byte(p, value >> 24);
493}
494
495void eeprom_write_block(const void *buf, void *addr, uint32_t len)
496{
497 uint8_t *p = (uint8_t *)addr;
498 const uint8_t *src = (const uint8_t *)buf;
499 while (len--) {
500 eeprom_write_byte(p++, *src++);
501 }
502}
503
504#else
505// No EEPROM supported, so emulate it
506
507#define EEPROM_SIZE 32
508static uint8_t buffer[EEPROM_SIZE];
509
510uint8_t eeprom_read_byte(const uint8_t *addr) {
511 uint32_t offset = (uint32_t)addr;
512 return buffer[offset];
513}
514
515void eeprom_write_byte(uint8_t *addr, uint8_t value) {
516 uint32_t offset = (uint32_t)addr;
517 buffer[offset] = value;
518}
519
520uint16_t eeprom_read_word(const uint16_t *addr) {
521 const uint8_t *p = (const uint8_t *)addr;
522 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
523}
524
525uint32_t eeprom_read_dword(const uint32_t *addr) {
526 const uint8_t *p = (const uint8_t *)addr;
527 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
528 | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
529}
530
531void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
532 const uint8_t *p = (const uint8_t *)addr;
533 uint8_t *dest = (uint8_t *)buf;
534 while (len--) {
535 *dest++ = eeprom_read_byte(p++);
536 }
537}
538
539void eeprom_write_word(uint16_t *addr, uint16_t value) {
540 uint8_t *p = (uint8_t *)addr;
541 eeprom_write_byte(p++, value);
542 eeprom_write_byte(p, value >> 8);
543}
544
545void eeprom_write_dword(uint32_t *addr, uint32_t value) {
546 uint8_t *p = (uint8_t *)addr;
547 eeprom_write_byte(p++, value);
548 eeprom_write_byte(p++, value >> 8);
549 eeprom_write_byte(p++, value >> 16);
550 eeprom_write_byte(p, value >> 24);
551}
552
553void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
554 uint8_t *p = (uint8_t *)addr;
555 const uint8_t *src = (const uint8_t *)buf;
556 while (len--) {
557 eeprom_write_byte(p++, *src++);
558 }
559}
560
561#endif /* chip selection */
562// The update functions just calls write for now, but could probably be optimized
563
564void eeprom_update_byte(uint8_t *addr, uint8_t value) {
565 eeprom_write_byte(addr, value);
566}
567
568void eeprom_update_word(uint16_t *addr, uint16_t value) {
569 uint8_t *p = (uint8_t *)addr;
570 eeprom_write_byte(p++, value);
571 eeprom_write_byte(p, value >> 8);
572}
573
574void eeprom_update_dword(uint32_t *addr, uint32_t value) {
575 uint8_t *p = (uint8_t *)addr;
576 eeprom_write_byte(p++, value);
577 eeprom_write_byte(p++, value >> 8);
578 eeprom_write_byte(p++, value >> 16);
579 eeprom_write_byte(p, value >> 24);
580}
581
582void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
583 uint8_t *p = (uint8_t *)addr;
584 const uint8_t *src = (const uint8_t *)buf;
585 while (len--) {
586 eeprom_write_byte(p++, *src++);
587 }
588}
diff --git a/tmk_core/common/chibios/printf.c b/tmk_core/common/chibios/printf.c
new file mode 100644
index 000000000..72e3d4f8c
--- /dev/null
+++ b/tmk_core/common/chibios/printf.c
@@ -0,0 +1,240 @@
1/*
2 * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
3 * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
4 */
5
6/*
7File: printf.c
8
9Copyright (C) 2004 Kustaa Nyholm
10
11This library is free software; you can redistribute it and/or
12modify it under the terms of the GNU Lesser General Public
13License as published by the Free Software Foundation; either
14version 2.1 of the License, or (at your option) any later version.
15
16This library is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public
22License along with this library; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25*/
26
27#include "printf.h"
28
29typedef void (*putcf) (void*,char);
30static putcf stdout_putf;
31static void* stdout_putp;
32
33// this adds cca 400 bytes
34#define PRINTF_LONG_SUPPORT
35
36#ifdef PRINTF_LONG_SUPPORT
37
38static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
39 {
40 int n=0;
41 unsigned int d=1;
42 while (num/d >= base)
43 d*=base;
44 while (d!=0) {
45 int dgt = num / d;
46 num%=d;
47 d/=base;
48 if (n || dgt>0|| d==0) {
49 *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
50 ++n;
51 }
52 }
53 *bf=0;
54 }
55
56static void li2a (long num, char * bf)
57 {
58 if (num<0) {
59 num=-num;
60 *bf++ = '-';
61 }
62 uli2a(num,10,0,bf);
63 }
64
65#endif
66
67static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
68 {
69 int n=0;
70 unsigned int d=1;
71 while (num/d >= base)
72 d*=base;
73 while (d!=0) {
74 int dgt = num / d;
75 num%= d;
76 d/=base;
77 if (n || dgt>0 || d==0) {
78 *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
79 ++n;
80 }
81 }
82 *bf=0;
83 }
84
85static void i2a (int num, char * bf)
86 {
87 if (num<0) {
88 num=-num;
89 *bf++ = '-';
90 }
91 ui2a(num,10,0,bf);
92 }
93
94static int a2d(char ch)
95 {
96 if (ch>='0' && ch<='9')
97 return ch-'0';
98 else if (ch>='a' && ch<='f')
99 return ch-'a'+10;
100 else if (ch>='A' && ch<='F')
101 return ch-'A'+10;
102 else return -1;
103 }
104
105static char a2i(char ch, char** src,int base,int* nump)
106 {
107 char* p= *src;
108 int num=0;
109 int digit;
110 while ((digit=a2d(ch))>=0) {
111 if (digit>base) break;
112 num=num*base+digit;
113 ch=*p++;
114 }
115 *src=p;
116 *nump=num;
117 return ch;
118 }
119
120static void putchw(void* putp,putcf putf,int n, char z, char* bf)
121 {
122 char fc=z? '0' : ' ';
123 char ch;
124 char* p=bf;
125 while (*p++ && n > 0)
126 n--;
127 while (n-- > 0)
128 putf(putp,fc);
129 while ((ch= *bf++))
130 putf(putp,ch);
131 }
132
133void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
134 {
135 char bf[12];
136
137 char ch;
138
139
140 while ((ch=*(fmt++))) {
141 if (ch!='%')
142 putf(putp,ch);
143 else {
144 char lz=0;
145#ifdef PRINTF_LONG_SUPPORT
146 char lng=0;
147#endif
148 int w=0;
149 ch=*(fmt++);
150 if (ch=='0') {
151 ch=*(fmt++);
152 lz=1;
153 }
154 if (ch>='0' && ch<='9') {
155 ch=a2i(ch,&fmt,10,&w);
156 }
157#ifdef PRINTF_LONG_SUPPORT
158 if (ch=='l') {
159 ch=*(fmt++);
160 lng=1;
161 }
162#endif
163 switch (ch) {
164 case 0:
165 goto abort;
166 case 'u' : {
167#ifdef PRINTF_LONG_SUPPORT
168 if (lng)
169 uli2a(va_arg(va, unsigned long int),10,0,bf);
170 else
171#endif
172 ui2a(va_arg(va, unsigned int),10,0,bf);
173 putchw(putp,putf,w,lz,bf);
174 break;
175 }
176 case 'd' : {
177#ifdef PRINTF_LONG_SUPPORT
178 if (lng)
179 li2a(va_arg(va, unsigned long int),bf);
180 else
181#endif
182 i2a(va_arg(va, int),bf);
183 putchw(putp,putf,w,lz,bf);
184 break;
185 }
186 case 'x': case 'X' :
187#ifdef PRINTF_LONG_SUPPORT
188 if (lng)
189 uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
190 else
191#endif
192 ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
193 putchw(putp,putf,w,lz,bf);
194 break;
195 case 'c' :
196 putf(putp,(char)(va_arg(va, int)));
197 break;
198 case 's' :
199 putchw(putp,putf,w,0,va_arg(va, char*));
200 break;
201 case '%' :
202 putf(putp,ch);
203 default:
204 break;
205 }
206 }
207 }
208 abort:;
209 }
210
211
212void init_printf(void* putp,void (*putf) (void*,char))
213 {
214 stdout_putf=putf;
215 stdout_putp=putp;
216 }
217
218void tfp_printf(char *fmt, ...)
219 {
220 va_list va;
221 va_start(va,fmt);
222 tfp_format(stdout_putp,stdout_putf,fmt,va);
223 va_end(va);
224 }
225
226static void putcp(void* p,char c)
227 {
228 *(*((char**)p))++ = c;
229 }
230
231
232
233void tfp_sprintf(char* s,char *fmt, ...)
234 {
235 va_list va;
236 va_start(va,fmt);
237 tfp_format(&s,putcp,fmt,va);
238 putcp(&s,0);
239 va_end(va);
240 }
diff --git a/tmk_core/common/chibios/printf.h b/tmk_core/common/chibios/printf.h
new file mode 100644
index 000000000..678a100c6
--- /dev/null
+++ b/tmk_core/common/chibios/printf.h
@@ -0,0 +1,111 @@
1/*
2 * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
3 * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
4 */
5
6/*
7File: printf.h
8
9Copyright (C) 2004 Kustaa Nyholm
10
11This library is free software; you can redistribute it and/or
12modify it under the terms of the GNU Lesser General Public
13License as published by the Free Software Foundation; either
14version 2.1 of the License, or (at your option) any later version.
15
16This library is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19See the GNU Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public
22License along with this library; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25This library is realy just two files: 'printf.h' and 'printf.c'.
26
27They provide a simple and small (+200 loc) printf functionality to
28be used in embedded systems.
29
30I've found them so usefull in debugging that I do not bother with a
31debugger at all.
32
33They are distributed in source form, so to use them, just compile them
34into your project.
35
36Two printf variants are provided: printf and sprintf.
37
38The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
39
40Zero padding and field width are also supported.
41
42If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
43long specifier is also
44supported. Note that this will pull in some long math routines (pun intended!)
45and thus make your executable noticably longer.
46
47The memory foot print of course depends on the target cpu, compiler and
48compiler options, but a rough guestimate (based on a H8S target) is about
491.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
50Not too bad. Your milage may vary. By hacking the source code you can
51get rid of some hunred bytes, I'm sure, but personally I feel the balance of
52functionality and flexibility versus code size is close to optimal for
53many embedded systems.
54
55To use the printf you need to supply your own character output function,
56something like :
57
58 void putc ( void* p, char c)
59 {
60 while (!SERIAL_PORT_EMPTY) ;
61 SERIAL_PORT_TX_REGISTER = c;
62 }
63
64Before you can call printf you need to initialize it to use your
65character output function with something like:
66
67 init_printf(NULL,putc);
68
69Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
70the NULL (or any pointer) you pass into the 'init_printf' will eventually be
71passed to your 'putc' routine. This allows you to pass some storage space (or
72anything realy) to the character output function, if necessary.
73This is not often needed but it was implemented like that because it made
74implementing the sprintf function so neat (look at the source code).
75
76The code is re-entrant, except for the 'init_printf' function, so it
77is safe to call it from interupts too, although this may result in mixed output.
78If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
79
80The printf and sprintf functions are actually macros that translate to
81'tfp_printf' and 'tfp_sprintf'. This makes it possible
82to use them along with 'stdio.h' printf's in a single source file.
83You just need to undef the names before you include the 'stdio.h'.
84Note that these are not function like macros, so if you have variables
85or struct members with these names, things will explode in your face.
86Without variadic macros this is the best we can do to wrap these
87fucnction. If it is a problem just give up the macros and use the
88functions directly or rename them.
89
90For further details see source code.
91
92regs Kusti, 23.10.2004
93*/
94
95
96#ifndef __TFP_PRINTF__
97#define __TFP_PRINTF__
98
99#include <stdarg.h>
100
101void init_printf(void* putp,void (*putf) (void*,char));
102
103void tfp_printf(char *fmt, ...);
104void tfp_sprintf(char* s,char *fmt, ...);
105
106void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
107
108#define printf tfp_printf
109#define sprintf tfp_sprintf
110
111#endif
diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c
new file mode 100644
index 000000000..4c35cfcba
--- /dev/null
+++ b/tmk_core/common/chibios/sleep_led.c
@@ -0,0 +1,226 @@
1#include "ch.h"
2#include "hal.h"
3
4#include "led.h"
5#include "sleep_led.h"
6
7/* All right, we go the "software" way: timer, toggle LED in interrupt.
8 * Based on hasu's code for AVRs.
9 * Use LP timer on Kinetises, TIM14 on STM32F0.
10 */
11
12#if defined(KL2x) || defined(K20x)
13
14/* Use Low Power Timer (LPTMR) */
15#define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
16#define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
17
18#elif defined(STM32F0XX)
19
20/* Use TIM14 manually */
21#define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
22#define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
23
24#endif
25
26#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */
27
28/* Breathing Sleep LED brighness(PWM On period) table
29 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
30 *
31 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
32 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
33 */
34static const uint8_t breathing_table[64] = {
350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
3615, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
37255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
3815, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
39};
40
41/* interrupt handler */
42OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
43 OSAL_IRQ_PROLOGUE();
44
45 /* Software PWM
46 * timer:1111 1111 1111 1111
47 * \_____/\/ \_______/____ count(0-255)
48 * \ \______________ duration of step(4)
49 * \__________________ index of step table(0-63)
50 */
51
52 // this works for cca 65536 irqs/sec
53 static union {
54 uint16_t row;
55 struct {
56 uint8_t count:8;
57 uint8_t duration:2;
58 uint8_t index:6;
59 } pwm;
60 } timer = { .row = 0 };
61
62 timer.row++;
63
64 // LED on
65 if (timer.pwm.count == 0) {
66 led_set(1<<USB_LED_CAPS_LOCK);
67 }
68 // LED off
69 if (timer.pwm.count == breathing_table[timer.pwm.index]) {
70 led_set(0);
71 }
72
73 /* Reset the counter */
74 RESET_COUNTER;
75
76 OSAL_IRQ_EPILOGUE();
77}
78
79#endif /* common parts for known platforms */
80
81
82#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
83
84/* LPTMR clock options */
85#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
86#define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
87#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
88#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
89
90/* Work around inconsistencies in Freescale naming */
91#if !defined(SIM_SCGC5_LPTMR)
92#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
93#endif
94
95/* Initialise the timer */
96void sleep_led_init(void) {
97 /* Make sure the clock to the LPTMR is enabled */
98 SIM->SCGC5 |= SIM_SCGC5_LPTMR;
99 /* Reset LPTMR settings */
100 LPTMR0->CSR = 0;
101 /* Set the compare value */
102 LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
103
104 /* Set up clock source and prescaler */
105 /* Software PWM
106 * ______ ______ __
107 * | ON |___OFF___| ON |___OFF___| ....
108 * |<-------------->|<-------------->|<- ....
109 * PWM period PWM period
110 *
111 * R interrupts/period[resolution]
112 * F periods/second[frequency]
113 * R * F interrupts/second
114 */
115
116 /* === OPTION 1 === */
117 #if 0
118 // 1kHz LPO
119 // No prescaler => 1024 irqs/sec
120 // Note: this is too slow for a smooth breathe
121 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
122 #endif /* OPTION 1 */
123
124 /* === OPTION 2 === */
125 #if 1
126 // nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
127 MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
128 #if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
129 MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
130 #endif /* KL27 */
131 MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
132 // to work in stop mode, also MCG_C1_IREFSTEN
133 // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
134 // => approx F=61, R=256, duration = 4
135 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6);
136 #endif /* OPTION 2 */
137
138 /* === OPTION 3 === */
139 #if 0
140 // OSC output (external crystal), usually 8MHz or 16MHz
141 OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
142 // to work in stop mode, also OSC_CR_EREFSTEN
143 // Divide by 2^N
144 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
145 #endif /* OPTION 3 */
146 /* === END OPTIONS === */
147
148 /* Interrupt on TCF set (compare flag) */
149 nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
150 LPTMR0->CSR |= LPTMRx_CSR_TIE;
151}
152
153void sleep_led_enable(void) {
154 /* Enable the timer */
155 LPTMR0->CSR |= LPTMRx_CSR_TEN;
156}
157
158void sleep_led_disable(void) {
159 /* Disable the timer */
160 LPTMR0->CSR &= ~LPTMRx_CSR_TEN;
161}
162
163void sleep_led_toggle(void) {
164 /* Toggle the timer */
165 LPTMR0->CSR ^= LPTMRx_CSR_TEN;
166}
167
168#elif defined(STM32F0XX) /* platform selection: STM32F0XX */
169
170/* Initialise the timer */
171void sleep_led_init(void) {
172 /* enable clock */
173 rccEnableTIM14(FALSE); /* low power enable = FALSE */
174 rccResetTIM14();
175
176 /* prescale */
177 /* Assuming 48MHz internal clock */
178 /* getting cca 65484 irqs/sec */
179 STM32_TIM14->PSC = 733;
180
181 /* auto-reload */
182 /* 0 => interrupt every time */
183 STM32_TIM14->ARR = 3;
184
185 /* enable counter update event interrupt */
186 STM32_TIM14->DIER |= STM32_TIM_DIER_UIE;
187
188 /* register interrupt vector */
189 nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */
190}
191
192void sleep_led_enable(void) {
193 /* Enable the timer */
194 STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS;
195 /* URS => update event only on overflow; setting UG bit disabled */
196}
197
198void sleep_led_disable(void) {
199 /* Disable the timer */
200 STM32_TIM14->CR1 = 0;
201}
202
203void sleep_led_toggle(void) {
204 /* Toggle the timer */
205 STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN;
206}
207
208
209#else /* platform selection: not on familiar chips */
210
211void sleep_led_init(void) {
212}
213
214void sleep_led_enable(void) {
215 led_set(1<<USB_LED_CAPS_LOCK);
216}
217
218void sleep_led_disable(void) {
219 led_set(0);
220}
221
222void sleep_led_toggle(void) {
223 // not implemented
224}
225
226#endif /* platform selection */ \ No newline at end of file
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
new file mode 100644
index 000000000..6ca16034f
--- /dev/null
+++ b/tmk_core/common/chibios/suspend.c
@@ -0,0 +1,65 @@
1/* TODO */
2
3#include "ch.h"
4#include "hal.h"
5
6#include "matrix.h"
7#include "action.h"
8#include "action_util.h"
9#include "mousekey.h"
10#include "host.h"
11#include "backlight.h"
12#include "suspend.h"
13
14void suspend_idle(uint8_t time) {
15 // TODO: this is not used anywhere - what units is 'time' in?
16 chThdSleepMilliseconds(time);
17}
18
19void suspend_power_down(void) {
20 // TODO: figure out what to power down and how
21 // shouldn't power down TPM/FTM if we want a breathing LED
22 // also shouldn't power down USB
23
24 // on AVR, this enables the watchdog for 15ms (max), and goes to
25 // SLEEP_MODE_PWR_DOWN
26
27 chThdSleepMilliseconds(17);
28}
29
30__attribute__ ((weak)) void matrix_power_up(void) {}
31__attribute__ ((weak)) void matrix_power_down(void) {}
32bool suspend_wakeup_condition(void)
33{
34 matrix_power_up();
35 matrix_scan();
36 matrix_power_down();
37 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
38 if (matrix_get_row(r)) return true;
39 }
40 return false;
41}
42
43// run immediately after wakeup
44void suspend_wakeup_init(void)
45{
46 // clear keyboard state
47 // need to do it manually, because we're running from ISR
48 // and clear_keyboard() calls print
49 // so only clear the variables in memory
50 // the reports will be sent from main.c afterwards
51 // or if the PC asks for GET_REPORT
52 clear_mods();
53 clear_weak_mods();
54 clear_keys();
55#ifdef MOUSEKEY_ENABLE
56 mousekey_clear();
57#endif /* MOUSEKEY_ENABLE */
58#ifdef EXTRAKEY_ENABLE
59 host_system_send(0);
60 host_consumer_send(0);
61#endif /* EXTRAKEY_ENABLE */
62#ifdef BACKLIGHT_ENABLE
63 backlight_init();
64#endif /* BACKLIGHT_ENABLE */
65}
diff --git a/tmk_core/common/chibios/timer.c b/tmk_core/common/chibios/timer.c
new file mode 100644
index 000000000..3de4cc368
--- /dev/null
+++ b/tmk_core/common/chibios/timer.c
@@ -0,0 +1,27 @@
1#include "ch.h"
2
3#include "timer.h"
4
5void timer_init(void) {}
6
7void timer_clear(void) {}
8
9uint16_t timer_read(void)
10{
11 return (uint16_t)ST2MS(chVTGetSystemTime());
12}
13
14uint32_t timer_read32(void)
15{
16 return ST2MS(chVTGetSystemTime());
17}
18
19uint16_t timer_elapsed(uint16_t last)
20{
21 return (uint16_t)(ST2MS(chVTTimeElapsedSinceX(MS2ST(last))));
22}
23
24uint32_t timer_elapsed32(uint32_t last)
25{
26 return ST2MS(chVTTimeElapsedSinceX(MS2ST(last)));
27}
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index 187a2b949..084c9fe15 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <util/delay.h> 19#include "wait.h"
20#include "keycode.h" 20#include "keycode.h"
21#include "host.h" 21#include "host.h"
22#include "keymap.h" 22#include "keymap.h"
@@ -103,12 +103,14 @@ bool command_proc(uint8_t code)
103bool command_extra(uint8_t code) __attribute__ ((weak)); 103bool command_extra(uint8_t code) __attribute__ ((weak));
104bool command_extra(uint8_t code) 104bool command_extra(uint8_t code)
105{ 105{
106 (void)code;
106 return false; 107 return false;
107} 108}
108 109
109bool command_console_extra(uint8_t code) __attribute__ ((weak)); 110bool command_console_extra(uint8_t code) __attribute__ ((weak));
110bool command_console_extra(uint8_t code) 111bool command_console_extra(uint8_t code)
111{ 112{
113 (void)code;
112 return false; 114 return false;
113} 115}
114 116
@@ -217,8 +219,11 @@ static void print_version(void)
217 " " STR(BOOTLOADER_SIZE) "\n"); 219 " " STR(BOOTLOADER_SIZE) "\n");
218 220
219 print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) 221 print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
222#if defined(__AVR__)
220 " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ 223 " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
221 " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n"); 224 " AVR_ARCH: avr" STR(__AVR_ARCH__)
225#endif
226 "\n");
222 227
223 return; 228 return;
224} 229}
@@ -234,7 +239,7 @@ static void print_status(void)
234#ifdef NKRO_ENABLE 239#ifdef NKRO_ENABLE
235 print_val_hex8(keyboard_nkro); 240 print_val_hex8(keyboard_nkro);
236#endif 241#endif
237 print_val_hex32(timer_count); 242 print_val_hex32(timer_read32());
238 243
239#ifdef PROTOCOL_PJRC 244#ifdef PROTOCOL_PJRC
240 print_val_hex8(UDCON); 245 print_val_hex8(UDCON);
@@ -360,7 +365,7 @@ static bool command_common(uint8_t code)
360 stop_all_notes(); 365 stop_all_notes();
361 shutdown_user(); 366 shutdown_user();
362 #else 367 #else
363 _delay_ms(1000); 368 wait_ms(1000);
364 #endif 369 #endif
365 bootloader_jump(); // not return 370 bootloader_jump(); // not return
366 break; 371 break;
@@ -430,10 +435,11 @@ static bool command_common(uint8_t code)
430 case MAGIC_KC(MAGIC_KEY_NKRO): 435 case MAGIC_KC(MAGIC_KEY_NKRO):
431 clear_keyboard(); // clear to prevent stuck keys 436 clear_keyboard(); // clear to prevent stuck keys
432 keyboard_nkro = !keyboard_nkro; 437 keyboard_nkro = !keyboard_nkro;
433 if (keyboard_nkro) 438 if (keyboard_nkro) {
434 print("NKRO: on\n"); 439 print("NKRO: on\n");
435 else 440 } else {
436 print("NKRO: off\n"); 441 print("NKRO: off\n");
442 }
437 break; 443 break;
438#endif 444#endif
439 445
@@ -750,10 +756,11 @@ static bool mousekey_console(uint8_t code)
750 print("?"); 756 print("?");
751 return false; 757 return false;
752 } 758 }
753 if (mousekey_param) 759 if (mousekey_param) {
754 xprintf("M%d> ", mousekey_param); 760 xprintf("M%d> ", mousekey_param);
755 else 761 } else {
756 print("M>" ); 762 print("M>" );
763 }
757 return true; 764 return true;
758} 765}
759#endif 766#endif
diff --git a/tmk_core/common/avr/eeconfig.c b/tmk_core/common/eeconfig.c
index 656938fb3..140d2b85b 100644
--- a/tmk_core/common/avr/eeconfig.c
+++ b/tmk_core/common/eeconfig.c
@@ -1,6 +1,6 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <stdbool.h> 2#include <stdbool.h>
3#include <avr/eeprom.h> 3#include "eeprom.h"
4#include "eeconfig.h" 4#include "eeconfig.h"
5 5
6void eeconfig_init(void) 6void eeconfig_init(void)
diff --git a/tmk_core/common/eeprom.h b/tmk_core/common/eeprom.h
new file mode 100644
index 000000000..2cc2ccee3
--- /dev/null
+++ b/tmk_core/common/eeprom.h
@@ -0,0 +1,22 @@
1#ifndef TMK_CORE_COMMON_EEPROM_H_
2#define TMK_CORE_COMMON_EEPROM_H_
3
4#if defined(__AVR__)
5#include <avr/eeprom.h>
6#else
7uint8_t eeprom_read_byte (const uint8_t *__p);
8uint16_t eeprom_read_word (const uint16_t *__p);
9uint32_t eeprom_read_dword (const uint32_t *__p);
10void eeprom_read_block (void *__dst, const void *__src, uint32_t __n);
11void eeprom_write_byte (uint8_t *__p, uint8_t __value);
12void eeprom_write_word (uint16_t *__p, uint16_t __value);
13void eeprom_write_dword (uint32_t *__p, uint32_t __value);
14void eeprom_write_block (const void *__src, void *__dst, uint32_t __n);
15void eeprom_update_byte (uint8_t *__p, uint8_t __value);
16void eeprom_update_word (uint16_t *__p, uint16_t __value);
17void eeprom_update_dword (uint32_t *__p, uint32_t __value);
18void eeprom_update_block (const void *__src, void *__dst, uint32_t __n);
19#endif
20
21
22#endif /* TMK_CORE_COMMON_EEPROM_H_ */
diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c
index f21d1346c..194e4cc02 100644
--- a/tmk_core/common/magic.c
+++ b/tmk_core/common/magic.c
@@ -1,6 +1,8 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <stdbool.h> 2#include <stdbool.h>
3#if defined(__AVR__)
3#include <util/delay.h> 4#include <util/delay.h>
5#endif
4#include "matrix.h" 6#include "matrix.h"
5#include "bootloader.h" 7#include "bootloader.h"
6#include "debug.h" 8#include "debug.h"
@@ -33,4 +35,4 @@ void magic(void)
33 default_layer = eeconfig_read_default_layer(); 35 default_layer = eeconfig_read_default_layer();
34 default_layer_set((uint32_t)default_layer); 36 default_layer_set((uint32_t)default_layer);
35 37
36} \ No newline at end of file 38}
diff --git a/tmk_core/common/print.c b/tmk_core/common/print.c
index ca94e1e5d..00489557f 100644
--- a/tmk_core/common/print.c
+++ b/tmk_core/common/print.c
@@ -38,11 +38,15 @@ void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
38 xdev_out(sendchar_func); 38 xdev_out(sendchar_func);
39} 39}
40 40
41#elif defined(__arm__) 41#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
42
43// don't need anything extra
44
45#elif defined(__arm__) /* __AVR__ */
42 46
43// TODO 47// TODO
44//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { } 48//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
45 49
46#endif 50#endif /* __AVR__ */
47 51
48#endif 52#endif
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
index 4f3dde65a..0368bcd4a 100644
--- a/tmk_core/common/print.h
+++ b/tmk_core/common/print.h
@@ -47,7 +47,15 @@ extern "C"
47/* function pointer of sendchar to be used by print utility */ 47/* function pointer of sendchar to be used by print utility */
48void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); 48void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
49 49
50#elif defined(__arm__) 50#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
51
52#include "chibios/printf.h"
53
54#define print(s) printf(s)
55#define println(s) printf(s "\r\n")
56#define xprintf printf
57
58#elif defined(__arm__) /* __AVR__ */
51 59
52#include "mbed/xprintf.h" 60#include "mbed/xprintf.h"
53 61
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h
index 199b1bedf..5b2765625 100644
--- a/tmk_core/common/progmem.h
+++ b/tmk_core/common/progmem.h
@@ -5,8 +5,8 @@
5# include <avr/pgmspace.h> 5# include <avr/pgmspace.h>
6#elif defined(__arm__) 6#elif defined(__arm__)
7# define PROGMEM 7# define PROGMEM
8# define pgm_read_byte(p) *(p) 8# define pgm_read_byte(p) *((unsigned char*)p)
9# define pgm_read_word(p) *(p) 9# define pgm_read_word(p) *((uint16_t*)p)
10#endif 10#endif
11 11
12#endif 12#endif
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index f6c0a315d..0c799eca3 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -84,6 +84,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
84# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE 84# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
85# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2) 85# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
86# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) 86# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87#elif defined(PROTOCOL_CHIBIOS) && defined(NKRO_ENABLE)
88# include "protocol/chibios/usb_main.h"
89# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
90# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
91# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87 92
88#else 93#else
89# define KEYBOARD_REPORT_SIZE 8 94# define KEYBOARD_REPORT_SIZE 8
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h
index 40d00b0c7..82727be01 100644
--- a/tmk_core/common/wait.h
+++ b/tmk_core/common/wait.h
@@ -9,9 +9,13 @@ extern "C" {
9# include <util/delay.h> 9# include <util/delay.h>
10# define wait_ms(ms) _delay_ms(ms) 10# define wait_ms(ms) _delay_ms(ms)
11# define wait_us(us) _delay_us(us) 11# define wait_us(us) _delay_us(us)
12#elif defined(__arm__) 12#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
13# include "ch.h"
14# define wait_ms(ms) chThdSleepMilliseconds(ms)
15# define wait_us(us) chThdSleepMicroseconds(us)
16#elif defined(__arm__) /* __AVR__ */
13# include "wait_api.h" 17# include "wait_api.h"
14#endif 18#endif /* __AVR__ */
15 19
16#ifdef __cplusplus 20#ifdef __cplusplus
17} 21}