forked from len0rd/rockbox
Log scale for the VU meter, patch #897248 by Lee Pilgrim
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4323 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
50c2261756
commit
e392a1b6e6
1 changed files with 178 additions and 188 deletions
|
|
@ -1,232 +1,222 @@
|
|||
/***************************************************************************
|
||||
|
||||
* __________ __ ___.
|
||||
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
|
||||
* \/ \/ \/ \/ \/
|
||||
|
||||
*
|
||||
|
||||
* Copyright (C) 2003 Lee Pilgrim
|
||||
|
||||
*
|
||||
|
||||
* 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 /* The simulator dosen't have a MAS */
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
|
||||
|
||||
static struct plugin_api* rb;
|
||||
|
||||
/* This table is used to define x positions on a logarithmic (dBfs) scale.
|
||||
The formula I used to figure these out was log(x+1)*31.89293,
|
||||
where x was the original x position. */
|
||||
static unsigned char db_scale[] = {0,9.6,15.2,19.2,22.3,24.8,27,28.8,30.4,31.9,33.2,34.4,35.5,36.6,37.5,38.4,
|
||||
39.2,40,40.8,41.5,52.2,42.8,43.4,44,44.6,45.1,45.7,46.2,46.6,47.1,47.6,48,
|
||||
48.4,48.8,49.2,49.6,50,50.4,50.7,51.1,51.4,51.8,52.1,52.4,52.7,53,53.3,53.6,
|
||||
53.9,54.2,54.5,54.7,55,55.3,55.5,55.8,56};
|
||||
|
||||
/* Define's y positions, and makes it look like an arch, like a real needle would. */
|
||||
static unsigned char y_values[] = {32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17,
|
||||
17,17,17,17,17,18,18,18,18,18,19,19,20,21,21,22,22,23,24,24,25,26,27,28,29,30,31,32,
|
||||
32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17,
|
||||
17,17,17,17,17,18,18,18,18,18,19,19,20,21,21,22,22,23,24,24,25,26,27,28,29,30,31,32};
|
||||
|
||||
/* Linear mode bitmap icon. */
|
||||
static unsigned char mode_linear[] = {0xDF,0x10,0xD0,0x00,0xDF,0x00,0xDF,0x02,0xC4,0x08,0xDF,
|
||||
0x00,0xDF,0x15,0xD1,0x00,0xDE,0x05,0xDE,0x00,0xDF,0x05,
|
||||
0xDA};
|
||||
|
||||
/* Logarithmic (dBfs) mode bitmap icon. */
|
||||
static unsigned char mode_dbfs[] = {0xC8,0x14,0x14,0x1F,0x00,0xDF,0x15,0x15,0x0A,0xC0,0x1E,
|
||||
0x05,0x05,0xC0,0x16,0x15,0xD5,0x09,0xC0,0x00,0xF0,0x00,
|
||||
0xFE};
|
||||
|
||||
|
||||
#define MAX_PEAK 0x7FFF
|
||||
#define NEEDLE_BOTTOM_Y 54
|
||||
|
||||
#define LEFT_NEEDLE_BOTTOM_X 28
|
||||
int left_needle_top_y;
|
||||
int left_needle_top_x;
|
||||
int old_left_needle_top_x = 0;
|
||||
int left_needle_top_x_no_log;
|
||||
|
||||
#define RIGHT_NEEDLE_BOTTOM_X 84
|
||||
int right_needle_top_y;
|
||||
int right_needle_top_x;
|
||||
int old_right_needle_top_x = 56;
|
||||
int right_needle_top_x_no_log;
|
||||
|
||||
bool show_arch = true;
|
||||
bool use_log_scale = true;
|
||||
int needle_cover_mode = 1;
|
||||
|
||||
/* This draws everthing but the needles, needle covers, and the visible arch. */
|
||||
void draw_status_bar(void)
|
||||
{
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
rb->lcd_clear_display();
|
||||
|
||||
rb->lcd_drawline(0, 10, 111, 10);
|
||||
rb->lcd_putsxy(1, 1, "VU Meter");
|
||||
|
||||
if(use_log_scale)
|
||||
rb->lcd_bitmap(mode_dbfs, 88, 1, 23, 8, true);
|
||||
else
|
||||
rb->lcd_bitmap(mode_linear, 88, 1, 23, 8, true);
|
||||
|
||||
rb->lcd_putsxy(25, 56, "L");
|
||||
rb->lcd_putsxy(81, 56, "R");
|
||||
|
||||
/* The last line under the needle covers. */
|
||||
rb->lcd_drawline(0, 54, 111, 54);
|
||||
|
||||
rb->lcd_update();
|
||||
}
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
|
||||
{
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
|
||||
(void) parameter;
|
||||
|
||||
rb = api;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
I hope to make (left/right)_needle_top_y change some day (because it looks
|
||||
|
||||
like it is stretching) so that is why it is a int and not a #define.
|
||||
|
||||
*/
|
||||
|
||||
#define LEFT_NEEDLE_BOTTOM_X 28
|
||||
|
||||
#define LEFT_NEEDLE_BOTTOM_Y 53
|
||||
|
||||
int left_needle_top_x;
|
||||
|
||||
int left_needle_top_y = 18;
|
||||
|
||||
|
||||
|
||||
#define RIGHT_NEEDLE_BOTTOM_X 84
|
||||
|
||||
#define RIGHT_NEEDLE_BOTTOM_Y 53
|
||||
|
||||
int right_needle_top_x;
|
||||
|
||||
int right_needle_top_y = 18;
|
||||
|
||||
|
||||
draw_status_bar();
|
||||
|
||||
while (!PLUGIN_OK)
|
||||
|
||||
{
|
||||
left_needle_top_x_no_log =
|
||||
(rb->mas_codec_readreg(0xC) * 56 / MAX_PEAK);
|
||||
|
||||
/* These are to define how far the tip of the needles can go to the
|
||||
|
||||
left and right. The names are a bit confusing. The LEFT/RIGHT tells
|
||||
|
||||
which needle it is for, and the L/R at the end tells which side
|
||||
|
||||
of the needle. */
|
||||
|
||||
#define MAX_LEFT_L 2
|
||||
|
||||
#define MAX_LEFT_R 55
|
||||
|
||||
#define MAX_RIGHT_L 57
|
||||
|
||||
#define MAX_RIGHT_R 111
|
||||
|
||||
|
||||
|
||||
#define MAX_PEAK 0x7FFF
|
||||
|
||||
|
||||
|
||||
left_needle_top_x =
|
||||
|
||||
(rb->mas_codec_readreg(0xC) *
|
||||
|
||||
(MAX_LEFT_R - MAX_LEFT_L) / MAX_PEAK) + MAX_LEFT_L;
|
||||
|
||||
|
||||
|
||||
right_needle_top_x =
|
||||
|
||||
(rb->mas_codec_readreg(0xD) *
|
||||
|
||||
(MAX_RIGHT_R - MAX_RIGHT_L) / MAX_PEAK) + MAX_RIGHT_L;
|
||||
|
||||
|
||||
|
||||
/* Time to draw all of the display stuff!
|
||||
|
||||
Could I move some of these out of the loop so they don't have to
|
||||
|
||||
be re-drawn everytime, but still be displayed, or would that
|
||||
|
||||
improve performance any at all? */
|
||||
right_needle_top_x_no_log =
|
||||
(rb->mas_codec_readreg(0xD) * 56 / MAX_PEAK) + 56;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
|
||||
|
||||
rb->lcd_drawline(LEFT_NEEDLE_BOTTOM_X, LEFT_NEEDLE_BOTTOM_Y,
|
||||
|
||||
left_needle_top_x, left_needle_top_y);
|
||||
|
||||
rb->lcd_drawline(RIGHT_NEEDLE_BOTTOM_X, RIGHT_NEEDLE_BOTTOM_Y,
|
||||
|
||||
right_needle_top_x, right_needle_top_y);
|
||||
|
||||
|
||||
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
|
||||
rb->lcd_putsxy(30, 1, "VU Meter");
|
||||
|
||||
|
||||
|
||||
/* The first is the line under "VU Meter" and the second is under
|
||||
|
||||
the needles. */
|
||||
|
||||
rb->lcd_drawline(30, 9, 77, 9);
|
||||
|
||||
rb->lcd_drawline(0, 53, 111, 53);
|
||||
|
||||
|
||||
|
||||
/* These are the needle "covers" - we're going for that
|
||||
|
||||
"old fashioned" look */
|
||||
|
||||
|
||||
|
||||
/* The left needle cover - organized from the top line to the bottom */
|
||||
|
||||
rb->lcd_drawline(27, 48, 29, 48);
|
||||
|
||||
rb->lcd_drawline(25, 49, 31, 49);
|
||||
|
||||
rb->lcd_drawline(23, 50, 33, 50);
|
||||
|
||||
rb->lcd_drawline(22, 51, 34, 51);
|
||||
|
||||
rb->lcd_drawline(22, 52, 34, 52);
|
||||
|
||||
|
||||
|
||||
/* The right needle cover - organized from the top line to
|
||||
|
||||
the bottom */
|
||||
|
||||
rb->lcd_drawline(83, 48, 85, 48);
|
||||
|
||||
rb->lcd_drawline(81, 49, 87, 49);
|
||||
|
||||
rb->lcd_drawline(79, 50, 89, 50);
|
||||
|
||||
rb->lcd_drawline(78, 51, 90, 51);
|
||||
|
||||
rb->lcd_drawline(78, 52, 90, 52);
|
||||
|
||||
|
||||
|
||||
rb->lcd_update();
|
||||
|
||||
|
||||
|
||||
/* We must yield once in a while to make sure that the MPEG thread
|
||||
|
||||
isn't starved, but we use the shortest possible timeout for best
|
||||
|
||||
performance */
|
||||
|
||||
switch (rb->button_get_w_tmo(1))
|
||||
|
||||
if (use_log_scale)
|
||||
{
|
||||
|
||||
case BUTTON_OFF:
|
||||
|
||||
return PLUGIN_OK;
|
||||
|
||||
left_needle_top_x = db_scale[left_needle_top_x_no_log];
|
||||
right_needle_top_x = db_scale[right_needle_top_x_no_log-56]+56;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
left_needle_top_x = left_needle_top_x_no_log;
|
||||
right_needle_top_x = right_needle_top_x_no_log;
|
||||
}
|
||||
|
||||
/* Makes a decay on the needle. Todo: Make a user custom decay. */
|
||||
left_needle_top_x = (left_needle_top_x+old_left_needle_top_x*2)/3;
|
||||
right_needle_top_x = (right_needle_top_x+old_right_needle_top_x*2)/3;
|
||||
|
||||
old_left_needle_top_x = left_needle_top_x;
|
||||
old_right_needle_top_x = right_needle_top_x;
|
||||
|
||||
left_needle_top_y = y_values[left_needle_top_x];
|
||||
right_needle_top_y = y_values[right_needle_top_x];
|
||||
|
||||
/* Draws the needles */
|
||||
rb->lcd_drawline(LEFT_NEEDLE_BOTTOM_X, NEEDLE_BOTTOM_Y,
|
||||
left_needle_top_x, left_needle_top_y);
|
||||
|
||||
rb->lcd_drawline(RIGHT_NEEDLE_BOTTOM_X, NEEDLE_BOTTOM_Y,
|
||||
right_needle_top_x, right_needle_top_y);
|
||||
|
||||
if(needle_cover_mode == 1) /* Rounded needle cover. */
|
||||
{
|
||||
/* Left needle cover, top to bottom */
|
||||
rb->lcd_drawline(27, 49, 29, 49);
|
||||
rb->lcd_drawline(25, 50, 31, 50);
|
||||
rb->lcd_drawline(23, 51, 33, 51);
|
||||
rb->lcd_drawline(22, 52, 34, 52);
|
||||
rb->lcd_drawline(22, 53, 34, 53);
|
||||
|
||||
/* Right needle cover, top to bottom */
|
||||
rb->lcd_drawline(83, 49, 85, 49);
|
||||
rb->lcd_drawline(81, 50, 87, 50);
|
||||
rb->lcd_drawline(79, 51, 89, 51);
|
||||
rb->lcd_drawline(78, 52, 90, 52);
|
||||
rb->lcd_drawline(78, 53, 90, 53);
|
||||
}
|
||||
|
||||
else /* Pyramid needle cover. */
|
||||
{
|
||||
/* Left needle cover, top to bottom */
|
||||
rb->lcd_drawpixel(28, 49);
|
||||
rb->lcd_drawline(27, 50, 29, 50);
|
||||
rb->lcd_drawline(26, 51, 30, 51);
|
||||
rb->lcd_drawline(25, 52, 31, 52);
|
||||
rb->lcd_drawline(24, 53, 32, 53);
|
||||
|
||||
/* Right needle cover, top to bottom */
|
||||
rb->lcd_drawpixel(84, 49);
|
||||
rb->lcd_drawline(83, 50, 85, 50);
|
||||
rb->lcd_drawline(82, 51, 86, 51);
|
||||
rb->lcd_drawline(81, 52, 87, 52);
|
||||
rb->lcd_drawline(80, 53, 88, 53);
|
||||
}
|
||||
|
||||
if(show_arch)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<=112;i++)
|
||||
rb->lcd_drawpixel(i, (y_values[i])-2 );
|
||||
}
|
||||
|
||||
rb->lcd_update_rect(0,15,112,39);
|
||||
|
||||
switch (rb->button_get_w_tmo(1))
|
||||
{
|
||||
case BUTTON_OFF:
|
||||
return PLUGIN_OK;
|
||||
break;
|
||||
|
||||
case BUTTON_ON:
|
||||
rb->lcd_clear_display();
|
||||
rb->lcd_putsxy(1, 1, "Information:");
|
||||
rb->lcd_putsxy(2, 15, "OFF: Exit");
|
||||
rb->lcd_putsxy(2, 25, "ON: This Info");
|
||||
rb->lcd_putsxy(2, 35, "PLAY: Change Scale");
|
||||
rb->lcd_putsxy(2, 45, "F1: Needle Covers");
|
||||
rb->lcd_putsxy(2, 55, "F2: Visible Arch");
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ*3);
|
||||
draw_status_bar();
|
||||
break;
|
||||
|
||||
case BUTTON_PLAY:
|
||||
use_log_scale = !use_log_scale;
|
||||
draw_status_bar();
|
||||
break;
|
||||
|
||||
case BUTTON_F1:
|
||||
needle_cover_mode==2 ? needle_cover_mode=1 : needle_cover_mode++;
|
||||
break;
|
||||
|
||||
case BUTTON_F2:
|
||||
show_arch = !show_arch;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* HAVE_LCD_BITMAP */
|
||||
|
||||
#endif /* #ifdef HAVE_LCD_BITMAP */
|
||||
#endif /* #ifndef SIMULATOR */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue