diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 996f13d55c..71094c0dd9 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -2074,7 +2074,6 @@ static bool dbg_fm_radio(void) while(1) { int row = 0; - unsigned long regs; lcd_clear_display(); fm_detected = radio_hardware_present(); @@ -2083,16 +2082,31 @@ static bool dbg_fm_radio(void) lcd_puts(0, row++, buf); #if (CONFIG_TUNER & S1A0903X01) - regs = samsung_get(RADIO_ALL); - snprintf(buf, sizeof buf, "Samsung regs: %08lx", regs); + snprintf(buf, sizeof buf, "Samsung regs: %08X", + samsung_get(RADIO_ALL)); lcd_puts(0, row++, buf); #endif #if (CONFIG_TUNER & TEA5767) - regs = philips_get(RADIO_ALL); - snprintf(buf, sizeof buf, "Philips regs: %08lx", regs); - lcd_puts(0, row++, buf); -#endif + { + struct philips_dbg_info info; + philips_dbg_info(&info); + snprintf(buf, sizeof buf, "Philips regs:"); + lcd_puts(0, row++, buf); + + snprintf(buf, sizeof buf, " Read: %02X %02X %02X %02X %02X", + (unsigned)info.read_regs[0], (unsigned)info.read_regs[1], + (unsigned)info.read_regs[2], (unsigned)info.read_regs[3], + (unsigned)info.read_regs[4]); + lcd_puts(0, row++, buf); + + snprintf(buf, sizeof buf, " Write: %02X %02X %02X %02X %02X", + (unsigned)info.write_regs[0], (unsigned)info.write_regs[1], + (unsigned)info.write_regs[2], (unsigned)info.write_regs[3], + (unsigned)info.write_regs[4]); + lcd_puts(0, row++, buf); + } +#endif lcd_update(); if (action_userabort(HZ)) diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c index 7258840dbf..8b79f2c9e7 100644 --- a/apps/recorder/radio.c +++ b/apps/recorder/radio.c @@ -20,12 +20,13 @@ #include "config.h" #include #include +#include #include "sprintf.h" #include "mas.h" #include "settings.h" #include "button.h" #include "status.h" -#include "kernel.h" +#include "thread.h" #include "mpeg.h" #include "audio.h" #include "mp3_playback.h" @@ -47,7 +48,6 @@ #include "recording.h" #include "talk.h" #include "tuner.h" -#include "hwcompat.h" #include "power.h" #include "sound.h" #include "screen_access.h" @@ -82,6 +82,10 @@ #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) #define FM_PRESET #define FM_MODE +/* This should be removeable if the whole tuning thing is sorted out since + proper tuning quiets the screen almost entirely in that extreme measures + have to be taken to hear any interference. */ +#define HAVE_NOISY_IDLE_MODE #elif CONFIG_KEYPAD == ONDIO_PAD #define FM_RECORD_DBLPRE @@ -91,26 +95,12 @@ #define RADIO_SCAN_MODE 0 #define RADIO_PRESET_MODE 1 -#if (CONFIG_TUNER & TEA5767) -#define DEEMPH_50 0, -#define DEEMPH_75 1, -#define BAND_LIM_EU 0 -#define BAND_LIM_JP 1 -#else -#define DEEMPH_50 -#define DEEMPH_75 -#define BAND_LIM_EU -#define BAND_LIM_JP -#endif -static struct fm_region_setting fm_region[] = { - /* Europe */ - { 87500000, 108000000, 50000, DEEMPH_50 BAND_LIM_EU }, - /* US / Canada */ - { 87900000, 107900000, 200000, DEEMPH_75 BAND_LIM_EU }, - /* Japan */ - { 76000000, 90000000, 100000, DEEMPH_50 BAND_LIM_JP }, - /* Korea */ - { 87500000, 108000000, 100000, DEEMPH_50 BAND_LIM_EU }, +static const struct fm_region_setting fm_region[] = { + /* Note: Desriptive strings are just for display atm and are not compiled. */ + FM_REGION_ENTRY("Europe", 87500000, 108000000, 50000, 0, 0), + FM_REGION_ENTRY("US/Canada", 87900000, 107900000, 200000, 1, 0), + FM_REGION_ENTRY("Japan", 76000000, 90000000, 100000, 0, 1), + FM_REGION_ENTRY("Korea", 87500000, 108000000, 100000, 0, 0), }; static int curr_preset = -1; @@ -138,22 +128,6 @@ static int clear_preset_list(void); static int scan_presets(void); -#ifdef SIMULATOR -void radio_set(int setting, int value); -int radio_get(int setting); -#else -#if CONFIG_TUNER == S1A0903X01 /* FM recorder */ -#define radio_set samsung_set -#define radio_get samsung_get -#elif CONFIG_TUNER == TEA5767 /* iriver, iaudio */ -#define radio_set philips_set -#define radio_get philips_get -#elif CONFIG_TUNER == (S1A0903X01 | TEA5767) /* OndioFM */ -static void (*radio_set)(int setting, int value); -static int (*radio_get)(int setting); -#endif -#endif - /* Function to manipulate all yesno dialogues. This function needs the output text as an argument. */ static bool yesno_pop(char* text) @@ -169,25 +143,10 @@ static bool yesno_pop(char* text) void radio_init(void) { -#ifndef SIMULATOR -#if CONFIG_TUNER == (S1A0903X01 | TEA5767) - if (read_hw_mask() & TUNER_MODEL) - { - radio_set = philips_set; - radio_get = philips_get; - } - else - { - radio_set = samsung_set; - radio_get = samsung_get; - } -#endif -#endif + tuner_init(); radio_stop(); } -/* For powermgmt.c to check status for shutdown since it can't access - the global_status structure directly. */ int get_radio_status(void) { return radio_status; @@ -202,12 +161,15 @@ bool in_radio_screen(void) #define FMRADIO_START_PAUSED 0x8000 void radio_start(void) { + const struct fm_region_setting *fmr; bool start_paused; int mute_timeout; if(radio_status == FMRADIO_PLAYING) return; + fmr = &fm_region[global_settings.fm_region]; + start_paused = radio_status & FMRADIO_START_PAUSED; /* clear flag before any yielding */ radio_status &= ~FMRADIO_START_PAUSED; @@ -216,21 +178,21 @@ void radio_start(void) radio_power(true); curr_freq = global_status.last_frequency - * fm_region[global_settings.fm_region].freq_step - + fm_region[global_settings.fm_region].freq_min; + * fmr->freq_step + fmr->freq_min; radio_set(RADIO_SLEEP, 0); /* wake up the tuner */ radio_set(RADIO_FREQUENCY, curr_freq); if(radio_status == FMRADIO_OFF) { +#if (CONFIG_TUNER & S1A0903X01) radio_set(RADIO_IF_MEASUREMENT, 0); radio_set(RADIO_SENSITIVITY, 0); +#endif radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); #if (CONFIG_TUNER & TEA5767) - radio_set(RADIO_SET_DEEMPHASIS, - fm_region[global_settings.fm_region].deemphasis); - radio_set(RADIO_SET_BAND, fm_region[global_settings.fm_region].band); + radio_set(RADIO_SET_DEEMPHASIS, fmr->deemphasis); + radio_set(RADIO_SET_BAND, fmr->band); #endif mute_timeout = current_tick + 1*HZ; } @@ -295,6 +257,25 @@ bool radio_hardware_present(void) #endif } +/* Keep freq on the grid for the current region */ +static int snap_freq_to_grid(int freq) +{ + const struct fm_region_setting * const fmr = + &fm_region[global_settings.fm_region]; + + /* Range clamp if out of range or just round to nearest */ + if (freq < fmr->freq_min) + freq = fmr->freq_min; + else if (freq > fmr->freq_max) + freq = fmr->freq_max; + else + freq = (freq - fmr->freq_min + fmr->freq_step/2) / + fmr->freq_step * fmr->freq_step + fmr->freq_min; + + return freq; +} + +/* Find a matching preset to freq */ static int find_preset(int freq) { int i; @@ -309,35 +290,43 @@ static int find_preset(int freq) return -1; } -static int find_closest_preset(int freq) +/* Return the first preset encountered in the search direction with + wraparound. */ +static int find_closest_preset(int freq, int direction) { - int i; - int diff; - int min_diff = fm_region[global_settings.fm_region].freq_min; - int preset = -1; + int i; - for(i = 0;i < MAX_PRESETS;i++) + if (direction == 0) /* direction == 0 isn't really used */ + return 0; + + for (i = 0; i < MAX_PRESETS; i++) { - diff = freq - presets[i].frequency; - if(diff==0) - return i; - if(diff < 0) - diff = -diff; - if(diff < min_diff) - { - preset = i; - min_diff = diff; - } + int preset_frequency = presets[i].frequency; + + if (preset_frequency == freq) + return i; /* Exact match = stop */ + /* Stop when the preset frequency exeeds freq so that we can + pick the correct one based on direction */ + if (preset_frequency > freq) + break; } - return preset; + /* wrap around depending on direction */ + if (i == 0 || i >= num_presets - 1) + i = direction < 0 ? num_presets - 1 : 0; + else if (direction < 0) + i--; /* use previous */ + + return i; } static void remember_frequency(void) { - global_status.last_frequency = (curr_freq - - fm_region[global_settings.fm_region].freq_min) - / fm_region[global_settings.fm_region].freq_step; + const struct fm_region_setting * const fmr = + &fm_region[global_settings.fm_region]; + + global_status.last_frequency = (curr_freq - fmr->freq_min) + / fmr->freq_step; status_save(); } @@ -346,60 +335,104 @@ static void next_preset(int direction) if (num_presets < 1) return; - if(curr_preset == -1) - curr_preset = find_closest_preset(curr_freq); - - if(direction > 0) - if(curr_preset == num_presets - 1) - curr_preset = 0; - else - curr_preset++; + if (curr_preset == -1) + curr_preset = find_closest_preset(curr_freq, direction); else - if(curr_preset == 0) - curr_preset = num_presets - 1; - else - curr_preset--; - - curr_freq = presets[curr_preset].frequency; + curr_preset = (curr_preset + direction + num_presets) % num_presets; + + /* Must stay on the current grid for the region */ + curr_freq = snap_freq_to_grid(presets[curr_preset].frequency); + radio_set(RADIO_FREQUENCY, curr_freq); remember_frequency(); } +/* Step to the next or previous frequency */ +static int step_freq(int freq, int direction) +{ + const struct fm_region_setting * const fmr = + &fm_region[global_settings.fm_region]; + + freq += direction*fmr->freq_step; + + /* Wrap first or snapping to grid will not let us on the band extremes */ + if (freq > fmr->freq_max) + freq = direction > 0 ? fmr->freq_min : fmr->freq_max; + else if (freq < fmr->freq_min) + freq = direction < 0 ? fmr->freq_max : fmr->freq_min; + else + freq = snap_freq_to_grid(freq); + + return freq; +} + +/* Step to the next or previous station */ +static void next_station(int direction) +{ + if (direction != 0 && radio_mode != RADIO_SCAN_MODE) + { + next_preset(direction); + return; + } + + curr_freq = step_freq(curr_freq, direction); + + if (radio_status == FMRADIO_PLAYING) + radio_set(RADIO_MUTE, 1); + + radio_set(RADIO_FREQUENCY, curr_freq); + + if (radio_status == FMRADIO_PLAYING) + radio_set(RADIO_MUTE, 0); + + curr_preset = find_preset(curr_freq); + remember_frequency(); +} int radio_screen(void) { char buf[MAX_PATH]; bool done = false; - int button, lastbutton = BUTTON_NONE; int ret_val = GO_TO_ROOT; -#ifdef FM_RECORD_DBLPRE - unsigned long rec_lastclick = 0; -#endif - int freq, i; - bool tuned; - bool stereo = false; + int button; + int i; int search_dir = 0; + bool stereo = false, last_stereo = false; int fh; - bool last_stereo_status = false; int top_of_screen = 0; bool update_screen = true; - int timeout = current_tick + HZ/10; bool screen_freeze = false; - bool have_recorded = false; - unsigned int seconds = 0; - unsigned int last_seconds = 0; -#if CONFIG_CODEC != SWCODEC - int hours, minutes; - struct audio_recording_options rec_options; -#endif bool keep_playing = false; bool statusbar = global_settings.statusbar; +#ifdef FM_RECORD_DBLPRE + int lastbutton = BUTTON_NONE; + unsigned long rec_lastclick = 0; +#endif +#if CONFIG_CODEC != SWCODEC + bool have_recorded = false; + int timeout = current_tick + HZ/10; + unsigned int seconds = 0; + unsigned int last_seconds = 0; + int hours, minutes; + struct audio_recording_options rec_options; +#endif /* CONFIG_CODEC != SWCODEC */ +#ifndef HAVE_NOISY_IDLE_MODE int button_timeout = current_tick + (2*HZ); +#endif #ifdef HAS_BUTTONBAR struct gui_buttonbar buttonbar; gui_buttonbar_init(&buttonbar); gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); #endif + + /* Ends an in-progress search - needs access to search_dir */ + void end_search(void) + { + if (search_dir != 0 && radio_status == FMRADIO_PLAYING) + radio_set(RADIO_MUTE, 0); + search_dir = 0; + } + /* change status to "in screen" */ in_screen = true; @@ -419,7 +452,7 @@ int radio_screen(void) if(fh < 10) top_of_screen = 1; - if(!num_presets) + if(num_presets <= 0) { memset(presets, 0, sizeof(presets)); radio_load_presets(global_settings.fmr_file); @@ -461,8 +494,7 @@ int radio_screen(void) radio_start(); #endif - /* I hate this thing with vehement passion (jhMikeS): */ - if(num_presets == 0 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN))) + if(num_presets < 1 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN))) scan_presets(); curr_preset = find_preset(curr_freq); @@ -474,50 +506,44 @@ int radio_screen(void) str(LANG_FM_BUTTONBAR_PRESETS), str(LANG_FM_BUTTONBAR_RECORD)); #endif +#ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(true); - +#endif + while(!done) { - if(search_dir) + if(search_dir != 0) { - curr_freq += search_dir - * fm_region[global_settings.fm_region].freq_step; - if(curr_freq < fm_region[global_settings.fm_region].freq_min) - curr_freq = fm_region[global_settings.fm_region].freq_max; - if(curr_freq > fm_region[global_settings.fm_region].freq_max) - curr_freq = fm_region[global_settings.fm_region].freq_min; + curr_freq = step_freq(curr_freq, search_dir); + update_screen = true; - /* Tune in and delay */ - radio_set(RADIO_FREQUENCY, curr_freq); - sleep(1); - - /* Start IF measurement */ - radio_set(RADIO_IF_MEASUREMENT, 1); - sleep(1); - - /* Now check how close to the IF frequency we are */ - tuned = radio_get(RADIO_TUNED); - - /* Stop searching if the tuning is close */ - if(tuned) + if(radio_set(RADIO_SCAN_FREQUENCY, curr_freq)) { - search_dir = 0; curr_preset = find_preset(curr_freq); remember_frequency(); + end_search(); } - - update_screen = true; + + trigger_cpu_boost(); } - if(search_dir) - button = button_get(false); - else - button = get_action(CONTEXT_FM, HZ / PEAK_METER_FPS); +#if CONFIG_CODEC != SWCODEC + /* TODO: Can we timeout at HZ when recording since peaks aren't + displayed? This should quiet recordings too. */ + button = get_action(CONTEXT_FM, + update_screen ? TIMEOUT_NOBLOCK : HZ / PEAK_METER_FPS); +#else + button = get_action(CONTEXT_FM, + update_screen ? TIMEOUT_NOBLOCK : HZ); +#endif + +#ifndef HAVE_NOISY_IDLE_MODE if (button != ACTION_NONE) { cpu_idle_mode(false); button_timeout = current_tick + (2*HZ); } +#endif switch(button) { case ACTION_FM_STOP: @@ -559,7 +585,7 @@ int radio_screen(void) rec_lastclick = current_tick; break; } -#endif +#endif /* FM_RECORD_DBLPRE */ #ifndef SIMULATOR if(audio_status() == AUDIO_STATUS_RECORD) { @@ -572,7 +598,7 @@ int radio_screen(void) rec_record(); update_screen = true; } -#endif +#endif /* SIMULATOR */ last_seconds = 0; break; #endif /* #ifdef FM_RECORD */ @@ -602,63 +628,31 @@ int radio_screen(void) break; case ACTION_STD_PREV: - if(radio_mode == RADIO_SCAN_MODE) - { - curr_freq - -= fm_region[global_settings.fm_region].freq_step; - if(curr_freq < fm_region[global_settings.fm_region].freq_min) - curr_freq - = fm_region[global_settings.fm_region].freq_max; - radio_set(RADIO_FREQUENCY, curr_freq); - curr_preset = find_preset(curr_freq); - remember_frequency(); - } - else - next_preset(-1); - search_dir = 0; - update_screen = true; - break; - case ACTION_STD_NEXT: - if(radio_mode == RADIO_SCAN_MODE) - { - curr_freq - += fm_region[global_settings.fm_region].freq_step; - if(curr_freq > fm_region[global_settings.fm_region].freq_max) - curr_freq - = fm_region[global_settings.fm_region].freq_min; - radio_set(RADIO_FREQUENCY, curr_freq); - curr_preset = find_preset(curr_freq); - remember_frequency(); - } - else - next_preset(1); - search_dir = 0; + next_station(button == ACTION_STD_PREV ? -1 : 1); + end_search(); update_screen = true; break; case ACTION_STD_PREVREPEAT: - if(radio_mode == RADIO_SCAN_MODE) - search_dir = -1; - else - { - next_preset(-1); - update_screen = true; - } - - break; - case ACTION_STD_NEXTREPEAT: - if(radio_mode == RADIO_SCAN_MODE) - search_dir = 1; - else + { + int dir = search_dir; + search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1; + if (radio_mode != RADIO_SCAN_MODE) { - next_preset(1); + next_preset(search_dir); + end_search(); + update_screen = true; + } + else if (dir == 0) + { + /* Starting auto scan */ + radio_set(RADIO_MUTE, 1); update_screen = true; } - break; - + } case ACTION_SETTINGS_INC: case ACTION_SETTINGS_INCREPEAT: @@ -693,8 +687,9 @@ int radio_screen(void) radio_menu(); curr_preset = find_preset(curr_freq); FOR_NB_SCREENS(i){ - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); + struct screen *sc = &screens[i]; + gui_textarea_clear(sc); + screen_set_xmargin(sc, 0); } #ifdef HAS_BUTTONBAR gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), @@ -712,9 +707,10 @@ int radio_screen(void) update_screen = true; FOR_NB_SCREENS(i) { - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); - gui_textarea_update(&screens[i]); + struct screen *sc = &screens[i]; + gui_textarea_clear(sc); + screen_set_xmargin(sc, 0); + gui_textarea_update(sc); } break; @@ -722,9 +718,10 @@ int radio_screen(void) handle_radio_presets(); FOR_NB_SCREENS(i) { - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); - gui_textarea_update(&screens[i]); + struct screen *sc = &screens[i]; + gui_textarea_clear(sc); + screen_set_xmargin(sc, 0); + gui_textarea_update(sc); } #ifdef HAS_BUTTONBAR gui_buttonbar_set(&buttonbar, @@ -734,7 +731,7 @@ int radio_screen(void) #endif update_screen = true; break; -#endif +#endif /* FM_PRESET */ #ifdef FM_FREEZE case ACTION_FM_FREEZE: @@ -749,10 +746,13 @@ int radio_screen(void) screen_freeze = false; } break; -#endif +#endif /* FM_FREEZE */ + case SYS_USB_CONNECTED: +#if CONFIG_CODEC != SWCODEC /* Only accept USB connection when not recording */ if(audio_status() != AUDIO_STATUS_RECORD) +#endif { default_event_handler(SYS_USB_CONNECTED); screen_freeze = true; /* Cosmetic: makes sure the @@ -773,18 +773,20 @@ int radio_screen(void) radio_mode = RADIO_SCAN_MODE; update_screen = true; break; -#endif +#endif /* FM_MODE */ + #ifdef FM_NEXT_PRESET case ACTION_FM_NEXT_PRESET: next_preset(1); - search_dir = 0; + end_search(); update_screen = true; break; #endif + #ifdef FM_PREV_PRESET case ACTION_FM_PREV_PRESET: next_preset(-1); - search_dir = 0; + end_search(); update_screen = true; break; #endif @@ -794,8 +796,10 @@ int radio_screen(void) break; } /*switch(button)*/ +#ifdef FM_RECORD_DBLPRE if (button != ACTION_NONE) lastbutton = button; +#endif #if CONFIG_CODEC != SWCODEC peak_meter_peek(); @@ -804,10 +808,9 @@ int radio_screen(void) if(!screen_freeze) { /* Only display the peak meter when not recording */ +#if CONFIG_CODEC != SWCODEC if(!audio_status()) { - -#if CONFIG_CODEC != SWCODEC FOR_NB_SCREENS(i) { peak_meter_screen(&screens[i],0, @@ -815,44 +818,46 @@ int radio_screen(void) screens[i].update_rect(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4), screens[i].width, fh); } -#endif - } if(TIME_AFTER(current_tick, timeout)) { timeout = current_tick + HZ; +#else /* SWCODEC */ + { +#endif /* CONFIG_CODEC == SWCODEC */ /* keep "mono" from always being displayed when paused */ if (radio_status != FMRADIO_PAUSED) { stereo = radio_get(RADIO_STEREO) && !global_settings.fm_force_mono; - if(stereo != last_stereo_status) + + if(stereo != last_stereo) { update_screen = true; - last_stereo_status = stereo; + last_stereo = stereo; } } } - -#ifndef SIMULATOR -#if CONFIG_CODEC != SWCODEC + +#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) seconds = audio_recorded_time() / HZ; -#endif -#endif - if(update_screen || seconds > last_seconds) + if (update_screen || seconds > last_seconds) { last_seconds = seconds; +#else + if (update_screen) + { +#endif + int freq; FOR_NB_SCREENS(i) screens[i].setfont(FONT_UI); - if (curr_preset >= 0 ) - snprintf(buf, 128, "%d. %s",curr_preset + 1, - presets[curr_preset].name); - else - snprintf(buf, 128, " "); + snprintf(buf, 128, curr_preset >= 0 ? "%d. %s" : " ", + curr_preset + 1, presets[curr_preset].name); + FOR_NB_SCREENS(i) screens[i].puts_scroll(0, top_of_screen, buf); @@ -871,6 +876,7 @@ int radio_screen(void) str(LANG_RADIO_SCAN_MODE)); FOR_NB_SCREENS(i) screens[i].puts_scroll(0, top_of_screen + 3, buf); + #if CONFIG_CODEC != SWCODEC if(audio_status() == AUDIO_STATUS_RECORD) { @@ -892,7 +898,7 @@ int radio_screen(void) screens[i].puts_scroll(0, top_of_screen + 4, buf); } } -#endif +#endif /* CONFIG_CODEC != SWCODEC */ #ifdef HAS_BUTTONBAR gui_buttonbar_draw(&buttonbar); @@ -902,21 +908,27 @@ int radio_screen(void) } /* Only force the redraw if update_screen is true */ gui_syncstatusbar_draw(&statusbars,true); - - update_screen = false; } + update_screen = false; + +#if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { done = true; } +#endif + +#ifndef HAVE_NOISY_IDLE_MODE if (TIME_AFTER(current_tick, button_timeout)) { cpu_idle_mode(true); } +#endif } /*while(!done)*/ #ifndef SIMULATOR +#if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { gui_syncsplash(0, true, str(LANG_DISK_FULL)); @@ -933,16 +945,15 @@ int radio_screen(void) } } -#if CONFIG_CODEC != SWCODEC audio_init_playback(); -#endif +#endif /* CONFIG_CODEC != SWCODEC */ sound_settings_apply(); #endif /* SIMULATOR */ if(keep_playing) { -/* Catch FMRADIO_PLAYING status for the sim. */ +/* Catch FMRADIO_PLAYING status for the sim. */ #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC /* Enable the Left and right A/D Converter */ @@ -951,7 +962,8 @@ int radio_screen(void) AUDIO_GAIN_LINEIN); mas_codec_writereg(6, 0x4000); #endif -#endif + end_search(); +#endif /* SIMULATOR */ } else { @@ -961,15 +973,20 @@ int radio_screen(void) radio_stop(); #endif } - + +#ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(false); +#endif /* restore status bar settings */ global_settings.statusbar = statusbar; in_screen = false; - +#if CONFIG_CODEC != SWCODEC return have_recorded; +#else + return false; +#endif } /* radio_screen */ static void radio_save_presets(void) @@ -1006,7 +1023,6 @@ void radio_load_presets(char *filename) bool done = false; int f; - memset(presets, 0, sizeof(presets)); num_presets = 0; @@ -1037,9 +1053,10 @@ void radio_load_presets(char *filename) f = atoi(freq); if(f) /* For backwards compatibility */ { - presets[num_presets].frequency = f; - strncpy(presets[num_presets].name, name, MAX_FMPRESET_LEN); - presets[num_presets].name[MAX_FMPRESET_LEN] = 0; + struct fmstation * const fms = &presets[num_presets]; + fms->frequency = f; + strncpy(fms->name, name, MAX_FMPRESET_LEN); + fms->name[MAX_FMPRESET_LEN] = '\0'; num_presets++; } } @@ -1051,12 +1068,8 @@ void radio_load_presets(char *filename) } else /* invalid file name? */ filepreset[0] = '\0'; - - if(num_presets > 0) - presets_loaded = true; - else - presets_loaded = false; - + + presets_loaded = num_presets > 0; presets_changed = false; } @@ -1071,13 +1084,13 @@ static int radio_add_preset(void) if (!kbd_input(buf, MAX_FMPRESET_LEN)) { - buf[MAX_FMPRESET_LEN] = 0; - strcpy(presets[num_presets].name, buf); - presets[num_presets].frequency = curr_freq; + struct fmstation * const fms = &presets[num_presets]; + buf[MAX_FMPRESET_LEN] = '\0'; + strcpy(fms->name, buf); + fms->frequency = curr_freq; num_presets++; presets_changed = true; - if(num_presets > 0) - presets_loaded = true; + presets_loaded = num_presets > 0; } } else @@ -1088,43 +1101,53 @@ static int radio_add_preset(void) } /* needed to know which preset we are edit/delete-ing */ -static int selected_preset = 0; +static int selected_preset = -1; static int radio_edit_preset(void) { char buf[MAX_FMPRESET_LEN]; - strncpy(buf, presets[selected_preset].name, MAX_FMPRESET_LEN); - - if (!kbd_input(buf, MAX_FMPRESET_LEN)) + if (num_presets > 0) { - buf[MAX_FMPRESET_LEN] = 0; - strcpy(presets[selected_preset].name, buf); - presets_changed = true; + struct fmstation * const fms = &presets[selected_preset]; + + strncpy(buf, fms->name, MAX_FMPRESET_LEN); + + if (!kbd_input(buf, MAX_FMPRESET_LEN)) + { + buf[MAX_FMPRESET_LEN] = '\0'; + strcpy(fms->name, buf); + presets_changed = true; + } } + return true; } static int radio_delete_preset(void) { - int pos = selected_preset; - int i; + if (num_presets > 0) + { + struct fmstation * const fms = &presets[selected_preset]; - for(i = pos;i < num_presets;i++) - presets[i] = presets[i+1]; - num_presets--; + if (selected_preset >= --num_presets) + selected_preset = num_presets - 1; + + memmove(fms, fms + 1, (uintptr_t)(fms + num_presets) - + (uintptr_t)fms); + + } /* Don't ask to save when all presets are deleted. */ - if(num_presets > 0) - presets_changed = true; - else + presets_changed = num_presets > 0; + + if (!presets_changed) { - presets_changed = false; /* The preset list will be cleared, switch to Scan Mode. */ radio_mode = RADIO_SCAN_MODE; presets_loaded = false; } - return true; /* Make the menu return immediately */ + return true; } static int load_preset_list(void) @@ -1134,7 +1157,7 @@ static int load_preset_list(void) static int save_preset_list(void) { - if(num_presets != 0) + if(num_presets > 0) { bool bad_file_name = true; @@ -1187,13 +1210,8 @@ static int save_preset_list(void) static int clear_preset_list(void) { - int i; - /* Clear all the preset entries */ - for(i = 0;i <= num_presets;i++){ - presets[i].name[0] = '\0'; - presets[i].frequency = 0; - } + memset(presets, 0, sizeof (presets)); num_presets = 0; presets_loaded = false; @@ -1211,10 +1229,10 @@ MENUITEM_FUNCTION(radio_delete_preset_item, ID2P(LANG_FM_DELETE_PRESET), radio_delete_preset, NULL, Icon_NOICON); int radio_preset_callback(int action, const struct menu_item_ex *this_item) { - (void)this_item; if (action == ACTION_STD_OK) - return ACTION_EXIT_AFTER_THIS_MENUITEM; + action = ACTION_EXIT_AFTER_THIS_MENUITEM; return action; + (void)this_item; } MAKE_MENU(handle_radio_preset_menu, ID2P(LANG_FM_BUTTONBAR_PRESETS), radio_preset_callback, Icon_NOICON, &radio_edit_preset_item, @@ -1272,7 +1290,7 @@ static int handle_radio_presets(void) case ACTION_STD_OK: curr_preset = gui_synclist_get_sel_pos(&lists); curr_freq = presets[curr_preset].frequency; - radio_set(RADIO_FREQUENCY, curr_freq); + next_station(0); remember_frequency(); result = 1; break; @@ -1302,15 +1320,7 @@ void set_radio_region(int region) fm_region[region].deemphasis); radio_set(RADIO_SET_BAND, fm_region[region].band); #endif - /* make sure the current frequency is in the region range */ - curr_freq -= (curr_freq - fm_region[region].freq_min) - % fm_region[region].freq_step; - if(curr_freq < fm_region[region].freq_min) - curr_freq = fm_region[region].freq_min; - if(curr_freq > fm_region[region].freq_max) - curr_freq = fm_region[region].freq_max; - radio_set(RADIO_FREQUENCY, curr_freq); - + next_station(0); remember_frequency(); } @@ -1340,52 +1350,52 @@ MENUITEM_FUNCTION_WPARAM_DYNTEXT(radio_mode_item, toggle_radio_mode, NULL, NULL, static int scan_presets(void) { - bool tuned = false, do_scan = true; - char buf[MAX_FMPRESET_LEN]; - int freq, i; + bool do_scan = true; if(num_presets > 0) /* Do that to avoid 2 questions. */ do_scan = yesno_pop(str(LANG_FM_CLEAR_PRESETS)); if(do_scan) { - curr_freq = fm_region[global_settings.fm_region].freq_min; + const struct fm_region_setting * const fmr = + &fm_region[global_settings.fm_region]; + char buf[MAX_FMPRESET_LEN]; + int i; + + curr_freq = fmr->freq_min; num_presets = 0; memset(presets, 0, sizeof(presets)); - while(curr_freq <= fm_region[global_settings.fm_region].freq_max) + radio_set(RADIO_MUTE, 1); + + while(curr_freq <= fmr->freq_max) { + int freq, frac; if (num_presets >= MAX_PRESETS || action_userabort(TIMEOUT_NOBLOCK)) break; freq = curr_freq / 10000; - snprintf(buf, MAX_FMPRESET_LEN, str(LANG_FM_SCANNING), - freq/100, freq % 100); + frac = freq % 100; + freq /= 100; + + snprintf(buf, MAX_FMPRESET_LEN, str(LANG_FM_SCANNING), freq, frac); gui_syncsplash(0, true, buf); - /* Tune in and delay */ - radio_set(RADIO_FREQUENCY, curr_freq); - sleep(1); - - /* Start IF measurement */ - radio_set(RADIO_IF_MEASUREMENT, 1); - sleep(1); - - /* Now check how close to the IF frequency we are */ - tuned = radio_get(RADIO_TUNED); - - /* add preset */ - if(tuned){ - snprintf(buf, MAX_FMPRESET_LEN, - str(LANG_FM_DEFAULT_PRESET_NAME),freq/100, freq % 100); - strcpy(presets[num_presets].name,buf); - presets[num_presets].frequency = curr_freq; - num_presets++; + if(radio_set(RADIO_SCAN_FREQUENCY, curr_freq)) + { + /* add preset */ + snprintf(buf, MAX_FMPRESET_LEN, + str(LANG_FM_DEFAULT_PRESET_NAME), freq, frac); + strcpy(presets[num_presets].name,buf); + presets[num_presets].frequency = curr_freq; + num_presets++; } - curr_freq += fm_region[global_settings.fm_region].freq_step; - + curr_freq += fmr->freq_step; } + if (radio_status == FMRADIO_PLAYING) + radio_set(RADIO_MUTE, 0); + presets_changed = true; FOR_NB_SCREENS(i) @@ -1395,22 +1405,24 @@ static int scan_presets(void) gui_textarea_update(&screens[i]); } - if(num_presets > 0 ) + if(num_presets > 0) { curr_freq = presets[0].frequency; - radio_set(RADIO_FREQUENCY, curr_freq); - remember_frequency(); radio_mode = RADIO_PRESET_MODE; presets_loaded = true; + next_station(0); } else + { + /* Wrap it to beginning or we'll be past end of band */ presets_loaded = false; + next_station(1); + } } return true; } -#ifndef SIMULATOR #ifdef HAVE_RECORDING #if defined(HAVE_FMRADIO_IN) && CONFIG_CODEC == SWCODEC @@ -1433,8 +1445,6 @@ static int fm_recording_screen(void) return ret; } -MENUITEM_FUNCTION(recscreen_item, ID2P(LANG_RECORDING_MENU), - fm_recording_screen, NULL, Icon_NOICON); #endif /* defined(HAVE_FMRADIO_IN) && CONFIG_CODEC == SWCODEC */ #if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC @@ -1442,6 +1452,7 @@ MENUITEM_FUNCTION(recscreen_item, ID2P(LANG_RECORDING_MENU), static int fm_recording_settings(void) { bool ret = recording_menu(true); + #if CONFIG_CODEC != SWCODEC if (!ret) { @@ -1454,11 +1465,17 @@ static int fm_recording_settings(void) return ret; } -MENUITEM_FUNCTION(recsettings_item, ID2P(LANG_RECORDING_SETTINGS), - fm_recording_settings, NULL, Icon_NOICON); #endif /* defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC */ #endif /* HAVE_RECORDING */ -#endif /* SIMULATOR */ + +#ifdef FM_RECORDING_SCREEN +MENUITEM_FUNCTION(recscreen_item, ID2P(LANG_RECORDING_MENU), + fm_recording_screen, NULL, Icon_NOICON); +#endif +#ifdef FM_RECORDING_SETTINGS +MENUITEM_FUNCTION(recsettings_item, ID2P(LANG_RECORDING_SETTINGS), + fm_recording_settings, NULL, Icon_NOICON); +#endif #ifndef FM_PRESET MENUITEM_FUNCTION(radio_presets_item, ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets, NULL, Icon_NOICON); diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h index add3989061..f04c14d6d3 100644 --- a/apps/recorder/radio.h +++ b/apps/recorder/radio.h @@ -50,8 +50,14 @@ struct fm_region_setting int freq_max; int freq_step; #if (CONFIG_TUNER & TEA5767) - int deemphasis; /* 0: 50us, 1: 75us */ - int band; /* 0: europe, 1: japan (BL in TEA spec)*/ + char deemphasis; /* 0: 50us, 1: 75us */ + char band; /* 0: europe, 1: japan (BL in TEA spec)*/ + /* Note: "region" parameter is just for display atm and is not compiled. */ + #define FM_REGION_ENTRY(region, fmin, fmax, fstep, deemph, band) \ + { fmin, fmax, fstep, deemph, band } +#else + #define FM_REGION_ENTRY(region, fmin, fmax, fstep, deemph, band) \ + { fmin, fmax, fstep } #endif }; diff --git a/firmware/export/tuner.h b/firmware/export/tuner.h index 0a13613711..590e61dedb 100644 --- a/firmware/export/tuner.h +++ b/firmware/export/tuner.h @@ -20,34 +20,81 @@ #ifndef __TUNER_SAMSUNG_H__ #define __TUNER_SAMSUNG_H__ +#include "hwcompat.h" + /* settings to the tuner layer */ +#define RADIO_ALL -1 /* debug */ #define RADIO_SLEEP 0 #define RADIO_FREQUENCY 1 #define RADIO_MUTE 2 #define RADIO_IF_MEASUREMENT 3 #define RADIO_SENSITIVITY 4 #define RADIO_FORCE_MONO 5 +#define RADIO_SCAN_FREQUENCY 6 #if (CONFIG_TUNER & TEA5767) -#define RADIO_SET_DEEMPHASIS 6 -#define RADIO_SET_BAND 7 +#define RADIO_SET_DEEMPHASIS 7 +#define RADIO_SET_BAND 8 #endif /* readback from the tuner layer */ #define RADIO_PRESENT 0 #define RADIO_TUNED 1 #define RADIO_STEREO 2 -#define RADIO_ALL 3 /* debug */ #if CONFIG_TUNER -#if (CONFIG_TUNER & S1A0903X01) -void samsung_set(int setting, int value); -int samsung_get(int setting); +#ifdef SIMULATOR +int radio_set(int setting, int value); +int radio_get(int setting); +#else +#if CONFIG_TUNER == S1A0903X01 /* FM recorder */ +#define radio_set samsung_set +#define radio_get samsung_get +#elif CONFIG_TUNER == TEA5767 /* iRiver, iAudio */ +#define radio_set philips_set +#define radio_get philips_get +#elif CONFIG_TUNER == (S1A0903X01 | TEA5767) /* OndioFM */ +#define radio_set _radio_set +#define radio_get _radio_get +int (*_radio_set)(int setting, int value); +int (*_radio_get)(int setting); +#endif #endif +#if (CONFIG_TUNER & S1A0903X01) +int samsung_set(int setting, int value); +int samsung_get(int setting); +#endif /* CONFIG_TUNER & S1A0903X01 */ + #if (CONFIG_TUNER & TEA5767) -void philips_set(int setting, int value); +struct philips_dbg_info +{ + unsigned char read_regs[5]; + unsigned char write_regs[5]; +}; +int philips_set(int setting, int value); int philips_get(int setting); +void philips_dbg_info(struct philips_dbg_info *info); +#endif /* CONFIG_TUNER & TEA5767 */ + +/* Just inline here since only radio screen needs this atm and + there's no tuner.c. */ +static inline void tuner_init(void) +{ +#ifndef SIMULATOR +#if CONFIG_TUNER == (S1A0903X01 | TEA5767) + if (read_hw_mask() & TUNER_MODEL) + { + _radio_set = philips_set; + _radio_get = philips_get; + } + else + { + _radio_set = samsung_set; + _radio_get = samsung_get; + } #endif +#endif +} #endif /* #if CONFIG_TUNER */ diff --git a/firmware/tuner_philips.c b/firmware/tuner_philips.c index 0a6f5c4c7f..8520fdbae9 100644 --- a/firmware/tuner_philips.c +++ b/firmware/tuner_philips.c @@ -29,7 +29,7 @@ static unsigned char write_bytes[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; /* tuner abstraction layer: set something to the tuner */ -void philips_set(int setting, int value) +int philips_set(int setting, int value) { switch(setting) { @@ -60,6 +60,11 @@ void philips_set(int setting, int value) } break; + case RADIO_SCAN_FREQUENCY: + philips_set(RADIO_FREQUENCY, value); + sleep(HZ/30); + return philips_get(RADIO_TUNED); + case RADIO_MUTE: write_bytes[0] = (write_bytes[0] & 0x7F) | (value ? 0x80 : 0); break; @@ -75,9 +80,10 @@ void philips_set(int setting, int value) case RADIO_SET_BAND: write_bytes[3] = (write_bytes[3] & ~(1<<5)) | (value ? (1<<5) : 0); default: - return; + return -1; } fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes)); + return 1; } /* tuner abstraction layer: read something from the tuner */ @@ -106,13 +112,12 @@ int philips_get(int setting) case RADIO_STEREO: val = read_bytes[2] >> 7; break; - - case RADIO_ALL: /* debug query */ - val = read_bytes[0] << 24 - | read_bytes[1] << 16 - | read_bytes[2] << 8 - | read_bytes[3]; - break; } return val; } + +void philips_dbg_info(struct philips_dbg_info *info) +{ + fmradio_i2c_read(I2C_ADR, info->read_regs, 5); + memcpy(info->write_regs, write_bytes, 5); +} diff --git a/firmware/tuner_samsung.c b/firmware/tuner_samsung.c index b0887d0d7a..82934d7160 100644 --- a/firmware/tuner_samsung.c +++ b/firmware/tuner_samsung.c @@ -21,6 +21,7 @@ #include #include #include "config.h" +#include "kernel.h" #include "tuner.h" /* tuner abstraction interface */ #include "fmradio.h" /* physical interface driver */ #include "mpeg.h" @@ -34,8 +35,10 @@ static int fm_in1; static int fm_in2; /* tuner abstraction layer: set something to the tuner */ -void samsung_set(int setting, int value) +int samsung_set(int setting, int value) { + int val = 1; + switch(setting) { case RADIO_SLEEP: @@ -90,6 +93,16 @@ void samsung_set(int setting, int value) break; } + case RADIO_SCAN_FREQUENCY: + /* Tune in and delay */ + samsung_set(RADIO_FREQUENCY, value); + sleep(1); + /* Start IF measurement */ + samsung_set(RADIO_IF_MEASUREMENT, 1); + sleep(1); + val = samsung_get(RADIO_TUNED); + break; + case RADIO_MUTE: fm_in1 = (fm_in1 & 0xfffffffe) | (value?1:0); fmradio_set(1, fm_in1); @@ -109,7 +122,11 @@ void samsung_set(int setting, int value) fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4); fmradio_set(2, fm_in2); break; + default: + val = -1; } + + return val; } /* tuner abstraction layer: read something from the tuner */ diff --git a/uisimulator/common/fmradio.c b/uisimulator/common/fmradio.c index ea6d6f6aa5..d7acaa513b 100644 --- a/uisimulator/common/fmradio.c +++ b/uisimulator/common/fmradio.c @@ -26,7 +26,7 @@ static int frequency = 0; static bool mono = false; -void radio_set(int setting, int value) +int radio_set(int setting, int value) { switch(setting) { @@ -37,6 +37,10 @@ void radio_set(int setting, int value) frequency = value; break; + case RADIO_SCAN_FREQUENCY: + frequency = value; + break; + case RADIO_MUTE: break; @@ -45,8 +49,10 @@ void radio_set(int setting, int value) break; default: - return; + return -1; } + + return 1; } int radio_get(int setting)