A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1261 lines 36 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese 11 * Revisions copyright (C) 2005 by Gerald Van Baren 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 <stdio.h> 23#include <ctype.h> 24#include "config.h" 25#include "system.h" 26#include "kernel.h" 27#include "thread.h" 28#include "debug.h" 29#include "adc.h" 30#include "string.h" 31#include "storage.h" 32#include "power.h" 33#include "audio.h" 34#include "usb.h" 35#include "powermgmt.h" 36#include "backlight.h" 37#include "lcd.h" 38#include "rtc.h" 39#if CONFIG_TUNER 40#include "fmradio.h" 41#endif 42#include "sound.h" 43#include "font.h" 44#include "logf.h" 45#ifdef HAVE_REMOTE_LCD 46#include "lcd-remote.h" 47#endif 48#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 49#include <time.h> 50#endif 51 52#if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) \ 53 && !defined (SIMULATOR) 54#include "pcf50606.h" 55#endif 56 57#if (BATTERY_CAPACITY_DEFAULT > 0) 58extern unsigned short power_history[POWER_HISTORY_LEN]; 59extern unsigned short battery_level_disksafe; 60extern unsigned short battery_level_shutoff; 61extern unsigned short percent_to_volt_discharge[11]; 62#endif 63#if CONFIG_CHARGING 64extern unsigned short percent_to_volt_charge[11]; 65#endif 66 67#ifndef BOOTLOADER 68#include "misc.h" 69#include "splash.h" 70 71struct battery_tables_t device_battery_tables = 72{ 73#if (BATTERY_CAPACITY_DEFAULT > 0) 74 .history = power_history, 75 .disksafe = &battery_level_disksafe, 76 .shutoff = &battery_level_shutoff, 77 .discharge = percent_to_volt_discharge, 78#if CONFIG_CHARGING 79 .charge = percent_to_volt_charge, 80#endif 81 .elems = ARRAYLEN(percent_to_volt_discharge), 82#endif 83 .isdefault = true, 84}; 85#endif 86 87static int last_sent_battery_level = 100; 88static void set_sleep_timer(int seconds); 89 90static bool sleeptimer_active = false; 91static long sleeptimer_endtick; 92/* Whether an active sleep timer should be restarted when a key is pressed */ 93static bool sleeptimer_key_restarts = false; 94/* The number of seconds the sleep timer was last set to */ 95static unsigned int sleeptimer_duration = 0; 96 97#if CONFIG_CHARGING 98/* State of the charger input as seen by the power thread */ 99enum charger_input_state_type charger_input_state; 100/* Power inputs as seen by the power thread */ 101unsigned int power_thread_inputs; 102#if CONFIG_CHARGING >= CHARGING_MONITOR 103/* Charging state (mode) as seen by the power thread */ 104enum charge_state_type charge_state = DISCHARGING; 105#endif 106#endif /* CONFIG_CHARGING */ 107 108static int shutdown_timeout = 0; 109 110void handle_auto_poweroff(void); 111static int poweroff_timeout = 0; 112static long last_event_tick = 0; 113 114#if BATTERY_CAPACITY_INC > 0 115static int battery_capacity = BATTERY_CAPACITY_DEFAULT; 116#else 117# define battery_capacity BATTERY_CAPACITY_DEFAULT 118#endif 119 120/* Power history: power_history[0] is the newest sample */ 121unsigned short power_history[POWER_HISTORY_LEN] = {0}; 122 123#if (CONFIG_CPU == JZ4732) || (CONFIG_CPU == JZ4760B) || \ 124 (CONFIG_CPU == X1000) || (CONFIG_PLATFORM & PLATFORM_HOSTED) 125static long power_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 126#else 127static long power_stack[DEFAULT_STACK_SIZE/2/sizeof(long)]; 128#endif 129static const char power_thread_name[] = "power"; 130 131/* Time estimation requires 64 bit math so don't use it in the bootloader. 132 * Also we need to be able to measure current, and not have a better time 133 * estimate source available. */ 134#if (!defined(BOOTLOADER) && !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) && \ 135 (defined(CURRENT_NORMAL) || (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE))) 136#define HAVE_TIME_ESTIMATION 137#endif 138 139#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) 140int _battery_level(void) { return -1; } 141#endif 142static int percent_now; /* Cached to avoid polling too often */ 143 144#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) 145int _battery_time(void) { return -1; } 146#else 147static int time_now; /* Cached to avoid polling too often */ 148#endif 149 150#ifdef HAVE_TIME_ESTIMATION 151static int time_now; /* reported time in minutes */ 152static int64_t time_cnt; /* reported time in seconds */ 153static int64_t time_err; /* error... it's complicated */ 154#endif 155 156#if !(CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) 157int _battery_voltage(void) { return -1; } 158#else 159/* Data for the digital exponential filter */ 160static int voltage_avg, voltage_now; 161#endif 162 163#if !(CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) 164int _battery_current(void) { return -1; } 165#else 166static int current_avg, current_now; 167#endif 168 169/* The battery level can be obtained in two ways. If the target reports 170 * voltage, the battery level can be estminated using percent_to_volt_* 171 * curves. If the target can report the percentage directly, then that 172 * will be used instead of voltage-based estimation. */ 173int battery_level(void) 174{ 175#ifdef HAVE_BATTERY_SWITCH 176 if ((power_input_status() & POWER_INPUT_BATTERY) == 0) 177 return -1; 178#endif 179 180 return percent_now; 181} 182 183/* The time remaining to full charge/discharge can be provided by the 184 * target if it has an accurate way of doing this. Otherwise, if the 185 * target defines a valid battery capacity and can report the charging 186 * and discharging current, the time remaining will be estimated based 187 * on the battery level and the actual current usage. */ 188int battery_time(void) 189{ 190#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(HAVE_TIME_ESTIMATION) 191 return time_now; 192#else 193 return -1; 194#endif 195} 196 197/* Battery voltage should always be reported if available, but it is 198 * optional if the the target reports battery percentage directly. */ 199int battery_voltage(void) 200{ 201#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 202 return voltage_now; 203#else 204 return -1; 205#endif 206} 207 208/* Battery current can be estimated if the target defines CURRENT_NORMAL 209 * as the number of milliamps usually consumed by the device in a normal 210 * state. The target can also define other CURRENT_* values to estimate 211 * the power consumed by the backlight, remote display, SPDIF, etc. */ 212int battery_current(void) 213{ 214#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 215 return current_now; 216#elif defined(CURRENT_NORMAL) 217 int current = CURRENT_NORMAL; 218 219#ifndef BOOTLOADER 220#if defined(HAVE_BACKLIGHT) && defined(CURRENT_BACKLIGHT) 221 if (backlight_get_current_timeout() == 0) /* LED always on */ 222 current += CURRENT_BACKLIGHT; 223#endif 224 225#if defined(HAVE_RECORDING) && defined(CURRENT_RECORD) 226 if (audio_status() & AUDIO_STATUS_RECORD) 227 current += CURRENT_RECORD; 228#endif 229 230#if defined(HAVE_SPDIF_POWER) && defined(CURRENT_SPDIF_OUT) 231 if (spdif_powered()) 232 current += CURRENT_SPDIF_OUT; 233#endif 234 235#if defined(HAVE_REMOTE_LCD) && defined(CURRENT_REMOTE) 236 if (remote_detect()) 237 current += CURRENT_REMOTE; 238#endif 239 240#if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA) 241 if (ide_powered()) 242 current += CURRENT_ATA; 243#endif 244 245#if CONFIG_CHARGING >= CHARGING_MONITOR 246 /* While charging we must report the charging current. */ 247 if (charging_state()) { 248 current = CURRENT_MAX_CHG - current; 249 current = MIN(current, 1); 250 } 251#endif 252 253#endif /* BOOTLOADER */ 254 255 return current; 256#else 257 return -1; 258#endif 259} 260 261/* Initialize the battery voltage/current filters. This is called 262 * once by the power thread before entering the main polling loop. */ 263static void average_init(void) 264{ 265#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 266 voltage_now = _battery_voltage() + 15; 267 268 /* The battery voltage is usually a little lower directly after 269 turning on, because the disk was used heavily. Raise it by 5% */ 270#ifdef HAVE_DISK_STORAGE 271#if CONFIG_CHARGING 272 if(!charger_inserted()) 273#endif 274 { 275 voltage_now += (percent_to_volt_discharge[6] - 276 percent_to_volt_discharge[5]) / 2; 277 } 278#endif /* HAVE_DISK_STORAGE */ 279 280 voltage_avg = voltage_now * BATT_AVE_SAMPLES; 281#endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */ 282 283#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 284 current_now = _battery_current(); 285 current_avg = current_now * BATT_CURRENT_AVE_SAMPLES; 286#endif 287} 288 289/* Sample the battery voltage/current and update the filters. 290 * Updated once every POWER_THREAD_STEP_TICKS. */ 291static void average_step(bool low_battery) 292{ 293#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 294 int millivolts = _battery_voltage(); 295 if(low_battery) { 296 voltage_now = (millivolts + voltage_now + 1) / 2; 297 voltage_avg += voltage_now - voltage_avg / BATT_AVE_SAMPLES; 298 } else { 299 voltage_avg += millivolts - voltage_avg / BATT_AVE_SAMPLES; 300 voltage_now = voltage_avg / BATT_AVE_SAMPLES; 301 } 302#else 303 (void)low_battery; 304#endif 305 306#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 307 current_avg += _battery_current() - current_avg / BATT_CURRENT_AVE_SAMPLES; 308 current_now = current_avg / BATT_CURRENT_AVE_SAMPLES; 309#endif 310} 311 312/* Send system battery level update events on reaching certain significant 313 * levels. This is called by battery_status_update() and does not have to 314 * be called separately. */ 315static void send_battery_level_event(int percent) 316{ 317 static const int levels[] = { 5, 15, 30, 50, 0 }; 318 const int *level = levels; 319 320 while (*level) 321 { 322 if (percent <= *level && last_sent_battery_level > *level) { 323 last_sent_battery_level = *level; 324 queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level); 325 break; 326 } 327 328 level++; 329 } 330} 331 332#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 333/* Look into the percent_to_volt_* table and estimate the battery level. */ 334static int voltage_to_percent(int voltage, const short* table) 335{ 336 if (voltage <= table[0]) { 337 return 0; 338 } 339 else if (voltage >= table[10]) { 340 return 100; 341 } 342 else { 343 /* search nearest value */ 344 int i = 0; 345 346 while (i < 10 && table[i+1] < voltage) 347 i++; 348 349 /* interpolate linear between the smaller and greater value */ 350 /* Tens digit, 10% per entry, ones digit: interpolated */ 351 return i*10 + (voltage - table[i])*10 / (table[i+1] - table[i]); 352 } 353} 354 355/* Convert voltage to a battery level percentage using the appropriate 356 * percent_to_volt_* lookup table. */ 357static int voltage_to_battery_level(int millivolts) 358{ 359 int level; 360 361 if (millivolts < 0) 362 return -1; 363 364#if CONFIG_CHARGING >= CHARGING_MONITOR 365 if (charging_state()) { 366 /* battery level is defined to be < 100% until charging is finished */ 367 level = voltage_to_percent(millivolts, percent_to_volt_charge); 368 if (level > 99) 369 level = 99; 370 } 371 else 372#endif /* CONFIG_CHARGING >= CHARGING_MONITOR */ 373 { 374 /* DISCHARGING or error state */ 375 level = voltage_to_percent(millivolts, percent_to_volt_discharge); 376 } 377 378 return level; 379} 380#endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */ 381 382/* Update battery percentage and time remaining information. 383 * 384 * This will be called by the power thread after polling new battery data. 385 * It must also be called if the battery type or capacity changes. 386 */ 387static void battery_status_update(void) 388{ 389#if ((CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)) 390 int level = _battery_level(); 391 if (level == -1) { 392 level = voltage_to_battery_level(voltage_now); 393 } 394#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE 395 int level = _battery_level(); 396#elif CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 397 int level = voltage_to_battery_level(voltage_now); 398#else 399 /* This should be a compile time error? */ 400 int level = -1; 401#endif 402 403#if CONFIG_BATTERY_MEASURE & TIME_MEASURE 404 time_now = _battery_time(); 405#elif defined(HAVE_TIME_ESTIMATION) 406 /* TODO: This is essentially a bad version of coloumb counting, 407 * so in theory using coloumb counters when they are available 408 * should provide a more accurate result. Also note that this 409 * is hard-coded with a HZ/2 update rate to simplify arithmetic. */ 410 411 int current = battery_current(); 412 int resolution = battery_capacity * 36; 413 414 int time_est = 0; 415 if(level >= 0 && current > 0) { 416#if CONFIG_CHARGING >= CHARGING_MONITOR 417 if (charging_state()) 418 time_est = (100 - level) * battery_capacity * 36 / current; 419 else 420#endif 421 time_est = level * battery_capacity * 36 / current; 422 423 /* The first term nudges the counter toward the estimate. */ 424 time_err += current * (time_est - time_cnt); 425 } 426 427 /* The second term decrements the counter due to elapsed time. */ 428 time_err -= resolution; 429 430 /* Arbitrary cutoff to ensure we don't get too far out 431 * of sync. Seems to work well on synthetic tests. */ 432 if(time_err > resolution * 12 || 433 time_err < -resolution * 13) { 434 time_cnt = time_est; 435 time_err = 0; 436 } 437 438 if(resolution > 0) { 439 /* Convert the error into a time and adjust the counter. */ 440 int64_t adjustment = time_err / (2 * resolution); 441 time_cnt += adjustment; 442 time_err -= adjustment * (2 * resolution); 443 } 444 445 /* Update the reported time based on the counter. */ 446 time_now = (time_cnt + 30) / 60; 447 if(time_now < 0) 448 time_now = 0; 449#endif 450 451 percent_now = level; 452 send_battery_level_event(level); 453} 454 455void battery_read_info(int *voltage, int *level) 456{ 457 int millivolts = _battery_voltage(); 458 459 if (voltage) 460 *voltage = millivolts; 461 462 if (level) { 463#if ((CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)) 464 *level = _battery_level(); 465 if (*level == -1) { 466 *level = voltage_to_battery_level(millivolts); 467 } 468#elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) 469 *level = _battery_level(); 470#elif (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) 471 *level = voltage_to_battery_level(millivolts); 472#else 473 *level = -1; 474#endif 475 } 476} 477 478#if BATTERY_CAPACITY_INC > 0 479void set_battery_capacity(int capacity) 480{ 481 if (capacity > BATTERY_CAPACITY_MAX) 482 capacity = BATTERY_CAPACITY_MAX; 483 if (capacity < BATTERY_CAPACITY_MIN) 484 capacity = BATTERY_CAPACITY_MIN; 485 486 if (capacity != battery_capacity) { 487 battery_capacity = capacity; 488 battery_status_update(); /* recalculate the battery status */ 489 } 490} 491#endif 492 493int get_battery_capacity(void) 494{ 495 return battery_capacity; 496} 497 498/* Tells if the battery level is safe for disk writes */ 499bool battery_level_safe(void) 500{ 501#if defined(NO_LOW_BATTERY_SHUTDOWN) 502 return true; 503#elif ((CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)) 504 return voltage_now > battery_level_disksafe; 505#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE 506 return percent_now > 0; 507#elif defined(HAVE_BATTERY_SWITCH) 508 /* Cannot rely upon the battery reading to be valid and the 509 * device could be powered externally. */ 510 return input_millivolts() > battery_level_disksafe; 511#else 512 return voltage_now > battery_level_disksafe; 513#endif 514} 515 516/* Check to see whether or not we've received an alarm in the last second */ 517#ifdef HAVE_RTC_ALARM 518static void power_thread_rtc_process(void) 519{ 520 if (rtc_check_alarm_flag()) 521 rtc_enable_alarm(false); 522} 523#endif 524 525/* switch off unit if battery level is too low for reliable operation */ 526bool query_force_shutdown(void) 527{ 528#if CONFIG_CHARGING 529 /* It doesn't make sense to force shutdown when externally powered. */ 530 if (power_input_present()) 531 return false; 532#endif 533 534#if defined(NO_LOW_BATTERY_SHUTDOWN) 535 return false; 536#elif ((CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)) 537 /* If we have both, prefer voltage */ 538 return voltage_now < battery_level_shutoff; 539#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE 540 return percent_now == 0; 541#elif defined(HAVE_BATTERY_SWITCH) 542 /* Cannot rely upon the battery reading to be valid and the 543 * device could be powered externally. */ 544 return input_millivolts() < battery_level_shutoff; 545#else 546 return voltage_now < battery_level_shutoff; 547#endif 548} 549 550#if defined(HAVE_BATTERY_SWITCH) || defined(HAVE_RESET_BATTERY_FILTER) 551/* 552 * Reset the battery voltage filter to a new value and update the 553 * status. 554 */ 555void reset_battery_filter(int millivolts) 556{ 557 voltage_avg = millivolts * BATT_AVE_SAMPLES; 558 voltage_now = millivolts; 559#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 560 /* current would probably be inaccurate too */ 561 current_now = _battery_current(); 562 current_avg = current_now * BATT_CURRENT_AVE_SAMPLES; 563#endif 564 battery_status_update(); 565} 566#endif /* HAVE_BATTERY_SWITCH */ 567 568/** Generic charging algorithms for common charging types **/ 569#if CONFIG_CHARGING == 0 || CONFIG_CHARGING == CHARGING_SIMPLE 570static inline void powermgmt_init_target(void) 571{ 572 /* Nothing to do */ 573} 574 575static inline void charging_algorithm_step(void) 576{ 577 /* Nothing to do */ 578} 579 580static inline void charging_algorithm_close(void) 581{ 582 /* Nothing to do */ 583} 584#elif CONFIG_CHARGING == CHARGING_MONITOR 585/* 586 * Monitor CHARGING/DISCHARGING state. 587 */ 588static inline void powermgmt_init_target(void) 589{ 590 /* Nothing to do */ 591} 592 593static inline void charging_algorithm_step(void) 594{ 595 switch (charger_input_state) 596 { 597 case CHARGER_PLUGGED: 598 case CHARGER: 599 if (charging_state()) { 600 charge_state = CHARGING; 601 break; 602 } 603 /* Fallthrough */ 604 case CHARGER_UNPLUGGED: 605 case NO_CHARGER: 606 charge_state = DISCHARGING; 607 break; 608 } 609} 610 611static inline void charging_algorithm_close(void) 612{ 613 /* Nothing to do */ 614} 615#endif /* CONFIG_CHARGING == * */ 616 617#if CONFIG_CHARGING 618/* Shortcut function calls - compatibility, simplicity. */ 619 620/* Returns true if any power input is capable of charging. */ 621bool charger_inserted(void) 622{ 623#ifndef BOOTLOADER 624 unsigned int data = power_thread_inputs; 625#else 626 unsigned int data = power_input_status(); 627#endif 628 return data & POWER_INPUT_CHARGER; 629} 630 631/* Returns true if any power input is connected - charging-capable 632 * or not. */ 633bool power_input_present(void) 634{ 635#ifndef BOOTLOADER 636 unsigned int data = power_thread_inputs; 637#else 638 unsigned int data = power_input_status(); 639#endif 640 return data & POWER_INPUT; 641} 642 643/* 644 * Detect charger inserted. Return true if the state is transistional. 645 */ 646static inline bool detect_charger(unsigned int pwr) 647{ 648 /* 649 * Detect charger plugged/unplugged transitions. On a plugged or 650 * unplugged event, we return immediately, run once through the main 651 * loop (including the subroutines), and end up back here where we 652 * transition to the appropriate steady state charger on/off state. 653 */ 654 if (pwr & POWER_INPUT_CHARGER) { 655 switch (charger_input_state) 656 { 657 case NO_CHARGER: 658 case CHARGER_UNPLUGGED: 659 charger_input_state = CHARGER_PLUGGED; 660 break; 661 662 case CHARGER_PLUGGED: 663 queue_broadcast(SYS_CHARGER_CONNECTED, 0); 664 last_sent_battery_level = 0; 665 charger_input_state = CHARGER; 666 break; 667 668 case CHARGER: 669 /* Steady state */ 670 return false; 671 } 672 } 673 else { /* charger not inserted */ 674 switch (charger_input_state) 675 { 676 case NO_CHARGER: 677 /* Steady state */ 678 return false; 679 680 case CHARGER_UNPLUGGED: 681 queue_broadcast(SYS_CHARGER_DISCONNECTED, 0); 682 last_sent_battery_level = 100; 683 charger_input_state = NO_CHARGER; 684 break; 685 686 case CHARGER_PLUGGED: 687 case CHARGER: 688 charger_input_state = CHARGER_UNPLUGGED; 689 break; 690 } 691 } 692 693 /* Transitional state */ 694 return true; 695} 696#endif /* CONFIG_CHARGING */ 697 698#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE 699static int power_hist_item(void) 700{ 701 return voltage_now; 702} 703#else 704static int power_hist_item(void) 705{ 706 return percent_now; 707} 708#endif 709 710static void collect_power_history(void) 711{ 712 /* rotate the power history */ 713 memmove(&power_history[1], &power_history[0], 714 sizeof(power_history) - sizeof(power_history[0])); 715 power_history[0] = power_hist_item(); 716} 717 718/* 719 * Monitor the presence of a charger and perform critical frequent steps 720 * such as running the battery voltage filter. 721 */ 722static inline void power_thread_step(void) 723{ 724 /* If the power off timeout expires, the main thread has failed 725 to shut down the system, and we need to force a power off */ 726 if (shutdown_timeout) { 727 shutdown_timeout -= POWER_THREAD_STEP_TICKS; 728 729 if (shutdown_timeout <= 0) 730 power_off(); 731 } 732 733#ifdef HAVE_RTC_ALARM 734 power_thread_rtc_process(); 735#endif 736 737 /* 738 * Do a digital exponential filter. We don't sample the battery if 739 * the disk is spinning unless we are in USB mode (the disk will most 740 * likely always be spinning in USB mode) or charging. 741 */ 742 if (!storage_disk_is_active() || usb_inserted() 743#if CONFIG_CHARGING >= CHARGING_MONITOR 744 || charger_input_state == CHARGER 745#endif 746 ) { 747 average_step(false); 748 battery_status_update(); 749 } 750 else if (percent_now < 8) { 751 average_step(true); 752 battery_status_update(); 753 754 /* 755 * If battery is low, observe voltage during disk activity. 756 * Shut down if voltage drops below shutoff level and we are not 757 * using NiMH or Alkaline batteries. 758 */ 759 if (!shutdown_timeout && query_force_shutdown()) { 760 sys_poweroff(); 761 } 762 } 763} /* power_thread_step */ 764 765static void power_thread(void) 766{ 767 long next_power_hist; 768 769 /* Delay reading the first battery level */ 770#ifdef MROBE_100 771 while (_battery_voltage() > 4200) /* gives false readings initially */ 772 { 773#elif defined(DX50) || defined(DX90) 774 while (_battery_voltage() < 1) /* can give false readings initially */ 775 { 776#elif defined(EROS_QN) || defined(FIIO_M3K) || defined(SHANLING_Q1) 777 778 /* wait until the first battery read is ready */ 779 while (_battery_voltage() <= 0) 780 { 781#else 782 { 783#endif 784 sleep(HZ/100); 785 } 786 787#if CONFIG_CHARGING 788 /* Initialize power input status before calling other routines. */ 789 power_thread_inputs = power_input_status(); 790#endif 791 792 /* call target specific init now */ 793 powermgmt_init_target(); 794 /* initialize voltage averaging (if available) */ 795 average_init(); 796 /* get initial battery level value (in %) */ 797 battery_status_update(); 798 /* get some initial data for the power curve */ 799 collect_power_history(); 800 801 next_power_hist = current_tick + HZ*60; 802 803 while (1) 804 { 805#if CONFIG_CHARGING 806 unsigned int pwr = power_input_status(); 807#ifdef HAVE_BATTERY_SWITCH 808 if ((pwr ^ power_thread_inputs) & POWER_INPUT_BATTERY) { 809 sleep(HZ/10); 810 reset_battery_filter(_battery_voltage()); 811 } 812#endif 813 power_thread_inputs = pwr; 814 815 if (!detect_charger(pwr)) 816#endif /* CONFIG_CHARGING */ 817 { 818 /* Steady state */ 819 sleep(POWER_THREAD_STEP_TICKS); 820 821 /* Do common power tasks */ 822 power_thread_step(); 823 } 824 825 /* Perform target tasks */ 826 charging_algorithm_step(); 827 828 /* check if some idle or sleep timer wears off */ 829 handle_auto_poweroff(); 830 831 if (TIME_AFTER(current_tick, next_power_hist)) { 832 /* increment to ensure there is a record for every minute 833 * rather than go forward from the current tick */ 834 next_power_hist += HZ*60; 835 collect_power_history(); 836 } 837 } 838} /* power_thread */ 839 840#if (BATTERY_CAPACITY_DEFAULT > 0) && !defined(BOOTLOADER) 841static bool battery_table_readln(int fd, char * buf, size_t bufsz, 842 const char *name, char **value, int* linect) INIT_ATTR; 843static bool battery_table_readln(int fd, char * buf, size_t bufsz, 844 const char *name, char **value, int* linect) 845{ 846 /* reads a line from user battery level file skips comments 847 * if name is NULL and the line is a continuation (no setting:) 848 * or name matches the found setting then remaining line contents are returned in value 849 * name if supplied should contain the name of the setting you are searching for */ 850 int rd; 851 char *setting; 852 if (name) 853 { 854 /* DEBUGF("%s Searching for '%s'\n", __func__, name); */ 855 lseek(fd, 0, SEEK_SET); 856 *linect = 0; 857 } 858 859 while(1) 860 { 861 rd = read_line(fd, buf, bufsz); 862 if (rd > 0) 863 { 864 /*DEBUGF("\nREAD '%s'\n", buf);*/ 865 *linect = *linect + 1; 866 if (buf[0] == '#' || buf[0] == '\0') 867 continue; /* skip empty lines and comments to EOL */ 868 869 bool found = settings_parseline(buf, &setting, value); 870 871 if (!name) /* if name is not supplied just return value */ 872 { 873 *value = buf; 874 if(found) /* expected more values but got a new setting instead */ 875 return false; /* error */ 876 } 877 else if (strcasecmp(name, setting) != 0) 878 continue; /* not the correct setting */ 879 } 880 break; 881 } 882 return rd > 0; 883} 884#endif 885 886void init_battery_tables(void) 887{ 888#if (BATTERY_CAPACITY_DEFAULT > 0) && !defined(BOOTLOADER) 889 /* parse and load user battery levels file */ 890#define PWRELEMS (ARRAYLEN(percent_to_volt_discharge)) 891 892 893 unsigned short tmparr[PWRELEMS]; 894 char buf[MAX_PATH]; 895 unsigned int i, bl_op; 896 897 enum { eSHUTOFF = 0, eDISKSAFE, eDISCHARGE, eCHARGE }; 898 static const char * const bl_options[4] = { 899 [eSHUTOFF] = "shutoff", 900 [eDISKSAFE] = "disksafe", 901 [eDISCHARGE] = "discharge", 902 [eCHARGE] = "charge" 903 }; 904 905 int fd = open(BATTERY_LEVELS_USER, O_RDONLY); 906 int line_num = 0; 907 908 unsigned short val; 909 unsigned short disksafe = *device_battery_tables.disksafe; 910 unsigned short shutoff = *device_battery_tables.shutoff; 911 char *value; 912 913 if (fd < 0) 914 return; 915 916 DEBUGF("%s %s\n", __func__, BATTERY_LEVELS_USER); 917 /* force order of reads to do error checking of values */ 918 for(bl_op = 0; bl_op < ARRAYLEN(bl_options); bl_op++) 919 { 920 if(!battery_table_readln(fd, buf, sizeof(buf), 921 bl_options[bl_op], &value, &line_num)) 922 { 923 continue; 924 } 925 926 switch(bl_op) 927 { 928 default: 929 goto error_loading; 930 case eSHUTOFF: 931 /*fall-through*/ 932 case eDISKSAFE: 933 /* parse single short */ 934 DEBUGF("%s ", bl_options[bl_op]); 935 936 while (*value != '\0' && !isdigit(*value)) 937 value++; 938 if (*value) 939 { 940 val = atoi(value); 941 DEBUGF("value = %u\n", val); 942 if (bl_op == eDISKSAFE) 943 { 944 if (val < shutoff) 945 { 946 goto error_loading; 947 } 948 disksafe = val; 949 break; 950 } 951 /* shutoff */ 952 shutoff = val; 953 break; 954 } 955 goto error_loading; 956 case eDISCHARGE: 957 /*fall-through*/ 958 case eCHARGE: 959 /* parse array of short */ 960 DEBUGF("%s = { ", bl_options[bl_op]); 961 val = shutoff; /* don't allow a value lower than shutoff */ 962 i = 0; 963 while(i < PWRELEMS) 964 { 965 while (*value != '\0' && !isdigit(*value)) 966 {value++;} 967 if (*value) 968 { 969 tmparr[i] = atoi(value); 970 while (isdigit(*value)) /* skip digits just read */ 971 {value++;} 972 if (tmparr[i] < val) 973 { 974 goto error_loading; /* value is not >= previous */ 975 } 976 val = tmparr[i]; 977 DEBUGF("%u, ", val); 978 i++; 979 } 980 else if (!battery_table_readln(fd, buf, sizeof(buf), 981 NULL, &value, &line_num)) 982 { 983 goto error_loading; /* failed to get another line */ 984 } 985 986 } /* while */ 987 DEBUGF("}\n"); 988 989 /* if we made it here, the values should be OK to use */ 990 if (bl_op == eCHARGE) 991 { 992#if CONFIG_CHARGING 993 memcpy(device_battery_tables.charge, &tmparr, PWRELEMS); 994#endif 995 break; 996 } 997 memcpy(device_battery_tables.discharge, &tmparr, PWRELEMS); 998 break; 999 } /* switch */ 1000 } /* for */ 1001 close(fd); 1002 1003 *device_battery_tables.disksafe = disksafe; 1004 *device_battery_tables.shutoff = shutoff; 1005 device_battery_tables.isdefault = false; 1006 battery_status_update(); 1007 1008 return; 1009 1010error_loading: 1011 if (fd >= 0) 1012 close(fd); 1013 splashf(HZ * 2, "Error line:(%d) loading %s", line_num, BATTERY_LEVELS_USER); 1014 DEBUGF("Error line:(%d) loading %s\n", line_num, BATTERY_LEVELS_USER); 1015#undef PWRELEMS 1016#endif /* ndef BOOTLOADER*/ 1017} 1018 1019void powermgmt_init(void) 1020{ 1021 create_thread(power_thread, power_stack, sizeof(power_stack), 0, 1022 power_thread_name IF_PRIO(, PRIORITY_SYSTEM) 1023 IF_COP(, CPU)); 1024} 1025 1026/* Various hardware housekeeping tasks relating to shutting down the player */ 1027void shutdown_hw(enum shutdown_type sd_type) 1028{ 1029 charging_algorithm_close(); 1030 audio_stop(); 1031 1032 if (battery_level_safe()) { /* do not save on critical battery */ 1033 font_unload_all(); 1034 1035/* Commit pending writes if needed. Even though we don't do write caching, 1036 things like flash translation layers may need this to commit scattered 1037 pages to their final locations. So far only used for iPod Nano 2G. */ 1038#ifdef HAVE_STORAGE_FLUSH 1039 storage_flush(); 1040#endif 1041 1042 if (storage_disk_is_active()) 1043 storage_spindown(1); 1044 } 1045 1046 audiohw_close(); 1047 1048 /* If HD is still active we try to wait for spindown, otherwise the 1049 shutdown_timeout in power_thread_step will force a power off */ 1050 while (storage_disk_is_active()) 1051 sleep(HZ/10); 1052 1053#ifndef HAVE_LCD_COLOR 1054 lcd_set_contrast(0); 1055#endif 1056#ifdef HAVE_REMOTE_LCD 1057 lcd_remote_set_contrast(0); 1058#endif 1059#ifdef HAVE_LCD_SHUTDOWN 1060 lcd_shutdown(); 1061#endif 1062 1063 /* Small delay to make sure all HW gets time to flush. Especially 1064 eeprom chips are quite slow and might be still writing the last 1065 byte. */ 1066 sleep(HZ/4); 1067 1068 switch (sd_type) { 1069 case SHUTDOWN_POWER_OFF: 1070 default: 1071 power_off(); 1072 break; 1073 1074 case SHUTDOWN_REBOOT: 1075 system_reboot(); 1076 break; 1077 } 1078} 1079 1080void set_poweroff_timeout(int timeout) 1081{ 1082 poweroff_timeout = timeout; 1083} 1084 1085void reset_poweroff_timer(void) 1086{ 1087 last_event_tick = current_tick; 1088 if (sleeptimer_active && sleeptimer_key_restarts) 1089 set_sleep_timer(sleeptimer_duration); 1090} 1091 1092#ifndef BOOTLOADER 1093static void sys_shutdown_common(void) 1094{ 1095 /* If the main thread fails to shut down the system, we will force a 1096 power off after an 20 second timeout - 28 seconds if recording */ 1097 if (shutdown_timeout == 0) { 1098#if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR) 1099 pcf50606_reset_timeout(); /* Reset timer on first attempt only */ 1100#endif 1101#ifdef HAVE_RECORDING 1102 if (audio_status() & AUDIO_STATUS_RECORD) 1103 shutdown_timeout += HZ*8; 1104#endif 1105#ifdef IPOD_NANO2G 1106 /* The FTL alone may take half a minute to shut down cleanly. */ 1107 shutdown_timeout += HZ*60; 1108#else 1109 shutdown_timeout += HZ*20; 1110#endif 1111 } 1112} 1113#endif /* BOOTLOADER */ 1114 1115void sys_poweroff(void) 1116{ 1117#ifndef BOOTLOADER 1118 logf("sys_poweroff()"); 1119 sys_shutdown_common(); 1120 queue_broadcast(SYS_POWEROFF, 0); 1121#endif 1122} 1123 1124/* not to be confused with system_reboot... :( */ 1125void sys_reboot(void) 1126{ 1127#ifndef BOOTLOADER 1128 logf("sys_reboot()"); 1129 sys_shutdown_common(); 1130 queue_broadcast(SYS_REBOOT, 0); 1131#endif 1132} 1133 1134void cancel_shutdown(void) 1135{ 1136 logf("cancel_shutdown()"); 1137 1138#if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR) 1139 /* TODO: Move some things to target/ tree */ 1140 if (shutdown_timeout) 1141 pcf50606_reset_timeout(); 1142#endif 1143 1144 shutdown_timeout = 0; 1145} 1146 1147void set_sleeptimer_duration(int minutes) 1148{ 1149 set_sleep_timer(minutes * 60); 1150} 1151 1152static void set_sleep_timer(int seconds) 1153{ 1154 if (seconds) { 1155 sleeptimer_active = true; 1156 sleeptimer_endtick = current_tick + seconds * HZ; 1157 } 1158 else { 1159 sleeptimer_active = false; 1160 sleeptimer_endtick = 0; 1161 } 1162 sleeptimer_duration = seconds; 1163} 1164 1165bool get_sleep_timer_active(void) 1166{ 1167 return sleeptimer_active; 1168} 1169 1170int get_sleep_timer(void) 1171{ 1172 if (sleeptimer_active && (sleeptimer_endtick >= current_tick)) 1173 return (sleeptimer_endtick - current_tick) / HZ; 1174 else 1175 return 0; 1176} 1177 1178void set_keypress_restarts_sleep_timer(bool enable) 1179{ 1180 sleeptimer_key_restarts = enable; 1181} 1182 1183#ifndef BOOTLOADER 1184static void handle_sleep_timer(void) 1185{ 1186 if (TIME_AFTER(current_tick, sleeptimer_endtick)) { 1187 if (usb_inserted() 1188#if CONFIG_CHARGING 1189 || charger_input_state != NO_CHARGER 1190#endif 1191 ) { 1192 DEBUGF("Sleep timer timeout. Stopping...\n"); 1193 audio_pause(); 1194 set_sleep_timer(0); 1195 backlight_off(); /* Nighty, nighty... */ 1196 } 1197 else { 1198 DEBUGF("Sleep timer timeout. Shutting off...\n"); 1199 // sys_poweroff(); 1200 } 1201 } 1202} 1203#endif /* BOOTLOADER */ 1204 1205/* 1206 * We shut off in the following cases: 1207 * 1) The unit is idle, not playing music 1208 * 2) The unit is playing music, but is paused 1209 * 3) The battery level has reached shutdown limit 1210 * 1211 * We do not shut off in the following cases: 1212 * 1) The USB is connected 1213 * 2) The charger is connected 1214 * 3) We are recording, or recording with pause 1215 * 4) The radio is playing 1216 */ 1217void handle_auto_poweroff(void) 1218{ 1219#ifndef BOOTLOADER 1220 long timeout = poweroff_timeout*60*HZ; 1221 int audio_stat = audio_status(); 1222 long tick = current_tick; 1223 1224 /* 1225 * Inhibit shutdown as long as the charger is plugged in. If it is 1226 * unplugged, wait for a timeout period and then shut down. 1227 */ 1228 if (audio_stat == AUDIO_STATUS_PLAY 1229#if CONFIG_CHARGING 1230 || charger_input_state == CHARGER 1231#endif 1232 ) { 1233 last_event_tick = current_tick; 1234 } 1235 1236 if (!shutdown_timeout && query_force_shutdown()) { 1237 backlight_on(); 1238 sys_poweroff(); 1239 } 1240 1241 if (timeout && 1242#if CONFIG_TUNER 1243 !(get_radio_status() & FMRADIO_PLAYING) && 1244#endif 1245 !usb_inserted() && 1246 (audio_stat == 0 || 1247 audio_stat == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE))) 1248 { 1249 if (TIME_AFTER(tick, last_event_tick + timeout) 1250#if !(CONFIG_PLATFORM & PLATFORM_HOSTED) 1251 && TIME_AFTER(tick, storage_last_disk_activity() + timeout) 1252#endif 1253 ) { 1254 // sys_poweroff(); 1255 } 1256 } 1257 1258 if (sleeptimer_active) 1259 handle_sleep_timer(); 1260#endif 1261}