summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs.h10
-rw-r--r--apps/lang/english.lang18
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/plugins/splitedit.c4
-rw-r--r--apps/recorder/peakmeter.c524
-rw-r--r--apps/recorder/peakmeter.h7
-rw-r--r--apps/recorder/radio.c7
-rw-r--r--apps/settings.c5
-rw-r--r--apps/settings.h1
-rw-r--r--apps/settings_menu.c33
-rw-r--r--apps/wps.c51
-rw-r--r--firmware/pcm_playback.c14
12 files changed, 307 insertions, 375 deletions
diff --git a/apps/codecs.h b/apps/codecs.h
index 4a4ccb229c..47cd5711ae 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -79,12 +79,12 @@
79#endif 79#endif
80 80
81/* increase this every time the api struct changes */ 81/* increase this every time the api struct changes */
82#define CODEC_API_VERSION 41 82#define CODEC_API_VERSION 42
83 83
84/* update this to latest version if a change to the api struct breaks 84/* update this to latest version if a change to the api struct breaks
85 backwards compatibility (and please take the opportunity to sort in any 85 backwards compatibility (and please take the opportunity to sort in any
86 new function which are "waiting" at the end of the function table) */ 86 new function which are "waiting" at the end of the function table) */
87#define CODEC_MIN_API_VERSION 40 87#define CODEC_MIN_API_VERSION 42
88 88
89/* codec return codes */ 89/* codec return codes */
90enum codec_status { 90enum codec_status {
@@ -314,8 +314,8 @@ struct codec_api {
314#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 314#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
315 unsigned short (*peak_meter_scale_value)(unsigned short val, 315 unsigned short (*peak_meter_scale_value)(unsigned short val,
316 int meterwidth); 316 int meterwidth);
317 void (*peak_meter_set_use_dbfs)(int use); 317 void (*peak_meter_set_use_dbfs)(bool use);
318 int (*peak_meter_get_use_dbfs)(void); 318 bool (*peak_meter_get_use_dbfs)(void);
319#endif 319#endif
320 320
321 /* new stuff at the end, sort into place next time 321 /* new stuff at the end, sort into place next time
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 75601c858b..6feac25ee8 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -878,21 +878,21 @@ voice: "Numeric"
878new: 878new:
879 879
880id: LANG_PM_PERFORMANCE 880id: LANG_PM_PERFORMANCE
881desc: in the peak meter menu 881desc: DEPRECATED
882eng: "Performance" 882eng: ""
883voice: "Performance" 883voice:
884new: 884new:
885 885
886id: LANG_PM_HIGH_PERFORMANCE 886id: LANG_PM_HIGH_PERFORMANCE
887desc: in the peak meter menu 887desc: DEPRECATED
888eng: "High performance" 888eng: ""
889voice: "High performance" 889voice: ""
890new: 890new:
891 891
892id: LANG_PM_ENERGY_SAVER 892id: LANG_PM_ENERGY_SAVER
893desc: in the peak meter menu 893desc: DEPRECATED
894eng: "Save Energy" 894eng: ""
895voice: "Save Energy" 895voice: ""
896new: 896new:
897 897
898id: LANG_PM_SCALE 898id: LANG_PM_SCALE
diff --git a/apps/plugin.h b/apps/plugin.h
index 7cda354808..8760162405 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -88,12 +88,12 @@
88#endif 88#endif
89 89
90/* increase this every time the api struct changes */ 90/* increase this every time the api struct changes */
91#define PLUGIN_API_VERSION 47 91#define PLUGIN_API_VERSION 48
92 92
93/* update this to latest version if a change to the api struct breaks 93/* update this to latest version if a change to the api struct breaks
94 backwards compatibility (and please take the opportunity to sort in any 94 backwards compatibility (and please take the opportunity to sort in any
95 new function which are "waiting" at the end of the function table) */ 95 new function which are "waiting" at the end of the function table) */
96#define PLUGIN_MIN_API_VERSION 47 96#define PLUGIN_MIN_API_VERSION 48
97 97
98/* plugin return codes */ 98/* plugin return codes */
99enum plugin_status { 99enum plugin_status {
@@ -413,8 +413,8 @@ struct plugin_api {
413#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 413#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
414 unsigned short (*peak_meter_scale_value)(unsigned short val, 414 unsigned short (*peak_meter_scale_value)(unsigned short val,
415 int meterwidth); 415 int meterwidth);
416 void (*peak_meter_set_use_dbfs)(int use); 416 void (*peak_meter_set_use_dbfs)(bool use);
417 int (*peak_meter_get_use_dbfs)(void); 417 bool (*peak_meter_get_use_dbfs)(void);
418#endif 418#endif
419#ifdef HAVE_LCD_BITMAP 419#ifdef HAVE_LCD_BITMAP
420 int (*read_bmp_file)(char* filename, int *get_width, int *get_height, 420 int (*read_bmp_file)(char* filename, int *get_width, int *get_height,
diff --git a/apps/plugins/splitedit.c b/apps/plugins/splitedit.c
index 142590d9e8..9317419c23 100644
--- a/apps/plugins/splitedit.c
+++ b/apps/plugins/splitedit.c
@@ -271,7 +271,7 @@ static void update_icons(void)
271 271
272#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 272#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
273 /* The scale icon */ 273 /* The scale icon */
274 rb->lcd_mono_bitmap(SCALE_BMP[rb->peak_meter_get_use_dbfs()], 274 rb->lcd_mono_bitmap(SCALE_BMP[rb->peak_meter_get_use_dbfs() ? 1 : 0],
275 2 *LCD_WIDTH/3 + LCD_WIDTH/3 / 2 - BMPWIDTH/2, LCD_HEIGHT - BMPHEIGHT, 275 2 *LCD_WIDTH/3 + LCD_WIDTH/3 / 2 - BMPWIDTH/2, LCD_HEIGHT - BMPHEIGHT,
276 BMPWIDTH, BMPHEIGHT); 276 BMPWIDTH, BMPHEIGHT);
277#else 277#else
@@ -1134,7 +1134,7 @@ unsigned long splitedit_editor(struct mp3entry * mp3_to_split,
1134 1134
1135 case SPLITEDIT_SCALE: 1135 case SPLITEDIT_SCALE:
1136#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 1136#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1137 rb->peak_meter_set_use_dbfs(rb->peak_meter_get_use_dbfs() +1); 1137 rb->peak_meter_set_use_dbfs(!rb->peak_meter_get_use_dbfs());
1138#endif 1138#endif
1139 splitedit_invalidate_osci(); 1139 splitedit_invalidate_osci();
1140 update_icons(); 1140 update_icons();
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c
index 002a3c48d5..088cf8e099 100644
--- a/apps/recorder/peakmeter.c
+++ b/apps/recorder/peakmeter.c
@@ -21,6 +21,7 @@
21#include "thread.h" 21#include "thread.h"
22#include "kernel.h" 22#include "kernel.h"
23#include "settings.h" 23#include "settings.h"
24#include "ata.h"
24#include "lcd.h" 25#include "lcd.h"
25#include "widgets.h" 26#include "widgets.h"
26#include "wps-display.h" 27#include "wps-display.h"
@@ -36,41 +37,48 @@
36#include "pcm_playback.h" 37#include "pcm_playback.h"
37#endif 38#endif
38 39
39/* no inline in simulator mode */ 40#if !defined(SIMULATOR) && CONFIG_HWCODEC != MASNONE
40#ifdef SIMULATOR 41/* Data source */
41#define inline 42static int pm_src_left = MAS_REG_DQPEAK_L;
43static int pm_src_right = MAS_REG_DQPEAK_R;
42#endif 44#endif
43 45
44/* buffer the read peak value */ 46/* Current values and cumulation */
45static int peak_meter_max_l; 47static int pm_cur_left; /* current values (last peak_meter_peek) */
46static int peak_meter_max_r; 48static int pm_cur_right;
47 49static int pm_max_left; /* maximum values between peak meter draws */
48/* point in time when peak_meter_max_x becomes invalid */ 50static int pm_max_right;
49static long peak_meter_timeout_l; 51
50static long peak_meter_timeout_r; 52/* Peak hold */
51 53static int pm_peak_left; /* buffered peak values */
52/* when true a clip has occurred */ 54static int pm_peak_right;
53static bool peak_meter_l_clip = false; 55static long pm_peak_timeout_l; /* peak hold timeouts */
54static bool peak_meter_r_clip = false; 56static long pm_peak_timeout_r;
55 57
56/* point in time when peak_meter_x_oveflow becomes invalid */ 58/* Clip hold */
57static long peak_meter_clip_timeout_l; 59static bool pm_clip_left = false; /* when true a clip has occurred */
58static long peak_meter_clip_timeout_r; 60static bool pm_clip_right = false;
59 61static long pm_clip_timeout_l; /* clip hold timeouts */
60static int peak_meter_clip_hold; 62static long pm_clip_timeout_r;
61 63
62/* specifies the value range in peak volume values */ 64/* Temporarily en- / disables peak meter. This is especially for external
63unsigned short peak_meter_range_min; 65 applications to detect if the peak_meter is in use and needs drawing at all */
64unsigned short peak_meter_range_max; 66bool peak_meter_enabled = true;
65static unsigned short peak_meter_range;
66
67/* if set to true clip timeout is disabled */
68static bool peak_meter_clip_eternal = false;
69 67
70static bool peak_meter_use_dbfs = true; 68/** Parameters **/
71static unsigned short db_min = 0; 69/* Range */
72static unsigned short db_max = 9000; 70unsigned short peak_meter_range_min; /* minimum of range in samples */
73static unsigned short db_range = 9000; 71unsigned short peak_meter_range_max; /* maximum of range in samples */
72static unsigned short pm_range; /* range width in samples */
73static bool pm_use_dbfs = true; /* true if peakmeter displays dBfs */
74static unsigned short pm_db_min = 0; /* minimum of range in 1/100 dB */
75static unsigned short pm_db_max = 9000; /* maximum of range in 1/100 dB */
76static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */
77/* Timing behaviour */
78static int pm_peak_hold = 1; /* peak hold timeout index */
79static int pm_peak_release = 8; /* peak release in units per read */
80static int pm_clip_hold = 16; /* clip hold timeout index */
81static bool pm_clip_eternal = false; /* true if clip timeout is disabled */
74 82
75#ifdef HAVE_RECORDING 83#ifdef HAVE_RECORDING
76static unsigned short trig_strt_threshold; 84static unsigned short trig_strt_threshold;
@@ -92,34 +100,6 @@ static int trig_status = TRIG_OFF;
92static void (*trigger_listener)(int) = NULL; 100static void (*trigger_listener)(int) = NULL;
93#endif 101#endif
94 102
95#if CONFIG_HWCODEC == MASNONE
96#define MAS_REG_DQPEAK_L 0
97#define MAS_REG_DQPEAK_R 0
98#endif
99
100#if !defined(SIMULATOR) && CONFIG_HWCODEC != MASNONE
101static int peak_meter_src_l = MAS_REG_DQPEAK_L;
102static int peak_meter_src_r = MAS_REG_DQPEAK_R;
103#endif
104
105/* temporarily en- / disables peak meter. This is
106 especially for external applications to detect
107 if the peak_meter is in use and needs drawing at all */
108bool peak_meter_enabled = true;
109
110/*
111bool peak_meter_use_thread = false;
112static char peak_meter_stack[DEFAULT_STACK_SIZE];
113*/
114/* used in wps.c to set the display frame rate of the peak meter */
115int peak_meter_fps = 20;
116
117static int peak_meter_l;
118static int peak_meter_r;
119
120static int peak_meter_hold = 1;
121static int peak_meter_release = 8;
122
123/* debug only */ 103/* debug only */
124#ifdef PM_DEBUG 104#ifdef PM_DEBUG
125static int peek_calls = 0; 105static int peek_calls = 0;
@@ -132,7 +112,7 @@ static unsigned int ticks_per_redraw[TICKS_PER_DRAW_SIZE];
132#endif 112#endif
133 113
134/* time out values for max */ 114/* time out values for max */
135static const long max_time_out[] = { 115static const short peak_time_out[] = {
136 0 * HZ, HZ / 5, 30, HZ / 2, HZ, 2 * HZ, 116 0 * HZ, HZ / 5, 30, HZ / 2, HZ, 2 * HZ,
137 3 * HZ, 4 * HZ, 5 * HZ, 6 * HZ, 7 * HZ, 8 * HZ, 117 3 * HZ, 4 * HZ, 5 * HZ, 6 * HZ, 7 * HZ, 8 * HZ,
138 9 * HZ, 10 * HZ, 15 * HZ, 20 * HZ, 30 * HZ, 60 * HZ 118 9 * HZ, 10 * HZ, 15 * HZ, 20 * HZ, 30 * HZ, 60 * HZ
@@ -150,22 +130,6 @@ static const long clip_time_out[] = {
150/* precalculated peak values that represent magical 130/* precalculated peak values that represent magical
151 dBfs values. Used to draw the scale */ 131 dBfs values. Used to draw the scale */
152#define DB_SCALE_SRC_VALUES_SIZE 12 132#define DB_SCALE_SRC_VALUES_SIZE 12
153#if 0
154static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
155 32767, /* 0 db */
156 23197, /* - 3 db */
157 16422, /* - 6 db */
158 11626, /* - 9 db */
159 8231, /* -12 db */
160 4125, /* -18 db */
161 2067, /* -24 db */
162 1036, /* -30 db */
163 328, /* -40 db */
164 104, /* -50 db */
165 33, /* -60 db */
166 1, /* -inf */
167};
168#else
169static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { 133static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
170 32752, /* 0 db */ 134 32752, /* 0 db */
171 22784, /* - 3 db */ 135 22784, /* - 3 db */
@@ -180,11 +144,10 @@ static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
180 33, /* -60 db */ 144 33, /* -60 db */
181 0, /* -inf */ 145 0, /* -inf */
182}; 146};
183#endif
184 147
185static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE; 148static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
186 149
187/* if db_scale_valid is false the content of 150/* if db_scale_valid is false the content of
188 db_scale_lcd_coord needs recalculation */ 151 db_scale_lcd_coord needs recalculation */
189static bool db_scale_valid = false; 152static bool db_scale_valid = false;
190 153
@@ -211,7 +174,8 @@ static int db_scale_lcd_coord[sizeof db_scale_src_values / sizeof (int)];
211 * for-loops. 174 * for-loops.
212 */ 175 */
213 176
214int calc_db (int isample) { 177int calc_db (int isample)
178{
215 /* return n+m*(isample-istart)/100 */ 179 /* return n+m*(isample-istart)/100 */
216 int n; 180 int n;
217 long m; 181 long m;
@@ -312,7 +276,8 @@ int calc_db (int isample) {
312 * minimal peak sample is searched. 276 * minimal peak sample is searched.
313 * @return int - A linear volume value with 0 <= value < MAX_PEAK 277 * @return int - A linear volume value with 0 <= value < MAX_PEAK
314 */ 278 */
315static int db_to_sample_bin_search(int min, int max, int db){ 279static int db_to_sample_bin_search(int min, int max, int db)
280{
316 int test = min + (max - min) / 2; 281 int test = min + (max - min) / 2;
317 282
318 if (min < max) { 283 if (min < max) {
@@ -339,7 +304,8 @@ static int db_to_sample_bin_search(int min, int max, int db){
339 * @return int - The return value is in the range of 304 * @return int - The return value is in the range of
340 * 0 <= return value < MAX_PEAK 305 * 0 <= return value < MAX_PEAK
341 */ 306 */
342int peak_meter_db2sample(int db) { 307int peak_meter_db2sample(int db)
308{
343 int retval = 0; 309 int retval = 0;
344 310
345 /* what is the maximum pseudo db value */ 311 /* what is the maximum pseudo db value */
@@ -371,13 +337,14 @@ int peak_meter_db2sample(int db) {
371 337
372/** 338/**
373 * Set the min value for restriction of the value range. 339 * Set the min value for restriction of the value range.
374 * @param int newmin - depending wether dBfs is used 340 * @param int newmin - depending whether dBfs is used
375 * newmin is a value in dBfs * 100 or in linear percent values. 341 * newmin is a value in dBfs * 100 or in linear percent values.
376 * for dBfs: -9000 < newmin <= 0 342 * for dBfs: -9000 < newmin <= 0
377 * for linear: 0 <= newmin <= 100 343 * for linear: 0 <= newmin <= 100
378 */ 344 */
379void peak_meter_set_min(int newmin) { 345void peak_meter_set_min(int newmin)
380 if (peak_meter_use_dbfs) { 346{
347 if (pm_use_dbfs) {
381 peak_meter_range_min = peak_meter_db2sample(newmin); 348 peak_meter_range_min = peak_meter_db2sample(newmin);
382 349
383 } else { 350 } else {
@@ -386,10 +353,10 @@ void peak_meter_set_min(int newmin) {
386 } 353 }
387 } 354 }
388 355
389 peak_meter_range = peak_meter_range_max - peak_meter_range_min; 356 pm_range = peak_meter_range_max - peak_meter_range_min;
390 357
391 db_min = calc_db(peak_meter_range_min); 358 pm_db_min = calc_db(peak_meter_range_min);
392 db_range = db_max - db_min; 359 pm_db_range = pm_db_max - pm_db_min;
393 db_scale_valid = false; 360 db_scale_valid = false;
394} 361}
395 362
@@ -400,9 +367,10 @@ void peak_meter_set_min(int newmin) {
400 * @return: using dBfs : -9000 < value <= 0 367 * @return: using dBfs : -9000 < value <= 0
401 * using linear scale: 0 <= value <= 100 368 * using linear scale: 0 <= value <= 100
402 */ 369 */
403int peak_meter_get_min(void) { 370int peak_meter_get_min(void)
371{
404 int retval = 0; 372 int retval = 0;
405 if (peak_meter_use_dbfs) { 373 if (pm_use_dbfs) {
406 retval = calc_db(peak_meter_range_min) - calc_db(MAX_PEAK - 1); 374 retval = calc_db(peak_meter_range_min) - calc_db(MAX_PEAK - 1);
407 } else { 375 } else {
408 retval = peak_meter_range_min * 100 / MAX_PEAK; 376 retval = peak_meter_range_min * 100 / MAX_PEAK;
@@ -417,8 +385,9 @@ int peak_meter_get_min(void) {
417 * for dBfs: -9000 < newmax <= 0 385 * for dBfs: -9000 < newmax <= 0
418 * for linear: 0 <= newmax <= 100 386 * for linear: 0 <= newmax <= 100
419 */ 387 */
420void peak_meter_set_max(int newmax) { 388void peak_meter_set_max(int newmax)
421 if (peak_meter_use_dbfs) { 389{
390 if (pm_use_dbfs) {
422 peak_meter_range_max = peak_meter_db2sample(newmax); 391 peak_meter_range_max = peak_meter_db2sample(newmax);
423 } else { 392 } else {
424 if (newmax > peak_meter_range_min) { 393 if (newmax > peak_meter_range_min) {
@@ -426,10 +395,10 @@ void peak_meter_set_max(int newmax) {
426 } 395 }
427 } 396 }
428 397
429 peak_meter_range = peak_meter_range_max - peak_meter_range_min; 398 pm_range = peak_meter_range_max - peak_meter_range_min;
430 399
431 db_max = calc_db(peak_meter_range_max); 400 pm_db_max = calc_db(peak_meter_range_max);
432 db_range = db_max - db_min; 401 pm_db_range = pm_db_max - pm_db_min;
433 db_scale_valid = false; 402 db_scale_valid = false;
434} 403}
435 404
@@ -440,9 +409,10 @@ void peak_meter_set_max(int newmax) {
440 * @return: using dBfs : -9000 < value <= 0 409 * @return: using dBfs : -9000 < value <= 0
441 * using linear scale: 0 <= value <= 100 410 * using linear scale: 0 <= value <= 100
442 */ 411 */
443int peak_meter_get_max(void) { 412int peak_meter_get_max(void)
413{
444 int retval = 0; 414 int retval = 0;
445 if (peak_meter_use_dbfs) { 415 if (pm_use_dbfs) {
446 retval = calc_db(peak_meter_range_max) - calc_db(MAX_PEAK - 1); 416 retval = calc_db(peak_meter_range_max) - calc_db(MAX_PEAK - 1);
447 } else { 417 } else {
448 retval = peak_meter_range_max * 100 / MAX_PEAK; 418 retval = peak_meter_range_max * 100 / MAX_PEAK;
@@ -451,23 +421,24 @@ int peak_meter_get_max(void) {
451} 421}
452 422
453/** 423/**
454 * Returns 1 if the meter currently is 424 * Returns whether the meter is currently displaying dBfs or percent values.
455 * displaying dBfs values, 0 if the meter 425 * @return bool - true if the meter is displaying dBfs
456 * displays percent values. 426 false if the meter is displaying percent values.
457 * @return int - returns 0 or 1.
458 */ 427 */
459int peak_meter_get_use_dbfs(void) { 428bool peak_meter_get_use_dbfs(void)
460 return peak_meter_use_dbfs ? 1 : 0; 429{
430 return pm_use_dbfs;
461} 431}
462 432
463/** 433/**
464 * Specifies wether the values displayed are scaled 434 * Specifies whether the values displayed are scaled
465 * as dBfs or as linear percent values. 435 * as dBfs or as linear percent values.
466 * @param int - Set to 0 for linear percent scale. Any other value 436 * @param use - set to true for dBfs,
467 * switches on dBfs. 437 * set to false for linear scaling in percent
468 */ 438 */
469void peak_meter_set_use_dbfs(int use){ 439void peak_meter_set_use_dbfs(bool use)
470 peak_meter_use_dbfs = ((use & 1) == 1); 440{
441 pm_use_dbfs = use;
471 db_scale_valid = false; 442 db_scale_valid = false;
472} 443}
473 444
@@ -486,7 +457,7 @@ void peak_meter_set_use_dbfs(int use){
486 */ 457 */
487void peak_meter_init_range( bool dbfs, int range_min, int range_max) 458void peak_meter_init_range( bool dbfs, int range_min, int range_max)
488{ 459{
489 peak_meter_use_dbfs = dbfs; 460 pm_use_dbfs = dbfs;
490 peak_meter_set_min(range_min); 461 peak_meter_set_min(range_min);
491 peak_meter_set_max(range_max); 462 peak_meter_set_max(range_max);
492} 463}
@@ -497,15 +468,16 @@ void peak_meter_init_range( bool dbfs, int range_min, int range_max)
497 * to decrease with each redraw 468 * to decrease with each redraw
498 * @param int hold - Select the time preset for the time the peak indicator 469 * @param int hold - Select the time preset for the time the peak indicator
499 * is reset after a peak occurred. The preset values are 470 * is reset after a peak occurred. The preset values are
500 * stored in max_time_out. 471 * stored in peak_time_out.
501 * @param int clip_hold - Select the time preset for the time the peak 472 * @param int clip_hold - Select the time preset for the time the peak
502 * indicator is reset after a peak occurred. The preset 473 * indicator is reset after a peak occurred. The preset
503 * values are stored in clip_time_out. 474 * values are stored in clip_time_out.
504 */ 475 */
505void peak_meter_init_times(int release, int hold, int clip_hold) { 476void peak_meter_init_times(int release, int hold, int clip_hold)
506 peak_meter_hold = hold; 477{
507 peak_meter_release = release; 478 pm_peak_hold = hold;
508 peak_meter_clip_hold = clip_hold; 479 pm_peak_release = release;
480 pm_clip_hold = clip_hold;
509} 481}
510 482
511/** 483/**
@@ -523,17 +495,18 @@ void peak_meter_playback(bool playback)
523 (void)playback; 495 (void)playback;
524#else 496#else
525 if (playback) { 497 if (playback) {
526 peak_meter_src_l = MAS_REG_DQPEAK_L; 498 pm_src_left = MAS_REG_DQPEAK_L;
527 peak_meter_src_r = MAS_REG_DQPEAK_R; 499 pm_src_right = MAS_REG_DQPEAK_R;
528 } else { 500 } else {
529 peak_meter_src_l = MAS_REG_QPEAK_L; 501 pm_src_left = MAS_REG_QPEAK_L;
530 peak_meter_src_r = MAS_REG_QPEAK_R; 502 pm_src_right = MAS_REG_QPEAK_R;
531 } 503 }
532#endif 504#endif
533} 505}
534 506
535#ifdef HAVE_RECORDING 507#ifdef HAVE_RECORDING
536static void set_trig_status(int new_state) { 508static void set_trig_status(int new_state)
509{
537 if (trig_status != new_state) { 510 if (trig_status != new_state) {
538 trig_status = new_state; 511 trig_status = new_state;
539 if (trigger_listener != NULL) { 512 if (trigger_listener != NULL) {
@@ -545,24 +518,25 @@ static void set_trig_status(int new_state) {
545 518
546/** 519/**
547 * Reads peak values from the MAS, and detects clips. The 520 * Reads peak values from the MAS, and detects clips. The
548 * values are stored in peak_meter_l peak_meter_r for later 521 * values are stored in pm_max_left pm_max_right for later
549 * evauluation. Consecutive calls to peak_meter_peek detect 522 * evauluation. Consecutive calls to peak_meter_peek detect
550 * that ocurred. This function could be used by a thread for 523 * that ocurred. This function could be used by a thread for
551 * busy reading the MAS. 524 * busy reading the MAS.
552 */ 525 */
553inline void peak_meter_peek(void) 526void peak_meter_peek(void)
554{ 527{
528 int left, right;
529 /* read current values */
555#ifdef SIMULATOR 530#ifdef SIMULATOR
556 int left = 8000; 531 pm_cur_left = left = 8000;
557 int right = 9000; 532 pm_cur_right = right = 9000;
558#elif CONFIG_HWCODEC == MASNONE 533#elif CONFIG_HWCODEC == MASNONE
559 int left; 534 pcm_calculate_peaks(&pm_cur_left, &pm_cur_right);
560 int right; 535 left = pm_cur_left;
561 pcm_calculate_peaks(&left, &right); 536 right = pm_cur_right;
562#else 537#else
563 /* read the peak values */ 538 pm_cur_left = left = mas_codec_readreg(pm_src_left);
564 int left = mas_codec_readreg(peak_meter_src_l); 539 pm_cur_right = right = mas_codec_readreg(pm_src_right);
565 int right = mas_codec_readreg(peak_meter_src_r);
566#endif 540#endif
567 541
568 /* check for clips 542 /* check for clips
@@ -571,26 +545,34 @@ inline void peak_meter_peek(void)
571 to be inaccurate in both ways: it may detect clips 545 to be inaccurate in both ways: it may detect clips
572 when no clip occurred and it may fail to detect 546 when no clip occurred and it may fail to detect
573 a real clip. */ 547 a real clip. */
574 if ((left == peak_meter_l) && 548 if ((left == pm_max_left) &&
575 (left == MAX_PEAK - 1)) { 549 (left == MAX_PEAK - 1)) {
576 peak_meter_l_clip = true; 550 pm_clip_left = true;
577 peak_meter_clip_timeout_l = 551 pm_clip_timeout_l =
578 current_tick + clip_time_out[peak_meter_clip_hold]; 552 current_tick + clip_time_out[pm_clip_hold];
579 } 553 }
580 554
581 if ((right == peak_meter_r) && 555 if ((right == pm_max_right) &&
582 (right == MAX_PEAK - 1)) { 556 (right == MAX_PEAK - 1)) {
583 peak_meter_r_clip = true; 557 pm_clip_right = true;
584 peak_meter_clip_timeout_r = 558 pm_clip_timeout_r =
585 current_tick + clip_time_out[peak_meter_clip_hold]; 559 current_tick + clip_time_out[pm_clip_hold];
586 } 560 }
587 561
562 /* peaks are searched -> we have to find the maximum. When
563 many calls of peak_meter_peek the maximum value will be
564 stored in pm_max_xxx. This maximum is reset by the
565 functions peak_meter_read_x. */
566 pm_max_left = MAX(pm_max_left, left);
567 pm_max_right = MAX(pm_max_right, right);
568
588#ifdef HAVE_RECORDING 569#ifdef HAVE_RECORDING
589 switch (trig_status) { 570 switch (trig_status) {
590 case TRIG_READY: 571 case TRIG_READY:
591 /* no more changes, if trigger was activated as release trigger */ 572 /* no more changes, if trigger was activated as release trigger */
592 /* threshold exceeded? */ 573 /* threshold exceeded? */
593 if ((left > trig_strt_threshold) || (right > trig_strt_threshold)) { 574 if ((left > trig_strt_threshold)
575 || (right > trig_strt_threshold)) {
594 if (trig_strt_duration) { 576 if (trig_strt_duration) {
595 /* reset trigger duration */ 577 /* reset trigger duration */
596 trig_hightime = current_tick; 578 trig_hightime = current_tick;
@@ -614,8 +596,8 @@ inline void peak_meter_peek(void)
614 set_trig_status(TRIG_GO); 596 set_trig_status(TRIG_GO);
615 } else { 597 } else {
616 /* threshold exceeded? */ 598 /* threshold exceeded? */
617 if ((left > trig_strt_threshold) || 599 if ((left > trig_strt_threshold)
618 (right > trig_strt_threshold)) { 600 || (right > trig_strt_threshold)) {
619 /* reset lowtime */ 601 /* reset lowtime */
620 trig_lowtime = current_tick; 602 trig_lowtime = current_tick;
621 } 603 }
@@ -640,7 +622,8 @@ inline void peak_meter_peek(void)
640 case TRIG_GO: 622 case TRIG_GO:
641 case TRIG_CONTINUE: 623 case TRIG_CONTINUE:
642 /* threshold exceeded? */ 624 /* threshold exceeded? */
643 if ((left > trig_stp_threshold) || (right > trig_stp_threshold)) { 625 if ((left > trig_stp_threshold)
626 || (right > trig_stp_threshold)) {
644 /* restart hold time countdown */ 627 /* restart hold time countdown */
645 trig_lowtime = current_tick; 628 trig_lowtime = current_tick;
646 } else { 629 } else {
@@ -653,8 +636,8 @@ inline void peak_meter_peek(void)
653 /* gap time expired? */ 636 /* gap time expired? */
654 if (current_tick - trig_lowtime > trig_rstrt_gap){ 637 if (current_tick - trig_lowtime > trig_rstrt_gap){
655 /* start threshold exceeded? */ 638 /* start threshold exceeded? */
656 if ((left > trig_strt_threshold) || 639 if ((left > trig_strt_threshold)
657 (right > trig_strt_threshold)) { 640 || (right > trig_strt_threshold)) {
658 641
659 set_trig_status(TRIG_RETRIG); 642 set_trig_status(TRIG_RETRIG);
660 trig_hightime = current_tick; 643 trig_hightime = current_tick;
@@ -662,8 +645,8 @@ inline void peak_meter_peek(void)
662 else 645 else
663 646
664 /* stop threshold exceeded */ 647 /* stop threshold exceeded */
665 if ((left > trig_stp_threshold) || 648 if ((left > trig_stp_threshold)
666 (right > trig_stp_threshold)) { 649 || (right > trig_stp_threshold)) {
667 if (current_tick - trig_hightime > trig_stp_hold){ 650 if (current_tick - trig_hightime > trig_stp_hold){
668 trig_lowtime = current_tick; 651 trig_lowtime = current_tick;
669 set_trig_status(TRIG_CONTINUE); 652 set_trig_status(TRIG_CONTINUE);
@@ -685,8 +668,8 @@ inline void peak_meter_peek(void)
685 /* still within the gap time */ 668 /* still within the gap time */
686 else { 669 else {
687 /* stop threshold exceeded */ 670 /* stop threshold exceeded */
688 if ((left > trig_stp_threshold) || 671 if ((left > trig_stp_threshold)
689 (right > trig_stp_threshold)) { 672 || (right > trig_stp_threshold)) {
690 set_trig_status(TRIG_CONTINUE); 673 set_trig_status(TRIG_CONTINUE);
691 trig_lowtime = current_tick; 674 trig_lowtime = current_tick;
692 } 675 }
@@ -702,13 +685,6 @@ inline void peak_meter_peek(void)
702 } 685 }
703#endif 686#endif
704 687
705 /* peaks are searched -> we have to find the maximum. When
706 many calls of peak_meter_peek the maximum value will be
707 stored in peak_meter_x. This maximum is reset by the
708 functions peak_meter_read_x. */
709 peak_meter_l = MAX(peak_meter_l, left);
710 peak_meter_r = MAX(peak_meter_r, right);
711
712#ifdef PM_DEBUG 688#ifdef PM_DEBUG
713 peek_calls++; 689 peek_calls++;
714#endif 690#endif
@@ -720,26 +696,18 @@ inline void peak_meter_peek(void)
720 * since the last call of peak_meter_read_l. The value 696 * since the last call of peak_meter_read_l. The value
721 * is in the range 0 <= value < MAX_PEAK. 697 * is in the range 0 <= value < MAX_PEAK.
722 */ 698 */
723static int peak_meter_read_l (void) 699static int peak_meter_read_l(void)
724{ 700{
725 /* peak_meter_l contains the maximum of 701 /* pm_max_left contains the maximum of all peak values that were read
726 all peak values that were read by peak_meter_peek 702 by peak_meter_peek since the last call of peak_meter_read_l */
727 since the last call of peak_meter_read_r */ 703 int retval = pm_max_left;
728 int retval = peak_meter_l; 704
729#ifdef PM_DEBUG 705#ifdef PM_DEBUG
730 peek_calls = 0; 706 peek_calls = 0;
731#endif 707#endif
732 708 /* reset pm_max_left so that subsequent calls of peak_meter_peek don't
733#ifdef SIMULATOR 709 get fooled by an old maximum value */
734 peak_meter_l = 8000; 710 pm_max_left = pm_cur_left;
735#elif CONFIG_HWCODEC == MASNONE
736 pcm_calculate_peaks(&peak_meter_l, NULL);
737#else
738 /* reset peak_meter_l so that subsequent calls of
739 peak_meter_peek doesn't get fooled by an old
740 maximum value */
741 peak_meter_l = mas_codec_readreg(peak_meter_src_l);
742#endif
743 return retval; 711 return retval;
744} 712}
745 713
@@ -749,25 +717,18 @@ static int peak_meter_read_l (void)
749 * since the last call of peak_meter_read_l. The value 717 * since the last call of peak_meter_read_l. The value
750 * is in the range 0 <= value < MAX_PEAK. 718 * is in the range 0 <= value < MAX_PEAK.
751 */ 719 */
752static int peak_meter_read_r (void) { 720static int peak_meter_read_r(void)
753 /* peak_meter_r contains the maximum of 721{
754 all peak values that were read by peak_meter_peek 722 /* peak_meter_r contains the maximum of all peak values that were read
755 since the last call of peak_meter_read_r */ 723 by peak_meter_peek since the last call of peak_meter_read_r */
756 int retval = peak_meter_r; 724 int retval = pm_max_right;
725
757#ifdef PM_DEBUG 726#ifdef PM_DEBUG
758 peek_calls = 0; 727 peek_calls = 0;
759#endif 728#endif
760 729 /* reset pm_max_right so that subsequent calls of peak_meter_peek don't
761#ifdef SIMULATOR 730 get fooled by an old maximum value */
762 peak_meter_l = 8000; 731 pm_max_right = pm_cur_right;
763#elif CONFIG_HWCODEC == MASNONE
764 pcm_calculate_peaks(NULL, &peak_meter_r);
765#else
766 /* reset peak_meter_r so that subsequent calls of
767 peak_meter_peek doesn't get fooled by an old
768 maximum value */
769 peak_meter_r = mas_codec_readreg(peak_meter_src_r);
770#endif
771 return retval; 732 return retval;
772} 733}
773 734
@@ -777,13 +738,14 @@ static int peak_meter_read_r (void) {
777 * @param int unused - This parameter was added to 738 * @param int unused - This parameter was added to
778 * make the function compatible with set_int 739 * make the function compatible with set_int
779 */ 740 */
780void peak_meter_set_clip_hold(int time) { 741void peak_meter_set_clip_hold(int time)
781 peak_meter_clip_eternal = false; 742{
743 pm_clip_eternal = false;
782 744
783 if (time <= 0) { 745 if (time <= 0) {
784 peak_meter_l_clip = false; 746 pm_clip_left = false;
785 peak_meter_r_clip = false; 747 pm_clip_right = false;
786 peak_meter_clip_eternal = true; 748 pm_clip_eternal = true;
787 } 749 }
788} 750}
789 751
@@ -795,7 +757,8 @@ void peak_meter_set_clip_hold(int time) {
795 * @param int meterwidht - The widht of the meter in pixel 757 * @param int meterwidht - The widht of the meter in pixel
796 * @return unsigned short - A value 0 <= return value <= meterwidth 758 * @return unsigned short - A value 0 <= return value <= meterwidth
797 */ 759 */
798unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){ 760unsigned short peak_meter_scale_value(unsigned short val, int meterwidth)
761{
799 int retval; 762 int retval;
800 763
801 if (val <= peak_meter_range_min) { 764 if (val <= peak_meter_range_min) {
@@ -809,10 +772,10 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){
809 retval = val; 772 retval = val;
810 773
811 /* different scaling is used for dBfs and linear percent */ 774 /* different scaling is used for dBfs and linear percent */
812 if (peak_meter_use_dbfs) { 775 if (pm_use_dbfs) {
813 776
814 /* scale the samples dBfs */ 777 /* scale the samples dBfs */
815 retval = (calc_db(retval) - db_min) * meterwidth / db_range; 778 retval = (calc_db(retval) - pm_db_min) * meterwidth / pm_db_range;
816 } 779 }
817 780
818 /* Scale for linear percent display */ 781 /* Scale for linear percent display */
@@ -820,7 +783,7 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){
820 { 783 {
821 /* scale the samples */ 784 /* scale the samples */
822 retval = ((retval - peak_meter_range_min) * meterwidth) 785 retval = ((retval - peak_meter_range_min) * meterwidth)
823 / peak_meter_range; 786 / pm_range;
824 } 787 }
825 return retval; 788 return retval;
826} 789}
@@ -854,8 +817,7 @@ void peak_meter_draw(int x, int y, int width, int height)
854 817
855 /* read the volume info from MAS */ 818 /* read the volume info from MAS */
856 left = peak_meter_read_l(); 819 left = peak_meter_read_l();
857 right = peak_meter_read_r(); 820 right = peak_meter_read_r();
858 /*peak_meter_peek();*/
859 821
860 /* scale the samples dBfs */ 822 /* scale the samples dBfs */
861 left = peak_meter_scale_value(left, meterwidth); 823 left = peak_meter_scale_value(left, meterwidth);
@@ -865,7 +827,7 @@ void peak_meter_draw(int x, int y, int width, int height)
865 (The scale becomes invalid when the range changed.) */ 827 (The scale becomes invalid when the range changed.) */
866 if (!db_scale_valid){ 828 if (!db_scale_valid){
867 829
868 if (peak_meter_use_dbfs) { 830 if (pm_use_dbfs) {
869 db_scale_count = DB_SCALE_SRC_VALUES_SIZE; 831 db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
870 for (i = 0; i < db_scale_count; i++){ 832 for (i = 0; i < db_scale_count; i++){
871 /* find the real x-coords for predefined interesting 833 /* find the real x-coords for predefined interesting
@@ -884,7 +846,7 @@ void peak_meter_draw(int x, int y, int width, int height)
884 for (i = 0; i < db_scale_count; i++) { 846 for (i = 0; i < db_scale_count; i++) {
885 db_scale_lcd_coord[i] = 847 db_scale_lcd_coord[i] =
886 (i * (MAX_PEAK / 10) - peak_meter_range_min) * 848 (i * (MAX_PEAK / 10) - peak_meter_range_min) *
887 meterwidth / peak_meter_range; 849 meterwidth / pm_range;
888 } 850 }
889 } 851 }
890 852
@@ -894,41 +856,41 @@ void peak_meter_draw(int x, int y, int width, int height)
894 } 856 }
895 857
896 /* apply release */ 858 /* apply release */
897 left = MAX(left , last_left - peak_meter_release); 859 left = MAX(left , last_left - pm_peak_release);
898 right = MAX(right, last_right - peak_meter_release); 860 right = MAX(right, last_right - pm_peak_release);
899 861
900 /* reset max values after timeout */ 862 /* reset max values after timeout */
901 if (TIME_AFTER(current_tick, peak_meter_timeout_l)){ 863 if (TIME_AFTER(current_tick, pm_peak_timeout_l)){
902 peak_meter_max_l = 0; 864 pm_peak_left = 0;
903 } 865 }
904 866
905 if (TIME_AFTER(current_tick, peak_meter_timeout_r)){ 867 if (TIME_AFTER(current_tick, pm_peak_timeout_r)){
906 peak_meter_max_r = 0; 868 pm_peak_right = 0;
907 } 869 }
908 870
909 if (!peak_meter_clip_eternal) { 871 if (!pm_clip_eternal) {
910 if (peak_meter_l_clip && 872 if (pm_clip_left &&
911 TIME_AFTER(current_tick, peak_meter_clip_timeout_l)){ 873 TIME_AFTER(current_tick, pm_clip_timeout_l)){
912 peak_meter_l_clip = false; 874 pm_clip_left = false;
913 } 875 }
914 876
915 if (peak_meter_r_clip && 877 if (pm_clip_right &&
916 TIME_AFTER(current_tick, peak_meter_clip_timeout_r)){ 878 TIME_AFTER(current_tick, pm_clip_timeout_r)){
917 peak_meter_r_clip = false; 879 pm_clip_right = false;
918 } 880 }
919 } 881 }
920 882
921 /* check for new max values */ 883 /* check for new max values */
922 if (left > peak_meter_max_l) { 884 if (left > pm_peak_left) {
923 peak_meter_max_l = left - 1; 885 pm_peak_left = left - 1;
924 peak_meter_timeout_l = 886 pm_peak_timeout_l =
925 current_tick + max_time_out[peak_meter_hold]; 887 current_tick + peak_time_out[pm_peak_hold];
926 } 888 }
927 889
928 if (right > peak_meter_max_r) { 890 if (right > pm_peak_right) {
929 peak_meter_max_r = right - 1; 891 pm_peak_right = right - 1;
930 peak_meter_timeout_r = 892 pm_peak_timeout_r =
931 current_tick + max_time_out[peak_meter_hold]; 893 current_tick + peak_time_out[pm_peak_hold];
932 } 894 }
933 } 895 }
934 896
@@ -939,19 +901,19 @@ void peak_meter_draw(int x, int y, int width, int height)
939 901
940 /* draw left */ 902 /* draw left */
941 lcd_fillrect (x, y, left, height / 2 - 2 ); 903 lcd_fillrect (x, y, left, height / 2 - 2 );
942 if (peak_meter_max_l > 0) { 904 if (pm_peak_left > 0) {
943 lcd_vline(x + peak_meter_max_l, y, y + height / 2 - 2 ); 905 lcd_vline(x + pm_peak_left, y, y + height / 2 - 2 );
944 } 906 }
945 if (peak_meter_l_clip) { 907 if (pm_clip_left) {
946 lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1); 908 lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1);
947 } 909 }
948 910
949 /* draw right */ 911 /* draw right */
950 lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2); 912 lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2);
951 if (peak_meter_max_r > 0) { 913 if (pm_peak_right > 0) {
952 lcd_vline( x + peak_meter_max_r, y + height / 2, y + height - 2); 914 lcd_vline( x + pm_peak_right, y + height / 2, y + height - 2);
953 } 915 }
954 if (peak_meter_r_clip) { 916 if (pm_clip_right) {
955 lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1); 917 lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1);
956 } 918 }
957 919
@@ -1071,7 +1033,8 @@ void peak_meter_define_trigger(
1071 * Enables or disables the trigger. 1033 * Enables or disables the trigger.
1072 * @param on - If true the trigger is turned on. 1034 * @param on - If true the trigger is turned on.
1073 */ 1035 */
1074void peak_meter_trigger(bool on) { 1036void peak_meter_trigger(bool on)
1037{
1075 /* don't use set_trigger here as that would fire an undesired event */ 1038 /* don't use set_trigger here as that would fire an undesired event */
1076 trig_status = on ? TRIG_READY : TRIG_OFF; 1039 trig_status = on ? TRIG_READY : TRIG_OFF;
1077} 1040}
@@ -1081,7 +1044,8 @@ void peak_meter_trigger(bool on) {
1081 * @param listener - The function that is called with each change of 1044 * @param listener - The function that is called with each change of
1082 * trig_status. May be set to NULL if no callback is desired. 1045 * trig_status. May be set to NULL if no callback is desired.
1083 */ 1046 */
1084void peak_meter_set_trigger_listener(void (*listener)(int status)) { 1047void peak_meter_set_trigger_listener(void (*listener)(int status))
1048{
1085 trigger_listener = listener; 1049 trigger_listener = listener;
1086} 1050}
1087 1051
@@ -1097,78 +1061,99 @@ void peak_meter_set_trigger_listener(void (*listener)(int status)) {
1097 * peak_meter_release_trigger. To turn the trigger off call 1061 * peak_meter_release_trigger. To turn the trigger off call
1098 * peak_meter_trigger_off. 1062 * peak_meter_trigger_off.
1099 */ 1063 */
1100int peak_meter_trigger_status(void) { 1064int peak_meter_trigger_status(void)
1065{
1101 return trig_status; /* & TRIG_PIT_MASK;*/ 1066 return trig_status; /* & TRIG_PIT_MASK;*/
1102} 1067}
1103 1068
1104void peak_meter_draw_trig(int xpos, int ypos) { 1069void peak_meter_draw_trig(int xpos, int ypos)
1105 int x = xpos + ICON_PLAY_STATE_WIDTH + 1; 1070{
1071 int barstart, barend;
1072 int icon, ixpos;
1106 switch (trig_status) { 1073 switch (trig_status) {
1107 long time_left;
1108 1074
1109 case TRIG_READY: 1075 case TRIG_READY:
1110 scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, 1076 barstart = 0;
1111 TRIGBAR_WIDTH, 0, 0, HORIZONTAL); 1077 barend = 0;
1112 lcd_mono_bitmap(bitmap_icons_7x8[Icon_Stop], xpos, ypos, 1078 icon = Icon_Stop;
1113 ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); 1079 ixpos = xpos;
1114 break; 1080 break;
1115 1081
1116 case TRIG_STEADY: 1082 case TRIG_STEADY:
1117 case TRIG_RETRIG: 1083 case TRIG_RETRIG:
1118 time_left = trig_strt_duration - (current_tick - trig_hightime); 1084 barstart = 0;
1119 time_left = time_left * TRIGBAR_WIDTH / trig_strt_duration; 1085 barend = TRIGBAR_WIDTH * (current_tick - trig_hightime)
1120 scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, 1086 / trig_strt_duration;
1121 TRIGBAR_WIDTH, 0, TRIGBAR_WIDTH - time_left, HORIZONTAL); 1087 icon = Icon_Stop;
1122 lcd_mono_bitmap(bitmap_icons_7x8[Icon_Stop], xpos, ypos, 1088 ixpos = xpos;
1123 ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT);
1124 break; 1089 break;
1125 1090
1126 case TRIG_GO: 1091 case TRIG_GO:
1127 case TRIG_CONTINUE: 1092 case TRIG_CONTINUE:
1128 scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, 1093 barstart = TRIGBAR_WIDTH;
1129 TRIGBAR_WIDTH, TRIGBAR_WIDTH, TRIGBAR_WIDTH, HORIZONTAL); 1094 barend = TRIGBAR_WIDTH;
1130 lcd_mono_bitmap(bitmap_icons_7x8[Icon_Record], 1095 icon = Icon_Record;
1131 TRIG_WIDTH - ICON_PLAY_STATE_WIDTH, ypos, 1096 ixpos = TRIG_WIDTH - ICON_PLAY_STATE_WIDTH;
1132 ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT);
1133 break; 1097 break;
1134 1098
1135 case TRIG_POSTREC: 1099 case TRIG_POSTREC:
1136 time_left = trig_stp_hold - (current_tick - trig_lowtime); 1100 barstart = TRIGBAR_WIDTH
1137 time_left = time_left * TRIGBAR_WIDTH / trig_stp_hold; 1101 - TRIGBAR_WIDTH * (current_tick - trig_lowtime)
1138 scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, 1102 / trig_stp_hold;
1139 TRIGBAR_WIDTH, time_left, TRIGBAR_WIDTH, HORIZONTAL); 1103 barend = TRIGBAR_WIDTH;
1140 lcd_mono_bitmap(bitmap_icons_7x8[Icon_Record], 1104 icon = Icon_Record;
1141 TRIG_WIDTH - ICON_PLAY_STATE_WIDTH, ypos, 1105 ixpos = TRIG_WIDTH - ICON_PLAY_STATE_WIDTH;
1142 ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT);
1143 break; 1106 break;
1144 }
1145 1107
1108 default:
1109 return;
1110 }
1111 scrollbar(xpos + ICON_PLAY_STATE_WIDTH + 1, ypos + 1,
1112 TRIGBAR_WIDTH, TRIG_HEIGHT - 2,
1113 TRIGBAR_WIDTH, barstart, barend, HORIZONTAL);
1114 lcd_mono_bitmap(bitmap_icons_7x8[icon], ixpos, ypos,
1115 ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT);
1146} 1116}
1147#endif 1117#endif
1148 1118
1149int peak_meter_draw_get_btn(int x, int y, int width, int height) 1119int peak_meter_draw_get_btn(int x, int y, int width, int height)
1150{ 1120{
1151 int button; 1121 int button = BUTTON_NONE;
1152 long next_refresh = current_tick; 1122 long next_refresh = current_tick;
1153 long next_big_refresh = current_tick + HZ / 10; 1123 long next_big_refresh = current_tick + HZ / 10;
1154 button = BUTTON_NONE; 1124#ifndef SIMULATOR
1125 bool highperf = !ata_disk_is_active();
1126#else
1127 bool highperf = false;
1128#endif
1129 bool dopeek = true;
1155 1130
1156 while (!TIME_AFTER(current_tick, next_big_refresh)) { 1131 while (TIME_BEFORE(current_tick, next_big_refresh)) {
1157 button = button_get(false); 1132 button = button_get(false);
1158 if (button != BUTTON_NONE) { 1133 if (button != BUTTON_NONE) {
1159 break; 1134 break;
1160 } 1135 }
1161 sleep(MAX(next_refresh - current_tick, 0) - 1); 1136 if (dopeek) { /* Peek only once per refresh when disk is */
1162 next_refresh = current_tick + HZ / peak_meter_fps; 1137 peak_meter_peek(); /* spinning, but as often as possible */
1163 peak_meter_peek(); 1138 dopeek = highperf; /* otherwise. */
1164 peak_meter_draw(x, y, width, height); 1139 yield();
1165 lcd_update_rect(x, y, width, height); 1140 } else {
1141 sleep(0); /* Sleep until end of current tick. */
1142 }
1143 if (TIME_AFTER(current_tick, next_refresh)) {
1144 peak_meter_draw(x, y, width, height);
1145 lcd_update_rect(x, y, width, height);
1146 next_refresh += HZ / PEAK_METER_FPS;
1147 dopeek = true;
1148 }
1166 } 1149 }
1150
1167 return button; 1151 return button;
1168} 1152}
1169 1153
1170#ifdef PM_DEBUG 1154#ifdef PM_DEBUG
1171static void peak_meter_clear_histogram(void) { 1155static void peak_meter_clear_histogram(void)
1156{
1172 int i = 0; 1157 int i = 0;
1173 for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) { 1158 for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) {
1174 ticks_per_redraw[i] = (unsigned int)0; 1159 ticks_per_redraw[i] = (unsigned int)0;
@@ -1179,7 +1164,8 @@ static void peak_meter_clear_histogram(void) {
1179 } 1164 }
1180} 1165}
1181 1166
1182bool peak_meter_histogram(void) { 1167bool peak_meter_histogram(void)
1168{
1183 int i; 1169 int i;
1184 int btn = BUTTON_NONE; 1170 int btn = BUTTON_NONE;
1185 while ((btn & BUTTON_OFF) != BUTTON_OFF ) 1171 while ((btn & BUTTON_OFF) != BUTTON_OFF )
@@ -1210,7 +1196,7 @@ bool peak_meter_histogram(void) {
1210 lcd_hline(0, x, y + i); 1196 lcd_hline(0, x, y + i);
1211 } 1197 }
1212 lcd_update(); 1198 lcd_update();
1213 1199
1214 btn = button_get(true); 1200 btn = button_get(true);
1215 if (btn == BUTTON_PLAY) { 1201 if (btn == BUTTON_PLAY) {
1216 peak_meter_clear_histogram(); 1202 peak_meter_clear_histogram();
diff --git a/apps/recorder/peakmeter.h b/apps/recorder/peakmeter.h
index 3c0a28bf3b..5513dfacf1 100644
--- a/apps/recorder/peakmeter.h
+++ b/apps/recorder/peakmeter.h
@@ -19,13 +19,14 @@
19#ifndef __PEAKMETER_H__ 19#ifndef __PEAKMETER_H__
20#define __PEAKMETER_H__ 20#define __PEAKMETER_H__
21 21
22#define PEAK_METER_FPS 20
23
22/*#define PM_DEBUG */ 24/*#define PM_DEBUG */
23#ifdef PM_DEBUG 25#ifdef PM_DEBUG
24extern bool peak_meter_histogram(void); 26extern bool peak_meter_histogram(void);
25#endif 27#endif
26 28
27extern bool peak_meter_enabled; 29extern bool peak_meter_enabled;
28extern int peak_meter_fps;
29 30
30extern void peak_meter_playback(bool playback); 31extern void peak_meter_playback(bool playback);
31extern void peak_meter_draw(int x, int y, int width, int height); 32extern void peak_meter_draw(int x, int y, int width, int height);
@@ -39,8 +40,8 @@ extern void peak_meter_set_min(int newmin);
39extern int peak_meter_get_min(void); 40extern int peak_meter_get_min(void);
40extern void peak_meter_set_max(int newmax); 41extern void peak_meter_set_max(int newmax);
41extern int peak_meter_get_max(void); 42extern int peak_meter_get_max(void);
42extern void peak_meter_set_use_dbfs(int use); 43extern void peak_meter_set_use_dbfs(bool use);
43extern int peak_meter_get_use_dbfs(void); 44extern bool peak_meter_get_use_dbfs(void);
44extern int calc_db (int isample); 45extern int calc_db (int isample);
45extern int peak_meter_db2sample(int db); 46extern int peak_meter_db2sample(int db);
46extern unsigned short peak_meter_scale_value(unsigned short val, int meterwidth); 47extern unsigned short peak_meter_scale_value(unsigned short val, int meterwidth);
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index 4e6c52ea84..a0280ecf1f 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -304,7 +304,7 @@ bool radio_screen(void)
304 if(search_dir) 304 if(search_dir)
305 button = button_get(false); 305 button = button_get(false);
306 else 306 else
307 button = button_get_w_tmo(HZ / peak_meter_fps); 307 button = button_get_w_tmo(HZ / PEAK_METER_FPS);
308 switch(button) 308 switch(button)
309 { 309 {
310 case FM_STOP: 310 case FM_STOP:
@@ -479,13 +479,10 @@ bool radio_screen(void)
479 /* Only display the peak meter when not recording */ 479 /* Only display the peak meter when not recording */
480 if(!audio_status()) 480 if(!audio_status())
481 { 481 {
482 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
483 lcd_fillrect(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh);
484 lcd_set_drawmode(DRMODE_SOLID);
485 peak_meter_draw(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh); 482 peak_meter_draw(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh);
486 lcd_update_rect(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh); 483 lcd_update_rect(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh);
487 } 484 }
488 485
489 if(TIME_AFTER(current_tick, timeout)) 486 if(TIME_AFTER(current_tick, timeout))
490 { 487 {
491 timeout = current_tick + HZ; 488 timeout = current_tick + HZ;
diff --git a/apps/settings.c b/apps/settings.c
index 4811ad2320..6fd2ec64bf 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -78,7 +78,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
78#include "pcm_playback.h" 78#include "pcm_playback.h"
79#endif 79#endif
80 80
81#define CONFIG_BLOCK_VERSION 25 81#define CONFIG_BLOCK_VERSION 26
82#define CONFIG_BLOCK_SIZE 512 82#define CONFIG_BLOCK_SIZE 512
83#define RTC_BLOCK_SIZE 44 83#define RTC_BLOCK_SIZE 44
84 84
@@ -349,8 +349,7 @@ static const struct bit_entry hd_bits[] =
349 /* peak meter */ 349 /* peak meter */
350 {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */ 350 {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */
351 "on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,2min,3min,5min,10min,20min,45min,90min" }, 351 "on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,2min,3min,5min,10min,20min,45min,90min" },
352 {1, S_O(peak_meter_performance), false, "peak meter busy", off_on }, 352 {5, S_O(peak_meter_hold), 3, "peak meter hold",
353 {5, S_O(peak_meter_hold), 3, "peak meter hold",
354 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" }, 353 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
355 {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */ 354 {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */
356 {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on }, 355 {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on },
diff --git a/apps/settings.h b/apps/settings.h
index d0041d2e99..c59fe47532 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -250,7 +250,6 @@ struct user_settings
250 int peak_meter_hold; /* hold time for peak meter in 1/100 s */ 250 int peak_meter_hold; /* hold time for peak meter in 1/100 s */
251 int peak_meter_clip_hold; /* hold time for clips */ 251 int peak_meter_clip_hold; /* hold time for clips */
252 bool peak_meter_dbfs; /* show linear or dbfs values */ 252 bool peak_meter_dbfs; /* show linear or dbfs values */
253 bool peak_meter_performance; /* true: high performance, else save energy*/
254 int peak_meter_min; /* range minimum */ 253 int peak_meter_min; /* range minimum */
255 int peak_meter_max; /* range maximum */ 254 int peak_meter_max; /* range maximum */
256 bool car_adapter_mode; /* 0=off 1=on */ 255 bool car_adapter_mode; /* 0=off 1=on */
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index 9f7259620e..bbbeca3683 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -318,16 +318,6 @@ static bool volume_type(void)
318 INT, names, 2, NULL); 318 INT, names, 2, NULL);
319} 319}
320 320
321#ifdef PM_DEBUG
322static bool peak_meter_fps_menu(void) {
323 bool retval = false;
324 retval = set_int( "Refresh rate", "/s", UNIT_PER_SEC,
325 &peak_meter_fps,
326 NULL, 1, 5, 40, NULL);
327 return retval;
328}
329#endif /* PM_DEBUG */
330
331/** 321/**
332 * Menu to set the hold time of normal peaks. 322 * Menu to set the hold time of normal peaks.
333 */ 323 */
@@ -545,25 +535,6 @@ static bool peak_meter_max(void) {
545} 535}
546 536
547/** 537/**
548 * Menu to select wether the meter is in
549 * precision or in energy saver mode
550 */
551static bool peak_meter_performance(void) {
552 bool retval = false;
553 retval = set_bool_options(str(LANG_PM_PERFORMANCE),
554 &global_settings.peak_meter_performance,
555 STR(LANG_PM_HIGH_PERFORMANCE), STR(LANG_PM_ENERGY_SAVER),
556 NULL);
557
558 if (global_settings.peak_meter_performance) {
559 peak_meter_fps = 25;
560 } else {
561 peak_meter_fps = 20;
562 }
563 return retval;
564}
565
566/**
567 * Menu to configure the peak meter 538 * Menu to configure the peak meter
568 */ 539 */
569static bool peak_meter_menu(void) 540static bool peak_meter_menu(void)
@@ -575,10 +546,6 @@ static bool peak_meter_menu(void)
575 { ID2P(LANG_PM_RELEASE) , peak_meter_release }, 546 { ID2P(LANG_PM_RELEASE) , peak_meter_release },
576 { ID2P(LANG_PM_PEAK_HOLD), peak_meter_hold }, 547 { ID2P(LANG_PM_PEAK_HOLD), peak_meter_hold },
577 { ID2P(LANG_PM_CLIP_HOLD), peak_meter_clip_hold }, 548 { ID2P(LANG_PM_CLIP_HOLD), peak_meter_clip_hold },
578 { ID2P(LANG_PM_PERFORMANCE), peak_meter_performance },
579#ifdef PM_DEBUG
580 { "Refresh rate" , -1 , peak_meter_fps_menu },
581#endif
582 { ID2P(LANG_PM_SCALE) , peak_meter_scale }, 549 { ID2P(LANG_PM_SCALE) , peak_meter_scale },
583 { ID2P(LANG_PM_MIN) , peak_meter_min }, 550 { ID2P(LANG_PM_MIN) , peak_meter_min },
584 { ID2P(LANG_PM_MAX) , peak_meter_max }, 551 { ID2P(LANG_PM_MAX) , peak_meter_max },
diff --git a/apps/wps.c b/apps/wps.c
index bf0283015f..784289ada4 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -391,46 +391,29 @@ long wps_show(void)
391#ifdef HAVE_LCD_BITMAP 391#ifdef HAVE_LCD_BITMAP
392 /* when the peak meter is enabled we want to have a 392 /* when the peak meter is enabled we want to have a
393 few extra updates to make it look smooth. On the 393 few extra updates to make it look smooth. On the
394 other hand we don't want to waste energy if it 394 other hand we don't want to waste energy if it
395 isn't displayed */ 395 isn't displayed */
396 if (peak_meter_enabled) { 396 if (peak_meter_enabled) {
397 int i; 397 long next_refresh = current_tick;
398 398 long next_big_refresh = current_tick + HZ / 5;
399 /* In high performance mode we read out the mas as 399 button = BUTTON_NONE;
400 often as we can. There is no sleep for cpu */ 400 while (TIME_BEFORE(current_tick, next_big_refresh)) {
401 if (global_settings.peak_meter_performance) { 401 button = button_get(false);
402 long next_refresh = current_tick; 402 if (button != BUTTON_NONE) {
403 long next_big_refresh = current_tick + HZ / 5; 403 break;
404 button = BUTTON_NONE;
405 while (!TIME_AFTER(current_tick, next_big_refresh)) {
406 button = button_get(false);
407 if (button != BUTTON_NONE) {
408 break;
409 }
410 peak_meter_peek();
411 sleep(1);
412
413 if (TIME_AFTER(current_tick, next_refresh)) {
414 wps_refresh(id3, nid3, 0, WPS_REFRESH_PEAK_METER);
415 next_refresh = current_tick + HZ / peak_meter_fps;
416 }
417 } 404 }
418 } 405 peak_meter_peek();
419 406 sleep(0); /* Sleep until end of current tick. */
420 /* In energy saver mode the cpu may sleep a 407
421 little bit while waiting for buttons */ 408 if (TIME_AFTER(current_tick, next_refresh)) {
422 else {
423 for (i = 0; i < 4; i++) {
424 button = button_get_w_tmo(HZ / peak_meter_fps);
425 if (button != 0) {
426 break;
427 }
428 wps_refresh(id3, nid3, 0, WPS_REFRESH_PEAK_METER); 409 wps_refresh(id3, nid3, 0, WPS_REFRESH_PEAK_METER);
410 next_refresh += HZ / PEAK_METER_FPS;
429 } 411 }
430 } 412 }
431 } 413
432 414 }
433 /* The peak meter is disabled 415
416 /* The peak meter is disabled
434 -> no additional screen updates needed */ 417 -> no additional screen updates needed */
435 else { 418 else {
436 button = button_get_w_tmo(HZ/5); 419 button = button_get_w_tmo(HZ/5);
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index f75ec69857..5597f69bdb 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -99,15 +99,15 @@ static void dma_stop(void)
99 99
100/* 100/*
101 * This function goes directly into the DMA buffer to calculate the left and 101 * This function goes directly into the DMA buffer to calculate the left and
102 * right peak values. To avoid missing peaks it tries to look forward a full 102 * right peak values. To avoid missing peaks it tries to look forward two full
103 * refresh period (1/20 sec) although it's always possible that the entire 103 * peek periods (2/HZ sec, 100% overlap), although it's always possible that
104 * period will not be visible. To reduce CPU load it only looks at every 104 * the entire period will not be visible. To reduce CPU load it only looks at
105 * third sample, and this can be reduced even further if needed (even every 105 * every third sample, and this can be reduced even further if needed (even
106 * tenth sample would still be pretty accurate). 106 * every tenth sample would still be pretty accurate).
107 */ 107 */
108 108
109#define PEAK_SAMPLES 2205 /* 44100 sample rate / 20 Hz refresh */ 109#define PEAK_SAMPLES (44100*2/HZ) /* 44100 samples * 2 / 100 Hz tick */
110#define PEAK_STRIDE 3 /* every 3rd sample is plenty... */ 110#define PEAK_STRIDE 3 /* every 3rd sample is plenty... */
111 111
112void pcm_calculate_peaks(int *left, int *right) 112void pcm_calculate_peaks(int *left, int *right)
113{ 113{