diff options
-rw-r--r-- | apps/demo_menu.c | 4 | ||||
-rw-r--r-- | apps/recorder/oscillograph.c | 201 | ||||
-rw-r--r-- | firmware/drivers/lcd.c | 17 | ||||
-rw-r--r-- | firmware/drivers/lcd.h | 1 |
4 files changed, 223 insertions, 0 deletions
diff --git a/apps/demo_menu.c b/apps/demo_menu.c index de625c5821..23cd7d1cb5 100644 --- a/apps/demo_menu.c +++ b/apps/demo_menu.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | extern Menu bounce(void); | 36 | extern Menu bounce(void); |
37 | extern Menu snow(void); | 37 | extern Menu snow(void); |
38 | extern Menu oscillograph(void); | ||
38 | 39 | ||
39 | Menu demo_menu(void) | 40 | Menu demo_menu(void) |
40 | { | 41 | { |
@@ -44,6 +45,9 @@ Menu demo_menu(void) | |||
44 | struct menu_items items[] = { | 45 | struct menu_items items[] = { |
45 | { str(LANG_BOUNCE), bounce }, | 46 | { str(LANG_BOUNCE), bounce }, |
46 | { str(LANG_SNOW), snow }, | 47 | { str(LANG_SNOW), snow }, |
48 | #ifndef SIMULATOR | ||
49 | { "Oscillograph", oscillograph }, | ||
50 | #endif | ||
47 | }; | 51 | }; |
48 | 52 | ||
49 | m=menu_init( items, sizeof items / sizeof(struct menu_items) ); | 53 | m=menu_init( items, sizeof items / sizeof(struct menu_items) ); |
diff --git a/apps/recorder/oscillograph.c b/apps/recorder/oscillograph.c new file mode 100644 index 0000000000..c3b76c4626 --- /dev/null +++ b/apps/recorder/oscillograph.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 Philipp Pertermann | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <stdlib.h> | ||
21 | #include <sprintf.h> | ||
22 | #include "menu.h" | ||
23 | #include "lcd.h" | ||
24 | #include "button.h" | ||
25 | #include "mas.h" | ||
26 | #include "system.h" | ||
27 | |||
28 | /* The different drawing modes */ | ||
29 | #define DRAW_MODE_FILLED 0 | ||
30 | #define DRAW_MODE_OUTLINE 1 | ||
31 | #define DRAW_MODE_PIXEL 2 | ||
32 | #define DRAW_MODE_COUNT 3 | ||
33 | |||
34 | #define MAX_PEAK 0x8000 | ||
35 | |||
36 | /* number of ticks between two volume samples */ | ||
37 | static int speed = 1; | ||
38 | /* roll == true -> lcd rolls */ | ||
39 | static bool roll = true; | ||
40 | /* see DRAW_MODE_XXX constants for valid values */ | ||
41 | static int drawMode = DRAW_MODE_FILLED; | ||
42 | |||
43 | /** | ||
44 | * Displays a vertically scrolling oscillosgraph using | ||
45 | * hardware scrolling of the display. The user can change | ||
46 | * speed | ||
47 | */ | ||
48 | Menu oscillograph(void) | ||
49 | { | ||
50 | /* stores current volume value left */ | ||
51 | int left; | ||
52 | /* stores current volume value right */ | ||
53 | int right; | ||
54 | /* specifies the current position on the lcd */ | ||
55 | int y = LCD_WIDTH - 1; | ||
56 | |||
57 | /* only needed when drawing lines */ | ||
58 | int lastLeft = 0; | ||
59 | int lastRight = 0; | ||
60 | int lasty = 0; | ||
61 | |||
62 | bool exit = false; | ||
63 | |||
64 | /* the main loop */ | ||
65 | while (!exit) { | ||
66 | |||
67 | /* read the volume info from MAS */ | ||
68 | left = mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_WIDTH / 2 - 2)); | ||
69 | right = mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_WIDTH / 2 - 2)); | ||
70 | |||
71 | /* delete current line */ | ||
72 | lcd_clearline(0, y, LCD_WIDTH-1, y); | ||
73 | |||
74 | switch (drawMode) { | ||
75 | case DRAW_MODE_FILLED: | ||
76 | lcd_drawline(LCD_WIDTH / 2 + 1 , y, | ||
77 | LCD_WIDTH / 2 + 1 + right, y); | ||
78 | lcd_drawline(LCD_WIDTH / 2 - 1 , y, | ||
79 | LCD_WIDTH / 2 - 1 -left , y); | ||
80 | break; | ||
81 | |||
82 | case DRAW_MODE_OUTLINE: | ||
83 | /* last position needed for lines */ | ||
84 | lasty = MAX(y-1, 0); | ||
85 | |||
86 | /* Here real lines were neccessary because | ||
87 | anything else was ugly. */ | ||
88 | lcd_drawline(LCD_WIDTH / 2 + right , y, | ||
89 | LCD_WIDTH / 2 + lastRight , lasty); | ||
90 | lcd_drawline(LCD_WIDTH / 2 - left , y, | ||
91 | LCD_WIDTH / 2 - lastLeft, lasty); | ||
92 | |||
93 | /* have to store the old values for drawing lines | ||
94 | the next time */ | ||
95 | lastRight = right; | ||
96 | lastLeft = left; | ||
97 | break; | ||
98 | |||
99 | case DRAW_MODE_PIXEL: | ||
100 | /* straight and simple */ | ||
101 | lcd_drawpixel(LCD_WIDTH / 2 + right, y); | ||
102 | lcd_drawpixel(LCD_WIDTH / 2 - left, y); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | |||
107 | /* increment and adjust the drawing position */ | ||
108 | y++; | ||
109 | if (y >= LCD_HEIGHT) | ||
110 | y = 0; | ||
111 | |||
112 | /* I roll before update because otherwise the new | ||
113 | line would appear at the wrong end of the display */ | ||
114 | if (roll) | ||
115 | lcd_roll(y); | ||
116 | |||
117 | /* now finally make the new sample visible */ | ||
118 | lcd_update_rect(0, MAX(y-1, 0), LCD_WIDTH, 2); | ||
119 | |||
120 | /* There are two mechanisms to alter speed: | ||
121 | 1.) slowing down is achieved by increasing | ||
122 | the time waiting for user input. This | ||
123 | mechanism uses positive values. | ||
124 | 2.) speeding up is achieved by leaving out | ||
125 | the user input check for (-speed) volume | ||
126 | samples. For this mechanism negative values | ||
127 | are used. | ||
128 | */ | ||
129 | |||
130 | if (speed >= 0 || ((speed < 0) && (y % (-speed) == 0))) { | ||
131 | bool draw = false; | ||
132 | |||
133 | /* speed values > 0 slow the oszi down. By user input | ||
134 | speed might become < 1. If a value < 1 was | ||
135 | passed user input would be disabled. Thus | ||
136 | it must be ensured that at least 1 is passed. */ | ||
137 | |||
138 | /* react to user input */ | ||
139 | switch (button_get_w_tmo(MAX(speed, 1))) { | ||
140 | case BUTTON_UP: | ||
141 | speed++; | ||
142 | draw = true; | ||
143 | break; | ||
144 | |||
145 | case BUTTON_DOWN: | ||
146 | speed--; | ||
147 | draw = true; | ||
148 | break; | ||
149 | |||
150 | case BUTTON_PLAY: | ||
151 | /* pause the demo */ | ||
152 | button_get(true); | ||
153 | break; | ||
154 | |||
155 | case BUTTON_F1: | ||
156 | /* toggle rolling */ | ||
157 | roll = !roll; | ||
158 | break; | ||
159 | |||
160 | case BUTTON_F2: | ||
161 | /* step through the display modes */ | ||
162 | drawMode ++; | ||
163 | drawMode = drawMode % DRAW_MODE_COUNT; | ||
164 | |||
165 | /* lcd buffer might be rolled so that | ||
166 | the transition from LCD_HEIGHT to 0 | ||
167 | takes place in the middle of the screen. | ||
168 | That produces ugly results in DRAW_MODE_OUTLINE | ||
169 | mode. If rolling is enabled this change will | ||
170 | be reverted before the next update anyway.*/ | ||
171 | lcd_roll(0); | ||
172 | break; | ||
173 | |||
174 | case BUTTON_F3: | ||
175 | speed = 1; | ||
176 | draw = true; | ||
177 | break; | ||
178 | |||
179 | case BUTTON_OFF: | ||
180 | exit = true; | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | if (draw) { | ||
185 | char buf[16]; | ||
186 | snprintf(buf, sizeof buf, "Speed: %d", -speed); | ||
187 | lcd_putsxy(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, buf, 0); | ||
188 | lcd_update_rect(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, | ||
189 | LCD_WIDTH, 8); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | /* restore to default roll position. | ||
195 | Looks funny if you forget to do this... */ | ||
196 | lcd_roll(0); | ||
197 | lcd_update(); | ||
198 | |||
199 | /* standard return */ | ||
200 | return MENU_OK; | ||
201 | } | ||
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c index 5240dfda42..8abc638175 100644 --- a/firmware/drivers/lcd.c +++ b/firmware/drivers/lcd.c | |||
@@ -1163,6 +1163,23 @@ static void scroll_thread(void) | |||
1163 | } | 1163 | } |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | #ifndef SIMULATOR | ||
1167 | #ifdef HAVE_LCD_BITMAP | ||
1168 | /** | ||
1169 | * Rolls up the lcd display by the specified amount of lines. | ||
1170 | * Lines that are rolled out over the top of the screen are | ||
1171 | * rolled in from the bottom again. This is a hardware | ||
1172 | * remapping only and all operations on the lcd are affected. | ||
1173 | * -> | ||
1174 | * @param int lines - The number of lines that are rolled. | ||
1175 | * The value must be 0 <= pixels < LCD_HEIGHT. | ||
1176 | */ | ||
1177 | void lcd_roll(int lines) | ||
1178 | { | ||
1179 | lcd_write(true, LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1))); | ||
1180 | } | ||
1181 | #endif | ||
1182 | #endif | ||
1166 | 1183 | ||
1167 | /* ----------------------------------------------------------------- | 1184 | /* ----------------------------------------------------------------- |
1168 | * local variables: | 1185 | * local variables: |
diff --git a/firmware/drivers/lcd.h b/firmware/drivers/lcd.h index 23b3d75e76..8c89d4c057 100644 --- a/firmware/drivers/lcd.h +++ b/firmware/drivers/lcd.h | |||
@@ -116,6 +116,7 @@ extern void lcd_clearline( int x1, int y1, int x2, int y2 ); | |||
116 | extern void lcd_drawpixel(int x, int y); | 116 | extern void lcd_drawpixel(int x, int y); |
117 | extern void lcd_clearpixel(int x, int y); | 117 | extern void lcd_clearpixel(int x, int y); |
118 | extern void lcd_invertpixel(int x, int y); | 118 | extern void lcd_invertpixel(int x, int y); |
119 | extern void lcd_roll(int pixels); | ||
119 | 120 | ||
120 | #endif /* CHARCELLS / BITMAP */ | 121 | #endif /* CHARCELLS / BITMAP */ |
121 | 122 | ||