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.
		
		
		
		
		
			
		
			
				
					131 lines
				
				3.2 KiB
			
		
		
			
		
	
	
					131 lines
				
				3.2 KiB
			| 
								 
											7 years ago
										 
									 | 
							
								#include <avr/io.h>
							 | 
						||
| 
								 | 
							
								#include <util/delay.h>
							 | 
						||
| 
								 | 
							
								#include "battery.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Battery
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								void battery_init(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // blink
							 | 
						||
| 
								 | 
							
								    battery_led(LED_ON);  _delay_ms(100);
							 | 
						||
| 
								 | 
							
								    battery_led(LED_OFF); _delay_ms(100);
							 | 
						||
| 
								 | 
							
								    battery_led(LED_ON);  _delay_ms(100);
							 | 
						||
| 
								 | 
							
								    battery_led(LED_OFF); _delay_ms(100);
							 | 
						||
| 
								 | 
							
								    // LED indicates charger status
							 | 
						||
| 
								 | 
							
								    battery_led(LED_CHARGER);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // ADC setting for voltage monitor
							 | 
						||
| 
								 | 
							
								    // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz)
							 | 
						||
| 
								 | 
							
								    ADMUX = (1<<REFS1) | (1<<REFS0);
							 | 
						||
| 
								 | 
							
								    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
							 | 
						||
| 
								 | 
							
								    // digital input buffer disable(24.9.5)
							 | 
						||
| 
								 | 
							
								    DIDR0 = (1<<ADC0D) | (1<<ADC4D) | (1<<ADC7D);
							 | 
						||
| 
								 | 
							
								    DIDR1 = (1<<AIN0D);
							 | 
						||
| 
								 | 
							
								    DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC11D) | (1<<ADC12D) | (1<<ADC13D);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // ADC disable voltate divider(PF4)
							 | 
						||
| 
								 | 
							
								    DDRF  |=  (1<<4);
							 | 
						||
| 
								 | 
							
								    PORTF &= ~(1<<4);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Indicator for battery
							 | 
						||
| 
								 | 
							
								void battery_led(battery_led_t val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (val == LED_TOGGLE) {
							 | 
						||
| 
								 | 
							
								        // Toggle LED
							 | 
						||
| 
								 | 
							
								        DDRF  |=  (1<<5);
							 | 
						||
| 
								 | 
							
								        PINF  |=  (1<<5);
							 | 
						||
| 
								 | 
							
								    } else if (val == LED_ON) {
							 | 
						||
| 
								 | 
							
								        // On overriding charger status
							 | 
						||
| 
								 | 
							
								        DDRF  |=  (1<<5);
							 | 
						||
| 
								 | 
							
								        PORTF &= ~(1<<5);
							 | 
						||
| 
								 | 
							
								    } else if (val == LED_OFF) {
							 | 
						||
| 
								 | 
							
								        // Off overriding charger status
							 | 
						||
| 
								 | 
							
								        DDRF  |=  (1<<5);
							 | 
						||
| 
								 | 
							
								        PORTF |=  (1<<5);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        // Display charger status
							 | 
						||
| 
								 | 
							
								        DDRF  &= ~(1<<5);
							 | 
						||
| 
								 | 
							
								        PORTF &= ~(1<<5);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool battery_charging(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (!(USBSTA&(1<<VBUS))) return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Charger Status:
							 | 
						||
| 
								 | 
							
								    //   MCP73831   MCP73832   LTC4054  Status
							 | 
						||
| 
								 | 
							
								    //   Hi-Z       Hi-Z       Hi-Z     Shutdown/No Battery
							 | 
						||
| 
								 | 
							
								    //   Low        Low        Low      Charging
							 | 
						||
| 
								 | 
							
								    //   Hi         Hi-Z       Hi-Z     Charged
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // preserve last register status
							 | 
						||
| 
								 | 
							
								    uint8_t ddrf_prev  = DDRF;
							 | 
						||
| 
								 | 
							
								    uint8_t portf_prev = PORTF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Input with pullup
							 | 
						||
| 
								 | 
							
								    DDRF  &= ~(1<<5);
							 | 
						||
| 
								 | 
							
								    PORTF |=  (1<<5);
							 | 
						||
| 
								 | 
							
								    _delay_ms(1);
							 | 
						||
| 
								 | 
							
								    bool charging = PINF&(1<<5) ? false : true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // restore last register status
							 | 
						||
| 
								 | 
							
								    DDRF  = (DDRF&~(1<<5))  | (ddrf_prev&(1<<5));
							 | 
						||
| 
								 | 
							
								    PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // TODO: With MCP73831 this can not get stable status when charging.
							 | 
						||
| 
								 | 
							
								    // LED is powered from PSEL line(USB or Lipo)
							 | 
						||
| 
								 | 
							
								    // due to weak low output of STAT pin?
							 | 
						||
| 
								 | 
							
								    // due to pull-up'd via resitor and LED?
							 | 
						||
| 
								 | 
							
								    return charging;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Returns voltage in mV
							 | 
						||
| 
								 | 
							
								uint16_t battery_voltage(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // ADC disable voltate divider(PF4)
							 | 
						||
| 
								 | 
							
								    DDRF  |=  (1<<4);
							 | 
						||
| 
								 | 
							
								    PORTF |=  (1<<4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    volatile uint16_t bat;
							 | 
						||
| 
								 | 
							
								    ADCSRA |= (1<<ADEN);
							 | 
						||
| 
								 | 
							
								    _delay_ms(1);   // wait for charging S/H capacitance
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ADCSRA |= (1<<ADSC);
							 | 
						||
| 
								 | 
							
								    while (ADCSRA & (1<<ADSC)) ;
							 | 
						||
| 
								 | 
							
								    bat = ADC;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ADCSRA &= ~(1<<ADEN);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // ADC disable voltate divider(PF4)
							 | 
						||
| 
								 | 
							
								    DDRF  |=  (1<<4);
							 | 
						||
| 
								 | 
							
								    PORTF &= ~(1<<4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool low_voltage(void) {
							 | 
						||
| 
								 | 
							
								    static bool low = false;
							 | 
						||
| 
								 | 
							
								    uint16_t v = battery_voltage();
							 | 
						||
| 
								 | 
							
								    if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
							 | 
						||
| 
								 | 
							
								        low = true;
							 | 
						||
| 
								 | 
							
								    } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
							 | 
						||
| 
								 | 
							
								        low = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return low;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								battery_status_t battery_status(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    if (USBSTA&(1<<VBUS)) {
							 | 
						||
| 
								 | 
							
								        /* powered */
							 | 
						||
| 
								 | 
							
								        return battery_charging() ? CHARGING : FULL_CHARGED;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        /* not powered */
							 | 
						||
| 
								 | 
							
								        return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |