From 331c7d9255e7873d3583aceea6bd00c7360f2366 Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Sat, 3 May 2003 02:40:09 +0000 Subject: Finally, FM radio support on the FM Recorder git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3640 a1c6a512-1295-4272-9138-f99709370657 --- apps/main_menu.c | 6 ++ apps/recorder/radio.c | 189 ++++++++++++++++++++++++++++++++++++ apps/recorder/radio.h | 26 +++++ firmware/drivers/fmradio.c | 133 +++++++++++++++++++++++++ firmware/export/config-fmrecorder.h | 4 + firmware/export/fmradio.h | 25 +++++ 6 files changed, 383 insertions(+) create mode 100644 apps/recorder/radio.c create mode 100644 apps/recorder/radio.h create mode 100644 firmware/drivers/fmradio.c create mode 100644 firmware/export/fmradio.h diff --git a/apps/main_menu.c b/apps/main_menu.c index 9f4aa8f812..b455e074a2 100644 --- a/apps/main_menu.c +++ b/apps/main_menu.c @@ -41,6 +41,9 @@ #include "fat.h" #include "sleeptimer.h" #include "wps.h" +#ifdef HAVE_FMRADIO +#include "radio.h" +#endif #include "lang.h" @@ -258,6 +261,9 @@ bool main_menu(void) struct menu_items items[] = { { str(LANG_SOUND_SETTINGS), sound_menu }, { str(LANG_GENERAL_SETTINGS), settings_menu }, +#ifdef HAVE_FMRADIO + { "FM Radio", radio_screen }, +#endif #ifdef HAVE_MAS3587F { str(LANG_RECORDING), recording_screen }, { str(LANG_RECORDING_SETTINGS), recording_menu }, diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c new file mode 100644 index 0000000000..7206fe08f3 --- /dev/null +++ b/apps/recorder/radio.c @@ -0,0 +1,189 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2003 Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include +#include +#include "lcd.h" +#include "mas.h" +#include "settings.h" +#include "button.h" +#include "fmradio.h" +#include "status.h" +#include "kernel.h" +#include "mpeg.h" + +#ifdef HAVE_FMRADIO + +#define MAX_FREQ (110000000) +#define MIN_FREQ (80000000) +#define FREQ_STEP 100000 + +static int curr_freq = 99400000; +static int pll_cnt; + +void fm_set_frequency(int freq) +{ + /* We add the standard Intermediate Frequency 10.7MHz before calculating + ** the divisor + ** The reference frequency is set to 50kHz, and the VCO output is prescaled + ** by 2. + */ + + pll_cnt = (freq + 10700000) / 50000 / 2; + + /* 0x100000 == FM mode + ** 0x000002 == Microprocessor controlled Mute + */ + fmradio_set(1, 0x100002 | pll_cnt << 3); +} + +bool radio_screen(void) +{ + char buf[128]; + bool done = false; + int button; + int val; + int freq; + int i_freq; + bool lock; + bool stereo; + int search_dir = 0; + + lcd_clear_display(); + lcd_setmargins(0, 8); + status_draw(false); + + /* Enable the Left and right A/D Converter */ + mas_codec_writereg(0x0, 0xccc7); + + mas_codec_writereg(6, 0x4000); + + fmradio_set(2, 0x108884); /* 50kHz, 7.2MHz crystal */ + fm_set_frequency(curr_freq); + + while(!done) + { + if(search_dir) + { + curr_freq += search_dir * FREQ_STEP; + if(curr_freq < MIN_FREQ) + curr_freq = MAX_FREQ; + if(curr_freq > MAX_FREQ) + curr_freq = MIN_FREQ; + + /* Tune in and delay */ + fm_set_frequency(curr_freq); + sleep(10); + + /* Start IF measurement */ + fmradio_set(1, 0x100006 | pll_cnt << 3); + sleep(10); + + /* Now check how close to the IF frequency we are */ + val = fmradio_read(3); + i_freq = (val & 0x7ffff) / 80; + lcd_puts(0, 5, "Debug data:"); + snprintf(buf, 128, "IF: %d.%dMHz", + i_freq / 100, (i_freq % 100) / 10); + lcd_puts(0, 6, buf); + + /* Stop searching if the IF frequency is close to 10.7MHz */ + if(i_freq > 1065 && i_freq < 1075) + search_dir = 0; + } + + freq = curr_freq / 100000; + snprintf(buf, 128, "Freq: %d.%dMHz", freq / 10, freq % 10); + lcd_puts(0, 1, buf); + + val = fmradio_read(3); + stereo = (val & 0x100000)?true:false; + lock = (val & 0x80000)?true:false; + snprintf(buf, 128, "Mode: %s", stereo?"Stereo":"Mono"); + lcd_puts(0, 2, buf); + + lcd_update(); + + if(search_dir) + button = button_get(false); + else + button = button_get_w_tmo(HZ/2); + switch(button) + { + case BUTTON_OFF | BUTTON_REL: + done = true; + break; + + case BUTTON_LEFT: + curr_freq -= 100000; + if(curr_freq < MIN_FREQ) + curr_freq = MIN_FREQ; + + fm_set_frequency(curr_freq); + search_dir = 0; + break; + + case BUTTON_RIGHT: + curr_freq += 100000; + if(curr_freq > MAX_FREQ) + curr_freq = MAX_FREQ; + + fm_set_frequency(curr_freq); + search_dir = 0; + break; + + case BUTTON_LEFT | BUTTON_REPEAT: + search_dir = -1; + break; + + case BUTTON_RIGHT | BUTTON_REPEAT: + search_dir = 1; + break; + + case BUTTON_UP: + case BUTTON_UP | BUTTON_REPEAT: + case BUTTON_RC_VOL_UP: + global_settings.volume++; + if(global_settings.volume > mpeg_sound_max(SOUND_VOLUME)) + global_settings.volume = mpeg_sound_max(SOUND_VOLUME); + mpeg_sound_set(SOUND_VOLUME, global_settings.volume); + status_draw(false); + settings_save(); + break; + + case BUTTON_DOWN: + case BUTTON_DOWN | BUTTON_REPEAT: + case BUTTON_RC_VOL_DOWN: + global_settings.volume--; + if(global_settings.volume < mpeg_sound_min(SOUND_VOLUME)) + global_settings.volume = mpeg_sound_min(SOUND_VOLUME); + mpeg_sound_set(SOUND_VOLUME, global_settings.volume); + status_draw(false); + settings_save(); + break; + + case BUTTON_NONE: + status_draw(true); + break; + } + } + return false; +} +#endif diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h new file mode 100644 index 0000000000..dafa46d90d --- /dev/null +++ b/apps/recorder/radio.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2003 Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef RADIO_H +#define RADIO_H + +#ifdef HAVE_FMRADIO +bool radio_screen(void); +#endif + +#endif diff --git a/firmware/drivers/fmradio.c b/firmware/drivers/fmradio.c new file mode 100644 index 0000000000..0d947f4480 --- /dev/null +++ b/firmware/drivers/fmradio.c @@ -0,0 +1,133 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "lcd.h" +#include "sh7034.h" +#include "kernel.h" +#include "thread.h" +#include "debug.h" + +#ifdef HAVE_FMRADIO + +/* Signals: + DI (Data In) - PB0 (doubles as data pin for the LCD) + CL (Clock) - PB1 (doubles as clock for the LCD) + CE (Chip Enable) - PB3 (also chip select for the LCD, but active low) + DO (Data Out) - PB4 +*/ + +#define PB0 0x0001 +#define PB1 0x0002 +#define PB3 0x0008 +#define PB4 0x0010 + +/* cute little functions */ +#define CE_LO (PBDR &= ~PB3) +#define CE_HI (PBDR |= PB3) +#define CL_LO (PBDR &= ~PB1) +#define CL_HI (PBDR |= PB1) +#define DO (PBDR & PB4) +#define DI_LO (PBDR &= ~PB0) +#define DI_HI (PBDR |= PB0) + +#define START (PBDR |= (PB3 | PB1)) + +/* delay loop */ +#define DELAY do { int _x; for(_x=0;_x<10;_x++);} while (0) + +static struct mutex fmradio_mtx; + +void fmradio_begin(void) +{ + mutex_lock(&fmradio_mtx); +} + +void fmradio_end(void) +{ + mutex_unlock(&fmradio_mtx); +} + +int fmradio_read(int addr) +{ + int i; + int data = 0; + + START; + + /* First address bit */ + CL_LO; + if(addr & 2) + DI_HI; + else + DI_LO; + DELAY; + CL_HI; + DELAY; + + /* Second address bit */ + CL_LO; + if(addr & 1) + DI_HI; + else + DI_LO; + DELAY; + CL_HI; + DELAY; + + for(i = 0; i < 21;i++) + { + CL_LO; + DELAY; + data <<= 1; + data |= (DO)?1:0; + CL_HI; + DELAY; + } + + CE_LO; + + return data; +} + +void fmradio_set(int addr, int data) +{ + int i; + + /* Include the address in the data */ + data |= addr << 21; + + START; + + for(i = 0; i < 23;i++) + { + CL_LO; + DELAY; + if(data & (1 << 22)) + DI_HI; + else + DI_LO; + + data <<= 1; + CL_HI; + DELAY; + } + + CE_LO; +} + +#endif diff --git a/firmware/export/config-fmrecorder.h b/firmware/export/config-fmrecorder.h index 36b304c46d..63a6ece95b 100644 --- a/firmware/export/config-fmrecorder.h +++ b/firmware/export/config-fmrecorder.h @@ -39,3 +39,7 @@ /* FM recorders can wake up from RTC alarm */ #define HAVE_ALARM_MOD 1 + +/* Define this if you have an FM Radio */ +#define HAVE_FMRADIO 1 + diff --git a/firmware/export/fmradio.h b/firmware/export/fmradio.h new file mode 100644 index 0000000000..2877501361 --- /dev/null +++ b/firmware/export/fmradio.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef FMRADIO_H +#define FMRADIO_H + +extern int fmradio_read(int addr); +extern void fmradio_set(int addr, int data); + +#endif -- cgit v1.2.3