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.

suspend.c 2.4KB

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