From 78e4f4d1b14eea3a78f1af267b6fc100c5297b25 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Fri, 10 Mar 2006 00:18:58 +0000 Subject: Oscilloscope: Added vertical orientation option. Flipped horizontal mode to show left channel on top. Vertical mode prints speed messages. Set default speed to 50 instead of 100. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8986 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/oscilloscope.c | 288 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 245 insertions(+), 43 deletions(-) (limited to 'apps') diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c index e215f78efe..2d1425b5b7 100644 --- a/apps/plugins/oscilloscope.c +++ b/apps/plugins/oscilloscope.c @@ -39,6 +39,7 @@ PLUGIN_HEADER #define OSCILLOSCOPE_QUIT BUTTON_OFF #define OSCILLOSCOPE_MODE BUTTON_F1 #define OSCILLOSCOPE_SCROLL BUTTON_F2 +#define OSCILLOSCOPE_ORIENTATION BUTTON_F3 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT @@ -50,6 +51,7 @@ PLUGIN_HEADER #define OSCILLOSCOPE_MODE_PRE BUTTON_MENU #define OSCILLOSCOPE_MODE (BUTTON_MENU | BUTTON_REL) #define OSCILLOSCOPE_SCROLL (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 @@ -60,6 +62,7 @@ PLUGIN_HEADER #define OSCILLOSCOPE_QUIT BUTTON_OFF #define OSCILLOSCOPE_MODE BUTTON_SELECT #define OSCILLOSCOPE_SCROLL BUTTON_MODE +#define OSCILLOSCOPE_ORIENTATION BUTTON_REC #define OSCILLOSCOPE_PAUSE BUTTON_ON #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT @@ -70,6 +73,7 @@ PLUGIN_HEADER #define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU) #define OSCILLOSCOPE_MODE (BUTTON_SELECT | BUTTON_PLAY) #define OSCILLOSCOPE_SCROLL (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 @@ -79,7 +83,8 @@ PLUGIN_HEADER #elif (CONFIG_KEYPAD == GIGABEAT_PAD) #define OSCILLOSCOPE_QUIT BUTTON_POWER #define OSCILLOSCOPE_MODE BUTTON_SELECT -#define OSCILLOSCOPE_SCROLL BUTTON_MENU +#define OSCILLOSCOPE_SCROLL BUTTON_DOWN +#define OSCILLOSCOPE_ORIENTATION BUTTON_UP #define OSCILLOSCOPE_PAUSE BUTTON_A #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT @@ -88,8 +93,10 @@ PLUGIN_HEADER #elif CONFIG_KEYPAD == IAUDIO_X5_PAD #define OSCILLOSCOPE_QUIT BUTTON_POWER -#define OSCILLOSCOPE_MODE BUTTON_SELECT +#define OSCILLOSCOPE_MODE_PRE BUTTON_SELECT +#define OSCILLOSCOPE_MODE (BUTTON_SELECT | BUTTON_REL) #define OSCILLOSCOPE_SCROLL BUTTON_REC +#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT) #define OSCILLOSCOPE_PAUSE BUTTON_PLAY #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT @@ -102,22 +109,33 @@ PLUGIN_HEADER #define mas_codec_readreg(x) rand()%MAX_PEAK #endif +/* prototypes */ + +void anim_horizontal(int, int); +void anim_vertical(int, int); + /* global variables */ -struct plugin_api* rb; /* global api struct pointer */ +struct plugin_api* rb; /* global api struct pointer */ int osc_mode = OSC_MODE_FILLED; -int osc_delay = 1; /* in ticks */ +int osc_delay = 2; /* in ticks */ bool osc_scroll = true; -long last_tick = 0; +void (*anim)(int, int) = anim_horizontal; + +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 */ -void animate(int cur_left, int cur_right) +void anim_horizontal(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; @@ -135,7 +153,7 @@ void animate(int cur_left, int cur_right) last_right = cur_right; return; } - cur_x = last_x + d; + cur_x = last_pos + d; if (cur_x >= LCD_WIDTH) { @@ -145,7 +163,7 @@ void animate(int cur_left, int cur_right) xlcd_scroll_left(shift); full_update = true; cur_x -= shift; - last_x -= shift; + last_pos -= shift; } else /* wrap */ { @@ -154,13 +172,13 @@ void animate(int cur_left, int cur_right) } rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - if (cur_x > last_x) + if (cur_x > last_pos) { - rb->lcd_fillrect(last_x + 1, 0, d + 2, LCD_HEIGHT); + rb->lcd_fillrect(last_pos + 1, 0, d + 2, LCD_HEIGHT); } else { - rb->lcd_fillrect(last_x + 1, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT); + rb->lcd_fillrect(last_pos + 1, 0, (LCD_WIDTH-1) - last_pos, LCD_HEIGHT); rb->lcd_fillrect(0, 0, cur_x + 2, LCD_HEIGHT); } rb->lcd_set_drawmode(DRMODE_SOLID); @@ -173,7 +191,7 @@ void animate(int cur_left, int cur_right) dl = (cur_left - left) / d; dr = (cur_right - right) / d; - for (x = last_x + 1; d > 0; x++, d--) + for (x = last_pos + 1; d > 0; x++, d--) { if (x == LCD_WIDTH) x = 0; @@ -181,47 +199,47 @@ void animate(int cur_left, int cur_right) 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)); + 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) + if (cur_x > last_pos) { 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) + 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_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16), - cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_right) >> 16) + 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_x) * (last_left - cur_left) / d; + + (LCD_WIDTH - last_pos) * (last_left - cur_left) / d; right = last_right - + (LCD_WIDTH - last_x) * (last_right - cur_right) / d; + + (LCD_WIDTH - last_pos) * (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) + 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_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16), - LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16) + 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) * left) >> 16), - cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_left) >> 16) + last_pos, 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) * right) >> 16), - cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_right) >> 16) + 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16), + cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16) ); } break; @@ -232,7 +250,7 @@ void animate(int cur_left, int cur_right) dl = (cur_left - left) / d; dr = (cur_right - right) / d; - for (x = last_x + 1; d > 0; x++, d--) + for (x = last_pos + 1; d > 0; x++, d--) { if (x == LCD_WIDTH) x = 0; @@ -240,8 +258,8 @@ void animate(int cur_left, int cur_right) 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)); + 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; @@ -255,17 +273,179 @@ void animate(int cur_left, int cur_right) } else { - if (cur_x > last_x) + if (cur_x > last_pos) { - rb->lcd_update_rect(last_x, 0, cur_x - last_x + 2, LCD_HEIGHT); + rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT); } else { - rb->lcd_update_rect(last_x, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT); + rb->lcd_update_rect(last_pos, 0, (LCD_WIDTH-1) - last_pos, LCD_HEIGHT); rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT); } } - last_x = cur_x; + last_pos = cur_x; +} + +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_scroll) /* scroll */ + { + int shift = cur_y - (LCD_HEIGHT-1); + xlcd_scroll_up(shift); + full_update = true; + cur_y -= shift; + last_pos -= shift; + } + else /* wrap */ + { + 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 + 2); + } + else + { + rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, (LCD_HEIGHT-1) - last_pos); + rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 2); + } + 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 (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 OSC_MODE_OUTLINE: + 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) * 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) * last_right) >> 16), last_pos, + LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT + ); + 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 OSC_MODE_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; + if (last_pos < 0) + last_pos = LCD_HEIGHT - font_height; + + rb->lcd_putsxy(0, last_pos, message); + displaymsg = false; + } + + if (full_update) + { + rb->lcd_update(); + } + else + { + 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-1) - last_pos); + rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2); + } + } + last_pos = cur_y; } void cleanup(void *parameter) @@ -284,6 +464,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) int lastbutton = BUTTON_NONE; bool exit = false; bool paused = false; + bool tell_speed; (void)parameter; rb = api; @@ -297,7 +478,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) rb->lcd_update(); rb->backlight_set_timeout(1); /* keep the light on */ #endif - + rb->lcd_getstringsize("A", NULL, &font_height); + while (!exit) { if (!paused) @@ -312,9 +494,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) #elif (CONFIG_CODEC == SWCODEC) rb->pcm_calculate_peaks(&left, &right); #endif - animate(left, right); + anim(left, right); } + tell_speed = false; button = rb->button_get(paused); switch (button) { @@ -334,6 +517,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) if (++osc_mode >= OSC_MODE_COUNT) osc_mode = 0; break; + + case OSCILLOSCOPE_ORIENTATION: + anim = (anim == anim_horizontal) ? anim_vertical : anim_horizontal; + last_pos = 0; + last_tick = 0; + displaymsg = false; + rb->lcd_clear_display(); + rb->lcd_update(); + break; case OSCILLOSCOPE_PAUSE: paused = !paused; @@ -343,12 +535,16 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 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: @@ -381,8 +577,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) } if (button != BUTTON_NONE) lastbutton = button; + + if (tell_speed) + { + rb->snprintf(message, sizeof(message), "Speed: %d", 100 / osc_delay); + displaymsg = true; + } } cleanup(NULL); return PLUGIN_OK; } -#endif /* if HAVE_LCD_BITMAP */ +#endif /* HAVE_LCD_BITMAP */ -- cgit v1.2.3