summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2004-11-07 10:31:39 +0000
committerJens Arnold <amiconn@rockbox.org>2004-11-07 10:31:39 +0000
commitdb14d8e50cbfcdc1e4c8dd15894d678a29df67aa (patch)
tree4082fa815948ccbc095a6f969f5f29b9985ec9ad
parent8ed50037e4c5b0e622045eb58c8ab54aad4477fc (diff)
New plugin: Oscilloscope, with the thought-to-be impossible horizontal aspect
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5389 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/oscilloscope.c278
2 files changed, 279 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index a42b919a8d..775e20e9ee 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -24,6 +24,7 @@ mandelbrot.c
minesweeper.c
mosaique.c
oscillograph.c
+oscilloscope.c
pong.c
rockblox.c
sliding_puzzle.c
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
new file mode 100644
index 0000000000..b37f473491
--- /dev/null
+++ b/apps/plugins/oscilloscope.c
@@ -0,0 +1,278 @@
+/***************************************************************************
+* __________ __ ___.
+* Open \______ \ ____ ____ | | _\_ |__ _______ ___
+* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+* \/ \/ \/ \/ \/
+* $Id$
+*
+* Oscilloscope, with the thought-to-be impossible horizontal aspect!
+*
+* Copyright (C) 2004 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.
+*
+* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+* KIND, either express or implied.
+*
+****************************************************************************/
+
+#ifndef SIMULATOR /* not for simulator by now */
+#include "plugin.h"
+
+#ifdef HAVE_LCD_BITMAP /* and also not for the Player */
+
+/* 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 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_PAUSE BUTTON_PLAY
+#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_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))))
+
+/* global variables */
+
+struct plugin_api* rb; /* global api struct pointer */
+int x;
+int draw_mode;
+bool scroll;
+int left_val;
+int right_val;
+bool new_val;
+
+/* 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);
+
+/* implementation */
+
+void lcd_scroll_left(int count, bool black_border)
+{
+ int by;
+ unsigned filler;
+ unsigned char *ptr;
+
+ if ((unsigned) count >= LCD_WIDTH)
+ return;
+
+ filler = black_border ? 0xFF : 0;
+
+ for (by = 0; by < (LCD_HEIGHT/8); by++)
+ {
+ ptr = rb->lcd_framebuffer + MULU16(LCD_WIDTH, by);
+ asm volatile (
+ "mov %0,r1 \n" /* check if both source... */
+ "or %2,r1 \n" /* ...and offset are even */
+ "shlr r1 \n" /* -> lsb = 0 */
+ "bf .sl_start2 \n" /* -> copy word-wise */
+
+ "add #-1,%2 \n" /* copy byte-wise */
+ ".sl_loop1: \n"
+ "mov.b @%0+,r1 \n"
+ "mov.b r1,@(%2,%0) \n"
+ "cmp/hi %0,%1 \n"
+ "bt .sl_loop1 \n"
+
+ "bra .sl_end \n"
+ "nop \n"
+
+ ".sl_start2: \n" /* copy word-wise */
+ "add #-2,%2 \n"
+ ".sl_loop2: \n"
+ "mov.w @%0+,r1 \n"
+ "mov.w r1,@(%2,%0) \n"
+ "cmp/hi %0,%1 \n"
+ "bt .sl_loop2 \n"
+
+ ".sl_end: \n"
+ : /* outputs */
+ : /* inputs */
+ /* %0 */ "r"(ptr + count),
+ /* %1 */ "r"(ptr + LCD_WIDTH),
+ /* %2 */ "z"(-count)
+ : /* clobbers */
+ "r1"
+ );
+
+ rb->memset(ptr + LCD_WIDTH - count, filler, count);
+ }
+}
+
+void timer_isr(void)
+{
+ static int last_left, last_right;
+ bool full_update = false;
+
+ if (new_val)
+ {
+ if ((unsigned)x >= LCD_WIDTH)
+ {
+ if (scroll)
+ {
+ lcd_scroll_left(1, false);
+ x = LCD_WIDTH-1;
+ full_update = true;
+ }
+ else
+ x = 0;
+ }
+
+ rb->lcd_clearline(x, 0, x, LCD_HEIGHT-1);
+
+ switch (draw_mode)
+ {
+ case DRAW_MODE_FILLED:
+ rb->lcd_drawline(x, LCD_HEIGHT/2+1,
+ x, LCD_HEIGHT/2+1 + left_val);
+ rb->lcd_drawline(x, LCD_HEIGHT/2-1,
+ x, 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;
+ }
+
+ 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;
+ }
+}
+
+void cleanup(void *parameter)
+{
+ (void)parameter;
+
+ rb->plugin_unregister_timer();
+}
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ int button, vol;
+ bool exit = false;
+ bool paused = false;
+
+ TEST_PLUGIN_API(api);
+ (void)parameter;
+ rb = api;
+
+ x = 0;
+ draw_mode = DRAW_MODE_FILLED;
+ scroll = true;
+ new_val = false;
+
+ rb->plugin_register_timer(FREQ / 67, 1, timer_isr);
+
+ 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;
+ }
+ rb->yield();
+
+ button = rb->button_get(false);
+ switch (button)
+ {
+ case OSCILLOSCOPE_QUIT:
+ exit = true;
+ break;
+
+ case OSCILLOSCOPE_SCROLL:
+ scroll = !scroll;
+ break;
+
+ case OSCILLOSCOPE_MODE:
+ draw_mode++;
+ draw_mode = draw_mode % DRAW_MODE_COUNT;
+ break;
+
+ case OSCILLOSCOPE_PAUSE:
+ paused = !paused;
+ break;
+
+ case OSCILLOSCOPE_VOL_UP:
+ case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
+ vol = rb->global_settings->volume;
+ if (vol < 100)
+ {
+ vol++;
+ rb->mpeg_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 > 0)
+ {
+ vol--;
+ rb->mpeg_sound_set(SOUND_VOLUME, vol);
+ rb->global_settings->volume = vol;
+ }
+ break;
+
+ default:
+ if (rb->default_event_handler_ex(button, cleanup, NULL)
+ == SYS_USB_CONNECTED)
+ return PLUGIN_USB_CONNECTED;
+ break;
+ }
+
+ }
+
+ cleanup(NULL);
+ return PLUGIN_OK;
+}
+#endif
+#endif