rockbox/apps/plugins/oscilloscope.c
Thomas Martitz 249bba03f1 Initial commit of the Samsung YP-R0 port.
This port is a hybrid native/RaaA port. It runs on a embedded linux system,
but is the only application. It therefore can implement lots of stuff that
native targets also implement, while leveraging the underlying linux kernel.

The port is quite advanced. User interface, audio playback, plugins work
mostly fine. Missing is e.g. power mangement and USB (see SamsungYPR0 wiki page).

Included in utils/ypr0tools are scripts and programs required to generate
a patched firmware. The patched firmware has the rootfs modified to load
Rockbox. It includes a early/safe USB mode.

This port needs a new toolchain, one that includes glibc headers and libraries.
rockboxdev.sh can generate it, but e.g. codesourcey and distro packages may
also work.

Most of the initial effort is done by Lorenzo Miori and others (on ABI),
including reverse engineering and patching of the original firmware,
initial drivers, and more. Big thanks to you.

Flyspray: FS#12348
Author: Lorenzo Miori, myself

Merry christmas to ypr0 owners! :)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31415 a1c6a512-1295-4272-9138-f99709370657
2011-12-24 11:56:46 +00:00

977 lines
33 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Oscilloscope, with many different modes of operation.
*
* Copyright (C) 2004-2006 Jens Arnold
*
* 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 "plugin.h"
#include "lib/helper.h"
#include "lib/pluginlib_exit.h"
#include "lib/xlcd.h"
#include "lib/configfile.h"
/* variable button definitions */
#if CONFIG_KEYPAD == RECORDER_PAD
#define OSCILLOSCOPE_QUIT BUTTON_OFF
#define OSCILLOSCOPE_DRAWMODE BUTTON_F1
#define OSCILLOSCOPE_ADVMODE BUTTON_F2
#define OSCILLOSCOPE_ORIENTATION BUTTON_F3
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
#define OSCILLOSCOPE_QUIT BUTTON_OFF
#define OSCILLOSCOPE_DRAWMODE BUTTON_F1
#define OSCILLOSCOPE_ADVMODE BUTTON_F2
#define OSCILLOSCOPE_ORIENTATION BUTTON_F3
#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == ONDIO_PAD
#define OSCILLOSCOPE_QUIT BUTTON_OFF
#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU
#define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT)
#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT)
#define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_OFF
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_MODE
#define OSCILLOSCOPE_ORIENTATION BUTTON_REC
#define OSCILLOSCOPE_PAUSE BUTTON_ON
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#define OSCILLOSCOPE_RC_QUIT BUTTON_RC_STOP
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_A
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_REC
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
#define OSCILLOSCOPE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
#define OSCILLOSCOPE_PAUSE BUTTON_UP
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
#elif (CONFIG_KEYPAD == SANSA_C200_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_REC
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_HOME
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == SANSA_M200_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE (BUTTON_SELECT | BUTTON_UP)
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE BUTTON_REC
#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
#define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE BUTTON_FF
#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
#define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
#define OSCILLOSCOPE_QUIT BUTTON_BACK
#define OSCILLOSCOPE_DRAWMODE BUTTON_PREV
#define OSCILLOSCOPE_ADVMODE BUTTON_NEXT
#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == MROBE100_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_MENU
#define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY
#define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
#define OSCILLOSCOPE_QUIT BUTTON_RC_REC
#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE
#define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL)
#define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU
#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE
#define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT)
#define OSCILLOSCOPE_PAUSE BUTTON_RC_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW
#define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN
#elif CONFIG_KEYPAD == COWON_D2_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_VOL_UP BUTTON_PLUS
#define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS
#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
#define OSCILLOSCOPE_QUIT BUTTON_BACK
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_CUSTOM
#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
#define OSCILLOSCOPE_ADVMODE BUTTON_VIEW
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == ONDAVX747_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == ONDAVX777_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#elif CONFIG_KEYPAD == MROBE500_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
#define OSCILLOSCOPE_QUIT BUTTON_REC
#define OSCILLOSCOPE_DRAWMODE (BUTTON_PLAY|BUTTON_LEFT)
#define OSCILLOSCOPE_ADVMODE (BUTTON_PLAY|BUTTON_RIGHT)
#define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY|BUTTON_UP)
#define OSCILLOSCOPE_PAUSE (BUTTON_PLAY|BUTTON_DOWN)
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
#define OSCILLOSCOPE_QUIT BUTTON_REC
#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
#define OSCILLOSCOPE_ADVMODE BUTTON_CANCEL
#define OSCILLOSCOPE_ORIENTATION BUTTON_OK
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_PREV
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_NEXT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
#define OSCILLOSCOPE_QUIT (BUTTON_REC | BUTTON_PLAY)
#define OSCILLOSCOPE_DRAWMODE BUTTON_FUNC
#define OSCILLOSCOPE_ADVMODE BUTTON_REC
#define OSCILLOSCOPE_ORIENTATION (BUTTON_FUNC|BUTTON_REPEAT)
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_FF
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif CONFIG_KEYPAD == MPIO_HD300_PAD
#define OSCILLOSCOPE_QUIT (BUTTON_REC | BUTTON_REPEAT)
#define OSCILLOSCOPE_DRAWMODE BUTTON_ENTER
#define OSCILLOSCOPE_ADVMODE BUTTON_REC
#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
#define OSCILLOSCOPE_SPEED_UP BUTTON_FF
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_BACK
#define OSCILLOSCOPE_ORIENTATION (BUTTON_BACK|BUTTON_REPEAT)
#define OSCILLOSCOPE_PAUSE BUTTON_PLAYPAUSE
#define OSCILLOSCOPE_SPEED_UP BUTTON_LEFT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RIGHT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
#define OSCILLOSCOPE_PAUSE BUTTON_NEXT
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_BACK
#define OSCILLOSCOPE_DRAWMODE BUTTON_USER
#define OSCILLOSCOPE_ADVMODE BUTTON_MENU
#define OSCILLOSCOPE_ORIENTATION BUTTON_POWER
#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
#else
#error No keymap defined!
#endif
#ifdef HAVE_TOUCHSCREEN
#ifndef OSCILLOSCOPE_QUIT
#define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT
#endif
#ifndef OSCILLOSCOPE_DRAWMODE
#define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE
#endif
#ifndef OSCILLOSCOPE_ADVMODE
#define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE
#endif
#ifndef OSCILLOSCOPE_ORIENTATION
#define OSCILLOSCOPE_ORIENTATION BUTTON_BOTTOMLEFT
#endif
#ifndef OSCILLOSCOPE_PAUSE
#define OSCILLOSCOPE_PAUSE BUTTON_CENTER
#endif
#ifndef OSCILLOSCOPE_SPEED_UP
#define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT
#endif
#ifndef OSCILLOSCOPE_SPEED_DOWN
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT
#endif
#ifndef OSCILLOSCOPE_VOL_UP
#define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT
#endif
#ifndef OSCILLOSCOPE_VOL_DOWN
#define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT
#endif
#endif
/* colours */
#if LCD_DEPTH > 1
#ifdef HAVE_LCD_COLOR
#define BACKG_COLOR LCD_BLACK
#define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
#define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
#else
#define BACKG_COLOR LCD_WHITE
#define GRAPH_COLOR LCD_BLACK
#define CURSOR_COLOR LCD_DARKGRAY
#endif
#endif
enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
#define CFGFILE_VERSION 0 /* Current config file version */
#define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
#define MAX_PEAK 0x8000
#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
#define mas_codec_readreg(x) rand()%MAX_PEAK
#endif
/* global variables */
/* settings */
struct osc_config {
int delay; /* in ticks */
int draw;
int advance;
int orientation;
};
struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ };
struct osc_config osc; /* running config */
static const char cfg_filename[] = "oscilloscope.cfg";
static char *draw_str[3] = { "filled", "line", "pixel" };
static char *advance_str[2] = { "scroll", "wrap" };
static char *orientation_str[2] = { "horizontal", "vertical" };
struct configdata disk_config[] = {
{ TYPE_INT, 1, 99, { .int_p = &osc_disk.delay }, "delay", NULL },
{ TYPE_ENUM, 0, MAX_DRAW, { .int_p = &osc_disk.draw }, "draw", draw_str },
{ TYPE_ENUM, 0, MAX_ADV, { .int_p = &osc_disk.advance }, "advance",
advance_str },
{ TYPE_ENUM, 0, MAX_OSC, { .int_p = &osc_disk.orientation }, "orientation",
orientation_str }
};
long last_tick = 0; /* time of last drawing */
int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
int last_left; /* last channel values */
int last_right;
unsigned char message[16]; /* message to display */
bool displaymsg = false;
int font_height = 8;
/* implementation */
static void anim_horizontal(int cur_left, int cur_right)
{
int cur_x, x;
int left, right, dl, dr;
long cur_tick = *rb->current_tick;
long d = (cur_tick - last_tick) / osc.delay;
bool full_update = false;
if (d == 0) /* too early, bail out */
return;
last_tick = cur_tick;
if (d > HZ) /* first call or too much delay, (re)start */
{
last_left = cur_left;
last_right = cur_right;
return;
}
cur_x = last_pos + d;
if (cur_x >= LCD_WIDTH)
{
if (osc.advance == ADV_SCROLL)
{
int shift = cur_x - (LCD_WIDTH-1);
xlcd_scroll_left(shift);
full_update = true;
cur_x -= shift;
last_pos -= shift;
}
else
{
cur_x -= LCD_WIDTH;
}
}
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
if (cur_x > last_pos)
{
rb->lcd_fillrect(last_pos + 1, 0, d, LCD_HEIGHT);
}
else
{
rb->lcd_fillrect(last_pos + 1, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
rb->lcd_fillrect(0, 0, cur_x + 1, LCD_HEIGHT);
}
rb->lcd_set_drawmode(DRMODE_SOLID);
switch (osc.draw)
{
case DRAW_FILLED:
left = last_left;
right = last_right;
dl = (cur_left - left) / d;
dr = (cur_right - right) / d;
for (x = last_pos + 1; d > 0; x++, d--)
{
if (x == LCD_WIDTH)
x = 0;
left += dl;
right += dr;
rb->lcd_vline(x, LCD_HEIGHT/2-1,
LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
rb->lcd_vline(x, LCD_HEIGHT/2+1,
LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
}
break;
case DRAW_LINE:
if (cur_x > last_pos)
{
rb->lcd_drawline(
last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
);
rb->lcd_drawline(
last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
);
}
else
{
left = last_left
+ (LCD_WIDTH - last_pos) * (last_left - cur_left) / d;
right = last_right
+ (LCD_WIDTH - last_pos) * (last_right - cur_right) / d;
rb->lcd_drawline(
last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16)
);
rb->lcd_drawline(
last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16)
);
if (cur_x > 0)
{
rb->lcd_drawline(
0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16),
cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
);
rb->lcd_drawline(
0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16),
cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
);
}
}
break;
case DRAW_PIXEL:
left = last_left;
right = last_right;
dl = (cur_left - left) / d;
dr = (cur_right - right) / d;
for (x = last_pos + 1; d > 0; x++, d--)
{
if (x == LCD_WIDTH)
x = 0;
left += dl;
right += dr;
rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
}
break;
}
last_left = cur_left;
last_right = cur_right;
if (displaymsg)
{
int width;
rb->lcd_getstringsize(message, &width, NULL);
last_pos -= width - 1;
rb->lcd_putsxy(last_pos, 0, message);
displaymsg = false;
if (last_pos < 0)
last_pos = 0;
}
if (full_update)
{
rb->lcd_update();
}
else
{
#if LCD_DEPTH > 1 /* cursor bar */
rb->lcd_set_foreground(CURSOR_COLOR);
rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
rb->lcd_set_foreground(GRAPH_COLOR);
#else
rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
rb->lcd_set_drawmode(DRMODE_SOLID);
#endif
if (cur_x > last_pos)
{
rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
}
else
{
rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
}
}
last_pos = cur_x;
}
static void anim_vertical(int cur_left, int cur_right)
{
int cur_y, y;
int left, right, dl, dr;
long cur_tick = *rb->current_tick;
long d = (cur_tick - last_tick) / osc.delay;
bool full_update = false;
if (d == 0) /* too early, bail out */
return;
last_tick = cur_tick;
if (d > HZ) /* first call or too much delay, (re)start */
{
last_left = cur_left;
last_right = cur_right;
return;
}
cur_y = last_pos + d;
if (cur_y >= LCD_HEIGHT)
{
if (osc.advance == ADV_SCROLL)
{
int shift = cur_y - (LCD_HEIGHT-1);
xlcd_scroll_up(shift);
full_update = true;
cur_y -= shift;
last_pos -= shift;
}
else
{
cur_y -= LCD_HEIGHT;
}
}
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
if (cur_y > last_pos)
{
rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, d);
}
else
{
rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, LCD_HEIGHT - last_pos);
rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 1);
}
rb->lcd_set_drawmode(DRMODE_SOLID);
switch (osc.draw)
{
case DRAW_FILLED:
left = last_left;
right = last_right;
dl = (cur_left - left) / d;
dr = (cur_right - right) / d;
for (y = last_pos + 1; d > 0; y++, d--)
{
if (y == LCD_HEIGHT)
y = 0;
left += dl;
right += dr;
rb->lcd_hline(LCD_WIDTH/2-1,
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
rb->lcd_hline(LCD_WIDTH/2+1,
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
}
break;
case DRAW_LINE:
if (cur_y > last_pos)
{
rb->lcd_drawline(
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
);
rb->lcd_drawline(
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
);
}
else
{
left = last_left
+ (LCD_HEIGHT - last_pos) * (last_left - cur_left) / d;
right = last_right
+ (LCD_HEIGHT - last_pos) * (last_right - cur_right) / d;
rb->lcd_drawline(
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), LCD_HEIGHT
);
rb->lcd_drawline(
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT
);
if (cur_y > 0)
{
rb->lcd_drawline(
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), 0,
LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
);
rb->lcd_drawline(
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), 0,
LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
);
}
}
break;
case DRAW_PIXEL:
left = last_left;
right = last_right;
dl = (cur_left - left) / d;
dr = (cur_right - right) / d;
for (y = last_pos + 1; d > 0; y++, d--)
{
if (y == LCD_HEIGHT)
y = 0;
left += dl;
right += dr;
rb->lcd_drawpixel(LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
rb->lcd_drawpixel(LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
}
break;
}
last_left = cur_left;
last_right = cur_right;
if (displaymsg)
{
last_pos -= font_height - 1;
rb->lcd_putsxy(0, last_pos, message);
displaymsg = false;
if (last_pos < 0)
last_pos = 0;
}
if (full_update)
{
rb->lcd_update();
}
else
{
#if LCD_DEPTH > 1 /* cursor bar */
rb->lcd_set_foreground(CURSOR_COLOR);
rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
rb->lcd_set_foreground(GRAPH_COLOR);
#else
rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
rb->lcd_set_drawmode(DRMODE_SOLID);
#endif
if (cur_y > last_pos)
{
rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
}
else
{
rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
}
}
last_pos = cur_y;
}
static void cleanup(void)
{
#if LCD_DEPTH > 1
rb->lcd_set_foreground(LCD_DEFAULT_FG);
rb->lcd_set_background(LCD_DEFAULT_BG);
#endif
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
}
enum plugin_status plugin_start(const void* parameter)
{
int button, vol;
#if defined(OSCILLOSCOPE_DRAWMODE_PRE) || defined(OSCILLOSCOPE_ORIENTATION_PRE)
int lastbutton = BUTTON_NONE;
#endif
bool exit = false;
bool paused = false;
bool tell_speed;
(void)parameter;
atexit(cleanup);
configfile_load(cfg_filename, disk_config,
sizeof(disk_config) / sizeof(disk_config[0]),
CFGFILE_MINVERSION);
rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */
#if LCD_DEPTH > 1
rb->lcd_set_foreground(GRAPH_COLOR);
rb->lcd_set_background(BACKG_COLOR);
rb->lcd_set_backdrop(NULL);
rb->lcd_clear_display();
rb->lcd_update();
#endif
/* Turn off backlight timeout */
backlight_ignore_timeout();
rb->lcd_getstringsize("A", NULL, &font_height);
while (!exit)
{
if (!paused)
{
int left, right;
rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
left = rb->mas_codec_readreg(0xC);
right = rb->mas_codec_readreg(0xD);
#elif (CONFIG_CODEC == SWCODEC)
rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
&left, &right);
#endif
if (osc.orientation == OSC_HORIZ)
anim_horizontal(left, right);
else
anim_vertical(left, right);
}
tell_speed = false;
button = rb->button_get(paused);
switch (button)
{
#ifdef OSCILLOSCOPE_RC_QUIT
case OSCILLOSCOPE_RC_QUIT:
#endif
case OSCILLOSCOPE_QUIT:
exit = true;
break;
case OSCILLOSCOPE_ADVMODE:
if (++osc.advance >= MAX_ADV)
osc.advance = 0;
break;
case OSCILLOSCOPE_DRAWMODE:
#ifdef OSCILLOSCOPE_DRAWMODE_PRE
if (lastbutton != OSCILLOSCOPE_DRAWMODE_PRE)
break;
#endif
if (++osc.draw >= MAX_DRAW)
osc.draw = 0;
break;
case OSCILLOSCOPE_ORIENTATION:
#ifdef OSCILLOSCOPE_ORIENTATION_PRE
if (lastbutton != OSCILLOSCOPE_ORIENTATION_PRE)
break;
#endif
if (++osc.orientation >= MAX_OSC)
osc.orientation = 0;
last_pos = 0;
last_tick = 0;
displaymsg = false;
rb->lcd_clear_display();
rb->lcd_update();
break;
case OSCILLOSCOPE_PAUSE:
paused = !paused;
last_tick = 0;
break;
case OSCILLOSCOPE_SPEED_UP:
case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
if (osc.delay > 1)
{
osc.delay--;
tell_speed = true;
}
break;
case OSCILLOSCOPE_SPEED_DOWN:
case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
osc.delay++;
tell_speed = true;
break;
case OSCILLOSCOPE_VOL_UP:
case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
vol = rb->global_settings->volume;
if (vol < rb->sound_max(SOUND_VOLUME))
{
vol++;
rb->sound_set(SOUND_VOLUME, vol);
rb->global_settings->volume = vol;
}
break;
case OSCILLOSCOPE_VOL_DOWN:
case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
vol = rb->global_settings->volume;
if (vol > rb->sound_min(SOUND_VOLUME))
{
vol--;
rb->sound_set(SOUND_VOLUME, vol);
rb->global_settings->volume = vol;
}
break;
default:
exit_on_usb(button);
break;
}
#if defined(OSCILLOSCOPE_DRAWMODE_PRE) || defined(OSCILLOSCOPE_ORIENTATION_PRE)
if (button != BUTTON_NONE)
lastbutton = button;
#endif
if (tell_speed)
{
rb->snprintf(message, sizeof(message), "%s%d",
(osc.orientation == OSC_VERT) ? "Speed: " : "",
100 / osc.delay);
displaymsg = true;
}
}
if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
{
rb->memcpy(&osc_disk, &osc, sizeof(osc));
configfile_save(cfg_filename, disk_config,
sizeof(disk_config) / sizeof(disk_config[0]),
CFGFILE_VERSION);
}
return PLUGIN_OK;
}