diff mbox

strange crashes in current main branch

Message ID alpine.LNX.2.10.1404062142220.20728@ssn.gwdg.de
State Accepted
Headers show

Commit Message

Tim Ehlers April 6, 2014, 8:02 p.m. UTC
On Sun, 6 Apr 2014, Christophe Devine wrote:

Hi Christophe,

> A year ago, you reported strange crashes in current branch. Did you 
> resolve the issue? It seems we are having a similar problem, where 
> layer1 would crash eventually.

yes, I tracked it down to the charging code. I think it comes from the 
fact, that layer1 is periodically polled by layer23 (mobile) about the 
current battery-status. And there seems to be a problem with queueing 
these things over the serial line. So if battery-status is polled and 
other things are going through serial at the same time, layer1 crashes 
eventually.

Thats my interpretation, but fact is, if you revert the patch attached to 
the mail, the crashes are gone, but you can't charge. :)

I modified the mobile battery, removing the battery itself, and replacing 
it with a 3.7V AC-Adapter, so that I don't need the charging.

Maybe you can investigate it in more detail? Or better I send it to the 
list too, so the problem could be discussed in the big round again.

Best

Tim

Comments

Max April 10, 2014, 10:39 a.m. UTC | #1
06.04.2014 22:02, Tim Ehlers пишет:

> I modified the mobile battery, removing the battery itself, and replacing it with a
> 3.7V AC-Adapter, so that I don't need the charging.
> 

Interesting - can you describe those modifications in more details?
Which adapter have you used? How did you connect it exactly? Some pics?

thanks,
Max.
Tim Ehlers April 10, 2014, 6:44 p.m. UTC | #2
On Thu, 10 Apr 2014, Max.Suraev@fairwaves.co wrote:

>> I modified the mobile battery, removing the battery itself, and replacing it with a
>> 3.7V AC-Adapter, so that I don't need the charging.
>
> Interesting - can you describe those modifications in more details?
> Which adapter have you used? How did you connect it exactly? Some pics?

ohh, this is no "advanced" modification. I just read on the battery, that 
it outputs 3.7V, then I found for an ACDC-adapter, outputing 3.3V DC (this 
is enough, but the phone tells you that the battery is nearly empty if you 
boot the original firmware; but we use osmocom :).

I openened the white plastic cover (or more correct, opened the sticker 
around the battery), removed the Li-ION battery from the little electronic 
parts and soldered the DC-adapter there instead.

Cheers

Tim
Christophe Devine April 23, 2014, 5:48 p.m. UTC | #3
Tim,

Following your advice, I disassembled a battery, and directly connected the
output of a 3.6v motorola charger to gnd and positive side of the charging
pcb (of course the lithium cell is completely disconnected). See pictures
below, gnd is the middle pad whereas the positive pad is on the left. When
doing so be careful not to heat or pierce the lithium battery, and
afterwards put some tape to ensure electrical isolation:

https://drive.google.com/file/d/0ByHQWL5Q6bSwOHVPNlV5T2ZyZndLZmwtMF9JQ2V0eHhSNFhn/edit?usp=sharing
https://drive.google.com/file/d/0ByHQWL5Q6bSwTGNfeUFOVFM5cldPNFZ3djMyMmlSNVZ5dlNZ/edit?usp=sharing
https://drive.google.com/file/d/0ByHQWL5Q6bSwUm9XUnBOcU5SRFg4T3VpNEFZOUFHaUFSUEk0/edit?usp=sharing

The result appears to work although strangely sometimes after unplugging
the charger for some time and replugging it the microcontroller on the pcb
will not wake up. However it does immediately wake up if I measure the
current between the + and - output with a basic multimeter, but with the
black probe on the + and the red probe on the - (other way does not work).
There's probably something I'm missing here, but it's not that big a deal.

Maybe this is caused by a quirk in the microcontroller, as I've tried the
same procedure on a new compatible battery (branded "OTB", see
http://pmcdn.priceminister.com/photo/926610349.jpg) and it doesn't have
this problem, the microcontroller wakes up immediately and powers the
phone. The voltage might be a bit too high, but the phone seems to work
fine (firmware reports a full battery - also it gets slightly hotter).


On Wed, Apr 23, 2014 at 3:05 PM, Christophe Devine <
devinechristophe@gmail.com> wrote:

> Tim,
>
> Following your advice, I disassembled a battery, and directly connected
> the output of a 3.6v motorola charger to gnd and positive side of the
> charging pcb (of course the lithium cell is completely disconnected). See
> pictures below, gnd is the middle pad whereas the positive pad is on the
> left. When doing so be careful not to heat or pierce the lithium battery,
> and afterwards put some tape to ensure electrical isolation.
>
> The result appears to work although strangely sometimes after unplugging
> the charger for some time and replugging it the microcontroller on the pcb
> will not wake up. However it does immediately wake up if I measure the
> current between the + and - output with a basic multimeter, but with the
> black probe on the + and the red probe on the - (other way does not work).
> There's probably something I'm missing here, but it's not that big a deal.
>
> Maybe this is caused by a quirk in the microcontroller, as I've tried the
> same procedure on a new compatible battery (branded "OTB", see
> http://pmcdn.priceminister.com/photo/926610349.jpg) and it doesn't have
> this problem, the microcontroller wakes up immediately and powers the
> phone. The voltage might be a bit too high, but the phone seems to work
> fine (firmware reports a full battery).
>
> Christophe
>
>
> On Thu, Apr 10, 2014 at 8:44 PM, Tim Ehlers <osmocom@ehlers.info> wrote:
>
>> On Thu, 10 Apr 2014, Max.Suraev@fairwaves.co wrote:
>>
>>  I modified the mobile battery, removing the battery itself, and
>>>> replacing it with a
>>>> 3.7V AC-Adapter, so that I don't need the charging.
>>>>
>>>
>>> Interesting - can you describe those modifications in more details?
>>> Which adapter have you used? How did you connect it exactly? Some pics?
>>>
>>
>> ohh, this is no "advanced" modification. I just read on the battery, that
>> it outputs 3.7V, then I found for an ACDC-adapter, outputing 3.3V DC (this
>> is enough, but the phone tells you that the battery is nearly empty if you
>> boot the original firmware; but we use osmocom :).
>>
>> I openened the white plastic cover (or more correct, opened the sticker
>> around the battery), removed the Li-ION battery from the little electronic
>> parts and soldered the DC-adapter there instead.
>>
>> Cheers
>>
>> Tim
>>
>>
>
Christophe Devine April 24, 2014, 5:10 p.m. UTC | #4
Quick heads up: I finally ended up using a LM 317T to lower the output
voltage to ~4V, using R1=220, R2=550 and a 1uF capacitor, plus a OTB
battery pcb. The phone doesn't get as hot as before, and the "battery"
powers without delay.

https://drive.google.com/file/d/0ByHQWL5Q6bSwTWo3ZnBHTS1KeXc/edit?usp=sharing
https://drive.google.com/file/d/0ByHQWL5Q6bSwM1FPeS1iVlBYX3M/edit?usp=sharing
diff mbox

Patch

diff -u -urN osmocom-bb.120404/src/target/firmware/Makefile osmocom-bb.120501/src/target/firmware/Makefile
--- osmocom-bb.120404/src/target/firmware/Makefile	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/Makefile	2013-02-04 13:45:45.000000000 +0100
@@ -9,7 +9,8 @@ 
 # Framebuffer support, board specific drivers
 # 	
 
-FB_OBJS=fb/framebuffer.o fb/font.o fb/helvR08.o fb/helvB14.o fb/c64.o
+FB_OBJS=fb/framebuffer.o fb/font.o fb/helvR08.o fb/helvB14.o fb/c64.o \
+	fb/symbols.o
 
 FB_e88_OBJS=$(FB_OBJS) fb/fb_bw8.o fb/fb_st7558.o
 FB_e99_OBJS=$(FB_OBJS) fb/fb_rgb332.o fb/fb_ssd1783.o
@@ -24,12 +25,14 @@ 
 
 # OpenMoko GTA0x
 
-gta0x_OBJS=$(calypso_COMMON_OBJS) board/gta0x/rffe_gta0x_triband.o board/gta0x/init.o board/gta0x/rf_power.o $(FB_dummy_OBJS)
+gta0x_OBJS=$(calypso_COMMON_OBJS) board/gta0x/rffe_gta0x_triband.o board/gta0x/init.o \
+	board/gta0x/rf_power.o battery/dummy.o $(FB_dummy_OBJS)
 gta0x_ENVIRONMENTS=highram
 
 # Pirelli DP-L10
 
-pirelli_dpl10_OBJS=$(calypso_COMMON_OBJS) board/pirelli_dpl10/rffe_dpl10_triband.o board/pirelli_dpl10/init.o board/pirelli_dpl10/rf_power.o $(FB_dpl10_OBJS)
+pirelli_dpl10_OBJS=$(calypso_COMMON_OBJS) board/pirelli_dpl10/rffe_dpl10_triband.o board/pirelli_dpl10/init.o \
+		board/pirelli_dpl10/rf_power.o battery/dummy.o $(FB_dpl10_OBJS)
 pirelli_dpl10_ENVIRONMENTS=highram
 
 # Compal Generic
@@ -45,7 +48,7 @@ 
 
 # Compal E88
 
-compal_e88_OBJS=$(compal_COMMON_OBJS) board/compal_e88/init.o $(FB_e88_OBJS)
+compal_e88_OBJS=$(compal_COMMON_OBJS) board/compal_e88/init.o battery/compal_e88.o $(FB_e88_OBJS)
 compal_e88_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS) e88loader e88flash
 
 e88loader_LDS=board/compal_e88/loader.lds
@@ -56,12 +59,13 @@ 
 
 # Compal E86 (has a different RFFE configuration)
 
-compal_e86_OBJS=$(calypso_COMMON_OBJS) board/compal_e86/rffe_dualband_e86.o board/compal/rf_power.o board/compal_e86/init.o $(FB_e86_OBJS)
+compal_e86_OBJS=$(calypso_COMMON_OBJS) board/compal_e86/rffe_dualband_e86.o board/compal/rf_power.o \
+			board/compal_e86/init.o battery/dummy.o $(FB_e86_OBJS)
 compal_e86_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
 
 # Compal E99
 
-compal_e99_OBJS=$(compal_COMMON_OBJS) board/compal_e99/init.o $(FB_e99_OBJS)
+compal_e99_OBJS=$(compal_COMMON_OBJS) board/compal_e99/init.o battery/dummy.o $(FB_e99_OBJS)
 compal_e99_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
 
 e99loader_LDS=board/compal_e99/loader.lds
@@ -70,7 +74,7 @@ 
 
 # Sony Ericsson J100 (made by Compal)
 
-se_j100_OBJS=$(compal_COMMON_OBJS) board/se_j100/init.o $(FB_j100_OBJS)
+se_j100_OBJS=$(compal_COMMON_OBJS) board/se_j100/init.o battery/dummy.o $(FB_j100_OBJS)
 se_j100_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
 
 # Global include path
diff -u -urN osmocom-bb.120404/src/target/firmware/apps/hello_world/main.c osmocom-bb.120501/src/target/firmware/apps/hello_world/main.c
--- osmocom-bb.120404/src/target/firmware/apps/hello_world/main.c	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/apps/hello_world/main.c	2013-02-04 13:45:45.000000000 +0100
@@ -41,6 +41,7 @@ 
 #include <comm/sercomm.h>
 #include <comm/timer.h>
 #include <fb/framebuffer.h>
+#include <battery/battery.h>
 
 /* Main Program */
 const char *hr = "======================================================================\n";
@@ -67,6 +68,36 @@ 
 	puts("\n");
 }
 
+void
+write_battery_info(void *p){
+	char buf[128];
+
+	fb_setfg(FB_COLOR_WHITE);
+	fb_setfont(FB_FONT_C64);
+
+	snprintf(buf,sizeof(buf),"B: %04d mV",battery_info.bat_volt_mV);
+	fb_gotoxy(8,41);
+	fb_putstr(buf,framebuffer->width-8);
+
+	snprintf(buf,sizeof(buf),"C: %04d mV",battery_info.charger_volt_mV);
+	fb_gotoxy(8,49);
+	fb_putstr(buf,framebuffer->width-8);
+
+	snprintf(buf,sizeof(buf),"F: %08x",battery_info.flags);
+	fb_gotoxy(8,57);
+	fb_putstr(buf,framebuffer->width-8);
+
+	fb_flush();
+	osmo_timer_schedule((struct osmo_timer_list*)p,100);
+
+}
+
+/* timer that fires the charging loop regularly */
+static struct osmo_timer_list write_battery_info_timer = {
+	.cb = &write_battery_info,
+	.data = &write_battery_info_timer
+};
+
 int main(void)
 {
 	board_init();
@@ -123,6 +154,8 @@ 
 	sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
 	sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);
 
+	osmo_timer_schedule(&write_battery_info_timer,100);
+
 	/* beyond this point we only react to interrupts */
 	puts("entering interrupt loop\n");
 	while (1) {
diff -u -urN osmocom-bb.120404/src/target/firmware/apps/rssi/main.c osmocom-bb.120501/src/target/firmware/apps/rssi/main.c
--- osmocom-bb.120404/src/target/firmware/apps/rssi/main.c	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/apps/rssi/main.c	2013-02-04 13:45:45.000000000 +0100
@@ -50,6 +50,7 @@ 
 #include <osmocom/gsm/rsl.h>
 #include <osmocom/gsm/protocol/gsm_04_08.h>
 #include <osmocom/gsm/gsm48_ie.h>
+#include <battery/battery.h>
 
 enum key_codes key_code = KEY_INV;
 int key_pressed = 0;
@@ -170,6 +171,7 @@ 
 static void refresh_display(void)
 {
 	char text[16];
+	int bat = battery_info.battery_percent;
 
 	fb_clear();
 
@@ -179,9 +181,25 @@ 
 		fb_setfg(FB_COLOR_BLUE);
 		fb_setfont(FB_FONT_HELVR08);
 		fb_gotoxy(0, 7);
-		fb_putstr("Osmocom Monitor Tool", -1);
-		fb_gotoxy(0, 10);
+		fb_putstr("Osmocom RSSI", -1);
+		fb_setfg(FB_COLOR_RGB(0xc0, 0xc0, 0x00));
+		fb_setfont(FB_FONT_SYMBOLS);
+		fb_gotoxy(framebuffer->width - 15, 8);
+		if (bat >= 100 && (battery_info.flags & BATTERY_CHG_ENABLED)
+		 && !(battery_info.flags & BATTERY_CHARGING))
+			fb_putstr("@HHBC", framebuffer->width);
+		else {
+			sprintf(text, "@%c%c%cC", (bat >= 30) ? 'B':'A',
+				(bat >= 60) ? 'B':'A', (bat >= 90) ? 'B':'A');
+			fb_putstr(text, framebuffer->width);
+		}
+		fb_gotoxy(0, 8);
+		sprintf(text, "%c%cE%c%c", (power >= 40) ? 'D':'G',
+			(power >= 10) ? 'D':'G', (power >= 10) ? 'F':'G',
+			(power >= 40) ? 'F':'G');
+		fb_putstr(text, framebuffer->width);
 		fb_setfg(FB_COLOR_GREEN);
+		fb_gotoxy(0, 10);
 		fb_boxto(framebuffer->width - 1, 10);
 	}
 	fb_setfg(FB_COLOR_BLACK);
diff -u -urN osmocom-bb.120404/src/target/firmware/battery/compal_e88.c osmocom-bb.120501/src/target/firmware/battery/compal_e88.c
--- osmocom-bb.120404/src/target/firmware/battery/compal_e88.c	1970-01-01 01:00:00.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/battery/compal_e88.c	2013-02-04 13:42:14.000000000 +0100
@@ -0,0 +1,384 @@ 
+/* Battery management for compal_e88 */
+
+/* (C) 2010 by Christian Vogel <vogelchr@vogel.cx>
+ *
+ * All Rights Reserved
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+/*
+ * ___C123 (compal e88) very simplified diagram of charging circuitry___
+ *
+ *                           ICTL
+ *                            |
+ *                            v
+ *  Charger -> OVP -------> P-Mosfet --->[0.15 Ohm]---> Battery
+ *             (NCP345,  |             |            |
+ *              6.85V)   v             v            v
+ *                      VCHG          VCCS        VBAT &
+ *                                                VBATS
+ *
+ * Inputs to IOTA:
+ *  VCHG:        senses voltage on the charger input
+ *  VCSS/VBATS:  to difference amplifier, to measure charge current
+ *  VBAT:        senses voltage on the battery terminal
+ * Outputs from IOTA:
+ *  ICTL:        Control signal for the switching mosfet
+ *
+ */
+
+#include <battery/battery.h>
+#include <battery/compal_e88.h>
+
+#include <stdint.h>
+#include <abb/twl3025.h>
+#include <comm/timer.h>
+#include <stdio.h>
+
+/* ADC calibration, scale is LSB/uV or LSB/uA, physical unit is mV or mA */
+#define ADC_TO_PHYSICAL(adc,scale) (((adc)*(scale)+500)/1000)
+#define PHYSICAL_TO_ADC(phy,scale) (((phy)*1000+(scale)/2)/(scale))
+
+/* conversion factors for internal IOTA battery charging/sensing circuitry */
+#define VREF_LSB_uV 1709  /* VREF = 1.75V    --> 1.709 mV/LSB */
+#define VBAT_LSB_uV 6836  /* VBAT = 7.0 V FS --> 6.836 mV/LSB */
+#define VCHG_LSB_uV 8545  /* VCHG = 8.75V FS --> 8.545 mV/LSB */
+#define ICHG_LSB_uA 854   /* ICHG = 875mA FS --> 0.854 mA/LSB */
+
+/* battery is considered full/empty at these thresholds... */
+#define VBAT_full   PHYSICAL_TO_ADC(4000,VBAT_LSB_uV)
+#define VBAT_empty  PHYSICAL_TO_ADC(3200,VBAT_LSB_uV)
+
+/* we declare overvoltage at this point... */
+#define VBAT_fail   PHYSICAL_TO_ADC(4250,VBAT_LSB_uV)
+
+/* DAC to ADC offsets in CC mode with my C123 
+   IMEI 358317015976471, P329431014
+
+   I/mA DAC     ADC
+   ----------------
+   100	117	108
+   150	176	168
+   200	234	227
+   250	293	291
+   300	351	349
+   350	410	410
+*/
+
+#define CHGDAC_GAIN   967  /* times 0.001 */
+#define CHGDAC_OFFS    13
+
+/* convert ADC reading to DAC value, according to calibration values
+   given above */
+#define CHGDAC_ADJ(x)   (CHGDAC_GAIN*(x)/1000+CHGDAC_OFFS)
+
+/* charging current in DAC LSBs, same ref. and # of bits, but keep
+   the correction specified above in mind!  */
+
+#define ICHG_set    CHGDAC_ADJ(PHYSICAL_TO_ADC(200,ICHG_LSB_uA))
+#define VCHG_set    CHGDAC_ADJ(VBAT_full)
+
+struct battery_info battery_info;	/* global battery info */
+uint16_t bat_compal_e88_madc[MADC_NUM_CHANNELS];	/* MADC measurements */
+
+static const int BATTERY_TIMER_DELAY=5000; /* 5000ms for control loop */
+static const int ADC_TIMER_DELAY=100;      /*  100ms for ADC conversion */
+
+/* thermistor sense current, turn it up to eleven! */
+#define  TH_SENS               (THSENS0|THSENS1|THSENS2|THEN)
+#define  BATTERY_ALL_SENSE     (TH_SENS|MESBAT|TYPEN)
+
+/*
+ * charger modes state machine
+ *
+ *    +------------------+-------------------+
+ *    |                  |                   | lost AC power
+ *    |                  ^                   ^
+ *    V  on AC power     |    @VBAT_full     |
+ * +-----+        +------------+ -----> +------------+
+ * | OFF | -----> | CONST_CURR |        | CONST_VOLT |
+ * +-----+        +------------+        +------------+
+ *    ^          ^        |                   |
+ *    |         /failure  v                   v failure
+ * +---------+ /  gone    |                   | condition
+ * | FAILURE | <----------+-------------------+
+ * +---------+
+ *
+ *  Failure modes currently detected:
+ *          + high battery voltage
+ *  Failure modes TODO:
+ *          + high battery temperature
+ */
+enum bat_compal_e88_chg_state {
+	CHARG_OFF,
+	CHARG_CONST_CURR,
+	CHARG_CONST_VOLT,
+	CHARG_FAIL
+};
+static enum bat_compal_e88_chg_state bat_compal_e88_chg_state;
+
+static const char *bat_compal_e88_chg_state_names[]={
+	"Off",
+	"Constant Current",
+	"Constant Voltage",
+	"Battery Failure"
+};
+
+static void
+bat_compal_e88_goto_state(enum bat_compal_e88_chg_state newstate){
+
+	if(bat_compal_e88_chg_state == newstate) /* already there? */
+		return;
+
+	printf("\033[34;1mCHARGER: %s --> %s.\033[0m\n",
+			bat_compal_e88_chg_state_names[bat_compal_e88_chg_state],
+			bat_compal_e88_chg_state_names[newstate]);
+
+	/* update user visible flags, set registers */
+	switch(newstate){
+	case CHARG_CONST_CURR:
+		battery_info.flags &= ~BATTERY_FAILURE;
+		battery_info.flags |= (BATTERY_CHG_ENABLED|
+						BATTERY_CHARGING);
+		twl3025_reg_write(BCICTL2,0);
+		twl3025_reg_write(CHGREG,0);
+		twl3025_reg_write(BCICTL2,CHEN|LEDC|CHIV);
+		twl3025_reg_write(CHGREG,ICHG_set);
+
+		break;
+
+	case CHARG_CONST_VOLT:
+		battery_info.flags &= ~( BATTERY_CHARGING |
+						BATTERY_FAILURE );
+		battery_info.flags |= BATTERY_CHG_ENABLED;
+		twl3025_reg_write(BCICTL2,0);
+		twl3025_reg_write(CHGREG,0);
+		twl3025_reg_write(BCICTL2,CHEN|LEDC);
+		twl3025_reg_write(CHGREG,VCHG_set);
+		break;
+
+	case CHARG_FAIL:
+	case CHARG_OFF:
+	default:
+		battery_info.flags &= ~( BATTERY_CHG_ENABLED |
+			BATTERY_CHARGING | BATTERY_FAILURE );
+		twl3025_reg_write(BCICTL2,0); /* turn off charger */
+		twl3025_reg_write(CHGREG,0);
+		break;
+	}
+
+	printf("BCICTL2 is 0x%03x, CHGREG=%d\n",
+			twl3025_reg_read(BCICTL2),
+			twl3025_reg_read(CHGREG));
+
+	bat_compal_e88_chg_state = newstate;
+}
+
+static void
+bat_compal_e88_chg_control(){
+	/* with AC power disconnected, always go to off state */
+	if(!(battery_info.flags & BATTERY_CHG_CONNECTED)){
+		bat_compal_e88_goto_state(CHARG_OFF);
+		return;
+	}
+
+	/* if failure condition is detected, always goto failure state */
+	if(bat_compal_e88_madc[MADC_VBAT] > VBAT_fail){
+		bat_compal_e88_goto_state(CHARG_FAIL);
+		return;
+	}
+
+	/* now AC power is present and battery is not over failure
+	   thresholds */
+	switch(bat_compal_e88_chg_state){
+	case CHARG_OFF:
+		if(bat_compal_e88_madc[MADC_VBAT] >= VBAT_full)
+			bat_compal_e88_goto_state(CHARG_CONST_VOLT);
+		else
+			bat_compal_e88_goto_state(CHARG_CONST_CURR);
+		break;
+	case CHARG_CONST_CURR:
+		if(bat_compal_e88_madc[MADC_VBAT] >= VBAT_full)
+			bat_compal_e88_goto_state(CHARG_CONST_VOLT);
+		break;
+	case CHARG_CONST_VOLT:
+		break;
+	default:
+	case CHARG_FAIL:
+		if(bat_compal_e88_madc[MADC_VBAT] < VBAT_full)
+			bat_compal_e88_goto_state(CHARG_CONST_CURR);
+		break;
+	}
+}
+
+/*
+ * Charging voltage connection - state machine, remembers
+ * state in battery_info.flags.
+ *
+ *                     VCHG > VCHG_thr_on
+ * +-----------------+ ------------------> +---------------+
+ * | ! CHG_CONNECTED |                     | CHG_CONNECTED |
+ * +-----------------+ <------------------ +---------------+
+ *                     VCHG < VCHG_thr_off
+ */
+static void
+bat_compal_e88_chk_ac_presence(){
+	int vrpcsts = twl3025_reg_read(VRPCSTS);
+
+	/* check for presence of charging voltage */
+	if(!(battery_info.flags & BATTERY_CHG_CONNECTED)){
+		if(vrpcsts & CHGPRES){
+			puts("\033[34;1mCHARGER: external voltage connected!\033[0m\n");
+			battery_info.flags |= BATTERY_CHG_CONNECTED;
+
+			/* always keep ADC, voltage dividers and bias voltages on */
+			twl3025_unit_enable(TWL3025_UNIT_MAD,1);
+			twl3025_reg_write(BCICTL1,BATTERY_ALL_SENSE);
+		}
+	} else {
+		if(!(vrpcsts & CHGPRES)){
+			/* we'll only run ADC on demand */
+			twl3025_unit_enable(TWL3025_UNIT_MAD,0);
+			twl3025_reg_write(BCICTL1,0);
+
+			battery_info.flags &= ~ BATTERY_CHG_CONNECTED;
+			puts("\033[34;1mCHARGER: external voltage disconnected!\033[0m\n");
+		}
+	}
+}
+
+/* ---- update voltages visible to the user ---- */
+static void
+bat_compal_e88_upd_measurements(){
+	int adc,i;
+
+	battery_info.charger_volt_mV=
+		ADC_TO_PHYSICAL(bat_compal_e88_madc[MADC_VCHG],VCHG_LSB_uV);
+	battery_info.bat_volt_mV=
+		ADC_TO_PHYSICAL(bat_compal_e88_madc[MADC_VBAT],VBAT_LSB_uV);
+	battery_info.bat_chg_curr_mA=
+		ADC_TO_PHYSICAL(bat_compal_e88_madc[MADC_ICHG],ICHG_LSB_uA);
+
+	adc = bat_compal_e88_madc[MADC_VBAT];
+	if(adc <= VBAT_empty){			/* battery 0..100% */
+		battery_info.battery_percent = 0;
+	} else if (adc >= VBAT_full){
+		battery_info.battery_percent = 100;
+	} else {
+		battery_info.battery_percent =
+			(50+100*(adc-VBAT_empty))/(VBAT_full-VBAT_empty);
+	}
+
+        /* DEBUG */
+        printf("BAT-ADC: ");
+        for(i=0;i<MADC_NUM_CHANNELS;i++)
+                printf("%3d ",bat_compal_e88_madc[i]);
+        printf("%c\n",32);
+        printf("\tCharger at %u mV.\n",battery_info.charger_volt_mV);
+        printf("\tBattery at %u mV.\n",battery_info.bat_volt_mV);
+        printf("\tCharging at %u mA.\n",battery_info.bat_chg_curr_mA);
+        printf("\tBattery capacity is %u%%.\n",battery_info.battery_percent);
+	printf("\tBattery range is %d..%d mV.\n",
+		ADC_TO_PHYSICAL(VBAT_empty,VBAT_LSB_uV),
+		ADC_TO_PHYSICAL(VBAT_full,VBAT_LSB_uV));
+        printf("\tBattery full at %d LSB .. full at %d LSB\n",VBAT_empty,VBAT_full);
+        printf("\tCharging at %d LSB (%d mA).\n",ICHG_set,
+                ADC_TO_PHYSICAL(ICHG_set,ICHG_LSB_uA));
+        i = twl3025_reg_read(BCICTL2);
+        printf("\tBCICTL2=0x%03x\n",i);      
+	printf("\tbattery-info.flags=0x%08x\n",battery_info.flags);
+	printf("\tbat_compal_e88_chg_state=%d\n",bat_compal_e88_chg_state);
+}
+
+/* bat_compal_e88_adc_read() :
+ *
+ * Schedule a ADC conversion or read values from ADC. If we are
+ * running on battery, bias currents/voltage dividers are turned
+ * on on demand.
+ *
+ * Return 0 if new ADC values have been acquired, 1 if ADC
+ * has been scheduled for a new conversion or is not yet finished.
+ * 
+ */
+
+enum bat_compal_e88_madc_stat {
+	ADC_CONVERSION = 1 << 0
+};
+static uint32_t bat_compal_e88_madc_stat=0;
+
+static int
+bat_compal_e88_adc_read(){
+	int i;
+
+	if(bat_compal_e88_madc_stat & ADC_CONVERSION){
+		i = twl3025_reg_read(MADCSTAT);
+		if(i & ADCBUSY)
+			return 1;
+		for(i=0;i<MADC_NUM_CHANNELS;i++)
+			bat_compal_e88_madc[i]=twl3025_reg_read(VBATREG+i);
+		/* if charger is connected, we keep the ADC and BIAS on
+		   continuously, if running on battery, we try to save power */
+		if(!(battery_info.flags & BATTERY_CHG_CONNECTED)){
+			twl3025_reg_write(BCICTL1,0x00); /* turn off bias */
+			twl3025_unit_enable(TWL3025_UNIT_MAD,0); /* & ADC */
+		}
+		bat_compal_e88_madc_stat &= ~ ADC_CONVERSION;
+		return 0;
+	} else {
+		/* if running on battery, turn on ADC & BIAS on demand */
+		if(!(battery_info.flags & BATTERY_CHG_CONNECTED)){
+			twl3025_unit_enable(TWL3025_UNIT_MAD,1);
+			twl3025_reg_write(BCICTL1,BATTERY_ALL_SENSE);
+		}
+
+		twl3025_reg_write(MADCTRL,0xff); /* convert all channels */
+		twl3025_reg_write(VBATREG,0);    /* trigger conversion */
+
+		bat_compal_e88_madc_stat |= ADC_CONVERSION;
+		return 1;
+	}
+}
+
+static void
+battery_compal_e88_timer_cb(void *p){
+	struct osmo_timer_list *tmr = (struct osmo_timer_list*)p;
+	int i;
+
+	if(bat_compal_e88_adc_read()){ /* read back ADCs after a brief delay */
+		osmo_timer_schedule(tmr,ADC_TIMER_DELAY);
+		return;
+	}
+
+	bat_compal_e88_upd_measurements();	/* convert user-accessible information */
+	bat_compal_e88_chk_ac_presence();	/* detect AC charger presence */
+	bat_compal_e88_chg_control();	/* battery charger state machine */
+
+	osmo_timer_schedule(tmr,BATTERY_TIMER_DELAY);
+}
+
+/* timer that fires the charging loop regularly */
+static struct osmo_timer_list battery_compal88_timer = {
+	.cb = &battery_compal_e88_timer_cb,
+	.data = &battery_compal88_timer
+};
+
+void
+battery_compal_e88_init(){
+	printf("%s: starting up\n",__FUNCTION__);
+	osmo_timer_schedule(&battery_compal88_timer,BATTERY_TIMER_DELAY);
+}
+
diff -u -urN osmocom-bb.120404/src/target/firmware/battery/dummy.c osmocom-bb.120501/src/target/firmware/battery/dummy.c
--- osmocom-bb.120404/src/target/firmware/battery/dummy.c	1970-01-01 01:00:00.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/battery/dummy.c	2013-02-04 13:42:14.000000000 +0100
@@ -0,0 +1,9 @@ 
+#include <battery/battery.h>
+
+/* Battery Management: Dummy file when no charging logic exists. */
+struct battery_info battery_info;
+
+void battery_dummy_init(){
+	battery_info.flags = BATTERY_FAILURE; /* not implemented */
+}
+
diff -u -urN osmocom-bb.120404/src/target/firmware/board/compal_e88/init.c osmocom-bb.120501/src/target/firmware/board/compal_e88/init.c
--- osmocom-bb.120404/src/target/firmware/board/compal_e88/init.c	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/board/compal_e88/init.c	2013-02-04 13:45:45.000000000 +0100
@@ -45,6 +45,7 @@ 
 #include <abb/twl3025.h>
 #include <rf/trf6151.h>
 #include <fb/framebuffer.h>
+#include <battery/compal_e88.h>
 
 #define ARMIO_LATCH_OUT 0xfffe4802
 #define IO_CNTL_REG	0xfffe4804
@@ -133,4 +134,7 @@ 
 
 	/* Initialize ABB driver (uses SPI) */
 	twl3025_init();
+
+	/* Initialize the charging controller */
+	battery_compal_e88_init();
 }
diff -u -urN osmocom-bb.120404/src/target/firmware/fb/font.c osmocom-bb.120501/src/target/firmware/fb/font.c
--- osmocom-bb.120404/src/target/firmware/fb/font.c	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/fb/font.c	2013-02-04 13:42:14.000000000 +0100
@@ -32,6 +32,7 @@ 
 extern const struct fb_font font_helvB14;
 // extern const struct fb_font font_helvB24;
 extern const struct fb_font font_c64;
+extern const struct fb_font font_symbols;
 
 const struct fb_font *fb_fonts[]={
 //	&font_4x6,
@@ -43,6 +44,7 @@ 
 	&font_helvB14,
 //	&font_helvB24,
 	&font_c64,
+	&font_symbols,
 };
 
 const struct fb_char *
diff -u -urN osmocom-bb.120404/src/target/firmware/fb/symbols.c osmocom-bb.120501/src/target/firmware/fb/symbols.c
--- osmocom-bb.120404/src/target/firmware/fb/symbols.c	1970-01-01 01:00:00.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/fb/symbols.c	2013-02-04 13:42:14.000000000 +0100
@@ -0,0 +1,113 @@ 
+#include <fb/font.h>
+static const uint8_t font_symbols_data[] = {
+/* @ battery - */
+	/*0000:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0005:*/	0x60,	/* .##..... */
+	/*0006:*/	0x40,	/* .#...... */
+	/*0007:*/	0x40,	/* .#...... */
+	/*0008:*/	0x40,	/* .#...... */
+	/*0009:*/	0x40,	/* .#...... */
+	/*000a:*/	0x40,	/* .#...... */
+	/*000b:*/	0x40,	/* .#...... */
+	/*000c:*/	0x60,	/* .##..... */
+/* A battery empty */
+	/*000d:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0012:*/	0xe0,	/* ###..... */
+	/*0013:*/	0x00,	/* ........ */
+	/*0014:*/	0x00,	/* ........ */
+	/*0015:*/	0x00,	/* ........ */
+	/*0016:*/	0x00,	/* ........ */
+	/*0017:*/	0x00,	/* ........ */
+	/*0018:*/	0x00,	/* ........ */
+	/*0019:*/	0xe0,	/* ###..... */
+/* B battery full */
+	/*001a:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*001f:*/	0xe0,	/* ###..... */
+	/*0020:*/	0x00,	/* ........ */
+	/*0021:*/	0xc0,	/* ##...... */
+	/*0022:*/	0xc0,	/* ##...... */
+	/*0023:*/	0xc0,	/* ##...... */
+	/*0024:*/	0xc0,	/* ##...... */
+	/*0025:*/	0x00,	/* ........ */
+	/*0026:*/	0xe0,	/* ###..... */
+/* C battery + */
+	/*0027:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*002c:*/	0x80,	/* #....... */
+	/*002d:*/	0x80,	/* #....... */
+	/*002e:*/	0xc0,	/* ##...... */
+	/*002f:*/	0xc0,	/* ##...... */
+	/*0030:*/	0xc0,	/* ##...... */
+	/*0031:*/	0xc0,	/* ##...... */
+	/*0032:*/	0x80,	/* #....... */
+	/*0033:*/	0x80,	/* #....... */
+/* D radiation left */
+	/*0034:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0039:*/	0x20,	/* ..#..... */
+	/*003a:*/	0x40,	/* .#...... */
+	/*003b:*/	0x20,	/* ..#..... */
+	/*003c:*/	0x00,	/* ........ */
+	/*003d:*/	0x00,	/* ........ */
+	/*003e:*/	0x00,	/* ........ */
+	/*003f:*/	0x00,	/* ........ */
+	/*0040:*/	0x00,	/* ........ */
+/* E tower */
+	/*0041:*/	5, 5, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0046:*/	0x20,	/* ..#..... */
+	/*0047:*/	0x50,	/* .#.#.... */
+	/*0048:*/	0x20,	/* ..#..... */
+	/*0049:*/	0x20,	/* ..#..... */
+	/*004a:*/	0x50,	/* .#.#.... */
+	/*004b:*/	0x50,	/* .#.#.... */
+	/*004c:*/	0x88,	/* #...#... */
+	/*004d:*/	0xf8,	/* #####... */
+/* F radiation right */
+	/*004e:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0053:*/	0x80,	/* #....... */
+	/*0054:*/	0x40,	/* .#...... */
+	/*0055:*/	0x80,	/* #....... */
+	/*0056:*/	0x00,	/* ........ */
+	/*0057:*/	0x00,	/* ........ */
+	/*0058:*/	0x00,	/* ........ */
+	/*0059:*/	0x00,	/* ........ */
+	/*005a:*/	0x00,	/* ........ */
+/* G no radiation */
+	/*005b:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*0060:*/	0x00,	/* ........ */
+	/*0061:*/	0x00,	/* ........ */
+	/*0062:*/	0x00,	/* ........ */
+	/*0063:*/	0x00,	/* ........ */
+	/*0064:*/	0x00,	/* ........ */
+	/*0065:*/	0x00,	/* ........ */
+	/*0066:*/	0x00,	/* ........ */
+	/*0067:*/	0x00,	/* ........ */
+/* H battery loaded */
+	/*0068:*/	3, 3, 8, 0, 0, /* width and bbox (w,h,x,y) */
+	/*006d:*/	0xe0,	/* ###..... */
+	/*006e:*/	0x00,	/* ........ */
+	/*006f:*/	0xe0,	/* ###..... */
+	/*0070:*/	0xe0,	/* ###..... */
+	/*0071:*/	0xe0,	/* ###..... */
+	/*0072:*/	0xe0,	/* ###..... */
+	/*0073:*/	0x00,	/* ........ */
+	/*0074:*/	0xe0,	/* ###..... */
+};
+static const uint16_t font_symbols_offsets[] = {
+	0x0000 /* '@' */,
+	0x000d /* 'A' */,
+	0x001a /* 'B' */,
+	0x0027 /* 'C' */,
+	0x0034 /* 'D' */,
+	0x0041 /* 'E' */,
+	0x004e /* 'F' */,
+	0x005b /* 'G' */,
+	0x0068 /* 'H' */,
+};
+const struct fb_font font_symbols = {
+	.height = 8,
+	.ascent = 8,
+	.firstchar = 64, /* '@' */
+	.lastchar = 72,
+	.chardata = font_symbols_data,
+	.charoffs = font_symbols_offsets,
+};
+
diff -u -urN osmocom-bb.120404/src/target/firmware/include/abb/twl3025.h osmocom-bb.120501/src/target/firmware/include/abb/twl3025.h
--- osmocom-bb.120404/src/target/firmware/include/abb/twl3025.h	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/include/abb/twl3025.h	2013-02-04 13:42:14.000000000 +0100
@@ -69,6 +69,56 @@ 
 };
 #define BULDATA2	BULDATA1
 
+/* available ADC inputs on IOTA */
+enum twl3025_dac_inputs {/* === Signal ============================= */
+	MADC_VBAT=0,	/* battery voltage / 4                      */
+	MADC_VCHG=1,	/* charger voltage / 5                      */
+	MADC_ICHG=2,	/* I-sense amp or CHGREG DAC output         */
+	MADC_VBKP=3,	/* backup battery voltage / 4               */
+	MADC_ADIN1=4,	/* VADCID, sense battery type, not used     */
+	MADC_ADIN2=5,	/* Temperature sensor in Battery            */
+	MADC_ADIN3=6,	/* Mode_detect: sense 2.5mm jack insertion  */
+	MADC_ADIN4=7,	/* RITA: TEMP_SEN                           */
+	MADC_NUM_CHANNELS=8
+};
+
+enum madcstat_reg_bits { /* monitoring ADC status register */
+	ADCBUSY = 0x01  /* if set, a conversion is currently going on */
+};
+
+/* BCICTL1 register bits */
+enum bcictl1_reg_bits {
+	MESBAT	= 1<<0,	/* connect resistive divider for bat voltage */
+	DACNBUF	= 1<<1,	/* bypass DAC buffer */
+	THSENS0	= 1<<3,	/* thermal sensor bias current (ADIN2), bit 0 */
+	THSENS1	= 1<<4,	/* "" bit 1 */
+	THSENS2	= 1<<5,	/* "" bit 2 */
+	THEN	= 1<<6,	/* enable thermal sensor bias current (ADIN1) */ 
+	TYPEN	= 1<<7	/* enable bias current for battery type reading */
+};
+
+/* BCICTL1 register bits */
+enum bcictl2_reg_bits {
+	CHEN	= 1<<0,	/* enable charger */
+	CHIV	= 1<<1,	/* 1=constant current, 0=constant voltage */
+	CHBPASSPA=1<<2,	/* full charging of the battery during pulse radio */
+	CLIB	= 1<<3,	/* calibrate I-to-V amp (short input pins) */
+	CHDISPA	= 1<<4,	/* disabel charging during pulse radio (???) */
+	LEDC	= 1<<5,	/* enable LED during charge */
+	CGAIN4	= 1<<6,	/* if set, I-to-V amp gain is reduced from 10 to 4 */
+	PREOFF	= 1<<7	/* disable battery precharge */
+};
+
+enum vrpcsts_reg_bits {
+	ONBSTS = 1<<0,	/* button push switched on the mobile */
+	ONRSTS = 1<<1,	/* RPWON terminal switched on the mobile */
+	ITWSTS = 1<<2,	/* ITWAKEUP terminal switched on the mobile */
+	CHGSTS = 1<<3,	/* plugging in charger has switched on the mobile */
+	ONREFLT= 1<<4,	/* state of PWON terminal after debouncing */
+	ONMRFLT= 1<<5,	/* state of RPWON terminal after debouncing */
+	CHGPRES= 1<<6	/* charger is connected */
+};
+
 enum togbr2_bits {
 	TOGBR2_KEEPR	= (1 << 0),	/* Clear KEEPON bit */
 	TOGBR2_KEEPS	= (1 << 1),	/* Set KEEPON bit */
diff -u -urN osmocom-bb.120404/src/target/firmware/include/battery/battery.h osmocom-bb.120501/src/target/firmware/include/battery/battery.h
--- osmocom-bb.120404/src/target/firmware/include/battery/battery.h	1970-01-01 01:00:00.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/include/battery/battery.h	2013-02-04 13:42:14.000000000 +0100
@@ -0,0 +1,37 @@ 
+#ifndef _BATTERY_BATTERY_H
+#define _BATTERY_BATTERY_H
+
+/* User-visible state of the battery charger.
+ *
+ * If CHG_CONNECTED, power is externally supplied to the mobile.
+ *
+ * If CHG_ENABLED, the charger will try to provide charge
+ * to the battery if needed, but this state might be switchable?
+ *
+ * BATTERY_CHARGING: Battery is not full, so a significant charging
+ * current (not trickle charge) is supplied.
+ *
+ * BATTERY_FAILURE: Overtemperature, overvoltage, ... if this bit
+ * is set, charging should be inhibited.
+ */
+
+
+enum battery_flags {
+	BATTERY_CHG_CONNECTED = 1 << 0,  /* AC adapter is connected */
+	BATTERY_CHG_ENABLED   = 1 << 1,  /* if needed charger could charge */
+	BATTERY_CHARGING      = 1 << 2,  /* charger is actively charging */
+	BATTERY_FAILURE       = 1 << 3,  /* problem exists preventing charge */
+};
+
+struct battery_info {
+	enum battery_flags flags;
+	int charger_volt_mV; /* charger connection voltage */
+	int bat_volt_mV;     /* battery terminal voltage */
+	int bat_chg_curr_mA; /* battery charging current */
+	int battery_percent; /* 0(empty) .. 100(full) */
+};
+
+extern struct battery_info
+battery_info;
+
+#endif
diff -u -urN osmocom-bb.120404/src/target/firmware/include/battery/compal_e88.h osmocom-bb.120501/src/target/firmware/include/battery/compal_e88.h
--- osmocom-bb.120404/src/target/firmware/include/battery/compal_e88.h	1970-01-01 01:00:00.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/include/battery/compal_e88.h	2013-02-04 13:42:14.000000000 +0100
@@ -0,0 +1,15 @@ 
+#ifndef _BATTERY_COMPAL_E88_H
+#define _BATTERY_COMPAL_E88_H
+
+#include <stdint.h>
+#include <abb/twl3025.h>
+
+/* initialize the charger control loop on C123 */
+
+extern void
+battery_compal_e88_init();
+
+extern uint16_t
+compal_e88_madc[MADC_NUM_CHANNELS];
+
+#endif
diff -u -urN osmocom-bb.120404/src/target/firmware/include/fb/font.h osmocom-bb.120501/src/target/firmware/include/fb/font.h
--- osmocom-bb.120404/src/target/firmware/include/fb/font.h	2013-02-15 10:31:40.000000000 +0100
+++ osmocom-bb.120501/src/target/firmware/include/fb/font.h	2013-02-04 13:42:14.000000000 +0100
@@ -70,6 +70,7 @@ 
 	FB_FONT_HELVB14,
 //	FB_FONT_HELVB24,
 	FB_FONT_C64,
+	FB_FONT_SYMBOLS,
 };
 
 extern const struct fb_font *fb_fonts[]; // note: has to match fb_font_id enum!