summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/oscilloscope.c337
1 files changed, 249 insertions, 88 deletions
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index de85dc3..e215f78 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -9,7 +9,7 @@
*
* Oscilloscope, with the thought-to-be impossible horizontal aspect!
*
-* Copyright (C) 2004 Jens Arnold
+* Copyright (C) 2004-2006 Jens Arnold
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
@@ -19,134 +19,269 @@
*
****************************************************************************/
-#ifndef SIMULATOR /* not for simulator by now */
#include "plugin.h"
-#ifdef HAVE_LCD_BITMAP /* and also not for the Player */
-#if CONFIG_CODEC != SWCODEC /* only for MAS-targets */
+#ifdef HAVE_LCD_BITMAP
#include "xlcd.h"
PLUGIN_HEADER
/* The different drawing modes */
-#define DRAW_MODE_FILLED 0
-#define DRAW_MODE_OUTLINE 1
-#define DRAW_MODE_PIXEL 2
-#define DRAW_MODE_COUNT 3
+#define OSC_MODE_FILLED 0
+#define OSC_MODE_OUTLINE 1
+#define OSC_MODE_PIXEL 2
+#define OSC_MODE_COUNT 3
#define MAX_PEAK 0x8000
/* variable button definitions */
#if CONFIG_KEYPAD == RECORDER_PAD
#define OSCILLOSCOPE_QUIT BUTTON_OFF
-#define OSCILLOSCOPE_SCROLL BUTTON_F1
-#define OSCILLOSCOPE_MODE BUTTON_F2
+#define OSCILLOSCOPE_MODE BUTTON_F1
+#define OSCILLOSCOPE_SCROLL BUTTON_F2
#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 == ONDIO_PAD
#define OSCILLOSCOPE_QUIT BUTTON_OFF
-#define OSCILLOSCOPE_SCROLL BUTTON_RIGHT
-#define OSCILLOSCOPE_MODE BUTTON_MENU
-#define OSCILLOSCOPE_PAUSE BUTTON_LEFT
+#define OSCILLOSCOPE_MODE_PRE BUTTON_MENU
+#define OSCILLOSCOPE_MODE (BUTTON_MENU | BUTTON_REL)
+#define OSCILLOSCOPE_SCROLL (BUTTON_MENU | BUTTON_RIGHT)
+#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_MODE BUTTON_SELECT
+#define OSCILLOSCOPE_SCROLL BUTTON_MODE
+#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
+
+#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define OSCILLOSCOPE_MODE (BUTTON_SELECT | BUTTON_PLAY)
+#define OSCILLOSCOPE_SCROLL (BUTTON_SELECT | BUTTON_RIGHT)
+#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_MODE BUTTON_SELECT
+#define OSCILLOSCOPE_SCROLL BUTTON_MENU
+#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 == IAUDIO_X5_PAD
+#define OSCILLOSCOPE_QUIT BUTTON_POWER
+#define OSCILLOSCOPE_MODE BUTTON_SELECT
+#define OSCILLOSCOPE_SCROLL BUTTON_REC
+#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
#endif
-/* unsigned 16 bit multiplication (a single instruction on the SH) */
-#define MULU16(a, b) ((unsigned long) \
- (((unsigned short) (a)) * ((unsigned short) (b))))
+#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
+#define mas_codec_readreg(x) rand()%MAX_PEAK
+#endif
/* global variables */
-struct plugin_api* rb; /* global api struct pointer */
-int x = 0;
-int draw_mode = DRAW_MODE_FILLED;
-bool scroll = true;
-int left_val;
-int right_val;
-bool new_val = false;
+struct plugin_api* rb; /* global api struct pointer */
-/* prototypes */
-
-void lcd_scroll_left(int count, bool black_border);
-void timer_isr(void);
-void cleanup(void *parameter);
-enum plugin_status plugin_start(struct plugin_api* api, void* parameter);
+int osc_mode = OSC_MODE_FILLED;
+int osc_delay = 1; /* in ticks */
+bool osc_scroll = true;
+long last_tick = 0;
/* implementation */
-void timer_isr(void)
+void animate(int cur_left, int cur_right)
{
+ static int last_x = 0;
static int last_left, last_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 (new_val)
- {
- if ((unsigned)x >= LCD_WIDTH)
+ 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_x + d;
+
+ if (cur_x >= LCD_WIDTH)
+ {
+ if (osc_scroll) /* scroll */
+ {
+ int shift = cur_x - (LCD_WIDTH-1);
+ xlcd_scroll_left(shift);
+ full_update = true;
+ cur_x -= shift;
+ last_x -= shift;
+ }
+ else /* wrap */
{
- if (scroll)
+ cur_x -= LCD_WIDTH;
+ }
+ }
+ rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
+
+ if (cur_x > last_x)
+ {
+ rb->lcd_fillrect(last_x + 1, 0, d + 2, LCD_HEIGHT);
+ }
+ else
+ {
+ rb->lcd_fillrect(last_x + 1, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT);
+ rb->lcd_fillrect(0, 0, cur_x + 2, LCD_HEIGHT);
+ }
+ rb->lcd_set_drawmode(DRMODE_SOLID);
+
+ switch (osc_mode)
+ {
+ case OSC_MODE_FILLED:
+ left = last_left;
+ right = last_right;
+ dl = (cur_left - left) / d;
+ dr = (cur_right - right) / d;
+
+ for (x = last_x + 1; d > 0; x++, d--)
{
- xlcd_scroll_left(1);
- x = LCD_WIDTH-1;
- full_update = true;
+ 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 OSC_MODE_OUTLINE:
+ if (cur_x > last_x)
+ {
+ rb->lcd_drawline(
+ last_x, 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_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16),
+ cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_right) >> 16)
+ );
}
else
- x = 0;
- }
+ {
+ left = last_left
+ + (LCD_WIDTH - last_x) * (last_left - cur_left) / d;
+ right = last_right
+ + (LCD_WIDTH - last_x) * (last_right - cur_right) / d;
+
+ rb->lcd_drawline(
+ last_x, 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_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16),
+ LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16)
+ );
+ 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 OSC_MODE_PIXEL:
+ left = last_left;
+ right = last_right;
+ dl = (cur_left - left) / d;
+ dr = (cur_right - right) / d;
+
+ for (x = last_x + 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;
- rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
- rb->lcd_vline(x, 0, LCD_HEIGHT-1);
- rb->lcd_set_drawmode(DRMODE_SOLID);
+ }
+ last_left = cur_left;
+ last_right = cur_right;
- switch (draw_mode)
+ if (full_update)
+ {
+ rb->lcd_update();
+ }
+ else
+ {
+ if (cur_x > last_x)
{
- case DRAW_MODE_FILLED:
- rb->lcd_vline(x, LCD_HEIGHT/2+1, LCD_HEIGHT/2+1 + left_val);
- rb->lcd_vline(x, LCD_HEIGHT/2-1, LCD_HEIGHT/2-1 - right_val);
- break;
-
- case DRAW_MODE_OUTLINE:
- if (x > 0)
- {
- rb->lcd_drawline(x - 1, LCD_HEIGHT/2+1 + last_left,
- x, LCD_HEIGHT/2+1 + left_val);
- rb->lcd_drawline(x - 1, LCD_HEIGHT/2-1 - last_right,
- x, LCD_HEIGHT/2-1 - right_val);
- break;
- }
- /* else fall through */
-
- case DRAW_MODE_PIXEL:
- rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + left_val);
- rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - right_val);
- break;
+ rb->lcd_update_rect(last_x, 0, cur_x - last_x + 2, LCD_HEIGHT);
}
-
- if (full_update)
- rb->lcd_update();
else
- rb->lcd_update_rect(MAX(x - 1, 0), 0, 2, LCD_HEIGHT);
-
- last_left = left_val;
- last_right = right_val;
- x++;
- new_val = false;
+ {
+ rb->lcd_update_rect(last_x, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT);
+ rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
+ }
}
+ last_x = cur_x;
}
void cleanup(void *parameter)
{
(void)parameter;
-
- rb->timer_unregister();
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(LCD_DEFAULT_FG);
+ rb->lcd_set_background(LCD_DEFAULT_BG);
+ rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
+#endif
}
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
int button, vol;
+ int lastbutton = BUTTON_NONE;
bool exit = false;
bool paused = false;
@@ -155,18 +290,30 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
xlcd_init(rb);
- rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr);
-
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(LCD_RGBPACK(128, 255, 0));
+ rb->lcd_set_background(LCD_BLACK);
+ rb->lcd_clear_display();
+ rb->lcd_update();
+ rb->backlight_set_timeout(1); /* keep the light on */
+#endif
+
while (!exit)
{
if (!paused)
{
- /* read the volume info from MAS */
- left_val = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_HEIGHT/2-2));
- right_val = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_HEIGHT/2-2));
- new_val = true;
+ 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->pcm_calculate_peaks(&left, &right);
+#endif
+ animate(left, right);
}
- rb->yield();
button = rb->button_get(paused);
switch (button)
@@ -176,18 +323,34 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
break;
case OSCILLOSCOPE_SCROLL:
- scroll = !scroll;
+ osc_scroll = !osc_scroll;
break;
case OSCILLOSCOPE_MODE:
- draw_mode++;
- draw_mode = draw_mode % DRAW_MODE_COUNT;
+#ifdef OSCILLOSCOPE_MODE_PRE
+ if (lastbutton != OSCILLOSCOPE_MODE_PRE)
+ break;
+#endif
+ if (++osc_mode >= OSC_MODE_COUNT)
+ osc_mode = 0;
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--;
break;
+ case OSCILLOSCOPE_SPEED_DOWN:
+ case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
+ osc_delay++;
+ break;
+
case OSCILLOSCOPE_VOL_UP:
case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
vol = rb->global_settings->volume;
@@ -216,12 +379,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
return PLUGIN_USB_CONNECTED;
break;
}
-
+ if (button != BUTTON_NONE)
+ lastbutton = button;
}
-
cleanup(NULL);
return PLUGIN_OK;
}
-#endif /* if using MAS */
#endif /* if HAVE_LCD_BITMAP */
-#endif /* SIMULATOR */