├── 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 | } --------------------------------------------------------------------------------