1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * tuner for the ipod fm remote and other ipod remote tuners
11 * Copyright (C) 2009 Laurent Gautier
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
29 #include "tuner.h" /* tuner abstraction interface */
34 static bool powered
= false;
36 static unsigned char tuner_param
= 0x00, old_tuner_param
= 0xFF;
37 /* temp var for tests to avoid looping execution in submenus settings*/
38 static int mono_mode
= -1, old_region
= -1;
40 int radio_present
= 0;
42 static int tuner_frequency
= 0;
43 static int tuner_signal_power
= 0;
44 static bool radio_tuned
= false;
45 static bool rds_event
= false;
47 static char rds_radioname
[9];
48 static char rds_radioinfo
[65];
50 static void rmt_tuner_signal_power(unsigned char value
)
52 tuner_signal_power
= (int)(value
);
55 void rmt_tuner_freq(unsigned int len
, const unsigned char *buf
)
57 /* length currently unused */
60 unsigned int khz
= (buf
[2] << 24) | (buf
[3] << 16) |
61 (buf
[4] << 8) | buf
[5];
62 tuner_frequency
= khz
*1000 ;
64 rmt_tuner_signal_power(buf
[6]);
67 static void rmt_tuner_set_freq(int curr_freq
)
69 if (curr_freq
!= tuner_frequency
)
72 tuner_signal_power
= 0;
73 /* clear rds name and info */
74 memset(rds_radioname
,' ',sizeof(rds_radioname
));
75 memset(rds_radioinfo
,' ',sizeof(rds_radioinfo
));
76 /* ex: 00 01 63 14 = 90.9MHz */
77 unsigned char data
[] = {0x07, 0x0B, 0x00, 0x01, 0x63, 0x14};
81 unsigned int khz
= curr_freq
/ 1000;
82 data
[2] = (khz
>> 24) & 0xFF;
83 data
[3] = (khz
>> 16) & 0xFF;
84 data
[4] = (khz
>> 8) & 0xFF;
85 data
[5] = (khz
>> 0) & 0xFF;
86 iap_send_pkt(data
, sizeof(data
));
91 static void rmt_tuner_sleep(int state
)
96 old_tuner_param
= 0xFF;
103 const unsigned char data
[] = {0x07, 0x05, 0x01};
104 iap_send_pkt(data
, sizeof(data
));
106 const unsigned char data1
[] = {0x07, 0x24, 0x06 };
107 iap_send_pkt(data1
, sizeof(data1
));
109 unsigned char data2
[] = {0x03, 0x09, 0x04, 0x00, 0x00 };
110 data2
[4] = (char)((global_settings
.volume
+58) * 4);
111 iap_send_pkt(data2
, sizeof(data2
));
113 const unsigned char data3
[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 };
114 iap_send_pkt(data3
, sizeof(data3
));
119 const unsigned char data
[] = {0x07, 0x24, 0x00};
120 iap_send_pkt(data
, sizeof(data
));
122 const unsigned char data1
[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 };
123 iap_send_pkt(data1
, sizeof(data1
));
125 const unsigned char data2
[] = {0x07, 0x05, 0x00};
126 iap_send_pkt(data2
, sizeof(data2
));
130 static void rmt_tuner_scan(int param
)
132 const unsigned char data
[] = {0x07, 0x11, 0x08}; /* RSSI level */
133 unsigned char updown
= 0x00;
135 iap_send_pkt(data
, sizeof(data
));
139 updown
= 0x07; /* scan up */
141 else if (param
== -1)
143 updown
= 0x08; /* scan down */
145 else if (param
== 10)
147 updown
= 0x01; /* scan up starting from beginning of the band */
149 unsigned char data1
[] = {0x07, 0x12, updown
};
150 iap_send_pkt(data1
, sizeof(data1
));
153 #if 0 /* function is not used */
154 static void rmt_tuner_mute(int value
)
156 /* mute flag off (play) */
157 unsigned char data
[] = {0x03, 0x09, 0x03, 0x01};
160 /* mute flag on (pause) */
163 iap_send_pkt(data
, sizeof(data
));
167 static void rmt_tuner_region(int region
)
169 if (region
!= old_region
)
171 const struct fm_region_data
*rd
= &fm_region_data
[region
];
172 unsigned char data
[] = {0x07, 0x08, 0x00};
173 if (rd
->freq_min
== 76000000)
175 data
[2] = 0x02; /* japan band */
179 data
[2] = 0x01; /* us eur band */
181 iap_send_pkt(data
, sizeof(data
));
187 /* set stereo/mono, deemphasis, delta freq... */
188 static void rmt_tuner_set_param(unsigned char tuner_param
)
190 if(tuner_param
!= old_tuner_param
)
192 unsigned char data
[] = {0x07, 0x0E, 0x00};
194 data
[2] = tuner_param
;
195 iap_send_pkt(data
, sizeof(data
));
196 old_tuner_param
= tuner_param
;
200 static void set_deltafreq(int delta
)
227 static void set_deemphasis(int deemphasis
)
245 static void set_mono(int value
)
249 if (value
!= mono_mode
)
254 rmt_tuner_set_param(tuner_param
);
260 static bool reply_timeout(void)
271 while((ipod_rmt_tuner_get(RADIO_TUNED
) == 0) && (timeout
< TIMEOUT_VALUE
));
273 return (timeout
>= TIMEOUT_VALUE
);
276 void rmt_tuner_rds_data(unsigned int len
, const unsigned char *buf
)
280 strlcpy(rds_radioname
,buf
+4,8);
282 else if(buf
[2] == 0x04)
284 strlcpy(rds_radioinfo
,buf
+4,len
-4);
289 /* tuner abstraction layer: set something to the tuner */
290 int ipod_rmt_tuner_set(int setting
, int value
)
296 rmt_tuner_sleep(value
);
305 case RADIO_FREQUENCY
:
307 rmt_tuner_set_freq(value
);
313 case RADIO_SCAN_FREQUENCY
:
315 const struct fm_region_data
* const fmr
=
316 &fm_region_data
[global_settings
.fm_region
];
318 /* case: scan for presets, back to beginning of the band */
319 if (radio_tuned
&& (value
== fmr
->freq_min
))
321 tuner_set(RADIO_FREQUENCY
,value
);
324 /* scan through frequencies */
327 if ((tuner_frequency
<= fmr
->freq_min
)
328 && (tuner_frequency
>= fmr
->freq_max
))
330 tuner_set(RADIO_FREQUENCY
,value
);
333 if(value
< tuner_frequency
)
342 tuner_set(RADIO_FREQUENCY
,value
);
344 if (reply_timeout() == true)
350 if (tuner_frequency
== value
)
364 /* mute flag sent to accessory */
365 /* rmt_tuner_mute(value); */
371 const struct fm_region_data
*rd
= &fm_region_data
[value
];
372 int band
= (rd
->freq_min
== 76000000) ? 2 : 0;
373 int spacing
= (100000 / rd
->freq_step
);
374 int deemphasis
= (rd
->deemphasis
== 50) ? 1 : 0;
376 rmt_tuner_region(band
);
377 set_deltafreq(spacing
);
378 set_deemphasis(deemphasis
);
379 rmt_tuner_set_param(tuner_param
);
383 case RADIO_FORCE_MONO
:
395 /* tuner abstraction layer: read something from the tuner */
396 int ipod_rmt_tuner_get(int setting
)
398 int val
= -1; /* default for unsupported query */
406 /* if accessory disconnected */
407 if(adc_read(ADC_ACCESSORY
) >= 10)
415 /* radio tuned: yes no */
422 /* radio is always stereo */
423 /* we can't know when it's in mono mode, depending of signal quality */
424 /* except if it is forced in mono mode */
440 char* ipod_get_rds_info(int setting
)
447 text
= rds_radioname
;
451 text
= rds_radioinfo
;
457 bool tuner_power(bool status
)
459 bool oldstatus
= powered
;