FM tuner region code cleanup - FS #11492 by me.
[maemo-rb.git] / firmware / drivers / tuner / ipod_remote_tuner.c
blob52d93b8b34e3a73abbb02e3ec04402edb13db3e4
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 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 */
186 else
188 data[2] = 0x01; /* us eur band */
190 iap_send_pkt(data, sizeof(data));
191 sleep(HZ/100);
192 old_region = region;
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)
211 tuner_param &= 0xFC;
212 switch (delta)
214 case 1:
216 /* 100KHz */
217 tuner_param |= 0x01;
218 break;
220 case 2:
222 /* 50KHz */
223 tuner_param |= 0x02;
224 break;
227 default:
229 /* 200KHz */
230 tuner_param |= 0x00;
231 break;
236 static void set_deemphasis(int deemphasis)
238 tuner_param &= 0xBF;
239 switch (deemphasis)
241 case 1:
243 tuner_param |= 0x40;
244 break;
246 default:
248 tuner_param |= 0x00;
249 break;
254 static void set_mono(int value)
256 tuner_param &= 0xEF;
258 if (value != mono_mode)
260 tuner_param &= 0xEF;
261 if (value == 1)
262 tuner_param |= 0x10;
263 rmt_tuner_set_param(tuner_param);
264 sleep(HZ/100);
265 mono_mode = value;
269 static bool reply_timeout(void)
271 int timeout = 0;
273 sleep(HZ/50);
276 iap_handlepkt();
277 sleep(HZ/50);
278 timeout++;
280 while((ipod_rmt_tuner_get(RADIO_TUNED) == 0) && (timeout < TIMEOUT_VALUE));
282 if (timeout >= TIMEOUT_VALUE)
283 return true;
284 else return false;
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));
297 rds_event = 1;
300 /* tuner abstraction layer: set something to the tuner */
301 int ipod_rmt_tuner_set(int setting, int value)
303 switch(setting)
305 case RADIO_SLEEP:
307 rmt_tuner_sleep(value);
308 sleep(HZ/10);
309 if(value)
311 tuner_frequency = 0;
313 break;
316 case RADIO_FREQUENCY:
318 rmt_tuner_set_freq(value);
319 if (reply_timeout())
320 return 0;
321 break;
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);
343 /* scan down */
344 if(value < tuner_frequency)
345 rmt_tuner_scan(-1);
346 /* scan up */
347 else
348 rmt_tuner_scan(1);
350 sleep(HZ/10);
351 if (reply_timeout())
353 tuner_set(RADIO_FREQUENCY,value);
354 rmt_tuner_scan(1);
355 if (reply_timeout() == true)
356 return 0;
358 radio_tuned = 0;
361 if (tuner_frequency == value)
363 radio_tuned = 1;
364 return 1;
366 else
368 radio_tuned = 0;
369 return 0;
373 case RADIO_MUTE:
375 /* mute flag sent to accessory */
376 /* rmt_tuner_mute(value); */
377 break;
380 case RADIO_REGION:
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);
391 break;
394 case RADIO_FORCE_MONO:
396 set_mono(value);
397 break;
400 default:
401 return -1;
403 return 1;
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 */
411 switch(setting)
413 case RADIO_PRESENT:
414 val = radio_present;
415 if (val)
417 /* if accessory disconnected */
418 if(adc_read(ADC_ACCESSORY) >= 10)
420 radio_present = 0;
421 val = 0;
424 break;
426 /* radio tuned: yes no */
427 case RADIO_TUNED:
428 val = 0;
429 if (radio_tuned == 1)
430 val = 1;
431 break;
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 */
436 case RADIO_STEREO:
437 val = true;
438 break;
440 case RADIO_EVENT:
441 if (rds_event)
443 val = 1;
444 rds_event = 0;
446 break;
448 return val;
451 char* ipod_get_rds_info(int setting)
453 char *text = NULL;
455 switch(setting)
457 case RADIO_RDS_NAME:
458 text = rds_radioname;
459 break;
461 case RADIO_RDS_TEXT:
462 text = rds_radioinfo;
463 break;
465 return text;
468 bool tuner_power(bool status)
470 bool oldstatus = powered;
471 powered = status;
472 return oldstatus;