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.

battery.c 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include "battery.h"
  4. /*
  5. * Battery
  6. */
  7. void battery_init(void)
  8. {
  9. // blink
  10. battery_led(LED_ON); _delay_ms(500);
  11. battery_led(LED_OFF); _delay_ms(500);
  12. battery_led(LED_ON); _delay_ms(500);
  13. battery_led(LED_OFF); _delay_ms(500);
  14. // LED indicates charger status
  15. battery_led(LED_CHARGER);
  16. // ADC setting for voltage monitor
  17. // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz)
  18. ADMUX = (1<<REFS1) | (1<<REFS0);
  19. ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
  20. ADCSRA |= (1<<ADEN);
  21. // digital input buffer disable(24.9.5)
  22. DIDR0 = (1<<ADC0D) | (1<<ADC4D) | (1<<ADC5D) | (1<<ADC7D);
  23. DIDR1 = (1<<AIN0D);
  24. DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC11D) | (1<<ADC12D) | (1<<ADC13D);
  25. // ADC disable voltate divider(PF4)
  26. DDRF |= (1<<4);
  27. PORTF &= ~(1<<4);
  28. }
  29. // Indicator for battery
  30. void battery_led(battery_led_t val)
  31. {
  32. if (val == LED_TOGGLE) {
  33. // Toggle LED
  34. DDRF |= (1<<5);
  35. PINF |= (1<<5);
  36. } else if (val == LED_ON) {
  37. // On overriding charger status
  38. DDRF |= (1<<5);
  39. PORTF &= ~(1<<5);
  40. } else if (val == LED_OFF) {
  41. // Off overriding charger status
  42. DDRF |= (1<<5);
  43. PORTF |= (1<<5);
  44. } else {
  45. // Display charger status
  46. DDRF &= ~(1<<5);
  47. PORTF &= ~(1<<5);
  48. }
  49. }
  50. bool battery_charging(void)
  51. {
  52. if (!(USBSTA&(1<<VBUS))) return false;
  53. // Charger Status:
  54. // MCP73831 MCP73832 LTC4054 Status
  55. // Hi-Z Hi-Z Hi-Z Shutdown/No Battery
  56. // Low Low Low Charging
  57. // Hi Hi-Z Hi-Z Charged
  58. // preserve last register status
  59. uint8_t ddrf_prev = DDRF;
  60. uint8_t portf_prev = PORTF;
  61. // Input with pullup
  62. DDRF &= ~(1<<5);
  63. PORTF |= (1<<5);
  64. _delay_ms(1);
  65. bool charging = PINF&(1<<5) ? false : true;
  66. // restore last register status
  67. DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5));
  68. PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
  69. // TODO: With MCP73831 this can not get stable status when charging.
  70. // LED is powered from PSEL line(USB or Lipo)
  71. // due to weak low output of STAT pin?
  72. // due to pull-up'd via resitor and LED?
  73. return charging;
  74. }
  75. // Returns voltage in mV
  76. uint16_t battery_voltage(void)
  77. {
  78. // ADC disable voltate divider(PF4)
  79. DDRF |= (1<<4);
  80. PORTF |= (1<<4);
  81. volatile uint16_t bat;
  82. //ADCSRA |= (1<<ADEN);
  83. // discard first result
  84. ADCSRA |= (1<<ADSC);
  85. while (ADCSRA & (1<<ADSC)) ;
  86. bat = ADC;
  87. // discard second result
  88. ADCSRA |= (1<<ADSC);
  89. while (ADCSRA & (1<<ADSC)) ;
  90. bat = ADC;
  91. ADCSRA |= (1<<ADSC);
  92. while (ADCSRA & (1<<ADSC)) ;
  93. bat = ADC;
  94. //ADCSRA &= ~(1<<ADEN);
  95. // ADC disable voltate divider(PF4)
  96. DDRF |= (1<<4);
  97. PORTF &= ~(1<<4);
  98. return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
  99. }
  100. static bool low_voltage(void) {
  101. static bool low = false;
  102. uint16_t v = battery_voltage();
  103. if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
  104. low = true;
  105. } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
  106. low = false;
  107. }
  108. return low;
  109. }
  110. battery_status_t battery_status(void)
  111. {
  112. if (USBSTA&(1<<VBUS)) {
  113. /* powered */
  114. return battery_charging() ? CHARGING : FULL_CHARGED;
  115. } else {
  116. /* not powered */
  117. return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
  118. }
  119. }