diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 5773374..b4d917a 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -58,7 +58,6 @@
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
#include "disk.h"
#include "adc.h"
-#include "power.h"
#include "usb.h"
#include "rtc.h"
#include "storage.h"
@@ -75,6 +74,7 @@
#include "radio.h"
#endif
#endif
+#include "power.h"

#ifdef HAVE_LCD_BITMAP
#include "scrollbar.h"
@@ -900,7 +900,7 @@ static bool tsc2100_debug(void)
return simplelist_show_list(&info);
}
#endif
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
#ifdef HAVE_LCD_BITMAP
/*
* view_battery() shows a automatically scaled graph of the battery voltage
@@ -2168,7 +2168,7 @@ static const struct the_menu_item menuitems[] = {
{ "View CPU stats", dbg_cpuinfo },
#endif
#ifdef HAVE_LCD_BITMAP
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
{ "View battery", view_battery },
#endif
#ifndef APPLICATION
diff --git a/apps/plugin.c b/apps/plugin.c
index 6dd84af..f17ad3c 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -664,7 +664,7 @@ static const struct plugin_api rockbox_api = {
battery_level,
battery_level_safe,
battery_time,
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
battery_voltage,
#endif
#if CONFIG_CHARGING
diff --git a/apps/plugin.h b/apps/plugin.h
index e778f51..3779801 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -793,7 +793,7 @@ struct plugin_api {
int (*battery_level)(void);
bool (*battery_level_safe)(void);
int (*battery_time)(void);
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
unsigned int (*battery_voltage)(void);
#endif
#if CONFIG_CHARGING
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 387f145..1b14c0d 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -1,4 +1,7 @@
/* plugins common to all models */
+#ifndef SIMULATOR
+battery_bench.c
+#endif
chessclock.c
credits.c
cube.c
@@ -116,8 +119,6 @@ iriver_flash.c
rockbox_flash.c
#endif /* CONFIG_CPU */

-battery_bench.c
-
#if defined(IPOD_NANO2G)
crypt_firmware.c
#endif
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index be509cf..3d90e34 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -414,7 +414,9 @@ static void thread(void)
bat[buf_idx].flags = charge_state();
#endif
buf_idx++;
+#if USING_STORAGE_CALLBACK
rb->register_storage_idle_func(flush_buffer);
+#endif
}

/* What to do when the measurement buffer is full:
@@ -454,8 +456,10 @@ static void thread(void)
}
}

+#if USING_STORAGE_CALLBACK
/* unregister flush callback and flush to disk */
rb->unregister_storage_idle_func(flush_buffer, true);
+#endif

/* log end of bench and exit reason */
fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND, 0666);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index e80a749..46ef51b 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -13,8 +13,8 @@ powermgmt.c
target/hosted/cpuinfo-linux.c
#endif

-target/hosted/powermgmt.c
#ifndef SAMSUNG_YPR0 /* uses as3514 rtc */
+target/hosted/powermgmt.c
target/hosted/rtc.c
#endif
#endif
diff --git a/firmware/export/config/samsungypr0.h b/firmware/export/config/samsungypr0.h
index 25e1906..8d133c4 100644
--- a/firmware/export/config/samsungypr0.h
+++ b/firmware/export/config/samsungypr0.h
@@ -21,7 +21,7 @@
#define USB_NONE

/* Hardware controlled charging with monitoring */
-//#define CONFIG_CHARGING CHARGING_MONITOR
+#define CONFIG_CHARGING CHARGING_MONITOR

/* There is only USB charging */
//#define HAVE_USB_POWER
@@ -127,16 +127,16 @@

/* Define current usage levels. */
/* TODO: to be filled with correct values after implementing power management */
-#define CURRENT_NORMAL 88 /* 18 hours from a 1600 mAh battery */
-#define CURRENT_BACKLIGHT 30 /* TBD */
-#define CURRENT_RECORD 0 /* no recording yet */
+//#define CURRENT_NORMAL 88 /* 18 hours from a 1600 mAh battery */
+//#define CURRENT_BACKLIGHT 30 /* TBD */
+//#define CURRENT_RECORD 0 /* no recording yet */

/* TODO: We need to do battery handling */
-//#define BATTERY_CAPACITY_DEFAULT 600 /* default battery capacity */
-//#define BATTERY_CAPACITY_MIN 600 /* min. capacity selectable */
-//#define BATTERY_CAPACITY_MAX 700 /* max. capacity selectable */
-//#define BATTERY_CAPACITY_INC 50 /* capacity increment */
-//#define BATTERY_TYPES_COUNT 1 /* only one type */
+#define BATTERY_CAPACITY_DEFAULT 600 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN 600 /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX 600 /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC 0 /* capacity increment */
+#define BATTERY_TYPES_COUNT 1 /* only one type */

/* TODO: We possibly can only watch linux charging */
//#define CONFIG_CHARGING CHARGING_TARGET
diff --git a/firmware/export/power.h b/firmware/export/power.h
index d46b9ba..4937705 100644
--- a/firmware/export/power.h
+++ b/firmware/export/power.h
@@ -23,6 +23,7 @@

#include "config.h"

+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
#if CONFIG_CHARGING
enum power_input_flags {
/* No external power source? Default. */
@@ -100,4 +101,6 @@ bool tuner_power(bool status);
bool tuner_powered(void);
#endif

+#endif
+
#endif /* _POWER_H_ */
diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h
index 808c858..11dd067 100644
--- a/firmware/export/powermgmt.h
+++ b/firmware/export/powermgmt.h
@@ -78,7 +78,7 @@ extern unsigned int power_thread_inputs;
/* Start up power management thread */
void powermgmt_init(void) INIT_ATTR;

-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)

/* Generic current values that are intentionally meaningless - config header
* should define proper numbers.*/
diff --git a/firmware/export/storage.h b/firmware/export/storage.h
index 58d8d32..6c875bc 100644
--- a/firmware/export/storage.h
+++ b/firmware/export/storage.h
@@ -71,7 +71,7 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }

#define storage_enable(on)
#define storage_sleepnow()
- #define storage_disk_is_active()
+ #define storage_disk_is_active() 0
#define storage_soft_reset()
#define storage_init()
#define storage_close()
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 76322d6..12f6b68 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -82,7 +82,7 @@ void handle_auto_poweroff(void);
static int poweroff_timeout = 0;
static long last_event_tick = 0;

-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0)
/*
* Average battery voltage and charger voltage, filtered via a digital
* exponential filter (aka. exponential moving average, scaled):
@@ -104,11 +104,7 @@ static int battery_type = 0;
/* Power history: power_history[0] is the newest sample */
unsigned short power_history[POWER_HISTORY_LEN] = {0};

-#if CONFIG_CPU == JZ4732 /* FIXME! */
static char power_stack[DEFAULT_STACK_SIZE + POWERMGMT_DEBUG_STACK];
-#else
-static char power_stack[DEFAULT_STACK_SIZE/2 + POWERMGMT_DEBUG_STACK];
-#endif
static const char power_thread_name[] = "power";

static int powermgmt_est_runningtime_min = -1;
diff --git a/firmware/target/hosted/ypr0/powermgmt-ypr0.c b/firmware/target/hosted/ypr0/powermgmt-ypr0.c
index 5701e9f..0cefd46 100644
--- a/firmware/target/hosted/ypr0/powermgmt-ypr0.c
+++ b/firmware/target/hosted/ypr0/powermgmt-ypr0.c
@@ -17,117 +17,71 @@
*
****************************************************************************/
#include "config.h"
-#include "system.h"
-#include <time.h>
+#include <sys/ioctl.h>
#include "kernel.h"
#include "powermgmt.h"
+#include "power.h"
+#include "file.h"
#include "ascodec-target.h"
-#include "stdio.h"
+#include "as3514.h"
+#include "sc900776.h"

-#if 0 /*still unused*/
-/* The battery manufacturer's website shows discharge curves down to 3.0V,
- so 'dangerous' and 'shutoff' levels of 3.4V and 3.3V should be safe.
- */
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
{
- 3550
+ 3500
};

+/* the OF shuts down at this voltage */
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
{
3450
};

/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+/* FIXME: This is guessed. Make proper curve using battery_bench */
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
{
- { 3300, 3692, 3740, 3772, 3798, 3828, 3876, 3943, 4013, 4094, 4194 }
+ { 3450, 3692, 3740, 3772, 3798, 3828, 3876, 3943, 4013, 4094, 4194 }
};

#if CONFIG_CHARGING
/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
-const unsigned short percent_to_volt_charge[11] =
+/* FIXME: This is guessed. Make proper curve using battery_bench */
+const unsigned short const percent_to_volt_charge[11] =
{
- 3417, 3802, 3856, 3888, 3905, 3931, 3973, 4025, 4084, 4161, 4219
+ 3600, 3802, 3856, 3888, 3905, 3931, 3973, 4025, 4084, 4161, 4219
};
-#endif /* CONFIG_CHARGING */
-#endif
-
-#define BATT_MINMVOLT 3450 /* minimum millivolts of battery */
-#define BATT_MAXMVOLT 4150 /* maximum millivolts of battery */
-#define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in
- minutes */
-
-extern void send_battery_level_event(void);
-extern int last_sent_battery_level;
-extern int battery_percent;
-
-static unsigned int battery_millivolts = BATT_MAXMVOLT;
-/* estimated remaining time in minutes */
-static int powermgmt_est_runningtime_min = BATT_MAXRUNTIME;

-static void battery_status_update(void)
+unsigned int power_input_status(void)
{
- static time_t last_change = 0;
- time_t now;
-
- time(&now);
-
- if (last_change < now) {
- last_change = now;
-
- battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) /
- (BATT_MAXMVOLT - BATT_MINMVOLT);
-
- powermgmt_est_runningtime_min =
- battery_percent * BATT_MAXRUNTIME / 100;
+ unsigned status = POWER_INPUT_NONE;
+ int fd = open("/dev/minivet", O_RDONLY);
+ if (fd >= 0)
+ {
+ if (ioctl(fd, IOCTL_MINIVET_DET_VBUS, NULL) > 0)
+ status = POWER_INPUT_MAIN_CHARGER;
+ close(fd);
}
-
- send_battery_level_event();
+ return status;
}

-void battery_read_info(int *voltage, int *level)
-{
- battery_status_update();
-
- if (voltage)
- *voltage = battery_millivolts;
-
- if (level)
- *level = battery_percent;
-}
-
-unsigned int battery_voltage(void)
-{
- battery_status_update();
- return battery_millivolts;
-}
-
-int battery_level(void)
-{
- battery_status_update();
- return battery_percent;
-}
-
-int battery_time(void)
-{
- battery_status_update();
- return powermgmt_est_runningtime_min;
-}
+#endif /* CONFIG_CHARGING */

-bool battery_level_safe(void)
-{
- return battery_level() >= 10;
-}

-void set_battery_capacity(int capacity)
+/* Returns battery voltage from ADC [millivolts] */
+unsigned int battery_adc_voltage(void)
{
- (void)capacity;
+ return adc_read(3) * 5;
}

-#if BATTERY_TYPES_COUNT > 1
-void set_battery_type(int type)
+bool charging_state(void)
{
- (void)type;
+ /* cannot make this static (initializer not constant error), but gcc
+ * seems to calculate at compile time anyway */
+ const unsigned short charged_thres =
+ ((percent_to_volt_charge[9] + percent_to_volt_charge[10]) / 2);
+
+ bool ret = (power_input_status() == POWER_INPUT_MAIN_CHARGER);
+ /* dont indicate for > ~95% */
+ return ret && (battery_adc_voltage() <= charged_thres);
}
-#endif
diff --git a/firmware/target/hosted/ypr0/system-ypr0.c b/firmware/target/hosted/ypr0/system-ypr0.c
index 3a2b303..bf3b1cd 100644
--- a/firmware/target/hosted/ypr0/system-ypr0.c
+++ b/firmware/target/hosted/ypr0/system-ypr0.c
@@ -32,16 +32,11 @@

#include "ascodec-target.h"

-void sim_do_exit(void)
-{
- exit(EXIT_SUCCESS);
-}
-
-void shutdown_hw(void)
+void power_off(void)
{
/* Something that we need to do before exit on our platform YPR0 */
ascodec_close();
- sim_do_exit();
+ exit(EXIT_SUCCESS);
}

uintptr_t *stackbegin;
@@ -62,7 +57,7 @@ void system_init(void)

void system_reboot(void)
{
- sim_do_exit();
+ power_off();
}

void system_exception_wait(void)