summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-05-03 02:40:09 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-05-03 02:40:09 +0000
commit331c7d9255e7873d3583aceea6bd00c7360f2366 (patch)
treed0dfb9e1eb62e8e96ef14e01b013179118c6c6f1
parent86704740792ae81add713f4f4b619c57fee79e47 (diff)
Finally, FM radio support on the FM Recorder
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3640 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/main_menu.c6
-rw-r--r--apps/recorder/radio.c189
-rw-r--r--apps/recorder/radio.h26
-rw-r--r--firmware/drivers/fmradio.c133
-rw-r--r--firmware/export/config-fmrecorder.h4
-rw-r--r--firmware/export/fmradio.h25
6 files changed, 383 insertions, 0 deletions
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 <stdio.h>
+#include <stdbool.h>
+#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