diff options
Diffstat (limited to 'tmk_core/common')
| -rw-r--r-- | tmk_core/common/action_tapping.c | 2 | ||||
| -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.c | 7 | ||||
| -rw-r--r-- | tmk_core/common/chibios/bootloader.c | 47 | ||||
| -rw-r--r-- | tmk_core/common/chibios/eeprom.c | 588 | ||||
| -rw-r--r-- | tmk_core/common/chibios/printf.c | 240 | ||||
| -rw-r--r-- | tmk_core/common/chibios/printf.h | 111 | ||||
| -rw-r--r-- | tmk_core/common/chibios/sleep_led.c | 226 | ||||
| -rw-r--r-- | tmk_core/common/chibios/suspend.c | 65 | ||||
| -rw-r--r-- | tmk_core/common/chibios/timer.c | 27 | ||||
| -rw-r--r-- | tmk_core/common/command.c | 23 | ||||
| -rw-r--r-- | tmk_core/common/eeconfig.c (renamed from tmk_core/common/avr/eeconfig.c) | 2 | ||||
| -rw-r--r-- | tmk_core/common/eeprom.h | 22 | ||||
| -rw-r--r-- | tmk_core/common/magic.c | 4 | ||||
| -rw-r--r-- | tmk_core/common/print.c | 8 | ||||
| -rw-r--r-- | tmk_core/common/print.h | 10 | ||||
| -rw-r--r-- | tmk_core/common/progmem.h | 4 | ||||
| -rw-r--r-- | tmk_core/common/report.h | 5 | ||||
| -rw-r--r-- | tmk_core/common/wait.h | 8 |
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 | ||
| 13 | keymap_config_t keymap_config; | ||
| 13 | 14 | ||
| 14 | void bootmagic(void) | 15 | void 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)) | ||
| 12 | extern uint32_t __ram0_end__; | ||
| 13 | |||
| 14 | void 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 | ||
| 29 | const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; | ||
| 30 | void 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 */ | ||
| 38 | void 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)) | ||
| 46 | void 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 | |||
| 82 | void 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 | |||
| 114 | uint8_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 | |||
| 122 | uint16_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 | |||
| 130 | uint32_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 | |||
| 138 | void 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 | |||
| 151 | int eeprom_is_ready(void) | ||
| 152 | { | ||
| 153 | return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static void flexram_wait(void) | ||
| 157 | { | ||
| 158 | while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { | ||
| 159 | // TODO: timeout | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | void 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 | |||
| 175 | void 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 | |||
| 202 | void 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 | |||
| 245 | void 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 | /* | ||
| 294 | void do_flash_cmd(volatile uint8_t *fstat) | ||
| 295 | { | ||
| 296 | *fstat = 0x80; | ||
| 297 | while ((*fstat & 0x80) == 0) ; // wait | ||
| 298 | } | ||
| 299 | 00000000 <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 | |||
| 313 | extern uint32_t __eeprom_workarea_start__; | ||
| 314 | extern uint32_t __eeprom_workarea_end__; | ||
| 315 | |||
| 316 | #define EEPROM_SIZE 128 | ||
| 317 | |||
| 318 | static uint32_t flashend = 0; | ||
| 319 | |||
| 320 | void 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 | |||
| 333 | uint8_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 | |||
| 354 | static 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 | |||
| 370 | void 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 | /* | ||
| 436 | void do_flash_cmd(volatile uint8_t *fstat) | ||
| 437 | { | ||
| 438 | *fstat = 0x80; | ||
| 439 | while ((*fstat & 0x80) == 0) ; // wait | ||
| 440 | } | ||
| 441 | 00000000 <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 | |||
| 452 | uint16_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 | |||
| 458 | uint32_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 | |||
| 465 | void 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 | |||
| 474 | int eeprom_is_ready(void) | ||
| 475 | { | ||
| 476 | return 1; | ||
| 477 | } | ||
| 478 | |||
| 479 | void 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 | |||
| 486 | void 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 | |||
| 495 | void 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 | ||
| 508 | static uint8_t buffer[EEPROM_SIZE]; | ||
| 509 | |||
| 510 | uint8_t eeprom_read_byte(const uint8_t *addr) { | ||
| 511 | uint32_t offset = (uint32_t)addr; | ||
| 512 | return buffer[offset]; | ||
| 513 | } | ||
| 514 | |||
| 515 | void eeprom_write_byte(uint8_t *addr, uint8_t value) { | ||
| 516 | uint32_t offset = (uint32_t)addr; | ||
| 517 | buffer[offset] = value; | ||
| 518 | } | ||
| 519 | |||
| 520 | uint16_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 | |||
| 525 | uint32_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 | |||
| 531 | void 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 | |||
| 539 | void 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 | |||
| 545 | void 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 | |||
| 553 | void 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 | |||
| 564 | void eeprom_update_byte(uint8_t *addr, uint8_t value) { | ||
| 565 | eeprom_write_byte(addr, value); | ||
| 566 | } | ||
| 567 | |||
| 568 | void 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 | |||
| 574 | void 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 | |||
| 582 | void 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 | /* | ||
| 7 | File: printf.c | ||
| 8 | |||
| 9 | Copyright (C) 2004 Kustaa Nyholm | ||
| 10 | |||
| 11 | This library is free software; you can redistribute it and/or | ||
| 12 | modify it under the terms of the GNU Lesser General Public | ||
| 13 | License as published by the Free Software Foundation; either | ||
| 14 | version 2.1 of the License, or (at your option) any later version. | ||
| 15 | |||
| 16 | This library is distributed in the hope that it will be useful, | ||
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | Lesser General Public License for more details. | ||
| 20 | |||
| 21 | You should have received a copy of the GNU Lesser General Public | ||
| 22 | License along with this library; if not, write to the Free Software | ||
| 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 24 | |||
| 25 | */ | ||
| 26 | |||
| 27 | #include "printf.h" | ||
| 28 | |||
| 29 | typedef void (*putcf) (void*,char); | ||
| 30 | static putcf stdout_putf; | ||
| 31 | static void* stdout_putp; | ||
| 32 | |||
| 33 | // this adds cca 400 bytes | ||
| 34 | #define PRINTF_LONG_SUPPORT | ||
| 35 | |||
| 36 | #ifdef PRINTF_LONG_SUPPORT | ||
| 37 | |||
| 38 | static 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 | |||
| 56 | static 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 | |||
| 67 | static 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 | |||
| 85 | static 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 | |||
| 94 | static 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 | |||
| 105 | static 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 | |||
| 120 | static 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 | |||
| 133 | void 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 | |||
| 212 | void init_printf(void* putp,void (*putf) (void*,char)) | ||
| 213 | { | ||
| 214 | stdout_putf=putf; | ||
| 215 | stdout_putp=putp; | ||
| 216 | } | ||
| 217 | |||
| 218 | void 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 | |||
| 226 | static void putcp(void* p,char c) | ||
| 227 | { | ||
| 228 | *(*((char**)p))++ = c; | ||
| 229 | } | ||
| 230 | |||
| 231 | |||
| 232 | |||
| 233 | void 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 | /* | ||
| 7 | File: printf.h | ||
| 8 | |||
| 9 | Copyright (C) 2004 Kustaa Nyholm | ||
| 10 | |||
| 11 | This library is free software; you can redistribute it and/or | ||
| 12 | modify it under the terms of the GNU Lesser General Public | ||
| 13 | License as published by the Free Software Foundation; either | ||
| 14 | version 2.1 of the License, or (at your option) any later version. | ||
| 15 | |||
| 16 | This library is distributed in the hope that it will be useful, | ||
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
| 19 | See the GNU Lesser General Public License for more details. | ||
| 20 | |||
| 21 | You should have received a copy of the GNU Lesser General Public | ||
| 22 | License along with this library; if not, write to the Free Software | ||
| 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 24 | |||
| 25 | This library is realy just two files: 'printf.h' and 'printf.c'. | ||
| 26 | |||
| 27 | They provide a simple and small (+200 loc) printf functionality to | ||
| 28 | be used in embedded systems. | ||
| 29 | |||
| 30 | I've found them so usefull in debugging that I do not bother with a | ||
| 31 | debugger at all. | ||
| 32 | |||
| 33 | They are distributed in source form, so to use them, just compile them | ||
| 34 | into your project. | ||
| 35 | |||
| 36 | Two printf variants are provided: printf and sprintf. | ||
| 37 | |||
| 38 | The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. | ||
| 39 | |||
| 40 | Zero padding and field width are also supported. | ||
| 41 | |||
| 42 | If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the | ||
| 43 | long specifier is also | ||
| 44 | supported. Note that this will pull in some long math routines (pun intended!) | ||
| 45 | and thus make your executable noticably longer. | ||
| 46 | |||
| 47 | The memory foot print of course depends on the target cpu, compiler and | ||
| 48 | compiler options, but a rough guestimate (based on a H8S target) is about | ||
| 49 | 1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. | ||
| 50 | Not too bad. Your milage may vary. By hacking the source code you can | ||
| 51 | get rid of some hunred bytes, I'm sure, but personally I feel the balance of | ||
| 52 | functionality and flexibility versus code size is close to optimal for | ||
| 53 | many embedded systems. | ||
| 54 | |||
| 55 | To use the printf you need to supply your own character output function, | ||
| 56 | something like : | ||
| 57 | |||
| 58 | void putc ( void* p, char c) | ||
| 59 | { | ||
| 60 | while (!SERIAL_PORT_EMPTY) ; | ||
| 61 | SERIAL_PORT_TX_REGISTER = c; | ||
| 62 | } | ||
| 63 | |||
| 64 | Before you can call printf you need to initialize it to use your | ||
| 65 | character output function with something like: | ||
| 66 | |||
| 67 | init_printf(NULL,putc); | ||
| 68 | |||
| 69 | Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', | ||
| 70 | the NULL (or any pointer) you pass into the 'init_printf' will eventually be | ||
| 71 | passed to your 'putc' routine. This allows you to pass some storage space (or | ||
| 72 | anything realy) to the character output function, if necessary. | ||
| 73 | This is not often needed but it was implemented like that because it made | ||
| 74 | implementing the sprintf function so neat (look at the source code). | ||
| 75 | |||
| 76 | The code is re-entrant, except for the 'init_printf' function, so it | ||
| 77 | is safe to call it from interupts too, although this may result in mixed output. | ||
| 78 | If you rely on re-entrancy, take care that your 'putc' function is re-entrant! | ||
| 79 | |||
| 80 | The printf and sprintf functions are actually macros that translate to | ||
| 81 | 'tfp_printf' and 'tfp_sprintf'. This makes it possible | ||
| 82 | to use them along with 'stdio.h' printf's in a single source file. | ||
| 83 | You just need to undef the names before you include the 'stdio.h'. | ||
| 84 | Note that these are not function like macros, so if you have variables | ||
| 85 | or struct members with these names, things will explode in your face. | ||
| 86 | Without variadic macros this is the best we can do to wrap these | ||
| 87 | fucnction. If it is a problem just give up the macros and use the | ||
| 88 | functions directly or rename them. | ||
| 89 | |||
| 90 | For further details see source code. | ||
| 91 | |||
| 92 | regs Kusti, 23.10.2004 | ||
| 93 | */ | ||
| 94 | |||
| 95 | |||
| 96 | #ifndef __TFP_PRINTF__ | ||
| 97 | #define __TFP_PRINTF__ | ||
| 98 | |||
| 99 | #include <stdarg.h> | ||
| 100 | |||
| 101 | void init_printf(void* putp,void (*putf) (void*,char)); | ||
| 102 | |||
| 103 | void tfp_printf(char *fmt, ...); | ||
| 104 | void tfp_sprintf(char* s,char *fmt, ...); | ||
| 105 | |||
| 106 | void 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 | */ | ||
| 34 | static const uint8_t breathing_table[64] = { | ||
| 35 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, | ||
| 36 | 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, | ||
| 37 | 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, | ||
| 38 | 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 39 | }; | ||
| 40 | |||
| 41 | /* interrupt handler */ | ||
| 42 | OSAL_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 */ | ||
| 96 | void 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 | |||
| 153 | void sleep_led_enable(void) { | ||
| 154 | /* Enable the timer */ | ||
| 155 | LPTMR0->CSR |= LPTMRx_CSR_TEN; | ||
| 156 | } | ||
| 157 | |||
| 158 | void sleep_led_disable(void) { | ||
| 159 | /* Disable the timer */ | ||
| 160 | LPTMR0->CSR &= ~LPTMRx_CSR_TEN; | ||
| 161 | } | ||
| 162 | |||
| 163 | void 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 */ | ||
| 171 | void 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 | |||
| 192 | void 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 | |||
| 198 | void sleep_led_disable(void) { | ||
| 199 | /* Disable the timer */ | ||
| 200 | STM32_TIM14->CR1 = 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | void 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 | |||
| 211 | void sleep_led_init(void) { | ||
| 212 | } | ||
| 213 | |||
| 214 | void sleep_led_enable(void) { | ||
| 215 | led_set(1<<USB_LED_CAPS_LOCK); | ||
| 216 | } | ||
| 217 | |||
| 218 | void sleep_led_disable(void) { | ||
| 219 | led_set(0); | ||
| 220 | } | ||
| 221 | |||
| 222 | void 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 | |||
| 14 | void suspend_idle(uint8_t time) { | ||
| 15 | // TODO: this is not used anywhere - what units is 'time' in? | ||
| 16 | chThdSleepMilliseconds(time); | ||
| 17 | } | ||
| 18 | |||
| 19 | void 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) {} | ||
| 32 | bool 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 | ||
| 44 | void 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 | |||
| 5 | void timer_init(void) {} | ||
| 6 | |||
| 7 | void timer_clear(void) {} | ||
| 8 | |||
| 9 | uint16_t timer_read(void) | ||
| 10 | { | ||
| 11 | return (uint16_t)ST2MS(chVTGetSystemTime()); | ||
| 12 | } | ||
| 13 | |||
| 14 | uint32_t timer_read32(void) | ||
| 15 | { | ||
| 16 | return ST2MS(chVTGetSystemTime()); | ||
| 17 | } | ||
| 18 | |||
| 19 | uint16_t timer_elapsed(uint16_t last) | ||
| 20 | { | ||
| 21 | return (uint16_t)(ST2MS(chVTTimeElapsedSinceX(MS2ST(last)))); | ||
| 22 | } | ||
| 23 | |||
| 24 | uint32_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) | |||
| 103 | bool command_extra(uint8_t code) __attribute__ ((weak)); | 103 | bool command_extra(uint8_t code) __attribute__ ((weak)); |
| 104 | bool command_extra(uint8_t code) | 104 | bool command_extra(uint8_t code) |
| 105 | { | 105 | { |
| 106 | (void)code; | ||
| 106 | return false; | 107 | return false; |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | bool command_console_extra(uint8_t code) __attribute__ ((weak)); | 110 | bool command_console_extra(uint8_t code) __attribute__ ((weak)); |
| 110 | bool command_console_extra(uint8_t code) | 111 | bool 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 | ||
| 6 | void eeconfig_init(void) | 6 | void 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 | ||
| 7 | uint8_t eeprom_read_byte (const uint8_t *__p); | ||
| 8 | uint16_t eeprom_read_word (const uint16_t *__p); | ||
| 9 | uint32_t eeprom_read_dword (const uint32_t *__p); | ||
| 10 | void eeprom_read_block (void *__dst, const void *__src, uint32_t __n); | ||
| 11 | void eeprom_write_byte (uint8_t *__p, uint8_t __value); | ||
| 12 | void eeprom_write_word (uint16_t *__p, uint16_t __value); | ||
| 13 | void eeprom_write_dword (uint32_t *__p, uint32_t __value); | ||
| 14 | void eeprom_write_block (const void *__src, void *__dst, uint32_t __n); | ||
| 15 | void eeprom_update_byte (uint8_t *__p, uint8_t __value); | ||
| 16 | void eeprom_update_word (uint16_t *__p, uint16_t __value); | ||
| 17 | void eeprom_update_dword (uint32_t *__p, uint32_t __value); | ||
| 18 | void 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 */ |
| 48 | void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); | 48 | void 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 | } |
