Simplify unsigned int <-> unsigned char array conversion in ipod_remote_tuner.c ...
[kugel-rb.git] / firmware / drivers / tuner / ipod_remote_tuner.c
bloba7a16c5217e4541f6b506819ad6ee5a08759dd22
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 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 ;
60 radio_tuned = true;
61 rmt_tuner_signal_power(serbuf[7]);
64 static void rmt_tuner_set_freq(int curr_freq)
66 if (curr_freq != tuner_frequency)
68 radio_tuned = false;
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};
76 if (curr_freq != 0)
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)
90 if (state == 0)
92 tuner_param = 0x00;
93 old_tuner_param = 0xFF;
94 mono_mode = -1;
95 old_region = -1;
96 tuner_frequency = 0;
97 radio_tuned = false;
99 /* tuner HW on */
100 const unsigned char data[] = {0x07, 0x05, 0x01};
101 iap_send_pkt(data, sizeof(data));
102 /* boost gain */
103 const unsigned char data1[] = {0x07, 0x24, 0x06 };
104 iap_send_pkt(data1, sizeof(data1));
105 /* set volume */
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));
109 /* set rds on */
110 const unsigned char data3[] = {0x07, 0x20, 0x40, 0x00, 0x00, 0x10 };
111 iap_send_pkt(data3, sizeof(data3));
113 else
115 /* unbooste gain */
116 const unsigned char data[] = {0x07, 0x24, 0x00};
117 iap_send_pkt(data, sizeof(data));
118 /* set rds off */
119 const unsigned char data1[] = {0x07, 0x20, 0x00, 0x00, 0x00, 0x00 };
120 iap_send_pkt(data1, sizeof(data1));
121 /* stop tuner HW */
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;
131 radio_tuned = false;
132 iap_send_pkt(data, sizeof(data));
134 if (param == 1)
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};
155 if (value)
157 /* mute flag on (pause) */
158 data[3] = 0x02;
160 iap_send_pkt(data, sizeof(data));
162 #endif
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 */
174 else
176 data[2] = 0x01; /* us eur band */
178 iap_send_pkt(data, sizeof(data));
179 sleep(HZ/100);
180 old_region = region;
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)
199 tuner_param &= 0xFC;
200 switch (delta)
202 case 1:
204 /* 100KHz */
205 tuner_param |= 0x01;
206 break;
208 case 2:
210 /* 50KHz */
211 tuner_param |= 0x02;
212 break;
215 default:
217 /* 200KHz */
218 tuner_param |= 0x00;
219 break;
224 static void set_deemphasis(int deemphasis)
226 tuner_param &= 0xBF;
227 switch (deemphasis)
229 case 1:
231 tuner_param |= 0x40;
232 break;
234 default:
236 tuner_param |= 0x00;
237 break;
242 static void set_mono(int value)
244 tuner_param &= 0xEF;
246 if (value != mono_mode)
248 tuner_param &= 0xEF;
249 if (value == 1)
250 tuner_param |= 0x10;
251 rmt_tuner_set_param(tuner_param);
252 sleep(HZ/100);
253 mono_mode = value;
257 static bool reply_timeout(void)
259 int timeout = 0;
261 sleep(HZ/50);
264 iap_handlepkt();
265 sleep(HZ/50);
266 timeout++;
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));
283 rds_event = true;
286 /* tuner abstraction layer: set something to the tuner */
287 int ipod_rmt_tuner_set(int setting, int value)
289 switch(setting)
291 case RADIO_SLEEP:
293 rmt_tuner_sleep(value);
294 sleep(HZ/10);
295 if(value)
297 tuner_frequency = 0;
299 break;
302 case RADIO_FREQUENCY:
304 rmt_tuner_set_freq(value);
305 if (reply_timeout())
306 return 0;
307 break;
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 */
322 if (radio_tuned)
324 if ((tuner_frequency <= fmr->freq_min)
325 && (tuner_frequency >= fmr->freq_max))
327 tuner_set(RADIO_FREQUENCY,value);
329 /* scan down */
330 if(value < tuner_frequency)
331 rmt_tuner_scan(-1);
332 /* scan up */
333 else
334 rmt_tuner_scan(1);
336 sleep(HZ/10);
337 if (reply_timeout())
339 tuner_set(RADIO_FREQUENCY,value);
340 rmt_tuner_scan(1);
341 if (reply_timeout() == true)
342 return 0;
344 radio_tuned = false;
347 if (tuner_frequency == value)
349 radio_tuned = true;
350 return 1;
352 else
354 radio_tuned = false;
355 return 0;
359 case RADIO_MUTE:
361 /* mute flag sent to accessory */
362 /* rmt_tuner_mute(value); */
363 break;
366 case RADIO_REGION:
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);
377 break;
380 case RADIO_FORCE_MONO:
382 set_mono(value);
383 break;
386 default:
387 return -1;
389 return 1;
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 */
397 switch(setting)
399 case RADIO_PRESENT:
400 val = radio_present;
401 if (val)
403 /* if accessory disconnected */
404 if(adc_read(ADC_ACCESSORY) >= 10)
406 radio_present = 0;
407 val = 0;
410 break;
412 /* radio tuned: yes no */
413 case RADIO_TUNED:
414 val = 0;
415 if (radio_tuned)
416 val = 1;
417 break;
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 */
422 case RADIO_STEREO:
423 val = true;
424 break;
426 case RADIO_EVENT:
427 if (rds_event)
429 val = 1;
430 rds_event = false;
432 break;
434 return val;
437 char* ipod_get_rds_info(int setting)
439 char *text = NULL;
441 switch(setting)
443 case RADIO_RDS_NAME:
444 text = rds_radioname;
445 break;
447 case RADIO_RDS_TEXT:
448 text = rds_radioinfo;
449 break;
451 return text;
454 bool tuner_power(bool status)
456 bool oldstatus = powered;
457 powered = status;
458 return oldstatus;