Add parse_testcodec.pl, a script for parsing and comparing test_codec.c logs and...
[kugel-rb.git] / firmware / drivers / tuner / ipod_remote_tuner.c
blob25ad2d98451b54f07878109f70488a387884142b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include "kernel.h"
28 #include "iap.h"
29 #include "tuner.h" /* tuner abstraction interface */
30 #include "adc.h"
31 #include "settings.h"
32 #include "power.h"
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;
43 int radio_tuned = 0;
44 int rds_event = 0;
46 char rds_radioname[9];
47 char rds_radioinfo[65];
49 union FRQ {
50 unsigned long int frequency_radio;
51 char data_frequency[4];
52 }Frequency;
54 void rmt_tuner_freq(void)
56 char tempdata[4];
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);
64 radio_tuned = 1;
65 rmt_tuner_signal_power(serbuf[7]);
68 void rmt_tuner_set_freq(int curr_freq)
70 if (curr_freq != tuner_frequency)
72 radio_tuned = 0;
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};
80 if (curr_freq != 0)
82 curr_freq = curr_freq / 1000;
83 char tempdata[4];
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)
104 if (state == 0)
106 tuner_param = 0x00;
107 old_tuner_param = 0xFF;
108 mono_mode = -1;
109 old_region = -1;
110 tuner_frequency = 0;
111 radio_tuned = 0;
113 /* tuner HW on */
114 unsigned char data[] = {0x07, 0x05, 0x01};
115 iap_send_pkt(data, sizeof(data));
116 /* boost gain */
117 unsigned char data1[] = {0x07, 0x24, 0x06 };
118 iap_send_pkt(data1, sizeof(data1));
119 /* set volume */
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));
123 /* set rds on */
124 unsigned char data3[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 };
125 iap_send_pkt(data3, sizeof(data3));
127 else
129 /* unbooste gain */
130 unsigned char data[] = {0x07, 0x24, 0x00};
131 iap_send_pkt(data, sizeof(data));
132 /* set rds off */
133 unsigned char data1[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 };
134 iap_send_pkt(data1, sizeof(data1));
135 /* stop tuner HW */
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;
145 radio_tuned = 0;
146 iap_send_pkt(data, sizeof(data));
148 if (param == 1)
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};
168 if (value)
170 /* mute flag on (pause) */
171 data[3] = 0x02;
173 iap_send_pkt(data, sizeof(data));
176 void rmt_tuner_region(int region)
178 if (region != old_region)
180 unsigned char data[] = {0x07, 0x08, 0x00};
181 if (region == 2)
183 data[2] = 0x02; /* japan band */
185 else
187 data[2] = 0x01; /* us eur band */
189 iap_send_pkt(data, sizeof(data));
190 sleep(HZ/100);
191 old_region = region;
195 /* set stereo/mono, deemphasis, delta freq... */
196 void rmt_tuner_set_param(unsigned char tuner_param)
198 if(tuner_param != old_tuner_param)
200 unsigned char data[] = {0x07, 0x0E, 0x00};
202 data[2] = tuner_param;
203 iap_send_pkt(data, sizeof(data));
204 old_tuner_param = tuner_param;
208 static void set_deltafreq(int delta)
210 tuner_param &= 0xFC;
211 switch (delta)
213 case 1:
215 /* 100KHz */
216 tuner_param |= 0x01;
217 break;
219 case 2:
221 /* 50KHz */
222 tuner_param |= 0x02;
223 break;
226 default:
228 /* 200KHz */
229 tuner_param |= 0x00;
230 break;
235 static void set_deemphasis(int deemphasis)
237 tuner_param &= 0xBF;
238 switch (deemphasis)
240 case 1:
242 tuner_param |= 0x40;
243 break;
245 default:
247 tuner_param |= 0x00;
248 break;
253 static void set_mono(int value)
255 tuner_param &= 0xEF;
257 if (value != mono_mode)
259 tuner_param &= 0xEF;
260 if (value == 1)
261 tuner_param |= 0x10;
262 rmt_tuner_set_param(tuner_param);
263 sleep(HZ/100);
264 mono_mode = value;
268 static bool reply_timeout(void)
270 int timeout = 0;
272 sleep(HZ/50);
275 iap_handlepkt();
276 sleep(HZ/50);
277 timeout++;
279 while((ipod_rmt_tuner_get(RADIO_TUNED) == 0) && (timeout < TIMEOUT_VALUE));
281 if (timeout >= TIMEOUT_VALUE)
282 return true;
283 else return false;
286 void rmt_tuner_rds_data(void)
288 if (serbuf[3] == 0x1E)
290 strlcpy(rds_radioname,serbuf+5,8);
292 else if(serbuf[3] == 0x04)
294 strlcpy(rds_radioinfo,serbuf+5,(serbuf[0]-4));
296 rds_event = 1;
299 /* tuner abstraction layer: set something to the tuner */
300 int ipod_rmt_tuner_set(int setting, int value)
302 switch(setting)
304 case RADIO_SLEEP:
306 rmt_tuner_sleep(value);
307 sleep(HZ/10);
308 if(value)
310 tuner_frequency = 0;
312 break;
315 case RADIO_FREQUENCY:
317 rmt_tuner_set_freq(value);
318 if (reply_timeout())
319 return 0;
320 break;
323 case RADIO_SCAN_FREQUENCY:
325 const struct fm_region_data * const fmr =
326 &fm_region_data[global_settings.fm_region];
328 /* case: scan for presets, back to beginning of the band */
329 if ((radio_tuned == 1) && (value == fmr->freq_min))
331 tuner_set(RADIO_FREQUENCY,value);
334 /* scan through frequencies */
335 if (radio_tuned == 1)
337 if ((tuner_frequency <= fmr->freq_min)
338 && (tuner_frequency >= fmr->freq_max))
340 tuner_set(RADIO_FREQUENCY,value);
342 /* scan down */
343 if(value < tuner_frequency)
344 rmt_tuner_scan(-1);
345 /* scan up */
346 else
347 rmt_tuner_scan(1);
349 sleep(HZ/10);
350 if (reply_timeout())
352 tuner_set(RADIO_FREQUENCY,value);
353 rmt_tuner_scan(1);
354 if (reply_timeout() == true)
355 return 0;
357 radio_tuned = 0;
360 if (tuner_frequency == value)
362 radio_tuned = 1;
363 return 1;
365 else
367 radio_tuned = 0;
368 return 0;
372 case RADIO_MUTE:
374 /* mute flag sent to accessory */
375 /* rmt_tuner_mute(value); */
376 break;
379 case RADIO_REGION:
381 const struct rmt_tuner_region_data *rd =
382 &rmt_tuner_region_data[value];
384 rmt_tuner_region(rd->band);
385 set_deltafreq(rd->spacing);
386 set_deemphasis(rd->deemphasis);
387 rmt_tuner_set_param(tuner_param);
388 break;
391 case RADIO_FORCE_MONO:
393 set_mono(value);
394 break;
397 default:
398 return -1;
400 return 1;
403 /* tuner abstraction layer: read something from the tuner */
404 int ipod_rmt_tuner_get(int setting)
406 int val = -1; /* default for unsupported query */
408 switch(setting)
410 case RADIO_PRESENT:
411 val = radio_present;
412 if (val)
414 /* if accessory disconnected */
415 if(adc_read(ADC_ACCESSORY) >= 10)
417 radio_present = 0;
418 val = 0;
421 break;
423 /* radio tuned: yes no */
424 case RADIO_TUNED:
425 val = 0;
426 if (radio_tuned == 1)
427 val = 1;
428 break;
430 /* radio is always stereo */
431 /* we can't know when it's in mono mode, depending of signal quality */
432 /* except if it is forced in mono mode */
433 case RADIO_STEREO:
434 val = true;
435 break;
437 case RADIO_EVENT:
438 if (rds_event)
440 val = 1;
441 rds_event = 0;
443 break;
445 return val;
448 char* ipod_get_rds_info(int setting)
450 char *text = NULL;
452 switch(setting)
454 case RADIO_RDS_NAME:
455 text = rds_radioname;
456 break;
458 case RADIO_RDS_TEXT:
459 text = rds_radioinfo;
460 break;
462 return text;
465 bool tuner_power(bool status)
467 bool oldstatus = powered;
468 powered = status;
469 return oldstatus;