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(const unsigned char *serbuf
)
57 unsigned int khz
= (serbuf
[3] << 24) | (serbuf
[4] << 16) |
58 (serbuf
[5] << 8) | serbuf
[6];
59 tuner_frequency
= khz
*1000 ;
61 rmt_tuner_signal_power(serbuf
[7]);
64 static void rmt_tuner_set_freq(int curr_freq
)
66 if (curr_freq
!= tuner_frequency
)
69 tuner_signal_power
= 0;
70 /* clear rds name and info */
71 memset(rds_radioname
,' ',sizeof(rds_radioname
));
72 memset(rds_radioinfo
,' ',sizeof(rds_radioinfo
));
73 /* ex: 00 01 63 14 = 90.9MHz */
74 unsigned char data
[] = {0x07, 0x0B, 0x00, 0x01, 0x63, 0x14};
78 unsigned int khz
= curr_freq
/ 1000;
79 data
[2] = (khz
>> 24) & 0xFF;
80 data
[3] = (khz
>> 16) & 0xFF;
81 data
[4] = (khz
>> 8) & 0xFF;
82 data
[5] = (khz
>> 0) & 0xFF;
83 iap_send_pkt(data
, sizeof(data
));
88 static void rmt_tuner_sleep(int state
)
93 old_tuner_param
= 0xFF;
100 const unsigned char data
[] = {0x07, 0x05, 0x01};
101 iap_send_pkt(data
, sizeof(data
));
103 const unsigned char data1
[] = {0x07, 0x24, 0x06 };
104 iap_send_pkt(data1
, sizeof(data1
));
106 unsigned char data2
[] = {0x03, 0x09, 0x04, 0x00, 0x00 };
107 data2
[4] = (char)((global_settings
.volume
+58) * 4);
108 iap_send_pkt(data2
, sizeof(data2
));
110 const unsigned char data3
[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 };
111 iap_send_pkt(data3
, sizeof(data3
));
116 const unsigned char data
[] = {0x07, 0x24, 0x00};
117 iap_send_pkt(data
, sizeof(data
));
119 const unsigned char data1
[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 };
120 iap_send_pkt(data1
, sizeof(data1
));
122 const unsigned char data2
[] = {0x07, 0x05, 0x00};
123 iap_send_pkt(data2
, sizeof(data2
));
127 static void rmt_tuner_scan(int param
)
129 const unsigned char data
[] = {0x07, 0x11, 0x08}; /* RSSI level */
130 unsigned char updown
= 0x00;
132 iap_send_pkt(data
, sizeof(data
));
136 updown
= 0x07; /* scan up */
138 else if (param
== -1)
140 updown
= 0x08; /* scan down */
142 else if (param
== 10)
144 updown
= 0x01; /* scan up starting from beginning of the band */
146 unsigned char data1
[] = {0x07, 0x12, updown
};
147 iap_send_pkt(data1
, sizeof(data1
));
150 #if 0 /* function is not used */
151 static void rmt_tuner_mute(int value
)
153 /* mute flag off (play) */
154 unsigned char data
[] = {0x03, 0x09, 0x03, 0x01};
157 /* mute flag on (pause) */
160 iap_send_pkt(data
, sizeof(data
));
164 static void rmt_tuner_region(int region
)
166 if (region
!= old_region
)
168 const struct fm_region_data
*rd
= &fm_region_data
[region
];
169 unsigned char data
[] = {0x07, 0x08, 0x00};
170 if (rd
->freq_min
== 76000000)
172 data
[2] = 0x02; /* japan band */
176 data
[2] = 0x01; /* us eur band */
178 iap_send_pkt(data
, sizeof(data
));
184 /* set stereo/mono, deemphasis, delta freq... */
185 static void rmt_tuner_set_param(unsigned char tuner_param
)
187 if(tuner_param
!= old_tuner_param
)
189 unsigned char data
[] = {0x07, 0x0E, 0x00};
191 data
[2] = tuner_param
;
192 iap_send_pkt(data
, sizeof(data
));
193 old_tuner_param
= tuner_param
;
197 static void set_deltafreq(int delta
)
224 static void set_deemphasis(int deemphasis
)
242 static void set_mono(int value
)
246 if (value
!= mono_mode
)
251 rmt_tuner_set_param(tuner_param
);
257 static bool reply_timeout(void)
268 while((ipod_rmt_tuner_get(RADIO_TUNED
) == 0) && (timeout
< TIMEOUT_VALUE
));
270 return (timeout
>= TIMEOUT_VALUE
);
273 void rmt_tuner_rds_data(const unsigned char *serbuf
)
275 if (serbuf
[3] == 0x1E)
277 strlcpy(rds_radioname
,serbuf
+5,8);
279 else if(serbuf
[3] == 0x04)
281 strlcpy(rds_radioinfo
,serbuf
+5,(serbuf
[0]-4));
286 /* tuner abstraction layer: set something to the tuner */
287 int ipod_rmt_tuner_set(int setting
, int value
)
293 rmt_tuner_sleep(value
);
302 case RADIO_FREQUENCY
:
304 rmt_tuner_set_freq(value
);
310 case RADIO_SCAN_FREQUENCY
:
312 const struct fm_region_data
* const fmr
=
313 &fm_region_data
[global_settings
.fm_region
];
315 /* case: scan for presets, back to beginning of the band */
316 if (radio_tuned
&& (value
== fmr
->freq_min
))
318 tuner_set(RADIO_FREQUENCY
,value
);
321 /* scan through frequencies */
324 if ((tuner_frequency
<= fmr
->freq_min
)
325 && (tuner_frequency
>= fmr
->freq_max
))
327 tuner_set(RADIO_FREQUENCY
,value
);
330 if(value
< tuner_frequency
)
339 tuner_set(RADIO_FREQUENCY
,value
);
341 if (reply_timeout() == true)
347 if (tuner_frequency
== value
)
361 /* mute flag sent to accessory */
362 /* rmt_tuner_mute(value); */
368 const struct fm_region_data
*rd
= &fm_region_data
[value
];
369 int band
= (rd
->freq_min
== 76000000) ? 2 : 0;
370 int spacing
= (100000 / rd
->freq_step
);
371 int deemphasis
= (rd
->deemphasis
== 50) ? 1 : 0;
373 rmt_tuner_region(band
);
374 set_deltafreq(spacing
);
375 set_deemphasis(deemphasis
);
376 rmt_tuner_set_param(tuner_param
);
380 case RADIO_FORCE_MONO
:
392 /* tuner abstraction layer: read something from the tuner */
393 int ipod_rmt_tuner_get(int setting
)
395 int val
= -1; /* default for unsupported query */
403 /* if accessory disconnected */
404 if(adc_read(ADC_ACCESSORY
) >= 10)
412 /* radio tuned: yes no */
419 /* radio is always stereo */
420 /* we can't know when it's in mono mode, depending of signal quality */
421 /* except if it is forced in mono mode */
437 char* ipod_get_rds_info(int setting
)
444 text
= rds_radioname
;
448 text
= rds_radioinfo
;
454 bool tuner_power(bool status
)
456 bool oldstatus
= powered
;