1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
33 #include "menus/exported_menus.h"
36 #include "peakmeter.h"
39 #include "recording.h"
41 #ifdef IPOD_ACCESSORY_PROTOCOL
48 #include "screen_access.h"
55 #include "skin_engine/skin_engine.h"
56 #include "statusbar-skinned.h"
57 #if CONFIG_CODEC == SWCODEC
64 #if CONFIG_KEYPAD == RECORDER_PAD
67 #define FM_PRESET_ACTION
71 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
74 #define FM_NEXT_PRESET
75 #define FM_PREV_PRESET
77 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
81 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
84 /* This should be removeable if the whole tuning thing is sorted out since
85 proper tuning quiets the screen almost entirely in that extreme measures
86 have to be taken to hear any interference. */
87 #define HAVE_NOISY_IDLE_MODE
89 #elif CONFIG_KEYPAD == ONDIO_PAD
90 #define FM_RECORD_DBLPRE
93 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
94 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
102 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
106 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
114 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
115 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
122 #elif (CONFIG_KEYPAD == MPIO_HD200_PAD)
132 /* presets.c needs these so keep unstatic or redo the whole thing! */
133 int curr_freq
; /* current frequency in Hz */
134 int radio_mode
= RADIO_SCAN_MODE
;
136 static int search_dir
= 0;
137 static int radio_status
= FMRADIO_OFF
;
138 static bool in_screen
= false;
141 static void radio_off(void);
143 bool radio_scan_mode(void)
145 return radio_mode
== RADIO_SCAN_MODE
;
148 bool radio_is_stereo(void)
150 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
152 int radio_current_frequency(void)
157 void radio_init(void)
162 radioart_init(false);
166 int get_radio_status(void)
171 bool in_radio_screen(void)
176 /* TODO: Move some more of the control functionality to firmware
177 and clean up the mess */
179 /* secret flag for starting paused - prevents unmute */
180 #define FMRADIO_START_PAUSED 0x8000
181 void radio_start(void)
183 const struct fm_region_data
*fmr
;
186 if(radio_status
== FMRADIO_PLAYING
)
189 fmr
= &fm_region_data
[global_settings
.fm_region
];
191 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
192 /* clear flag before any yielding */
193 radio_status
&= ~FMRADIO_START_PAUSED
;
195 if(radio_status
== FMRADIO_OFF
)
198 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
200 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
202 if(radio_status
== FMRADIO_OFF
)
204 #ifdef HAVE_RADIO_REGION
205 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
207 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
210 tuner_set(RADIO_FREQUENCY
, curr_freq
);
212 #ifdef HAVE_RADIO_MUTE_TIMEOUT
214 unsigned long mute_timeout
= current_tick
+ HZ
;
215 if (radio_status
!= FMRADIO_OFF
)
221 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
223 if(TIME_AFTER(current_tick
, mute_timeout
))
230 /* keep radio from sounding initially */
232 tuner_set(RADIO_MUTE
, 0);
234 radio_status
= FMRADIO_PLAYING
;
237 void radio_pause(void)
239 if(radio_status
== FMRADIO_PAUSED
)
242 if(radio_status
== FMRADIO_OFF
)
244 radio_status
|= FMRADIO_START_PAUSED
;
248 tuner_set(RADIO_MUTE
, 1);
249 /* For si4700: 2==this is really 'pause'. other tuners treat it
251 tuner_set(RADIO_SLEEP
, 2);
253 radio_status
= FMRADIO_PAUSED
;
256 static void radio_off(void)
258 tuner_set(RADIO_MUTE
, 1);
259 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
260 radio_status
= FMRADIO_OFF
;
261 tuner_power(false); /* status update, power off if avail. */
264 void radio_stop(void)
266 if(radio_status
== FMRADIO_OFF
)
272 bool radio_hardware_present(void)
274 return tuner_get(RADIO_PRESENT
);
277 /* Keep freq on the grid for the current region */
278 int snap_freq_to_grid(int freq
)
280 const struct fm_region_data
* const fmr
=
281 &fm_region_data
[global_settings
.fm_region
];
283 /* Range clamp if out of range or just round to nearest */
284 if (freq
< fmr
->freq_min
)
285 freq
= fmr
->freq_min
;
286 else if (freq
> fmr
->freq_max
)
287 freq
= fmr
->freq_max
;
289 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
290 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
295 void remember_frequency(void)
297 const struct fm_region_data
* const fmr
=
298 &fm_region_data
[global_settings
.fm_region
];
299 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
304 /* Step to the next or previous frequency */
305 static int step_freq(int freq
, int direction
)
307 const struct fm_region_data
* const fmr
=
308 &fm_region_data
[global_settings
.fm_region
];
310 freq
+= direction
*fmr
->freq_step
;
312 /* Wrap first or snapping to grid will not let us on the band extremes */
313 if (freq
> fmr
->freq_max
)
314 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
315 else if (freq
< fmr
->freq_min
)
316 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
318 freq
= snap_freq_to_grid(freq
);
323 /* Step to the next or previous station */
324 void next_station(int direction
)
326 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
328 preset_next(direction
);
332 curr_freq
= step_freq(curr_freq
, direction
);
334 if (radio_status
== FMRADIO_PLAYING
)
335 tuner_set(RADIO_MUTE
, 1);
337 tuner_set(RADIO_FREQUENCY
, curr_freq
);
339 if (radio_status
== FMRADIO_PLAYING
)
340 tuner_set(RADIO_MUTE
, 0);
342 preset_set_current(preset_find(curr_freq
));
343 remember_frequency();
346 /* Ends an in-progress search */
347 static void end_search(void)
349 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
350 tuner_set(RADIO_MUTE
, 0);
354 void radio_screen(void)
359 bool stereo
= false, last_stereo
= false;
361 bool screen_freeze
= false;
362 bool keep_playing
= false;
364 #ifdef FM_RECORD_DBLPRE
365 int lastbutton
= BUTTON_NONE
;
366 unsigned long rec_lastclick
= 0;
368 #if CONFIG_CODEC != SWCODEC
369 int timeout
= current_tick
+ HZ
/10;
370 #if !defined(SIMULATOR)
371 unsigned int last_seconds
= 0;
372 unsigned int seconds
= 0;
373 struct audio_recording_options rec_options
;
374 #endif /* SIMULATOR */
375 #endif /* CONFIG_CODEC != SWCODEC */
376 #ifndef HAVE_NOISY_IDLE_MODE
377 int button_timeout
= current_tick
+ (2*HZ
);
380 /* change status to "in screen" */
381 push_current_activity(ACTIVITY_FM
);
384 if(radio_preset_count() <= 0)
386 radio_load_presets(global_settings
.fmr_file
);
388 skin_get_global_state()->id3
= NULL
;
393 if(radio_status
== FMRADIO_OFF
)
398 #if CONFIG_CODEC != SWCODEC
399 rec_create_directory();
400 audio_init_recording();
402 sound_settings_apply();
403 /* Yes, we use the D/A for monitoring */
404 peak_meter_playback(true);
406 peak_meter_enable(true);
408 rec_init_recording_options(&rec_options
);
409 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
410 rec_set_recording_options(&rec_options
);
412 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
413 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
415 #endif /* CONFIG_CODEC != SWCODEC */
416 #endif /* ndef SIMULATOR */
419 #if CONFIG_CODEC == SWCODEC
420 /* This should be done before touching audio settings */
421 while (!audio_is_thread_ready())
424 audio_set_input_source(AUDIO_SRC_FMRADIO
,
425 (radio_status
== FMRADIO_PAUSED
) ?
426 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
428 if (radio_status
== FMRADIO_OFF
)
432 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
435 fms_fix_displays(FMS_ENTER
);
437 skin_update(FM_SCREEN
, i
, SKIN_REFRESH_ALL
);
439 preset_set_current(preset_find(curr_freq
));
440 if(radio_current_preset() != -1)
441 radio_mode
= RADIO_PRESET_MODE
;
443 #ifndef HAVE_NOISY_IDLE_MODE
451 curr_freq
= step_freq(curr_freq
, search_dir
);
452 update_type
= SKIN_REFRESH_ALL
;
454 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
456 preset_set_current(preset_find(curr_freq
));
457 remember_frequency();
469 button
= fms_do_button_loop(update_type
>0);
471 #ifndef HAVE_NOISY_IDLE_MODE
472 if (button
!= ACTION_NONE
)
474 cpu_idle_mode(false);
475 button_timeout
= current_tick
+ (2*HZ
);
481 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
482 if(audio_status() == AUDIO_STATUS_RECORD
)
490 if(presets_have_changed())
492 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
498 update_type
= SKIN_REFRESH_NON_STATIC
;
502 case ACTION_FM_RECORD
:
503 #ifdef FM_RECORD_DBLPRE
504 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
509 if (current_tick
- rec_lastclick
> HZ
/2)
511 rec_lastclick
= current_tick
;
514 #endif /* FM_RECORD_DBLPRE */
516 if(audio_status() == AUDIO_STATUS_RECORD
)
518 rec_command(RECORDING_CMD_START_NEWFILE
);
519 update_type
= SKIN_REFRESH_ALL
;
523 rec_command(RECORDING_CMD_START
);
524 update_type
= SKIN_REFRESH_ALL
;
526 #if CONFIG_CODEC != SWCODEC
529 #endif /* SIMULATOR */
531 #endif /* #ifdef FM_RECORD */
534 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
535 if(audio_status() == AUDIO_STATUS_RECORD
)
540 if(presets_have_changed())
542 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
550 case ACTION_STD_PREV
:
551 case ACTION_STD_NEXT
:
552 next_station(button
== ACTION_STD_PREV
? -1 : 1);
554 update_type
= SKIN_REFRESH_ALL
;
558 case ACTION_STD_PREVREPEAT
:
559 case ACTION_STD_NEXTREPEAT
:
561 int dir
= search_dir
;
562 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
563 if (radio_mode
!= RADIO_SCAN_MODE
)
565 preset_next(search_dir
);
571 /* Starting auto scan */
572 tuner_set(RADIO_MUTE
, 1);
574 update_type
= SKIN_REFRESH_ALL
;
578 case ACTION_SETTINGS_INC
:
579 case ACTION_SETTINGS_INCREPEAT
:
580 global_settings
.volume
++;
582 update_type
= SKIN_REFRESH_NON_STATIC
;
585 case ACTION_SETTINGS_DEC
:
586 case ACTION_SETTINGS_DECREPEAT
:
587 global_settings
.volume
--;
589 update_type
= SKIN_REFRESH_NON_STATIC
;
593 if (radio_status
== FMRADIO_PLAYING
)
598 update_type
= SKIN_REFRESH_NON_STATIC
;
604 fms_fix_displays(FMS_EXIT
);
605 do_menu(&radio_settings_menu
, NULL
, NULL
, false);
606 preset_set_current(preset_find(curr_freq
));
607 fms_fix_displays(FMS_ENTER
);
608 update_type
= SKIN_REFRESH_ALL
;
612 case ACTION_FM_PRESET
:
613 if(radio_preset_count() < 1)
615 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
616 update_type
= SKIN_REFRESH_ALL
;
619 fms_fix_displays(FMS_EXIT
);
620 handle_radio_presets();
621 fms_fix_displays(FMS_ENTER
);
622 update_type
= SKIN_REFRESH_ALL
;
624 #endif /* FM_PRESET */
627 case ACTION_FM_FREEZE
:
630 splash(HZ
, str(LANG_FM_FREEZE
));
631 screen_freeze
= true;
635 update_type
= SKIN_REFRESH_ALL
;
636 screen_freeze
= false;
639 #endif /* FM_FREEZE */
641 case SYS_USB_CONNECTED
:
642 #if CONFIG_CODEC != SWCODEC
643 /* Only accept USB connection when not recording */
644 if(audio_status() != AUDIO_STATUS_RECORD
)
647 default_event_handler(SYS_USB_CONNECTED
);
648 screen_freeze
= true; /* Cosmetic: makes sure the
649 radio screen doesn't redraw */
656 if(radio_mode
== RADIO_SCAN_MODE
)
658 /* Force scan mode if there are no presets. */
659 if(radio_preset_count() > 0)
660 radio_mode
= RADIO_PRESET_MODE
;
663 radio_mode
= RADIO_SCAN_MODE
;
664 update_type
= SKIN_REFRESH_ALL
;
665 cond_talk_ids_fq(radio_mode
?
666 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
671 #ifdef FM_NEXT_PRESET
672 case ACTION_FM_NEXT_PRESET
:
675 update_type
= SKIN_REFRESH_ALL
;
680 #ifdef FM_PREV_PRESET
681 case ACTION_FM_PREV_PRESET
:
684 update_type
= SKIN_REFRESH_ALL
;
689 update_type
= SKIN_REFRESH_NON_STATIC
;
693 default_event_handler(button
);
695 if (tuner_get(RADIO_EVENT
))
696 update_type
= SKIN_REFRESH_ALL
;
698 if (!tuner_get(RADIO_PRESENT
))
700 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
701 if(audio_status() == AUDIO_STATUS_RECORD
)
704 keep_playing
= false;
706 if(presets_have_changed())
708 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
710 radio_save_presets();
714 /* Clear the preset list on exit. */
720 #ifdef FM_RECORD_DBLPRE
721 if (button
!= ACTION_NONE
)
725 #if CONFIG_CODEC != SWCODEC
731 /* Only display the peak meter when not recording */
732 #if CONFIG_CODEC != SWCODEC
733 if(TIME_AFTER(current_tick
, timeout
))
735 timeout
= current_tick
+ HZ
;
738 #endif /* CONFIG_CODEC == SWCODEC */
740 /* keep "mono" from always being displayed when paused */
741 if (radio_status
!= FMRADIO_PAUSED
)
743 stereo
= tuner_get(RADIO_STEREO
) &&
744 !global_settings
.fm_force_mono
;
746 if(stereo
!= last_stereo
)
748 update_type
= SKIN_REFRESH_ALL
;
749 last_stereo
= stereo
;
754 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
755 seconds
= audio_recorded_time() / HZ
;
756 if (update_type
|| seconds
> last_seconds
)
758 last_seconds
= seconds
;
764 skin_update(FM_SCREEN
, i
, update_type
);
769 if (global_settings
.talk_file
&& talk
770 && radio_status
== FMRADIO_PAUSED
)
773 bool enqueue
= false;
774 if (radio_mode
== RADIO_SCAN_MODE
)
776 talk_value_decimal(curr_freq
, UNIT_INT
, 6, enqueue
);
779 if (radio_current_preset() >= 0)
780 preset_talk(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
784 #if CONFIG_CODEC != SWCODEC
785 if(audio_status() & AUDIO_STATUS_ERROR
)
791 #ifndef HAVE_NOISY_IDLE_MODE
792 if (TIME_AFTER(current_tick
, button_timeout
))
800 #if CONFIG_CODEC != SWCODEC
801 if(audio_status() & AUDIO_STATUS_ERROR
)
803 splash(0, str(LANG_DISK_FULL
));
808 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
809 if(button
== ACTION_FM_STOP
)
814 audio_init_playback();
815 #endif /* CONFIG_CODEC != SWCODEC */
817 sound_settings_apply();
818 #endif /* SIMULATOR */
822 /* Catch FMRADIO_PLAYING status for the sim. */
824 #if CONFIG_CODEC != SWCODEC
825 /* Enable the Left and right A/D Converter */
826 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
827 sound_default(SOUND_RIGHT_GAIN
),
829 mas_codec_writereg(6, 0x4000);
832 #endif /* SIMULATOR */
836 #if CONFIG_CODEC == SWCODEC
837 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
843 #ifndef HAVE_NOISY_IDLE_MODE
844 cpu_idle_mode(false);
846 fms_fix_displays(FMS_EXIT
);
847 pop_current_activity();
851 void toggle_mono_mode(bool mono
)
853 tuner_set(RADIO_FORCE_MONO
, mono
);
856 void set_radio_region(int region
)
858 #ifdef HAVE_RADIO_REGION
859 tuner_set(RADIO_REGION
, region
);
862 remember_frequency();