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.

suspend.c 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. #define wdt_intr_enable(value) \
  11. __asm__ __volatile__ ( \
  12. "in __tmp_reg__,__SREG__" "\n\t" \
  13. "cli" "\n\t" \
  14. "wdr" "\n\t" \
  15. "sts %0,%1" "\n\t" \
  16. "out __SREG__,__tmp_reg__" "\n\t" \
  17. "sts %0,%2" "\n\t" \
  18. : /* no outputs */ \
  19. : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
  20. "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
  21. "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
  22. _BV(WDIE) | (value & 0x07)) ) \
  23. : "r0" \
  24. )
  25. void suspend_power_down(void)
  26. {
  27. #ifdef BACKLIGHT_ENABLE
  28. backlight_set(0);
  29. #endif
  30. #ifndef NO_SUSPEND_POWER_DOWN
  31. // Enable watchdog to wake from MCU sleep
  32. cli();
  33. wdt_reset();
  34. // Watchdog Interrupt and System Reset Mode
  35. //wdt_enable(WDTO_1S);
  36. //WDTCSR |= _BV(WDIE);
  37. // Watchdog Interrupt Mode
  38. wdt_intr_enable(WDTO_120MS);
  39. // TODO: more power saving
  40. // See PicoPower application note
  41. // - I/O port input with pullup
  42. // - prescale clock
  43. // - BOD disable
  44. // - Power Reduction Register PRR
  45. // sleep in power down mode
  46. set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  47. sleep_enable();
  48. sei();
  49. sleep_cpu();
  50. sleep_disable();
  51. // Disable watchdog after sleep
  52. wdt_disable();
  53. #endif
  54. }
  55. bool suspend_wakeup_condition(void)
  56. {
  57. matrix_scan();
  58. for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
  59. if (matrix_get_row(r)) return true;
  60. }
  61. return false;
  62. }
  63. // run immediately after wakeup
  64. void suspend_wakeup_init(void)
  65. {
  66. // clear keyboard state
  67. clear_keyboard();
  68. #ifdef BACKLIGHT_ENABLE
  69. backlight_init();
  70. #endif
  71. }
  72. #ifndef NO_SUSPEND_POWER_DOWN
  73. /* watchdog timeout */
  74. ISR(WDT_vect)
  75. {
  76. /* wakeup from MCU sleep mode */
  77. /*
  78. // blink LED
  79. static uint8_t led_state = 0;
  80. static uint8_t led_count = 0;
  81. led_count++;
  82. if ((led_count & 0x07) == 0) {
  83. led_set((led_state ^= (1<<USB_LED_CAPS_LOCK)));
  84. }
  85. */
  86. }
  87. #endif