1 /**************************************************************************/
6 @brief Driver for the TEA5767 FM receiver.
10 Software License Agreement (BSD License)
12 Copyright (c) 2012, K. Townsend
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are met:
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
22 3. Neither the name of the copyright holders nor the
23 names of its contributors may be used to endorse or promote products
24 derived from this software without specific prior written permission.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
27 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
30 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /**************************************************************************/
39 #include "core/i2c/i2c.h"
40 #include "core/systick/systick.h"
42 extern volatile uint8_t I2CMasterBuffer
[I2C_BUFSIZE
];
43 extern volatile uint8_t I2CSlaveBuffer
[I2C_BUFSIZE
];
45 static bool _tea5767Initialised
= false;
47 /**************************************************************************/
49 @brief Sends 5 bytes over I2C
51 /**************************************************************************/
52 void tea5767SendData(uint8_t * bytes
)
54 // Clear write buffers
56 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
58 I2CMasterBuffer
[i
] = 0x00;
63 I2CMasterBuffer
[0] = TEA5767_ADDRESS
;
64 I2CMasterBuffer
[1] = bytes
[0];
65 I2CMasterBuffer
[2] = bytes
[1];
66 I2CMasterBuffer
[3] = bytes
[2];
67 I2CMasterBuffer
[4] = bytes
[3];
68 I2CMasterBuffer
[5] = bytes
[4];
72 /**************************************************************************/
74 @brief Reads 5 bytes over I2C
76 /**************************************************************************/
77 void tea5767ReadData(uint8_t * bytes
)
81 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
83 I2CMasterBuffer
[i
] = 0x00;
84 I2CSlaveBuffer
[i
] = 0x00;
89 I2CMasterBuffer
[0] = TEA5767_ADDRESS
| TEA5767_READ
;
92 bytes
[0] = I2CSlaveBuffer
[0];
93 bytes
[1] = I2CSlaveBuffer
[1];
94 bytes
[2] = I2CSlaveBuffer
[2];
95 bytes
[3] = I2CSlaveBuffer
[3];
96 bytes
[4] = I2CSlaveBuffer
[4];
99 /**************************************************************************/
101 @brief This is a test function to evaluate the quality of crystals
102 used on 3rd party modules. Most modules use cheap 32.768kHz
103 crystals which are prone to de-tuning. Checking the IF bits
104 at 81.4MHz can check if the crystal is problematic or not.
106 @returns True (1) if the IF bits are equal to 0x37 (good), otherwise
107 false (0). The device may still function if the IF values
108 are slightly off, but auto-scan and tuning will likely be
111 /**************************************************************************/
112 bool tea5767CheckCrystal(void)
114 /* AN10133 (p.38) states:
116 The choice of 32768Hz reference frequency makes it possible to use a
117 cheap 32.768kHz watch crystal. A drawback of these clocks is that they
118 have a very high second order temperature coefficient. This may result
119 in de-tuning the radio or a search action may fail.
121 Care should be taken when using this crystal. The accuracy of the
122 32768Hz crystal can be checked by tuning the radio to 81.4 MHz
123 with high/low side injection and reading the IF via the bus. The IF
126 An other issue when using this crystal is the grid position. It is
127 not possible to create a 100kHz grid position, but 98.304kHz
128 (3*32768Hz). This should not be a problem if this is resolved in
131 The motional capacitance of the 32768Hz crystal should be between
132 1.5fF and 3fF. Shunt capacitance must be max 3.5pF. The series
133 resistance should not exceed 75KOhm.
135 Further, the frequency accuracy of this crystal must not exceed ±20
136 ppm, while the temperature drift should be in the order of ±50 ppm
137 over a temperature range of –10oC to +60oC.
141 uint8_t buffer
[5] = { 0, 0, 0, 0, 0 };
143 // Set the frequency to 81.4MHz
144 tea5767SetFrequency(81400000);
147 // Read back the IF bits
148 tea5767ReadData(&buffer
[0]);
149 ifValue
= buffer
[2] & 0x7F;
151 // Reconfigure the chip to a known frequency to avoid user problems
152 // tea5767SetFrequency(TEA5767_FMBANDSTART_JAPAN);
153 tea5767SetFrequency(TEA5767_FMBANDSTART_US_EUROPE
);
155 // Return true if the crystal is OK (IF = 0x37 @ 81.4MHz),
156 // false if it's something else
163 /**************************************************************************/
165 @brief Initialises I2C for the TEA5767.
167 /**************************************************************************/
168 uint32_t tea5767Init()
171 if (i2cInit(I2CMASTER
) == false)
177 /* Set initialisation flag */
178 _tea5767Initialised
= true;
180 // Set the frequency to a known value to make sure the PLL is properly configured
181 // tea5767SetFrequency(TEA5767_FMBANDSTART_JAPAN);
182 tea5767SetFrequency(TEA5767_FMBANDSTART_US_EUROPE
);
187 /**************************************************************************/
189 @brief Sets the frequency to the specified value in Hz
192 The frequency in Hz, meaning that 95.7MHz = 97,500,000
193 101.4 MHz = 101,400,000 etc.
195 /**************************************************************************/
196 void tea5767SetFrequency( uint32_t frequency
)
199 uint8_t buffer
[5] = { 0, 0, 0, 0, 0 };
201 // Make sure I2C is initialised
202 if (!_tea5767Initialised
) tea5767Init();
204 // Calculate PLL word for high side injection mode
205 // NDEC = (4*(FRF + FIF)) / FREFS
207 // FRF = Desired tuning frequency in Hz
208 // FIF = Intermediate frequency in Hz (225kHz)
209 // FREFS = Reference frequency in Hz (32.768kHz)
210 pllValue
= (4 * (frequency
+ 225000)) / 32768;
212 buffer
[0] = (pllValue
>> 8) & 0x3F; // Upper 6 PLL bits (also turns mute and search mode off!)
213 buffer
[1] = (pllValue
& 0xFF); // Lower 8 PLL bits
214 buffer
[2] = TEA5767_WBYTE3_HLSI
; // High side injection mode
215 buffer
[3] = TEA5767_WBYTE4_XTAL
; // XTAL bit = 1 for 32.768kHz crystal
216 buffer
[4] = 0; // PLLREF bit = 0 for 32.768kHz crystal
218 // Send data over I2C
219 tea5767SendData(buffer
);
222 /**************************************************************************/
224 @brief Returns the current frequency in Hz (meaning 97.5MHz will be
225 returned as 97,500,000 etc.
227 /**************************************************************************/
228 uint32_t tea5767GetFrequency( void )
230 uint32_t frequency
= 0;
231 uint8_t buffer
[5] = { 0, 0, 0, 0, 0 };
233 if (!_tea5767Initialised
) tea5767Init();
235 tea5767ReadData(&buffer
[0]);
237 // Retrieve the raw 14-bit PLL value from word 1 and 2
238 frequency
= ((buffer
[0] & 0x3F) << 8) + buffer
[1];
239 // Determine the current frequency using the same high side formula as above
240 frequency
= frequency
* 32768 / 4 - 225000;
245 /**************************************************************************/
247 @brief Starts the auto-scan process from the current frequency
249 @param[in] scanDirection
250 Set this to 0 to scan down, or one to scan up, starting
251 at the current frequency.
253 /**************************************************************************/
254 void tea5767Scan( uint8_t scanDirection
)
256 uint8_t rbuffer
[5] = { 0, 0, 0, 0, 0 };
257 uint8_t wbuffer
[5] = { 0, 0, 0, 0, 0 };
259 // Make sure I2C is initialised
260 if (!_tea5767Initialised
) tea5767Init();
262 // First we need to get the current PLL word to know where to start from
263 tea5767ReadData(&rbuffer
[0]);
265 // Set the PLL value again and append the search enable bu
266 wbuffer
[0] = TEA5767_WBYTE1_SEARCHMODE
+ // Search mode enabled
267 (rbuffer
[0] & 0x3F); // Upper PLL bits
268 wbuffer
[1] = rbuffer
[1]; // Lower PLL bits
269 wbuffer
[2] = TEA5767_WBYTE3_SEARCHSTOPLEVEL_MID
| // Mid level ADC for search steps
270 TEA5767_WBYTE3_HLSI
; // HLSI (must be 1 for PLL)
271 wbuffer
[3] = TEA5767_WBYTE4_XTAL
; // Must be 1 for 32.768kHz crystal
274 // Set the scan direction bit to 1 (scan up) if scanDirection is non-zero
275 if (scanDirection
) wbuffer
[2] |= TEA5767_WBYTE3_SEARCHUPDOWN
;
277 // Send data over I2C
278 tea5767SendData(wbuffer
);