├── AR1010lib-logo.png
├── keywords.txt
├── LICENSE
├── README.md
├── ar1010lib.h
└── ar1010lib.cpp
/AR1010lib-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamjansch/AR1010lib/HEAD/AR1010lib-logo.png
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 |
2 | #######################################
3 | # Datatypes (KEYWORD1)
4 | #######################################
5 |
6 | AR1010 KEYWORD1
7 | ar1010lib KEYWORD1
8 | ar1010lib.h KEYWORD1
9 |
10 | #######################################
11 | # Methods and Functions (KEYWORD2)
12 | #######################################
13 |
14 | writeToRegister KEYWORD2
15 | readFromRegister KEYWORD2
16 |
17 | initialise KEYWORD2
18 |
19 | setSeekDirection KEYWORD2
20 | setSeekThreshold KEYWORD2
21 |
22 | setFrequency KEYWORD2
23 | setVolume KEYWORD2
24 | setHardmute KEYWORD2
25 | setSoftmute KEYWORD2
26 |
27 | frequency KEYWORD2
28 | seek KEYWORD2
29 | buildSeekMap KEYWORD2
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Software License Agreement (New BSD License)
2 |
3 | Copyright (c) 2009, Adam Jansch
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 | * Neither the name of the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ADAM JANSCH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AR1010lib
2 | =========
3 |
4 | The AR1010 FM Receiver Breakout Board is a miniature FM radio receiver whose parameters can be controlled over an I2C ('two-wire') or an SPI ('three-wire') serial interface, thus making it ideal for connection to an Arduino.
5 |
6 | The **AR1010lib** library uses the I2C serial protocol, accessed through the Arduino's analog in pins 4 & 5. It allows for custom initialisation, and the setting of tuning frequency, volume, hardmute and softmute values. Although the library probably isn't feature complete, it shouldn't be difficult to add in higher-level methods using the available programming guide and some of the lower-level methods available in the library.
7 |
8 |
9 |
10 | (The programming guide for the Airoha AR1000 (version 0.81, RevF) is also suitable for the AR1010, and contains accurate register maps of the module's functionality.)
11 |
12 |
13 |
14 | INSTALLATION
15 | ------------
16 |
17 | 1. Install the AR1010lib library, following the instructions in the Contributed Libraries section on the Arduino Libraries page
18 | 2. Make sure to add `#include ` to the beginning of any necessary Sketchbook file
19 | 3. Add the Arduino's Wire library here too
20 |
21 |
22 | USAGE
23 | --------------
24 |
25 | ### Hardware
26 |
27 | 1. Connect AR1010 Data To to Arduino Analog in 4
28 | 2. Connect AR1010 Clock to Arduino Analog in 5
29 |
30 | ### Global
31 |
32 | 1. Define an AR1010 instance: `AR1010 radio = AR1010();`
33 | 2. Optionally define an array to set the AR1010's registers. This should be of type `word` and 18 elements large. Refer to the programming guide for the configurations of the registers
34 |
35 | ### Setup() method
36 |
37 | 1. Begin I2C comms with the Wire library: `Wire.begin();`
38 | 2. Initialise the AR1010 instance: `radio.initialise();` - optionally pass register array as argument here
39 | 3. Add a one-second delay: `delay(1000);`
40 |
41 | ### The rest
42 |
43 | Access library methods through the AR1010 instance; for example, to set the radio frequency use `radio.setFrequency(910);` to set it to 91.0MHz. Methods available are:
44 |
45 | * `seek([char direction])`: seek (autotune) to next station - pass `u` to seek up and `d` to seek down
46 | * `frequency()`: get current radio frequency - measured in tenths of MHz, so 934 equates to 93.4MHz
47 | * `setFrequency([int frequency])`: set radio FM frequency directly - measured in tenths of MHz, so 934 equates to 93.4MHz
48 | * `setHardmute([bool mute_on])`: set radio hard mute
49 | * `setSoftmute([bool mute_on])`: set radio soft mute
50 | * `setSeekThreshold([int threshold])`: set seek (autotune) threshold, or the point at which the radio will decide a given frequency is a station
51 | * `setVolume([int volume])`: set radio volume, at integer between 0-18
--------------------------------------------------------------------------------
/ar1010lib.h:
--------------------------------------------------------------------------------
1 | /* -------------------------------------------------------------------------------
2 | ar1010lib.h
3 |
4 | Version: 0.9
5 | Created by Adam Jansch on 20/03/2010.
6 | Library for I2C (TWI) communications from Arduino to AR1010 radio receiver module
7 |
8 | Tested with Arduino Duemilanove running an ATmega328
9 |
10 | Copyright (c) 2010, Adam Jansch
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 | * Redistributions of source code must retain the above copyright
16 | notice, this list of conditions and the following disclaimer.
17 | * Redistributions in binary form must reproduce the above copyright
18 | notice, this list of conditions and the following disclaimer in the
19 | documentation and/or other materials provided with the distribution.
20 | * Neither the name of the names of its contributors may be used to endorse
21 | or promote products derived from this software without specific prior
22 | written permission.
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | DISCLAIMED. IN NO EVENT SHALL ADAM JANSCH BE LIABLE FOR ANY
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 | -------------------------------------------------------------------------------- */
35 |
36 | // Ensure this library description is only included once
37 | #ifndef ar1010lib_h
38 | #define ar1010lib_h
39 |
40 | // Include libraries ============================================
41 | #include "WProgram.h" // Arduino standard types and constants
42 |
43 | class AR1010
44 | {
45 | public:
46 | // Constructor/destructor --------------------------------------------------
47 | AR1010();
48 | ~AR1010();
49 |
50 | // Write/read methods -------------------------------------------
51 | void writeToRegister(uint8_t address, uint16_t data);
52 | uint16_t readFromRegister(uint8_t address);
53 |
54 | // Other methods ------------------------------------------------
55 | void initialise(uint16_t *customRegisters = NULL);
56 |
57 | void setSeekThreshold(uint8_t threshold);
58 |
59 | void setFrequency(uint16_t frequency);
60 | void setVolume(uint8_t volume);
61 | void setHardmute(bool hmute);
62 | void setSoftmute(bool smute);
63 |
64 | uint16_t frequency();
65 | uint16_t seek(char direction = 'u'); // 'u' - up, 'd' - down
66 |
67 | private:
68 | void setBitInRegister(uint8_t address, uint8_t bit, bool bitState);
69 | void setSeekDirection(char direction); // 'u' - up, 'd' - down
70 |
71 | uint8_t readLOInjection(bool loHi = 0); // Returns stronger signal - 0 = low-side, 1 = high-side
72 | void tuneWithAutoHiLo();
73 | };
74 |
75 | #endif
--------------------------------------------------------------------------------
/ar1010lib.cpp:
--------------------------------------------------------------------------------
1 | /* ------------------------------------------------------------------------------
2 | ar1010lib.cpp
3 |
4 | Version: 0.9.3
5 | Created by Adam Jansch on 20/03/2010.
6 | Library for I2C (TWI) communications from Arduino to AR1010 radio receiver module
7 |
8 | Tested with Arduino Duemilanove running an ATmega328
9 |
10 | Copyright (c) 2010, Adam Jansch
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without
14 | modification, are permitted provided that the following conditions are met:
15 | * Redistributions of source code must retain the above copyright
16 | notice, this list of conditions and the following disclaimer.
17 | * Redistributions in binary form must reproduce the above copyright
18 | notice, this list of conditions and the following disclaimer in the
19 | documentation and/or other materials provided with the distribution.
20 | * Neither the name of the names of its contributors may be used to endorse
21 | or promote products derived from this software without specific prior
22 | written permission.
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 | DISCLAIMED. IN NO EVENT SHALL ADAM JANSCH BE LIABLE FOR ANY
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 | -------------------------------------------------------------------------------- */
35 |
36 | #include // Library for I2C comms
37 | #include "WProgram.h" // Arduino standard types and constants
38 | #include "ar1010lib.h"
39 |
40 |
41 | #define AR1010_ADDRESS (0x4 << 2 | 0x0) // !! DON'T ADD R/W BIT - WIRE LIBRARY DOES THIS FOR YOU!
42 |
43 | #define RSSI_ADDR 0x12 // Address of the RSSI register
44 | #define ADDR_STATUS 0x13 // Address of the status register
45 | #define CHAN_MASK 0xFE00 // Bit range of register 2's channel setting
46 | #define SHIFT_READCHAN 7 // Number of bits to shift to get READCHAN value
47 |
48 | #define MASK_ST 0x0008 // Stereo D3 in address 13H
49 | #define MASK_READCHAN 0xFF80 // D7~D15 in address 13H
50 |
51 | #define HILO_MASK 0x7FFA // D15, D2 and D0 in register 11 - hi/lo injection bits
52 |
53 | // DEFINED ARRAYS ---------------------------------------------------------
54 | // Array of 2-byte ints to set the radio's registers on start-up
55 | // TAKEN FROM PROGRAMMING GUIDE REV F 0.81
56 | const uint16_t register_init[18] = {
57 | 0xFFFB, // R0: 1111 1111 1111 1011
58 | 0x5B15, // R1: 0101 1011 0001 0101 - Mono (D3), Softmute (D2), Hardmute (D1) !! SOFT-MUTED BY DEFAULT !!
59 | 0xD0B9, // R2: 1101 0000 1011 1001 - Tune/Channel
60 | 0xA010, // R3: 1010 0000 0001 0000 - Seekup (D15), Seek bit (D14), Space 100kHz (D13), Seek threshold: 16 (D6-D0)
61 | 0x0780, // R4: 0000 0111 1000 0000
62 | 0x28AB, // R5: 0010 1000 1010 1011
63 | 0x6400, // R6: 0110 0100 0000 0000
64 | 0x1EE7, // R7: 0001 1110 1110 0111
65 | 0x7141, // R8: 0111 0001 0100 0001
66 | 0x007D, // R9: 0000 0000 0111 1101
67 | 0x82C6, // R10: 1000 0010 1100 0110 - Seek wrap (D3)
68 | 0x4E55, // R11: 0100 1110 0101 0101
69 | 0x970C, // R12: 1001 0111 0000 1100
70 | 0xB845, // R13: 1011 1000 0100 0101
71 | 0xFC2D, // R14: 1111 1100 0010 1101 - Volume control 2 (D12-D15)
72 | 0x8097, // R15: 1000 0000 1001 0111
73 | 0x04A1, // R16: 0000 0100 1010 0001
74 | 0xDF61 // R17: 1101 1111 0110 0001
75 | };
76 |
77 | // Recommended volume settings
78 | const uint8_t volume_map[19] = {
79 | 0x0F, 0xCF, 0xDF, 0xFF, 0xCB,
80 | 0xDB, 0xFB, 0xFA, 0xF9, 0xF8,
81 | 0xF7, 0xD6, 0xE6, 0xF6, 0xE3,
82 | 0xF3, 0xF2, 0xF1, 0xF0
83 | };
84 |
85 | // Define register/bit arrays for particular functions
86 | const uint8_t hardmute_bit[2] = { 1, 1 }; // Register 1 - xxxx xxxx xxxx xxDx
87 | const uint8_t softmute_bit[2] = { 1, 2 }; // Register 1 - xxxx xxxx xxxx xDxx
88 | const uint8_t seek_bit[2] = { 3, 14 }; // Register 3 - xDxx xxxx xxxx xxxx
89 | const uint8_t seekup_bit[2] = { 3, 15 }; // Register 3 - Dxxx xxxx xxxx xxxx
90 | const uint8_t tune_bit[2] = { 2, 9 }; // Register 2 - xxxx xxDx xxxx xxxx
91 | const uint8_t hiloctrl1_bit[2] = { 11, 2 }; // Register 11 - xxxx xxxx xxxx xDxx
92 | const uint8_t hiloctrl2_bit[2] = { 11, 0 }; // Register 11 - xxxx xxxx xxxx xxxD
93 | const uint8_t hiloside_bit[2] = { 11, 15 }; // Register 11 - Dxxx xxxx xxxx xxxx
94 |
95 |
96 |
97 | // Constructor ============================================================
98 | AR1010::AR1010()
99 | {
100 | // Nada
101 | }
102 |
103 | // Destructor =============================================================
104 | AR1010::~AR1010()
105 | {
106 | // Nada
107 | }
108 |
109 |
110 | // Write/read methods -----------------------------------------------------
111 | // Write method ===========================================================
112 | void AR1010::writeToRegister(uint8_t address, uint16_t data)
113 | {
114 | // Write [data] to register at [address] ------------------------------
115 | Wire.beginTransmission(AR1010_ADDRESS); // START condition
116 | Wire.send(address);
117 |
118 | Wire.send(uint8_t((data & 0xFF00) >> 8));
119 | Wire.send(uint8_t(data & 0x00FF));
120 |
121 | Wire.endTransmission();
122 | }
123 |
124 | // Read method ============================================================
125 | uint16_t AR1010::readFromRegister(uint8_t address)
126 | {
127 | uint8_t receive_msb = 0, receive_lsb = 0;
128 | uint16_t received_data;
129 |
130 | // Establish connection, select receipt address
131 | Wire.beginTransmission(AR1010_ADDRESS);
132 | Wire.send(address);
133 | Wire.endTransmission();
134 |
135 | // Request two data bytes
136 | Wire.requestFrom(AR1010_ADDRESS, 2);
137 |
138 | // Fill variables when ready
139 | while(Wire.available())
140 | {
141 | receive_msb = Wire.receive();
142 | receive_lsb = Wire.receive();
143 | }
144 |
145 | // Reconstitute 2-byte register into uint16_t
146 | received_data = (receive_msb << 8) + receive_lsb;
147 |
148 | return received_data;
149 | }
150 |
151 |
152 | // Other methods ----------------------------------------------------------
153 | // Initialise AR1010 - fill all writeable registers =======================
154 | void AR1010::initialise(uint16_t *customRegisters)
155 | {
156 | // customRegisters set as NULL by default
157 |
158 | // Write registers 1-17 -----------------------------------------------
159 | for(uint8_t i = 1; i < 18; i++)
160 | {
161 | if(customRegisters == NULL)
162 | writeToRegister(i, register_init[i]);
163 | else
164 | writeToRegister(i, customRegisters[i]);
165 | }
166 |
167 |
168 | // Following 1-17 write register 0, ---------------------------------
169 | if(customRegisters == NULL)
170 | writeToRegister(0, register_init[0]);
171 | else
172 | writeToRegister(0, customRegisters[0]);
173 | }
174 |
175 |
176 | // Set seek threshold =================================================================
177 | void AR1010::setSeekThreshold(uint8_t threshold)
178 | {
179 | uint16_t temp = readFromRegister(3) & 0xFF80; // Get register data and clear affected bits (D6-D0)
180 | writeToRegister(3, temp | threshold); // Set threshold value and write back to register
181 | }
182 |
183 |
184 | // Set radio frequency ================================================================
185 | void AR1010::setFrequency(uint16_t frequency)
186 | {
187 | uint16_t register2, channel = frequency - 690;
188 |
189 | // Correct out of lower range
190 | if(channel < 185)
191 | channel = 185;
192 | else if(channel > 390)
193 | channel = 390;
194 |
195 | setBitInRegister(tune_bit[0], tune_bit[1], 0); // Set tune bit
196 |
197 | // Set radio channel
198 | register2 = readFromRegister(2) & CHAN_MASK;
199 | register2 |= channel;
200 | writeToRegister(2, register2);
201 |
202 | setBitInRegister(tune_bit[0], tune_bit[1], 1); // Set tune bit
203 | }
204 |
205 | // Set volume using the defined volume values =========================================
206 | void AR1010::setVolume(uint8_t volume)
207 | {
208 | // Put volume value in range 0 - 18
209 | uint8_t temp_vol = volume;
210 |
211 | if(temp_vol < 0)
212 | temp_vol = 0;
213 | else if(temp_vol > 18)
214 | temp_vol = 18;
215 |
216 | // Volume values are held in registers 3 (D7-10) and 14 (D12-15)
217 | uint16_t register3, register14;
218 | uint8_t volume_setting = volume_map[temp_vol];
219 |
220 | register3 = readFromRegister(3) & 0xF87F; // Zero the bits to change (D7-10)
221 | register3 |= ((volume_setting & 0x0F) << 7); // Place 4 LSBs of volume at D7-10
222 |
223 | register14 = readFromRegister(14) & 0x0FFF; // Zero the bits to change (D12-15)
224 | register14 |= ((volume_setting & 0xF0) << 8); // Place 4 MSBs of volume at D12-15
225 |
226 | writeToRegister(3, register3);
227 | writeToRegister(14, register14);
228 | }
229 |
230 | // Set the hardmute function ==========================================================
231 | void AR1010::setHardmute(bool hmute)
232 | {
233 | setBitInRegister(hardmute_bit[0], hardmute_bit[1], hmute);
234 | }
235 |
236 | // Set the softmute function ==========================================================
237 | void AR1010::setSoftmute(bool smute)
238 | {
239 | setBitInRegister(softmute_bit[0], softmute_bit[1], smute);
240 | }
241 |
242 |
243 | // Get current channel ================================================================
244 | uint16_t AR1010::frequency()
245 | {
246 | return(((readFromRegister(ADDR_STATUS) & MASK_READCHAN) >> SHIFT_READCHAN) + 690);
247 | }
248 |
249 |
250 | // Seek method ============================================================
251 | uint16_t AR1010::seek(char direction)
252 | {
253 | /*
254 | PSEUDO-CODE FROM PROGRAMMING GUIDE
255 | 1 Set hmute Bit
256 | 2 Clear TUNE Bit
257 | 3 Set CHAN Bits
258 | 4 Clear SEEK Bit
259 | 5 Set SEEKUP/SPACE/BAND/SEEKTH Bits
260 | 6 Enable SEEK Bit
261 | 7 Wait STC flag (Seek/Tune Complete, in “Status” register)
262 | 8 If SF then tune with AutoHiLo
263 | 9 Clear hmute Bit
264 | 10 Update Functions (optional, but remember to update CHAN with the seek in READCHAN before next seek)
265 | */
266 |
267 | uint16_t temp = 0, curChannel;
268 |
269 | // 1 May put in later
270 |
271 | // 2 Unset tune bit ------------------------------------------------------
272 | setBitInRegister(tune_bit[0], tune_bit[1], 0);
273 |
274 | // 3 is not required - no override required
275 |
276 | // 4 Unset seek bit ------------------------------------------------------
277 | setBitInRegister(seek_bit[0], seek_bit[1], 0);
278 |
279 | // 5 Seek attributes - can be set by other functions ---------------------
280 | setSeekDirection(direction);
281 |
282 | // 6 Set seek bit to enable seek -----------------------------------------
283 | setBitInRegister(seek_bit[0], seek_bit[1], 1);
284 |
285 | // 7 Wait for tune to stabilize (STC flag)
286 | while(temp == 0)
287 | temp = readFromRegister(ADDR_STATUS) & 0x0020;
288 |
289 | // 8 Check if tune was successful, tune with Auto Hi Lo if not
290 | temp = readFromRegister(ADDR_STATUS) & 0x0010;
291 |
292 | if(temp != 0)
293 | tuneWithAutoHiLo();
294 |
295 | // 9 May put in later
296 |
297 | // 10 Update CHAN from result (READCHAN) ------------------------------------
298 | curChannel = frequency() - 690;
299 | temp = readFromRegister(2) & CHAN_MASK;
300 | temp |= curChannel;
301 | writeToRegister(2, temp);
302 |
303 | return frequency();
304 | }
305 |
306 |
307 | // PRIVATE METHODS -------------------------------------------------------
308 | // Set one bit of a given register =======================================
309 | void AR1010::setBitInRegister(uint8_t address, uint8_t bit, bool bitState)
310 | {
311 | uint16_t temp;
312 |
313 | // Use bitState to decide which masking to use (to 1 or to 0)
314 | if(bitState)
315 | temp = readFromRegister(address) | (1 << bit);
316 | else
317 | temp = readFromRegister(address) & ~(1 << bit);
318 |
319 | writeToRegister(address, temp);
320 | }
321 |
322 |
323 | // Set seek direction =================================================================
324 | void AR1010::setSeekDirection(char direction)
325 | {
326 | // Change the direction of the seek function: 'u' - up, 'd' - down
327 | if(direction == 'd')
328 | setBitInRegister(seekup_bit[0], seekup_bit[1], 0);
329 | else if(direction == 'u')
330 | setBitInRegister(seekup_bit[0], seekup_bit[1], 1);
331 | }
332 |
333 |
334 | // Read low-side or high-side LO injection data =======================================
335 | uint8_t AR1010::readLOInjection(bool loHi)
336 | {
337 | /* PSEUDO-CODE FOR READING LO/HI INJECTION
338 | 1. Set R11 (clear D15, clear D0/D2)
339 | 2. Enable TUNE Bit
340 | 3. Wait STC flag (Seek/Tune Complete, in “Status” register)
341 | 4. Get RSSI
342 | 5. Clear TUNE Bit
343 | 6. Return RSSI
344 | */
345 |
346 | uint16_t temp = 0;
347 | uint8_t rssi_val = 0;
348 |
349 | // 1. Set R11 - D15, D2-D0 - clear for low-side, set for high-side
350 | if(loHi)
351 | temp = readFromRegister(11) | ~(HILO_MASK);
352 | else
353 | temp = readFromRegister(11) & HILO_MASK;
354 |
355 | writeToRegister(11, temp);
356 |
357 | // 2. Set tune bit -----------------------------
358 | setBitInRegister(tune_bit[0], tune_bit[1], 1);
359 |
360 | // 3. Wait for STC flag to stabilise -----------
361 | while(temp == 0)
362 | temp = readFromRegister(ADDR_STATUS) & 0x0020;
363 |
364 | // 4. Get RSSI value (R0x12, D9-D15)
365 | rssi_val = (readFromRegister(RSSI_ADDR) & 0xFE00) >> 9;
366 |
367 | // 5. Clear tune bit -----------------------------
368 | setBitInRegister(tune_bit[0], tune_bit[1], 0);
369 |
370 | return rssi_val;
371 | }
372 |
373 | // Tune with auto high-side/low-side injection ========================================
374 | void AR1010::tuneWithAutoHiLo()
375 | {
376 | // * A WORK IN PROGRESS!! *
377 |
378 | /* PSEUDO-CODE from programming guide
379 | (1) Set hmute Bit
380 | (2) Clear TUNE Bit
381 | (3) Clear SEEK Bit
382 | (4) Set BAND/SPACE/CHAN Bits
383 | (5) Read Low-side LO Injection
384 | 1. Set R11 ( clear D15, clear D0/D2 )
385 | 2. Enable TUNE Bit
386 | 3. Wait STC flag (Seek/Tune Complete, in “Status” register)
387 | 4. Get RSSI (RSSI1)
388 | 5. Clear TUNE Bit
389 | (6) Read High-side LO Injection
390 | 1. Set R11( set D15, set D0/D2 )
391 | 2. Enable TUNE Bit
392 | 3. Wait STC flag (Seek/Tune Complete, in “Status” register)
393 | 4. Get RSSI (RSSI2)
394 | 5. Clear TUNE Bit
395 | (7) Compare Hi/Lo Side Signal Strength
396 | 1. If (RSSI2 > RSSI1) Set R11( clear D15, set D0/D2), else Set R11( set D15, clear D0/D2 )
397 | (8) Enable TUNE Bit
398 | (9) Wait STC flag (Seek/Tune Complete, in “Status” register)
399 | (10) Clear hmute Bit
400 | (11) Update Functions (optional)
401 | */
402 |
403 | uint8_t rssi_lo, rssi_hi;
404 | uint16_t temp = 0, curChannel;
405 |
406 | // 1. Set hardware mute
407 |
408 | // 2. Clear tune bit ------------------------------------------------------
409 | setBitInRegister(tune_bit[0], tune_bit[1], 0);
410 |
411 | // 3. Clear seek bit ------------------------------------------------------
412 | setBitInRegister(seek_bit[0], seek_bit[1], 0);
413 |
414 | // 4. Set CHAN from READCHAN ----------------------------------------------
415 | curChannel = frequency() - 690;
416 | temp = readFromRegister(2) & CHAN_MASK;
417 | temp |= curChannel;
418 | writeToRegister(2, temp);
419 |
420 | // 5. Read low-side LO injection ------------------------------------------
421 | rssi_lo = readLOInjection(0);
422 |
423 | // 6. Read high-side LO injection -----------------------------------------
424 | rssi_hi = readLOInjection(1);
425 |
426 | // 7. Compare signal strength, set bits accordingly -----------------------
427 | if(rssi_hi > rssi_lo)
428 | {
429 | // Set D0 and D2, clear D15 ----------------------------
430 | setBitInRegister(hiloctrl1_bit[0], hiloctrl1_bit[1], 1);
431 | setBitInRegister(hiloctrl2_bit[0], hiloctrl2_bit[1], 1);
432 | setBitInRegister(hiloside_bit[0], hiloside_bit[1], 0);
433 | }
434 | else
435 | {
436 | // Clear D0 and D2, set D15 ----------------------------
437 | setBitInRegister(hiloctrl1_bit[0], hiloctrl1_bit[1], 0);
438 | setBitInRegister(hiloctrl2_bit[0], hiloctrl2_bit[1], 0);
439 | setBitInRegister(hiloside_bit[0], hiloside_bit[1], 1);
440 | }
441 |
442 | // 8. Enable tune bit -----------------------------------------------------
443 | setBitInRegister(tune_bit[0], tune_bit[1], 1);
444 |
445 | // 9. Wait for STC flag to stabilise --------------------------------------
446 | while(temp == 0)
447 | temp = readFromRegister(ADDR_STATUS) & 0x0020;
448 |
449 | // 10. Clear hardware mute
450 | }
--------------------------------------------------------------------------------