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 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
197 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
199 if(radio_status
== FMRADIO_OFF
)
201 #ifdef HAVE_RADIO_REGION
202 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
204 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
207 tuner_set(RADIO_FREQUENCY
, curr_freq
);
209 #ifdef HAVE_RADIO_MUTE_TIMEOUT
211 unsigned long mute_timeout
= current_tick
+ HZ
;
212 if (radio_status
!= FMRADIO_OFF
)
218 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
220 if(TIME_AFTER(current_tick
, mute_timeout
))
227 /* keep radio from sounding initially */
229 tuner_set(RADIO_MUTE
, 0);
231 radio_status
= FMRADIO_PLAYING
;
234 void radio_pause(void)
236 if(radio_status
== FMRADIO_PAUSED
)
239 if(radio_status
== FMRADIO_OFF
)
241 radio_status
|= FMRADIO_START_PAUSED
;
245 tuner_set(RADIO_MUTE
, 1);
247 radio_status
= FMRADIO_PAUSED
;
250 static void radio_off(void)
252 tuner_set(RADIO_MUTE
, 1);
253 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
254 radio_status
= FMRADIO_OFF
;
257 void radio_stop(void)
259 if(radio_status
== FMRADIO_OFF
)
265 bool radio_hardware_present(void)
267 return tuner_get(RADIO_PRESENT
);
270 /* Keep freq on the grid for the current region */
271 int snap_freq_to_grid(int freq
)
273 const struct fm_region_data
* const fmr
=
274 &fm_region_data
[global_settings
.fm_region
];
276 /* Range clamp if out of range or just round to nearest */
277 if (freq
< fmr
->freq_min
)
278 freq
= fmr
->freq_min
;
279 else if (freq
> fmr
->freq_max
)
280 freq
= fmr
->freq_max
;
282 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
283 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
288 void remember_frequency(void)
290 const struct fm_region_data
* const fmr
=
291 &fm_region_data
[global_settings
.fm_region
];
292 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
297 /* Step to the next or previous frequency */
298 static int step_freq(int freq
, int direction
)
300 const struct fm_region_data
* const fmr
=
301 &fm_region_data
[global_settings
.fm_region
];
303 freq
+= direction
*fmr
->freq_step
;
305 /* Wrap first or snapping to grid will not let us on the band extremes */
306 if (freq
> fmr
->freq_max
)
307 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
308 else if (freq
< fmr
->freq_min
)
309 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
311 freq
= snap_freq_to_grid(freq
);
316 /* Step to the next or previous station */
317 void next_station(int direction
)
319 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
321 preset_next(direction
);
325 curr_freq
= step_freq(curr_freq
, direction
);
327 if (radio_status
== FMRADIO_PLAYING
)
328 tuner_set(RADIO_MUTE
, 1);
330 tuner_set(RADIO_FREQUENCY
, curr_freq
);
332 if (radio_status
== FMRADIO_PLAYING
)
333 tuner_set(RADIO_MUTE
, 0);
335 preset_set_current(preset_find(curr_freq
));
336 remember_frequency();
339 /* Ends an in-progress search */
340 static void end_search(void)
342 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
343 tuner_set(RADIO_MUTE
, 0);
347 void radio_screen(void)
351 bool stereo
= false, last_stereo
= false;
353 bool screen_freeze
= false;
354 bool keep_playing
= false;
356 #ifdef FM_RECORD_DBLPRE
357 int lastbutton
= BUTTON_NONE
;
358 unsigned long rec_lastclick
= 0;
360 #if CONFIG_CODEC != SWCODEC
361 int timeout
= current_tick
+ HZ
/10;
362 #if !defined(SIMULATOR)
363 unsigned int last_seconds
= 0;
364 unsigned int seconds
= 0;
365 struct audio_recording_options rec_options
;
366 #endif /* SIMULATOR */
367 #endif /* CONFIG_CODEC != SWCODEC */
368 #ifndef HAVE_NOISY_IDLE_MODE
369 int button_timeout
= current_tick
+ (2*HZ
);
372 /* change status to "in screen" */
373 push_current_activity(ACTIVITY_FM
);
376 if(radio_preset_count() <= 0)
378 radio_load_presets(global_settings
.fmr_file
);
380 skin_get_global_state()->id3
= NULL
;
385 if(radio_status
== FMRADIO_OFF
)
390 #if CONFIG_CODEC != SWCODEC
391 rec_create_directory();
392 audio_init_recording();
394 sound_settings_apply();
395 /* Yes, we use the D/A for monitoring */
396 peak_meter_playback(true);
398 peak_meter_enable(true);
400 rec_init_recording_options(&rec_options
);
401 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
402 rec_set_recording_options(&rec_options
);
404 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
405 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
407 #endif /* CONFIG_CODEC != SWCODEC */
408 #endif /* ndef SIMULATOR */
410 #if CONFIG_CODEC == SWCODEC
411 /* This should be done before touching audio settings */
412 while (!pcm_is_initialized())
415 audio_set_input_source(AUDIO_SRC_FMRADIO
,
416 (radio_status
== FMRADIO_PAUSED
) ?
417 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
419 if (radio_status
== FMRADIO_OFF
)
423 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
426 fms_fix_displays(FMS_ENTER
);
428 skin_update(FM_SCREEN
, i
, SKIN_REFRESH_ALL
);
430 preset_set_current(preset_find(curr_freq
));
431 if(radio_current_preset() != -1)
432 radio_mode
= RADIO_PRESET_MODE
;
434 #ifndef HAVE_NOISY_IDLE_MODE
442 curr_freq
= step_freq(curr_freq
, search_dir
);
443 update_type
= SKIN_REFRESH_ALL
;
445 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
447 preset_set_current(preset_find(curr_freq
));
448 remember_frequency();
460 button
= fms_do_button_loop(update_type
>0);
462 #ifndef HAVE_NOISY_IDLE_MODE
463 if (button
!= ACTION_NONE
)
465 cpu_idle_mode(false);
466 button_timeout
= current_tick
+ (2*HZ
);
472 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
473 if(audio_status() == AUDIO_STATUS_RECORD
)
481 if(presets_have_changed())
483 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
489 update_type
= SKIN_REFRESH_NON_STATIC
;
493 case ACTION_FM_RECORD
:
494 #ifdef FM_RECORD_DBLPRE
495 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
500 if (current_tick
- rec_lastclick
> HZ
/2)
502 rec_lastclick
= current_tick
;
505 #endif /* FM_RECORD_DBLPRE */
507 if(audio_status() == AUDIO_STATUS_RECORD
)
509 rec_command(RECORDING_CMD_START_NEWFILE
);
510 update_type
= SKIN_REFRESH_ALL
;
514 rec_command(RECORDING_CMD_START
);
515 update_type
= SKIN_REFRESH_ALL
;
517 #if CONFIG_CODEC != SWCODEC
520 #endif /* SIMULATOR */
522 #endif /* #ifdef FM_RECORD */
525 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
526 if(audio_status() == AUDIO_STATUS_RECORD
)
531 if(presets_have_changed())
533 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
541 case ACTION_STD_PREV
:
542 case ACTION_STD_NEXT
:
543 next_station(button
== ACTION_STD_PREV
? -1 : 1);
545 update_type
= SKIN_REFRESH_ALL
;
549 case ACTION_STD_PREVREPEAT
:
550 case ACTION_STD_NEXTREPEAT
:
552 int dir
= search_dir
;
553 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
554 if (radio_mode
!= RADIO_SCAN_MODE
)
556 preset_next(search_dir
);
562 /* Starting auto scan */
563 tuner_set(RADIO_MUTE
, 1);
565 update_type
= SKIN_REFRESH_ALL
;
569 case ACTION_SETTINGS_INC
:
570 case ACTION_SETTINGS_INCREPEAT
:
571 global_settings
.volume
++;
573 update_type
= SKIN_REFRESH_NON_STATIC
;
576 case ACTION_SETTINGS_DEC
:
577 case ACTION_SETTINGS_DECREPEAT
:
578 global_settings
.volume
--;
580 update_type
= SKIN_REFRESH_NON_STATIC
;
584 if (radio_status
== FMRADIO_PLAYING
)
589 update_type
= SKIN_REFRESH_NON_STATIC
;
595 fms_fix_displays(FMS_EXIT
);
596 do_menu(&radio_settings_menu
, NULL
, NULL
, false);
597 preset_set_current(preset_find(curr_freq
));
598 fms_fix_displays(FMS_ENTER
);
599 update_type
= SKIN_REFRESH_ALL
;
603 case ACTION_FM_PRESET
:
604 if(radio_preset_count() < 1)
606 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
607 update_type
= SKIN_REFRESH_ALL
;
610 fms_fix_displays(FMS_EXIT
);
611 handle_radio_presets();
612 fms_fix_displays(FMS_ENTER
);
613 update_type
= SKIN_REFRESH_ALL
;
615 #endif /* FM_PRESET */
618 case ACTION_FM_FREEZE
:
621 splash(HZ
, str(LANG_FM_FREEZE
));
622 screen_freeze
= true;
626 update_type
= SKIN_REFRESH_ALL
;
627 screen_freeze
= false;
630 #endif /* FM_FREEZE */
632 case SYS_USB_CONNECTED
:
633 #if CONFIG_CODEC != SWCODEC
634 /* Only accept USB connection when not recording */
635 if(audio_status() != AUDIO_STATUS_RECORD
)
638 default_event_handler(SYS_USB_CONNECTED
);
639 screen_freeze
= true; /* Cosmetic: makes sure the
640 radio screen doesn't redraw */
647 if(radio_mode
== RADIO_SCAN_MODE
)
649 /* Force scan mode if there are no presets. */
650 if(radio_preset_count() > 0)
651 radio_mode
= RADIO_PRESET_MODE
;
654 radio_mode
= RADIO_SCAN_MODE
;
655 update_type
= SKIN_REFRESH_ALL
;
656 cond_talk_ids_fq(radio_mode
?
657 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
662 #ifdef FM_NEXT_PRESET
663 case ACTION_FM_NEXT_PRESET
:
666 update_type
= SKIN_REFRESH_ALL
;
671 #ifdef FM_PREV_PRESET
672 case ACTION_FM_PREV_PRESET
:
675 update_type
= SKIN_REFRESH_ALL
;
680 update_type
= SKIN_REFRESH_NON_STATIC
;
684 default_event_handler(button
);
686 if (tuner_get(RADIO_EVENT
))
687 update_type
= SKIN_REFRESH_ALL
;
689 if (!tuner_get(RADIO_PRESENT
))
691 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
692 if(audio_status() == AUDIO_STATUS_RECORD
)
695 keep_playing
= false;
697 if(presets_have_changed())
699 if(yesno_pop(ID2P(LANG_SAVE_CHANGES
)))
701 radio_save_presets();
705 /* Clear the preset list on exit. */
711 #ifdef FM_RECORD_DBLPRE
712 if (button
!= ACTION_NONE
)
716 #if CONFIG_CODEC != SWCODEC
722 /* Only display the peak meter when not recording */
723 #if CONFIG_CODEC != SWCODEC
724 if(TIME_AFTER(current_tick
, timeout
))
726 timeout
= current_tick
+ HZ
;
729 #endif /* CONFIG_CODEC == SWCODEC */
731 /* keep "mono" from always being displayed when paused */
732 if (radio_status
!= FMRADIO_PAUSED
)
734 stereo
= tuner_get(RADIO_STEREO
) &&
735 !global_settings
.fm_force_mono
;
737 if(stereo
!= last_stereo
)
739 update_type
= SKIN_REFRESH_ALL
;
740 last_stereo
= stereo
;
745 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
746 seconds
= audio_recorded_time() / HZ
;
747 if (update_type
|| seconds
> last_seconds
)
749 last_seconds
= seconds
;
755 skin_update(FM_SCREEN
, i
, update_type
);
756 if (update_type
== (int)SKIN_REFRESH_ALL
)
757 skin_request_full_update(CUSTOM_STATUSBAR
);
762 if (global_settings
.talk_file
&& talk
763 && radio_status
== FMRADIO_PAUSED
)
766 bool enqueue
= false;
767 if (radio_mode
== RADIO_SCAN_MODE
)
769 talk_value_decimal(curr_freq
, UNIT_INT
, 6, enqueue
);
772 if (radio_current_preset() >= 0)
773 preset_talk(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
777 #if CONFIG_CODEC != SWCODEC
778 if(audio_status() & AUDIO_STATUS_ERROR
)
784 #ifndef HAVE_NOISY_IDLE_MODE
785 if (TIME_AFTER(current_tick
, button_timeout
))
793 #if CONFIG_CODEC != SWCODEC
794 if(audio_status() & AUDIO_STATUS_ERROR
)
796 splash(0, str(LANG_DISK_FULL
));
801 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
802 if(button
== ACTION_FM_STOP
)
807 audio_init_playback();
808 #endif /* CONFIG_CODEC != SWCODEC */
810 sound_settings_apply();
811 #endif /* SIMULATOR */
815 /* Catch FMRADIO_PLAYING status for the sim. */
817 #if CONFIG_CODEC != SWCODEC
818 /* Enable the Left and right A/D Converter */
819 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
820 sound_default(SOUND_RIGHT_GAIN
),
822 mas_codec_writereg(6, 0x4000);
825 #endif /* SIMULATOR */
829 #if CONFIG_CODEC == SWCODEC
830 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
836 #ifndef HAVE_NOISY_IDLE_MODE
837 cpu_idle_mode(false);
839 fms_fix_displays(FMS_EXIT
);
840 pop_current_activity();
844 void toggle_mono_mode(bool mono
)
846 tuner_set(RADIO_FORCE_MONO
, mono
);
849 void set_radio_region(int region
)
851 #ifdef HAVE_RADIO_REGION
852 tuner_set(RADIO_REGION
, region
);
855 remember_frequency();