implemented low battery warning

thanks to eggs owl overlay examples and BlackSeraph's uImage mods
This commit is contained in:
Shaun Inman 2023-02-26 00:23:35 -05:00
parent bec0e5182c
commit c2c8f2d067
6 changed files with 256 additions and 42 deletions

View file

@ -25,6 +25,7 @@ int main(int argc , char* argv[]) {
POW_setCPUSpeed(CPU_SPEED_MENU); POW_setCPUSpeed(CPU_SPEED_MENU);
SDL_Surface* screen = GFX_init(MODE_MAIN); SDL_Surface* screen = GFX_init(MODE_MAIN);
POW_init();
InitSettings(); InitSettings();
// TODO: make use of SCALE1() // TODO: make use of SCALE1()
@ -304,6 +305,7 @@ int main(int argc , char* argv[]) {
SDL_FreeSurface(digits); SDL_FreeSurface(digits);
QuitSettings(); QuitSettings();
POW_quit();
GFX_quit(); GFX_quit();

View file

@ -12,6 +12,7 @@
#include <SDL/SDL_image.h> #include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h> #include <SDL/SDL_ttf.h>
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <msettings.h> #include <msettings.h>
#include "api.h" #include "api.h"
@ -85,6 +86,63 @@ struct owlfb_sync_info {
__u8 disp_id; __u8 disp_id;
__u16 reserved2; __u16 reserved2;
}; };
enum owlfb_overlay_type {
OWLFB_OVERLAY_VIDEO = 1,
OWLFB_OVERLAY_CURSOR,
};
enum owl_color_mode {
OWL_DSS_COLOR_RGB16 = 0,
OWL_DSS_COLOR_BGR16 = 1,
OWL_DSS_COLOR_ARGB32 = 4,
OWL_DSS_COLOR_ABGR32 = 5,
OWL_DSS_COLOR_RGBA32 = 6,
OWL_DSS_COLOR_BGRA32 = 7,
OWL_DSS_COLOR_NV21 = 8,
OWL_DSS_COLOR_NU21 = 9,
OWL_DSS_COLOR_YU12 = 10,
OWL_DSS_COLOR_ARGB16 = 12,
OWL_DSS_COLOR_ABGR16 = 13,
OWL_DSS_COLOR_RGBA16 = 14,
OWL_DSS_COLOR_BGRA16 = 15,
OWL_DSS_COLOR_RGB24U = 16,
OWL_DSS_COLOR_RGB24P = 17,
OWL_DSS_COLOR_RGBX32 = 18,
OWL_DSS_COLOR_NV12 = 19,
OWL_DSS_COLOR_XBGR32 = 20,
OWL_DSS_COLOR_XRGB32 = 21,
};
struct owlfb_overlay_args {
__u16 fb_id;
__u16 overlay_id;
__u16 overlay_type;
__u32 overlay_mem_base;
__u32 overlay_mem_size;
__u32 uintptr_overly_info;
};
struct owlfb_overlay_info {
__u32 mem_off;
__u32 mem_size;
__u32 screen_width;
enum owl_color_mode color_mode;
__u32 img_width;
__u32 img_height;
__u32 xoff;
__u32 yoff;
__u32 width;
__u32 height;
__u8 rotation;
__u32 pos_x;
__u32 pos_y;
__u32 out_width;
__u32 out_height;
__u8 lightness;
__u8 saturation;
__u8 contrast;
bool global_alpha_en;
__u8 global_alpha;
bool pre_mult_alpha_en;
__u8 zorder;
};
#define OWL_IOW(num, dtype) _IOW('O', num, dtype) #define OWL_IOW(num, dtype) _IOW('O', num, dtype)
#define OWL_IOR(num, dtype) _IOR('O', num, dtype) #define OWL_IOR(num, dtype) _IOR('O', num, dtype)
@ -92,6 +150,12 @@ struct owlfb_sync_info {
#define OWLFB_GET_DISPLAY_INFO OWL_IOW(74, struct owlfb_disp_device) #define OWLFB_GET_DISPLAY_INFO OWL_IOW(74, struct owlfb_disp_device)
#define OWLFB_SET_DISPLAY_INFO OWL_IOW(75, struct owlfb_disp_device) #define OWLFB_SET_DISPLAY_INFO OWL_IOW(75, struct owlfb_disp_device)
#define OWLFB_VSYNC_EVENT_EN OWL_IOW(67, struct owlfb_sync_info) #define OWLFB_VSYNC_EVENT_EN OWL_IOW(67, struct owlfb_sync_info)
#define OWLFB_OVERLAY_REQUEST OWL_IOR(41, struct owlfb_overlay_args)
#define OWLFB_OVERLAY_RELEASE OWL_IOR(42, struct owlfb_overlay_args)
#define OWLFB_OVERLAY_ENABLE OWL_IOR(43, struct owlfb_overlay_args)
#define OWLFB_OVERLAY_DISABLE OWL_IOR(45, struct owlfb_overlay_args)
#define OWLFB_OVERLAY_GETINFO OWL_IOW(46, struct owlfb_overlay_args)
#define OWLFB_OVERLAY_SETINFO OWL_IOW(47, struct owlfb_overlay_args)
/////////////////////////////// ///////////////////////////////
@ -109,7 +173,9 @@ static struct GFX_Context {
int mode; int mode;
int vsync; int vsync;
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
void* fb0_buffer; void* fb0_buffer;
SDL_Surface* screen; SDL_Surface* screen;
@ -148,6 +214,24 @@ GFX_Fonts font;
/////////////////////////////// ///////////////////////////////
static struct POW_Context {
int can_poweroff;
int previous_speed; // TODO: unused
int can_autosleep;
pthread_t battery_pt;
int is_charging;
int charge;
int should_warn;
struct owlfb_overlay_args oargs;
struct owlfb_overlay_info oinfo;
SDL_Surface* overlay;
} pow;
///////////////////////////////
static int _; static int _;
SDL_Surface* GFX_init(int mode) { SDL_Surface* GFX_init(int mode) {
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
@ -160,6 +244,7 @@ SDL_Surface* GFX_init(int mode) {
gfx.fb0_fd = open("/dev/fb0", O_RDWR); gfx.fb0_fd = open("/dev/fb0", O_RDWR);
ioctl(gfx.fb0_fd, FBIOGET_FSCREENINFO, &gfx.finfo);
ioctl(gfx.fb0_fd, FBIOGET_VSCREENINFO, &gfx.vinfo); ioctl(gfx.fb0_fd, FBIOGET_VSCREENINFO, &gfx.vinfo);
gfx.vinfo.bits_per_pixel = FIXED_DEPTH; gfx.vinfo.bits_per_pixel = FIXED_DEPTH;
gfx.vinfo.xres = FIXED_WIDTH; gfx.vinfo.xres = FIXED_WIDTH;
@ -187,7 +272,7 @@ SDL_Surface* GFX_init(int mode) {
if (ioctl(gfx.fb0_fd, OWLFB_VSYNC_EVENT_EN, &sinfo)) LOG_info("OWLFB_VSYNC_EVENT_EN failed %s\n", strerror(errno)); if (ioctl(gfx.fb0_fd, OWLFB_VSYNC_EVENT_EN, &sinfo)) LOG_info("OWLFB_VSYNC_EVENT_EN failed %s\n", strerror(errno));
gfx.page = 1; // start on the backbuffer gfx.page = 1; // start on the backbuffer
gfx.fb0_buffer = mmap(0, VIRTUAL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, gfx.fb0_fd, 0); gfx.fb0_buffer = mmap(0, gfx.finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, gfx.fb0_fd, 0);
memset(gfx.fb0_buffer, 0, VIRTUAL_SIZE); // clear both buffers memset(gfx.fb0_buffer, 0, VIRTUAL_SIZE); // clear both buffers
gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), FIXED_WIDTH,FIXED_HEIGHT, FIXED_DEPTH,FIXED_PITCH, 0,0,0,0); gfx.screen = SDL_CreateRGBSurfaceFrom(gfx.fb0_buffer + (gfx.page * PAGE_SIZE), FIXED_WIDTH,FIXED_HEIGHT, FIXED_DEPTH,FIXED_PITCH, 0,0,0,0);
@ -299,11 +384,13 @@ SDL_Surface* GFX_resize(int w, int h, int pitch) {
return gfx.screen; return gfx.screen;
} }
static void POW_flipOverlay(void);
void GFX_flip(SDL_Surface* screen) { void GFX_flip(SDL_Surface* screen) {
// point framebuffer at the first line of the backbuffer // point framebuffer at the first line of the backbuffer
gfx.vinfo.yoffset = gfx.page * PAGE_HEIGHT; gfx.vinfo.yoffset = gfx.page * PAGE_HEIGHT;
if (ioctl(gfx.fb0_fd, gfx.resized ? FBIOPUT_VSCREENINFO : FBIOPAN_DISPLAY, &gfx.vinfo)) LOG_info("%s failed %s\n", (gfx.resized ? "FBIOPUT_VSCREENINFO" : "FBIOPAN_DISPLAY"), strerror(errno)); if (ioctl(gfx.fb0_fd, gfx.resized ? FBIOPUT_VSCREENINFO : FBIOPAN_DISPLAY, &gfx.vinfo)) LOG_info("%s failed %s\n", (gfx.resized ? "FBIOPUT_VSCREENINFO" : "FBIOPAN_DISPLAY"), strerror(errno));
gfx.resized = 0; gfx.resized = 0;
POW_flipOverlay(); // TODO: tmp?
if (gfx.vsync!=VSYNC_OFF) { if (gfx.vsync!=VSYNC_OFF) {
// this limiting condition helps SuperFX chip games // this limiting condition helps SuperFX chip games
@ -312,6 +399,7 @@ void GFX_flip(SDL_Surface* screen) {
} }
} }
// swap backbuffer // swap backbuffer
gfx.page += 1; gfx.page += 1;
if (gfx.page>=PAGE_COUNT) gfx.page -= PAGE_COUNT; if (gfx.page>=PAGE_COUNT) gfx.page -= PAGE_COUNT;
@ -467,18 +555,22 @@ void GFX_blitRect(int asset, SDL_Surface* dst, SDL_Rect* dst_rect) {
GFX_blitAsset(asset, &(SDL_Rect){r,r,r,r}, dst, &(SDL_Rect){x+w-r,y+h-r}); GFX_blitAsset(asset, &(SDL_Rect){r,r,r,r}, dst, &(SDL_Rect){x+w-r,y+h-r});
} }
void GFX_blitBattery(SDL_Surface* dst, SDL_Rect* dst_rect) { void GFX_blitBattery(SDL_Surface* dst, SDL_Rect* dst_rect) {
// LOG_info("dst: %p\n", dst);
if (!dst_rect) dst_rect = &(SDL_Rect){0,0,0,0};
SDL_Rect rect = asset_rects[ASSET_BATTERY]; SDL_Rect rect = asset_rects[ASSET_BATTERY];
int x = dst_rect->x; int x = dst_rect->x;
int y = dst_rect->y; int y = dst_rect->y;
x += (SCALE1(PILL_SIZE) - (rect.w + SCREEN_SCALE)) / 2; x += (SCALE1(PILL_SIZE) - (rect.w + SCREEN_SCALE)) / 2;
y += (SCALE1(PILL_SIZE) - rect.h) / 2; y += (SCALE1(PILL_SIZE) - rect.h) / 2;
if (POW_isCharging()) { if (pow.is_charging) {
GFX_blitAsset(ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y}); GFX_blitAsset(ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y});
GFX_blitAsset(ASSET_BATTERY_BOLT, NULL, dst, &(SDL_Rect){x+SCALE1(3),y+SCALE1(2)}); GFX_blitAsset(ASSET_BATTERY_BOLT, NULL, dst, &(SDL_Rect){x+SCALE1(3),y+SCALE1(2)});
} }
else { else {
int percent = POW_getBattery(); int percent = pow.charge;
GFX_blitAsset(percent<=10?ASSET_BATTERY_LOW:ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y}); GFX_blitAsset(percent<=10?ASSET_BATTERY_LOW:ASSET_BATTERY, NULL, dst, &(SDL_Rect){x,y});
rect = asset_rects[ASSET_BATTERY_FILL]; rect = asset_rects[ASSET_BATTERY_FILL];
@ -1091,7 +1183,129 @@ int VIB_getStrength(void) {
/////////////////////////////// ///////////////////////////////
// TODO: separate settings/battery and power management? #define OVERLAY_WIDTH PILL_SIZE // unscaled
#define OVERLAY_HEIGHT PILL_SIZE // unscaled
#define OVERLAY_BPP 4
#define OVERLAY_DEPTH 32
#define OVERLAY_PITCH (OVERLAY_WIDTH * OVERLAY_BPP) // unscaled
#define OVERLAY_RGBA_MASK 0x00ff0000,0x0000ff00,0x000000ff,0xff000000
#define POW_LOW_CHARGE 10
static void POW_initOverlay(void) {
// setup surface
pow.overlay = SDL_CreateRGBSurfaceFrom(NULL,SCALE2(OVERLAY_WIDTH,OVERLAY_HEIGHT),OVERLAY_DEPTH,SCALE1(OVERLAY_PITCH), OVERLAY_RGBA_MASK);
uint32_t size = pow.overlay->h * pow.overlay->pitch;
uint32_t offset = (gfx.finfo.smem_len - size)&(~4095);
pow.overlay->pixels = gfx.fb0_buffer + offset;
// draw battery
SDL_SetAlpha(gfx.assets, 0,0);
GFX_blitAsset(ASSET_BLACK_PILL, NULL, pow.overlay, NULL);
SDL_SetAlpha(gfx.assets, SDL_SRCALPHA,0);
GFX_blitBattery(pow.overlay, NULL);
// SDL_Rect rect = asset_rects[ASSET_BATTERY];
// int ox = (SCALE1(PILL_SIZE) - (rect.w + SCREEN_SCALE)) / 2;
// int oy = (SCALE1(PILL_SIZE) - rect.h) / 2;
// GFX_blitAsset(ASSET_BATTERY_LOW, NULL, pow.overlay, &(SDL_Rect){ox,oy});
// setup overlay
memset(&pow.oargs, 0, sizeof(struct owlfb_overlay_args));
pow.oargs.fb_id = 0;
pow.oargs.overlay_id = 1;
pow.oargs.overlay_type = OWLFB_OVERLAY_VIDEO;
pow.oargs.uintptr_overly_info = (uintptr_t)&pow.oinfo;
int x,y,w,h;
w = h = pow.overlay->w;
x = FIXED_WIDTH - SCALE1(PADDING) - w;
y = SCALE1(PADDING);
pow.oinfo.mem_off = offset;
pow.oinfo.mem_size = size;
pow.oinfo.screen_width = VIRTUAL_WIDTH; // ???
pow.oinfo.color_mode = OWL_DSS_COLOR_ARGB32;
pow.oinfo.img_width = w;
pow.oinfo.img_height = h;
pow.oinfo.xoff = 0;
pow.oinfo.yoff = 0;
pow.oinfo.width = w;
pow.oinfo.height = h;
pow.oinfo.rotation = 0;
pow.oinfo.pos_x = x; // position
pow.oinfo.pos_y = y; //
pow.oinfo.out_width = w; // scaled size
pow.oinfo.out_height = h; //
pow.oinfo.global_alpha_en = 0;
pow.oinfo.global_alpha = 0;
pow.oinfo.pre_mult_alpha_en = 0;
pow.oinfo.zorder = 3;
}
static void POW_flipOverlay(void) {
if (pow.should_warn && pow.charge<=POW_LOW_CHARGE) ioctl(gfx.fb0_fd, OWLFB_OVERLAY_SETINFO, &pow.oargs);
}
static void POW_quitOverlay(void) {
if (pow.overlay) SDL_FreeSurface(pow.overlay);
memset(&pow.oargs, 0, sizeof(struct owlfb_overlay_args));
pow.oargs.fb_id = 0;
pow.oargs.overlay_id = 1;
pow.oargs.overlay_type = OWLFB_OVERLAY_VIDEO;
pow.oargs.uintptr_overly_info = 0;
ioctl(gfx.fb0_fd, OWLFB_OVERLAY_DISABLE, &pow.oargs);
}
static void POW_updateBatteryStatus(void) {
pow.is_charging = getInt("/sys/class/power_supply/battery/charger_online");
int i = getInt("/sys/class/power_supply/battery/voltage_now") / 10000; // 310-410
i -= 310; // ~0-100
// worry less about battery and more about the game you're playing
if (i>80) pow.charge = 100;
else if (i>60) pow.charge = 80;
else if (i>40) pow.charge = 60;
else if (i>20) pow.charge = 40;
else if (i>10) pow.charge = 20;
else pow.charge = 10;
// LOG_info("battery charge: %i (%i) charging: %i\n", pow.charge, i, pow.is_charging);
pow.charge = POW_LOW_CHARGE;
}
static void* POW_monitorBattery(void *arg) {
while(1) {
// TODO: the frequency of checking should depend on whether
// we're in game (less frequent) or menu (more frequent)
sleep(1);
POW_updateBatteryStatus();
}
return NULL;
}
void POW_init(void) {
pow.can_poweroff = 1;
pow.previous_speed = CPU_SPEED_NORMAL;
pow.can_autosleep = 1;
pow.should_warn = 0;
pow.charge = POW_LOW_CHARGE;
POW_initOverlay();
POW_updateBatteryStatus();
pthread_create(&pow.battery_pt, NULL, &POW_monitorBattery, NULL);
}
void POW_quit(void) {
POW_quitOverlay();
// cancel battery thread
pthread_cancel(pow.battery_pt);
pthread_join(pow.battery_pt, NULL);
}
void POW_warn(int enable) {
pow.should_warn = enable;
}
void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep) { void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep) {
int dirty = _dirty ? *_dirty : 0; int dirty = _dirty ? *_dirty : 0;
int show_setting = _show_setting ? *_show_setting : 0; int show_setting = _show_setting ? *_show_setting : 0;
@ -1103,7 +1317,7 @@ void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, PO
static uint32_t setting_start = 0; static uint32_t setting_start = 0;
static uint32_t charge_start = 0; static uint32_t charge_start = 0;
static int was_charging = -1; static int was_charging = -1;
if (was_charging==-1) was_charging = POW_isCharging(); if (was_charging==-1) was_charging = pow.is_charging;
uint32_t now = SDL_GetTicks(); uint32_t now = SDL_GetTicks();
if (cancel_start==0) cancel_start = now; if (cancel_start==0) cancel_start = now;
@ -1113,7 +1327,7 @@ void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, PO
#define CHARGE_DELAY 1000 #define CHARGE_DELAY 1000
if (dirty || now-charge_start>=CHARGE_DELAY) { if (dirty || now-charge_start>=CHARGE_DELAY) {
int is_charging = POW_isCharging(); int is_charging = pow.is_charging;
if (was_charging!=is_charging) { if (was_charging!=is_charging) {
was_charging = is_charging; was_charging = is_charging;
dirty = 1; dirty = 1;
@ -1170,12 +1384,11 @@ void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, PO
if (_show_setting) *_show_setting = show_setting; if (_show_setting) *_show_setting = show_setting;
} }
static int can_poweroff = 1;
void POW_disablePowerOff(void) { void POW_disablePowerOff(void) {
can_poweroff = 0; pow.can_poweroff = 0;
} }
void POW_powerOff(void) { void POW_powerOff(void) {
if (can_poweroff) { if (pow.can_poweroff) {
char* msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npowering off" : "Powering off"; char* msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npowering off" : "Powering off";
GFX_clear(gfx.screen); GFX_clear(gfx.screen);
GFX_blitMessage(msg, gfx.screen, NULL); GFX_blitMessage(msg, gfx.screen, NULL);
@ -1192,7 +1405,6 @@ void POW_powerOff(void) {
#define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power" #define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power"
#define CPU_SPEED_SET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed" #define CPU_SPEED_SET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
#define CPU_SPEED_GET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" #define CPU_SPEED_GET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
static int previous_speed = CPU_SPEED_NORMAL;
void POW_setCPUSpeed(int speed) { void POW_setCPUSpeed(int speed) {
putInt(CPU_SPEED_SET_PATH, speed); putInt(CPU_SPEED_SET_PATH, speed);
@ -1202,19 +1414,21 @@ void POW_setCPUSpeed(int speed) {
static void POW_enterSleep(void) { static void POW_enterSleep(void) {
SetRawVolume(0); SetRawVolume(0);
putInt(BACKLIGHT_PATH, FB_BLANK_POWERDOWN); putInt(BACKLIGHT_PATH, FB_BLANK_POWERDOWN);
system("killall -STOP keymon.elf");
// TODO: not sure this is necessary // TODO: not sure this is necessary
// previous_speed = getInt(CPU_SPEED_GET_PATH); // pow.previous_speed = getInt(CPU_SPEED_GET_PATH);
// POW_setCPUSpeed(CPU_SPEED_MENU); // POW_setCPUSpeed(CPU_SPEED_MENU);
sync(); sync();
} }
static void POW_exitSleep(void) { static void POW_exitSleep(void) {
system("killall -CONT keymon.elf");
putInt(BACKLIGHT_PATH, FB_BLANK_UNBLANK); putInt(BACKLIGHT_PATH, FB_BLANK_UNBLANK);
SetVolume(GetVolume()); SetVolume(GetVolume());
// TODO: not sure this is necessary // TODO: not sure this is necessary
// POW_setCPUSpeed(previous_speed); // POW_setCPUSpeed(pow.previous_speed);
sync(); sync();
} }
@ -1233,8 +1447,8 @@ static void POW_waitForWake(void) {
} }
} }
SDL_Delay(200); SDL_Delay(200);
if (can_poweroff && SDL_GetTicks()-sleep_ticks>=120000) { // increased to two minutes if (pow.can_poweroff && SDL_GetTicks()-sleep_ticks>=120000) { // increased to two minutes
if (POW_isCharging()) sleep_ticks += 60000; // check again in a minute if (pow.is_charging) sleep_ticks += 60000; // check again in a minute
else POW_powerOff(); // TODO: not working... else POW_powerOff(); // TODO: not working...
} }
} }
@ -1244,34 +1458,24 @@ void POW_fauxSleep(void) {
GFX_clear(gfx.screen); GFX_clear(gfx.screen);
PAD_reset(); PAD_reset();
POW_enterSleep(); POW_enterSleep();
system("killall -STOP keymon.elf");
POW_waitForWake(); POW_waitForWake();
system("killall -CONT keymon.elf");
POW_exitSleep(); POW_exitSleep();
} }
static int can_autosleep = 1;
void POW_disableAutosleep(void) { void POW_disableAutosleep(void) {
can_autosleep = 0; pow.can_autosleep = 0;
} }
void POW_enableAutosleep(void) { void POW_enableAutosleep(void) {
can_autosleep = 1; pow.can_autosleep = 1;
} }
int POW_preventAutosleep(void) { int POW_preventAutosleep(void) {
return POW_isCharging() || !can_autosleep; return pow.is_charging || !pow.can_autosleep;
} }
// updated by POW_updateBatteryStatus()
int POW_isCharging(void) { int POW_isCharging(void) {
return getInt("/sys/class/power_supply/battery/charger_online"); return pow.is_charging;
} }
int POW_getBattery(void) { // 10-100 in 10-20% fragments int POW_getBattery(void) { // 10-100 in 10-20% fragments
int i = getInt("/sys/class/power_supply/battery/voltage_now") / 10000; // 310-410 return pow.charge;
i -= 310; // ~0-100
// worry less about battery and more about the game you're playing
if (i>80) return 100;
if (i>60) return 80;
if (i>40) return 60;
if (i>20) return 40;
if (i>10) return 20;
else return 10;
} }

View file

@ -209,20 +209,26 @@ void VIB_setStrength(int strength);
/////////////////////////////// ///////////////////////////////
// TODO: rename PLAT_*? #define BRIGHTNESS_BUTTON_LABEL "+ -" // ew
#define BRIGHTNESS_BUTTON_LABEL "+ -"
typedef void (*POW_callback_t)(void); typedef void (*POW_callback_t)(void);
void POW_init(void);
void POW_quit(void);
void POW_warn(int enable);
void POW_update(int* dirty, int* show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep); void POW_update(int* dirty, int* show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep);
void POW_disablePowerOff(void); void POW_disablePowerOff(void);
void POW_powerOff(void); void POW_powerOff(void);
void POW_fauxSleep(void); void POW_fauxSleep(void);
void POW_disableAutosleep(void); void POW_disableAutosleep(void);
void POW_enableAutosleep(void); void POW_enableAutosleep(void);
int POW_preventAutosleep(void); int POW_preventAutosleep(void);
int POW_isCharging(void); int POW_isCharging(void);
int POW_getBattery(void); int POW_getBattery(void);
#define CPU_SPEED_MENU 504000 // 240000 was having latency issues #define CPU_SPEED_MENU 504000 // 240000 had latency issues
#define CPU_SPEED_POWERSAVE 1104000 #define CPU_SPEED_POWERSAVE 1104000
#define CPU_SPEED_NORMAL 1296000 #define CPU_SPEED_NORMAL 1296000
#define CPU_SPEED_PERFORMANCE 1488000 #define CPU_SPEED_PERFORMANCE 1488000

View file

@ -3480,6 +3480,7 @@ static void Menu_loop(void) {
screen = GFX_resize(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_PITCH); screen = GFX_resize(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_PITCH);
} }
POW_warn(0);
POW_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly POW_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly
GFX_setVsync(VSYNC_STRICT); GFX_setVsync(VSYNC_STRICT);
@ -3852,6 +3853,7 @@ static void Menu_loop(void) {
SDL_FreeSurface(backing); SDL_FreeSurface(backing);
SDL_FreeSurface(resized); SDL_FreeSurface(resized);
POW_disableAutosleep(); POW_disableAutosleep();
POW_warn(1);
} }
// TODO: move to POW_*? // TODO: move to POW_*?
@ -3938,6 +3940,7 @@ int main(int argc , char* argv[]) {
screen = GFX_init(MODE_MENU); screen = GFX_init(MODE_MENU);
VIB_init(); VIB_init();
POW_init();
MSG_init(); MSG_init();
InitSettings(); InitSettings();
@ -3964,6 +3967,7 @@ int main(int argc , char* argv[]) {
State_resume(); State_resume();
POW_warn(1);
POW_disableAutosleep(); POW_disableAutosleep();
sec_start = SDL_GetTicks(); sec_start = SDL_GetTicks();
while (!quit) { while (!quit) {
@ -3989,6 +3993,7 @@ int main(int argc , char* argv[]) {
SDL_FreeSurface(screen); SDL_FreeSurface(screen);
MSG_quit(); MSG_quit();
QuitSettings(); QuitSettings();
POW_quit();
VIB_quit(); VIB_quit();
GFX_quit(); GFX_quit();

View file

@ -1167,6 +1167,7 @@ int main (int argc, char *argv[]) {
LOG_info("MinUI\n"); LOG_info("MinUI\n");
SDL_Surface* screen = GFX_init(MODE_MAIN); SDL_Surface* screen = GFX_init(MODE_MAIN);
POW_init();
InitSettings(); InitSettings();
PAD_reset(); PAD_reset();
@ -1487,6 +1488,7 @@ int main (int argc, char *argv[]) {
SDL_FreeSurface(screen); SDL_FreeSurface(screen);
Menu_quit(); Menu_quit();
POW_quit();
GFX_quit(); GFX_quit();
QuitSettings(); QuitSettings();
} }

View file

@ -20,11 +20,6 @@ minarch
minui minui
- -
common
move battery check to thread?
add low-bat icon to owlfb overlay?
https://discord.com/channels/741895796315914271/1063158507366535249/1077626268645863495
misc misc
port say, show, blank, and confirm port say, show, blank, and confirm
make my own simple file browser? :sweat_smile: make my own simple file browser? :sweat_smile: