rockbox/firmware/target/hosted/sonynwz/debug-nwz.c
Amaury Pouly dd82f13fa1 nwz/alsa: various improvements
Also audiohw driver to specific device name, rewrite alsa controls code to
cache more data, thus making the code easier and use less stack. Avoid using
short/long in pcm alsa code since it's the wrong size on 64-bit (simulator
for example)

Change-Id: Ibc1ec44396e37b6cbdedbcf37300878638e5d2d3
2020-10-31 14:16:31 +00:00

471 lines
13 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2016 by Amaury Pouly
*
* 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "cpu.h"
#include "system.h"
#include "kernel.h"
#include "lcd.h"
#include "font.h"
#include "adc.h"
#include "adc-target.h"
#include "button.h"
#include "button-target.h"
#include "powermgmt.h"
#include "power-nwz.h"
#include "nvp-nwz.h"
#include "nwz_sysinfo.h"
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "nwzlinux_codec.h"
/* NOTE: some targets with touchscreen don't have the usual keypad, on those
* we use a mixture of rewind/forward/volume+/- to emulate it */
#define ACT_NONE 0
#define ACT_CANCEL 1
#define ACT_OK 2
#define ACT_PREV 3
#define ACT_NEXT 4
#define ACT_DEC 5
#define ACT_INC 6
#define ACT_REPEAT 0x1000
int xlate_button(int btn)
{
switch(btn)
{
#ifdef BUTTON_POWER
case BUTTON_POWER:
#endif
case BUTTON_BACK:
return ACT_CANCEL;
case BUTTON_PLAY:
return ACT_OK;
case BUTTON_UP:
#ifdef BUTTON_FF
case BUTTON_FF:
#endif
return ACT_PREV;
case BUTTON_RIGHT:
case BUTTON_VOL_UP:
return ACT_INC;
case BUTTON_DOWN:
#ifdef BUTTON_FF
case BUTTON_REW:
#endif
return ACT_NEXT;
case BUTTON_LEFT:
case BUTTON_VOL_DOWN:
return ACT_DEC;
default:
return ACT_NONE;
}
}
int my_get_status(void)
{
return xlate_button(button_status());
}
int my_get_action(int tmo)
{
int btn = button_get_w_tmo(tmo);
while(btn & BUTTON_REL)
btn = button_get_w_tmo(tmo);
bool repeat = btn & BUTTON_REPEAT;
int act = xlate_button(btn & ~BUTTON_REPEAT);
if(repeat)
act |= ACT_REPEAT;
return act;
}
bool dbg_hw_info_adc(void)
{
lcd_setfont(FONT_SYSFIXED);
while(1)
{
int button = my_get_action(HZ / 25);
switch(button)
{
case ACT_OK:
lcd_setfont(FONT_UI);
return true;
case ACT_CANCEL:
lcd_setfont(FONT_UI);
return false;
}
lcd_clear_display();
/* add battery readout in mV, this it is not the direct output of a channel */
lcd_putsf(0, 0, "Battery(mV) %d", _battery_voltage());
for(unsigned i = NWZ_ADC_MIN_CHAN; i <= NWZ_ADC_MAX_CHAN; i++)
lcd_putsf(0, i + 1, "%7s %3d", adc_name(i), adc_read(i));
lcd_update();
yield();
}
}
static const char *charge_status_name(int chgstat)
{
switch(chgstat)
{
case NWZ_POWER_STATUS_CHARGE_STATUS_CHARGING: return "charging";
case NWZ_POWER_STATUS_CHARGE_STATUS_SUSPEND: return "suspend";
case NWZ_POWER_STATUS_CHARGE_STATUS_TIMEOUT: return "timeout";
case NWZ_POWER_STATUS_CHARGE_STATUS_NORMAL: return "normal";
default: return "unknown";
}
}
static const char *get_batt_gauge_name(int gauge)
{
switch(gauge)
{
case NWZ_POWER_BAT_NOBAT: return "no batt";
case NWZ_POWER_BAT_VERYLOW: return "very low";
case NWZ_POWER_BAT_LOW: return "low";
case NWZ_POWER_BAT_GAUGE0: return "____";
case NWZ_POWER_BAT_GAUGE1: return "O___";
case NWZ_POWER_BAT_GAUGE2: return "OO__";
case NWZ_POWER_BAT_GAUGE3: return "OOO_";
case NWZ_POWER_BAT_GAUGE4: return "OOOO";
default: return "unknown";
}
}
static const char *acc_charge_mode_name(int mode)
{
switch(mode)
{
case NWZ_POWER_ACC_CHARGE_NONE: return "none";
case NWZ_POWER_ACC_CHARGE_VBAT: return "vbat";
case NWZ_POWER_ACC_CHARGE_VSYS: return "vsys";
default: return "unknown";
}
}
bool dbg_hw_info_power(void)
{
lcd_setfont(FONT_SYSFIXED);
while(1)
{
int button = my_get_action(HZ / 25);
switch(button)
{
case ACT_OK:
lcd_setfont(FONT_UI);
return true;
case ACT_CANCEL:
lcd_setfont(FONT_UI);
return false;
}
lcd_clear_display();
int line = 0;
int status = nwz_power_get_status();
int chgstat = status & NWZ_POWER_STATUS_CHARGE_STATUS;
int acc_chg_mode = nwz_power_get_acc_charge_mode();
lcd_putsf(0, line++, "ac detected: %s",
(status & NWZ_POWER_STATUS_AC_DET) ? "yes" : "no");
lcd_putsf(0, line++, "vbus detected: %s ",
(status & NWZ_POWER_STATUS_VBUS_DET) ? "yes" : "no");
lcd_putsf(0, line++, "vbus voltage: %d mV (AD=%d)",
nwz_power_get_vbus_voltage(), nwz_power_get_vbus_adval());
lcd_putsf(0, line++, "vbus limit: %d mA ",
nwz_power_get_vbus_limit());
lcd_putsf(0, line++, "vsys voltage: %d mV (AD=%d)",
nwz_power_get_vsys_voltage(), nwz_power_get_vsys_adval());
lcd_putsf(0, line++, "charge switch: %s ",
nwz_power_get_charge_switch() ? "on" : "off");
lcd_putsf(0, line++, "full voltage: %s V ",
(status & NWZ_POWER_STATUS_CHARGE_LOW) ? "4.1" : "4.2");
lcd_putsf(0, line++, "current limit: %d mA",
nwz_power_get_charge_current());
lcd_putsf(0, line++, "charge status: %s (%x)",
charge_status_name(chgstat), chgstat);
lcd_putsf(0, line++, "battery full: %s ",
nwz_power_is_fully_charged() ? "yes" : "no");
lcd_putsf(0, line++, "bat gauge: %s (%d)",
get_batt_gauge_name(nwz_power_get_battery_gauge()),
nwz_power_get_battery_gauge());
lcd_putsf(0, line++, "avg voltage: %d mV (AD=%d)",
nwz_power_get_battery_voltage(), nwz_power_get_battery_adval());
lcd_putsf(0, line++, "sample count: %d ",
nwz_power_get_sample_count());
lcd_putsf(0, line++, "raw voltage: %d mV (AD=%d)",
nwz_power_get_vbat_voltage(), nwz_power_get_vbat_adval());
lcd_putsf(0, line++, "acc charge mode: %s (%d)",
acc_charge_mode_name(acc_chg_mode), acc_chg_mode);
lcd_update();
yield();
}
}
bool dbg_hw_info_button(void)
{
lcd_setfont(FONT_SYSFIXED);
while(1)
{
int btn = my_get_action(0);
switch(btn)
{
case ACT_OK:
lcd_setfont(FONT_UI);
return true;
case ACT_CANCEL:
lcd_setfont(FONT_UI);
return false;
}
lcd_clear_display();
int line = 0;
#ifdef HAVE_BUTTON_DATA
int data;
btn = button_read_device(&data);
#else
btn = button_read_device();
#endif
lcd_putsf(0, line++, "raw buttons: %x", btn);
#ifdef HAS_BUTTON_HOLD
lcd_putsf(0, line++, "hold: %d", button_hold());
#endif
#ifdef HAVE_HEADPHONE_DETECTION
lcd_putsf(0, line++, "headphones: %d", headphones_inserted());
#endif
#ifdef HAVE_BUTTON_DATA
#ifdef HAVE_TOUCHSCREEN
lcd_putsf(0, line++, "touch: x=%d y=%d", data >> 16, data & 0xffff);
#else
lcd_putsf(0, line++, "data: %d", data);
#endif
#endif
lcd_update();
yield();
}
}
int read_sysinfo(int ioctl_nr, unsigned int *val)
{
int fd = open(NWZ_SYSINFO_DEV, O_RDONLY);
if(fd < 0)
return -1;
int ret = ioctl(fd, ioctl_nr, val);
close(fd);
return ret;
}
bool dbg_hw_info_sysinfo(void)
{
lcd_setfont(FONT_SYSFIXED);
while(1)
{
int btn = my_get_action(0);
switch(btn)
{
case ACT_OK:
lcd_setfont(FONT_UI);
return true;
case ACT_CANCEL:
lcd_setfont(FONT_UI);
return false;
}
lcd_clear_display();
int line = 0;
unsigned int val;
lcd_putsf(0, line++, "mid: %x (%s)", nwz_get_model_id(), nwz_get_model_name());
#define print_info(def, name) \
if(read_sysinfo(NWZ_SYSINFO_GET_##def##_TYPE, &val) < 0) \
lcd_putsf(0, line++, "%s: -", name); \
else \
lcd_putsf(0, line++, "%s: %d", name, val);
/* WARNING the interpretation of values is difficult because it changes
* very often */
/* DAC type: ... */
print_info(DAC, "dac")
/* Noise cancelling: 0=no, 1=yes */
print_info(NCR, "nc")
/* Speaker: 0=no, 1=yes */
print_info(SPK, "spk")
/* Microphone: 0=no, 1=yes */
print_info(MIC, "mic")
/* Video encoder: 0=no, ... */
print_info(NPE, "videoenc")
/* FM receiver: 0=no, 1=si470x */
print_info(FMT, "fm")
/* Touch screen: 0=none, ... */
print_info(TSP, "touch")
/* Bluetooth: 0=no, 1=yes */
print_info(WAB, "bt")
/* SD card: 0=no, ... */
print_info(SDC, "sd")
lcd_update();
yield();
}
}
#include "pcm-alsa.h"
bool dbg_hw_info_audio(void)
{
lcd_setfont(FONT_SYSFIXED);
int vol = 0;
enum { VOL, ACOUSTIC, CUEREV, NR_SETTINGS } setting = VOL;
while(1)
{
int btn = my_get_action(0);
switch(btn)
{
case ACT_PREV:
setting = (setting + NR_SETTINGS - 1) % NR_SETTINGS;
break;
case ACT_NEXT:
setting = (setting + 1) % NR_SETTINGS;
break;
case ACT_OK:
lcd_setfont(FONT_UI);
return true;
case ACT_CANCEL:
lcd_setfont(FONT_UI);
return false;
}
if(btn == ACT_INC || btn == ACT_DEC)
{
bool inc = (btn == ACT_INC);
switch(setting)
{
case VOL:
vol += inc ? 1 : -1;
pcm_set_mixer_volume(vol, vol);
break;
case ACOUSTIC:
audiohw_enable_acoustic(!audiohw_acoustic_enabled());
break;
case CUEREV:
audiohw_enable_cuerev(!audiohw_cuerev_enabled());
break;
default:
break;
}
}
lcd_clear_display();
int line = 0;
#define SEL_COL(item) lcd_set_foreground(item == setting ? LCD_RGBPACK(255, 0, 0) : LCD_WHITE);
SEL_COL(VOL)
lcd_putsf(0, line++, "vol: %d dB", vol);
SEL_COL(ACOUSTIC)
lcd_putsf(0, line++, "acoustic: %s", audiohw_acoustic_enabled() ? "on" : "off");
SEL_COL(CUEREV)
lcd_putsf(0, line++, "cue/rev: %s", audiohw_cuerev_enabled() ? "on" : "off");
lcd_set_foreground(LCD_WHITE);
#undef SEL_COL
lcd_update();
yield();
}
}
static struct
{
const char *name;
bool (*fn)(void);
} debug_screens[] =
{
{"sysinfo", dbg_hw_info_sysinfo},
{"adc", dbg_hw_info_adc},
{"power", dbg_hw_info_power},
{"button", dbg_hw_info_button},
{"audio", dbg_hw_info_audio},
};
bool dbg_hw_info(void)
{
int nr_lines = lcd_getheight() / font_get(lcd_getfont())->height;
int len = ARRAYLEN(debug_screens);
int top_visible = 0;
int highlight = 0;
while(1)
{
int button = my_get_action(HZ / 10);
switch(button)
{
case ACT_NEXT:
highlight = (highlight + 1) % len;
break;
case ACT_PREV:
highlight = (highlight + len - 1) % len;
break;
case ACT_OK:
// if the screen returns true, advance to next screen
while(debug_screens[highlight].fn())
highlight = (highlight + 1) % len;
lcd_setfont(FONT_UI);
break;
case ACT_CANCEL:
return false;
}
// adjust top visible if needed
if(highlight < top_visible)
top_visible = highlight;
else if(highlight >= top_visible + nr_lines)
top_visible = highlight - nr_lines + 1;
lcd_clear_display();
for(int i = top_visible; i < len && i < top_visible + nr_lines; i++)
{
if(i == highlight)
{
lcd_set_foreground(LCD_BLACK);
lcd_set_background(LCD_RGBPACK(255, 255, 0));
}
else
{
lcd_set_foreground(LCD_WHITE);
lcd_set_background(LCD_BLACK);
}
lcd_putsf(0, i - top_visible, "%s", debug_screens[i].name);
}
lcd_set_foreground(LCD_WHITE);
lcd_set_background(LCD_BLACK);
lcd_update();
yield();
}
return false;
}