Add battery management
This commit is contained in:
		
							parent
							
								
									807ed33a9a
								
							
						
					
					
						commit
						02939ab1d8
					
				
					 4 changed files with 165 additions and 60 deletions
				
			
		
							
								
								
									
										119
									
								
								keyboard/hhkb_rn42/rn42/battery.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								keyboard/hhkb_rn42/rn42/battery.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
#include <avr/io.h>
 | 
			
		||||
#include <util/delay.h>
 | 
			
		||||
#include "battery.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Battery
 | 
			
		||||
 */
 | 
			
		||||
void battery_init(void)
 | 
			
		||||
{
 | 
			
		||||
    // blink 
 | 
			
		||||
    battery_led(LED_ON);  _delay_ms(500);
 | 
			
		||||
    battery_led(LED_OFF); _delay_ms(500);
 | 
			
		||||
    battery_led(LED_ON);  _delay_ms(500);
 | 
			
		||||
    battery_led(LED_OFF); _delay_ms(500);
 | 
			
		||||
    // 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);
 | 
			
		||||
    ADCSRA |= (1<<ADEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
 | 
			
		||||
    // MCP73831:STAT
 | 
			
		||||
    //   HiZ:    Shutdown/No Battery
 | 
			
		||||
    //   Low:    Charging
 | 
			
		||||
    //   Hi:     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));
 | 
			
		||||
 | 
			
		||||
    return charging;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns voltage in mV
 | 
			
		||||
uint16_t battery_voltage(void)
 | 
			
		||||
{
 | 
			
		||||
    volatile uint16_t bat;
 | 
			
		||||
    //ADCSRA |= (1<<ADEN);
 | 
			
		||||
 | 
			
		||||
    // discard first result
 | 
			
		||||
    ADCSRA |= (1<<ADSC);
 | 
			
		||||
    while (ADCSRA & (1<<ADSC)) ;
 | 
			
		||||
    bat = ADC;
 | 
			
		||||
 | 
			
		||||
    // discard second result
 | 
			
		||||
    ADCSRA |= (1<<ADSC);
 | 
			
		||||
    while (ADCSRA & (1<<ADSC)) ;
 | 
			
		||||
    bat = ADC;
 | 
			
		||||
 | 
			
		||||
    ADCSRA |= (1<<ADSC);
 | 
			
		||||
    while (ADCSRA & (1<<ADSC)) ;
 | 
			
		||||
    bat = ADC;
 | 
			
		||||
 | 
			
		||||
    //ADCSRA &= ~(1<<ADEN);
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue