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 int mono_mode
= -1, old_region
= -1;
40 int radio_present
= 0;
41 int tuner_frequency
= 0;
42 int tuner_signal_power
= 0;
46 char rds_radioname
[9];
47 char rds_radioinfo
[65];
50 unsigned long int frequency_radio
;
51 char data_frequency
[4];
54 void rmt_tuner_freq(void)
57 tempdata
[0] = serbuf
[6];
58 tempdata
[1] = serbuf
[5];
59 tempdata
[2] = serbuf
[4];
60 tempdata
[3] = serbuf
[3];
62 memcpy(Frequency
.data_frequency
,tempdata
,4);
63 tuner_frequency
= (Frequency
.frequency_radio
*1000);
65 rmt_tuner_signal_power(serbuf
[7]);
68 void rmt_tuner_set_freq(int curr_freq
)
70 if (curr_freq
!= tuner_frequency
)
73 tuner_signal_power
= 0;
74 /* clear rds name and info */
75 memset(rds_radioname
,' ',sizeof(rds_radioname
));
76 memset(rds_radioinfo
,' ',sizeof(rds_radioinfo
));
77 /* ex: 00 01 63 14 = 90.9MHz */
78 unsigned char data
[] = {0x07, 0x0B, 0x00, 0x01, 0x63, 0x14};
82 curr_freq
= curr_freq
/ 1000;
85 Frequency
.frequency_radio
= curr_freq
;
86 tempdata
[0] = Frequency
.data_frequency
[3];
87 tempdata
[1] = Frequency
.data_frequency
[2];
88 tempdata
[2] = Frequency
.data_frequency
[1];
89 tempdata
[3] = Frequency
.data_frequency
[0];
91 memcpy(data
+2,tempdata
,4);
92 iap_send_pkt(data
, sizeof(data
));
97 void rmt_tuner_signal_power(unsigned char value
)
99 tuner_signal_power
= (int)(value
);
102 void rmt_tuner_sleep(int state
)
107 old_tuner_param
= 0xFF;
114 unsigned char data
[] = {0x07, 0x05, 0x01};
115 iap_send_pkt(data
, sizeof(data
));
117 unsigned char data1
[] = {0x07, 0x24, 0x06 };
118 iap_send_pkt(data1
, sizeof(data1
));
120 unsigned char data2
[] = {0x03, 0x09, 0x04, 0x00, 0x00 };
121 data2
[4] = (char)((global_settings
.volume
+58) * 4);
122 iap_send_pkt(data2
, sizeof(data2
));
124 unsigned char data3
[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 };
125 iap_send_pkt(data3
, sizeof(data3
));
130 unsigned char data
[] = {0x07, 0x24, 0x00};
131 iap_send_pkt(data
, sizeof(data
));
133 unsigned char data1
[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 };
134 iap_send_pkt(data1
, sizeof(data1
));
136 unsigned char data2
[] = {0x07, 0x05, 0x00};
137 iap_send_pkt(data2
, sizeof(data2
));
141 void rmt_tuner_scan(int param
)
143 unsigned char data
[] = {0x07, 0x11, 0x08}; /* RSSI level */
144 unsigned char updown
= 0x00;
146 iap_send_pkt(data
, sizeof(data
));
150 updown
= 0x07; /* scan up */
152 else if (param
== -1)
154 updown
= 0x08; /* scan down */
156 else if (param
== 10)
158 updown
= 0x01; /* scan up starting from beginning of the band */
160 unsigned char data1
[] = {0x07, 0x12, updown
};
161 iap_send_pkt(data1
, sizeof(data1
));
164 void rmt_tuner_mute(int value
)
166 /* mute flag off (play) */
167 unsigned char data
[] = {0x03, 0x09, 0x03, 0x01};
170 /* mute flag on (pause) */
173 iap_send_pkt(data
, sizeof(data
));
176 void rmt_tuner_region(int region
)
178 if (region
!= old_region
)
180 const struct fm_region_data
*rd
= &fm_region_data
[region
];
181 unsigned char data
[] = {0x07, 0x08, 0x00};
182 if (rd
->freq_min
== 76000000)
184 data
[2] = 0x02; /* japan band */
188 data
[2] = 0x01; /* us eur band */
190 iap_send_pkt(data
, sizeof(data
));
196 /* set stereo/mono, deemphasis, delta freq... */
197 void rmt_tuner_set_param(unsigned char tuner_param
)
199 if(tuner_param
!= old_tuner_param
)
201 unsigned char data
[] = {0x07, 0x0E, 0x00};
203 data
[2] = tuner_param
;
204 iap_send_pkt(data
, sizeof(data
));
205 old_tuner_param
= tuner_param
;
209 static void set_deltafreq(int delta
)
236 static void set_deemphasis(int deemphasis
)
254 static void set_mono(int value
)
258 if (value
!= mono_mode
)
263 rmt_tuner_set_param(tuner_param
);
269 static bool reply_timeout(void)
280 while((ipod_rmt_tuner_get(RADIO_TUNED
) == 0) && (timeout
< TIMEOUT_VALUE
));
282 if (timeout
>= TIMEOUT_VALUE
)
287 void rmt_tuner_rds_data(void)
289 if (serbuf
[3] == 0x1E)
291 strlcpy(rds_radioname
,serbuf
+5,8);
293 else if(serbuf
[3] == 0x04)
295 strlcpy(rds_radioinfo
,serbuf
+5,(serbuf
[0]-4));
300 /* tuner abstraction layer: set something to the tuner */
301 int ipod_rmt_tuner_set(int setting
, int value
)
307 rmt_tuner_sleep(value
);
316 case RADIO_FREQUENCY
:
318 rmt_tuner_set_freq(value
);
324 case RADIO_SCAN_FREQUENCY
:
326 const struct fm_region_data
* const fmr
=
327 &fm_region_data
[global_settings
.fm_region
];
329 /* case: scan for presets, back to beginning of the band */
330 if ((radio_tuned
== 1) && (value
== fmr
->freq_min
))
332 tuner_set(RADIO_FREQUENCY
,value
);
335 /* scan through frequencies */
336 if (radio_tuned
== 1)
338 if ((tuner_frequency
<= fmr
->freq_min
)
339 && (tuner_frequency
>= fmr
->freq_max
))
341 tuner_set(RADIO_FREQUENCY
,value
);
344 if(value
< tuner_frequency
)
353 tuner_set(RADIO_FREQUENCY
,value
);
355 if (reply_timeout() == true)
361 if (tuner_frequency
== value
)
375 /* mute flag sent to accessory */
376 /* rmt_tuner_mute(value); */
382 const struct fm_region_data
*rd
= &fm_region_data
[value
];
383 int band
= (rd
->freq_min
== 76000000) ? 2 : 0;
384 int spacing
= (100000 / rd
->freq_step
);
385 int deemphasis
= (rd
->deemphasis
== 50) ? 1 : 0;
387 rmt_tuner_region(band
);
388 set_deltafreq(spacing
);
389 set_deemphasis(deemphasis
);
390 rmt_tuner_set_param(tuner_param
);
394 case RADIO_FORCE_MONO
:
406 /* tuner abstraction layer: read something from the tuner */
407 int ipod_rmt_tuner_get(int setting
)
409 int val
= -1; /* default for unsupported query */
417 /* if accessory disconnected */
418 if(adc_read(ADC_ACCESSORY
) >= 10)
426 /* radio tuned: yes no */
429 if (radio_tuned
== 1)
433 /* radio is always stereo */
434 /* we can't know when it's in mono mode, depending of signal quality */
435 /* except if it is forced in mono mode */
451 char* ipod_get_rds_info(int setting
)
458 text
= rds_radioname
;
462 text
= rds_radioinfo
;
468 bool tuner_power(bool status
)
470 bool oldstatus
= powered
;