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.

battery.c 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. }
  22. // Indicator for battery
  23. void battery_led(battery_led_t val)
  24. {
  25. if (val == LED_TOGGLE) {
  26. // Toggle LED
  27. DDRF |= (1<<5);
  28. PINF |= (1<<5);
  29. } else if (val == LED_ON) {
  30. // On overriding charger status
  31. DDRF |= (1<<5);
  32. PORTF &= ~(1<<5);
  33. } else if (val == LED_OFF) {
  34. // Off overriding charger status
  35. DDRF |= (1<<5);
  36. PORTF |= (1<<5);
  37. } else {
  38. // Display charger status
  39. DDRF &= ~(1<<5);
  40. PORTF &= ~(1<<5);
  41. }
  42. }
  43. bool battery_charging(void)
  44. {
  45. if (!(USBSTA&(1<<VBUS))) return false;
  46. // MCP73831:STAT
  47. // HiZ: Shutdown/No Battery
  48. // Low: Charging
  49. // Hi: Charged
  50. // preserve last register status
  51. uint8_t ddrf_prev = DDRF;
  52. uint8_t portf_prev = PORTF;
  53. // Input with pullup
  54. DDRF &= ~(1<<5);
  55. PORTF |= (1<<5);
  56. _delay_ms(1);
  57. bool charging = PINF&(1<<5) ? false : true;
  58. // restore last register status
  59. DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5));
  60. PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
  61. return charging;
  62. }
  63. // Returns voltage in mV
  64. uint16_t battery_voltage(void)
  65. {
  66. volatile uint16_t bat;
  67. //ADCSRA |= (1<<ADEN);
  68. // discard first result
  69. ADCSRA |= (1<<ADSC);
  70. while (ADCSRA & (1<<ADSC)) ;
  71. bat = ADC;
  72. // discard second result
  73. ADCSRA |= (1<<ADSC);
  74. while (ADCSRA & (1<<ADSC)) ;
  75. bat = ADC;
  76. ADCSRA |= (1<<ADSC);
  77. while (ADCSRA & (1<<ADSC)) ;
  78. bat = ADC;
  79. //ADCSRA &= ~(1<<ADEN);
  80. return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
  81. }
  82. static bool low_voltage(void) {
  83. static bool low = false;
  84. uint16_t v = battery_voltage();
  85. if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
  86. low = true;
  87. } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
  88. low = false;
  89. }
  90. return low;
  91. }
  92. battery_status_t battery_status(void)
  93. {
  94. if (USBSTA&(1<<VBUS)) {
  95. /* powered */
  96. return battery_charging() ? CHARGING : FULL_CHARGED;
  97. } else {
  98. /* not powered */
  99. return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
  100. }
  101. }