Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eeconfig.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. #include "ch.h"
  2. #include "hal.h"
  3. #include "eeconfig.h"
  4. /*************************************/
  5. /* Hardware backend */
  6. /* */
  7. /* Code from PJRC/Teensyduino */
  8. /*************************************/
  9. /* Teensyduino Core Library
  10. * http://www.pjrc.com/teensy/
  11. * Copyright (c) 2013 PJRC.COM, LLC.
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining
  14. * a copy of this software and associated documentation files (the
  15. * "Software"), to deal in the Software without restriction, including
  16. * without limitation the rights to use, copy, modify, merge, publish,
  17. * distribute, sublicense, and/or sell copies of the Software, and to
  18. * permit persons to whom the Software is furnished to do so, subject to
  19. * the following conditions:
  20. *
  21. * 1. The above copyright notice and this permission notice shall be
  22. * included in all copies or substantial portions of the Software.
  23. *
  24. * 2. If the Software is incorporated into a build system that allows
  25. * selection among a list of target devices, then similar target
  26. * devices manufactured by PJRC.COM must be included in the list of
  27. * target devices and selectable in the same manner.
  28. *
  29. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  30. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  31. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  32. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  33. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  34. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  35. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  36. * SOFTWARE.
  37. */
  38. #if defined(K20x) /* chip selection */
  39. /* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
  40. // The EEPROM is really RAM with a hardware-based backup system to
  41. // flash memory. Selecting a smaller size EEPROM allows more wear
  42. // leveling, for higher write endurance. If you edit this file,
  43. // set this to the smallest size your application can use. Also,
  44. // due to Freescale's implementation, writing 16 or 32 bit words
  45. // (aligned to 2 or 4 byte boundaries) has twice the endurance
  46. // compared to writing 8 bit bytes.
  47. //
  48. #define EEPROM_SIZE 32
  49. // Writing unaligned 16 or 32 bit data is handled automatically when
  50. // this is defined, but at a cost of extra code size. Without this,
  51. // any unaligned write will cause a hard fault exception! If you're
  52. // absolutely sure all 16 and 32 bit writes will be aligned, you can
  53. // remove the extra unnecessary code.
  54. //
  55. #define HANDLE_UNALIGNED_WRITES
  56. // Minimum EEPROM Endurance
  57. // ------------------------
  58. #if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
  59. #define EEESIZE 0x33
  60. #elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
  61. #define EEESIZE 0x34
  62. #elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
  63. #define EEESIZE 0x35
  64. #elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
  65. #define EEESIZE 0x36
  66. #elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
  67. #define EEESIZE 0x37
  68. #elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
  69. #define EEESIZE 0x38
  70. #elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
  71. #define EEESIZE 0x39
  72. #endif
  73. void eeprom_initialize(void)
  74. {
  75. uint32_t count=0;
  76. uint16_t do_flash_cmd[] = {
  77. 0xf06f, 0x037f, 0x7003, 0x7803,
  78. 0xf013, 0x0f80, 0xd0fb, 0x4770};
  79. uint8_t status;
  80. if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
  81. // FlexRAM is configured as traditional RAM
  82. // We need to reconfigure for EEPROM usage
  83. FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
  84. FTFL->FCCOB4 = EEESIZE; // EEPROM Size
  85. FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
  86. __disable_irq();
  87. // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
  88. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
  89. __enable_irq();
  90. status = FTFL->FSTAT;
  91. if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
  92. FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
  93. return; // error
  94. }
  95. }
  96. // wait for eeprom to become ready (is this really necessary?)
  97. while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
  98. if (++count > 20000) break;
  99. }
  100. }
  101. #define FlexRAM ((uint8_t *)0x14000000)
  102. uint8_t eeprom_read_byte(const uint8_t *addr)
  103. {
  104. uint32_t offset = (uint32_t)addr;
  105. if (offset >= EEPROM_SIZE) return 0;
  106. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  107. return FlexRAM[offset];
  108. }
  109. uint16_t eeprom_read_word(const uint16_t *addr)
  110. {
  111. uint32_t offset = (uint32_t)addr;
  112. if (offset >= EEPROM_SIZE-1) return 0;
  113. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  114. return *(uint16_t *)(&FlexRAM[offset]);
  115. }
  116. uint32_t eeprom_read_dword(const uint32_t *addr)
  117. {
  118. uint32_t offset = (uint32_t)addr;
  119. if (offset >= EEPROM_SIZE-3) return 0;
  120. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  121. return *(uint32_t *)(&FlexRAM[offset]);
  122. }
  123. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  124. {
  125. uint32_t offset = (uint32_t)addr;
  126. uint8_t *dest = (uint8_t *)buf;
  127. uint32_t end = offset + len;
  128. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  129. if (end > EEPROM_SIZE) end = EEPROM_SIZE;
  130. while (offset < end) {
  131. *dest++ = FlexRAM[offset++];
  132. }
  133. }
  134. int eeprom_is_ready(void)
  135. {
  136. return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
  137. }
  138. static void flexram_wait(void)
  139. {
  140. while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
  141. // TODO: timeout
  142. }
  143. }
  144. void eeprom_write_byte(uint8_t *addr, uint8_t value)
  145. {
  146. uint32_t offset = (uint32_t)addr;
  147. if (offset >= EEPROM_SIZE) return;
  148. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  149. if (FlexRAM[offset] != value) {
  150. FlexRAM[offset] = value;
  151. flexram_wait();
  152. }
  153. }
  154. void eeprom_write_word(uint16_t *addr, uint16_t value)
  155. {
  156. uint32_t offset = (uint32_t)addr;
  157. if (offset >= EEPROM_SIZE-1) return;
  158. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  159. #ifdef HANDLE_UNALIGNED_WRITES
  160. if ((offset & 1) == 0) {
  161. #endif
  162. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  163. *(uint16_t *)(&FlexRAM[offset]) = value;
  164. flexram_wait();
  165. }
  166. #ifdef HANDLE_UNALIGNED_WRITES
  167. } else {
  168. if (FlexRAM[offset] != value) {
  169. FlexRAM[offset] = value;
  170. flexram_wait();
  171. }
  172. if (FlexRAM[offset + 1] != (value >> 8)) {
  173. FlexRAM[offset + 1] = value >> 8;
  174. flexram_wait();
  175. }
  176. }
  177. #endif
  178. }
  179. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  180. {
  181. uint32_t offset = (uint32_t)addr;
  182. if (offset >= EEPROM_SIZE-3) return;
  183. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  184. #ifdef HANDLE_UNALIGNED_WRITES
  185. switch (offset & 3) {
  186. case 0:
  187. #endif
  188. if (*(uint32_t *)(&FlexRAM[offset]) != value) {
  189. *(uint32_t *)(&FlexRAM[offset]) = value;
  190. flexram_wait();
  191. }
  192. return;
  193. #ifdef HANDLE_UNALIGNED_WRITES
  194. case 2:
  195. if (*(uint16_t *)(&FlexRAM[offset]) != value) {
  196. *(uint16_t *)(&FlexRAM[offset]) = value;
  197. flexram_wait();
  198. }
  199. if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
  200. *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
  201. flexram_wait();
  202. }
  203. return;
  204. default:
  205. if (FlexRAM[offset] != value) {
  206. FlexRAM[offset] = value;
  207. flexram_wait();
  208. }
  209. if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
  210. *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
  211. flexram_wait();
  212. }
  213. if (FlexRAM[offset + 3] != (value >> 24)) {
  214. FlexRAM[offset + 3] = value >> 24;
  215. flexram_wait();
  216. }
  217. }
  218. #endif
  219. }
  220. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  221. {
  222. uint32_t offset = (uint32_t)addr;
  223. const uint8_t *src = (const uint8_t *)buf;
  224. if (offset >= EEPROM_SIZE) return;
  225. if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
  226. if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
  227. if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
  228. while (len > 0) {
  229. uint32_t lsb = offset & 3;
  230. if (lsb == 0 && len >= 4) {
  231. // write aligned 32 bits
  232. uint32_t val32;
  233. val32 = *src++;
  234. val32 |= (*src++ << 8);
  235. val32 |= (*src++ << 16);
  236. val32 |= (*src++ << 24);
  237. if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
  238. *(uint32_t *)(&FlexRAM[offset]) = val32;
  239. flexram_wait();
  240. }
  241. offset += 4;
  242. len -= 4;
  243. } else if ((lsb == 0 || lsb == 2) && len >= 2) {
  244. // write aligned 16 bits
  245. uint16_t val16;
  246. val16 = *src++;
  247. val16 |= (*src++ << 8);
  248. if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
  249. *(uint16_t *)(&FlexRAM[offset]) = val16;
  250. flexram_wait();
  251. }
  252. offset += 2;
  253. len -= 2;
  254. } else {
  255. // write 8 bits
  256. uint8_t val8 = *src++;
  257. if (FlexRAM[offset] != val8) {
  258. FlexRAM[offset] = val8;
  259. flexram_wait();
  260. }
  261. offset++;
  262. len--;
  263. }
  264. }
  265. }
  266. /*
  267. void do_flash_cmd(volatile uint8_t *fstat)
  268. {
  269. *fstat = 0x80;
  270. while ((*fstat & 0x80) == 0) ; // wait
  271. }
  272. 00000000 <do_flash_cmd>:
  273. 0: f06f 037f mvn.w r3, #127 ; 0x7f
  274. 4: 7003 strb r3, [r0, #0]
  275. 6: 7803 ldrb r3, [r0, #0]
  276. 8: f013 0f80 tst.w r3, #128 ; 0x80
  277. c: d0fb beq.n 6 <do_flash_cmd+0x6>
  278. e: 4770 bx lr
  279. */
  280. #elif defined(KL2x) /* chip selection */
  281. /* Teensy LC (emulated) */
  282. #define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
  283. extern uint32_t __eeprom_workarea_start__;
  284. extern uint32_t __eeprom_workarea_end__;
  285. #define EEPROM_SIZE 128
  286. static uint32_t flashend = 0;
  287. void eeprom_initialize(void)
  288. {
  289. const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
  290. do {
  291. if (*p++ == 0xFFFF) {
  292. flashend = (uint32_t)(p - 2);
  293. return;
  294. }
  295. } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
  296. flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
  297. }
  298. uint8_t eeprom_read_byte(const uint8_t *addr)
  299. {
  300. uint32_t offset = (uint32_t)addr;
  301. const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
  302. const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
  303. uint16_t val;
  304. uint8_t data=0xFF;
  305. if (!end) {
  306. eeprom_initialize();
  307. end = (const uint16_t *)((uint32_t)flashend);
  308. }
  309. if (offset < EEPROM_SIZE) {
  310. while (p <= end) {
  311. val = *p++;
  312. if ((val & 255) == offset) data = val >> 8;
  313. }
  314. }
  315. return data;
  316. }
  317. static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
  318. {
  319. // with great power comes great responsibility....
  320. uint32_t stat;
  321. *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
  322. *(uint32_t *)&(FTFA->FCCOB7) = data;
  323. __disable_irq();
  324. (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
  325. __enable_irq();
  326. stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
  327. if (stat) {
  328. FTFA->FSTAT = stat;
  329. }
  330. MCM->PLACR |= MCM_PLACR_CFCC;
  331. }
  332. void eeprom_write_byte(uint8_t *addr, uint8_t data)
  333. {
  334. uint32_t offset = (uint32_t)addr;
  335. const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
  336. uint32_t i, val, flashaddr;
  337. uint16_t do_flash_cmd[] = {
  338. 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
  339. uint8_t buf[EEPROM_SIZE];
  340. if (offset >= EEPROM_SIZE) return;
  341. if (!end) {
  342. eeprom_initialize();
  343. end = (const uint16_t *)((uint32_t)flashend);
  344. }
  345. if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
  346. val = (data << 8) | offset;
  347. flashaddr = (uint32_t)end;
  348. flashend = flashaddr;
  349. if ((flashaddr & 2) == 0) {
  350. val |= 0xFFFF0000;
  351. } else {
  352. val <<= 16;
  353. val |= 0x0000FFFF;
  354. }
  355. flash_write(do_flash_cmd, flashaddr, val);
  356. } else {
  357. for (i=0; i < EEPROM_SIZE; i++) {
  358. buf[i] = 0xFF;
  359. }
  360. for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
  361. val = *p;
  362. if ((val & 255) < EEPROM_SIZE) {
  363. buf[val & 255] = val >> 8;
  364. }
  365. }
  366. buf[offset] = data;
  367. for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
  368. *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
  369. __disable_irq();
  370. (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
  371. __enable_irq();
  372. val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
  373. if (val) FTFA->FSTAT = val;
  374. MCM->PLACR |= MCM_PLACR_CFCC;
  375. }
  376. flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
  377. for (i=0; i < EEPROM_SIZE; i++) {
  378. if (buf[i] == 0xFF) continue;
  379. if ((flashaddr & 2) == 0) {
  380. val = (buf[i] << 8) | i;
  381. } else {
  382. val = val | (buf[i] << 24) | (i << 16);
  383. flash_write(do_flash_cmd, flashaddr, val);
  384. }
  385. flashaddr += 2;
  386. }
  387. flashend = flashaddr;
  388. if ((flashaddr & 2)) {
  389. val |= 0xFFFF0000;
  390. flash_write(do_flash_cmd, flashaddr, val);
  391. }
  392. }
  393. }
  394. /*
  395. void do_flash_cmd(volatile uint8_t *fstat)
  396. {
  397. *fstat = 0x80;
  398. while ((*fstat & 0x80) == 0) ; // wait
  399. }
  400. 00000000 <do_flash_cmd>:
  401. 0: 2380 movs r3, #128 ; 0x80
  402. 2: 7003 strb r3, [r0, #0]
  403. 4: 7803 ldrb r3, [r0, #0]
  404. 6: b25b sxtb r3, r3
  405. 8: 2b00 cmp r3, #0
  406. a: dafb bge.n 4 <do_flash_cmd+0x4>
  407. c: 4770 bx lr
  408. */
  409. uint16_t eeprom_read_word(const uint16_t *addr)
  410. {
  411. const uint8_t *p = (const uint8_t *)addr;
  412. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
  413. }
  414. uint32_t eeprom_read_dword(const uint32_t *addr)
  415. {
  416. const uint8_t *p = (const uint8_t *)addr;
  417. return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
  418. | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
  419. }
  420. void eeprom_read_block(void *buf, const void *addr, uint32_t len)
  421. {
  422. const uint8_t *p = (const uint8_t *)addr;
  423. uint8_t *dest = (uint8_t *)buf;
  424. while (len--) {
  425. *dest++ = eeprom_read_byte(p++);
  426. }
  427. }
  428. int eeprom_is_ready(void)
  429. {
  430. return 1;
  431. }
  432. void eeprom_write_word(uint16_t *addr, uint16_t value)
  433. {
  434. uint8_t *p = (uint8_t *)addr;
  435. eeprom_write_byte(p++, value);
  436. eeprom_write_byte(p, value >> 8);
  437. }
  438. void eeprom_write_dword(uint32_t *addr, uint32_t value)
  439. {
  440. uint8_t *p = (uint8_t *)addr;
  441. eeprom_write_byte(p++, value);
  442. eeprom_write_byte(p++, value >> 8);
  443. eeprom_write_byte(p++, value >> 16);
  444. eeprom_write_byte(p, value >> 24);
  445. }
  446. void eeprom_write_block(const void *buf, void *addr, uint32_t len)
  447. {
  448. uint8_t *p = (uint8_t *)addr;
  449. const uint8_t *src = (const uint8_t *)buf;
  450. while (len--) {
  451. eeprom_write_byte(p++, *src++);
  452. }
  453. }
  454. #else
  455. #error EEPROM support not implemented for your chip
  456. #endif /* chip selection */
  457. /*****************/
  458. /* TMK functions */
  459. /*****************/
  460. void eeconfig_init(void)
  461. {
  462. eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
  463. eeprom_write_byte(EECONFIG_DEBUG, 0);
  464. eeprom_write_byte(EECONFIG_DEFAULT_LAYER, 0);
  465. eeprom_write_byte(EECONFIG_KEYMAP, 0);
  466. eeprom_write_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
  467. #ifdef BACKLIGHT_ENABLE
  468. eeprom_write_byte(EECONFIG_BACKLIGHT, 0);
  469. #endif
  470. }
  471. void eeconfig_enable(void)
  472. {
  473. eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
  474. }
  475. void eeconfig_disable(void)
  476. {
  477. eeprom_write_word(EECONFIG_MAGIC, 0xFFFF);
  478. }
  479. bool eeconfig_is_enabled(void)
  480. {
  481. return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
  482. }
  483. uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
  484. void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); }
  485. uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
  486. void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); }
  487. uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); }
  488. void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); }
  489. #ifdef BACKLIGHT_ENABLE
  490. uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
  491. void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); }
  492. #endif