summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-01-11 10:07:22 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-01-11 10:07:22 +0000
commit7d7969114da36a99afc4d80576ff9b089cb09e50 (patch)
tree48c3c574e382d80454c28a6b77de64a64f3cedcd /firmware/target/arm
parentb84fe020a5bc497cee9b88eb782c2d4a9b7be711 (diff)
downloadrockbox-7d7969114da36a99afc4d80576ff9b089cb09e50.tar.gz
rockbox-7d7969114da36a99afc4d80576ff9b089cb09e50.zip
c200v1/e200v1: Add battery charging. This should be usable on v2 players but those should be evaluated for current, endpoint voltage and whether or not accurate battery readings may always be obtained (which determines algorithm setup and behavior).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19748 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/powermgmt-ascodec.c231
-rw-r--r--firmware/target/arm/sandisk/powermgmt-target.h59
-rw-r--r--firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c13
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c11
4 files changed, 291 insertions, 23 deletions
diff --git a/firmware/target/arm/powermgmt-ascodec.c b/firmware/target/arm/powermgmt-ascodec.c
new file mode 100644
index 0000000000..ab9fd7b490
--- /dev/null
+++ b/firmware/target/arm/powermgmt-ascodec.c
@@ -0,0 +1,231 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Michael Sevakis
11 * Copyright (C) 2008 by Bertrik Sikken
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "config.h"
23#include "system.h"
24#include "thread.h"
25#include "as3514.h"
26#include "ascodec.h"
27#include "adc.h"
28#include "powermgmt.h"
29#include "power.h"
30
31/*===========================================================================
32 * These parameters may be defined per target:
33 *
34 * BATT_FULL_VOLTAGE - Upon connect a charge cycle begins if the reading is
35 * lower than this value (millivolts).
36 *
37 * BATT_VAUTO_RECHARGE - While left plugged after cycle completion, the
38 * charger restarts automatically if the reading drops
39 * below this value (millivolts). Must be less than
40 * BATT_FULL_VOLTAGE.
41 *
42 * ADC_BATTERY - ADC channel from which to read the battery voltage
43 *
44 * BATT_CHG_V - Charger voltage regulation setting (as3514 regval)
45 *
46 * BATT_CHG_I - Charger current regulation setting (as3514 regval)
47 *
48 * CHARGER_TOTAL_TIMER - Maximum allowed charging time (1/2-second steps)
49 *===========================================================================
50 */
51
52/* This code assumes USB power input is not distinguishable from main
53 * power and charger connect cannot wait for USB configuration before
54 * considering USB charging available. Where they are distinguishable,
55 * things get more complicated. */
56static bool charger_close = false; /* Shutting down? */
57static int charger_total_timer = 0; /* Timeout in algorithm steps */
58
59/* Current battery threshold for (re)charge:
60 * First plugged = BATT_FULL_VOLTAGE
61 * After charge cycle or non-start = BATT_VAUTO_RECHARGE
62 */
63static unsigned int batt_threshold = 0;
64
65/* ADC should read 0x3ff=5.12V */
66/* full-scale ADC readout (2^10) in millivolt */
67
68/* Returns battery voltage from ADC [millivolts] */
69unsigned int battery_adc_voltage(void)
70{
71 return (adc_read(ADC_BATTERY) * 5125 + 512) >> 10;
72}
73
74/* Returns true if the unit is charging the batteries. */
75bool charging_state(void)
76{
77 return charge_state == CHARGING;
78}
79
80/* Reset the battery filter to a new voltage */
81static void battery_voltage_sync(void)
82{
83 int i;
84 unsigned int mv;
85
86 for (i = 0, mv = 0; i < 5; i++)
87 mv += battery_adc_voltage();
88
89 reset_battery_filter(mv / 5);
90}
91
92/* Disable charger and minimize all settings. Reset timers, etc. */
93static void disable_charger(void)
94{
95 ascodec_write(AS3514_IRQ_ENRD0, 0);
96 ascodec_write(AS3514_CHARGER,
97 TMPSUP_OFF | CHG_I_50MA | CHG_V_3_90V | CHG_OFF);
98
99 if (charge_state > DISCHARGING)
100 charge_state = DISCHARGING; /* Not an error state already */
101
102 charger_total_timer = 0;
103 battery_voltage_sync();
104}
105
106/* Enable charger with specified settings. Start timers, etc. */
107static void enable_charger(void)
108{
109 ascodec_write(AS3514_CHARGER, BATT_CHG_I | BATT_CHG_V);
110 /* Watch for end of charge. Temperature supervision is handled in
111 * hardware. Charger status can be read and has no interrupt enable. */
112 ascodec_write(AS3514_IRQ_ENRD0, CHG_ENDOFCH);
113
114 sleep(HZ/10); /* Allow charger turn-on time (it could be gradual). */
115
116 ascodec_read(AS3514_IRQ_ENRD0); /* Clear out interrupts (important!) */
117
118 charge_state = CHARGING;
119 charger_total_timer = CHARGER_TOTAL_TIMER;
120 battery_voltage_sync();
121}
122
123void powermgmt_init_target(void)
124{
125 /* Everything CHARGER, OFF! */
126 ascodec_write(AS3514_IRQ_ENRD0, 0);
127 ascodec_write(AS3514_CHARGER,
128 TMPSUP_OFF | CHG_I_50MA | CHG_V_3_90V | CHG_OFF);
129}
130
131static inline void charger_plugged(void)
132{
133 batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */
134 battery_voltage_sync();
135}
136
137static inline void charger_control(void)
138{
139 switch (charge_state)
140 {
141 case DISCHARGING:
142 {
143 unsigned int millivolts;
144 unsigned int thresh = batt_threshold;
145
146 if (BATT_FULL_VOLTAGE == thresh)
147 {
148 /* Wait for CHG_status to be indicated. */
149 if ((ascodec_read(AS3514_IRQ_ENRD0) & CHG_STATUS) == 0)
150 break;
151
152 batt_threshold = BATT_VAUTO_RECHARGE;
153 }
154
155 millivolts = battery_voltage();
156
157 if (millivolts <= thresh)
158 enable_charger();
159 break;
160 } /* DISCHARGING: */
161
162 case CHARGING:
163 {
164 if ((ascodec_read(AS3514_IRQ_ENRD0) & CHG_ENDOFCH) == 0)
165 {
166 if (--charger_total_timer > 0)
167 break;
168
169 /* Timer ran out - require replug. */
170 charge_state = CHARGE_STATE_ERROR;
171 }
172 /* else end of charge */
173
174 disable_charger();
175 break;
176 } /* CHARGING: */
177
178 default:
179 /* DISABLED, ERROR */
180 break;
181 }
182}
183
184static inline void charger_unplugged(void)
185{
186 disable_charger();
187 if (charge_state >= CHARGE_STATE_ERROR)
188 charge_state = DISCHARGING; /* Reset error */
189}
190
191/* Main charging algorithm - called from powermgmt.c */
192void charging_algorithm_step(void)
193{
194 switch (charger_input_state)
195 {
196 case NO_CHARGER:
197 /* Nothing to do */
198 break;
199
200 case CHARGER_PLUGGED:
201 charger_plugged();
202 break;
203
204 case CHARGER:
205 charger_control();
206 break;
207
208 case CHARGER_UNPLUGGED:
209 charger_unplugged();
210 break;
211 }
212
213 if (charger_close)
214 {
215 /* Disable further charging and ack. */
216 charge_state = CHARGE_STATE_DISABLED;
217 disable_charger();
218 charger_close = false;
219 }
220}
221
222/* Disable the charger and prepare for poweroff - called off-thread so we
223 * signal the charging thread to prepare to quit. */
224void charging_algorithm_close(void)
225{
226 charger_close = true;
227
228 /* Power management thread will set it false again. */
229 while (charger_close)
230 sleep(HZ/10);
231}
diff --git a/firmware/target/arm/sandisk/powermgmt-target.h b/firmware/target/arm/sandisk/powermgmt-target.h
new file mode 100644
index 0000000000..aa6a0e0e3d
--- /dev/null
+++ b/firmware/target/arm/sandisk/powermgmt-target.h
@@ -0,0 +1,59 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Michael Sevakis
11 * Copyright (C) 2008 by Bertrik Sikken
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#ifndef POWERMGMT_TARGET_H
23#define POWERMGMT_TARGET_H
24
25#if defined(SANSA_C200)
26/* This configuration triggers a single charge cycle upon plugging and stops.
27 * The true voltage cannot be read accurately and so monitoring isn't really
28 * possible. The battery filter is still synced to have a proper reading
29 * when disconnecting. */
30#define BATT_FULL_VOLTAGE 5121 /* Won't read this high - force start */
31#define BATT_VAUTO_RECHARGE 0 /* Won't read this low - force one cycle */
32#define BATT_CHG_V CHG_V_4_20V
33#define BATT_CHG_I CHG_I_300MA
34#define CHARGER_TOTAL_TIMER (4*3600*2) /* 4 hours enough? */
35#define ADC_BATTERY ADC_BVDD
36#elif defined(SANSA_E200)
37/* PREFERRED - Check if topped-off and monitor voltage while plugged. */
38#define BATT_FULL_VOLTAGE 4160
39#define BATT_VAUTO_RECHARGE 4100
40#define BATT_CHG_V CHG_V_4_20V
41#define BATT_CHG_I CHG_I_300MA
42#define CHARGER_TOTAL_TIMER (4*3600*2) /* 4 hours enough? */
43/* On e200 ADC_RTCSUP seems to represent battery voltage better than
44 * ADC_BVDD during charging (ADC_BVDD is way too high) and appears the
45 * same in normal use.
46 */
47#define ADC_BATTERY ADC_RTCSUP
48#endif
49
50void powermgmt_init_target(void);
51void charging_algorithm_step(void);
52void charging_algorithm_close(void);
53
54/* We want to be able to reset the averaging filter */
55#define HAVE_RESET_BATTERY_FILTER
56
57#define BATT_AVE_SAMPLES 32
58
59#endif /* POWERMGMT_TARGET_H */
diff --git a/firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c b/firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c
index 963e7218de..9d7a0e2965 100644
--- a/firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c
+++ b/firmware/target/arm/sandisk/sansa-c200/powermgmt-c200.c
@@ -38,8 +38,8 @@ const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
38const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = 38const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
39{ 39{
40 40
41 /* NOTE: why is the top voltage 4237? That's just too high. */
41 { 3286, 3679, 3734, 3764, 3788, 3824, 3886, 3950, 4014, 4098, 4237 }, 42 { 3286, 3679, 3734, 3764, 3788, 3824, 3886, 3950, 4014, 4098, 4237 },
42
43}; 43};
44 44
45/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ 45/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
@@ -48,14 +48,3 @@ const unsigned short percent_to_volt_charge[11] =
48 /* Sansa c200 has a 530 mAh LiPo battery */ 48 /* Sansa c200 has a 530 mAh LiPo battery */
49 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200 49 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200
50}; 50};
51
52/* ADC should read 0x3ff=5.12V */
53#define BATTERY_SCALE_FACTOR 5125
54/* full-scale ADC readout (2^10) in millivolt */
55
56/* Returns battery voltage from ADC [millivolts] */
57unsigned int battery_adc_voltage(void)
58{
59 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
60}
61
diff --git a/firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c b/firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c
index 43f37463f8..144ca37ebf 100644
--- a/firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/powermgmt-e200.c
@@ -47,14 +47,3 @@ const unsigned short percent_to_volt_charge[11] =
47 /* Sansa Li Ion 750mAH FIXME */ 47 /* Sansa Li Ion 750mAH FIXME */
48 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 48 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160
49}; 49};
50
51/* ADC should read 0x3ff=5.12V */
52#define BATTERY_SCALE_FACTOR 5125
53/* full-scale ADC readout (2^10) in millivolt */
54
55/* Returns battery voltage from ADC [millivolts] */
56unsigned int battery_adc_voltage(void)
57{
58 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
59}
60