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)
130 #elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
137 #define FM_PREV_PRESET
138 #define FM_NEXT_PRESET
142 /* presets.c needs these so keep unstatic or redo the whole thing! */
143 int curr_freq
; /* current frequency in Hz */
144 int radio_mode
= RADIO_SCAN_MODE
;
146 static int search_dir
= 0;
147 static int radio_status
= FMRADIO_OFF
;
148 static bool in_screen
= false;
151 static void radio_off(void);
153 bool radio_scan_mode(void)
155 return radio_mode
== RADIO_SCAN_MODE
;
158 bool radio_is_stereo(void)
160 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
162 int radio_current_frequency(void)
167 void radio_init(void)
172 radioart_init(false);
176 int get_radio_status(void)
181 bool in_radio_screen(void)
186 /* TODO: Move some more of the control functionality to firmware
187 and clean up the mess */
189 /* secret flag for starting paused - prevents unmute */
190 #define FMRADIO_START_PAUSED 0x8000
191 void radio_start(void)
193 const struct fm_region_data
*fmr
;
196 if(radio_status
== FMRADIO_PLAYING
)
199 fmr
= &fm_region_data
[global_settings
.fm_region
];
201 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
202 /* clear flag before any yielding */
203 radio_status
&= ~FMRADIO_START_PAUSED
;
205 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
207 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
209 if(radio_status
== FMRADIO_OFF
)
211 #ifdef HAVE_RADIO_REGION
212 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
214 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
217 tuner_set(RADIO_FREQUENCY
, curr_freq
);
219 #ifdef HAVE_RADIO_MUTE_TIMEOUT
221 unsigned long mute_timeout
= current_tick
+ HZ
;
222 if (radio_status
!= FMRADIO_OFF
)
228 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
230 if(TIME_AFTER(current_tick
, mute_timeout
))
237 /* keep radio from sounding initially */
239 tuner_set(RADIO_MUTE
, 0);
241 radio_status
= FMRADIO_PLAYING
;
244 void radio_pause(void)
246 if(radio_status
== FMRADIO_PAUSED
)
249 if(radio_status
== FMRADIO_OFF
)
251 radio_status
|= FMRADIO_START_PAUSED
;
255 tuner_set(RADIO_MUTE
, 1);
257 radio_status
= FMRADIO_PAUSED
;
260 static void radio_off(void)
262 tuner_set(RADIO_MUTE
, 1);
263 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
264 radio_status
= FMRADIO_OFF
;
267 void radio_stop(void)
269 if(radio_status
== FMRADIO_OFF
)
275 bool radio_hardware_present(void)
277 return tuner_get(RADIO_PRESENT
);
280 /* Keep freq on the grid for the current region */
281 int snap_freq_to_grid(int freq
)
283 const struct fm_region_data
* const fmr
=
284 &fm_region_data
[global_settings
.fm_region
];
286 /* Range clamp if out of range or just round to nearest */
287 if (freq
< fmr
->freq_min
)
288 freq
= fmr
->freq_min
;
289 else if (freq
> fmr
->freq_max
)
290 freq
= fmr
->freq_max
;
292 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
293 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
298 void remember_frequency(void)
300 const struct fm_region_data
* const fmr
=
301 &fm_region_data
[global_settings
.fm_region
];
302 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
307 /* Step to the next or previous frequency */
308 static int step_freq(int freq
, int direction
)
310 const struct fm_region_data
* const fmr
=
311 &fm_region_data
[global_settings
.fm_region
];
313 freq
+= direction
*fmr
->freq_step
;
315 /* Wrap first or snapping to grid will not let us on the band extremes */
316 if (freq
> fmr
->freq_max
)
317 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
318 else if (freq
< fmr
->freq_min
)
319 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
321 freq
= snap_freq_to_grid(freq
);
326 /* Step to the next or previous station */
327 void next_station(int direction
)
329 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
331 preset_next(direction
);
335 curr_freq
= step_freq(curr_freq
, direction
);
337 if (radio_status
== FMRADIO_PLAYING
)
338 tuner_set(RADIO_MUTE
, 1);
340 tuner_set(RADIO_FREQUENCY
, curr_freq
);
342 if (radio_status
== FMRADIO_PLAYING
)
343 tuner_set(RADIO_MUTE
, 0);
345 preset_set_current(preset_find(curr_freq
));
346 remember_frequency();
349 /* Ends an in-progress search */
350 static void end_search(void)
352 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
353 tuner_set(RADIO_MUTE
, 0);
357 void radio_screen(void)
361 bool stereo
= false, last_stereo
= false;
363 bool screen_freeze
= false;
364 bool keep_playing
= false;
366 #ifdef FM_RECORD_DBLPRE
367 int lastbutton
= BUTTON_NONE
;
368 unsigned long rec_lastclick
= 0;
370 #if CONFIG_CODEC != SWCODEC
371 int timeout
= current_tick
+ HZ
/10;
372 #if !defined(SIMULATOR)
373 unsigned int last_seconds
= 0;
374 unsigned int seconds
= 0;
375 struct audio_recording_options rec_options
;
376 #endif /* SIMULATOR */
377 #endif /* CONFIG_CODEC != SWCODEC */
378 #ifndef HAVE_NOISY_IDLE_MODE
379 int button_timeout
= current_tick
+ (2*HZ
);
382 /* change status to "in screen" */
383 push_current_activity(ACTIVITY_FM
);
386 if(radio_preset_count() <= 0)
388 radio_load_presets(global_settings
.fmr_file
);
390 skin_get_global_state()->id3
= NULL
;
395 if(radio_status
== FMRADIO_OFF
)
400 #if CONFIG_CODEC != SWCODEC
401 rec_create_directory();
402 audio_init_recording();
404 sound_settings_apply();
405 /* Yes, we use the D/A for monitoring */
406 peak_meter_playback(true);
408 peak_meter_enable(true);
410 rec_init_recording_options(&rec_options
);
411 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
412 rec_set_recording_options(&rec_options
);
414 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
415 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
417 #endif /* CONFIG_CODEC != SWCODEC */
418 #endif /* ndef SIMULATOR */
420 #if CONFIG_CODEC == SWCODEC
421 /* This should be done before touching audio settings */
422 while (!pcm_is_initialized())
425 audio_set_input_source(AUDIO_SRC_FMRADIO
,
426 (radio_status
== FMRADIO_PAUSED
) ?
427 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
429 if (radio_status
== FMRADIO_OFF
)
433 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
436 fms_fix_displays(FMS_ENTER
);
438 skin_update(FM_SCREEN
, i
, SKIN_REFRESH_ALL
);
440 preset_set_current(preset_find(curr_freq
));
441 if(radio_current_preset() != -1)
442 radio_mode
= RADIO_PRESET_MODE
;
444 #ifndef HAVE_NOISY_IDLE_MODE
452 curr_freq
= step_freq(curr_freq
, search_dir
);
453 update_type
= SKIN_REFRESH_ALL
;
455 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
457 preset_set_current(preset_find(curr_freq
));
458 remember_frequency();
470 button
= fms_do_button_loop(update_type
>0);
472 #ifndef HAVE_NOISY_IDLE_MODE
473 if (button
!= ACTION_NONE
)
475 cpu_idle_mode(false);
476 button_timeout
= current_tick
+ (2*HZ
);
482 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
483 if(audio_status() == AUDIO_STATUS_RECORD
)
491 if(presets_have_changed())
493 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
499 update_type
= SKIN_REFRESH_NON_STATIC
;
503 case ACTION_FM_RECORD
:
504 #ifdef FM_RECORD_DBLPRE
505 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
510 if (current_tick
- rec_lastclick
> HZ
/2)
512 rec_lastclick
= current_tick
;
515 #endif /* FM_RECORD_DBLPRE */
517 if(audio_status() == AUDIO_STATUS_RECORD
)
519 rec_command(RECORDING_CMD_START_NEWFILE
);
520 update_type
= SKIN_REFRESH_ALL
;
524 rec_command(RECORDING_CMD_START
);
525 update_type
= SKIN_REFRESH_ALL
;
527 #if CONFIG_CODEC != SWCODEC
530 #endif /* SIMULATOR */
532 #endif /* #ifdef FM_RECORD */
535 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
536 if(audio_status() == AUDIO_STATUS_RECORD
)
541 if(presets_have_changed())
543 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
551 case ACTION_STD_PREV
:
552 case ACTION_STD_NEXT
:
553 next_station(button
== ACTION_STD_PREV
? -1 : 1);
555 update_type
= SKIN_REFRESH_ALL
;
559 case ACTION_STD_PREVREPEAT
:
560 case ACTION_STD_NEXTREPEAT
:
562 int dir
= search_dir
;
563 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
564 if (radio_mode
!= RADIO_SCAN_MODE
)
566 preset_next(search_dir
);
572 /* Starting auto scan */
573 tuner_set(RADIO_MUTE
, 1);
575 update_type
= SKIN_REFRESH_ALL
;
579 case ACTION_SETTINGS_INC
:
580 case ACTION_SETTINGS_INCREPEAT
:
581 global_settings
.volume
++;
583 update_type
= SKIN_REFRESH_NON_STATIC
;
586 case ACTION_SETTINGS_DEC
:
587 case ACTION_SETTINGS_DECREPEAT
:
588 global_settings
.volume
--;
590 update_type
= SKIN_REFRESH_NON_STATIC
;
594 if (radio_status
== FMRADIO_PLAYING
)
599 update_type
= SKIN_REFRESH_NON_STATIC
;
605 fms_fix_displays(FMS_EXIT
);
606 do_menu(&radio_settings_menu
, NULL
, NULL
, false);
607 preset_set_current(preset_find(curr_freq
));
608 fms_fix_displays(FMS_ENTER
);
609 update_type
= SKIN_REFRESH_ALL
;
613 case ACTION_FM_PRESET
:
614 if(radio_preset_count() < 1)
616 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
617 update_type
= SKIN_REFRESH_ALL
;
620 fms_fix_displays(FMS_EXIT
);
621 handle_radio_presets();
622 fms_fix_displays(FMS_ENTER
);
623 update_type
= SKIN_REFRESH_ALL
;
625 #endif /* FM_PRESET */
628 case ACTION_FM_FREEZE
:
631 splash(HZ
, str(LANG_FM_FREEZE
));
632 screen_freeze
= true;
636 update_type
= SKIN_REFRESH_ALL
;
637 screen_freeze
= false;
640 #endif /* FM_FREEZE */
642 case SYS_USB_CONNECTED
:
643 #if CONFIG_CODEC != SWCODEC
644 /* Only accept USB connection when not recording */
645 if(audio_status() != AUDIO_STATUS_RECORD
)
648 default_event_handler(SYS_USB_CONNECTED
);
649 screen_freeze
= true; /* Cosmetic: makes sure the
650 radio screen doesn't redraw */
657 if(radio_mode
== RADIO_SCAN_MODE
)
659 /* Force scan mode if there are no presets. */
660 if(radio_preset_count() > 0)
661 radio_mode
= RADIO_PRESET_MODE
;
664 radio_mode
= RADIO_SCAN_MODE
;
665 update_type
= SKIN_REFRESH_ALL
;
666 cond_talk_ids_fq(radio_mode
?
667 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
672 #ifdef FM_NEXT_PRESET
673 case ACTION_FM_NEXT_PRESET
:
676 update_type
= SKIN_REFRESH_ALL
;
681 #ifdef FM_PREV_PRESET
682 case ACTION_FM_PREV_PRESET
:
685 update_type
= SKIN_REFRESH_ALL
;
690 update_type
= SKIN_REFRESH_NON_STATIC
;
694 default_event_handler(button
);
696 if (tuner_get(RADIO_EVENT
))
697 update_type
= SKIN_REFRESH_ALL
;
699 if (!tuner_get(RADIO_PRESENT
))
701 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
702 if(audio_status() == AUDIO_STATUS_RECORD
)
705 keep_playing
= false;
707 if(presets_have_changed())
709 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
711 radio_save_presets();
715 /* Clear the preset list on exit. */
721 #ifdef FM_RECORD_DBLPRE
722 if (button
!= ACTION_NONE
)
726 #if CONFIG_CODEC != SWCODEC
732 /* Only display the peak meter when not recording */
733 #if CONFIG_CODEC != SWCODEC
734 if(TIME_AFTER(current_tick
, timeout
))
736 timeout
= current_tick
+ HZ
;
739 #endif /* CONFIG_CODEC == SWCODEC */
741 /* keep "mono" from always being displayed when paused */
742 if (radio_status
!= FMRADIO_PAUSED
)
744 stereo
= tuner_get(RADIO_STEREO
) &&
745 !global_settings
.fm_force_mono
;
747 if(stereo
!= last_stereo
)
749 update_type
= SKIN_REFRESH_ALL
;
750 last_stereo
= stereo
;
755 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
756 seconds
= audio_recorded_time() / HZ
;
757 if (update_type
|| seconds
> last_seconds
)
759 last_seconds
= seconds
;
765 skin_update(FM_SCREEN
, i
, update_type
);
766 if (update_type
== (int)SKIN_REFRESH_ALL
)
767 skin_request_full_update(CUSTOM_STATUSBAR
);
772 if (global_settings
.talk_file
&& talk
773 && radio_status
== FMRADIO_PAUSED
)
776 bool enqueue
= false;
777 if (radio_mode
== RADIO_SCAN_MODE
)
779 talk_value_decimal(curr_freq
, UNIT_INT
, 6, enqueue
);
782 if (radio_current_preset() >= 0)
783 preset_talk(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
787 #if CONFIG_CODEC != SWCODEC
788 if(audio_status() & AUDIO_STATUS_ERROR
)
794 #ifndef HAVE_NOISY_IDLE_MODE
795 if (TIME_AFTER(current_tick
, button_timeout
))
803 #if CONFIG_CODEC != SWCODEC
804 if(audio_status() & AUDIO_STATUS_ERROR
)
806 splash(0, str(LANG_DISK_FULL
));
811 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
812 if(button
== ACTION_FM_STOP
)
817 audio_init_playback();
818 #endif /* CONFIG_CODEC != SWCODEC */
820 sound_settings_apply();
821 #endif /* SIMULATOR */
825 /* Catch FMRADIO_PLAYING status for the sim. */
827 #if CONFIG_CODEC != SWCODEC
828 /* Enable the Left and right A/D Converter */
829 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
830 sound_default(SOUND_RIGHT_GAIN
),
832 mas_codec_writereg(6, 0x4000);
835 #endif /* SIMULATOR */
839 #if CONFIG_CODEC == SWCODEC
840 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
846 #ifndef HAVE_NOISY_IDLE_MODE
847 cpu_idle_mode(false);
849 fms_fix_displays(FMS_EXIT
);
850 pop_current_activity();
854 void toggle_mono_mode(bool mono
)
856 tuner_set(RADIO_FORCE_MONO
, mono
);
859 void set_radio_region(int region
)
861 #ifdef HAVE_RADIO_REGION
862 tuner_set(RADIO_REGION
, region
);
865 remember_frequency();