Index: apps/debug_menu.c =================================================================== --- apps/debug_menu.c (revision 19704) +++ apps/debug_menu.c (working copy) @@ -1251,10 +1251,6 @@ lcd_puts(0, line++, buf); snprintf(buf, sizeof(buf), "ADC_VBAT: %4d", adc_read(ADC_VBAT)); lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "CHARGER: %02X/%02X", - ascodec_read(AS3514_CHARGER), - ascodec_read(AS3514_IRQ_ENRD0)); - lcd_puts(0, line++, buf); #endif #endif lcd_update(); @@ -1757,6 +1753,40 @@ } lcd_puts(0, line++, buf); +#elif defined(SANSA_E200) || defined(SANSA_C200) + static const unsigned char * const chrgstate_strings[] = + { + "Disabled", + "Error", + "Discharging", + "Charging", + "", + }; + + int line = 3; + + snprintf(buf, 30, "Charger: %s", + charger_inserted() ? "present" : "absent"); + lcd_puts(0, line++, buf); + + y = ARRAYLEN(chrgstate_strings) - 1; + + switch (charge_state) + { + case CHARGE_STATE_DISABLED: y--; + case CHARGE_STATE_ERROR: y--; + case DISCHARGING: y--; + case CHARGING: y--; + default:; + } + + snprintf(buf, sizeof(buf), "State: %s", + chrgstate_strings[y]); + lcd_puts(0, line++, buf); + + snprintf(buf, sizeof(buf), "CHARGER: %02X", + ascodec_read(AS3514_CHARGER)); + lcd_puts(0, line++, buf); #else snprintf(buf, 30, "Charger: %s", charger_inserted() ? "present" : "absent"); Index: firmware/export/config-c200.h =================================================================== --- firmware/export/config-c200.h (revision 19704) +++ firmware/export/config-c200.h (working copy) @@ -123,8 +123,9 @@ #define BATTERY_CAPACITY_INC 0 /* capacity increment */ #define BATTERY_TYPES_COUNT 1 /* only one type */ -/* Hardware controlled charging? FIXME */ -#define CONFIG_CHARGING CHARGING_SIMPLE +/* Charging implemented in a target-specific algorithm */ +#define CONFIG_CHARGING CHARGING_TARGET +#define HAVE_POWEROFF_WHILE_CHARGING /* define this if the unit can be powered or charged via USB */ #define HAVE_USB_POWER Index: firmware/export/config-e200.h =================================================================== --- firmware/export/config-e200.h (revision 19704) +++ firmware/export/config-e200.h (working copy) @@ -120,8 +120,9 @@ #define BATTERY_CAPACITY_INC 0 /* capacity increment */ #define BATTERY_TYPES_COUNT 1 /* only one type */ -/* Hardware controlled charging? FIXME */ -#define CONFIG_CHARGING CHARGING_SIMPLE +/* Charging implemented in a target-specific algorithm */ +#define CONFIG_CHARGING CHARGING_TARGET +#define HAVE_POWEROFF_WHILE_CHARGING /* define current usage levels */ #define CURRENT_NORMAL 30 /* Toni's measurements in Nov 2008 */ Index: firmware/export/powermgmt.h =================================================================== --- firmware/export/powermgmt.h (revision 19704) +++ firmware/export/powermgmt.h (working copy) @@ -143,14 +143,17 @@ #ifdef HAVE_BATTERY_SWITCH unsigned int input_millivolts(void); /* voltage that device is running from */ +#endif /* HAVE_BATTERY_SWITCH */ +#if defined(HAVE_BATTERY_SWITCH) || defined(HAVE_RESET_BATTERY_FILTER) /* Set the filtered battery voltage (to adjust it before beginning a charge * cycle for instance where old, loaded readings will likely be invalid). * Also readjust when battery switch is opened or closed. */ void reset_battery_filter(int millivolts); -#endif /* HAVE_BATTERY_SWITCH */ +#endif /* HAVE_BATTERY_SWITCH || HAVE_RESET_BATTERY_FILTER */ + /* read unfiltered battery info */ void battery_read_info(int *voltage, int *level); Index: firmware/export/as3514.h =================================================================== --- firmware/export/as3514.h (revision 19704) +++ firmware/export/as3514.h (working copy) @@ -251,7 +251,38 @@ #define ADC_UNREG_POWER ADC_BVDD /* For compatibility */ +/* AS3514_CHARGER */ +#define TMPSUP_off (0x1 << 7) +#define CHG_I (0x7 << 4) +#define CHG_I_400MA (0x7 << 4) +#define CHG_I_350MA (0x6 << 4) +#define CHG_I_300MA (0x5 << 4) +#define CHG_I_250MA (0x4 << 4) +#define CHG_I_200MA (0x3 << 4) +#define CHG_I_150MA (0x2 << 4) +#define CHG_I_100MA (0x1 << 4) +#define CHG_I_50MA (0x0 << 4) +#define CHG_V (0x7 << 1) +#define CHG_V_4_25V (0x7 << 1) +#define CHG_V_4_20V (0x6 << 1) +#define CHG_V_4_15V (0x5 << 1) +#define CHG_V_4_10V (0x4 << 1) +#define CHG_V_4_05V (0x3 << 1) +#define CHG_V_4_00V (0x2 << 1) +#define CHG_V_3_95V (0x1 << 1) +#define CHG_V_3_90V (0x0 << 1) +#define CHG_OFF (0x1 << 0) +/* AS3514_IRQ_ENRD0 */ +#define CHG_TMPHIGH (0x1 << 7) +#define CHG_ENDOFCH (0x1 << 6) +#define CHG_STATUS (0x1 << 5) +#define CHG_CHANGED (0x1 << 4) +#define USB_STATUS (0x1 << 3) +#define USB_CHANGED (0x1 << 2) +#define RVDD_WASLOW (0x1 << 1) +#define BVDD_ISLOW (0x1 << 0) + #define AS3514_I2C_ADDR 0x46 #endif /* _AS3514_H */ Index: firmware/SOURCES =================================================================== --- firmware/SOURCES (revision 19704) +++ firmware/SOURCES (working copy) @@ -497,6 +497,7 @@ target/arm/i2s-pp.c #ifndef BOOTLOADER target/arm/sandisk/audio-c200_e200.c +target/arm/sandisk/powermgmt-as3514.c #endif /* BOOTLOADER */ #endif /* SIMULATOR */ #endif /* SANSA_E200 */ @@ -516,6 +517,7 @@ target/arm/i2s-pp.c #ifndef BOOTLOADER target/arm/sandisk/audio-c200_e200.c +target/arm/sandisk/powermgmt-as3514.c #endif /* BOOTLOADER */ #endif /* SIMULATOR */ #endif /* SANSA_C200 */ Index: firmware/target/arm/sandisk/powermgmt-as3514.c =================================================================== --- firmware/target/arm/sandisk/powermgmt-as3514.c (revision 0) +++ firmware/target/arm/sandisk/powermgmt-as3514.c (revision 0) @@ -0,0 +1,208 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * Copyright (C) 2008 by Bertrik Sikken + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "system.h" +#include "as3514.h" +#include "ascodec.h" +#include "adc.h" +#include "powermgmt.h" +#include "power.h" + +static bool charger_close = false; /* Shutting down? */ +static int charger_total_timer = 0; /* Timeout in algorithm steps */ + +#define CHARGER_TOTAL_TIMER_RELOAD (4*3600*2) /* 4 hours? */ +#define BATT_VENDPOINT CHG_V_4_20V /* CV regulation setting */ +#define BATT_ICHARGE CHG_I_300MA /* CC regulation setting */ +#define BATT_FULL_VOLTAGE 4160 /* V threshold when plugged */ +#define BATT_VAUTO_RECHARGE 4100 /* V threshold for auto restart */ + +/* Current battery threshold for recharge: + * First plugged = BATT_FULL_VOLTAGE + * After charge cycle = BATT_VAUTO_RECHARGE + */ +static unsigned int batt_threshold = BATT_FULL_VOLTAGE; + +unsigned int battery_adc_voltage(void) +{ + /* on e200 ADC_RTCSUP seems to represent battery voltage better than + * ADC_BVDD during charging (ADC_BVDD is way too high) and appears the same + * in normal use. + * + * 5125 = floor(1024/1023*5120) + */ + return (adc_read(ADC_RTCSUP) * 5125 + 512) >> 10; +} + +/* Returns true if the unit is charging the batteries. */ +bool charging_state(void) +{ + return charge_state == CHARGING; +} + +/* Reset the battery filter to a new voltage */ +static void battery_voltage_sync(void) +{ + int i; + unsigned int mv; + + for (i = 0, mv = 0; i < 5; i++) + mv += battery_adc_voltage(); + + reset_battery_filter(mv / 5); +} + +/* Disable charger and minimize all settings. Reset timers, etc. */ +static void disable_charger(void) +{ + ascodec_write(AS3514_IRQ_ENRD0, 0); + ascodec_write(AS3514_CHARGER, + TMPSUP_off | CHG_I_50MA | CHG_V_3_90V | CHG_OFF); + + if (charge_state > DISCHARGING) + charge_state = DISCHARGING; /* Not an error state already */ + + charger_total_timer = 0; + battery_voltage_sync(); +} + +/* Enable charger with specified settings. Start timers, etc. */ +static void enable_charger(void) +{ + ascodec_write(AS3514_CHARGER, BATT_ICHARGE | BATT_VENDPOINT); + + sleep(HZ/10); /* Allow HW FET turn-on time (it could be gradual). */ + + ascodec_write(AS3514_IRQ_ENRD0, CHG_TMPHIGH | CHG_ENDOFCH); + ascodec_read(AS3514_IRQ_ENRD0); /* Clear out interrupts (important!) */ + + charge_state = CHARGING; + charger_total_timer = CHARGER_TOTAL_TIMER_RELOAD; + battery_voltage_sync(); +} + +void powermgmt_init_target(void) +{ + /* Set CHARGER to default value. */ + ascodec_write(AS3514_CHARGER, + TMPSUP_off | CHG_I_50MA | CHG_V_3_90V | CHG_OFF); +} + +static inline void charger_plugged(void) +{ + batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */ + battery_voltage_sync(); +} + +static inline void charger_control(void) +{ + switch (charge_state) + { + case DISCHARGING: + { + unsigned int millivolts = battery_voltage(); + unsigned int thresh = batt_threshold; + + batt_threshold = BATT_VAUTO_RECHARGE; + + if (millivolts <= thresh) + enable_charger(); + break; + } /* DISCHARGING: */ + + case CHARGING: + { + unsigned int enrd0 = ascodec_read(AS3514_IRQ_ENRD0); + + if (enrd0 & (CHG_TMPHIGH | CHG_ENDOFCH)) + { + /* End of charge or temp is too high */ + if (enrd0 & CHG_TMPHIGH) + charge_state = CHARGE_STATE_ERROR; + disable_charger(); + } + else if (charger_total_timer > 0 && --charger_total_timer == 0) + { + /* Timer ran out - require replug. */ + charge_state = CHARGE_STATE_ERROR; + disable_charger(); + } + break; + } /* CHARGING: */ + + default: + /* DISABLED, ERROR */ + break; + } +} + +static inline void charger_unplugged(void) +{ + disable_charger(); + + if (charge_state >= CHARGE_STATE_ERROR) + charge_state = DISCHARGING; /* Reset error */ + + battery_voltage_sync(); +} + +/* Main charging algorithm - called from powermgmt.c */ +void charging_algorithm_step(void) +{ + switch (charger_input_state) + { + case NO_CHARGER: + /* Nothing to do */ + break; + + case CHARGER_PLUGGED: + charger_plugged(); + break; + + case CHARGER: + charger_control(); + break; + + case CHARGER_UNPLUGGED: + charger_unplugged(); + break; + } /* switch */ + + if (charger_close) + { + /* Disable further charging and ack. */ + charge_state = CHARGE_STATE_DISABLED; + disable_charger(); + charger_close = false; + } +} + +/* Disable the charger and prepare for poweroff - called off-thread so we + * signal the charging thread to prepare to quit. */ +void charging_algorithm_close(void) +{ + charger_close = true; + + /* Power management thread will set it false again. */ + while (charger_close) + sleep(HZ/10); +} Property changes on: firmware/target/arm/sandisk/powermgmt-as3514.c ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c =================================================================== --- firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c (revision 19704) +++ firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c (working copy) @@ -48,14 +48,3 @@ /* Sansa c200 has a 530 mAh LiPo battery */ 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200 }; - -/* ADC should read 0x3ff=5.12V */ -#define BATTERY_SCALE_FACTOR 5125 -/* full-scale ADC readout (2^10) in millivolt */ - -/* Returns battery voltage from ADC [millivolts] */ -unsigned int battery_adc_voltage(void) -{ - return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10; -} - Index: firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c =================================================================== --- firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c (revision 19704) +++ firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c (working copy) @@ -47,14 +47,3 @@ /* Sansa Li Ion 750mAH FIXME */ 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 }; - -/* ADC should read 0x3ff=5.12V */ -#define BATTERY_SCALE_FACTOR 5125 -/* full-scale ADC readout (2^10) in millivolt */ - -/* Returns battery voltage from ADC [millivolts] */ -unsigned int battery_adc_voltage(void) -{ - return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10; -} - Index: firmware/target/arm/sandisk/powermgmt-target.h =================================================================== --- firmware/target/arm/sandisk/powermgmt-target.h (revision 0) +++ firmware/target/arm/sandisk/powermgmt-target.h (revision 0) @@ -0,0 +1,33 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Michael Sevakis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef POWERMGMT_TARGET_H +#define POWERMGMT_TARGET_H + +void powermgmt_init_target(void); +void charging_algorithm_step(void); +void charging_algorithm_close(void); + +/* We want to be able to reset the averaging filter */ +#define HAVE_RESET_BATTERY_FILTER + +#define BATT_AVE_SAMPLES 32 + +#endif /* POWERMGMT_TARGET_H */ Property changes on: firmware/target/arm/sandisk/powermgmt-target.h ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: firmware/powermgmt.c =================================================================== --- firmware/powermgmt.c (revision 19704) +++ firmware/powermgmt.c (working copy) @@ -435,7 +435,7 @@ #endif } -#ifdef HAVE_BATTERY_SWITCH +#if defined(HAVE_BATTERY_SWITCH) || defined(HAVE_RESET_BATTERY_FILTER) /* * Reset the battery voltage filter to a new value and update the * status.