summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2004-10-17 23:24:18 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2004-10-17 23:24:18 +0000
commit4adf929a90e1cc7bc559a69193a505166ddaba1b (patch)
treea436c69572d55459f2f5e46b282a2ef15fb04d0f
parentca45869a8866756c5c11cba307a7ff62566afb22 (diff)
downloadrockbox-4adf929a90e1cc7bc559a69193a505166ddaba1b.tar.gz
rockbox-4adf929a90e1cc7bc559a69193a505166ddaba1b.zip
Philips tuner supported
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5300 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/fmradio_i2c.c179
-rw-r--r--firmware/export/fmradio_i2c.h4
-rw-r--r--firmware/tuner_philips.c25
3 files changed, 197 insertions, 11 deletions
diff --git a/firmware/drivers/fmradio_i2c.c b/firmware/drivers/fmradio_i2c.c
index 93c5d2fa91..d503980391 100644
--- a/firmware/drivers/fmradio_i2c.c
+++ b/firmware/drivers/fmradio_i2c.c
@@ -8,7 +8,7 @@
8 * $Id$ 8 * $Id$
9 * Physical interface of the Philips TEA5767 in Archos Ondio 9 * Physical interface of the Philips TEA5767 in Archos Ondio
10 * 10 *
11 * Copyright (C) 2004 by Jörg Hohensohn 11 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * 12 *
13 * All files in this archive are subject to the GNU General Public License. 13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement. 14 * See the file COPYING in the source tree root for full license agreement.
@@ -26,16 +26,181 @@
26 26
27#ifdef CONFIG_TUNER 27#ifdef CONFIG_TUNER
28 28
29/* reads 5 byte */ 29
30void fmradio_i2c_read(unsigned char* p_data) 30/* cute little functions, atomic read-modify-write */
31/* SDA is PB4 */
32#define SDA_LO and_b(~0x10, &PBDRL)
33#define SDA_HI or_b(0x10, &PBDRL)
34#define SDA_INPUT and_b(~0x10, &PBIORL)
35#define SDA_OUTPUT or_b(0x10, &PBIORL)
36#define SDA (PBDR & 0x0010)
37
38/* SCL is PB1 */
39#define SCL_INPUT and_b(~0x02, &PBIORL)
40#define SCL_OUTPUT or_b(0x02, &PBIORL)
41#define SCL_LO and_b(~0x02, &PBDRL)
42#define SCL_HI or_b(0x02, &PBDRL)
43#define SCL (PBDR & 0x0002)
44
45/* arbitrary delay loop */
46#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
47
48
49static void fmradio_i2c_start(void)
50{
51 SDA_OUTPUT;
52 SDA_HI;
53 SCL_HI;
54 SDA_LO;
55 DELAY;
56 SCL_LO;
57}
58
59static void fmradio_i2c_stop(void)
60{
61 SDA_LO;
62 SCL_HI;
63 DELAY;
64 SDA_HI;
65}
66
67
68static void fmradio_i2c_ack(int bit)
69{
70 /* Here's the deal. The slave is slow, and sometimes needs to wait
71 before it can receive the acknowledge. Therefore it forces the clock
72 low until it is ready. We need to poll the clock line until it goes
73 high before we release the ack. */
74
75 SCL_LO; /* Set the clock low */
76 if ( bit )
77 {
78 SDA_HI;
79 }
80 else
81 {
82 SDA_LO;
83 }
84
85 SCL_INPUT; /* Set the clock to input */
86 while(!SCL) /* and wait for the slave to release it */
87 sleep_thread();
88 wake_up_thread();
89
90 DELAY;
91 SCL_OUTPUT;
92 SCL_LO;
93}
94
95static int fmradio_i2c_getack(void)
31{ 96{
32 (void)p_data; 97 int ret = 1;
98
99 /* Here's the deal. The slave is slow, and sometimes needs to wait
100 before it can send the acknowledge. Therefore it forces the clock
101 low until it is ready. We need to poll the clock line until it goes
102 high before we read the ack. */
103
104 SDA_INPUT; /* And set to input */
105 SCL_INPUT; /* Set the clock to input */
106 while(!SCL) /* and wait for the slave to release it */
107 sleep_thread();
108 wake_up_thread();
109
110 if (SDA)
111 /* ack failed */
112 ret = 0;
113
114 SCL_OUTPUT;
115 SCL_LO;
116 SDA_HI;
117 SDA_OUTPUT;
118 return ret;
119}
120
121static void fmradio_i2c_outb(unsigned char byte)
122{
123 int i;
124
125 /* clock out each bit, MSB first */
126 for ( i=0x80; i; i>>=1 ) {
127 if ( i & byte )
128 {
129 SDA_HI;
130 }
131 else
132 {
133 SDA_LO;
134 }
135 SCL_HI;
136 SCL_LO;
137 }
138
139 SDA_HI;
140}
141
142static unsigned char fmradio_i2c_inb(int ack)
143{
144 int i;
145 unsigned char byte = 0;
146
147 /* clock in each bit, MSB first */
148 for ( i=0x80; i; i>>=1 ) {
149 SDA_INPUT; /* And set to input */
150 SCL_HI;
151 if ( SDA )
152 byte |= i;
153 SCL_LO;
154 SDA_OUTPUT;
155 }
156
157 fmradio_i2c_ack(ack);
158
159 return byte;
160}
161
162int fmradio_i2c_write(int address, const unsigned char* buf, int count)
163{
164 int i,x=0;
165
166 fmradio_i2c_start();
167 fmradio_i2c_outb(address & 0xfe);
168 if (fmradio_i2c_getack())
169 {
170 for (i=0; i<count; i++)
171 {
172 fmradio_i2c_outb(buf[i]);
173 if (!fmradio_i2c_getack())
174 {
175 x=-2;
176 break;
177 }
178 }
179 }
180 else
181 {
182 debugf("fmradio_i2c_write() - no ack\n");
183 x=-1;
184 }
185 fmradio_i2c_stop();
186 return x;
33} 187}
34 188
35/* writes 5 bytes */ 189int fmradio_i2c_read(int address, unsigned char* buf, int count)
36void fmradio_i2c_set(const unsigned char* p_data)
37{ 190{
38 (void)p_data; 191 int i,x=0;
192
193 fmradio_i2c_start();
194 fmradio_i2c_outb(address | 1);
195 if (fmradio_i2c_getack()) {
196 for (i=0; i<count; i++) {
197 buf[i] = fmradio_i2c_inb(0);
198 }
199 }
200 else
201 x=-1;
202 fmradio_i2c_stop();
203 return x;
39} 204}
40 205
41#endif 206#endif
diff --git a/firmware/export/fmradio_i2c.h b/firmware/export/fmradio_i2c.h
index 06b7f9f7b7..b7007a80dd 100644
--- a/firmware/export/fmradio_i2c.h
+++ b/firmware/export/fmradio_i2c.h
@@ -20,7 +20,7 @@
20#ifndef FMRADIO_I2C_H 20#ifndef FMRADIO_I2C_H
21#define FMRADIO_I2C_H 21#define FMRADIO_I2C_H
22 22
23void fmradio_i2c_read(unsigned char* p_data); /* reads 5 byte */ 23int fmradio_i2c_write(int address, const unsigned char* buf, int count);
24void fmradio_i2c_set(const unsigned char* p_data); /* writes 5 bytes */ 24int fmradio_i2c_read(int address, unsigned char* buf, int count);
25 25
26#endif 26#endif
diff --git a/firmware/tuner_philips.c b/firmware/tuner_philips.c
index 50559af23e..e63d063bfd 100644
--- a/firmware/tuner_philips.c
+++ b/firmware/tuner_philips.c
@@ -19,10 +19,12 @@
19 ****************************************************************************/ 19 ****************************************************************************/
20 20
21#include <stdbool.h> 21#include <stdbool.h>
22#include <string.h>
22#include "tuner.h" /* tuner abstraction interface */ 23#include "tuner.h" /* tuner abstraction interface */
23#include "fmradio_i2c.h" /* physical interface driver */ 24#include "fmradio_i2c.h" /* physical interface driver */
24 25
25/* FIXME: this is just a dummy */ 26#define I2C_ADR 0xC0
27static unsigned char write_bytes[5];
26 28
27/* tuner abstraction layer: set something to the tuner */ 29/* tuner abstraction layer: set something to the tuner */
28void philips_set(int setting, int value) 30void philips_set(int setting, int value)
@@ -31,12 +33,22 @@ void philips_set(int setting, int value)
31 switch(setting) 33 switch(setting)
32 { 34 {
33 case RADIO_INIT: 35 case RADIO_INIT:
36 memset(write_bytes, 0, sizeof(write_bytes));
34 break; 37 break;
35 38
36 case RADIO_FREQUENCY: 39 case RADIO_FREQUENCY:
40 {
41 int n;
42 n = (4 * (value - 225000)) / 50000;
43 write_bytes[0] = (write_bytes[0] & 0xC0) | (n >> 8);
44 write_bytes[1] = n & 0xFF;
45 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
46 }
37 break; 47 break;
38 48
39 case RADIO_MUTE: 49 case RADIO_MUTE:
50 write_bytes[0] = (write_bytes[0] & 0x7F) | (value ? 0x80 : 0);
51 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
40 break; 52 break;
41 53
42 case RADIO_IF_MEASUREMENT: 54 case RADIO_IF_MEASUREMENT:
@@ -46,6 +58,8 @@ void philips_set(int setting, int value)
46 break; 58 break;
47 59
48 case RADIO_FORCE_MONO: 60 case RADIO_FORCE_MONO:
61 write_bytes[2] = (write_bytes[2] & 0xF7) | (value ? 0x08 : 0);
62 fmradio_i2c_write(I2C_ADR, write_bytes, sizeof(write_bytes));
49 break; 63 break;
50 } 64 }
51} 65}
@@ -53,17 +67,24 @@ void philips_set(int setting, int value)
53/* tuner abstraction layer: read something from the tuner */ 67/* tuner abstraction layer: read something from the tuner */
54int philips_get(int setting) 68int philips_get(int setting)
55{ 69{
70 unsigned char read_bytes[5];
56 int val = -1; 71 int val = -1;
72
73 fmradio_i2c_read(I2C_ADR, read_bytes, sizeof(read_bytes));
74
57 switch(setting) 75 switch(setting)
58 { 76 {
59 case RADIO_PRESENT: 77 case RADIO_PRESENT:
60 val = 0; /* false */ 78 val = 1; /* true */
61 break; 79 break;
62 80
63 case RADIO_IF_MEASURED: 81 case RADIO_IF_MEASURED:
82 val = read_bytes[2] & 0x7F;
83 val = 1070 + (val-55)/2;
64 break; 84 break;
65 85
66 case RADIO_STEREO: 86 case RADIO_STEREO:
87 val = read_bytes[2] >> 7;
67 break; 88 break;
68 } 89 }
69 return val; 90 return val;