Keyboard firmwares for Atmel AVR and Cortex-M
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
11 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <stdbool.h>
  2. #include <avr/sleep.h>
  3. #include <avr/wdt.h>
  4. #include <avr/interrupt.h>
  5. #include "matrix.h"
  6. #include "action.h"
  7. #include "backlight.h"
  8. #include "suspend_avr.h"
  9. #include "suspend.h"
  10. #include "timer.h"
  11. #ifdef PROTOCOL_LUFA
  12. #include "lufa.h"
  13. #endif
  14. #define wdt_intr_enable(value) \
  15. __asm__ __volatile__ ( \
  16. "in __tmp_reg__,__SREG__" "\n\t" \
  17. "cli" "\n\t" \
  18. "wdr" "\n\t" \
  19. "sts %0,%1" "\n\t" \
  20. "out __SREG__,__tmp_reg__" "\n\t" \
  21. "sts %0,%2" "\n\t" \
  22. : /* no outputs */ \
  23. : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
  24. "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
  25. "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
  26. _BV(WDIE) | (value & 0x07)) ) \
  27. : "r0" \
  28. )
  29. void suspend_idle(uint8_t time)
  30. {
  31. cli();
  32. set_sleep_mode(SLEEP_MODE_IDLE);
  33. sleep_enable();
  34. sei();
  35. sleep_cpu();
  36. sleep_disable();
  37. }
  38. /* Power down MCU with watchdog timer
  39. * wdto: watchdog timer timeout defined in <avr/wdt.h>
  40. * WDTO_15MS
  41. * WDTO_30MS
  42. * WDTO_60MS
  43. * WDTO_120MS
  44. * WDTO_250MS
  45. * WDTO_500MS
  46. * WDTO_1S
  47. * WDTO_2S
  48. * WDTO_4S
  49. * WDTO_8S
  50. */
  51. static uint8_t wdt_timeout = 0;
  52. static void power_down(uint8_t wdto)
  53. {
  54. #ifdef PROTOCOL_LUFA
  55. if (USB_DeviceState == DEVICE_STATE_Configured) return;
  56. #endif
  57. wdt_timeout = wdto;
  58. // Watchdog Interrupt Mode
  59. wdt_intr_enable(wdto);
  60. // TODO: more power saving
  61. // See PicoPower application note
  62. // - I/O port input with pullup
  63. // - prescale clock
  64. // - BOD disable
  65. // - Power Reduction Register PRR
  66. set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  67. sleep_enable();
  68. sei();
  69. sleep_cpu();
  70. sleep_disable();
  71. // Disable watchdog after sleep
  72. wdt_disable();
  73. }
  74. void suspend_power_down(void)
  75. {
  76. power_down(WDTO_15MS);
  77. }
  78. bool suspend_wakeup_condition(void)
  79. {
  80. matrix_power_up();
  81. matrix_scan();
  82. matrix_power_down();
  83. for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
  84. if (matrix_get_row(r)) return true;
  85. }
  86. return false;
  87. }
  88. // run immediately after wakeup
  89. void suspend_wakeup_init(void)
  90. {
  91. // clear keyboard state
  92. clear_keyboard();
  93. #ifdef BACKLIGHT_ENABLE
  94. backlight_init();
  95. #endif
  96. }
  97. #ifndef NO_SUSPEND_POWER_DOWN
  98. /* watchdog timeout */
  99. ISR(WDT_vect)
  100. {
  101. // compensate timer for sleep
  102. switch (wdt_timeout) {
  103. case WDTO_15MS:
  104. timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
  105. break;
  106. default:
  107. ;
  108. }
  109. }
  110. #endif