Index: apps/settings.c
===================================================================
RCS file: /cvsroot/rockbox/apps/settings.c,v
retrieving revision 1.365
diff -u -r1.365 settings.c
--- apps/settings.c	3 Mar 2006 01:12:49 -0000	1.365
+++ apps/settings.c	16 Mar 2006 16:28:48 -0000
@@ -550,6 +550,17 @@
     {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"}, 
     {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"}, 
 #endif
+#if defined(HAVE_LCD_BITMAP) && (LCD_WIDTH > 111)
+    {2, S_O(rec_histogram_mode), 1, "histogram mode", NULL},
+    {2, S_O(rec_histogram_interval), 0, "histogram interval", "0.5s,1s,2s,4s"},
+#endif
+#ifdef HAVE_UDA1380
+    {3, S_O(rec_agc_cliptime), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"},
+    {4, S_O(rec_agc_preset_mic), 1, "agc mic preset", NULL}, /* 0...5 */
+    {4, S_O(rec_agc_preset_line), 1, "agc line preset", NULL}, /* 0...5 */
+    {8|SIGNED, S_O(rec_agc_maxgain_mic), 0, "agc maximum mic gain", NULL},
+    {8|SIGNED, S_O(rec_agc_maxgain_line), 0, "agc maximum line gain", NULL},
+#endif
     /* If values are just added to the end, no need to bump the version. */
     /* new stuff to be added at the end */
 
Index: apps/settings.h
===================================================================
RCS file: /cvsroot/rockbox/apps/settings.h,v
retrieving revision 1.206
diff -u -r1.206 settings.h
--- apps/settings.h	3 Mar 2006 01:12:49 -0000	1.206
+++ apps/settings.h	16 Mar 2006 16:28:49 -0000
@@ -258,6 +258,31 @@
     int rec_stop_gap;       /* index of trig_durations */
     int rec_trigger_mode;   /* see TRIG_MODE_XXX constants */
 
+#ifdef HAVE_UDA1380
+    int rec_agc_preset_mic; /* AGC mic preset modes:
+                             0 = Off
+                             1 = Safety (clip)
+                             2 = Live (slow)
+                             3 = DJ-Set (slow)
+                             4 = Medium
+                             5 = Voice (fast) */
+    int rec_agc_preset_line; /* AGC line-in preset modes:
+                              0 = Off
+                              1 = Safety (clip)
+                              2 = Live (slow)
+                              3 = DJ-Set (slow)
+                              4 = Medium
+                              5 = Voice (fast) */
+    int rec_agc_cliptime;     /* 0.2, 0.4, 0.6, 0.8, 1s */
+    int rec_agc_maxgain_mic;  /* AGC maximum mic gain */
+    int rec_agc_maxgain_line; /* AGC maximum line-in gain */
+#endif
+
+#if defined(HAVE_LCD_BITMAP) && (LCD_WIDTH > 111)
+    int rec_histogram_mode;     /* small lin/log /w balance, big lin/log */
+    int rec_histogram_interval; /* interval: 0.5s, 1s, 2s, 4s */
+#endif
+
     /* device settings */
 
     int contrast;   /* lcd contrast:          0-63 0=low 63=high            */
Index: apps/sound_menu.c
===================================================================
RCS file: /cvsroot/rockbox/apps/sound_menu.c,v
retrieving revision 1.98
diff -u -r1.98 sound_menu.c
--- apps/sound_menu.c	19 Feb 2006 12:45:32 -0000	1.98
+++ apps/sound_menu.c	16 Mar 2006 16:28:52 -0000
@@ -363,6 +363,57 @@
 }
 #endif /*CONFIG_BACKLIGHT */
 
+#ifdef HAVE_UDA1380
+static bool agc_preset(void)
+{
+    static const struct opt_items names[] = {
+        { STR(LANG_OFF) },
+        { STR(LANG_AGC_SAFETY) },
+        { STR(LANG_AGC_LIVE) },
+        { STR(LANG_AGC_DJSET) },
+        { STR(LANG_AGC_MEDIUM) },
+        { STR(LANG_AGC_VOICE) },
+    };
+    if (global_settings.rec_source)
+        return set_option(str(LANG_RECORD_AGC_PRESET),
+                          &global_settings.rec_agc_preset_line,
+                          INT, names, 6, NULL );
+    else
+        return set_option(str(LANG_RECORD_AGC_PRESET),
+                          &global_settings.rec_agc_preset_mic,
+                          INT, names, 6, NULL );
+}
+
+static bool agc_cliptime(void)
+{
+    static const struct opt_items names[] = {
+        { "200ms", TALK_ID(200, UNIT_MS) },
+        { "400ms", TALK_ID(400, UNIT_MS) },
+        { "600ms", TALK_ID(600, UNIT_MS) },
+        { "800ms", TALK_ID(800, UNIT_MS) },
+        { "1s", TALK_ID(1, UNIT_SEC) }
+    };
+    return set_option(str(LANG_RECORD_AGC_CLIPTIME),
+                      &global_settings.rec_agc_cliptime,
+                      INT, names, 5, NULL );
+}
+#endif /* HAVE_UDA1380 */
+
+#if LCD_HEIGHT > 111
+static bool history_interval(void)
+{
+    static const struct opt_items names[] = {
+        { "0.5s", TALK_ID(500, UNIT_MS) },
+        { "1s", TALK_ID(1, UNIT_SEC) },
+        { "2s", TALK_ID(2, UNIT_SEC) },
+        { "4s", TALK_ID(4, UNIT_SEC) }
+    };
+    return set_option(str(LANG_RECORDING_HISTOGRAM_INTERVAL),
+                      &global_settings.rec_histogram_interval,
+                      INT, names, 4, NULL );
+}
+#endif /* LCD_HEIGHT > 111 */
+
 #endif /* HAVE_RECORDING */
 
 static bool chanconf(void)
@@ -653,7 +704,7 @@
 
         peak_meter_draw_trig(0, LCD_HEIGHT - 8 - TRIG_HEIGHT);
 
-        button = peak_meter_draw_get_btn(0, LCD_HEIGHT - 8, LCD_WIDTH, 8);
+        button = peak_meter_draw_get_btn(0, LCD_HEIGHT - 8, 8);
 
         lcd_update();
 
@@ -805,7 +856,7 @@
 {
     int m;
     int i = 0;
-    struct menu_item items[13];
+    struct menu_item items[15];
     bool result;
 
 #ifndef HAVE_UDA1380
@@ -838,6 +889,16 @@
     items[i].desc = ID2P(LANG_RECORD_TRIGGER);
     items[i++].function = rectrigger;
 #endif
+#ifdef HAVE_UDA1380
+    items[i].desc = ID2P(LANG_RECORD_AGC_PRESET);
+    items[i++].function = agc_preset;
+    items[i].desc = ID2P(LANG_RECORD_AGC_CLIPTIME);
+    items[i++].function = agc_cliptime;
+#endif
+#if LCD_WIDTH > 111
+    items[i].desc = ID2P(LANG_RECORDING_HISTOGRAM_INTERVAL);
+    items[i++].function = history_interval;
+#endif
 
     m=menu_init( items, i, NULL, NULL, NULL, NULL);
     result = menu_run(m);
Index: apps/status.c
===================================================================
RCS file: /cvsroot/rockbox/apps/status.c,v
retrieving revision 1.83
diff -u -r1.83 status.c
--- apps/status.c	4 Dec 2005 15:23:46 -0000	1.83
+++ apps/status.c	16 Mar 2006 16:28:52 -0000
@@ -46,6 +46,9 @@
 #ifdef CONFIG_TUNER
 #include "radio.h"
 #endif
+#if CONFIG_CODEC == SWCODEC
+#include "pcm_record.h"
+#endif
 
 enum playmode ff_mode;
 
@@ -99,6 +102,17 @@
                 return STATUS_RECORD;
         }
     }
+#elif (CONFIG_CODEC == SWCODEC) && HAVE_RECORDING
+    else
+    {
+        if(pcm_rec_status() & AUDIO_STATUS_RECORD)
+        {
+            if(pcm_rec_status() & AUDIO_STATUS_PAUSE)
+                return STATUS_RECORD_PAUSE;
+            else
+                return STATUS_RECORD;
+        }
+    }
 #endif
 
 #ifdef CONFIG_TUNER
Index: apps/gui/gwps-common.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v
retrieving revision 1.43
diff -u -r1.43 gwps-common.c
--- apps/gui/gwps-common.c	15 Mar 2006 20:16:21 -0000	1.43
+++ apps/gui/gwps-common.c	16 Mar 2006 16:28:58 -0000
@@ -1611,7 +1611,7 @@
 #endif
                 update_line = true;
             }
-            if (flags & refresh_mode & WPS_REFRESH_PEAK_METER && display->height >= LCD_HEIGHT) {
+            if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) {
                 /* peak meter */
                 int peak_meter_y;
 
@@ -1622,12 +1622,12 @@
                    line so that it is only displayed if no status bar is
                    visible. If so we neither want do draw nor enable the
                    peak meter. */
-                if (peak_meter_y + h <= LCD_HEIGHT) {
+                if (peak_meter_y + h <= display->height) {
                     /* found a line with a peak meter -> remember that we must
                        enable it later */
                     enable_pm = true;
-                    peak_meter_draw(0, peak_meter_y, LCD_WIDTH,
-                                    MIN(h, LCD_HEIGHT - peak_meter_y));
+                    peak_meter_screen(gwps->display, 0, peak_meter_y,
+                                    MIN(h, display->height - peak_meter_y));
                 }
             }
 #else
Index: apps/gui/icon.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/icon.c,v
retrieving revision 1.4
diff -u -r1.4 icon.c
--- apps/gui/icon.c	16 Nov 2005 02:12:25 -0000	1.4
+++ apps/gui/icon.c	16 Mar 2006 16:28:59 -0000
@@ -26,12 +26,14 @@
 void screen_put_iconxy(struct screen * display, int x, int y, ICON icon)
 {
 #ifdef HAVE_LCD_BITMAP
+    int width, height;
     int xpos, ypos;
+    display->getstringsize((unsigned char *)"A", &width, &height);
     xpos = x*CURSOR_WIDTH;
-    ypos = y*display->char_height + display->getymargin();
+    ypos = y*height + display->getymargin();
 
-    if ( display->char_height > CURSOR_HEIGHT )/* center the cursor */
-        ypos += (display->char_height - CURSOR_HEIGHT) / 2;
+    if ( height > CURSOR_HEIGHT )/* center the cursor */
+        ypos += (height - CURSOR_HEIGHT) / 2;
     if(icon==0)/* Don't display invalid icons */
         screen_clear_area(display, xpos, ypos, CURSOR_WIDTH, CURSOR_HEIGHT);
     else
Index: apps/lang/deutsch.lang
===================================================================
RCS file: /cvsroot/rockbox/apps/lang/deutsch.lang,v
retrieving revision 1.92
diff -u -r1.92 deutsch.lang
--- apps/lang/deutsch.lang	6 Dec 2005 13:27:00 -0000	1.92
+++ apps/lang/deutsch.lang	16 Mar 2006 16:29:03 -0000
@@ -928,13 +928,13 @@
 desc: in the recording screen
 eng: "Gain Left"
 voice: ""
-new: "V. Links"
+new: "Verst L"
 
 id: LANG_RECORDING_RIGHT
 desc: in the recording screen
 eng: "Gain Right"
 voice: ""
-new: "V. Rechts"
+new: "Verst R"
 
 id: LANG_RECORDING_QUALITY
 desc: in the recording settings
@@ -3459,3 +3459,105 @@
 eng: "Mode:"
 voice: ""
 new: "Modus:"
+
+id: LANG_WARNING_DISKSPACE_LOW
+desc: in recording screen
+eng: "WARNING! Low Disk-Space!"
+voice:
+new: "WARNUNG! Festplatte fast voll!"
+
+id: LANG_WARNING_DISK_FULL
+desc: in recording screen
+eng: "Disk is full!"
+voice:
+new: "Festplatte ist voll!"
+
+id: LANG_WARNING_STOP_RECORDING
+desc: in recording screen
+eng: "Stopping Recording..."
+voice:
+new: "Stoppe Aufnahme..."
+
+id: LANG_RECORD_AGC_PRESET
+desc: automatic gain control in record settings
+eng: "Automatic Gain Control"
+voice:
+new: "Aut. Verstärkungs-Steuerung"
+
+id: LANG_AGC_VOICE_LIM
+desc: AGC preset
+eng: "Voice Limiter"
+voice:
+new: "Stimme Limiter"
+
+id: LANG_AGC_MEDIUM_LIM
+desc: AGC preset
+eng: "Medium Limiter"
+voice:
+new: "Mittel Limiter"
+
+id: LANG_AGC_DJSET_LIM
+desc: AGC preset
+eng: "DJ-Set Limiter"
+voice:
+new:
+
+id: LANG_AGC_LIVE_LIM
+desc: AGC preset
+eng: "Live Limiter"
+voice:
+new:
+
+id: LANG_AGC_SAFETY
+desc: AGC preset
+eng: "Safety (clip)"
+voice:
+new: "Sicherheit (Clip)"
+
+id: LANG_AGC_LIVE
+desc: AGC preset
+eng: "Live (slow)"
+voice:
+new: "Live (lang)"
+
+id: LANG_AGC_DJSET
+desc: AGC preset
+eng: "DJ-Set (slow)"
+voice:
+new: "DJ-Set"
+
+id: LANG_AGC_MEDIUM
+desc: AGC preset
+eng: "Medium"
+voice:
+new: "Mittel"
+
+id: LANG_AGC_VOICE
+desc: AGC preset
+eng: "Voice (fast)"
+voice:
+new: "Stimme (kurz)"
+
+id: LANG_RECORD_AGC_CLIPTIME
+desc: in record settings
+eng: "AGC clip time"
+voice:
+new: "AVS Clip Zeit"
+
+id: LANG_RECORDING_AGC_PRESET
+desc: automatic gain control in recording screen
+eng: "AGC"
+voice:
+new: "AVS"
+
+id: LANG_RECORDING_AGC_MAXGAIN
+desc: AGC maximum gain in recording screen
+eng: "AGC max. gain"
+voice:
+new: "AVS max. V."
+
+id: LANG_RECORDING_HISTOGRAM_INTERVAL
+desc: in record settings menu
+eng: "Histogram interval"
+voice:
+new: "Histogramm Abstand"
Index: apps/lang/english.lang
===================================================================
RCS file: /cvsroot/rockbox/apps/lang/english.lang,v
retrieving revision 1.226
diff -u -r1.226 english.lang
--- apps/lang/english.lang	4 Mar 2006 23:53:09 -0000	1.226
+++ apps/lang/english.lang	16 Mar 2006 16:29:08 -0000
@@ -939,13 +939,13 @@
 
 id: LANG_RECORDING_LEFT
 desc: in the recording screen
-eng: "Gain Left"
+eng: "Gain L"
 voice: ""
 new:
 
 id: LANG_RECORDING_RIGHT
 desc: in the recording screen
-eng: "Gain Right"
+eng: "Gain R"
 voice: ""
 new:
 
@@ -3796,3 +3796,105 @@
 eng: "Searching... %d found (%s)"
 voice: ""
 new:
+
+id: LANG_WARNING_DISKSPACE_LOW
+desc: in recording screen
+eng: "WARNING! Low Disk-Space!"
+voice:
+new:
+
+id: LANG_WARNING_DISK_FULL
+desc: in recording screen
+eng: "Disk is full!"
+voice:
+new:
+
+id: LANG_WARNING_STOP_RECORDING
+desc: in recording screen
+eng: "Stopping Recording..."
+voice:
+new:
+
+id: LANG_RECORD_AGC_PRESET
+desc: automatic gain control in record settings
+eng: "Automatic Gain Control"
+voice:
+new:
+
+id: LANG_AGC_VOICE_LIM
+desc: AGC preset
+eng: "Voice Limiter"
+voice:
+new:
+
+id: LANG_AGC_MEDIUM_LIM
+desc: AGC preset
+eng: "Medium Limiter"
+voice:
+new:
+
+id: LANG_AGC_DJSET_LIM
+desc: AGC preset
+eng: "DJ-Set Limiter"
+voice:
+new:
+
+id: LANG_AGC_LIVE_LIM
+desc: AGC preset
+eng: "Live Limiter"
+voice:
+new:
+
+id: LANG_AGC_SAFETY
+desc: AGC preset
+eng: "Safety (clip)"
+voice:
+new:
+
+id: LANG_AGC_LIVE
+desc: AGC preset
+eng: "Live (slow)"
+voice:
+new:
+
+id: LANG_AGC_DJSET
+desc: AGC preset
+eng: "DJ-Set (slow)"
+voice:
+new:
+
+id: LANG_AGC_MEDIUM
+desc: AGC preset
+eng: "Medium"
+voice:
+new:
+
+id: LANG_AGC_VOICE
+desc: AGC preset
+eng: "Voice (fast)"
+voice:
+new:
+
+id: LANG_RECORD_AGC_CLIPTIME
+desc: in record settings
+eng: "AGC clip time"
+voice:
+new:
+
+id: LANG_RECORDING_AGC_PRESET
+desc: automatic gain control in recording screen
+eng: "AGC"
+voice:
+new:
+
+id: LANG_RECORDING_AGC_MAXGAIN
+desc: AGC maximum gain in recording screen
+eng: "AGC max. gain"
+voice:
+new:
+
+id: LANG_RECORDING_HISTOGRAM_INTERVAL
+desc: in record settings menu
+eng: "Histogram interval"
+voice:
+new:
Index: apps/recorder/peakmeter.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/peakmeter.c,v
retrieving revision 1.32
diff -u -r1.32 peakmeter.c
--- apps/recorder/peakmeter.c	8 Mar 2006 20:38:16 -0000	1.32
+++ apps/recorder/peakmeter.c	16 Mar 2006 16:29:12 -0000
@@ -33,6 +33,7 @@
 #include "lang.h"
 #include "peakmeter.h"
 #include "audio.h"
+#include "screen_access.h"
 #ifdef CONFIG_BACKLIGHT
 #include "backlight.h"
 #endif
@@ -48,6 +49,8 @@
 
 #endif
 
+struct meter_scales scales[NB_SCREENS];
+
 #if !defined(SIMULATOR) && CONFIG_CODEC != SWCODEC
 /* Data source */
 static int pm_src_left = MAS_REG_DQPEAK_L;
@@ -59,12 +62,8 @@
 static int pm_cur_right;
 static int pm_max_left;        /* maximum values between peak meter draws */
 static int pm_max_right;
-
-/* Peak hold */
-static int pm_peak_left;       /* buffered peak values */
-static int pm_peak_right;
-static long pm_peak_timeout_l; /* peak hold timeouts */
-static long pm_peak_timeout_r;
+static int pm_peakhold_left;   /* max. peak values between peakhold calls */
+static int pm_peakhold_right;  /* used for AGC and histogram display */
 
 /* Clip hold */
 static bool pm_clip_left = false;  /* when true a clip has occurred */
@@ -82,6 +81,7 @@
 unsigned short peak_meter_range_max;  /* maximum of range in samples */
 static unsigned short pm_range;       /* range width in samples */
 static bool pm_use_dbfs = true;       /* true if peakmeter displays dBfs */
+bool level_check;                     /* true if peeked at peakmeter before drawing */
 static unsigned short pm_db_min = 0;      /* minimum of range in 1/100 dB */
 static unsigned short pm_db_max = 9000;   /* maximum of range in 1/100 dB */
 static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */
@@ -140,49 +140,41 @@
 
 /* precalculated peak values that represent magical
    dBfs values. Used to draw the scale */
-#define DB_SCALE_SRC_VALUES_SIZE 12
 static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
-    32752, /*   0 db */
-    22784, /* - 3 db */
-    14256, /* - 6 db */
-    11752, /* - 9 db */
-    9256,  /* -12 db */
-    4256,  /* -18 db */
-    2186,  /* -24 db */
-    1186,  /* -30 db */
-    373,   /* -40 db */
-    102,   /* -50 db */
-    33,    /* -60 db */
+    32736, /*   0 db */
+    22752, /* - 3 db */
+    16640, /* - 6 db */
+    11648, /* - 9 db */
+    8320,  /* -12 db */
+    4364,  /* -18 db */
+    2064,  /* -24 db */
+    1194,  /* -30 db */
+    363,   /* -40 db */
+    101,   /* -50 db */
+    34,    /* -60 db */
     0,     /* -inf   */
 };
 
 static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
 
-/* if db_scale_valid is false the content of
-   db_scale_lcd_coord needs recalculation */
-static bool db_scale_valid = false;
-
-/* contains the lcd x coordinates of the magical
-   scale values in db_scale_src_values */
-static int db_scale_lcd_coord[sizeof db_scale_src_values / sizeof (int)];
-
-
 /**
  * Calculates dB Value for the peak meter, uses peak value as input
  * @param int sample - The input value 
  *                    Make sure that 0 <= value < SAMPLE_RANGE
  *
- * @return int - The 2 digit fixed comma result of the euation
+ * @return int - The 2 digit fixed point result of the euation
  *               20 * log (sample / SAMPLE_RANGE) + 90
- *               Output range is 0-8961 (that is 0,0 - 89,6 dB).
+ *               Output range is 0-9000 (that is 0.0 - 90.0 dB).
  *               Normally 0dB is full scale, here it is shifted +90dB.
  *               The calculation is based on the results of a linear
  *               approximation tool written specifically for this problem
- *               by Andreas Zwirtes (radhard@gmx.de). The result hat an
+ *               by Andreas Zwirtes (radhard@gmx.de). The result has an
  *               accurracy of better than 2%. It is highly runtime optimized,
  *               the cascading if-clauses do an successive approximation on
  *               the input value. This avoids big lookup-tables and
  *               for-loops.
+ *               Improved by Jvo Studer for errors < 0.2dB for critical
+ *               range of -12dB to 0dB (78.0 to 90.0dB).
  */
 
 int calc_db (int isample) 
@@ -192,81 +184,69 @@
     long m;
     int istart;
 
-    /* Range 1-4 */
-    if (isample < 119) {
+    if (isample < 2308) { /* Range 1-5 */
 
-        /* Range 1-2 */
-        if (isample < 5) {
+        if (isample < 115) { /* Range 1-3 */
 
-            /* Range 1 */
-            if (isample < 1) {
-                istart = 0;
-                n = 0;
-                m = 5900;
-            }
+            if (isample < 24) {
 
-            /* Range 2 */
-            else {
-                istart = 1;
-                n = 59;
+                if (isample < 5) {
+                    istart = 1; /* Range 1 */
+                    n = 98;
                 m = 34950;
             }
-        }
-
-        /* Range 3-4 */
         else {
-
-            /* Range 3 */
-            if (isample < 24) {
-                istart = 5;
-                n = 1457;
+                    istart = 5; /* Range 2 */
+                    n = 1496;
                 m = 7168;
             }
+            }
+            else {
+                istart = 24;  /* Range 3 */
+                n = 2858;
+                m = 1498;
+            }
+        }
+        else { /* Range 4-5 */
 
-            /* Range 4 */
+            if (isample < 534) {
+                istart = 114; /* Range 4 */
+                n = 4207;
+                m = 319;
+            }
             else {
-                istart = 24;
-                n = 2819;
-                m = 1464;
+                istart = 588; /* Range 5 */
+                n = 5583;
+                m = 69;
             }
         }
     }
 
-    /* Range 5-8 */
-    else {
+    else {  /* Range 6-9 */
 
-        /* Range 5-6 */
-        if (isample < 2918) {
+        if (isample < 12932) {
 
-            /* Range 5 */
-            if (isample < 592) {
-                istart = 119;
-                n = 4210;
-                m = 295;
+            if (isample < 6394) {
+                istart = 2608; /* Range 6 */
+                n = 6832;
+                m = 21;
             }
-
-            /* Range 6 */
             else {
-                istart = 592;
-                n = 5605;
-                m = 60;
+                istart = 7000; /* Range 7 */
+                n = 7682;
+                m = 9;
             }
         }
-
-        /* Range 7-8 */
         else {
 
-            /* Range 7 */
-            if (isample < 15352) {
-                istart = 2918;
-                n = 7001;
-                m = 12;
+            if (isample < 22450) {
+                istart = 13000; /* Range 8 */
+                n = 8219;
+                m = 5;
             }
-
-            /* Range 8 */
             else {
-                istart = 15352;
-                n = 8439;
+                istart = 22636; /* Range 9 */
+                n = 8697;
                 m = 3;
             }
         }
@@ -368,7 +348,9 @@
 
     pm_db_min = calc_db(peak_meter_range_min);
     pm_db_range = pm_db_max - pm_db_min;
-    db_scale_valid = false;
+    int i;
+    FOR_NB_SCREENS(i)
+        scales[i].db_scale_valid=false;    
 }
 
 /**
@@ -410,7 +392,9 @@
 
     pm_db_max = calc_db(peak_meter_range_max);
     pm_db_range = pm_db_max - pm_db_min;
-    db_scale_valid = false;
+    int i;
+    FOR_NB_SCREENS(i)
+        scales[i].db_scale_valid = false;
 }
 
 /**
@@ -449,8 +433,10 @@
  */
 void peak_meter_set_use_dbfs(bool use)
 {
+    int i;
     pm_use_dbfs = use;
-    db_scale_valid = false;
+    FOR_NB_SCREENS(i)
+        scales[i].db_scale_valid = false;
 }
 
 /**
@@ -713,7 +699,8 @@
             break;
     }
 #endif
-
+    /* check levels next time peakmeter drawn */
+    level_check = true;
 #ifdef PM_DEBUG
     peek_calls++;
 #endif
@@ -731,6 +718,9 @@
        by peak_meter_peek since the last call of peak_meter_read_l */
     int retval = pm_max_left;
 
+    /* store max peak value for peak_meter_get_peakhold_x readout */
+    pm_peakhold_left = MAX(pm_max_left, pm_peakhold_left);
+
 #ifdef PM_DEBUG
     peek_calls = 0;
 #endif
@@ -752,6 +742,9 @@
        by peak_meter_peek since the last call of peak_meter_read_r */
     int retval = pm_max_right;
 
+    /* store max peak value for peak_meter_get_peakhold_x readout */
+    pm_peakhold_right = MAX(pm_max_right, pm_peakhold_right);
+
 #ifdef PM_DEBUG
     peek_calls = 0;
 #endif
@@ -762,6 +755,21 @@
 }
 
 /**
+ * Reads out the current peak-hold values since the last call.
+ * This is used by the histogram feature in the recording screen.
+ * Values are in the range 0 <= peak_x < MAX_PEAK. MAX_PEAK is typ 32767.
+ */
+extern void peak_meter_get_peakhold(int *peak_left, int *peak_right)
+{
+    if (peak_left)
+        *peak_left  = pm_peakhold_left;
+    if (peak_right)
+        *peak_right = pm_peakhold_right;
+    pm_peakhold_left  = 0;
+    pm_peakhold_right = 0;
+}
+
+/**
  * Reset the detected clips. This method is for
  * use by the user interface.
  * @param int unused - This parameter was added to
@@ -816,23 +824,27 @@
     }
     return retval;
 }
-
-
+void peak_meter_screen(struct screen *display, int x, int y, int height)
+{
+    peak_meter_draw(display, &scales[display->screen_type], x, y,
+                        display->width, height);
+}           
 /**
  * Draws a peak meter in the specified size at the specified position.
  * @param int x - The x coordinate. 
- *                Make sure that 0 <= x and x + width < LCD_WIDTH
+ *                Make sure that 0 <= x and x + width < display->width
  * @param int y - The y coordinate. 
- *                Make sure that 0 <= y and y + height < LCD_HEIGHT
+ *                Make sure that 0 <= y and y + height < display->height
  * @param int width - The width of the peak meter. Note that for display
  *                    of clips a 3 pixel wide area is used ->
  *                    width > 3
  * @param int height - The height of the peak meter. height > 3
  */
-void peak_meter_draw(int x, int y, int width, int height) 
+void peak_meter_draw(struct screen *display, struct meter_scales *scales,
+                         int x, int y, int width, int height) 
 {
+    static int left_level = 0, right_level = 0;
     int left = 0, right = 0;
-    static int last_left = 0, last_right = 0;
     int meterwidth = width - 3;
     int i;
 
@@ -844,17 +856,21 @@
     /* if disabled only draw the peak meter */
     if (peak_meter_enabled) {
 
-        /* read the volume info from MAS */
-        left  = peak_meter_read_l(); 
-        right = peak_meter_read_r();
+
+        if (level_check){
+            /* only read the volume info from MAS if peek since last read*/      
+            left_level  = peak_meter_read_l(); 
+            right_level = peak_meter_read_r();
+            level_check = false;
+        }
 
         /* scale the samples dBfs */
-        left  = peak_meter_scale_value(left, meterwidth);
-        right = peak_meter_scale_value(right, meterwidth);
+        left  = peak_meter_scale_value(left_level, meterwidth);
+        right = peak_meter_scale_value(right_level, meterwidth);        
     
-        /* if the scale has changed -> recalculate the scale 
+         /*if the scale has changed -> recalculate the scale 
            (The scale becomes invalid when the range changed.) */
-        if (!db_scale_valid){
+        if (!scales->db_scale_valid){
 
             if (pm_use_dbfs) {
                 db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
@@ -862,7 +878,7 @@
                     /* find the real x-coords for predefined interesting
                        dBfs values. These only are recalculated when the
                        scaling of the meter changed. */
-                        db_scale_lcd_coord[i] = 
+                        scales->db_scale_lcd_coord[i] = 
                             peak_meter_scale_value(
                                 db_scale_src_values[i], 
                                 meterwidth - 1);
@@ -873,7 +889,7 @@
             else {
                 db_scale_count = 10;
                 for (i = 0; i < db_scale_count; i++) {
-                    db_scale_lcd_coord[i] = 
+                    scales->db_scale_lcd_coord[i] = 
                         (i * (MAX_PEAK / 10) - peak_meter_range_min) *
                         meterwidth / pm_range;
                 }
@@ -881,20 +897,20 @@
 
             /* mark scale valid to avoid recalculating dBfs values
                of the scale. */
-            db_scale_valid = true;
+            scales->db_scale_valid = true;
         }
 
         /* apply release */
-        left  = MAX(left , last_left  - pm_peak_release);
-        right = MAX(right, last_right - pm_peak_release);
+        left  = MAX(left , scales->last_left  - pm_peak_release);
+        right = MAX(right, scales->last_right - pm_peak_release);
 
         /* reset max values after timeout */
-        if (TIME_AFTER(current_tick, pm_peak_timeout_l)){
-            pm_peak_left = 0;
+        if (TIME_AFTER(current_tick, scales->pm_peak_timeout_l)){
+            scales->pm_peak_left = 0;
         }
 
-        if (TIME_AFTER(current_tick, pm_peak_timeout_r)){
-            pm_peak_right = 0;
+        if (TIME_AFTER(current_tick, scales->pm_peak_timeout_r)){
+            scales->pm_peak_right = 0;
         }
 
         if (!pm_clip_eternal) {
@@ -910,51 +926,51 @@
         }
 
         /* check for new max values */
-        if (left > pm_peak_left) {
-            pm_peak_left = left - 1;
-            pm_peak_timeout_l =
+        if (left > scales->pm_peak_left) {
+            scales->pm_peak_left = left - 1;
+            scales->pm_peak_timeout_l =
                 current_tick + peak_time_out[pm_peak_hold];
         }
 
-        if (right > pm_peak_right) {
-            pm_peak_right = right - 1;
-            pm_peak_timeout_r = 
+        if (right > scales->pm_peak_right) {
+            scales->pm_peak_right = right - 1;
+            scales->pm_peak_timeout_r = 
                 current_tick + peak_time_out[pm_peak_hold];
         }
     }
 
     /* draw the peak meter */
-    lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
-    lcd_fillrect(x, y, width, height);
-    lcd_set_drawmode(DRMODE_SOLID);
+    display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
+    display->fillrect(x, y, width, height);
+    display->set_drawmode(DRMODE_SOLID);
 
     /* draw left */
-    lcd_fillrect (x, y, left, height / 2 - 2 );
-    if (pm_peak_left > 0) {
-        lcd_vline(x + pm_peak_left, y, y + height / 2 - 2 );
+    display->fillrect (x, y, left, height / 2 - 2 );
+    if (scales->pm_peak_left > 0) {
+        display->vline(x + scales->pm_peak_left, y, y + height / 2 - 2 );
     }
     if (pm_clip_left) {
-        lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1);
+        display->fillrect(x + meterwidth, y, 3, height / 2 - 1);
     }
 
     /* draw right */
-    lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2);
-    if (pm_peak_right > 0) {
-        lcd_vline( x + pm_peak_right, y + height / 2, y + height - 2);
+    display->fillrect(x, y + height / 2 + 1, right, height / 2 - 2);
+    if (scales->pm_peak_right > 0) {
+        display->vline( x + scales->pm_peak_right, y + height / 2, y + height - 2);
     }
     if (pm_clip_right) {
-        lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1);
+        display->fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1);
     }
 
     /* draw scale end */
-    lcd_vline(x + meterwidth, y, y + height - 2);
+    display->vline(x + meterwidth, y, y + height - 2);
 
-    lcd_set_drawmode(DRMODE_COMPLEMENT);
+    display->set_drawmode(DRMODE_COMPLEMENT);
     /* draw dots for scale marks */
     for (i = 0; i < db_scale_count; i++) {
         /* The x-coordinates of interesting scale mark points 
            have been calculated before */
-        lcd_drawpixel(db_scale_lcd_coord[i], y + height / 2 - 1);
+        display->drawpixel(scales->db_scale_lcd_coord[i], y + height / 2 - 1);
     }
     
 #ifdef HAVE_RECORDING
@@ -988,25 +1004,25 @@
     if (trig_status != TRIG_OFF) {
         int start_trigx, stop_trigx, ycenter;
 
-        lcd_set_drawmode(DRMODE_SOLID);
+        display->set_drawmode(DRMODE_SOLID);
         ycenter = y + height / 2;
         /* display threshold value */
         start_trigx = x+peak_meter_scale_value(trig_strt_threshold,meterwidth);
-        lcd_vline(start_trigx, ycenter - 2, ycenter);
+        display->vline(start_trigx, ycenter - 2, ycenter);
         start_trigx ++;
-        if (start_trigx < LCD_WIDTH) lcd_drawpixel(start_trigx, ycenter - 1);
+        if (start_trigx < display->width ) display->drawpixel(start_trigx, ycenter - 1);
 
         stop_trigx = x + peak_meter_scale_value(trig_stp_threshold,meterwidth);
-        lcd_vline(stop_trigx, ycenter - 2, ycenter);
-        if (stop_trigx > 0) lcd_drawpixel(stop_trigx - 1, ycenter - 1);
+        display->vline(stop_trigx, ycenter - 2, ycenter);
+        if (stop_trigx > 0) display->drawpixel(stop_trigx - 1, ycenter - 1);
     }
 #endif /*HAVE_RECORDING*/
 
 #ifdef PM_DEBUG
     /* display a bar to show how many calls to peak_meter_peek 
        have ocurred since the last display */
-    lcd_set_drawmode(DRMODE_COMPLEMENT);
-    lcd_fillrect(x, y, tmp, 3);
+    display->set_drawmode(DRMODE_COMPLEMENT);
+    display->fillrect(x, y, tmp, 3);
 
     if (tmp < PEEKS_PER_DRAW_SIZE) {
         peeks_per_redraw[tmp]++;
@@ -1019,14 +1035,14 @@
 
     /* display a bar to show how many ticks have passed since 
        the last redraw */
-    lcd_fillrect(x, y + height / 2, current_tick - pm_tick, 2);
+    display->fillrect(x, y + height / 2, current_tick - pm_tick, 2);
     pm_tick = current_tick;
 #endif
 
-    last_left = left;
-    last_right = right;
+    scales->last_left = left;
+    scales->last_right = right;
 
-    lcd_set_drawmode(DRMODE_SOLID);
+    display->set_drawmode(DRMODE_SOLID);
 }
 
 #ifdef HAVE_RECORDING
@@ -1171,11 +1187,12 @@
 }
 #endif
 
-int peak_meter_draw_get_btn(int x, int y, int width, int height)
+int peak_meter_draw_get_btn(int x, int y[], int height[])
 {
     int button = BUTTON_NONE;
     long next_refresh = current_tick;
     long next_big_refresh = current_tick + HZ / 10;
+    int i;
 #ifndef SIMULATOR
     bool highperf = !ata_disk_is_active();
 #else
@@ -1196,8 +1213,11 @@
             sleep(0);          /* Sleep until end of current tick. */
         }
         if (TIME_AFTER(current_tick, next_refresh)) {
-            peak_meter_draw(x, y, width, height);
-            lcd_update_rect(x, y, width, height);
+            FOR_NB_SCREENS(i)
+            {
+                peak_meter_screen(&screens[i], x, y[i], height[i]);
+                screens[i].update_rect(x, y[i], screens[i].width, height[i]);
+            }
             next_refresh += HZ / PEAK_METER_FPS;
             dopeek = true;
         }
Index: apps/recorder/peakmeter.h
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/peakmeter.h,v
retrieving revision 1.6
diff -u -r1.6 peakmeter.h
--- apps/recorder/peakmeter.h	29 Aug 2005 20:07:17 -0000	1.6
+++ apps/recorder/peakmeter.h	16 Mar 2006 16:29:12 -0000
@@ -29,12 +29,12 @@
 extern bool peak_meter_enabled;
 
 extern void peak_meter_playback(bool playback);
-extern void peak_meter_draw(int x, int y, int width, int height);
-extern int  peak_meter_draw_get_btn(int x, int y, int width, int height);
+extern int  peak_meter_draw_get_btn(int x, int y[], int height[]);
 extern void peak_meter_set_clip_hold(int time);
 extern void peak_meter_peek(void);
 extern void peak_meter_init_range( bool dbfs, int range_min, int range_max);
 extern void peak_meter_init_times(int release, int hold, int clip_hold);
+extern void peak_meter_get_peakhold(int *peak_left, int *peak_right);
 
 extern void peak_meter_set_min(int newmin);
 extern int  peak_meter_get_min(void);
@@ -80,4 +80,24 @@
 extern unsigned short peak_meter_range_min;
 extern unsigned short peak_meter_range_max;
 
+#define DB_SCALE_SRC_VALUES_SIZE 12
+struct meter_scales{
+    /* buffered peak values */
+    int pm_peak_left;
+    int pm_peak_right;
+    /* if db_scale_valid is false the content of
+       db_scale_lcd_coord needs recalculation */
+    bool db_scale_valid;
+    /* contains the lcd x coordinates of the magical
+       scale values in db_scale_src_values */
+    int db_scale_lcd_coord[DB_SCALE_SRC_VALUES_SIZE];
+    int last_left;
+    int last_right;
+    /* peak hold timeouts */
+    long pm_peak_timeout_l;
+    long pm_peak_timeout_r;
+};
+extern void peak_meter_draw(struct screen *display, struct meter_scales *meter_scales,
+                                int x, int y, int width, int height);
+extern void peak_meter_screen(struct screen *display, int x, int y, int height);
 #endif /* __PEAKMETER_H__ */
Index: apps/recorder/radio.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/radio.c,v
retrieving revision 1.92
diff -u -r1.92 radio.c
--- apps/recorder/radio.c	7 Mar 2006 11:49:06 -0000	1.92
+++ apps/recorder/radio.c	16 Mar 2006 16:29:14 -0000
@@ -768,11 +768,17 @@
             /* Only display the peak meter when not recording */
             if(!audio_status())
             {
-                /* just main screen for the time being */
+
 #if CONFIG_CODEC != SWCODEC
-                peak_meter_draw(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4), LCD_WIDTH, fh);
+                FOR_NB_SCREENS(i)
+                {
+                    peak_meter_screen(&screens[i],0,
+                                          STATUSBAR_HEIGHT + fh*(top_of_screen + 4), fh);
+                    screens[i].update_rect(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4),
+                                               screens[i].width, fh);
+                }
 #endif
-                screens[SCREEN_MAIN].update_rect(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4), screens[SCREEN_MAIN].width, fh);
+
             }
 
             if(TIME_AFTER(current_tick, timeout))
Index: apps/recorder/recording.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/recording.c,v
retrieving revision 1.102
diff -u -r1.102 recording.c
--- apps/recorder/recording.c	1 Mar 2006 22:27:11 -0000	1.102
+++ apps/recorder/recording.c	16 Mar 2006 16:29:19 -0000
@@ -43,6 +43,7 @@
 #include "lang.h"
 #include "font.h"
 #include "icons.h"
+#include "icon.h"
 #include "screens.h"
 #include "peakmeter.h"
 #include "statusbar.h"
@@ -60,6 +61,11 @@
 #include "sound.h"
 #include "ata.h"
 #include "splash.h"
+#include "screen_access.h"
+#include "fat.h"
+#include "power.h"
+#include "powermgmt.h"
+#include "backlight.h"
 #ifdef HAVE_RECORDING
 
 
@@ -104,6 +110,17 @@
 #define REC_DEC BUTTON_LEFT
 #endif
 
+#if (CONFIG_REMOTE_KEYPAD == H100_REMOTE) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
+#define REC_RC_SHUTDOWN (BUTTON_RC_STOP | BUTTON_REPEAT)
+#define REC_RC_STOPEXIT BUTTON_RC_STOP
+#define REC_RC_RECPAUSE BUTTON_RC_ON
+#define REC_RC_INC BUTTON_RC_BITRATE
+#define REC_RC_DEC BUTTON_RC_SOURCE
+#define REC_RC_NEXT BUTTON_RC_FF
+#define REC_RC_PREV BUTTON_RC_REW
+#define REC_RC_SETTINGS BUTTON_RC_MODE
+#endif
+
 bool f2_rec_screen(void);
 bool f3_rec_screen(void);
 
@@ -122,7 +139,17 @@
 #define REC_FILE_ENDING ".mp3"
 #endif
 
-#define MAX_FILE_SIZE 0x7FF00000 /* 2 GB - 1 MB */
+#ifdef HAVE_UDA1380
+#define HAVE_AGC /* only for codecs with 0.5dB gain resolution */
+#endif
+
+#if defined(HAVE_LCD_BITMAP) && (LCD_HEIGHT > 111)
+#define HAVE_HISTOGRAM /* only for bigger screens */
+#endif
+
+#define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 8 MB */
+#define MIN_DISK_SPACE 64        /* minimum remaining disk space */
+unsigned long disk_space = 0;
 
 const char* const freq_str[6] =
 {
@@ -134,6 +161,76 @@
     "16kHz"
 };
 
+/* Timing counters:
+ * peak_time is incremented every 0.2s, every 2nd run of record screen loop.
+ * hist_time is incremented every 0.5s, display update.
+ * peak_time is the counter of the peak hold read and agc process,
+ * overflow every 13 years 8-)
+ */
+static long peak_time = 0;
+static long hist_time = 0;
+
+static short peak_valid_mem[4];
+#define BAL_MEM_SIZE 24
+static short balance_mem[BAL_MEM_SIZE];
+
+/* Automatic Gain Control */
+#ifdef HAVE_AGC
+#define AGC_MODE_SIZE 5
+static char* agc_preset_str[] =
+{ "Off", "S", "L", "D", "M", "V" };
+/*  "Off",
+    "Safety (clip)",
+    "Live (slow)",
+    "DJ-Set (slow)",
+    "Medium",
+    "Voice (fast)"  */
+#define AGC_CLIP 32766
+#define AGC_PEAK 29883 /* fast gain reduction threshold -0.8dB */
+#define AGC_HIGH 27254 /* accelerated gain reduction threshold -1.6dB */
+#define AGC_IMG    823 /* threshold for balance control -32dB */
+/* autogain high level thresholds (-3dB, -7dB, -4dB, -5dB, -5dB) */
+const short agc_th_hi[AGC_MODE_SIZE] =
+{ 23197, 14637, 21156, 18428, 18426 };
+/* autogain low level thresholds (-14dB, -11dB, -6dB, -7dB, -8dB) */
+const short agc_th_lo[AGC_MODE_SIZE] =
+{ 6538, 9235, 16422, 14636, 13045 };
+/* autogain threshold times [1/5s] or [200ms] */
+const short agc_tdrop[AGC_MODE_SIZE] =
+{ 900,  225, 150, 60, 8 };
+const short agc_trise[AGC_MODE_SIZE] =
+{ 9000, 750, 400, 150, 20 };
+const short agc_tbal[AGC_MODE_SIZE] =
+{ 4500, 500, 300, 100, 15 };
+/* AGC operation */
+static bool agc_enable = true;
+static short agc_preset;
+/* AGC levels */
+static int agc_left = 0;
+static int agc_right = 0;
+/* AGC time since high target volume was exceeded */
+static short agc_droptime = 0;
+/* AGC time since volume fallen below low target */
+static short agc_risetime = 0;
+/* AGC balance time exceeding +/- 0.7dB */
+static short agc_baltime = 0;
+/* AGC maximum gain */
+static short agc_maxgain;
+#endif /* HAVE_AGC */
+
+/* Histogram data, only for bigger screens */
+#ifdef HAVE_HISTOGRAM
+#define HIST_Y (LCD_HEIGHT - 1)
+#define HIST_W (LCD_WIDTH / 2 - 4)
+static short history_mode;
+static short hist_time_interval = 1; /* 1, 2, 4, 8 */
+static int hist_l = 0;
+static int hist_r = 0;
+static unsigned char history_l[HIST_W];
+static unsigned char history_r[HIST_W];
+#endif
+
+
 static void set_gain(void)
 {
     if(global_settings.rec_source == SOURCE_MIC)
@@ -227,13 +324,40 @@
 {
     int max_cursor;
     
-    if(cursor < 0)
+    if(cursor < 0) {
         cursor = 0;
+#ifdef HAVE_HISTOGRAM
+        int i;
+        history_mode++;
+        if (history_mode == 2) {
+            for (i=0; i < HIST_W; i++) {
+                history_l[i] = history_l[i] * 2;
+                history_r[i] = history_r[i] * 2;
+            }
+        } else if (history_mode == 4) {
+            for (i=0; i < HIST_W; i++) {
+                history_l[i] = history_l[i] / 2;
+                history_r[i] = history_r[i] / 2;
+            }
+            history_mode = 0;
+        }
+#endif
+    }
 
+#ifdef HAVE_AGC
+    if (global_settings.rec_source == SOURCE_MIC)
+    {
+        if(cursor == 2)
+            cursor = 4;
+        else if(cursor == 3)
+            cursor = 1;
+    }
+    max_cursor = 5;
+#else
     switch(global_settings.rec_source)
     {
     case SOURCE_MIC:
-        max_cursor = 1;
+        maxcursor = 1;
         break;
     case SOURCE_LINE:
         max_cursor = 3;
@@ -242,6 +366,7 @@
         max_cursor = 0;
         break;
     }
+#endif /* HAVE_AGC */
 
     if(cursor > max_cursor)
         cursor = max_cursor;
@@ -488,6 +613,229 @@
 }
 #endif /* UDA1380 */
 
+/* Read peak meter values & calculate balance.
+ * Returns validity of peak values.
+ * Used for automatic gain control and history diagram.
+ */
+bool read_peak_levels(int *peak_l, int *peak_r, int *balance)
+{
+    peak_meter_get_peakhold(peak_l, peak_r);
+    peak_valid_mem[peak_time % 3] = *peak_l;
+    if (((peak_valid_mem[0] == peak_valid_mem[1]) &&
+         (peak_valid_mem[1] == peak_valid_mem[2])) &&
+        ((*peak_l < 32767) || ata_disk_is_active()))
+            return false;
+
+    if (*peak_r > *peak_l)
+        balance_mem[peak_time % BAL_MEM_SIZE] =
+            MIN((10000 * *peak_r) / *peak_l - 10000, 15118);
+    else
+        balance_mem[peak_time % BAL_MEM_SIZE] =
+            MAX(10000 - (10000 * *peak_l) / *peak_r, -15118);
+    *balance = 0;
+    int i;
+    for (i = 0; i < BAL_MEM_SIZE; i++)
+        *balance += balance_mem[i];
+    *balance = *balance / BAL_MEM_SIZE;
+
+#ifdef HAVE_HISTOGRAM
+    if (*peak_l > hist_l)
+        hist_l = *peak_l;
+    if (*peak_r > hist_r)
+        hist_r = *peak_r;
+#endif
+
+    return true;
+}
+
+#ifdef HAVE_AGC
+/* AGC helper function to check if maximum gain is reached */
+bool agc_gain_is_max(bool left, bool right, int ana_mic_step, int ana_line_step)
+{
+    /* range -128...+108 [0.5dB] */
+    short gain_current_l;
+    short gain_current_r;
+
+    if (agc_preset == 0)
+        return false;
+
+    if (global_settings.rec_source == SOURCE_LINE)
+    {
+        gain_current_l = global_settings.rec_linein_decimator_left_gain +
+                         global_settings.rec_left_gain * ana_line_step;
+        gain_current_r = global_settings.rec_linein_decimator_right_gain +
+                         global_settings.rec_right_gain * ana_line_step;
+    } else
+    {
+        gain_current_l = global_settings.rec_mic_decimator_left_gain +
+                         global_settings.rec_mic_gain * ana_mic_step;
+        gain_current_r = global_settings.rec_mic_decimator_right_gain +
+                         global_settings.rec_mic_gain * ana_mic_step;
+    }
+
+    return ((left && (gain_current_l >= agc_maxgain)) ||
+            (right && (gain_current_r >= agc_maxgain)));
+}
+
+/* 
+ * Handle automatic gain control (AGC).
+ * Change recording gain if peak_x levels are above or below
+ * target volume for specified timeouts.
+ */
+void auto_gain_control(int *peak_l, int *peak_r, int *balance,
+                       int ana_mic_size, int ana_line_size)
+{
+    int agc_mono;
+    short agc_mode;
+    bool increment;
+
+    if (*peak_l > agc_left)
+        agc_left = *peak_l;
+    else
+        agc_left -= (agc_left - *peak_l + 3) >> 2;
+    if (*peak_r > agc_right)
+        agc_right = *peak_r;
+    else
+        agc_right -= (agc_right - *peak_r + 3) >> 2;
+    agc_mono = (agc_left + agc_right) / 2;
+    
+    agc_mode = abs(agc_preset) - 1;
+    if (agc_mode < 0) {
+        agc_enable = false;
+        return;
+    }
+
+    /* Automatic balance control */
+    if ((agc_left > AGC_IMG) && (agc_right > AGC_IMG))
+    {
+        if (*balance < -556)
+        {
+            if (*balance > -900)
+                agc_baltime -= !(peak_time % 4); /* 0.47 - 0.75dB */
+            else if (*balance > -4125)
+                agc_baltime--;                   /* 0.75 - 3.00dB */
+            else if (*balance > -7579)
+                agc_baltime -= 2;                /* 3.00 - 4.90dB */
+            else
+                agc_baltime -= !(peak_time % 8); /* 4.90 - inf dB */
+            if (agc_baltime > 0)
+                agc_baltime -= (peak_time % 2);
+        }
+        else if (*balance > 556)
+        {
+            if (*balance < 900)
+                agc_baltime += !(peak_time % 4);
+            else if (*balance < 4125)
+                agc_baltime++;
+            else if (*balance < 7579)
+                agc_baltime += 2;
+            else
+                agc_baltime += !(peak_time % 8);
+            if (agc_baltime < 0)
+                agc_baltime += (peak_time % 2);
+        }
+
+        if ((*balance * agc_baltime) < 0)
+        {
+            if (*balance < 0)
+                agc_baltime -= peak_time % 2;
+            else
+                agc_baltime += peak_time % 2;
+        }
+
+        increment = ((agc_risetime / 2) > agc_droptime);
+        
+        if (agc_baltime < -agc_tbal[agc_mode])
+        {
+            if (!increment || !agc_gain_is_max(!increment, increment,
+                                              ana_mic_size, ana_line_size)) {
+                change_recording_gain(increment, !increment, increment,
+                                      ana_mic_size, ana_line_size);
+                set_gain();
+            }
+            agc_baltime = 0;
+        }
+        else if (agc_baltime > +agc_tbal[agc_mode])
+        {
+            if (!increment || !agc_gain_is_max(increment, !increment,
+                                              ana_mic_size, ana_line_size)) {
+                change_recording_gain(increment, increment, !increment,
+                                      ana_mic_size, ana_line_size);
+                set_gain();
+            }
+            agc_baltime = 0;
+        }
+    }
+    else if (!(hist_time % 4))
+    {
+        if (agc_baltime < 0)
+            agc_baltime++;
+        else
+            agc_baltime--;
+    }
+    
+    /* Automatic gain control */
+    if ((agc_left > agc_th_hi[agc_mode]) || (agc_right > agc_th_hi[agc_mode]))
+    {
+        if ((agc_left > AGC_CLIP) || (agc_right > AGC_CLIP))
+            agc_droptime += agc_tdrop[agc_mode] /
+                            (global_settings.rec_agc_cliptime + 1);
+        if (agc_left  > AGC_HIGH) {
+            agc_droptime++;
+            agc_risetime=0;
+            if (agc_left > AGC_PEAK)
+                agc_droptime += 2;
+        }
+        if (agc_right > AGC_HIGH) {
+            agc_droptime++;
+            agc_risetime=0;
+            if (agc_right > AGC_PEAK)
+                agc_droptime += 2;
+        }
+        if (agc_mono > agc_th_hi[agc_mode])
+            agc_droptime++;
+        else
+            agc_droptime += !(peak_time % 2);
+    
+        if (agc_droptime >= agc_tdrop[agc_mode])
+        {
+            change_recording_gain(false, true, true,
+                                  ana_mic_size, ana_line_size);
+            agc_droptime = 0;
+            agc_risetime = 0;
+            set_gain();
+        }
+        agc_risetime = MAX(agc_risetime - 1, 0);
+    }
+    else if (agc_mono < agc_th_lo[agc_mode])
+    {
+        if (agc_mono < (agc_th_lo[agc_mode] / 8))
+            agc_risetime += !(peak_time % 5);
+        else if (agc_mono < (agc_th_lo[agc_mode] / 2))
+            agc_risetime += 2;
+        else
+            agc_risetime++;
+    
+        if (agc_risetime >= agc_trise[agc_mode]) {
+            if (!agc_gain_is_max(true, true, ana_mic_size, ana_line_size)) {
+                change_recording_gain(true, true, true,
+                                      ana_mic_size, ana_line_size);
+                set_gain();
+            }
+            agc_risetime = 0;
+            agc_droptime = 0;
+        }
+        agc_droptime = MAX(agc_droptime - 1, 0);
+    }
+    else if (!(peak_time % 6)) /* on target level every 1.2 sec */
+    {
+        agc_risetime = MAX(agc_risetime - 1, 0);
+        agc_droptime = MAX(agc_droptime - 1, 0);
+    }
+}
+#endif /* HAVE_AGC */
+
+
 bool recording_screen(void)
 {
     long button;
@@ -495,7 +843,10 @@
     bool done = false;
     char buf[32];
     char buf2[32];
-    int w, h;
+    int font[2];
+    int w[2], h[2];
+    int pm_y[2], pm_h[2];
+    int line = 0;
     int update_countdown = 1;
     bool have_recorded = false;
     unsigned int seconds;
@@ -508,6 +859,84 @@
     bool led_state = false;
     int led_countdown = 2;
 #endif
+    unsigned long disk_free;
+    int bitrate;
+    int disk_time;
+    bool disk_was_active = false;
+    bool warn_message = true;
+    bool peak_read = false;
+    bool peak_valid = false;
+    int peak_l, peak_r;
+    int balance = 0;
+    int i;
+
+    memset(balance_mem, 0x00, BAL_MEM_SIZE);
+
+#ifdef HAVE_HISTOGRAM
+    int history_pos = 0;
+    int hist_height;
+    const short hist_size_h[2] = {17, 31};
+    /* 
+     * Peak histogram linear to logarithmic [dB] table.
+     * The thresholds are scaled between the corresponding
+     * dispayed values, e.g. -6dB is -5.5dB < level <= 6.5dB
+     */
+    const short hist_peak_lin2dB[2][31] =
+    {
+        /* Clip,  0,    -2,    -4,    -6,    -8,    -10 */
+        { 32767, 28539, 23197, 18427, 14637, 11627, 9236,
+        /* -12, -14,  -16,  -18,  -20,  -24,  -30, -36, -48, -inf */
+          7336, 5828, 4629, 3677, 2602, 1642, 734, 328, 104, 0 },
+        /* Clip,  0,    -1,    -2,    -3,    -4,    -5,    -6,    -7,    -8 */
+        { 32767, 30579, 27569, 24573, 21901, 19519, 17397, 15505, 13819, 12316,
+        /* -9,   -10,  -11,  -12,  -13,  -14,  -15,  -16,  -18,  -20,  -22 */
+          10977, 9783, 8719, 7771, 6926, 6173, 5502, 4629, 3677, 2921, 2320,
+        /* -24, -27,  -30, -33, -36, -39, -42, -48, -60, -inf */
+          1842, 1232, 872, 618, 437, 310, 207, 124, 33, 0 }
+    };
+    const char hist_level_marks[4][6] =
+    {
+        /* linear: 0, -6, -12, -24, -inf [dB] */
+        { 15,  8, 4, 1, 0, 0},
+        /* logarithmic: 0, -6, -12, -24, -48 [dB] */
+        { 15, 12, 9, 4, 1, 1},
+        /* linear: 0, -3, -6, -12, -24, -inf [dB] */
+        { 29, 21, 15,  7, 2, 0},
+        /* logarithmic: 0, -3, -6, -12, -24, -48 [dB] */
+        { 29, 26, 23, 17, 9, 2}
+    };
+    const short hist_balance_marks[12] =
+    /* -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 */
+    {-9953, -7783, -5849, -4125, -2589, -1220, 1220, 2589, 4125, 5849, 7783, 9953};
+
+#define ICON_FREQ_X     (LOCK_X_POS + LOCK_WIDTH + 5)
+
+    const unsigned char rec_icons_6x8[][6] =
+    {
+        {0x00,0x1c,0x3e,0x36,0x3e,0x1c}
+    };
+    const unsigned char rec_icons_14x8[][14] =
+    {
+        {0x7f,0x10,0x28,0x44,0x00,0x7f,0x08,0x08,0x08,0x7f,0x00,0x64,0x54,0x4c},
+        {0x00,0x00,0x00,0x1c,0x22,0x5d,0x55,0x5d,0x22,0x1c,0x00,0x00,0x00,0x00},
+        {0x00,0x00,0x1c,0x22,0x41,0x41,0x5d,0x22,0x5d,0x41,0x41,0x22,0x1c,0x00}
+    };
+    enum icons_6x8
+    {
+        Icon_Disk,
+        Icon_6x8end
+    };
+    enum icons_14x8
+    {
+        Icon_kHz,
+        Icon_Mono,
+        Icon_Stereo,
+        Icon_14x8end
+    };
+
+    memset(history_l, 0x00, sizeof(history_l));
+    memset(history_r, 0x00, sizeof(history_r));
+#endif
 
 #ifdef HAVE_UDA1380
 /*calculate no. of digital steps to each analogue step. Assuming 
@@ -550,6 +979,7 @@
     peak_meter_playback(true);
 #endif
     peak_meter_enabled = true;
+    peak_meter_get_peakhold(&peak_l, &peak_r);
 
     if (global_settings.rec_prerecord_time)
         talk_buffer_steal(); /* will use the mp3 buffer */
@@ -565,13 +995,78 @@
 
     settings_apply_trigger();
 
-    lcd_setfont(FONT_SYSFIXED);
-    lcd_getstringsize("M", &w, &h);
-    lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8);
+#ifdef HAVE_AGC
+    agc_preset_str[0] = str(LANG_OFF);
+    agc_preset_str[1] = str(LANG_AGC_SAFETY);
+    agc_preset_str[2] = str(LANG_AGC_LIVE);
+    agc_preset_str[3] = str(LANG_AGC_DJSET);
+    agc_preset_str[4] = str(LANG_AGC_MEDIUM);
+    agc_preset_str[5] = str(LANG_AGC_VOICE);
+    if (global_settings.rec_source == SOURCE_MIC) {
+        agc_preset = global_settings.rec_agc_preset_mic;
+        agc_maxgain = global_settings.rec_agc_maxgain_mic;
+    }
+    else {
+        agc_preset = global_settings.rec_agc_preset_line;
+        agc_maxgain = global_settings.rec_agc_maxgain_line;
+    }
+#endif
+#ifdef HAVE_HISTOGRAM
+    history_mode = global_settings.rec_histogram_mode;
+    hist_time_interval = 1 << global_settings.rec_histogram_interval;
+    
+    FOR_NB_SCREENS(i)
+    {
+        screens[i].setfont(FONT_UI);
+        screens[i].getstringsize("M", &w[i], &h[i]);
+        if (i == SCREEN_MAIN) {
+            if (h[i] < ((LCD_HEIGHT - 40) / 8))
+                font[i] = FONT_UI;
+            else
+                font[i] = FONT_SYSFIXED;
+        }
+        else if (h[i] <= ((64 - 8) / 7))
+            font[i] = FONT_UI;
+        else
+            font[i] = FONT_SYSFIXED;
+
+        screens[i].setfont(font[i]);
+        screens[i].getstringsize("M", &w[i], &h[i]);
+        screens[i].setmargins(global_settings.invert_cursor ? 0 : w[i], 8);
+        if (h[i] > 8) {
+            pm_y[i] = 9 + h[i] * 2;
+            pm_h[i] = (h[i] - 1) * 2;
+        }
+        else {
+            pm_y[i] = 8 + h[i] * 2;
+            pm_h[i] = h[i] * 2;
+        }
+    }
+#else
+    FOR_NB_SCREENS(i)
+    {
+        font[i] = FONT_SYSFIXED;
+        screens[i].setfont(font[i]);
+        screens[i].getstringsize("M", &w[i], &h[i]);
+        screens[i].setmargins(global_settings.invert_cursor ? 0 : w[i], 8);
+        pm_y[i] = 8 + h[i] * 2;
+        pm_h[i] = h[i] * 2;
+    }
+#endif /* HAVE_HISTOGRAM */
+
+    gui_syncsplash(1, true, "%s...", str(LANG_RECORDING));
 
     if(rec_create_directory() > 0)
         have_recorded = true;
 
+    /* store the free disk space for this session [MBytes] */
+    fat_size( IF_MV2(0,) NULL, &disk_free ); /* free KBytes */
+    disk_free = disk_free / 1024;
+    if (disk_free > disk_space)
+        disk_space = disk_free;
+    bitrate = 1411; /* [kbps] default for 44kHz stereo 16bit WAV */
+
+
     while(!done)
     {
 #if CONFIG_CODEC == SWCODEC        
@@ -581,7 +1076,6 @@
 #endif
         
 #if CONFIG_LED == LED_REAL
-
         /*
          * Flash the LED while waiting to record.  Turn it on while
          * recording.
@@ -628,7 +1122,7 @@
 #endif /* CONFIG_LED */
 
         /* Wait for a button a while (HZ/10) drawing the peak meter */
-        button = peak_meter_draw_get_btn(0, 8 + h*2, LCD_WIDTH, h);
+        button = peak_meter_draw_get_btn(0, pm_y, pm_h);
 
         if (last_audio_stat != audio_stat)
         {
@@ -643,6 +1137,12 @@
         {
             case REC_STOPEXIT:
             case REC_SHUTDOWN:
+#ifdef REC_RC_STOPEXIT
+            case REC_RC_STOPEXIT:
+#endif
+#ifdef REC_RC_SHUTDOWN
+            case REC_RC_SHUTDOWN:
+#endif          
                 /* turn off the trigger */
                 peak_meter_trigger(false);
                 peak_meter_set_trigger_listener(NULL);
@@ -663,6 +1163,9 @@
                 break;
 
             case REC_RECPAUSE:
+#ifdef REC_RC_RECPAUSE
+            case REC_RC_RECPAUSE:
+#endif
 #ifdef REC_RECPAUSE_PRE
                 if (lastbutton != REC_RECPAUSE_PRE)
                     break;
@@ -715,6 +1218,9 @@
 
 #ifdef REC_PREV
             case REC_PREV:
+#ifdef REC_RC_PREV
+            case REC_RC_PREV:
+#endif
                 cursor--;
                 adjust_cursor();
                 update_countdown = 1; /* Update immediately */
@@ -723,6 +1229,9 @@
 
 #ifdef REC_NEXT
             case REC_NEXT:
+#ifdef REC_RC_NEXT
+            case REC_RC_NEXT:
+#endif
                 cursor++;
                 adjust_cursor();
                 update_countdown = 1; /* Update immediately */
@@ -731,6 +1240,10 @@
        
             case REC_INC:
             case REC_INC | BUTTON_REPEAT:
+#ifdef REC_RC_INC
+            case REC_RC_INC:
+            case REC_RC_INC | BUTTON_REPEAT:
+#endif
                 switch(cursor)
                 {
                     case 0:
@@ -741,14 +1254,17 @@
                         break;
 #ifdef HAVE_UDA1380
                     case 1:
+                        /* both channels */
                         change_recording_gain(true, true, true,
                             ana_mic_size, ana_line_size);
                         break;
                     case 2:
+                        /* only left */
                         change_recording_gain(true, true, false,
                             ana_mic_size, ana_line_size);
                         break;
                     case 3:
+                        /* only right */
                         change_recording_gain(true, false, true,
                             ana_mic_size, ana_line_size);
                         break;
@@ -781,6 +1297,26 @@
                             global_settings.rec_right_gain++;
                         break;
 #endif
+#ifdef HAVE_AGC
+                    case 4:
+                        agc_preset = MIN(agc_preset + 1, AGC_MODE_SIZE);
+                        agc_enable = (agc_preset != 0);
+                        if (global_settings.rec_source == SOURCE_MIC) {
+                            global_settings.rec_agc_preset_mic = agc_preset;
+                            agc_maxgain = global_settings.rec_agc_maxgain_mic;
+                        } else {
+                            global_settings.rec_agc_preset_line = agc_preset;
+                            agc_maxgain = global_settings.rec_agc_maxgain_line;
+                        }
+                        break;
+                    case 5:
+                        agc_maxgain = MIN(agc_maxgain + 1, 96);
+                        if (global_settings.rec_source == SOURCE_MIC)
+                            global_settings.rec_agc_maxgain_mic = agc_maxgain;
+                        else
+                            global_settings.rec_agc_maxgain_line = agc_maxgain;
+                        break;
+#endif
                 }
                 set_gain();
                 update_countdown = 1; /* Update immediately */
@@ -788,6 +1324,10 @@
                 
             case REC_DEC:
             case REC_DEC | BUTTON_REPEAT:
+#ifdef REC_RC_INC
+            case REC_RC_DEC:
+            case REC_RC_DEC | BUTTON_REPEAT:
+#endif
                 switch(cursor)
                 {
                     case 0:
@@ -798,17 +1338,14 @@
                         break;
 #ifdef HAVE_UDA1380
                     case 1:
-                        /* both channels */
                         change_recording_gain(false, true, true,
                             ana_mic_size, ana_line_size);
                         break;
                     case 2:
-                        /* only left */
                         change_recording_gain(false, true, false,
                             ana_mic_size, ana_line_size);
                         break;
                     case 3:
-                        /* only right */
                         change_recording_gain(false, false, true,
                             ana_mic_size, ana_line_size);
                         break;
@@ -841,6 +1378,26 @@
                             global_settings.rec_right_gain--;
                         break;
 #endif
+#ifdef HAVE_AGC
+                    case 4:
+                        agc_preset = MAX(agc_preset - 1, 0);
+                        agc_enable = (agc_preset != 0);
+                        if (global_settings.rec_source == SOURCE_MIC) {
+                            global_settings.rec_agc_preset_mic = agc_preset;
+                            agc_maxgain = global_settings.rec_agc_maxgain_mic;
+                        } else {
+                            global_settings.rec_agc_preset_line = agc_preset;
+                            agc_maxgain = global_settings.rec_agc_maxgain_line;
+                        }
+                        break;
+                    case 5:
+                        agc_maxgain = MAX(agc_maxgain - 1, -24);
+                        if (global_settings.rec_source == SOURCE_MIC)
+                            global_settings.rec_agc_maxgain_mic = agc_maxgain;
+                        else
+                            global_settings.rec_agc_maxgain_line = agc_maxgain;
+                        break;
+#endif
                 }
                 set_gain();
                 update_countdown = 1; /* Update immediately */
@@ -848,6 +1405,9 @@
                 
 #ifdef REC_SETTINGS
             case REC_SETTINGS:
+#ifdef REC_RC_SETTINGS
+            case REC_RC_SETTINGS:
+#endif
                 if(audio_stat != AUDIO_STATUS_RECORD)
                 {
 #if CONFIG_LED == LED_REAL
@@ -869,13 +1429,28 @@
                                                global_settings.rec_channels,
                                                global_settings.rec_editable,
                                                global_settings.rec_prerecord_time);
+#ifdef HAVE_AGC
+                    if (global_settings.rec_source == SOURCE_MIC) {
+                        agc_preset = global_settings.rec_agc_preset_mic;
+                        agc_maxgain = global_settings.rec_agc_maxgain_mic;
+                    }
+                    else {
+                        agc_preset = global_settings.rec_agc_preset_line;
+                        agc_maxgain = global_settings.rec_agc_maxgain_line;
+                    }
+#endif
+#ifdef HAVE_HISTOGRAM
+                    hist_time_interval = 1 << global_settings.rec_histogram_interval;
+#endif
 
                     adjust_cursor();
                     set_gain();
                     update_countdown = 1; /* Update immediately */
 
-                    lcd_setfont(FONT_SYSFIXED);
-                    lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8);
+                    FOR_NB_SCREENS(i)
+                    {
+                        screens[i].setmargins(global_settings.invert_cursor ? 0 : w[i], 8);
+                    }
                 }
                 break;
 #endif
@@ -943,7 +1518,18 @@
         if (button != BUTTON_NONE)
             lastbutton = button;
 
-        lcd_setfont(FONT_SYSFIXED);
+        peak_read = !peak_read;
+        if (peak_read) {
+            peak_time++;
+            peak_valid = read_peak_levels(&peak_l, &peak_r, &balance);
+        }
+
+#ifdef HAVE_AGC
+        /* Handle AGC every 200ms when enabled and peak data is valid */
+        if (peak_read && agc_enable && peak_valid)
+            auto_gain_control(&peak_l, &peak_r, &balance,
+                              ana_mic_size, ana_line_size);
+#endif
 
         seconds = audio_recorded_time() / HZ;
         
@@ -957,14 +1543,28 @@
             update_countdown = 5;
             last_seconds = seconds;
 
-            lcd_clear_display();
+            /* Get free disk space and calculate remain time */
+            fat_size( IF_MV2(0,) NULL, &disk_free ); /* [KBytes] */
+            disk_free = disk_free / 1024;
+            if (disk_free > MIN_DISK_SPACE)
+                disk_free -= MIN_DISK_SPACE;
+            else
+                disk_free = 0;
+            disk_time = 140 * (int)disk_free / bitrate; /* rough estimation */
+
+            FOR_NB_SCREENS(i)
+            {
+                screens[i].clear_display();
+                screens[i].setfont(font[i]);
+            }
 
             hours = seconds / 3600;
             minutes = (seconds - (hours * 3600)) / 60;
             snprintf(buf, 32, "%s %02d:%02d:%02d",
                      str(LANG_RECORDING_TIME),
                      hours, minutes, seconds%60);
-            lcd_puts(0, 0, buf);
+            FOR_NB_SCREENS(i)
+                screens[i].puts(0, 0, buf); 
 
             dseconds = rec_timesplit_seconds();
             num_recorded_bytes = audio_num_recorded_bytes();
@@ -997,7 +1597,8 @@
                              str(LANG_RECORDING_SIZE), buf2);
                 }
             }
-            lcd_puts(0, 1, buf);
+            FOR_NB_SCREENS(i)
+                screens[i].puts(0, 1, buf);
 
             /* We will do file splitting regardless, either at the end of
                a split interval, or when the filesize approaches the 2GB
@@ -1017,10 +1618,15 @@
                               buf2, sizeof(buf2)));
             
             if (global_settings.invert_cursor && (pos++ == cursor))
-                lcd_puts_style(0, 3, buf, STYLE_INVERT);
+            {
+                FOR_NB_SCREENS(i)
+                    screens[i].puts_style_offset(0, 4, buf, STYLE_INVERT,0);
+            }
             else
-                lcd_puts(0, 3, buf);
-                
+            {
+                FOR_NB_SCREENS(i)
+                    screens[i].puts(0, 4, buf);
+            }                
 
             if(global_settings.rec_source == SOURCE_MIC)
             { 
@@ -1050,8 +1656,7 @@
                             sound_min(SOUND_MIC_GAIN)) &&
                            (global_settings.rec_mic_decimator_left_gain < 0)))?
                          str(LANG_RECORDING_GAIN_DIGITAL) :
-                         str(LANG_RECORDING_GAIN_ANALOG)
-                        );
+                         str(LANG_RECORDING_GAIN_ANALOG) );
 #else /* HAVE_UDA1380 */
                 snprintf(buf, 32, "%s:%s", str(LANG_RECORDING_GAIN),
                          fmt_gain(SOUND_MIC_GAIN,
@@ -1059,9 +1664,15 @@
                                   buf2, sizeof(buf2)));
 #endif
                 if(global_settings.invert_cursor && ((1==cursor)||(2==cursor)))
-                    lcd_puts_style(0, 4, buf, STYLE_INVERT);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts_style_offset(0, 5, buf, STYLE_INVERT,0);
+                }
                 else
-                    lcd_puts(0, 4, buf);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts(0, 5, buf);
+                }
             }
             else if(global_settings.rec_source == SOURCE_LINE)
             {
@@ -1104,9 +1715,16 @@
                                   buf2, sizeof(buf2)));
 #endif /* HAVE_UDA1380 */
                 if(global_settings.invert_cursor && ((1==cursor)||(2==cursor)))
-                    lcd_puts_style(0, 4, buf, STYLE_INVERT);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts_style_offset(0, 5, buf, STYLE_INVERT,0);
+                }
                 else
-                    lcd_puts(0, 4, buf);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts(0, 5, buf);
+                }
+
 #ifdef HAVE_UDA1380
                 snprintf(buf, 32, "%s:%s (%s)",
                          str(LANG_RECORDING_RIGHT),
@@ -1134,45 +1752,339 @@
                                   buf2, sizeof(buf2)));
 #endif /* HAVE_UDA1380 */
                 if(global_settings.invert_cursor && ((1==cursor)||(3==cursor)))
-                    lcd_puts_style(0, 5, buf, STYLE_INVERT);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts_style_offset(0, 6, buf, STYLE_INVERT,0);
+                }
                 else
-                    lcd_puts(0, 5, buf);
+                {
+                    FOR_NB_SCREENS(i)
+                        screens[i].puts(0, 6, buf);
+                }                
+            }
+
+#ifdef HAVE_AGC
+            if (cursor == 5)
+                snprintf(buf, 32, "%s: %s",
+                         str(LANG_RECORDING_AGC_MAXGAIN),
+                         fmt_gain(SOUND_DECIMATOR_LEFT_GAIN,
+                                  agc_maxgain, buf2, sizeof(buf2)));
+            else if (agc_preset == 0)
+                snprintf(buf, 32, "%s: %s",
+                         str(LANG_RECORDING_AGC_PRESET),
+                         agc_preset_str[agc_preset]);
+            else if (global_settings.rec_source == SOURCE_MIC)
+                snprintf(buf, 32, "%s: %s%s",
+                         str(LANG_RECORDING_AGC_PRESET),
+                         agc_preset_str[agc_preset],
+                         fmt_gain(SOUND_DECIMATOR_LEFT_GAIN,
+                             agc_maxgain -
+                             global_settings.rec_mic_gain * ana_mic_size -
+                             global_settings.rec_mic_decimator_left_gain,
+                             buf2, sizeof(buf2)));
+            else
+                snprintf(buf, 32, "%s: %s%s",
+                         str(LANG_RECORDING_AGC_PRESET),
+                         agc_preset_str[agc_preset],
+                         fmt_gain(SOUND_DECIMATOR_LEFT_GAIN,
+                             agc_maxgain -
+                            (global_settings.rec_left_gain * ana_line_size +
+                             global_settings.rec_linein_decimator_left_gain +
+                             global_settings.rec_right_gain * ana_line_size +
+                             global_settings.rec_linein_decimator_right_gain)/2,
+                             buf2, sizeof(buf2)));
+            line = (global_settings.rec_source == SOURCE_MIC)? 6 : 7;
+            if(global_settings.invert_cursor && ((cursor==4) || (cursor==5)))
+            {
+                screens[0].puts_style_offset(0, line, buf, STYLE_INVERT,0);
+#ifdef HAVE_REMOTE_LCD
+                screens[1].puts_style_offset(0, 6, buf, STYLE_INVERT,0);
+#endif
+            }
+                else
+            {
+                FOR_NB_SCREENS(i)
+                    screens[i].puts(0, line, buf);
+            }
+            
+            if (global_settings.rec_source == SOURCE_MIC)
+            {
+                if(agc_maxgain < (global_settings.rec_mic_gain * ana_mic_size +
+                                  global_settings.rec_mic_decimator_left_gain))
+                    change_recording_gain(false, true, true,
+                                          ana_mic_size, ana_line_size);
             }
+            else
+            {
+                if(agc_maxgain < (global_settings.rec_left_gain * ana_line_size
+                                + global_settings.rec_linein_decimator_left_gain))
+                    change_recording_gain(false, true, false,
+                                          ana_mic_size, ana_line_size);
+                if(agc_maxgain < (global_settings.rec_right_gain * ana_line_size
+                                + global_settings.rec_linein_decimator_right_gain))
+                    change_recording_gain(false, false, true,
+                                          ana_mic_size, ana_line_size);
+            }
+#endif /* HAVE_AGC */
+
+            if(!global_settings.invert_cursor) {
             switch(cursor)
             {
             case 1:
-                put_cursorxy(0, 4, true);
+                        FOR_NB_SCREENS(i)
+                            screen_put_cursorxy(&screens[i], 0, 5, true);
                 
                 if(global_settings.rec_source != SOURCE_MIC)
-                    put_cursorxy(0, 5, true);
-                
+                        {
+                            FOR_NB_SCREENS(i)
+                                screen_put_cursorxy(&screens[i], 0, 6, true);
+                        }               
                 break;
             case 2:
-                put_cursorxy(0, 4, true);
+                        FOR_NB_SCREENS(i)
+                            screen_put_cursorxy(&screens[i], 0, 5, true);
                 break;
             case 3:
-                put_cursorxy(0, 5, true);
+                        FOR_NB_SCREENS(i)
+                            screen_put_cursorxy(&screens[i], 0, 6, true);
+                    break;
+#ifdef HAVE_AGC
+                    case 4:
+                    case 5:
+                        screen_put_cursorxy(&screens[0], 0, line, true);
+#ifdef HAVE_REMOTE_LCD
+                        screen_put_cursorxy(&screens[1], 0, 6, true);
+#endif
                 break;
+#endif /* HAVE_AGC */
             default:
-                put_cursorxy(0, 0, true);
+                        FOR_NB_SCREENS(i)
+                            screen_put_cursorxy(&screens[i], 0, 4, true);
+                }
             }
 
+            gui_syncstatusbar_draw(&statusbars, true);
+
+#ifdef HAVE_AGC
+            lcd_setfont(FONT_SYSFIXED);
+            snprintf(buf, 32, "%s", freq_str[global_settings.rec_frequency]);
+            buf[2] = NULL;
+            lcd_putsxy(ICON_FREQ_X, 0, buf);
+            lcd_mono_bitmap(rec_icons_14x8[Icon_kHz],
+                            ICON_FREQ_X + 13, 0, 14, 8);
+            lcd_mono_bitmap(rec_icons_14x8[global_settings.rec_channels?
+                                           Icon_Mono:Icon_Stereo],
+                            ICON_FREQ_X + 27, 0, 14, 8);
+#else
+            /* Main screen only for this info */
             snprintf(buf, 32, "%s %s",
                      freq_str[global_settings.rec_frequency],
                      global_settings.rec_channels?
                      str(LANG_CHANNEL_MONO):str(LANG_CHANNEL_STEREO));
-            lcd_puts(0, 7, buf);
+            lcd_puts(0, 8, buf);
+#endif /* HAVE_AGC*/
 
-            gui_syncstatusbar_draw(&statusbars, true);
-            peak_meter_draw(0, 8 + h*2, LCD_WIDTH, h);
-
-            lcd_update();
+#ifdef HAVE_HISTOGRAM
+            /* Draw histogram graphs (on main unit only).
+             * 4 modes: low size linear or logarithmic histogram with
+             * disk space usage, battery level and balance meter or
+             * high size linear or logarithmic peak histogram.
+             */
+#define HIST_BAL_X (LCD_WIDTH/2 + 4)
+#define HIST_BAL_W (LCD_WIDTH/2 - 5)
+#define BAL_MAX_R 9953
+#define BAL_MAX_L (-BAL_MAX_R * (HIST_BAL_W/2 + 1) / (HIST_BAL_W/2))
+            int hist_bal_y = HIST_Y - hist_size_h[history_mode/2] - 11;
+
+            /************** AGC Test Info only *************/
+            lcd_setfont(FONT_SYSFIXED);
+            snprintf(buf, 32, "D:%d U:%d",
+                     (agc_droptime+2)/5, (agc_risetime+2)/5);
+            lcd_putsxy(1, LCD_HEIGHT - 8, buf);
+            snprintf(buf, 32, "B:%d",
+                     (agc_baltime+2)/5);
+            lcd_putsxy(LCD_WIDTH/2 + 3, LCD_HEIGHT - 8, buf);
+            /***********************************************/
+
+            if (hist_bal_y > (8 + 8 * h[SCREEN_MAIN]))
+            {
+                lcd_setfont(FONT_SYSFIXED);
+                if (charger_inserted())
+                    lcd_mono_bitmap(bitmap_icons_7x8[Icon_Plug],
+                                    2 + 19*(battery_level() > 48),
+                                    hist_bal_y + 1, 7, 8);
+                if (battery_time() > 90)
+                    snprintf(buf, 32, "%dh", (battery_time() + 10) / 60);
+                else
+                    snprintf(buf,32, "%dm", battery_time());
+                if (battery_level() > 48)
+                    i = 1;
+                else if ((battery_time() < 590) && (battery_time() > 90))
+                    i = 15;
+                else
+                    i = 10;
+                lcd_putsxy(i, hist_bal_y + 1, buf);
+                
+                if (disk_time > 90)
+                    snprintf(buf, 32, "%dh", (disk_time + 10) / 60);
+                else
+                    snprintf(buf, 32, "%dm", disk_time);
+                i = ((disk_time < 91) || (disk_time > 589))? 30:26;
+                lcd_putsxy((5*disk_free > 3*disk_space) ?
+                           (LCD_WIDTH/2 - i) : 37,
+                           hist_bal_y + 1, buf);
+                if ((hist_time % 2) || !ata_disk_is_active())
+                    lcd_mono_bitmap(rec_icons_6x8[Icon_Disk],
+                                    LCD_WIDTH/2 - 11,
+                                    hist_bal_y + 1, 6, 8);
+                lcd_set_drawmode(DRMODE_COMPLEMENT);
+                lcd_fillrect(0, hist_bal_y,
+                             (31 * battery_level() - 15) / 100, 9);
+                lcd_fillrect(34, hist_bal_y, (LCD_WIDTH/2 - 35) *
+                             (disk_space - disk_free - 2) / disk_space, 9);
+                lcd_set_drawmode(DRMODE_SOLID);
+                lcd_drawrect(0, hist_bal_y - 1, 30, 11);
+                lcd_vline(30, hist_bal_y + 2, hist_bal_y + 6);
+                lcd_vline(31, hist_bal_y + 2, hist_bal_y + 6);
+                lcd_drawrect(34, hist_bal_y - 1, LCD_WIDTH/2 - 36, 11);
+
+                int bal;
+                bal = MAX(balance, BAL_MAX_L);
+                bal = MIN(bal, BAL_MAX_R);
+                lcd_drawrect(HIST_BAL_X-2, hist_bal_y-1, HIST_BAL_W+3, 11);
+                lcd_hline(HIST_BAL_X + HIST_BAL_W/2 - 1,
+                          HIST_BAL_X + HIST_BAL_W/2 + 1,
+                          hist_bal_y - 2);
+                lcd_hline(HIST_BAL_X + HIST_BAL_W/2 - 1,
+                          HIST_BAL_X + HIST_BAL_W/2 + 1,
+                          hist_bal_y + 10);
+                lcd_fillrect(HIST_BAL_X-1 + HIST_BAL_W/2 +
+                             HIST_BAL_W * bal / 19905,
+                             hist_bal_y, 3, 9);
+                for (i = 0; i < BAL_MEM_SIZE; i++) {
+                    bal = MIN(balance_mem[i], BAL_MAX_R);
+                    bal = MAX(bal, BAL_MAX_L);
+                    lcd_vline(HIST_BAL_X + HIST_BAL_W/2 +
+                              HIST_BAL_W * bal / 19905,
+                              hist_bal_y + 2, hist_bal_y + 6);
+                }
+                lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y + 4);
+                lcd_set_drawmode(DRMODE_COMPLEMENT);
+                lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y - 1);
+                lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y + 9);
+                for (i = 0; i < 12; i++)
+                    lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2 +
+                                  HIST_BAL_W * hist_balance_marks[i] / 19905,
+                                  hist_bal_y + 4);
+                lcd_drawpixel(34, hist_bal_y - 1);
+                lcd_drawpixel(34, hist_bal_y + 9);
+                lcd_drawpixel(LCD_WIDTH/2 - 3, hist_bal_y - 1);
+                lcd_drawpixel(LCD_WIDTH/2 - 3, hist_bal_y + 9);
+                lcd_set_drawmode(DRMODE_SOLID);
+            }
+
+            hist_height = hist_size_h[history_mode/2] - 1;
+            if (peak_valid && !(hist_time % hist_time_interval) && hist_l)
+            {
+                if (history_mode % 2) {
+                    i = 0;
+                    while (hist_l < hist_peak_lin2dB[history_mode / 2][i])
+                        i++;
+                    history_l[history_pos] = hist_height - i;
+                    i = 0;
+                    while (hist_r < hist_peak_lin2dB[history_mode / 2][i])
+                        i++;
+                    history_r[history_pos] = hist_height - i;
+                } else {
+                    history_l[history_pos] = hist_l * hist_height / 32767;
+                    history_r[history_pos] = hist_r * hist_height / 32767;
+                }
+                history_pos = (history_pos + 1) % HIST_W;
+                history_l[history_pos] = history_r[history_pos] = 0;
+                history_l[(history_pos + 1) % HIST_W] = 0;
+                history_r[(history_pos + 1) % HIST_W] = 0;
+                hist_l = 0;
+                hist_r = 0;
+            }
+            lcd_drawrect(0, HIST_Y - hist_height,
+                         HIST_W + 2, hist_height + 1);
+            lcd_drawrect(HIST_W + 6, HIST_Y - hist_height,
+                         HIST_W + 2, hist_height + 1);
+            lcd_set_drawmode(DRMODE_COMPLEMENT);
+            for (i = 0; i < HIST_W; i++) {
+                if (history_l[i])
+                    lcd_vline(i+1, HIST_Y - 1, HIST_Y - history_l[i]);
+                if (history_r[i])
+                    lcd_vline(i+HIST_W+7, HIST_Y - 1, HIST_Y - history_r[i]);
+            }
+            lcd_set_drawmode(DRMODE_SOLID);
+            for (i = 0; i < 6; i++)
+                lcd_hline(HIST_W + 3, HIST_W + 4,
+                          HIST_Y - hist_level_marks[history_mode][i]);
+#endif /* HAVE_HISTOGRAM */
+
+            hist_time++;
+
+            FOR_NB_SCREENS(i)
+            {
+                peak_meter_screen(&screens[i], 0, pm_y[i], pm_h[i]);
+                screens[i].update();
+            }
+
+            /* Check battery level & free disk space */
+            if (ata_disk_is_active())
+                disk_was_active = true;
+            else if (disk_was_active)
+            {
+                if (disk_time == 0) {
+                    backlight_on();
+#ifdef HAVE_REMOTE_LCD
+                    remote_backlight_on();
+#endif
+                    if (audio_stat & AUDIO_STATUS_RECORD) {
+                        lcd_setfont(FONT_UI);
+                        gui_syncsplash(HZ, true, "%s %s",
+                            str(LANG_WARNING_DISK_FULL),
+                            str(LANG_WARNING_STOP_RECORDING));
+                        lcd_setfont(FONT_SYSFIXED);
+                        audio_stop_recording();
+                    }
+                    else {
+                        lcd_setfont(FONT_UI);
+                        gui_syncsplash(2*HZ, true,
+                            str(LANG_WARNING_DISK_FULL));
+                        lcd_setfont(FONT_SYSFIXED);
+                    }
+                }
+                else if (warn_message && (battery_level() < 10)) {
+                    backlight_on();
+#ifdef HAVE_REMOTE_LCD
+                    remote_backlight_on();
+#endif
+                    lcd_setfont(FONT_UI);
+                    gui_syncsplash(3*HZ, true,
+                        str(LANG_WARNING_BATTERY_LOW));
+                    lcd_setfont(FONT_SYSFIXED);
+                }
+                else if (!warn_message && (disk_free < 512)) {
+                    backlight_on();
+#ifdef HAVE_REMOTE_LCD
+                    remote_backlight_on();
+#endif
+                    lcd_setfont(FONT_UI);
+                    gui_syncsplash(3*HZ, true,
+                        str(LANG_WARNING_DISKSPACE_LOW));
+                    lcd_setfont(FONT_SYSFIXED);
+                }
+                warn_message = !warn_message;
+                disk_was_active  = false;
+            }
 
             /* draw the trigger status */
             if (peak_meter_trigger_status() != TRIG_OFF)
             {
-                peak_meter_draw_trig(LCD_WIDTH - TRIG_WIDTH, 4 * h);
-                lcd_update_rect(LCD_WIDTH - (TRIG_WIDTH + 2), 4 * h,
+                peak_meter_draw_trig(LCD_WIDTH - TRIG_WIDTH, 4 * h[0]);
+                lcd_update_rect(LCD_WIDTH - (TRIG_WIDTH + 2), 4 * h[0],
                                 TRIG_WIDTH + 2, TRIG_HEIGHT);
             }
         }
@@ -1223,13 +2135,14 @@
     if (have_recorded)
         reload_directory();
 
+#ifdef HAVE_HISTOGRAM
+    global_settings.rec_histogram_mode = history_mode;
+#endif
+
 #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR)
     ata_set_led_enabled(true);
 #endif
     return been_in_usb_mode;
-/*
-#endif
-*/
 }
 
 #ifdef REC_F2
