ergodox.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "ergodox.h"
  2. #include "i2cmaster.h"
  3. bool i2c_initialized = 0;
  4. uint8_t mcp23018_status = 0x20;
  5. bool ergodox_left_led_1 = 0; // left top
  6. bool ergodox_left_led_2 = 0; // left middle
  7. bool ergodox_left_led_3 = 0; // left bottom
  8. __attribute__ ((weak))
  9. void * matrix_init_user(void) {
  10. };
  11. __attribute__ ((weak))
  12. void * matrix_scan_user(void) {
  13. };
  14. void * matrix_init_kb(void) {
  15. // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
  16. TCCR1A = 0b10101001; // set and configure fast PWM
  17. TCCR1B = 0b00001001; // set and configure fast PWM
  18. // (tied to Vcc for hardware convenience)
  19. DDRB &= ~(1<<4); // set B(4) as input
  20. PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
  21. // unused pins - C7, D4, D5, D7, E6
  22. // set as input with internal pull-ip enabled
  23. DDRC &= ~(1<<7);
  24. DDRD &= ~(1<<7 | 1<<5 | 1<<4);
  25. DDRE &= ~(1<<6);
  26. PORTC |= (1<<7);
  27. PORTD |= (1<<7 | 1<<5 | 1<<4);
  28. PORTE |= (1<<6);
  29. ergodox_blink_all_leds();
  30. if (matrix_init_user) {
  31. (*matrix_init_user)();
  32. }
  33. };
  34. void * matrix_scan_kb(void) {
  35. if (matrix_scan_user) {
  36. (*matrix_scan_user)();
  37. }
  38. };
  39. void ergodox_blink_all_leds(void)
  40. {
  41. ergodox_led_all_off();
  42. ergodox_led_all_set(LED_BRIGHTNESS_HI);
  43. ergodox_led_all_on();
  44. _delay_ms(333);
  45. ergodox_led_all_off();
  46. }
  47. uint8_t init_mcp23018(void) {
  48. mcp23018_status = 0x20;
  49. // I2C subsystem
  50. if (i2c_initialized == 0) {
  51. i2c_init(); // on pins D(1,0)
  52. i2c_initialized++;
  53. _delay_ms(1000);
  54. }
  55. // set pin direction
  56. // - unused : input : 1
  57. // - input : input : 1
  58. // - driving : output : 0
  59. mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
  60. mcp23018_status = i2c_write(IODIRA); if (mcp23018_status) goto out;
  61. mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
  62. mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
  63. i2c_stop();
  64. // set pull-up
  65. // - unused : on : 1
  66. // - input : on : 1
  67. // - driving : off : 0
  68. mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
  69. mcp23018_status = i2c_write(GPPUA); if (mcp23018_status) goto out;
  70. mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
  71. mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
  72. out:
  73. i2c_stop();
  74. if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
  75. return mcp23018_status;
  76. }
  77. uint8_t ergodox_left_leds_update(void) {
  78. if (mcp23018_status) { // if there was an error
  79. return mcp23018_status;
  80. }
  81. // set logical value (doesn't matter on inputs)
  82. // - unused : hi-Z : 1
  83. // - input : hi-Z : 1
  84. // - driving : hi-Z : 1
  85. mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
  86. mcp23018_status = i2c_write(OLATA); if (mcp23018_status) goto out;
  87. mcp23018_status = i2c_write(0b11111111
  88. & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
  89. ); if (mcp23018_status) goto out;
  90. mcp23018_status = i2c_write(0b11111111
  91. & ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
  92. & ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT)
  93. ); if (mcp23018_status) goto out;
  94. out:
  95. i2c_stop();
  96. return mcp23018_status;
  97. }