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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

kimera.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. Copyright 2014 Kai Ryu <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #define KIMERA_C
  15. #include <stdbool.h>
  16. #include <avr/eeprom.h>
  17. #include <avr/interrupt.h>
  18. #include <avr/wdt.h>
  19. #include <util/delay.h>
  20. #include "action.h"
  21. #include "i2cmaster.h"
  22. #include "kimera.h"
  23. #include "debug.h"
  24. #define wdt_intr_enable(value) \
  25. __asm__ __volatile__ ( \
  26. "in __tmp_reg__,__SREG__" "\n\t" \
  27. "cli" "\n\t" \
  28. "wdr" "\n\t" \
  29. "sts %0,%1" "\n\t" \
  30. "out __SREG__,__tmp_reg__" "\n\t" \
  31. "sts %0,%2" "\n\t" \
  32. : /* no outputs */ \
  33. : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
  34. "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
  35. "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
  36. _BV(WDIE) | (value & 0x07)) ) \
  37. : "r0" \
  38. )
  39. #define SCL_CLOCK 400000L
  40. #define SCL_DURATION (1000000L/SCL_CLOCK)/2
  41. extern uint8_t i2c_force_stop;
  42. static uint8_t row_mapping[PX_COUNT] = {
  43. #ifndef TWO_HEADED_KIMERA
  44. 0, 1, 2, 3, 4, 5, 6, 7,
  45. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED,
  46. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED,
  47. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED
  48. #else
  49. 0, 1, 2, 3, 4, 5, 6, 7,
  50. 32, 33, 34, 35, 36, 37, 38, 39,
  51. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED,
  52. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED
  53. #endif
  54. };
  55. static uint8_t col_mapping[PX_COUNT] = {
  56. #ifndef TWO_HEADED_KIMERA
  57. 8, 9, 10, 11, 12, 13, 14, 15,
  58. 16, 17, 18, 19, 20, 21, 22, 23,
  59. 24, 25, 26, 27, 28, 29, 30, 31,
  60. UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED
  61. #else
  62. 8, 9, 10, 11, 12, 13, 14, 15,
  63. 16, 17, 18, 19, 20, 21, 22, 23,
  64. 40, 41, 42, 43, 44, 45, 46, 47,
  65. 48, 49, 50, 51, 52, 53, 54, 55
  66. #endif
  67. };
  68. #ifndef TWO_HEADED_KIMERA
  69. static uint8_t row_count = 8;
  70. static uint8_t col_count = 24;
  71. #else
  72. static uint8_t row_count = 16;
  73. static uint8_t col_count = 32;
  74. static uint8_t row_left_count = 8;
  75. static uint8_t col_left_count = 16;
  76. static matrix_row_t col_left_mask;
  77. #endif
  78. static uint8_t data[EXP_COUNT][EXP_PORT_COUNT];
  79. static uint8_t exp_in_use = 0;
  80. static uint8_t exp_online = 0;
  81. static uint8_t read_matrix_mapping(void);
  82. static void write_matrix_mapping(void);
  83. static void expander_init(uint8_t exp);
  84. static uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data);
  85. static uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data);
  86. static uint8_t expander_write_output(uint8_t exp, uint8_t *data);
  87. static uint8_t expander_write_inversion(uint8_t exp, uint8_t *data);
  88. static uint8_t expander_write_config(uint8_t exp, uint8_t *data);
  89. static uint8_t expander_read_input(uint8_t exp, uint8_t *data);
  90. static void init_data(uint8_t value);
  91. void kimera_init(void)
  92. {
  93. /* read config */
  94. //write_matrix_mapping(); /* debug */
  95. if (read_matrix_mapping()) {
  96. write_matrix_mapping();
  97. }
  98. /* init i2c */
  99. i2c_init();
  100. /* init watch dog */
  101. wdt_init();
  102. /* init i/o expanders */
  103. kimera_scan();
  104. }
  105. void wdt_init(void)
  106. {
  107. cli();
  108. wdt_reset();
  109. wdt_intr_enable(WDTO_1S);
  110. sei();
  111. }
  112. uint8_t read_matrix_mapping(void)
  113. {
  114. uint8_t error = 0;
  115. /* read number of rows and cols */
  116. uint8_t rows = eeprom_read_byte(EECONFIG_ROW_COUNT);
  117. uint8_t cols = eeprom_read_byte(EECONFIG_COL_COUNT);
  118. if (rows == 0) error++;
  119. if (rows == UNCONFIGURED) error++;
  120. if (cols == 0) error++;
  121. if (cols == UNCONFIGURED) error++;
  122. if (rows + cols > PX_COUNT) error++;
  123. if (error) return error;
  124. row_count = rows;
  125. col_count = cols;
  126. #ifdef TWO_HEADED_KIMERA
  127. row_left_count = (rows + 1) / 2;
  128. col_left_count = (cols + 1) / 2;
  129. col_left_mask = (1 << col_left_count) - 1;
  130. #endif
  131. /* read row mapping */
  132. uint8_t *mapping = EECONFIG_ROW_COL_MAPPING;
  133. uint8_t exp;
  134. for (uint8_t i = 0; i < PX_COUNT; i++) {
  135. if (i < row_count) {
  136. row_mapping[i] = eeprom_read_byte(mapping++);
  137. if (row_mapping[i] >= PX_COUNT) {
  138. error++;
  139. }
  140. else {
  141. exp = PX_TO_EXP(row_mapping[i]);
  142. exp_in_use |= (1<<exp);
  143. }
  144. }
  145. else {
  146. row_mapping[i] = UNCONFIGURED;
  147. }
  148. }
  149. /* read col mapping*/
  150. for (uint8_t i = 0; i < PX_COUNT; i++) {
  151. if (i < col_count) {
  152. col_mapping[i] = eeprom_read_byte(mapping++);
  153. if (col_mapping[i] >= PX_COUNT) {
  154. error++;
  155. }
  156. else {
  157. exp = PX_TO_EXP(col_mapping[i]);
  158. exp_in_use |= (1<<exp);
  159. }
  160. }
  161. else {
  162. col_mapping[i] = UNCONFIGURED;
  163. }
  164. }
  165. return error;
  166. }
  167. void write_matrix_mapping(void)
  168. {
  169. /* write number of rows and cols */
  170. eeprom_write_byte(EECONFIG_ROW_COUNT, row_count);
  171. eeprom_write_byte(EECONFIG_COL_COUNT, col_count);
  172. /* write row mapping */
  173. uint8_t *mapping = EECONFIG_ROW_COL_MAPPING;
  174. for (uint8_t row = 0; row < row_count; row++) {
  175. eeprom_write_byte(mapping++, row_mapping[row]);
  176. }
  177. /* write col mapping */
  178. for (uint8_t col = 0; col < col_count; col++) {
  179. eeprom_write_byte(mapping++, col_mapping[col]);
  180. }
  181. }
  182. void kimera_scan(void)
  183. {
  184. uint8_t ret;
  185. xprintf("exp in use: %d\n", exp_in_use);
  186. xprintf("exp online: %d\n", exp_online);
  187. for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
  188. if (exp_in_use & (1<<exp)) {
  189. ret = i2c_start(EXP_ADDR(exp) | I2C_WRITE);
  190. if (ret == 0) {
  191. i2c_stop();
  192. if ((exp_online & (1<<exp)) == 0) {
  193. xprintf("found: %d\n", exp);
  194. exp_online |= (1<<exp);
  195. expander_init(exp);
  196. clear_keyboard();
  197. }
  198. }
  199. else {
  200. if ((exp_online & (1<<exp)) != 0) {
  201. xprintf("lost: %d\n", exp);
  202. exp_online &= ~(1<<exp);
  203. clear_keyboard();
  204. }
  205. }
  206. #if 0
  207. if (exp_online & (1<<exp)) {
  208. if (ret) {
  209. xprintf("lost: %d\n", exp);
  210. exp_online &= ~(1<<exp);
  211. clear_keyboard();
  212. }
  213. }
  214. else {
  215. if (!ret) {
  216. xprintf("found: %d\n", exp);
  217. exp_online |= (1<<exp);
  218. i2c_stop();
  219. expander_init(exp);
  220. clear_keyboard();
  221. }
  222. else {
  223. i2c_stop();
  224. }
  225. }
  226. #endif
  227. }
  228. }
  229. }
  230. #define CHANGE_COMBINING 1
  231. inline
  232. uint8_t kimera_matrix_rows(void)
  233. {
  234. #if CHANGE_COMBINING
  235. #ifndef TWO_HEADED_KIMERA
  236. return row_count;
  237. #else
  238. return row_left_count;
  239. #endif
  240. #else
  241. return row_count;
  242. #endif
  243. }
  244. inline
  245. uint8_t kimera_matrix_cols(void)
  246. {
  247. #if CHANGE_COMBINING
  248. return col_count;
  249. #else
  250. #ifndef TWO_HEADED_KIMERA
  251. return col_count;
  252. #else
  253. return col_left_count;
  254. #endif
  255. #endif
  256. }
  257. void kimera_read_cols(void)
  258. {
  259. /* read all input registers */
  260. init_data(0xFF);
  261. for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
  262. expander_read_input(exp, data[exp]);
  263. }
  264. }
  265. uint8_t kimera_get_col(uint8_t row, uint8_t col)
  266. {
  267. #if CHANGE_COMBINING
  268. #else
  269. #ifdef TWO_HEADED_KIMERA
  270. if (row >= row_left_count) {
  271. col += col_left_count;
  272. }
  273. #endif
  274. #endif
  275. uint8_t px = col_mapping[col];
  276. if (px != UNCONFIGURED) {
  277. if (!(data[PX_TO_EXP(px)][PX_TO_PORT(px)] & (1 << PX_TO_PIN(px)))) {
  278. return 1;
  279. }
  280. }
  281. return 0;
  282. }
  283. matrix_row_t kimera_read_row(uint8_t row)
  284. {
  285. kimera_read_cols();
  286. /* make cols */
  287. matrix_row_t cols = 0;
  288. for (uint8_t col = 0; col < col_count; col++) {
  289. uint8_t px = col_mapping[col];
  290. if (px != UNCONFIGURED) {
  291. if (!(data[PX_TO_EXP(px)][PX_TO_PORT(px)] & (1 << PX_TO_PIN(px)))) {
  292. cols |= (1UL << col);
  293. }
  294. }
  295. }
  296. #if CHANGE_COMBINING
  297. #else
  298. #ifdef TWO_HEADED_KIMERA
  299. if (row < row_left_count) {
  300. cols &= col_left_mask;
  301. }
  302. else {
  303. cols >>= col_left_count;
  304. }
  305. #endif
  306. #endif
  307. return cols;
  308. }
  309. void kimera_unselect_rows(void)
  310. {
  311. /* set all output registers to 0xFF */
  312. init_data(0xFF);
  313. for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
  314. expander_write_config(exp, data[exp]);
  315. }
  316. }
  317. void kimera_select_row(uint8_t row)
  318. {
  319. /* set selected row to low */
  320. init_data(0xFF);
  321. uint8_t px = row_mapping[row];
  322. if (px != UNCONFIGURED) {
  323. uint8_t exp = PX_TO_EXP(px);
  324. data[exp][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px));
  325. expander_write_config(exp, data[exp]);
  326. }
  327. #if CHANGE_COMBINING
  328. #ifdef TWO_HEADED_KIMERA
  329. if (row < row_left_count) {
  330. kimera_select_row(row + row_left_count);
  331. }
  332. #endif
  333. #endif
  334. }
  335. void expander_init(uint8_t exp)
  336. {
  337. init_data(0x00);
  338. /* write inversion register */
  339. /*
  340. for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
  341. expander_write_inversion(exp, data[exp]);
  342. }
  343. */
  344. /* set output bit */
  345. /*
  346. for (uint8_t row = 0; row < row_count; row++) {
  347. uint8_t px = row_mapping[row];
  348. if (px != UNCONFIGURED) {
  349. data[PX_TO_EXP(px)][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px));
  350. }
  351. }
  352. */
  353. /* write config registers */
  354. //expander_write_config(exp, data[exp]);
  355. /* write output registers */
  356. expander_write_output(exp, data[exp]);
  357. }
  358. uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data)
  359. {
  360. wdt_reset();
  361. if ((exp_online & (1<<exp)) == 0) {
  362. return 0;
  363. }
  364. uint8_t addr = EXP_ADDR(exp);
  365. uint8_t ret;
  366. ret = i2c_start(addr | I2C_WRITE);
  367. if (ret) goto stop;
  368. ret = i2c_write(command);
  369. if (ret) goto stop;
  370. ret = i2c_write(*data++);
  371. if (ret) goto stop;
  372. ret = i2c_write(*data);
  373. stop:
  374. i2c_stop();
  375. return ret;
  376. }
  377. uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data)
  378. {
  379. wdt_reset();
  380. if ((exp_online & (1<<exp)) == 0) {
  381. return 0;
  382. }
  383. uint8_t addr = EXP_ADDR(exp);
  384. uint8_t ret;
  385. ret = i2c_start(addr | I2C_WRITE);
  386. if (ret) goto stop;
  387. ret = i2c_write(command);
  388. if (ret) goto stop;
  389. ret = i2c_start(addr | I2C_READ);
  390. if (ret) goto stop;
  391. *data++ = i2c_readAck();
  392. *data = i2c_readNak();
  393. stop:
  394. i2c_stop();
  395. return ret;
  396. }
  397. inline
  398. uint8_t expander_write_output(uint8_t exp, uint8_t *data)
  399. {
  400. return expander_write(exp, EXP_COMM_OUTPUT_0, data);
  401. }
  402. inline
  403. uint8_t expander_write_inversion(uint8_t exp, uint8_t *data)
  404. {
  405. return expander_write(exp, EXP_COMM_INVERSION_0, data);
  406. }
  407. inline
  408. uint8_t expander_write_config(uint8_t exp, uint8_t *data)
  409. {
  410. return expander_write(exp, EXP_COMM_CONFIG_0, data);
  411. }
  412. inline
  413. uint8_t expander_read_input(uint8_t exp, uint8_t *data)
  414. {
  415. return expander_read(exp, EXP_COMM_INPUT_0, data);
  416. }
  417. void init_data(uint8_t value)
  418. {
  419. for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
  420. for (uint8_t port = 0; port < EXP_PORT_COUNT; port++) {
  421. data[exp][port] = value;
  422. }
  423. }
  424. }
  425. ISR(WDT_vect)
  426. {
  427. dprintf("i2c timeout\n");
  428. /* let slave to release SDA */
  429. TWCR = 0;
  430. DDRD |= (1<<PD0);
  431. DDRD &= ~(1<<PD1);
  432. if (!(PIND & (1<<PD1))) {
  433. for (uint8_t i = 0; i < 9; i++) {
  434. PORTD &= ~(1<<PD0);
  435. _delay_us(SCL_DURATION);
  436. PORTD |= (1<<PD0);
  437. _delay_us(SCL_DURATION);
  438. }
  439. }
  440. /* send stop condition */
  441. TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
  442. /* escape from loop */
  443. i2c_force_stop = 1;
  444. }