├── Car-Radio-module-with-main-chip-TEF6686HN-F8602-Tuner-TDQ-230V-AM-FM-Digital-Tuning-Car.jpg ├── README.md ├── TEF6686_1602i2c_v2x ├── TEF6686.cpp ├── TEF6686.h ├── TEF6686_1602i2c_v2x.ino ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h └── Tuner_Patch_Lithio_V102_p209.h ├── TEF6686_1602i2c_v3x ├── TEF6686.cpp ├── TEF6686.h ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h ├── radio_i2c_LCD3ax.ino ├── sketch_in_on _the_way.txt └── test.txt ├── TEF6686_1602i2c_v4 ├── TEF6686.cpp ├── TEF6686.h ├── TEF6686_1602i2c_v4.ino ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h └── read.me ├── TEF6686_1602i2c_v5 ├── TEF6686.cpp ├── TEF6686.h ├── TEF6686_1602i2c_v5.ino ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h └── new.txt ├── TEF6686_1602i2c_v6beta ├── TEF6686.cpp ├── TEF6686.h ├── TEF6686_1602i2c_v6beta.ino ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h └── v6beta.txt ├── TEF6686_Mega_LCD2004_i2c.png ├── TEF6686_bestpractice.png ├── TEF6686_radio_rev2.brd ├── radio_i2c_LCD3ax1 ├── TEF6686.cpp ├── TEF6686.h ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h ├── radio_i2c_LCD3ax1.ino └── read,me ├── radio_serialLCD2 ├── TEF6686.cpp ├── TEF6686.h ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h ├── radio_serialLCD2.ino └── test.txt ├── radio_serialLCD3a ├── TEF6686.cpp ├── TEF6686.h ├── Tuner_Api.cpp ├── Tuner_Api.h ├── Tuner_Drv_Lithio.cpp ├── Tuner_Drv_Lithio.h ├── Tuner_Interface.cpp ├── Tuner_Interface.h ├── Tuner_Patch_Lithio_V102_p209.h ├── radio_serialLCD3a.ino └── test.txt ├── radio_stailus_scroll.ino ├── tef6686_rds_stailus.ino ├── tef6686_v3_LUXYFM.jpg └── th0Dsgr.png /Car-Radio-module-with-main-chip-TEF6686HN-F8602-Tuner-TDQ-230V-AM-FM-Digital-Tuning-Car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tehniq3/TEF6686/a88e8937188dedbab6ab5d574bf41f35a68fbcbe/Car-Radio-module-with-main-chip-TEF6686HN-F8602-Tuner-TDQ-230V-AM-FM-Digital-Tuning-Car.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TEF6686 2 | it use info from https://github.com/makserge/tef6686_radio and https://github.com/stailus/tef6686_rds 3 | 4 | my articles: 5 | - https://nicuflorica.blogspot.com/2020/02/radio-cu-tef6686.html 6 | 7 | - https://nicuflorica.blogspot.com/2020/03/radio-cu-tef6686-si-stm32f103.html 8 | 9 | - https://nicuflorica.blogspot.com/2020/03/radio-am-fm-rds-cu-tef6686-si-stm32f103.html 10 | 11 | - https://nicuflorica.blogspot.com/2020/07/radio-fm-rds-cu-tef6686-si-arduino-nano.html 12 | 13 | ![TEF6686_v3_LUXYFM](https://github.com/tehniq3/TEF6686/blob/master/tef6686_v3_LUXYFM.jpg) 14 | 15 | ![schematic](https://github.com/tehniq3/TEF6686/blob/master/TEF6686_Mega_LCD2004_i2c.png) 16 | 17 | another article (for STM32F103): https://nicuflorica.blogspot.com/2020/03/radio-cu-tef6686-si-stm32f103.html 18 | 19 | ![TEF6686 STM32F103](https://1.bp.blogspot.com/-SKwZ6mT2DU4/XnHXvQXMkEI/AAAAAAAAbk8/D959NTBnklUSlKTTBVhdSl23CuxfimdcwCLcBGAsYHQ/s1600/radioTEF6686_01.jpg) 20 | 21 | ![cu STM32](https://1.bp.blogspot.com/-aV1aZunmwKQ/XnIbLJMcXWI/AAAAAAAAbnQ/1Mp0ky_ybMA32WvERR5HgH1XBJeIZ6UzQCLcBGAsYHQ/s1600/TEF6686_STM32F103_i2c_LCD1602.png) 22 | 23 | ![am](https://1.bp.blogspot.com/-L7R7wa8eJe8/XnTErJqBG7I/AAAAAAAAbpc/pTJmpoeyu18sWKzFB30b8WGmDxI27HwTgCLcBGAsYHQ/s1600/AMFMRDSradio_MW3.jpg) 24 | 25 | ![AM / FM RDS Radio with TEF6686](https://1.bp.blogspot.com/--Drlm0aD6NE/XnTAuIm-K6I/AAAAAAAAbnw/CoE1fOShrTQnzb2fJdau-WcYlOyrG2_GQCLcBGAsYHQ/s1600/stm32f103c8t6_schematic2.png) 26 | 27 | ![TEG6686 and Nano](https://1.bp.blogspot.com/-y-c8xv8Fw0I/XwHLj5Bm2wI/AAAAAAAAc8g/yD8wYbmyjT8MwsJJ-EwFjQhw96Iry21jgCLcBGAsYHQ/s1600/TEF6686_radio_RDS.png) 28 | 29 | ![TEF6686_nano-real](https://1.bp.blogspot.com/-I-hsW3VHX18/XxGvF7bOW-I/AAAAAAAAdAg/v6UCDM2aIC0RAFIpjNmmM58glPEvXzHWQCLcBGAsYHQ/s1600/radioimpuls0.jpg) 30 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v2x/TEF6686.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | 3 | const char* ptyLUT[51] = { 4 | " None ", 5 | " News ", 6 | " Information ", 7 | " Sports ", 8 | " Talk ", 9 | " Rock ", 10 | " Classic Rock ", 11 | " Adult Hits ", 12 | " Soft Rock ", 13 | " Top 40 ", 14 | " Country ", 15 | " Oldies ", 16 | " Soft ", 17 | " Nostalgia ", 18 | " Jazz ", 19 | " Classical ", 20 | "Rhythm and Blues", 21 | " Soft R & B ", 22 | "Foreign Language", 23 | "Religious Music ", 24 | " Religious Talk ", 25 | " Personality ", 26 | " Public ", 27 | " College ", 28 | " Reserved -24- ", 29 | " Reserved -25- ", 30 | " Reserved -26- ", 31 | " Reserved -27- ", 32 | " Reserved -28- ", 33 | " Weather ", 34 | " Emergency Test ", 35 | " !!!ALERT!!! ", 36 | "Current Affairs ", 37 | " Education ", 38 | " Drama ", 39 | " Cultures ", 40 | " Science ", 41 | " Varied Speech ", 42 | " Easy Listening ", 43 | " Light Classics ", 44 | "Serious Classics", 45 | " Other Music ", 46 | " Finance ", 47 | "Children's Progs", 48 | " Social Affairs ", 49 | " Phone In ", 50 | "Travel & Touring", 51 | "Leisure & Hobby ", 52 | " National Music ", 53 | " Folk Music ", 54 | " Documentary "}; 55 | 56 | TEF6686::TEF6686() { 57 | } 58 | 59 | uint8_t TEF6686::init() { 60 | uint8_t result; 61 | uint8_t counter = 0; 62 | uint8_t status; 63 | 64 | Tuner_I2C_Init(); 65 | 66 | delay(5); 67 | while (true) { 68 | result = devTEF668x_APPL_Get_Operation_Status(&status); 69 | if (result == 1) { 70 | Tuner_Init(); 71 | powerOff(); 72 | return 1; //Ok 73 | } 74 | else if (++counter > 50) { 75 | return 2; //Doesn't exist 76 | } 77 | else { 78 | delay(5); 79 | return 0; //Busy 80 | } 81 | } 82 | } 83 | 84 | void TEF6686::powerOn() { 85 | devTEF668x_APPL_Set_OperationMode(0); 86 | } 87 | 88 | void TEF6686::powerOff() { 89 | devTEF668x_APPL_Set_OperationMode(1); 90 | } 91 | 92 | void TEF6686::setFrequency(uint16_t frequency) { 93 | Radio_SetFreq(Radio_PRESETMODE, FM1_BAND, frequency); 94 | } 95 | 96 | uint16_t TEF6686::getFrequency() { 97 | return Radio_GetCurrentFreq(); 98 | } 99 | 100 | uint16_t TEF6686::getLevel() { 101 | return Radio_Get_Level(1); 102 | } 103 | 104 | uint8_t TEF6686::getStereoStatus() { 105 | return Radio_CheckStereo(); 106 | } 107 | 108 | uint16_t TEF6686::seekUp() { 109 | return seek(1); 110 | } 111 | 112 | uint16_t TEF6686::seekDown() { 113 | return seek(0); 114 | } 115 | 116 | uint16_t TEF6686::tuneUp() { 117 | return tune(1); 118 | } 119 | 120 | uint16_t TEF6686::tuneDown() { 121 | return tune(0); 122 | } 123 | 124 | void TEF6686::setVolume(uint16_t volume) { 125 | devTEF668x_Audio_Set_Volume(volume); 126 | } 127 | 128 | void TEF6686::setMute() { 129 | devTEF668x_Audio_Set_Mute(1); 130 | } 131 | 132 | void TEF6686::setUnMute() { 133 | devTEF668x_Audio_Set_Mute(0); 134 | } 135 | 136 | uint8_t TEF6686::readRDS() { 137 | char status; 138 | uint8_t rdsBHigh, rdsBLow, rdsCHigh, rdsCLow, rdsDHigh, isReady, rdsDLow; 139 | 140 | uint16_t rdsStat, rdsA, rdsB, rdsC, rdsD, rdsErr; 141 | uint16_t result = devTEF668x_Radio_Get_RDS_Data(1, &rdsStat, &rdsA, &rdsB, &rdsC, &rdsD, &rdsErr); 142 | 143 | if (!(result && (rdsB != 0x0) && ((rdsStat & 0x8000) != 0x0) && ((rdsErr & 0x0a00) == 0x0))) { 144 | return isReady; 145 | } 146 | 147 | rdsBHigh = (uint8_t)(rdsB >> 8); 148 | rdsBLow = (uint8_t)rdsB; 149 | rdsCHigh = (uint8_t)(rdsC >> 8); 150 | rdsCLow = (uint8_t)rdsC; 151 | rdsDHigh = (uint8_t)(rdsD >> 8); 152 | rdsDLow = (uint8_t)rdsD; 153 | 154 | uint8_t programType = ((rdsBHigh & 3) << 3) | ((rdsBLow >> 5) & 7); 155 | strcpy(rdsProgramType, (programType >= 0 && programType < 32) ? ptyLUT[programType] : " PTY ERROR "); 156 | 157 | uint8_t type = (rdsBHigh >> 4) & 15; 158 | uint8_t version = bitRead(rdsBHigh, 4); 159 | 160 | // Groups 0A & 0B 161 | // Basic tuning and switching information only 162 | if (type == 0) { 163 | uint8_t address = rdsBLow & 3; 164 | // Groups 0A & 0B: to extract PS segment we need blocks 1 and 3 165 | if (address >= 0 && address <= 3) { 166 | if (rdsDHigh != '\0') { 167 | rdsProgramService[address * 2] = rdsDHigh; 168 | } 169 | if (rdsDLow != '\0') { 170 | rdsProgramService[address * 2 + 1] = rdsDLow; 171 | } 172 | isReady = (address == 3) ? 1 : 0; 173 | } 174 | rdsFormatString(rdsProgramService, 8); 175 | } 176 | // Groups 2A & 2B 177 | // Radio Text 178 | else if (type == 2) { 179 | uint16_t addressRT = rdsBLow & 15; 180 | uint8_t ab = bitRead(rdsBLow, 4); 181 | uint8_t cr = 0; 182 | uint8_t len = 64; 183 | if (version == 0) { 184 | if (addressRT >= 0 && addressRT <= 15) { 185 | if (rdsCHigh != 0x0D) { 186 | rdsRadioText[addressRT*4] = rdsCHigh; 187 | } 188 | else { 189 | len = addressRT * 4; 190 | cr = 1; 191 | } 192 | if (rdsCLow != 0x0D) { 193 | rdsRadioText[addressRT * 4 + 1] = rdsCLow; 194 | } 195 | else { 196 | len = addressRT * 4 + 1; 197 | cr = 1; 198 | } 199 | if (rdsDHigh != 0x0D) { 200 | rdsRadioText[addressRT * 4 + 2] = rdsDHigh; 201 | } 202 | else { 203 | len = addressRT * 4 + 2; 204 | cr = 1; 205 | } 206 | if (rdsDLow != 0x0D) { 207 | rdsRadioText[addressRT * 4 + 3] = rdsDLow; 208 | } 209 | else { 210 | len = addressRT * 4 + 3; 211 | cr = 1; 212 | } 213 | } 214 | } 215 | else { 216 | if (addressRT >= 0 && addressRT <= 7) { 217 | if (rdsDHigh != '\0') { 218 | rdsRadioText[addressRT * 2] = rdsDHigh; 219 | } 220 | if (rdsDLow != '\0') { 221 | rdsRadioText[addressRT * 2 + 1] = rdsDLow; 222 | } 223 | } 224 | } 225 | if (cr) { 226 | for (uint8_t i = len; i < 64; i++) { 227 | rdsRadioText[i] = ' '; 228 | } 229 | } 230 | if (ab != rdsAb) { 231 | for (uint8_t i = 0; i < 64; i++) { 232 | rdsRadioText[i] = ' '; 233 | } 234 | rdsRadioText[64] = '\0'; 235 | isRdsNewRadioText = 1; 236 | } 237 | else { 238 | isRdsNewRadioText = 0; 239 | } 240 | rdsAb = ab; 241 | rdsFormatString(rdsRadioText, 64); 242 | } 243 | return isReady; 244 | } 245 | 246 | void TEF6686::getRDS(RdsInfo* rdsInfo) { 247 | strcpy(rdsInfo->programType, rdsProgramType); 248 | strcpy(rdsInfo->programService, rdsProgramService); 249 | strcpy(rdsInfo->radioText, rdsRadioText); 250 | } 251 | 252 | void TEF6686::rdsFormatString(char* str, uint16_t length) { 253 | for (uint16_t i = 0; i < length; i++) { 254 | if ((str[i] != 0 && str[i] < 32) || str[i] > 126 ) { 255 | str[i] = ' '; 256 | } 257 | } 258 | } 259 | 260 | uint16_t TEF6686::seek(uint8_t up) { 261 | uint16_t mode = 20; 262 | uint16_t startFrequency = Radio_GetCurrentFreq(); 263 | 264 | while (true) { 265 | switch(mode){ 266 | case 20: 267 | Radio_ChangeFreqOneStep(up); 268 | Radio_SetFreq(Radio_SEARCHMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 269 | 270 | mode = 30; 271 | Radio_CheckStationInit(); 272 | Radio_ClearCurrentStation(); 273 | 274 | break; 275 | 276 | case 30: 277 | delay(20); 278 | Radio_CheckStation(); 279 | if (Radio_CheckStationStatus() >= NO_STATION) { 280 | mode = 40; 281 | } 282 | 283 | break; 284 | 285 | case 40: 286 | if (Radio_CheckStationStatus() == NO_STATION) { 287 | mode = (startFrequency == Radio_GetCurrentFreq()) ? 50 : 20; 288 | } 289 | else if (Radio_CheckStationStatus() == PRESENT_STATION) { 290 | mode = 50; 291 | } 292 | 293 | break; 294 | 295 | case 50: 296 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 297 | return Radio_GetCurrentFreq(); 298 | } 299 | } 300 | return 0; 301 | } 302 | 303 | uint16_t TEF6686::seekSync(uint8_t up) { 304 | if (seekMode == 0) { 305 | seekMode = 20; 306 | seekStartFrequency = Radio_GetCurrentFreq(); 307 | } 308 | switch(seekMode) { 309 | case 20: 310 | Radio_ChangeFreqOneStep(up); 311 | Radio_SetFreq(Radio_SEARCHMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 312 | 313 | seekMode = 30; 314 | Radio_CheckStationInit(); 315 | Radio_ClearCurrentStation(); 316 | 317 | return 0; 318 | 319 | case 30: 320 | delay(20); 321 | Radio_CheckStation(); 322 | if (Radio_CheckStationStatus() >= NO_STATION) { 323 | seekMode = 40; 324 | } 325 | 326 | return 0; 327 | 328 | case 40: 329 | if (Radio_CheckStationStatus() == NO_STATION) { 330 | seekMode = (seekStartFrequency == Radio_GetCurrentFreq()) ? 50 : 20; 331 | } 332 | else if (Radio_CheckStationStatus() == PRESENT_STATION) { 333 | seekMode = 50; 334 | } 335 | 336 | return 0; 337 | 338 | case 50: 339 | seekMode = 0; 340 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 341 | return 1; 342 | } 343 | return 0; 344 | } 345 | 346 | uint16_t TEF6686::tune(uint8_t up) { 347 | Radio_ChangeFreqOneStep(up); 348 | 349 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 350 | Radio_ClearCurrentStation(); 351 | return Radio_GetCurrentFreq(); 352 | } 353 | 354 | 355 | 356 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v2x/TEF6686.h: -------------------------------------------------------------------------------- 1 | #ifndef TEF6686_h 2 | #define TEF6686_h 3 | 4 | #include 5 | 6 | #include "Arduino.h" 7 | #include "Tuner_Api.h" 8 | #include "Tuner_Drv_Lithio.h" 9 | #include "Tuner_Interface.h" 10 | 11 | #define I2C_PORT 2 12 | #define I2C_ADDR 0x64 13 | 14 | struct RdsInfo { 15 | char programType[17]; 16 | char programService[9]; 17 | char radioText[65]; 18 | bool newRadioText; 19 | }; 20 | 21 | class TEF6686 { 22 | public: 23 | TEF6686(); 24 | uint8_t init(); 25 | void powerOn(); // call in setup 26 | void powerOff(); 27 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 28 | uint16_t getFrequency(); // returns the current frequency 29 | uint16_t getLevel(); 30 | uint8_t getStereoStatus(); 31 | uint16_t seekUp(); // returns the tuned frequency or 0 32 | uint16_t seekDown(); // returns the tuned frequency or 0 33 | uint16_t seekSync(uint8_t up); // returns 1 if seek was completed and 0 if seek in progress 34 | uint16_t tuneUp(); // returns the tuned frequency or 0 35 | uint16_t tuneDown(); // returns the tuned frequency or 0 36 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 37 | void setMute(); 38 | void setUnMute(); 39 | uint8_t readRDS(); 40 | void getRDS(RdsInfo* rdsInfo); 41 | 42 | private: 43 | uint16_t seek(uint8_t up); 44 | uint16_t tune(uint8_t up); 45 | void rdsFormatString(char* str, uint16_t length); 46 | 47 | char rdsRadioText[65]; 48 | char rdsProgramService[9]; 49 | uint8_t rdsAb; 50 | char rdsProgramType[17]; 51 | uint8_t isRdsNewRadioText; 52 | 53 | uint16_t seekMode; 54 | uint16_t seekStartFrequency; 55 | }; 56 | 57 | #endif 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v2x/TEF6686_1602i2c_v2x.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * original sketch from https://github.com/makserge/tef6686_radio 3 | * adapted for i2c display and phical buttons by Nicu FLORICA (niq_ro) 4 | * http://www.arduinotehniq.com/ 5 | * 6 | */ 7 | 8 | #include "TEF6686.h" 9 | 10 | #include 11 | #include // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library 12 | // or an old version used by me, stored in https://github.com/tehniq3/used_library/tree/master/LiquidCrystal_I2C 13 | LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display 14 | 15 | int frequency; 16 | int volume; 17 | int volume2; 18 | byte plus = 0; 19 | 20 | uint8_t isRDSReady; 21 | 22 | char programTypePrevious[17] = " "; 23 | char programServicePrevious[9]; 24 | char radioTextPrevious[65]; 25 | char radioTextRezumat[20]; 26 | 27 | boolean isFmSeekMode; 28 | boolean isFmSeekUp; 29 | 30 | TEF6686 radio; 31 | RdsInfo rdsInfo; 32 | 33 | #define volumminus 4 34 | #define volumplus 5 35 | #define cautareplus 6 36 | #define cautareminus 7 37 | 38 | 39 | void setup() { 40 | pinMode(volumminus, INPUT); 41 | pinMode(volumplus, INPUT); 42 | pinMode(cautareminus, INPUT); 43 | pinMode(cautareplus, INPUT); 44 | digitalWrite(volumminus, HIGH); 45 | digitalWrite(volumplus, HIGH); 46 | digitalWrite(cautareminus, HIGH); 47 | digitalWrite(cautareplus, HIGH); 48 | 49 | lcd.begin(); // initialize the LCD 50 | // Print a message to the LCD. 51 | lcd.backlight(); 52 | lcd.clear(); 53 | // Print a logo message to the LCD. 54 | lcd.setCursor(0,0); 55 | lcd.print(" TEF6686 radio v.2bx"); 56 | lcd.setCursor(0,1); 57 | lcd.print("github.com/makserge "); 58 | lcd.setCursor(0,2); 59 | lcd.print(" updated by niq_ro "); 60 | lcd.setCursor(0,3); 61 | lcd.print(" github.com/tehniq3 "); 62 | delay (3000); 63 | lcd.clear(); 64 | 65 | Serial.begin(115200); 66 | while (!Serial); 67 | Serial.println("TEF6686 radio"); 68 | radio.init(); 69 | radio.powerOn(); 70 | radio.setFrequency(9200); 71 | frequency = radio.getFrequency(); 72 | displayInfo(); 73 | } 74 | 75 | void loop() { 76 | readRds(); 77 | // showFmSeek(); 78 | // displayInfo(); 79 | 80 | if (digitalRead(volumplus) == LOW) 81 | { 82 | volume += 4; 83 | if (volume >= 24) volume = 24; 84 | radio.setVolume(volume); 85 | displayInfo(); 86 | delay(250); 87 | } 88 | if (digitalRead(volumminus) == LOW) 89 | { 90 | volume -= 4; 91 | if (volume < -60) volume = -60; 92 | radio.setVolume(volume); 93 | displayInfo(); 94 | delay(250); 95 | } 96 | if (digitalRead(cautareplus) == LOW) 97 | { 98 | frequency = radio.seekUp(); 99 | displayInfo(); 100 | delay(250); 101 | } 102 | if (digitalRead(cautareminus) == LOW) 103 | { 104 | frequency = radio.seekDown(); 105 | displayInfo(); 106 | delay(250); 107 | } 108 | 109 | if (Serial.available()) { 110 | char ch = Serial.read(); 111 | if (ch == 'm') { 112 | radio.setMute(); 113 | displayInfo(); 114 | } 115 | else if (ch == 'n') { 116 | radio.setUnMute(); 117 | displayInfo(); 118 | } 119 | else if (ch == 'p') { 120 | radio.powerOn(); 121 | displayInfo(); 122 | } 123 | else if (ch == 'o') { 124 | radio.powerOff(); 125 | displayInfo(); 126 | } 127 | else if (ch == 'u') { 128 | frequency = radio.seekUp(); 129 | lcd.clear(); 130 | displayInfo(); 131 | } 132 | else if (ch == 'd') { 133 | frequency = radio.seekDown(); 134 | lcd.clear(); 135 | displayInfo(); 136 | } 137 | else if (ch == 'c') { 138 | Serial.println("Seeking up"); 139 | isFmSeekMode = true; 140 | isFmSeekUp = true; 141 | } 142 | else if (ch == 'e') { 143 | Serial.println("Seeking down"); 144 | isFmSeekMode = true; 145 | isFmSeekUp = false; 146 | } 147 | else if (ch == '+') 148 | { 149 | volume += 4; 150 | if (volume >= 24) volume = 24; 151 | radio.setVolume(volume); 152 | // lcd.clear(); 153 | displayInfo(); 154 | } 155 | else if (ch == '-') 156 | { 157 | volume -= 4; 158 | if (volume < -60) volume = -60; 159 | radio.setVolume(volume); 160 | displayInfo(); 161 | } 162 | else if (ch == '8') 163 | { 164 | frequency = radio.tuneUp(); 165 | displayInfo(); 166 | } 167 | else if (ch == '2') 168 | { 169 | frequency = radio.tuneDown(); 170 | displayInfo(); 171 | } 172 | } 173 | } 174 | 175 | void readRds() { 176 | isRDSReady = radio.readRDS(); 177 | radio.getRDS(&rdsInfo); 178 | 179 | showPTY(); 180 | showPS(); 181 | showRadioText(); 182 | } 183 | 184 | void showPTY() { 185 | if ((isRDSReady == 1) && !strcmp(rdsInfo.programType, programTypePrevious, 16)) { 186 | Serial.print(rdsInfo.programType); 187 | strcpy(programTypePrevious, rdsInfo.programType); 188 | Serial.println(); 189 | if (programTypePrevious != " None ") 190 | { 191 | lcd.setCursor(0,3); 192 | lcd.print(" "); 193 | lcd.setCursor(0,3); 194 | //lcd.print(" "); 195 | lcd.print(rdsInfo.programType); 196 | } 197 | // lcd.print(strcpy(programTypePrevious, rdsInfo.programType)); 198 | } 199 | 200 | } 201 | 202 | void showPS() { 203 | if ((isRDSReady == 1) && (strlen(rdsInfo.programService) == 8) && !strcmp(rdsInfo.programService, programServicePrevious, 8)) { 204 | Serial.print("-=[ "); 205 | Serial.print(rdsInfo.programService); 206 | Serial.print(" ]=-"); 207 | strcpy(programServicePrevious, rdsInfo.programService); 208 | Serial.println(); 209 | lcd.setCursor(0,1); 210 | lcd.print(strcpy(programServicePrevious, rdsInfo.programService)); 211 | } 212 | } 213 | 214 | 215 | void showRadioText() { 216 | if ((isRDSReady == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 65)){ 217 | // if ((isRDSReady == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 20)){ 218 | Serial.println(rdsInfo.radioText); 219 | strcpy(radioTextPrevious, rdsInfo.radioText); 220 | lcd.setCursor(0,2); 221 | lcd.print(" "); 222 | for (int i = 0; i < 20; i++) 223 | { 224 | Serial.print(radioTextPrevious[i]); 225 | lcd.setCursor(i,2); 226 | lcd.print(radioTextPrevious[i]); 227 | } 228 | delay(500); 229 | for (int i = 20; i < 40; i++) 230 | { 231 | Serial.print(radioTextPrevious[i]); 232 | lcd.setCursor(i-20,3); 233 | lcd.print(radioTextPrevious[i]); 234 | } 235 | delay(500); 236 | Serial.println(); 237 | Serial.print("--> "); 238 | Serial.print(radioTextRezumat); 239 | Serial.println(); 240 | } 241 | } 242 | 243 | bool strcmp(char* str1, char* str2, int length) { 244 | for (int i = 0; i < length; i++) { 245 | if (str1[i] != str2[i]) { 246 | return false; 247 | } 248 | } 249 | return true; 250 | } 251 | 252 | void displayInfo() { 253 | delay(10); 254 | Serial.print("Frequency:"); 255 | Serial.print(frequency); 256 | Serial.print(" Volume:"); 257 | Serial.println(volume); 258 | Serial.print("Level:"); 259 | Serial.println(radio.getLevel() / 10); 260 | Serial.print("Stereo:"); 261 | Serial.println(radio.getStereoStatus()); 262 | lcd.clear(); 263 | lcd.setCursor(0, 0); 264 | if (frequency < 10000) lcd.print(" "); 265 | lcd.print(frequency/100); 266 | lcd.print(","); 267 | // lcd.print(frequency%100); 268 | lcd.print(frequency%100/10); // thanks to carkiller08 269 | lcd.print(frequency%10); 270 | lcd.print("MHz "); 271 | lcd.setCursor(10,0); 272 | lcd.print("vol."); 273 | if (volume > 0) 274 | { 275 | plus = 1; 276 | volume2 = volume; 277 | } 278 | else 279 | { 280 | plus = 0; 281 | volume2 = -volume; 282 | } 283 | if (volume2/10 == 0) 284 | lcd.print(" "); 285 | if (volume2 == 0) lcd.print(" "); 286 | else 287 | if (plus == 0) 288 | { 289 | lcd.print("-"); 290 | } 291 | else 292 | { 293 | lcd.print("+"); 294 | } 295 | lcd.print(volume2); 296 | lcd.print("dB "); 297 | lcd.setCursor(9,1); 298 | // lcd.print("level:"); 299 | if (radio.getLevel() < 100) 300 | lcd.print(" "); 301 | if (radio.getLevel() < 10) 302 | lcd.print(" "); 303 | lcd.print(radio.getLevel()); 304 | lcd.print("%"); 305 | lcd.setCursor(14,1); 306 | if (radio.getStereoStatus() == 1) 307 | lcd.print("STEREO"); 308 | else 309 | lcd.print(" "); 310 | 311 | } 312 | 313 | void showFmSeek() { 314 | if (isFmSeekMode) { 315 | if (radio.seekSync(isFmSeekUp)) { 316 | isFmSeekMode = false; 317 | Serial.println("Seek stopped"); 318 | // lcd.setCursor(3, 1); 319 | // lcd.print("Seek stopped"); 320 | frequency = radio.getFrequency(); 321 | displayInfo(); 322 | } 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v2x/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v2x/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | //TwoWire Wire2 (I2C_PORT, I2C_FAST_MODE); 5 | TwoWire Wire2; 6 | 7 | #define INIT_FLAG_TIMER 0xff 8 | #define INIT_FLAG_PATCH1 0xfe 9 | #define INIT_FLAG_PATCH2 0xfd 10 | 11 | static const unsigned char tuner_init_tab[] = { 12 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 13 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 14 | //Load Required Initialization(s).... 15 | 1, INIT_FLAG_PATCH1, 16 | 17 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 18 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 19 | //Load Required Initialization(s).... 20 | 1, INIT_FLAG_PATCH2, 21 | 22 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 23 | 3, 0x14,0x00,0x01,//Start Firmware.... 24 | 25 | //wait 50ms 26 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 27 | 28 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 29 | 30 | //Activate Device...(Idle state to Active state) 31 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 32 | //wait 100ms 33 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 34 | 35 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 36 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 37 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 38 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 39 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 40 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 41 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 42 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 43 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 44 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 45 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 46 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 47 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 48 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 49 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 57 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 58 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 59 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 60 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 61 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 62 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 63 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 64 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 65 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 66 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 67 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 68 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 69 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 70 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 71 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 72 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 73 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 74 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 75 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 76 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 77 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 78 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 79 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 80 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 81 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 82 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 83 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 84 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 85 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 86 | //Set the Audio and Application related API settings... 87 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 88 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 90 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 91 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 92 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 93 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 94 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 95 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 96 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 97 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 98 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 99 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 100 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 101 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 102 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 103 | }; 104 | 105 | //return 1 --> IIC sucess 106 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 107 | { 108 | uint16_t i; 109 | uint8_t r; 110 | //Serial.println(I2C_ADDR, HEX); 111 | //Serial.println("Send to I2C: "); 112 | Wire2.beginTransmission(I2C_ADDR); 113 | //Serial.println("beginTransmission"); 114 | for (i = 0; i < len; i++) { 115 | Wire2.write(buf[i]); 116 | //Serial.print(buf[i], HEX); 117 | //Serial.print(" "); 118 | } 119 | //Serial.println("Wire.write"); 120 | r = Wire2.endTransmission(); 121 | //Serial.println("Wire.endTransmission:"); 122 | //Serial.print(r); 123 | //Serial.println(); 124 | delay(1); 125 | return (r == 0) ? 1 : 0; 126 | } 127 | 128 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 129 | { 130 | uint16_t i; 131 | //Serial.println("\nRead from I2C: "); 132 | Wire2.requestFrom(I2C_ADDR, len); 133 | if (Wire2.available() == len) { 134 | for (i = 0; i < len; i++) { 135 | buf[i] = Wire2.read(); 136 | //Serial.print(buf[i], HEX); 137 | //Serial.print(" "); 138 | } 139 | //Serial.println(); 140 | return 1; 141 | } 142 | return 0; 143 | } 144 | 145 | void Tuner_WaitMs (uint16_t ms) 146 | { 147 | delay(ms); 148 | } 149 | //-------------------------------------------------------------------------------------------- 150 | 151 | 152 | //------------load patch and init parameters----------------- 153 | 154 | /* 155 | The transmission example below shows a data content of 12 words for every data transmission. 156 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 157 | */ 158 | #define TEF665X_SPLIT_SIZE 24 159 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 160 | { 161 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 162 | uint16_t i,len; 163 | uint16_t r; 164 | 165 | buf[0] = 0x1b; 166 | 167 | while(size) 168 | { 169 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 170 | size -= len; 171 | 172 | for(i=0;i= 100 2 | #include "Arduino.h" 3 | #else 4 | #include "WProgram.h" 5 | #endif 6 | 7 | 8 | #ifndef TEF6686_h 9 | #define TEF6686_h 10 | 11 | #include 12 | 13 | #include "Tuner_Api.h" 14 | #include "Tuner_Drv_Lithio.h" 15 | #include "Tuner_Interface.h" 16 | 17 | #define I2C_PORT 2 18 | #define I2C_ADDR 0x64 19 | #define I2C_FAST_MODE 0x2 20 | 21 | typedef struct RdsInfo { 22 | char programType[17]; 23 | char programService[9]; 24 | char programServiceUnsafe[9]; 25 | char programId[5]; 26 | char radioText[65]; 27 | bool newRadioText; 28 | }; 29 | 30 | class TEF6686 { 31 | public: 32 | TEF6686(); 33 | uint8_t init(); 34 | void powerOn(); // call in setup 35 | void powerOff(); 36 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 37 | uint16_t getFrequency(); // returns the current frequency 38 | uint16_t getLevel(); 39 | uint8_t getStereoStatus(); 40 | uint16_t seekUp(); // returns the tuned frequency or 0 41 | uint16_t seekDown(); // returns the tuned frequency or 0 42 | uint16_t tuneUp(); // returns the tuned frequency or 0 43 | uint16_t tuneDown(); // returns the tuned frequency or 0 44 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 45 | void setMute(); 46 | void setUnMute(); 47 | bool readRDS(); 48 | void getRDS(RdsInfo* rdsInfo); 49 | void clearRDS(); 50 | 51 | private: 52 | uint16_t seek(uint8_t up); 53 | uint16_t tune(uint8_t up); 54 | void rdsFormatString(char* str, uint16_t length); 55 | 56 | char rdsRadioText[65]; 57 | char rdsProgramService[9]; 58 | char rdsProgramServiceUnsafe[9]; 59 | char rdsProgramId[5]; 60 | uint8_t rdsAb; 61 | char rdsProgramType[17]; 62 | uint8_t isRdsNewRadioText; 63 | 64 | // 0: working with PS A, 1: working with PS B 65 | bool psAB; 66 | // first dimension: ps A, ps B, second dimension: PS characters 67 | char unsafePs[2][8]; 68 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 69 | uint32_t psErrors = 0xFFFFFFFF; 70 | // 4 bit groups: ps A, B blocks (0-3) is set 71 | uint8_t psCharIsSet = 0; 72 | // previous address (if prev address greater than current, change psAB status) 73 | uint8_t prevAddress = 3; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v3x/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v3x/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | TwoWire Wire2; 5 | 6 | #define INIT_FLAG_TIMER 0xff 7 | #define INIT_FLAG_PATCH1 0xfe 8 | #define INIT_FLAG_PATCH2 0xfd 9 | 10 | static const unsigned char tuner_init_tab[] = { 11 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 12 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 13 | //Load Required Initialization(s).... 14 | 1, INIT_FLAG_PATCH1, 15 | 16 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 17 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 18 | //Load Required Initialization(s).... 19 | 1, INIT_FLAG_PATCH2, 20 | 21 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 22 | 3, 0x14,0x00,0x01,//Start Firmware.... 23 | 24 | //wait 50ms 25 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 26 | 27 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 28 | 29 | //Activate Device...(Idle state to Active state) 30 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 31 | //wait 100ms 32 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 33 | 34 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 35 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 36 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 37 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 38 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 39 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 40 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 41 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 42 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 43 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 44 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 45 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 46 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 47 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 48 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 49 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 57 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 58 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 59 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 60 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 61 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 62 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 63 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 64 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 65 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 66 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 67 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 68 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 69 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 70 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 71 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 72 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 73 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 74 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 75 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 76 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 77 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 78 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 79 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 80 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 81 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 82 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 83 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 84 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 85 | //Set the Audio and Application related API settings... 86 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 87 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 88 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 90 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 91 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 92 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 93 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 94 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 95 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 96 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 97 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 98 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 99 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 100 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 101 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 102 | }; 103 | 104 | //return 1 --> IIC sucess 105 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 106 | { 107 | uint16_t i; 108 | uint8_t r; 109 | //Serial.println(I2C_ADDR, HEX); 110 | //Serial.println("Send to I2C: "); 111 | Wire2.beginTransmission(I2C_ADDR); 112 | //Serial.println("beginTransmission"); 113 | for (i = 0; i < len; i++) { 114 | Wire2.write(buf[i]); 115 | //Serial.print(buf[i], HEX); 116 | //Serial.print(" "); 117 | } 118 | //Serial.println("Wire.write"); 119 | r = Wire2.endTransmission(); 120 | //Serial.println("Wire.endTransmission:"); 121 | //Serial.print(r); 122 | //Serial.println(); 123 | delay(1); 124 | return (r == 0) ? 1 : 0; 125 | } 126 | 127 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 128 | { 129 | uint16_t i; 130 | //Serial.println("\nRead from I2C: "); 131 | Wire2.requestFrom(I2C_ADDR, len); 132 | if (Wire2.available() == len) { 133 | for (i = 0; i < len; i++) { 134 | buf[i] = Wire2.read(); 135 | //Serial.print(buf[i], HEX); 136 | //Serial.print(" "); 137 | } 138 | //Serial.println(); 139 | return 1; 140 | } 141 | return 0; 142 | } 143 | 144 | void Tuner_WaitMs (uint16_t ms) 145 | { 146 | delay(ms); 147 | } 148 | //-------------------------------------------------------------------------------------------- 149 | 150 | 151 | //------------load patch and init parameters----------------- 152 | 153 | /* 154 | The transmission example below shows a data content of 12 words for every data transmission. 155 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 156 | */ 157 | #define TEF665X_SPLIT_SIZE 24 158 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 159 | { 160 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 161 | uint16_t i,len; 162 | uint16_t r; 163 | 164 | buf[0] = 0x1b; 165 | 166 | while(size) 167 | { 168 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 169 | size -= len; 170 | 171 | for(i=0;i 8 | #include 9 | LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display 10 | 11 | #include "TEF6686.h" 12 | 13 | uint16_t frequency; 14 | int volume; 15 | int volume2; 16 | byte plus = 0; 17 | 18 | bool isRdsSync; 19 | ; 20 | 21 | char programTypePrevious[17] = " "; 22 | char programServicePrevious[9]; 23 | char programServiceUnsafePrevious[9]; 24 | char programIdPrevious[4]; 25 | char radioTextPrevious[65]; 26 | 27 | TEF6686 radio; 28 | RdsInfo rdsInfo; 29 | 30 | #define volumminus 4 31 | #define volumplus 5 32 | #define cautareplus 6 33 | #define cautareminus 7 34 | #define inainte 8 35 | #define inapoi 9 36 | 37 | /* 38 | byte antena[] = { // https://maxpromer.github.io/LCD-Character-Creator/ 39 | B10001, 40 | B10101, 41 | B10101, 42 | B01110, 43 | B00100, 44 | B00100, 45 | B00100, 46 | B00100 47 | }; 48 | */ 49 | 50 | byte antena[] = { 51 | B11111, 52 | B10101, 53 | B10101, 54 | B01110, 55 | B01110, 56 | B00100, 57 | B00100, 58 | B00100 59 | }; 60 | 61 | byte difuzor[] = { 62 | B00001, 63 | B00001, 64 | B00011, 65 | B11101, 66 | B10101, 67 | B11101, 68 | B00011, 69 | B00001 70 | }; 71 | 72 | void setup() { 73 | pinMode(volumminus, INPUT); 74 | pinMode(volumplus, INPUT); 75 | pinMode(cautareminus, INPUT); 76 | pinMode(cautareplus, INPUT); 77 | pinMode(inainte, INPUT); 78 | pinMode(inapoi, INPUT); 79 | digitalWrite(volumminus, HIGH); 80 | digitalWrite(volumplus, HIGH); 81 | digitalWrite(cautareminus, HIGH); 82 | digitalWrite(cautareplus, HIGH); 83 | digitalWrite(inainte, HIGH); 84 | digitalWrite(inapoi, HIGH); 85 | 86 | //lcd.init(); // initialize the lcd 87 | lcd.begin(); // initialize the LCD 88 | lcd.createChar(0, antena); 89 | lcd.createChar(1, difuzor); 90 | // Print a message to the LCD. 91 | lcd.backlight(); 92 | lcd.clear(); 93 | // Print a logo message to the LCD. 94 | lcd.setCursor(0, 0); 95 | lcd.print(" TEF6686 radio v.3x"); 96 | lcd.setCursor(0, 1); 97 | lcd.print("github.com/makserge "); 98 | lcd.setCursor(0, 2); 99 | lcd.print(" updated by niq_ro "); 100 | lcd.setCursor(0, 3); 101 | lcd.print(" github.com/tehniq3 "); 102 | delay (3000); 103 | lcd.clear(); 104 | 105 | delay(1000); 106 | Serial.begin(115200); 107 | while (!Serial); 108 | Serial.println(F("Start")); 109 | radio.init(); 110 | radio.powerOn(); 111 | radio.setFrequency(9200); 112 | frequency = radio.getFrequency(); 113 | //displayInfo(); 114 | radioGui(1); 115 | 116 | } 117 | 118 | void loop() { 119 | readRds(); 120 | radioGui(0); 121 | displayInfo(); 122 | 123 | if (digitalRead(volumplus) == LOW) 124 | { 125 | volume += 4; 126 | if (volume >= 24) volume = 24; 127 | radio.setVolume(volume); 128 | displayInfo(); 129 | delay(250); 130 | } 131 | if (digitalRead(volumminus) == LOW) 132 | { 133 | volume -= 4; 134 | if (volume < -60) volume = -60; 135 | radio.setVolume(volume); 136 | displayInfo(); 137 | delay(250); 138 | } 139 | if (digitalRead(cautareplus) == LOW) 140 | { 141 | frequency = radio.seekUp(); 142 | displayInfo(); 143 | delay(250); 144 | } 145 | if (digitalRead(cautareminus) == LOW) 146 | { 147 | frequency = radio.seekDown(); 148 | displayInfo(); 149 | delay(250); 150 | } 151 | 152 | if (digitalRead(inainte) == LOW) 153 | { 154 | frequency = radio.tuneUp(); 155 | displayInfo(); 156 | delay(250); 157 | } 158 | if (digitalRead(inapoi) == LOW) 159 | { 160 | frequency = radio.tuneDown(); 161 | displayInfo(); 162 | delay(250); 163 | } 164 | 165 | 166 | if (Serial.available()) { 167 | char ch = Serial.read(); 168 | if (ch == 'm') { 169 | radio.setMute(); 170 | Serial.println("Mute"); 171 | //displayInfo(); 172 | } 173 | else if (ch == 'n') { 174 | radio.setUnMute(); 175 | Serial.println("Unmute"); 176 | //displayInfo(); 177 | } 178 | else if (ch == 'p') { 179 | radio.powerOn(); 180 | Serial.println("Power ON"); 181 | //displayInfo(); 182 | } 183 | else if (ch == 'o') { 184 | radio.powerOff(); 185 | Serial.println("Power OFF"); 186 | //displayInfo(); 187 | } 188 | if (ch == 'u') { 189 | frequency = radio.seekUp(); 190 | //displayInfo(); 191 | radioGui(true); 192 | } 193 | else if (ch == 'd') { 194 | frequency = radio.seekDown(); 195 | //displayInfo(); 196 | radioGui(true); 197 | } 198 | else if (ch == '+') { 199 | volume += 4; 200 | if (volume >= 24) volume = 24; 201 | radio.setVolume(volume); 202 | displayInfo(); 203 | } 204 | else if (ch == '-') { 205 | volume -= 4; 206 | if (volume < -60) volume = -60; 207 | radio.setVolume(volume); 208 | displayInfo(); 209 | } 210 | else if (ch == '8') { 211 | frequency = radio.tuneUp(); 212 | //displayInfo(); 213 | radioGui(true); 214 | } 215 | else if (ch == '2') { 216 | frequency = radio.tuneDown(); 217 | //displayInfo(); 218 | radioGui(true); 219 | } 220 | else if (ch == 'r') { 221 | radioGui(true); 222 | } 223 | } 224 | /* 225 | delay(500); 226 | lcd.setCursor(3, 0); 227 | lcd.print(" "); 228 | lcd.setCursor(4, 0); 229 | lcd.print(" "); 230 | */ 231 | } 232 | 233 | void readRds() { 234 | isRdsSync = radio.readRDS(); 235 | radio.getRDS(&rdsInfo); 236 | } 237 | 238 | void showPI() { 239 | if (isNewPi()){ 240 | strcpy(programIdPrevious, rdsInfo.programId); 241 | } 242 | Serial.print(rdsInfo.programId); 243 | lcd.setCursor(0,3); 244 | lcd.print("Pi: "); 245 | lcd.print(rdsInfo.programId); 246 | } 247 | 248 | bool isNewPi(){ 249 | return (strlen(rdsInfo.programId) == 4) && !strcmp(rdsInfo.programId, programIdPrevious, 4); 250 | } 251 | 252 | 253 | void showPTY() { 254 | if (isNewPty()) { 255 | strcpy(programTypePrevious, rdsInfo.programType); 256 | } 257 | Serial.print(rdsInfo.programType); 258 | lcd.setCursor(0,2); 259 | lcd.print("PTY:"); 260 | lcd.print(rdsInfo.programType); 261 | } 262 | 263 | bool isNewPty() { 264 | return (isRdsSync == 1) && !strcmp(rdsInfo.programType, programTypePrevious, 16); 265 | } 266 | 267 | 268 | void showPS() { 269 | if (isNewPs()) { 270 | strcpy(programServicePrevious, rdsInfo.programService); 271 | } 272 | Serial.print(rdsInfo.programService); 273 | // lcd.setCursor(0,3); 274 | // lcd.print(rdsInfo.programService); 275 | } 276 | 277 | 278 | void showPsUnsafe(){ 279 | if (isNewPsUnsafe()){ 280 | strcpy(programServiceUnsafePrevious, rdsInfo.programServiceUnsafe); 281 | } 282 | Serial.print(rdsInfo.programServiceUnsafe); 283 | lcd.setCursor(10,3); 284 | lcd.print(rdsInfo.programServiceUnsafe); 285 | } 286 | 287 | bool isNewPs() { 288 | return (strlen(rdsInfo.programService) == 8) && !strcmp(rdsInfo.programService, programServicePrevious, 8); 289 | } 290 | 291 | bool isNewPsUnsafe() { 292 | return (strlen(rdsInfo.programServiceUnsafe) == 8) && !strcmp(rdsInfo.programServiceUnsafe, programServiceUnsafePrevious, 8); 293 | } 294 | 295 | 296 | void showRadioText() { 297 | if (isNewRt()){ 298 | strcpy(radioTextPrevious, rdsInfo.radioText); 299 | } 300 | Serial.print(rdsInfo.radioText); 301 | // lcd.setCursor(10,3); 302 | // lcd.print(rdsInfo.radioText); 303 | } 304 | 305 | 306 | bool isNewRt() { 307 | return (isRdsSync == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 65); 308 | } 309 | 310 | bool strcmp(char* str1, char* str2, int length) { 311 | for (int i = 0; i < length; i++) { 312 | if (str1[i] != str2[i]) { 313 | return false; 314 | } 315 | } 316 | return true; 317 | } 318 | 319 | void displayInfo() { 320 | delay(10); 321 | Serial.print(F("Frequency:")); 322 | Serial.print(frequency); 323 | Serial.print(F(" Volume:")); 324 | Serial.println(volume); 325 | Serial.print(F("Level:")); 326 | Serial.println(radio.getLevel() / 10); 327 | Serial.print(F("Stereo:")); 328 | Serial.println(radio.getStereoStatus()); 329 | lcd.setCursor(0, 0); 330 | if (frequency < 10000) lcd.print(" "); 331 | lcd.print(frequency/100); 332 | lcd.print(","); 333 | // lcd.print(frequency%100); 334 | lcd.print(frequency%100/10); // thanks to carkiller08 335 | lcd.print(frequency%10); 336 | lcd.print("MHz "); 337 | lcd.setCursor(0,1); 338 | // lcd.print("vol."); 339 | lcd.write(1); // speaker sign 340 | if (volume > 0) 341 | { 342 | plus = 1; 343 | volume2 = volume; 344 | } 345 | else 346 | { 347 | plus = 0; 348 | volume2 = -volume; 349 | } 350 | if (volume2/10 == 0) 351 | lcd.print(" "); 352 | if (volume2 == 0) lcd.print(" "); 353 | else 354 | if (plus == 0) 355 | { 356 | lcd.print("-"); 357 | } 358 | else 359 | { 360 | lcd.print("+"); 361 | } 362 | lcd.print(volume2); 363 | lcd.print("dB"); 364 | lcd.setCursor(13,0); 365 | // lcd.print("level:"); 366 | lcd.write(0); // antenna sign 367 | if (radio.getLevel() < 100) 368 | lcd.print(" "); 369 | if (radio.getLevel() < 10) 370 | lcd.print(" "); 371 | lcd.print(radio.getLevel()); 372 | lcd.print("%"); 373 | lcd.setCursor(13,1); 374 | if (radio.getStereoStatus() == 1) 375 | lcd.print("STEREO "); 376 | else 377 | lcd.print(" "); 378 | } 379 | 380 | void radioGui(bool force){ 381 | if (force || isNewPi() || isNewPs() || isNewPsUnsafe()) { 382 | //clrscr 383 | Serial.write(27); // ESC command 384 | Serial.print("[2J"); // clear screen command 385 | Serial.write(27); 386 | Serial.print("[H"); // cursor to home command 387 | 388 | //first line 389 | Serial.print(F("FM ")); 390 | Serial.print(frequency / 100); 391 | Serial.print(F(".")); 392 | Serial.print(frequency % 100 / 10); 393 | Serial.print(F(" MHz ")); 394 | 395 | Serial.print(frequency >= 10000 ? F("[ ") : F(" [ ")); 396 | // showPS(); 397 | Serial.print(" ]"); 398 | 399 | //second line 400 | Serial.println(); 401 | Serial.print(F("PI: ")); 402 | showPI(); 403 | Serial.print(F(" ( ")); 404 | showPsUnsafe(); 405 | Serial.print(F(" ) ")); 406 | 407 | Serial.println(); 408 | Serial.print(F("PTY: ")); 409 | showPTY(); 410 | Serial.println(); 411 | Serial.print( ("radio text: ")); 412 | showRadioText(); 413 | Serial.println(); 414 | Serial.println(); 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v3x/sketch_in_on _the_way.txt: -------------------------------------------------------------------------------- 1 | I will put in few hours the sketch 1 2 | 3 | Nicu 4 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v3x/test.txt: -------------------------------------------------------------------------------- 1 | https://github.com/makserge/tef6686_radio 2 | 3 | https://www.rundfunkforum.de/viewtopic.php?t=58244 4 | 5 | https://fmdx.pl/xdr-gtk/ 6 | https://github.com/kkonradpl/xdr-gtk 7 | https://github.com/kkonradpl/xdr-i2c 8 | 9 | 10 | http://www.crystalradio.cn/forum.php?mod=viewthread&tid=1672500&page=5#pid19463274 11 | 12 | http://www.crystalradio.cn/thread-606905-1-1.html 13 | 14 | https://www.electronics-notes.com/articles/audio-video/broadcast-audio/rds-radio-data-system-pty-codes.php 15 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v4/TEF6686.h: -------------------------------------------------------------------------------- 1 | #ifndef TEF6686_h 2 | #define TEF6686_h 3 | 4 | #include 5 | 6 | #include "Arduino.h" 7 | #include "Tuner_Api.h" 8 | #include "Tuner_Drv_Lithio.h" 9 | #include "Tuner_Interface.h" 10 | 11 | #define I2C_PORT 2 12 | #define I2C_ADDR 0x64 13 | #define I2C_FAST_MODE 0x2 14 | 15 | struct RdsInfo { 16 | char programType[17]; 17 | char programService[9]; 18 | char programServiceUnsafe[9]; 19 | char programId[5]; 20 | char radioText[65]; 21 | bool newRadioText; 22 | }; 23 | 24 | class TEF6686 { 25 | public: 26 | TEF6686(); 27 | uint8_t init(); 28 | void powerOn(); // call in setup 29 | void powerOff(); 30 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 31 | uint16_t getFrequency(); // returns the current frequency 32 | uint16_t getLevel(); 33 | uint8_t getStereoStatus(); 34 | uint16_t seekUp(); // returns the tuned frequency or 0 35 | uint16_t seekDown(); // returns the tuned frequency or 0 36 | uint16_t seekSync(uint8_t up); // returns 1 if seek was completed and 0 if seek in progress 37 | uint16_t tuneUp(); // returns the tuned frequency or 0 38 | uint16_t tuneDown(); // returns the tuned frequency or 0 39 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 40 | void setMute(); 41 | void setUnMute(); 42 | uint8_t readRDS(); 43 | void getRDS(RdsInfo* rdsInfo); 44 | void clearRDS(); 45 | 46 | private: 47 | uint16_t seek(uint8_t up); 48 | uint16_t tune(uint8_t up); 49 | void rdsFormatString(char* str, uint16_t length); 50 | 51 | char rdsRadioText[65]; 52 | char rdsProgramService[9]; 53 | char rdsProgramServiceUnsafe[9]; 54 | char rdsProgramId[5]; 55 | // uint8_t rdsAb; 56 | 57 | char rdsProgramType[17]; 58 | uint8_t isRdsNewRadioText; 59 | 60 | uint16_t seekMode; 61 | uint16_t seekStartFrequency; 62 | 63 | // 0: working with PS A, 1: working with PS B 64 | bool psAB; 65 | // first dimension: ps A, ps B, second dimension: PS characters 66 | char unsafePs[2][8]; 67 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 68 | uint32_t psErrors = 0xFFFFFFFF; 69 | // 4 bit groups: ps A, B blocks (0-3) is set 70 | uint8_t psCharIsSet = 0; 71 | // previous address (if prev address greater than current, change psAB status) 72 | uint8_t prevAddress = 3;uint8_t rdsAb; 73 | }; 74 | 75 | #endif 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v4/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v4/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | //TwoWire Wire2 (I2C_PORT, I2C_FAST_MODE); 5 | TwoWire Wire2; 6 | 7 | #define INIT_FLAG_TIMER 0xff 8 | #define INIT_FLAG_PATCH1 0xfe 9 | #define INIT_FLAG_PATCH2 0xfd 10 | 11 | static const unsigned char tuner_init_tab[] = { 12 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 13 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 14 | //Load Required Initialization(s).... 15 | 1, INIT_FLAG_PATCH1, 16 | 17 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 18 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 19 | //Load Required Initialization(s).... 20 | 1, INIT_FLAG_PATCH2, 21 | 22 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 23 | 3, 0x14,0x00,0x01,//Start Firmware.... 24 | 25 | //wait 50ms 26 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 27 | 28 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 29 | 30 | //Activate Device...(Idle state to Active state) 31 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 32 | //wait 100ms 33 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 34 | 35 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 36 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 37 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 38 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 39 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 40 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 41 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 42 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 43 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 44 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 45 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 46 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 47 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 48 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 49 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 57 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 58 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 59 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 60 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 61 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 62 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 63 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 64 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 65 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 66 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 67 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 68 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 69 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 70 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 71 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 72 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 73 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 74 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 75 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 76 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 77 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 78 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 79 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 80 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 81 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 82 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 83 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 84 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 85 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 86 | //Set the Audio and Application related API settings... 87 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 88 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 90 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 91 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 92 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 93 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 94 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 95 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 96 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 97 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 98 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 99 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 100 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 101 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 102 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 103 | }; 104 | 105 | //return 1 --> IIC sucess 106 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 107 | { 108 | uint16_t i; 109 | uint8_t r; 110 | //Serial.println(I2C_ADDR, HEX); 111 | //Serial.println("Send to I2C: "); 112 | Wire2.beginTransmission(I2C_ADDR); 113 | //Serial.println("beginTransmission"); 114 | for (i = 0; i < len; i++) { 115 | Wire2.write(buf[i]); 116 | //Serial.print(buf[i], HEX); 117 | //Serial.print(" "); 118 | } 119 | //Serial.println("Wire.write"); 120 | r = Wire2.endTransmission(); 121 | //Serial.println("Wire.endTransmission:"); 122 | //Serial.print(r); 123 | //Serial.println(); 124 | delay(1); 125 | return (r == 0) ? 1 : 0; 126 | } 127 | 128 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 129 | { 130 | uint16_t i; 131 | //Serial.println("\nRead from I2C: "); 132 | Wire2.requestFrom(I2C_ADDR, len); 133 | if (Wire2.available() == len) { 134 | for (i = 0; i < len; i++) { 135 | buf[i] = Wire2.read(); 136 | //Serial.print(buf[i], HEX); 137 | //Serial.print(" "); 138 | } 139 | //Serial.println(); 140 | return 1; 141 | } 142 | return 0; 143 | } 144 | 145 | void Tuner_WaitMs (uint16_t ms) 146 | { 147 | delay(ms); 148 | } 149 | //-------------------------------------------------------------------------------------------- 150 | 151 | 152 | //------------load patch and init parameters----------------- 153 | 154 | /* 155 | The transmission example below shows a data content of 12 words for every data transmission. 156 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 157 | */ 158 | #define TEF665X_SPLIT_SIZE 24 159 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 160 | { 161 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 162 | uint16_t i,len; 163 | uint16_t r; 164 | 165 | buf[0] = 0x1b; 166 | 167 | while(size) 168 | { 169 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 170 | size -= len; 171 | 172 | for(i=0;i 5 | 6 | #include "Arduino.h" 7 | #include "Tuner_Api.h" 8 | #include "Tuner_Drv_Lithio.h" 9 | #include "Tuner_Interface.h" 10 | 11 | #define I2C_PORT 2 12 | #define I2C_ADDR 0x64 13 | #define I2C_FAST_MODE 0x2 14 | 15 | struct RdsInfo { 16 | char programType[17]; 17 | char programService[9]; 18 | char programServiceUnsafe[9]; 19 | char programId[5]; 20 | char radioText[65]; 21 | bool newRadioText; 22 | }; 23 | 24 | class TEF6686 { 25 | public: 26 | TEF6686(); 27 | uint8_t init(); 28 | void powerOn(); // call in setup 29 | void powerOff(); 30 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 31 | uint16_t getFrequency(); // returns the current frequency 32 | uint16_t getLevel(); 33 | uint8_t getStereoStatus(); 34 | uint16_t seekUp(); // returns the tuned frequency or 0 35 | uint16_t seekDown(); // returns the tuned frequency or 0 36 | uint16_t seekSync(uint8_t up); // returns 1 if seek was completed and 0 if seek in progress 37 | uint16_t tuneUp(); // returns the tuned frequency or 0 38 | uint16_t tuneDown(); // returns the tuned frequency or 0 39 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 40 | void setMute(); 41 | void setUnMute(); 42 | uint8_t readRDS(); 43 | void getRDS(RdsInfo* rdsInfo); 44 | void clearRDS(); 45 | 46 | private: 47 | uint16_t seek(uint8_t up); 48 | uint16_t tune(uint8_t up); 49 | void rdsFormatString(char* str, uint16_t length); 50 | 51 | char rdsRadioText[65]; 52 | char rdsProgramService[9]; 53 | char rdsProgramServiceUnsafe[9]; 54 | char rdsProgramId[5]; 55 | // uint8_t rdsAb; 56 | 57 | char rdsProgramType[17]; 58 | uint8_t isRdsNewRadioText; 59 | 60 | uint16_t seekMode; 61 | uint16_t seekStartFrequency; 62 | 63 | // 0: working with PS A, 1: working with PS B 64 | bool psAB; 65 | // first dimension: ps A, ps B, second dimension: PS characters 66 | char unsafePs[2][8]; 67 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 68 | uint32_t psErrors = 0xFFFFFFFF; 69 | // 4 bit groups: ps A, B blocks (0-3) is set 70 | uint8_t psCharIsSet = 0; 71 | // previous address (if prev address greater than current, change psAB status) 72 | uint8_t prevAddress = 3;uint8_t rdsAb; 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v5/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v5/Tuner_Interface.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _RADIO_DRV_INIT_H_ 3 | #define _RADIO_DRV_INIT_H_ 4 | 5 | void Tuner_I2C_Init(void); 6 | uint16_t Tuner_Init(void); 7 | unsigned char Tuner_WriteBuffer(unsigned char *buf,uint16_t len); 8 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v5/new.txt: -------------------------------------------------------------------------------- 1 | NOTE: 2 | 3 | If you want to use with STM32F103 must change exiting WIRE library from local 4 | (e.g: C:\Users\niq_ro\Documents\Arduino\hardware\Arduino_STM32\STM32F1\libraries) 5 | with WIRE library from https://github.com/stm32duino/Arduino_Core_STM32/tree/master/libraries/Wire 6 | You can see details at https://nicuflorica.blogspot.com/2020/03/functionare-corecta-comunicatie-pe-i2c.html 7 | 8 | Best regrds, 9 | Nicu FLORICA (niq_ro) 10 | 11 | ---------------------------------------------------------- 12 | http://www.arduinotehniq.com 13 | http://nicuflorica.blogspot.ro/ 14 | http://arduinotehniq.blogspot.com/ 15 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v6beta/TEF6686.h: -------------------------------------------------------------------------------- 1 | #ifndef TEF6686_h 2 | #define TEF6686_h 3 | 4 | #include 5 | 6 | #include "Arduino.h" 7 | #include "Tuner_Api.h" 8 | #include "Tuner_Drv_Lithio.h" 9 | #include "Tuner_Interface.h" 10 | 11 | #define I2C_PORT 2 12 | #define I2C_ADDR 0x64 13 | #define I2C_FAST_MODE 0x2 14 | 15 | struct RdsInfo { 16 | char programType[17]; 17 | char programService[9]; 18 | char programServiceUnsafe[9]; 19 | char programId[5]; 20 | char radioText[65]; 21 | bool newRadioText; 22 | }; 23 | 24 | class TEF6686 { 25 | public: 26 | TEF6686(); 27 | uint8_t init(); 28 | void powerOn(); // call in setup 29 | void powerOff(); 30 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 31 | uint16_t getFrequency(); // returns the current frequency 32 | uint16_t getLevel(); 33 | uint8_t getStereoStatus(); 34 | uint16_t seekUp(); // returns the tuned frequency or 0 35 | uint16_t seekDown(); // returns the tuned frequency or 0 36 | uint16_t seekSync(uint8_t up); // returns 1 if seek was completed and 0 if seek in progress 37 | uint16_t tuneUp(); // returns the tuned frequency or 0 38 | uint16_t tuneDown(); // returns the tuned frequency or 0 39 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 40 | void setMute(); 41 | void setUnMute(); 42 | uint8_t readRDS(); 43 | void getRDS(RdsInfo* rdsInfo); 44 | void clearRDS(); 45 | 46 | private: 47 | uint16_t seek(uint8_t up); 48 | uint16_t tune(uint8_t up); 49 | void rdsFormatString(char* str, uint16_t length); 50 | 51 | char rdsRadioText[65]; 52 | char rdsProgramService[9]; 53 | char rdsProgramServiceUnsafe[9]; 54 | char rdsProgramId[5]; 55 | // uint8_t rdsAb; 56 | 57 | char rdsProgramType[17]; 58 | uint8_t isRdsNewRadioText; 59 | 60 | uint16_t seekMode; 61 | uint16_t seekStartFrequency; 62 | 63 | // 0: working with PS A, 1: working with PS B 64 | bool psAB; 65 | // first dimension: ps A, ps B, second dimension: PS characters 66 | char unsafePs[2][8]; 67 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 68 | uint32_t psErrors = 0xFFFFFFFF; 69 | // 4 bit groups: ps A, B blocks (0-3) is set 70 | uint8_t psCharIsSet = 0; 71 | // previous address (if prev address greater than current, change psAB status) 72 | uint8_t prevAddress = 3;uint8_t rdsAb; 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v6beta/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 6 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v6beta/Tuner_Interface.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _RADIO_DRV_INIT_H_ 3 | #define _RADIO_DRV_INIT_H_ 4 | 5 | void Tuner_I2C_Init(void); 6 | uint16_t Tuner_Init(void); 7 | unsigned char Tuner_WriteBuffer(unsigned char *buf,uint16_t len); 8 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /TEF6686_1602i2c_v6beta/v6beta.txt: -------------------------------------------------------------------------------- 1 | added band changes 2 | not finished 3 | -------------------------------------------------------------------------------- /TEF6686_Mega_LCD2004_i2c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tehniq3/TEF6686/a88e8937188dedbab6ab5d574bf41f35a68fbcbe/TEF6686_Mega_LCD2004_i2c.png -------------------------------------------------------------------------------- /TEF6686_bestpractice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tehniq3/TEF6686/a88e8937188dedbab6ab5d574bf41f35a68fbcbe/TEF6686_bestpractice.png -------------------------------------------------------------------------------- /radio_i2c_LCD3ax1/TEF6686.h: -------------------------------------------------------------------------------- 1 | #if defined(ARDUINO) && ARDUINO >= 100 2 | #include "Arduino.h" 3 | #else 4 | #include "WProgram.h" 5 | #endif 6 | 7 | 8 | #ifndef TEF6686_h 9 | #define TEF6686_h 10 | 11 | #include 12 | 13 | #include "Tuner_Api.h" 14 | #include "Tuner_Drv_Lithio.h" 15 | #include "Tuner_Interface.h" 16 | 17 | #define I2C_PORT 2 18 | #define I2C_ADDR 0x64 19 | #define I2C_FAST_MODE 0x2 20 | 21 | typedef struct RdsInfo { 22 | char programType[17]; 23 | char programService[9]; 24 | char programServiceUnsafe[9]; 25 | char programId[5]; 26 | char radioText[65]; 27 | bool newRadioText; 28 | }; 29 | 30 | class TEF6686 { 31 | public: 32 | TEF6686(); 33 | uint8_t init(); 34 | void powerOn(); // call in setup 35 | void powerOff(); 36 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 37 | uint16_t getFrequency(); // returns the current frequency 38 | uint16_t getLevel(); 39 | uint8_t getStereoStatus(); 40 | uint16_t seekUp(); // returns the tuned frequency or 0 41 | uint16_t seekDown(); // returns the tuned frequency or 0 42 | uint16_t tuneUp(); // returns the tuned frequency or 0 43 | uint16_t tuneDown(); // returns the tuned frequency or 0 44 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 45 | void setMute(); 46 | void setUnMute(); 47 | bool readRDS(); 48 | void getRDS(RdsInfo* rdsInfo); 49 | void clearRDS(); 50 | 51 | private: 52 | uint16_t seek(uint8_t up); 53 | uint16_t tune(uint8_t up); 54 | void rdsFormatString(char* str, uint16_t length); 55 | 56 | char rdsRadioText[65]; 57 | char rdsProgramService[9]; 58 | char rdsProgramServiceUnsafe[9]; 59 | char rdsProgramId[5]; 60 | uint8_t rdsAb; 61 | char rdsProgramType[17]; 62 | uint8_t isRdsNewRadioText; 63 | 64 | // 0: working with PS A, 1: working with PS B 65 | bool psAB; 66 | // first dimension: ps A, ps B, second dimension: PS characters 67 | char unsafePs[2][8]; 68 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 69 | uint32_t psErrors = 0xFFFFFFFF; 70 | // 4 bit groups: ps A, B blocks (0-3) is set 71 | uint8_t psCharIsSet = 0; 72 | // previous address (if prev address greater than current, change psAB status) 73 | uint8_t prevAddress = 3; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /radio_i2c_LCD3ax1/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_10k 1 //fm step 10khz 116 | #define FM_Step_50k 5 //fm step 50khz 117 | #define FM_Step_100k 10 //fm step 100khz 118 | #define FM_Step_200k 20 //fm step 200khz 119 | 120 | /*tuner scan/seek condition define*/ 121 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 122 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 123 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 124 | #define Radio_FMScanUNoise 70 125 | #define Radio_FMScanMNoise 60 126 | #define Radio_FMScanOffset 10 127 | 128 | #define Radio_FM_Status 0x20 129 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 130 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 131 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 132 | #define Radio_AM_Status 0xA0 133 | 134 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 135 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 136 | /*check station result */ 137 | #define NO_STATION 90 138 | #define PRESENT_STATION 100 139 | 140 | /*station max*/ 141 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 142 | 143 | 144 | 145 | #define F_UP 1 146 | #define F_DOWN 0 147 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 148 | 149 | /*are config parameters struct*/ 150 | typedef struct{ //area radio parameter 151 | uint32_t FM_MaxFreq; //fm max freq 152 | uint32_t FM_MinFreq; //fm min freq 153 | uint32_t AM_MaxFreq; // am max freq 154 | uint32_t AM_MinFreq; //am min freq 155 | uint32_t FM_AutoSeekStep; // fm step 156 | uint32_t FM_ManualSeekStep; 157 | uint32_t AM_AutoSeekStep; //am step 158 | uint32_t AM_ManualSeekStep; 159 | }Radio_AreaConfigDef; 160 | 161 | /*area define*/ 162 | enum Radio_AreaCode{ 163 | Radio_CHN=0, 164 | Radio_EUR, 165 | Radio_USA, 166 | Radio_JPN 167 | }; 168 | 169 | /*band freq range*/ 170 | typedef struct 171 | { 172 | uint16_t MinFreq; 173 | uint16_t MaxFreq; 174 | }FreqBaundDef; 175 | 176 | /*tation freq*/ 177 | typedef struct 178 | { 179 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 180 | }StationMemType; 181 | 182 | typedef enum 183 | { 184 | eAR_TuningAction_Standby = 0, 185 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 186 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 187 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 188 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 189 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 190 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 191 | } AR_TuningAction_t, *pAR_TuningAction_t; 192 | 193 | /*band function*/ 194 | extern void Radio_SetBand(uint8_t Band); 195 | extern void Radio_NextBand(void); 196 | extern uint8_t Radio_IsFMBand(void); 197 | extern uint8_t Radio_GetCurrentBand(void); 198 | 199 | /*preset function*/ 200 | extern void Radio_ClearCurrentStation(void); 201 | extern uint8_t Radio_GetCurrentStation(void); 202 | 203 | /*radio freqency function*/ 204 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 205 | extern uint32_t Radio_GetFreqStep(uint8_t band); 206 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 207 | extern uint16_t Radio_GetCurrentFreq(void); 208 | 209 | 210 | /*check station */ 211 | extern void Radio_CheckStation(void); 212 | extern void Radio_CheckStationInit(void); 213 | extern uint8_t Radio_CheckStationStatus(void); 214 | 215 | void Radio_SetSeekSenLevel(uint8_t Lev); 216 | uint8_t Radio_CheckStereo(void); 217 | uint16_t Radio_Get_Level(uint8_t fm); 218 | uint8_t Radio_Is_AF_Update_Available (void); 219 | uint8_t Radio_Is_RDAV_Available (void); 220 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /radio_i2c_LCD3ax1/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | TwoWire Wire2; 5 | 6 | #define INIT_FLAG_TIMER 0xff 7 | #define INIT_FLAG_PATCH1 0xfe 8 | #define INIT_FLAG_PATCH2 0xfd 9 | 10 | static const unsigned char tuner_init_tab[] = { 11 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 12 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 13 | //Load Required Initialization(s).... 14 | 1, INIT_FLAG_PATCH1, 15 | 16 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 17 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 18 | //Load Required Initialization(s).... 19 | 1, INIT_FLAG_PATCH2, 20 | 21 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 22 | 3, 0x14,0x00,0x01,//Start Firmware.... 23 | 24 | //wait 50ms 25 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 26 | 27 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 28 | 29 | //Activate Device...(Idle state to Active state) 30 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 31 | //wait 100ms 32 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 33 | 34 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 35 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 36 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 37 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 38 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 39 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 40 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 41 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 42 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 43 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 44 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 45 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 46 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 47 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 48 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 49 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 57 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 58 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 59 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 60 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 61 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 62 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 63 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 64 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 65 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 66 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 67 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 68 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 69 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 70 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 71 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 72 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 73 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 74 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 75 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 76 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 77 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 78 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 79 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 80 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 81 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 82 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 83 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 84 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 85 | //Set the Audio and Application related API settings... 86 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 87 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 88 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 90 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 91 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 92 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 93 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 94 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 95 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 96 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 97 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 98 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 99 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 100 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 101 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 102 | }; 103 | 104 | //return 1 --> IIC sucess 105 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 106 | { 107 | uint16_t i; 108 | uint8_t r; 109 | //Serial.println(I2C_ADDR, HEX); 110 | //Serial.println("Send to I2C: "); 111 | Wire2.beginTransmission(I2C_ADDR); 112 | //Serial.println("beginTransmission"); 113 | for (i = 0; i < len; i++) { 114 | Wire2.write(buf[i]); 115 | //Serial.print(buf[i], HEX); 116 | //Serial.print(" "); 117 | } 118 | //Serial.println("Wire.write"); 119 | r = Wire2.endTransmission(); 120 | //Serial.println("Wire.endTransmission:"); 121 | //Serial.print(r); 122 | //Serial.println(); 123 | delay(1); 124 | return (r == 0) ? 1 : 0; 125 | } 126 | 127 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 128 | { 129 | uint16_t i; 130 | //Serial.println("\nRead from I2C: "); 131 | Wire2.requestFrom(I2C_ADDR, len); 132 | if (Wire2.available() == len) { 133 | for (i = 0; i < len; i++) { 134 | buf[i] = Wire2.read(); 135 | //Serial.print(buf[i], HEX); 136 | //Serial.print(" "); 137 | } 138 | //Serial.println(); 139 | return 1; 140 | } 141 | return 0; 142 | } 143 | 144 | void Tuner_WaitMs (uint16_t ms) 145 | { 146 | delay(ms); 147 | } 148 | //-------------------------------------------------------------------------------------------- 149 | 150 | 151 | //------------load patch and init parameters----------------- 152 | 153 | /* 154 | The transmission example below shows a data content of 12 words for every data transmission. 155 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 156 | */ 157 | #define TEF665X_SPLIT_SIZE 24 158 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 159 | { 160 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 161 | uint16_t i,len; 162 | uint16_t r; 163 | 164 | buf[0] = 0x1b; 165 | 166 | while(size) 167 | { 168 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 169 | size -= len; 170 | 171 | for(i=0;i 8 | #include 9 | LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F (0x27) for a 16 chars and 2 line display 10 | 11 | #include "TEF6686.h" 12 | 13 | uint16_t frequency; 14 | int volume; 15 | int volume2; 16 | byte plus = 0; 17 | 18 | bool isRdsSync; 19 | ; 20 | 21 | char programTypePrevious[17] = " "; 22 | char programServicePrevious[9]; 23 | char programServiceUnsafePrevious[9]; 24 | char programIdPrevious[4]; 25 | char radioTextPrevious[65]; 26 | 27 | TEF6686 radio; 28 | RdsInfo rdsInfo; 29 | 30 | #define volumplus 4 31 | #define volumminus 5 32 | #define cautareplus 6 33 | #define cautareminus 7 34 | #define inainte 8 35 | #define inapoi 9 36 | 37 | 38 | byte antena[] = { // https://maxpromer.github.io/LCD-Character-Creator/ 39 | B10001, 40 | B10101, 41 | B10101, 42 | B01110, 43 | B00100, 44 | B00100, 45 | B00100, 46 | B00100 47 | }; 48 | 49 | /* 50 | byte antena[] = { 51 | B11111, 52 | B10101, 53 | B10101, 54 | B01110, 55 | B01110, 56 | B00100, 57 | B00100, 58 | B00100 59 | }; 60 | */ 61 | 62 | byte difuzor[] = { 63 | B00001, 64 | B00001, 65 | B00011, 66 | B11101, 67 | B10101, 68 | B11101, 69 | B00011, 70 | B00001 71 | }; 72 | 73 | void setup() { 74 | pinMode(volumminus, INPUT); 75 | pinMode(volumplus, INPUT); 76 | pinMode(cautareminus, INPUT); 77 | pinMode(cautareplus, INPUT); 78 | pinMode(inainte, INPUT); 79 | pinMode(inapoi, INPUT); 80 | digitalWrite(volumminus, HIGH); 81 | digitalWrite(volumplus, HIGH); 82 | digitalWrite(cautareminus, HIGH); 83 | digitalWrite(cautareplus, HIGH); 84 | digitalWrite(inainte, HIGH); 85 | digitalWrite(inapoi, HIGH); 86 | 87 | //lcd.init(); // initialize the lcd 88 | lcd.begin(); // initialize the LCD 89 | lcd.createChar(0, antena); 90 | lcd.createChar(1, difuzor); 91 | // Print a message to the LCD. 92 | lcd.backlight(); 93 | lcd.clear(); 94 | // Print a logo message to the LCD. 95 | lcd.setCursor(0, 0); 96 | lcd.print(" TEF6686 radio v.3x1"); 97 | lcd.setCursor(0, 1); 98 | lcd.print("github.com/makserge "); 99 | lcd.setCursor(0, 2); 100 | lcd.print(" updated by niq_ro "); 101 | lcd.setCursor(0, 3); 102 | lcd.print(" github.com/tehniq3 "); 103 | delay (3000); 104 | lcd.clear(); 105 | 106 | delay(1000); 107 | Serial.begin(115200); 108 | while (!Serial); 109 | Serial.println(F("Start")); 110 | radio.init(); 111 | radio.powerOn(); 112 | radio.setFrequency(9200); 113 | frequency = radio.getFrequency(); 114 | //displayInfo(); 115 | radioGui(1); 116 | 117 | } 118 | 119 | void loop() { 120 | readRds(); 121 | radioGui(0); 122 | displayInfo(); 123 | 124 | if (digitalRead(volumplus) == LOW) 125 | { 126 | volume += 4; 127 | if (volume >= 24) volume = 24; 128 | radio.setVolume(volume); 129 | displayInfo(); 130 | delay(250); 131 | } 132 | if (digitalRead(volumminus) == LOW) 133 | { 134 | volume -= 4; 135 | if (volume < -60) volume = -60; 136 | radio.setVolume(volume); 137 | displayInfo(); 138 | delay(250); 139 | } 140 | if (digitalRead(cautareplus) == LOW) 141 | { 142 | frequency = radio.seekUp(); 143 | displayInfo(); 144 | delay(250); 145 | } 146 | if (digitalRead(cautareminus) == LOW) 147 | { 148 | frequency = radio.seekDown(); 149 | displayInfo(); 150 | delay(250); 151 | } 152 | 153 | if (digitalRead(inainte) == LOW) 154 | { 155 | frequency = radio.tuneUp(); 156 | displayInfo(); 157 | delay(250); 158 | } 159 | if (digitalRead(inapoi) == LOW) 160 | { 161 | frequency = radio.tuneDown(); 162 | displayInfo(); 163 | delay(250); 164 | } 165 | 166 | 167 | if (Serial.available()) { 168 | char ch = Serial.read(); 169 | if (ch == 'm') { 170 | radio.setMute(); 171 | Serial.println("Mute"); 172 | //displayInfo(); 173 | } 174 | else if (ch == 'n') { 175 | radio.setUnMute(); 176 | Serial.println("Unmute"); 177 | //displayInfo(); 178 | } 179 | else if (ch == 'p') { 180 | radio.powerOn(); 181 | Serial.println("Power ON"); 182 | //displayInfo(); 183 | } 184 | else if (ch == 'o') { 185 | radio.powerOff(); 186 | Serial.println("Power OFF"); 187 | //displayInfo(); 188 | } 189 | if (ch == 'u') { 190 | frequency = radio.seekUp(); 191 | //displayInfo(); 192 | radioGui(true); 193 | } 194 | else if (ch == 'd') { 195 | frequency = radio.seekDown(); 196 | //displayInfo(); 197 | radioGui(true); 198 | } 199 | else if (ch == '+') { 200 | volume += 4; 201 | if (volume >= 24) volume = 24; 202 | radio.setVolume(volume); 203 | displayInfo(); 204 | } 205 | else if (ch == '-') { 206 | volume -= 4; 207 | if (volume < -60) volume = -60; 208 | radio.setVolume(volume); 209 | displayInfo(); 210 | } 211 | else if (ch == '8') { 212 | frequency = radio.tuneUp(); 213 | //displayInfo(); 214 | radioGui(true); 215 | } 216 | else if (ch == '2') { 217 | frequency = radio.tuneDown(); 218 | //displayInfo(); 219 | radioGui(true); 220 | } 221 | else if (ch == 'r') { 222 | radioGui(true); 223 | } 224 | } 225 | /* 226 | delay(500); 227 | lcd.setCursor(3, 0); 228 | lcd.print(" "); 229 | lcd.setCursor(4, 0); 230 | lcd.print(" "); 231 | */ 232 | } 233 | 234 | void readRds() { 235 | isRdsSync = radio.readRDS(); 236 | radio.getRDS(&rdsInfo); 237 | } 238 | 239 | void showPI() { 240 | if (isNewPi()){ 241 | strcpy(programIdPrevious, rdsInfo.programId); 242 | } 243 | Serial.print(rdsInfo.programId); 244 | lcd.setCursor(0,3); 245 | lcd.print("Pi: "); 246 | lcd.print(rdsInfo.programId); 247 | } 248 | 249 | bool isNewPi(){ 250 | return (strlen(rdsInfo.programId) == 4) && !strcmp(rdsInfo.programId, programIdPrevious, 4); 251 | } 252 | 253 | 254 | void showPTY() { 255 | if (isNewPty()) { 256 | strcpy(programTypePrevious, rdsInfo.programType); 257 | } 258 | Serial.print(rdsInfo.programType); 259 | lcd.setCursor(0,2); 260 | lcd.print("PTY:"); 261 | for (int i = 0; i < 15; i++) 262 | { 263 | Serial.print(radioTextPrevious[i]); 264 | lcd.setCursor(i+4,2); 265 | lcd.print(rdsInfo.programType[i]); 266 | } 267 | // lcd.print(rdsInfo.programType); 268 | } 269 | 270 | bool isNewPty() { 271 | return (isRdsSync == 1) && !strcmp(rdsInfo.programType, programTypePrevious, 16); 272 | } 273 | 274 | 275 | void showPS() { 276 | if (isNewPs()) { 277 | strcpy(programServicePrevious, rdsInfo.programService); 278 | } 279 | Serial.print(rdsInfo.programService); 280 | // lcd.setCursor(0,3); 281 | // lcd.print(rdsInfo.programService); 282 | } 283 | 284 | 285 | void showPsUnsafe(){ 286 | if (isNewPsUnsafe()){ 287 | strcpy(programServiceUnsafePrevious, rdsInfo.programServiceUnsafe); 288 | } 289 | Serial.print(rdsInfo.programServiceUnsafe); 290 | lcd.setCursor(10,3); 291 | lcd.print(rdsInfo.programServiceUnsafe); 292 | } 293 | 294 | bool isNewPs() { 295 | return (strlen(rdsInfo.programService) == 8) && !strcmp(rdsInfo.programService, programServicePrevious, 8); 296 | } 297 | 298 | bool isNewPsUnsafe() { 299 | return (strlen(rdsInfo.programServiceUnsafe) == 8) && !strcmp(rdsInfo.programServiceUnsafe, programServiceUnsafePrevious, 8); 300 | } 301 | 302 | 303 | void showRadioText() { 304 | if (isNewRt()){ 305 | strcpy(radioTextPrevious, rdsInfo.radioText); 306 | } 307 | Serial.print(rdsInfo.radioText); 308 | // lcd.setCursor(10,3); 309 | // lcd.print(rdsInfo.radioText); 310 | } 311 | 312 | 313 | bool isNewRt() { 314 | return (isRdsSync == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 65); 315 | } 316 | 317 | bool strcmp(char* str1, char* str2, int length) { 318 | for (int i = 0; i < length; i++) { 319 | if (str1[i] != str2[i]) { 320 | return false; 321 | } 322 | } 323 | return true; 324 | } 325 | 326 | void displayInfo() { 327 | delay(10); 328 | Serial.print(F("Frequency:")); 329 | Serial.print(frequency); 330 | Serial.print(F(" Volume:")); 331 | Serial.println(volume); 332 | Serial.print(F("Level:")); 333 | Serial.println(radio.getLevel() / 10); 334 | Serial.print(F("Stereo:")); 335 | Serial.println(radio.getStereoStatus()); 336 | lcd.setCursor(0, 0); 337 | if (frequency < 10000) lcd.print(" "); 338 | lcd.print(frequency/100); 339 | lcd.print(","); 340 | lcd.print(frequency%100/10); // thanks to carkiller08 341 | lcd.print(frequency%10); 342 | lcd.print("MHz"); 343 | lcd.setCursor(0,1); 344 | // lcd.print("vol."); 345 | lcd.write(1); // speaker sign 346 | if (volume > 0) 347 | { 348 | plus = 1; 349 | volume2 = volume; 350 | } 351 | else 352 | { 353 | plus = 0; 354 | volume2 = -volume; 355 | } 356 | if (volume2/10 == 0) 357 | lcd.print(" "); 358 | if (volume2 == 0) lcd.print(" "); 359 | else 360 | if (plus == 0) 361 | { 362 | lcd.print("-"); 363 | } 364 | else 365 | { 366 | lcd.print("+"); 367 | } 368 | lcd.print(volume2); 369 | lcd.print("dB"); 370 | lcd.setCursor(13,0); 371 | // lcd.print("level:"); 372 | lcd.write(0); // antenna sign 373 | if (radio.getLevel() < 100) 374 | lcd.print(" "); 375 | if (radio.getLevel() < 10) 376 | lcd.print(" "); 377 | lcd.print(radio.getLevel()); 378 | lcd.print("%"); 379 | lcd.setCursor(13,1); 380 | if (radio.getStereoStatus() == 1) 381 | lcd.print("STEREO "); 382 | else 383 | lcd.print(" "); 384 | } 385 | 386 | void radioGui(bool force){ 387 | if (force || isNewPi() || isNewPs() || isNewPsUnsafe()) { 388 | //clrscr 389 | Serial.write(27); // ESC command 390 | Serial.print("[2J"); // clear screen command 391 | Serial.write(27); 392 | Serial.print("[H"); // cursor to home command 393 | 394 | //first line 395 | Serial.print(F("FM ")); 396 | Serial.print(frequency / 100); 397 | Serial.print(F(".")); 398 | Serial.print(frequency % 100 / 10); 399 | Serial.print(F(" MHz ")); 400 | 401 | Serial.print(frequency >= 10000 ? F("[ ") : F(" [ ")); 402 | // showPS(); 403 | Serial.print(" ]"); 404 | 405 | //second line 406 | Serial.println(); 407 | Serial.print(F("PI: ")); 408 | showPI(); 409 | Serial.print(F(" ( ")); 410 | showPsUnsafe(); 411 | Serial.print(F(" ) ")); 412 | 413 | Serial.println(); 414 | Serial.print(F("PTY: ")); 415 | showPTY(); 416 | Serial.println(); 417 | Serial.print( ("radio text: ")); 418 | showRadioText(); 419 | Serial.println(); 420 | Serial.println(); 421 | } 422 | } 423 | -------------------------------------------------------------------------------- /radio_i2c_LCD3ax1/read,me: -------------------------------------------------------------------------------- 1 | corrected PTY info to enter just on 3rd row 2 | add info for European PTY 3 | add small step for search (50kHz) 4 | -------------------------------------------------------------------------------- /radio_serialLCD2/TEF6686.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | 3 | const char* ptyLUT[51] = { 4 | " None ", 5 | " News ", 6 | " Information ", 7 | " Sports ", 8 | " Talk ", 9 | " Rock ", 10 | " Classic Rock ", 11 | " Adult Hits ", 12 | " Soft Rock ", 13 | " Top 40 ", 14 | " Country ", 15 | " Oldies ", 16 | " Soft ", 17 | " Nostalgia ", 18 | " Jazz ", 19 | " Classical ", 20 | "Rhythm and Blues", 21 | " Soft R & B ", 22 | "Foreign Language", 23 | "Religious Music ", 24 | " Religious Talk ", 25 | " Personality ", 26 | " Public ", 27 | " College ", 28 | " Reserved -24- ", 29 | " Reserved -25- ", 30 | " Reserved -26- ", 31 | " Reserved -27- ", 32 | " Reserved -28- ", 33 | " Weather ", 34 | " Emergency Test ", 35 | " !!!ALERT!!! ", 36 | "Current Affairs ", 37 | " Education ", 38 | " Drama ", 39 | " Cultures ", 40 | " Science ", 41 | " Varied Speech ", 42 | " Easy Listening ", 43 | " Light Classics ", 44 | "Serious Classics", 45 | " Other Music ", 46 | " Finance ", 47 | "Children's Progs", 48 | " Social Affairs ", 49 | " Phone In ", 50 | "Travel & Touring", 51 | "Leisure & Hobby ", 52 | " National Music ", 53 | " Folk Music ", 54 | " Documentary "}; 55 | 56 | TEF6686::TEF6686() { 57 | } 58 | 59 | uint8_t TEF6686::init() { 60 | uint8_t result; 61 | uint8_t counter = 0; 62 | uint8_t status; 63 | 64 | Tuner_I2C_Init(); 65 | 66 | delay(5); 67 | while (true) { 68 | result = devTEF668x_APPL_Get_Operation_Status(&status); 69 | if (result == 1) { 70 | Tuner_Init(); 71 | powerOff(); 72 | return 1; //Ok 73 | } 74 | else if (++counter > 50) { 75 | return 2; //Doesn't exist 76 | } 77 | else { 78 | delay(5); 79 | return 0; //Busy 80 | } 81 | } 82 | } 83 | 84 | void TEF6686::powerOn() { 85 | devTEF668x_APPL_Set_OperationMode(0); 86 | } 87 | 88 | void TEF6686::powerOff() { 89 | devTEF668x_APPL_Set_OperationMode(1); 90 | } 91 | 92 | void TEF6686::setFrequency(uint16_t frequency) { 93 | Radio_SetFreq(Radio_PRESETMODE, FM1_BAND, frequency); 94 | } 95 | 96 | uint16_t TEF6686::getFrequency() { 97 | return Radio_GetCurrentFreq(); 98 | } 99 | 100 | uint16_t TEF6686::getLevel() { 101 | return Radio_Get_Level(1); 102 | } 103 | 104 | uint8_t TEF6686::getStereoStatus() { 105 | return Radio_CheckStereo(); 106 | } 107 | 108 | uint16_t TEF6686::seekUp() { 109 | return seek(1); 110 | } 111 | 112 | uint16_t TEF6686::seekDown() { 113 | return seek(0); 114 | } 115 | 116 | uint16_t TEF6686::tuneUp() { 117 | return tune(1); 118 | } 119 | 120 | uint16_t TEF6686::tuneDown() { 121 | return tune(0); 122 | } 123 | 124 | void TEF6686::setVolume(uint16_t volume) { 125 | devTEF668x_Audio_Set_Volume(volume); 126 | } 127 | 128 | void TEF6686::setMute() { 129 | devTEF668x_Audio_Set_Mute(1); 130 | } 131 | 132 | void TEF6686::setUnMute() { 133 | devTEF668x_Audio_Set_Mute(0); 134 | } 135 | 136 | uint8_t TEF6686::readRDS() { 137 | char status; 138 | uint8_t rdsBHigh, rdsBLow, rdsCHigh, rdsCLow, rdsDHigh, isReady, rdsDLow; 139 | 140 | uint16_t rdsStat, rdsA, rdsB, rdsC, rdsD, rdsErr; 141 | uint16_t result = devTEF668x_Radio_Get_RDS_Data(1, &rdsStat, &rdsA, &rdsB, &rdsC, &rdsD, &rdsErr); 142 | 143 | if (!(result && (rdsB != 0x0) && ((rdsStat & 0x8000) != 0x0) && ((rdsErr & 0x0a00) == 0x0))) { 144 | return isReady; 145 | } 146 | 147 | rdsBHigh = (uint8_t)(rdsB >> 8); 148 | rdsBLow = (uint8_t)rdsB; 149 | rdsCHigh = (uint8_t)(rdsC >> 8); 150 | rdsCLow = (uint8_t)rdsC; 151 | rdsDHigh = (uint8_t)(rdsD >> 8); 152 | rdsDLow = (uint8_t)rdsD; 153 | 154 | uint8_t programType = ((rdsBHigh & 3) << 3) | ((rdsBLow >> 5) & 7); 155 | strcpy(rdsProgramType, (programType >= 0 && programType < 32) ? ptyLUT[programType] : " PTY ERROR "); 156 | 157 | uint8_t type = (rdsBHigh >> 4) & 15; 158 | uint8_t version = bitRead(rdsBHigh, 4); 159 | 160 | // Groups 0A & 0B 161 | // Basic tuning and switching information only 162 | if (type == 0) { 163 | uint8_t address = rdsBLow & 3; 164 | // Groups 0A & 0B: to extract PS segment we need blocks 1 and 3 165 | if (address >= 0 && address <= 3) { 166 | if (rdsDHigh != '\0') { 167 | rdsProgramService[address * 2] = rdsDHigh; 168 | } 169 | if (rdsDLow != '\0') { 170 | rdsProgramService[address * 2 + 1] = rdsDLow; 171 | } 172 | isReady = (address == 3) ? 1 : 0; 173 | } 174 | rdsFormatString(rdsProgramService, 8); 175 | } 176 | // Groups 2A & 2B 177 | // Radio Text 178 | else if (type == 2) { 179 | uint16_t addressRT = rdsBLow & 15; 180 | uint8_t ab = bitRead(rdsBLow, 4); 181 | uint8_t cr = 0; 182 | uint8_t len = 64; 183 | if (version == 0) { 184 | if (addressRT >= 0 && addressRT <= 15) { 185 | if (rdsCHigh != 0x0D) { 186 | rdsRadioText[addressRT*4] = rdsCHigh; 187 | } 188 | else { 189 | len = addressRT * 4; 190 | cr = 1; 191 | } 192 | if (rdsCLow != 0x0D) { 193 | rdsRadioText[addressRT * 4 + 1] = rdsCLow; 194 | } 195 | else { 196 | len = addressRT * 4 + 1; 197 | cr = 1; 198 | } 199 | if (rdsDHigh != 0x0D) { 200 | rdsRadioText[addressRT * 4 + 2] = rdsDHigh; 201 | } 202 | else { 203 | len = addressRT * 4 + 2; 204 | cr = 1; 205 | } 206 | if (rdsDLow != 0x0D) { 207 | rdsRadioText[addressRT * 4 + 3] = rdsDLow; 208 | } 209 | else { 210 | len = addressRT * 4 + 3; 211 | cr = 1; 212 | } 213 | } 214 | } 215 | else { 216 | if (addressRT >= 0 && addressRT <= 7) { 217 | if (rdsDHigh != '\0') { 218 | rdsRadioText[addressRT * 2] = rdsDHigh; 219 | } 220 | if (rdsDLow != '\0') { 221 | rdsRadioText[addressRT * 2 + 1] = rdsDLow; 222 | } 223 | } 224 | } 225 | if (cr) { 226 | for (uint8_t i = len; i < 64; i++) { 227 | rdsRadioText[i] = ' '; 228 | } 229 | } 230 | if (ab != rdsAb) { 231 | for (uint8_t i = 0; i < 64; i++) { 232 | rdsRadioText[i] = ' '; 233 | } 234 | rdsRadioText[64] = '\0'; 235 | isRdsNewRadioText = 1; 236 | } 237 | else { 238 | isRdsNewRadioText = 0; 239 | } 240 | rdsAb = ab; 241 | rdsFormatString(rdsRadioText, 64); 242 | } 243 | return isReady; 244 | } 245 | 246 | void TEF6686::getRDS(RdsInfo* rdsInfo) { 247 | strcpy(rdsInfo->programType, rdsProgramType); 248 | strcpy(rdsInfo->programService, rdsProgramService); 249 | strcpy(rdsInfo->radioText, rdsRadioText); 250 | } 251 | 252 | void TEF6686::rdsFormatString(char* str, uint16_t length) { 253 | for (uint16_t i = 0; i < length; i++) { 254 | if ((str[i] != 0 && str[i] < 32) || str[i] > 126 ) { 255 | str[i] = ' '; 256 | } 257 | } 258 | } 259 | 260 | uint16_t TEF6686::seek(uint8_t up) { 261 | uint16_t mode = 20; 262 | uint16_t startFrequency = Radio_GetCurrentFreq(); 263 | 264 | while (true) { 265 | switch(mode){ 266 | case 20: 267 | Radio_ChangeFreqOneStep(up); 268 | Radio_SetFreq(Radio_SEARCHMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 269 | 270 | mode = 30; 271 | Radio_CheckStationInit(); 272 | Radio_ClearCurrentStation(); 273 | 274 | break; 275 | 276 | case 30: 277 | delay(20); 278 | Radio_CheckStation(); 279 | if (Radio_CheckStationStatus() >= NO_STATION) { 280 | mode = 40; 281 | } 282 | 283 | break; 284 | 285 | case 40: 286 | if (Radio_CheckStationStatus() == NO_STATION) { 287 | mode = (startFrequency == Radio_GetCurrentFreq()) ? 50 : 20; 288 | } 289 | else if (Radio_CheckStationStatus() == PRESENT_STATION) { 290 | mode = 50; 291 | } 292 | 293 | break; 294 | 295 | case 50: 296 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 297 | return Radio_GetCurrentFreq(); 298 | } 299 | } 300 | return 0; 301 | } 302 | 303 | uint16_t TEF6686::seekSync(uint8_t up) { 304 | if (seekMode == 0) { 305 | seekMode = 20; 306 | seekStartFrequency = Radio_GetCurrentFreq(); 307 | } 308 | switch(seekMode) { 309 | case 20: 310 | Radio_ChangeFreqOneStep(up); 311 | Radio_SetFreq(Radio_SEARCHMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 312 | 313 | seekMode = 30; 314 | Radio_CheckStationInit(); 315 | Radio_ClearCurrentStation(); 316 | 317 | return 0; 318 | 319 | case 30: 320 | delay(20); 321 | Radio_CheckStation(); 322 | if (Radio_CheckStationStatus() >= NO_STATION) { 323 | seekMode = 40; 324 | } 325 | 326 | return 0; 327 | 328 | case 40: 329 | if (Radio_CheckStationStatus() == NO_STATION) { 330 | seekMode = (seekStartFrequency == Radio_GetCurrentFreq()) ? 50 : 20; 331 | } 332 | else if (Radio_CheckStationStatus() == PRESENT_STATION) { 333 | seekMode = 50; 334 | } 335 | 336 | return 0; 337 | 338 | case 50: 339 | seekMode = 0; 340 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 341 | return 1; 342 | } 343 | return 0; 344 | } 345 | 346 | uint16_t TEF6686::tune(uint8_t up) { 347 | Radio_ChangeFreqOneStep(up); 348 | 349 | Radio_SetFreq(Radio_PRESETMODE, Radio_GetCurrentBand(), Radio_GetCurrentFreq()); 350 | Radio_ClearCurrentStation(); 351 | return Radio_GetCurrentFreq(); 352 | } 353 | 354 | -------------------------------------------------------------------------------- /radio_serialLCD2/TEF6686.h: -------------------------------------------------------------------------------- 1 | #ifndef TEF6686_h 2 | #define TEF6686_h 3 | 4 | #include 5 | 6 | #include "Arduino.h" 7 | #include "Tuner_Api.h" 8 | #include "Tuner_Drv_Lithio.h" 9 | #include "Tuner_Interface.h" 10 | 11 | #define I2C_PORT 2 12 | #define I2C_ADDR 0x64 13 | 14 | struct RdsInfo { 15 | char programType[17]; 16 | char programService[9]; 17 | char radioText[65]; 18 | bool newRadioText; 19 | }; 20 | 21 | class TEF6686 { 22 | public: 23 | TEF6686(); 24 | uint8_t init(); 25 | void powerOn(); // call in setup 26 | void powerOff(); 27 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 28 | uint16_t getFrequency(); // returns the current frequency 29 | uint16_t getLevel(); 30 | uint8_t getStereoStatus(); 31 | uint16_t seekUp(); // returns the tuned frequency or 0 32 | uint16_t seekDown(); // returns the tuned frequency or 0 33 | uint16_t seekSync(uint8_t up); // returns 1 if seek was completed and 0 if seek in progress 34 | uint16_t tuneUp(); // returns the tuned frequency or 0 35 | uint16_t tuneDown(); // returns the tuned frequency or 0 36 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 37 | void setMute(); 38 | void setUnMute(); 39 | uint8_t readRDS(); 40 | void getRDS(RdsInfo* rdsInfo); 41 | 42 | private: 43 | uint16_t seek(uint8_t up); 44 | uint16_t tune(uint8_t up); 45 | void rdsFormatString(char* str, uint16_t length); 46 | 47 | char rdsRadioText[65]; 48 | char rdsProgramService[9]; 49 | uint8_t rdsAb; 50 | char rdsProgramType[17]; 51 | uint8_t isRdsNewRadioText; 52 | 53 | uint16_t seekMode; 54 | uint16_t seekStartFrequency; 55 | }; 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /radio_serialLCD2/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | 223 | -------------------------------------------------------------------------------- /radio_serialLCD2/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | //TwoWire Wire2 (I2C_PORT, I2C_FAST_MODE); 5 | TwoWire Wire2; 6 | 7 | #define INIT_FLAG_TIMER 0xff 8 | #define INIT_FLAG_PATCH1 0xfe 9 | #define INIT_FLAG_PATCH2 0xfd 10 | 11 | static const unsigned char tuner_init_tab[] = { 12 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 13 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 14 | //Load Required Initialization(s).... 15 | 1, INIT_FLAG_PATCH1, 16 | 17 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 18 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 19 | //Load Required Initialization(s).... 20 | 1, INIT_FLAG_PATCH2, 21 | 22 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 23 | 3, 0x14,0x00,0x01,//Start Firmware.... 24 | 25 | //wait 50ms 26 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 27 | 28 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 29 | 30 | //Activate Device...(Idle state to Active state) 31 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 32 | //wait 100ms 33 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 34 | 35 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 36 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 37 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 38 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 39 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 40 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 41 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 42 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 43 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 44 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 45 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 46 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 47 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 48 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 49 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 57 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 58 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 59 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 60 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 61 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 62 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 63 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 64 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 65 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 66 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 67 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 68 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 69 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 70 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 71 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 72 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 73 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 74 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 75 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 76 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 77 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 78 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 79 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 80 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 81 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 82 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 83 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 84 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 85 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 86 | //Set the Audio and Application related API settings... 87 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 88 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 90 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 91 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 92 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 93 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 94 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 95 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 96 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 97 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 98 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 99 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 100 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 101 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 102 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 103 | }; 104 | 105 | //return 1 --> IIC sucess 106 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 107 | { 108 | uint16_t i; 109 | uint8_t r; 110 | //Serial.println(I2C_ADDR, HEX); 111 | //Serial.println("Send to I2C: "); 112 | Wire2.beginTransmission(I2C_ADDR); 113 | //Serial.println("beginTransmission"); 114 | for (i = 0; i < len; i++) { 115 | Wire2.write(buf[i]); 116 | //Serial.print(buf[i], HEX); 117 | //Serial.print(" "); 118 | } 119 | //Serial.println("Wire.write"); 120 | r = Wire2.endTransmission(); 121 | //Serial.println("Wire.endTransmission:"); 122 | //Serial.print(r); 123 | //Serial.println(); 124 | delay(1); 125 | return (r == 0) ? 1 : 0; 126 | } 127 | 128 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 129 | { 130 | uint16_t i; 131 | //Serial.println("\nRead from I2C: "); 132 | Wire2.requestFrom(I2C_ADDR, len); 133 | if (Wire2.available() == len) { 134 | for (i = 0; i < len; i++) { 135 | buf[i] = Wire2.read(); 136 | //Serial.print(buf[i], HEX); 137 | //Serial.print(" "); 138 | } 139 | //Serial.println(); 140 | return 1; 141 | } 142 | return 0; 143 | } 144 | 145 | void Tuner_WaitMs (uint16_t ms) 146 | { 147 | delay(ms); 148 | } 149 | //-------------------------------------------------------------------------------------------- 150 | 151 | 152 | //------------load patch and init parameters----------------- 153 | 154 | /* 155 | The transmission example below shows a data content of 12 words for every data transmission. 156 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 157 | */ 158 | #define TEF665X_SPLIT_SIZE 24 159 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 160 | { 161 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 162 | uint16_t i,len; 163 | uint16_t r; 164 | 165 | buf[0] = 0x1b; 166 | 167 | while(size) 168 | { 169 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 170 | size -= len; 171 | 172 | for(i=0;i 7 | #include 8 | // Make a SoftwareSerial object, and a new SerLCD object, 9 | // which points at the NewSoftSerial object. 10 | // 11 | // In this demo the Rx pin of the SerLCD is connected to 12 | // Arduino digital pin 4 (Tx) We set the SoftwareSerial 13 | // Rx to 0 because the SerLCD has no facility to transmit 14 | // back. 15 | // 16 | SoftwareSerial NSS(255,4,1); 17 | SerLCD lcd(NSS,20,4); 18 | 19 | 20 | int frequency; 21 | int volume; 22 | int volume2; 23 | byte plus = 0; 24 | 25 | uint8_t isRDSReady; 26 | 27 | char programTypePrevious[17] = " "; 28 | char programServicePrevious[9]; 29 | char radioTextPrevious[65]; 30 | 31 | boolean isFmSeekMode; 32 | boolean isFmSeekUp; 33 | 34 | TEF6686 radio; 35 | RdsInfo rdsInfo; 36 | 37 | void setup() { 38 | NSS.begin(9600); 39 | lcd.begin(); 40 | lcd.clear(); 41 | // Print a logo message to the LCD. 42 | lcd.setPosition(1, 0); 43 | lcd.print(" TEF6686 radio "); 44 | lcd.setPosition(2, 0); 45 | lcd.print("github.com/kkonradpl"); 46 | lcd.setPosition(3, 0); 47 | lcd.print(" updated by niq_ro "); 48 | lcd.setPosition(4, 0); 49 | lcd.print(" github.com/tehniq3 "); 50 | delay (3000); 51 | lcd.clear(); 52 | 53 | // delay(1000); 54 | Serial.begin(115200); 55 | while (!Serial); 56 | Serial.println("TEF6686 radio"); 57 | radio.init(); 58 | radio.powerOn(); 59 | radio.setFrequency(9400); 60 | frequency = radio.getFrequency(); 61 | displayInfo(); 62 | } 63 | 64 | void loop() { 65 | readRds(); 66 | showFmSeek(); 67 | displayInfo(); 68 | 69 | if (Serial.available()) { 70 | char ch = Serial.read(); 71 | if (ch == 'm') { 72 | radio.setMute(); 73 | displayInfo(); 74 | } 75 | else if (ch == 'n') { 76 | radio.setUnMute(); 77 | displayInfo(); 78 | } 79 | else if (ch == 'p') { 80 | radio.powerOn(); 81 | displayInfo(); 82 | } 83 | else if (ch == 'o') { 84 | radio.powerOff(); 85 | displayInfo(); 86 | } 87 | else if (ch == 'u') { 88 | frequency = radio.seekUp(); 89 | displayInfo(); 90 | } 91 | else if (ch == 'd') { 92 | frequency = radio.seekDown(); 93 | displayInfo(); 94 | } 95 | else if (ch == 'c') { 96 | Serial.println("Seeking up"); 97 | isFmSeekMode = true; 98 | isFmSeekUp = true; 99 | } 100 | else if (ch == 'e') { 101 | Serial.println("Seeking down"); 102 | isFmSeekMode = true; 103 | isFmSeekUp = false; 104 | } 105 | else if (ch == '+') { 106 | volume += 4; 107 | if (volume >= 24) volume = 24; 108 | radio.setVolume(volume); 109 | displayInfo(); 110 | } 111 | else if (ch == '-') { 112 | volume -= 4; 113 | if (volume < -60) volume = -60; 114 | radio.setVolume(volume); 115 | displayInfo(); 116 | } 117 | else if (ch == 'a') { 118 | frequency = radio.tuneUp(); 119 | displayInfo(); 120 | } 121 | else if (ch == 'b') { 122 | frequency = radio.tuneDown(); 123 | displayInfo(); 124 | } 125 | } 126 | } 127 | 128 | void readRds() { 129 | isRDSReady = radio.readRDS(); 130 | radio.getRDS(&rdsInfo); 131 | 132 | showPTY(); 133 | showPS(); 134 | showRadioText(); 135 | } 136 | 137 | void showPTY() { 138 | if ((isRDSReady == 1) && !strcmp(rdsInfo.programType, programTypePrevious, 16)) { 139 | Serial.print(rdsInfo.programType); 140 | strcpy(programTypePrevious, rdsInfo.programType); 141 | Serial.println(); 142 | lcd.setPosition(4, 11); 143 | //lcd.print(rdsInfo.programType); 144 | lcd.print(strcpy(programTypePrevious, rdsInfo.programType)); 145 | } 146 | } 147 | 148 | void showPS() { 149 | if ((isRDSReady == 1) && (strlen(rdsInfo.programService) == 8) && !strcmp(rdsInfo.programService, programServicePrevious, 8)) { 150 | Serial.print("-=[ "); 151 | Serial.print(rdsInfo.programService); 152 | Serial.print(" ]=-"); 153 | strcpy(programServicePrevious, rdsInfo.programService); 154 | Serial.println(); 155 | lcd.setPosition(4, 0); 156 | //lcd.print(rdsInfo.programService); 157 | lcd.print(strcpy(programServicePrevious, rdsInfo.programService)); 158 | } 159 | } 160 | 161 | void showRadioText() { 162 | if ((isRDSReady == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 65)){ 163 | Serial.print(rdsInfo.radioText); 164 | strcpy(radioTextPrevious, rdsInfo.radioText); 165 | Serial.println(); 166 | // lcd.setPosition(3, 11); 167 | lcd.setPosition(3, 0); 168 | // lcd.print(rdsInfo.radioText); 169 | lcd.print(strcpy(radioTextPrevious, rdsInfo.radioText)); 170 | } 171 | } 172 | 173 | bool strcmp(char* str1, char* str2, int length) { 174 | for (int i = 0; i < length; i++) { 175 | if (str1[i] != str2[i]) { 176 | return false; 177 | } 178 | } 179 | return true; 180 | } 181 | 182 | void displayInfo() { 183 | delay(10); 184 | Serial.print("Frequency:"); 185 | Serial.print(frequency); 186 | Serial.print(" Volume:"); 187 | Serial.println(volume); 188 | Serial.print("Level:"); 189 | Serial.println(radio.getLevel() / 10); 190 | Serial.print("Stereo:"); 191 | Serial.println(radio.getStereoStatus()); 192 | 193 | lcd.setPosition(1, 0); 194 | if (frequency < 10000) lcd.print(" "); 195 | lcd.print(frequency/100); 196 | lcd.print(","); 197 | lcd.print(frequency%100); 198 | lcd.print("MHz"); 199 | lcd.setPosition(2, 0); 200 | lcd.print("vol."); 201 | if (volume > 0) 202 | { 203 | plus = 1; 204 | volume2 = volume; 205 | } 206 | else 207 | { 208 | plus = 0; 209 | volume2 = -volume; 210 | } 211 | if (volume2/10 == 0) 212 | lcd.print(" "); 213 | if (volume2 == 0) lcd.print(" "); 214 | else 215 | if (plus == 0) 216 | { 217 | lcd.print("-"); 218 | } 219 | else 220 | { 221 | lcd.print("+"); 222 | } 223 | lcd.print(volume2); 224 | lcd.print("dB"); 225 | lcd.setPosition(2, 10); 226 | lcd.print("level:"); 227 | if (radio.getLevel() < 100) 228 | lcd.print(" "); 229 | if (radio.getLevel() < 10) 230 | lcd.print(" "); 231 | lcd.print(radio.getLevel()); 232 | lcd.print("%"); 233 | lcd.setPosition(1, 13); 234 | if (radio.getStereoStatus() == 1) 235 | lcd.print("STEREO"); 236 | else 237 | lcd.print(" "); 238 | } 239 | 240 | void showFmSeek() { 241 | if (isFmSeekMode) { 242 | if (radio.seekSync(isFmSeekUp)) { 243 | isFmSeekMode = false; 244 | Serial.println("Seek stopped"); 245 | // lcd.setPosition(3, 1); 246 | // lcd.print("Seek stopped"); 247 | frequency = radio.getFrequency(); 248 | displayInfo(); 249 | } 250 | } 251 | } 252 | 253 | -------------------------------------------------------------------------------- /radio_serialLCD2/test.txt: -------------------------------------------------------------------------------- 1 | uu 2 | -------------------------------------------------------------------------------- /radio_serialLCD3a/TEF6686.h: -------------------------------------------------------------------------------- 1 | #if defined(ARDUINO) && ARDUINO >= 100 2 | #include "Arduino.h" 3 | #else 4 | #include "WProgram.h" 5 | #endif 6 | 7 | 8 | #ifndef TEF6686_h 9 | #define TEF6686_h 10 | 11 | #include 12 | 13 | #include "Tuner_Api.h" 14 | #include "Tuner_Drv_Lithio.h" 15 | #include "Tuner_Interface.h" 16 | 17 | #define I2C_PORT 2 18 | #define I2C_ADDR 0x64 19 | #define I2C_FAST_MODE 0x2 20 | 21 | typedef struct RdsInfo { 22 | char programType[17]; 23 | char programService[9]; 24 | char programServiceUnsafe[9]; 25 | char programId[5]; 26 | char radioText[65]; 27 | bool newRadioText; 28 | }; 29 | 30 | class TEF6686 { 31 | public: 32 | TEF6686(); 33 | uint8_t init(); 34 | void powerOn(); // call in setup 35 | void powerOff(); 36 | void setFrequency(uint16_t frequency); // frequency as int, i.e. 100.00 as 10000 37 | uint16_t getFrequency(); // returns the current frequency 38 | uint16_t getLevel(); 39 | uint8_t getStereoStatus(); 40 | uint16_t seekUp(); // returns the tuned frequency or 0 41 | uint16_t seekDown(); // returns the tuned frequency or 0 42 | uint16_t tuneUp(); // returns the tuned frequency or 0 43 | uint16_t tuneDown(); // returns the tuned frequency or 0 44 | void setVolume(uint16_t volume); //-60 -- +24 dB volume 45 | void setMute(); 46 | void setUnMute(); 47 | bool readRDS(); 48 | void getRDS(RdsInfo* rdsInfo); 49 | void clearRDS(); 50 | 51 | private: 52 | uint16_t seek(uint8_t up); 53 | uint16_t tune(uint8_t up); 54 | void rdsFormatString(char* str, uint16_t length); 55 | 56 | char rdsRadioText[65]; 57 | char rdsProgramService[9]; 58 | char rdsProgramServiceUnsafe[9]; 59 | char rdsProgramId[5]; 60 | uint8_t rdsAb; 61 | char rdsProgramType[17]; 62 | uint8_t isRdsNewRadioText; 63 | 64 | // 0: working with PS A, 1: working with PS B 65 | bool psAB; 66 | // first dimension: ps A, ps B, second dimension: PS characters 67 | char unsafePs[2][8]; 68 | // 4 bit groups, 1111: no data, 0000: no error, 0001: small error, 0010, 0011: large error 69 | uint32_t psErrors = 0xFFFFFFFF; 70 | // 4 bit groups: ps A, B blocks (0-3) is set 71 | uint8_t psCharIsSet = 0; 72 | // previous address (if prev address greater than current, change psAB status) 73 | uint8_t prevAddress = 3; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /radio_serialLCD3a/Tuner_Api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RADIO_FUNC_H 2 | #define __RADIO_FUNC_H 3 | 4 | //#define RADIO_D3_ENABLE 5 | #define RADIO_LITHIO_ENABLE 6 | 7 | 8 | typedef enum{ 9 | Radio_Hero, 10 | Radio_Atomic, 11 | Radio_Atomic2, 12 | Radio_Lithio, 13 | Radio_Helio, 14 | Radio_Dirana3, 15 | 16 | Radio_Last 17 | }eDev_Type; 18 | extern eDev_Type RadioDev; 19 | 20 | #define Is_Radio_Dirana3 (RadioDev == Radio_Dirana3) 21 | #define Is_Radio_Atomic2 (RadioDev == Radio_Atomic2) 22 | #define Is_Radio_Lithio (RadioDev == Radio_Lithio) 23 | #define Is_Radio_Hero (RadioDev == Radio_Hero) 24 | 25 | 26 | #ifndef HIGH 27 | #define HIGH 1 28 | #endif 29 | 30 | #ifndef LOW 31 | #define LOW 0; 32 | #endif 33 | 34 | typedef enum{ 35 | RADIO_PRIMARY, 36 | RADIO_SECONDARY, 37 | 38 | RADIO_ID_LAST 39 | }RADIO_ID; 40 | 41 | 42 | /* tuner mode */ 43 | #define Radio_POWERDOWNMODE 0 44 | #define Radio_PRESETMODE 0x10 45 | #define Radio_SEARCHMODE 0x20 46 | #define Radio_AFUPDATEMODE 0x30 47 | #define Radio_JUMPMODE 0x40 48 | #define Radio_CHECKMODE 0x50 49 | #define Radio_ENDMODE 0x70 50 | 51 | #define TUNER_LEVEL_3dB 3 52 | #define TUNER_LEVEL_5dB 5 53 | #define TUNER_LEVEL_10dB 10 54 | #define TUNER_LEVEL_14dB 14 55 | #define TUNER_LEVEL_20dB 20 56 | #define TUNER_LEVEL_25dB 25 57 | #define TUNER_LEVEL_30dB 30 58 | #define TUNER_LEVEL_35dB 35 59 | #define TUNER_LEVEL_40dB 40 60 | #define TUNER_LEVEL_45dB 45 61 | #define TUNER_LEVEL_50dB 50 62 | #define TUNER_LEVEL_55dB 55 63 | #define TUNER_LEVEL_60dB 60 64 | 65 | #define TUNER_PERCENT_27 27 66 | #define TUNER_PERCENT_23 23 67 | #define TUNER_PERCENT_20 20 68 | 69 | #define TUNER_OFFSET_10KHz 100 70 | #define TUNER_OFFSET_1500Hz 15 71 | #define TUNER_OFFSET_300KHz 300 72 | 73 | 74 | #define RADIO_FM_LEVEL_AVAILABLE_TIME 4 //5 ms after tuning 75 | #define RADIO_AM_LEVEL_AVAILABLE_TIME 36 //36 ms after tuning 76 | #define RADIO_USN_AVAILABLE_TIME 34 //34ms 77 | 78 | #define FM_SCAN_LEVEL TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 79 | #define AM_SCAN_LEVEL TUNER_LEVEL_35dB //dB, 0.5dB/step -8dB~99.5dB 80 | #define FM_SCAN_LEVEL_HI TUNER_LEVEL_45dB //dB, 0.5dB/step -8dB~99.5dB 81 | #define AM_SCAN_LEVEL_HI TUNER_LEVEL_55dB //dB, 0.5dB/step -8dB~99.5dB 82 | 83 | #define FM_USN_DISTURBANCE TUNER_PERCENT_27 //disturbance = 27% 84 | #define FM_WAM_DISTURBANCE TUNER_PERCENT_23 //disturbance = 23% 85 | 86 | #define FM_FREQ_OFFSET TUNER_OFFSET_10KHz //offset = 10k, step=100Hz 87 | #define AM_FREQ_OFFSET TUNER_OFFSET_1500Hz //offset = 1.5k, step=100Hz 88 | 89 | #define STEREO_Separation_Level_H TUNER_LEVEL_20dB //Stereo indication by LEVEL 90 | #define STEREO_Separation_Level_L TUNER_LEVEL_14dB //Stereo indication by LEVEL 91 | 92 | //RDS search condition 93 | #define RDS_STOP_LEVEL TUNER_LEVEL_20dB 94 | #define RDS_STOP_USN TUNER_PERCENT_20 95 | #define RDS_STOP_WAM TUNER_PERCENT_20 96 | #define RDS_STOP_IFCResult TUNER_OFFSET_300KHz //30KHz 97 | 98 | 99 | /*radio band define*/ 100 | #define MaxBandNum 9 101 | #define FM1_BAND 0 102 | #define FM2_BAND 1 103 | #define FM3_BAND 2 104 | #define MW_BAND 3 105 | #define LW_BAND 4 106 | #define SW_BAND 5 107 | #define WX_BAND 6 108 | #define DAB_3_BAND 7 109 | #define DAB_L_BAND 8 110 | 111 | /*one step define 112 | NOTE:FM Freqency uint is 10KHz,AM Freqency uint is 1KHz*/ 113 | #define AM_Step_9k 9 //am step 9khz 114 | #define AM_Step_10k 10 //am step 10khz 115 | #define FM_Step_50k 5 //fm step 50khz 116 | #define FM_Step_100k 10 //fm step 10 0khz 117 | #define FM_Step_200k 20 //fm step 200khz 118 | 119 | /*tuner scan/seek condition define*/ 120 | #define Radio_ScanLevel TUNER_LEVEL_25dB //dB, 0.5dB/step -8dB~99.5dB 121 | #define Radio_FMScanSen ((uint8_t)((Radio_ScanLevel+8)*2))//DX 122 | #define Radio_FMScanSen_Loc ((uint8_t)((Radio_ScanLevel+TUNER_LEVEL_20dB+8)*2))// Local Att=DX+20 123 | #define Radio_FMScanUNoise 70 124 | #define Radio_FMScanMNoise 60 125 | #define Radio_FMScanOffset 10 126 | 127 | #define Radio_FM_Status 0x20 128 | #define Radio_AMScanSen ((8+TUNER_LEVEL_35dB)*2)//DX 129 | #define Radio_AMScanSen_Loc ((8+TUNER_LEVEL_35dB+20)*2) // Local Att=DX+20 130 | #define Radio_AMScanOffset TUNER_OFFSET_1500Hz 131 | #define Radio_AM_Status 0xA0 132 | 133 | #define StereoSeparation_Level_H ((uint8_t)((TUNER_LEVEL_20dB+8)*2)) //Stereo indication by LEVEL 134 | #define StereoSeparation_Level_L ((uint8_t)((TUNER_LEVEL_14dB+8)*2)) //Stereo indication by LEVEL 135 | /*check station result */ 136 | #define NO_STATION 90 137 | #define PRESENT_STATION 100 138 | 139 | /*station max*/ 140 | #define MaxStationNum 7/*Station count(6)+current statuin(1)1*/ 141 | 142 | 143 | 144 | #define F_UP 1 145 | #define F_DOWN 0 146 | #define StationRecordLen (MaxBandNum*MaxStationNum*2) 147 | 148 | /*are config parameters struct*/ 149 | typedef struct{ //area radio parameter 150 | uint32_t FM_MaxFreq; //fm max freq 151 | uint32_t FM_MinFreq; //fm min freq 152 | uint32_t AM_MaxFreq; // am max freq 153 | uint32_t AM_MinFreq; //am min freq 154 | uint32_t FM_AutoSeekStep; // fm step 155 | uint32_t FM_ManualSeekStep; 156 | uint32_t AM_AutoSeekStep; //am step 157 | uint32_t AM_ManualSeekStep; 158 | }Radio_AreaConfigDef; 159 | 160 | /*area define*/ 161 | enum Radio_AreaCode{ 162 | Radio_CHN=0, 163 | Radio_EUR, 164 | Radio_USA, 165 | Radio_JPN 166 | }; 167 | 168 | /*band freq range*/ 169 | typedef struct 170 | { 171 | uint16_t MinFreq; 172 | uint16_t MaxFreq; 173 | }FreqBaundDef; 174 | 175 | /*tation freq*/ 176 | typedef struct 177 | { 178 | uint16_t Freq[MaxStationNum]; //0-current work freq,or backup freq; 179 | }StationMemType; 180 | 181 | typedef enum 182 | { 183 | eAR_TuningAction_Standby = 0, 184 | eAR_TuningAction_Preset = 1, /*!< Tune to new program with short mute time */ 185 | eAR_TuningAction_Search = 2, /*!< Tune to new program and stay muted */ 186 | eAR_TuningAction_AF_Update = 3, /*!< Tune to alternative frequency, store quality and tune back with inaudible mute */ 187 | eAR_TuningAction_Jump = 4, /*!< Tune to alternative frequency with short inaudible mute */ 188 | eAR_TuningAction_Check = 5, /*!< Tune to alternative frequency and stay muted */ 189 | eAR_TuningAction_End = 7 /*!< Release the mute of a Search/Check action (frequency is ignored) */ 190 | } AR_TuningAction_t, *pAR_TuningAction_t; 191 | 192 | /*band function*/ 193 | extern void Radio_SetBand(uint8_t Band); 194 | extern void Radio_NextBand(void); 195 | extern uint8_t Radio_IsFMBand(void); 196 | extern uint8_t Radio_GetCurrentBand(void); 197 | 198 | /*preset function*/ 199 | extern void Radio_ClearCurrentStation(void); 200 | extern uint8_t Radio_GetCurrentStation(void); 201 | 202 | /*radio freqency function*/ 203 | extern void Radio_SetFreq(uint8_t mode,uint8_t Band,uint16_t Freq); 204 | extern uint32_t Radio_GetFreqStep(uint8_t band); 205 | extern void Radio_ChangeFreqOneStep(uint8_t UpDown); 206 | extern uint16_t Radio_GetCurrentFreq(void); 207 | 208 | 209 | /*check station */ 210 | extern void Radio_CheckStation(void); 211 | extern void Radio_CheckStationInit(void); 212 | extern uint8_t Radio_CheckStationStatus(void); 213 | 214 | void Radio_SetSeekSenLevel(uint8_t Lev); 215 | uint8_t Radio_CheckStereo(void); 216 | uint16_t Radio_Get_Level(uint8_t fm); 217 | uint8_t Radio_Is_AF_Update_Available (void); 218 | uint8_t Radio_Is_RDAV_Available (void); 219 | uint16_t Radio_Get_RDS_Data(uint32_t*rds_data); 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /radio_serialLCD3a/Tuner_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include "TEF6686.h" 2 | #include "Tuner_Patch_Lithio_V102_p209.h" 3 | 4 | TwoWire Wire2; 5 | 6 | #define INIT_FLAG_TIMER 0xff 7 | #define INIT_FLAG_PATCH1 0xfe 8 | #define INIT_FLAG_PATCH2 0xfd 9 | 10 | static const unsigned char tuner_init_tab[] = { 11 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 12 | 3, 0x1C,0x00,0x74,//Set Required Initialization Control(1) 13 | //Load Required Initialization(s).... 14 | 1, INIT_FLAG_PATCH1, 15 | 16 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 17 | 3, 0x1C,0x00,0x75,//Set Required Initialization Control(2) 18 | //Load Required Initialization(s).... 19 | 1, INIT_FLAG_PATCH2, 20 | 21 | 3, 0x1c,0x00,0x00,//Clear Required Initialization Control 22 | 3, 0x14,0x00,0x01,//Start Firmware.... 23 | 24 | //wait 50ms 25 | 2, INIT_FLAG_TIMER,50, //(Boot state to Idle State) 26 | 27 | 9, 0x40,0x04,0x01,0x00,0x8C,0xA0,0x00,0x00,0x00,//APPL_Set_ReferenceClock 28 | 29 | //Activate Device...(Idle state to Active state) 30 | 5, 0x40,0x05,0x01,0x00,0x01,// APPL_Activate 31 | //wait 100ms 32 | 2, INIT_FLAG_TIMER,100, //(Idle state to Active state) 33 | 34 | 11, 0x20,0x0A,0x01,0x00,0x01,0x09,0x38,0x03,0xE8,0x03,0xE8, // FM_Set_Bandwidth (1, 1, 2360, 1000, 1000) 35 | 5, 0x20,0x16,0x01,0x00,0x01, // FM_Set_ChannelEqualizer (1, 1) 36 | 5, 0x20,0x1F,0x01,0x01,0xF4, // FM_Set_Deemphasis (1, 500) 37 | 5, 0x20,0x1E,0x01,0x00,0x00, // FM_Set_DigitalRadio (1, 0) 38 | 11, 0x20,0x53,0x01,0x00,0x00,0x00,0x32,0x00,0x32,0x00,0x00, // FM_Set_DR_Blend (1, 0, 50, 50, 0) 39 | 9, 0x20,0x54,0x01,0x00,0x00,0x22,0x04,0x10,0x10, // FM_Set_DR_Options (1, 0, 8708, 4112) 40 | 5, 0x20,0x14,0x01,0x00,0x01, // FM_Set_MphSuppression (1, 1) 41 | 7, 0x20,0x17,0x01,0x00,0x01,0x03,0xE8, // FM_Set_NoiseBlanker (1, 1, 1000) 42 | 7, 0x20,0x52,0x01,0x00,0x00,0x00,0x00, // FM_Set_QualityStatus (1, 0, 0) 43 | 7, 0x20,0x52,0x01,0x00,0xC8,0x00,0x00, // FM_Set_QualityStatus (1, 200, 0) 44 | 7, 0x20,0x0B,0x01,0x03,0x98,0x00,0x00, // FM_Set_RFAGC (1, 920, 0) 45 | 5, 0x20,0x50,0x01,0x00,0x00, // FM_Set_Scaler (1, 0) 46 | 5, 0x20,0x55,0x01,0x00,0x00, // FM_Set_Specials (1, 0) 47 | 11, 0x20,0x02,0x01,0x00,0x00,0x09,0x38,0x03,0xE8,0x07,0xD0, // FM_Set_Tune_Options (1, 0, 2360, 1000, 2000) 48 | 9, 0x20,0x51,0x01,0x00,0x01,0x00,0x02,0x00,0x00, // FM_Set_RDS (1, 1, 2, 0) 49 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 50 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 51 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 52 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 53 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 54 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 55 | 17, 0x20,0x26,0x01,0xFF,0xEC,0xFF,0xE2,0xFF,0xD8,0xFF,0xCE,0xFF,0xC4,0xFF,0xC4,0xFF,0xC4, // FM_Set_LevelStep (1, -20, -30, -40, -50, -60, -60, -60) 56 | 5, 0x20,0x27,0x01,0x00,0x00, // FM_Set_LevelOffset (1, 0) 57 | 9, 0x20,0x2A,0x01,0x00,0x02,0x00,0x96,0x00,0xDC, // FM_Set_SoftMute_Level (1, 2, 150, 220) 58 | 11, 0x20,0x28,0x01,0x00,0x78,0x01,0xF4,0x00,0x0A,0x00,0x14, // FM_Set_SoftMute_Time (1, 120, 500, 10, 20) 59 | 9, 0x20,0x2C,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Mph (1, 0, 200, 1000) 60 | 9, 0x20,0x2B,0x01,0x00,0x00,0x00,0xC8,0x03,0xE8, // FM_Set_SoftMute_Noise (1, 0, 200, 1000) 61 | 7, 0x20,0x2D,0x01,0x00,0x01,0x00,0xC8, // FM_Set_SoftMute_Max (1, 1, 200) 62 | 9, 0x20,0x34,0x01,0x00,0x03,0x01,0x68,0x01,0x2C, // FM_Set_HighCut_Level (1, 3, 360, 300) 63 | 11, 0x20,0x32,0x01,0x00,0xC8,0x07,0xD0,0x00,0x0A,0x00,0x50, // FM_Set_HighCut_Time (1, 200, 2000, 10, 80) 64 | 11, 0x20,0x33,0x01,0x00,0x00,0x00,0xFA,0x00,0x82,0x01,0xF4, // FM_Set_HighCut_Mod (1, 0, 250, 130, 500) 65 | 9, 0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_HighCut_Mph (1, 3, 120, 160) 66 | 9, 0x20,0x35,0x01,0x00,0x03,0x00,0x96,0x00,0xC8, // FM_Set_HighCut_Noise (1, 3, 150, 200) 67 | 7, 0x20,0x3A,0x01,0x00,0x00,0x00,0x14, // FM_Set_LowCut_Min (1, 0, 20) 68 | 7, 0x20,0x37,0x01,0x00,0x01,0x09,0x60, // FM_Set_HighCut_Max (1, 1, 2400) 69 | 7, 0x20,0x39,0x01,0x00,0x01,0x00,0x64, // FM_Set_LowCut_Max (1, 1, 100) 70 | 5, 0x20,0x3B,0x01,0x00,0x01, // FM_Set_HighCut_Options (1, 1) 71 | 9, 0x20,0x3E,0x01,0x00,0x03,0x01,0xCC,0x00,0xF0, // FM_Set_Stereo_Level (1, 3, 460, 240) 72 | 11, 0x20,0x3C,0x01,0x00,0xC8,0x0F,0xA0,0x00,0x14,0x00,0x50, // FM_Set_Stereo_Time (1, 200, 4000, 20, 80) 73 | 11, 0x20,0x3D,0x01,0x00,0x00,0x00,0xD2,0x00,0x5A,0x01,0xF4, // FM_Set_Stereo_Mod (1, 0, 210, 90, 500) 74 | 9, 0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96, // FM_Set_Stereo_Mph (1, 3, 100, 150) 75 | 9, 0x20,0x3F,0x01,0x00,0x03,0x00,0x78,0x00,0xA0, // FM_Set_Stereo_Noise (1, 3, 120, 160) 76 | 7, 0x20,0x42,0x01,0x00,0x00,0x01,0x90, // FM_Set_Stereo_Min (1, 0, 400) 77 | 5, 0x20,0x41,0x01,0x00,0x01, // FM_Set_Stereo_Max (1, 1) 78 | 9, 0x20,0x48,0x01,0x00,0x03,0x02,0x58,0x00,0xF0, // FM_Set_StHiBlend_Level (1, 3, 600, 240) 79 | 11, 0x20,0x46,0x01,0x01,0xF4,0x07,0xD0,0x00,0x14,0x00,0x14, // FM_Set_StHiBlend_Time (1, 500, 2000, 20, 20) 80 | 11, 0x20,0x47,0x01,0x00,0x00,0x00,0xF0,0x00,0x78,0x02,0x9E, // FM_Set_StHiBlend_Mod (1, 0, 240, 120, 670) 81 | 9, 0x20,0x4A,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Mph (1, 3, 80, 140) 82 | 9, 0x20,0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8C, // FM_Set_StHiBlend_Noise (1, 3, 80, 140) 83 | 7, 0x20,0x4C,0x01,0x00,0x00,0x1B,0x58, // FM_Set_StHiBlend_Min (1, 0, 7000) 84 | 7, 0x20,0x4B,0x01,0x00,0x01,0x0F,0xA0, // FM_Set_StHiBlend_Max (1, 1, 4000) 85 | //Set the Audio and Application related API settings... 86 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x21,0x00,0x03, // APPL_Set_GPIO (1, 0, 33, 3) 87 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 1, 33, 0) 88 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x21,0x00,0x00, // APPL_Set_GPIO (1, 2, 33, 0) 89 | 9, 0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03, // APPL_Set_GPIO (1, 0, 32, 3) 90 | 9, 0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 1, 32, 0) 91 | 9, 0x40,0x03,0x01,0x00,0x02,0x00,0x20,0x00,0x00, // APPL_Set_GPIO (1, 2, 32, 0) 92 | 7, 0x30,0x15,0x01,0x00,0x80,0x00,0x01, // AUDIO_Set_Ana_Out (1, 128, 1) 93 | 13, 0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 32, 0, 32, 0, 4410) 94 | 13, 0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3A, // AUDIO_Set_Dig_IO (1, 33, 0, 32, 0, 4410) 95 | 5, 0x30,0x0C,0x01,0x00,0x00, // AUDIO_Set_Input (1, 0) 96 | 7, 0x30,0x17,0x01,0x00,0x20,0x00,0x00, // AUDIO_Set_Input_Scaler (1, 32, 0) 97 | 5, 0x30,0x0B,0x01,0x00,0x00, // AUDIO_Set_Mute (1, 0) 98 | 5, 0x30,0x0A,0x01,0x00,0x00, // AUDIO_Set_Volume (1, 0) 99 | 15, 0x30,0x18,0x01,0x00,0x00,0x00,0x00,0xFF,0x38,0x01,0x90,0xFF,0x38,0x03,0xE8, // AUDIO_Set_WaveGen (1, 0, 0, -200, 400, -200, 1000) 100 | 7, 0x30,0x0D,0x01,0x00,0x21,0x00,0xE0, // AUDIO_Set_Output_Source (1, 33, 224) 101 | 7, 0x30,0x0D,0x01,0x00,0x80,0x00,0xE0, // AUDIO_Set_Output_Source (1, 128, 224) 102 | }; 103 | 104 | //return 1 --> IIC sucess 105 | unsigned char Tuner_WriteBuffer(unsigned char *buf, uint16_t len) 106 | { 107 | uint16_t i; 108 | uint8_t r; 109 | //Serial.println(I2C_ADDR, HEX); 110 | //Serial.println("Send to I2C: "); 111 | Wire2.beginTransmission(I2C_ADDR); 112 | //Serial.println("beginTransmission"); 113 | for (i = 0; i < len; i++) { 114 | Wire2.write(buf[i]); 115 | //Serial.print(buf[i], HEX); 116 | //Serial.print(" "); 117 | } 118 | //Serial.println("Wire.write"); 119 | r = Wire2.endTransmission(); 120 | //Serial.println("Wire.endTransmission:"); 121 | //Serial.print(r); 122 | //Serial.println(); 123 | delay(1); 124 | return (r == 0) ? 1 : 0; 125 | } 126 | 127 | unsigned char Tuner_ReadBuffer(unsigned char *buf, uint16_t len) 128 | { 129 | uint16_t i; 130 | //Serial.println("\nRead from I2C: "); 131 | Wire2.requestFrom(I2C_ADDR, len); 132 | if (Wire2.available() == len) { 133 | for (i = 0; i < len; i++) { 134 | buf[i] = Wire2.read(); 135 | //Serial.print(buf[i], HEX); 136 | //Serial.print(" "); 137 | } 138 | //Serial.println(); 139 | return 1; 140 | } 141 | return 0; 142 | } 143 | 144 | void Tuner_WaitMs (uint16_t ms) 145 | { 146 | delay(ms); 147 | } 148 | //-------------------------------------------------------------------------------------------- 149 | 150 | 151 | //------------load patch and init parameters----------------- 152 | 153 | /* 154 | The transmission example below shows a data content of 12 words for every data transmission. 155 | The data stream can be split in any desired length on (2-byte) word boundaries with every data transmission starting with hex value 1B 156 | */ 157 | #define TEF665X_SPLIT_SIZE 24 158 | static uint16_t Tuner_Patch_Load(const unsigned char * pLutBytes, uint16_t size) 159 | { 160 | unsigned char buf[TEF665X_SPLIT_SIZE+1]; 161 | uint16_t i,len; 162 | uint16_t r; 163 | 164 | buf[0] = 0x1b; 165 | 166 | while(size) 167 | { 168 | len = (size>TEF665X_SPLIT_SIZE)? TEF665X_SPLIT_SIZE : size; 169 | size -= len; 170 | 171 | for(i=0;i 6 | #include 7 | // Make a SoftwareSerial object, and a new SerLCD object, 8 | // which points at the NewSoftSerial object. 9 | // 10 | // In this demo the Rx pin of the SerLCD is connected to 11 | // Arduino digital pin 4 (Tx) We set the SoftwareSerial 12 | // Rx to 0 because the SerLCD has no facility to transmit 13 | // back. 14 | // 15 | SoftwareSerial NSS(255,4,1); 16 | SerLCD lcd(NSS,20,4); 17 | 18 | #include "TEF6686.h" 19 | 20 | uint16_t frequency; 21 | int volume; 22 | int volume2; 23 | byte plus = 0; 24 | 25 | bool isRdsSync; 26 | 27 | char programTypePrevious[17] = " "; 28 | char programServicePrevious[9]; 29 | char programServiceUnsafePrevious[9]; 30 | char programIdPrevious[4]; 31 | char radioTextPrevious[65]; 32 | 33 | TEF6686 radio; 34 | RdsInfo rdsInfo; 35 | 36 | void setup() { 37 | NSS.begin(9600); 38 | lcd.begin(); 39 | lcd.clear(); 40 | // Print a logo message to the LCD. 41 | lcd.setPosition(1, 0); 42 | lcd.print(" TEF6686 radio v.3 "); 43 | lcd.setPosition(2, 0); 44 | lcd.print("github.com/kkonradpl"); 45 | lcd.setPosition(3, 0); 46 | lcd.print(" updated by niq_ro "); 47 | lcd.setPosition(4, 0); 48 | lcd.print(" github.com/tehniq3 "); 49 | delay (3000); 50 | lcd.clear(); 51 | 52 | delay(1000); 53 | Serial.begin(115200); 54 | while (!Serial); 55 | Serial.println(F("Start")); 56 | radio.init(); 57 | radio.powerOn(); 58 | radio.setFrequency(9800); 59 | frequency = radio.getFrequency(); 60 | //displayInfo(); 61 | radioGui(1); 62 | 63 | } 64 | 65 | void loop() { 66 | readRds(); 67 | radioGui(0); 68 | displayInfo(); 69 | if (Serial.available()) { 70 | char ch = Serial.read(); 71 | if (ch == 'm') { 72 | radio.setMute(); 73 | Serial.println("Mute"); 74 | //displayInfo(); 75 | } 76 | else if (ch == 'n') { 77 | radio.setUnMute(); 78 | Serial.println("Unmute"); 79 | //displayInfo(); 80 | } 81 | else if (ch == 'p') { 82 | radio.powerOn(); 83 | Serial.println("Power ON"); 84 | //displayInfo(); 85 | } 86 | else if (ch == 'o') { 87 | radio.powerOff(); 88 | Serial.println("Power OFF"); 89 | //displayInfo(); 90 | } 91 | if (ch == 'u') { 92 | frequency = radio.seekUp(); 93 | //displayInfo(); 94 | radioGui(true); 95 | } 96 | else if (ch == 'd') { 97 | frequency = radio.seekDown(); 98 | //displayInfo(); 99 | radioGui(true); 100 | } 101 | else if (ch == '+') { 102 | volume += 4; 103 | if (volume >= 24) volume = 24; 104 | radio.setVolume(volume); 105 | displayInfo(); 106 | } 107 | else if (ch == '-') { 108 | volume -= 4; 109 | if (volume < -60) volume = -60; 110 | radio.setVolume(volume); 111 | displayInfo(); 112 | } 113 | else if (ch == '8') { 114 | frequency = radio.tuneUp(); 115 | //displayInfo(); 116 | radioGui(true); 117 | } 118 | else if (ch == '2') { 119 | frequency = radio.tuneDown(); 120 | //displayInfo(); 121 | radioGui(true); 122 | } 123 | else if (ch == 'r') { 124 | radioGui(true); 125 | } 126 | } 127 | /* 128 | delay(500); 129 | lcd.setPosition(3, 0); 130 | lcd.print(" "); 131 | lcd.setPosition(4, 0); 132 | lcd.print(" "); 133 | */ 134 | } 135 | 136 | void readRds() { 137 | isRdsSync = radio.readRDS(); 138 | radio.getRDS(&rdsInfo); 139 | } 140 | 141 | void showPI() { 142 | if (isNewPi()){ 143 | strcpy(programIdPrevious, rdsInfo.programId); 144 | } 145 | Serial.print(rdsInfo.programId); 146 | lcd.setPosition(2, 13); 147 | lcd.print(rdsInfo.programId); 148 | } 149 | 150 | bool isNewPi(){ 151 | return (strlen(rdsInfo.programId) == 4) && !strcmp(rdsInfo.programId, programIdPrevious, 4); 152 | } 153 | 154 | 155 | void showPTY() { 156 | if (isNewPty()) { 157 | strcpy(programTypePrevious, rdsInfo.programType); 158 | } 159 | Serial.print(rdsInfo.programType); 160 | lcd.setPosition(3, 10); 161 | lcd.print(rdsInfo.programType); 162 | } 163 | 164 | bool isNewPty() { 165 | return (isRdsSync == 1) && !strcmp(rdsInfo.programType, programTypePrevious, 16); 166 | } 167 | 168 | void showPS() { 169 | if (isNewPs()) { 170 | strcpy(programServicePrevious, rdsInfo.programService); 171 | } 172 | Serial.print(rdsInfo.programService); 173 | lcd.setPosition(3, 0); 174 | lcd.print(rdsInfo.programService); 175 | 176 | } 177 | 178 | void showPsUnsafe(){ 179 | if (isNewPsUnsafe()){ 180 | strcpy(programServiceUnsafePrevious, rdsInfo.programServiceUnsafe); 181 | } 182 | Serial.print(rdsInfo.programServiceUnsafe); 183 | lcd.setPosition(4, 0); 184 | lcd.print(rdsInfo.programServiceUnsafe); 185 | } 186 | 187 | bool isNewPs() { 188 | return (strlen(rdsInfo.programService) == 8) && !strcmp(rdsInfo.programService, programServicePrevious, 8); 189 | } 190 | 191 | bool isNewPsUnsafe() { 192 | return (strlen(rdsInfo.programServiceUnsafe) == 8) && !strcmp(rdsInfo.programServiceUnsafe, programServiceUnsafePrevious, 8); 193 | } 194 | 195 | 196 | void showRadioText() { 197 | if (isNewRt()){ 198 | strcpy(radioTextPrevious, rdsInfo.radioText); 199 | } 200 | Serial.print(rdsInfo.radioText); 201 | lcd.setPosition(4, 10); 202 | lcd.print(rdsInfo.radioText); 203 | } 204 | 205 | 206 | bool isNewRt() { 207 | return (isRdsSync == 1) && !strcmp(rdsInfo.radioText, radioTextPrevious, 65); 208 | } 209 | 210 | bool strcmp(char* str1, char* str2, int length) { 211 | for (int i = 0; i < length; i++) { 212 | if (str1[i] != str2[i]) { 213 | return false; 214 | } 215 | } 216 | return true; 217 | } 218 | 219 | void displayInfo() { 220 | delay(10); 221 | Serial.print(F("Frequency:")); 222 | Serial.print(frequency); 223 | Serial.print(F(" Volume:")); 224 | Serial.println(volume); 225 | Serial.print(F("Level:")); 226 | Serial.println(radio.getLevel() / 10); 227 | Serial.print(F("Stereo:")); 228 | Serial.println(radio.getStereoStatus()); 229 | lcd.setPosition(1, 0); 230 | if (frequency < 10000) lcd.print(" "); 231 | lcd.print(frequency/100); 232 | lcd.print(","); 233 | lcd.print(frequency%100); 234 | lcd.print("MHz"); 235 | lcd.setPosition(2, 0); 236 | // lcd.print("vol."); 237 | if (volume > 0) 238 | { 239 | plus = 1; 240 | volume2 = volume; 241 | } 242 | else 243 | { 244 | plus = 0; 245 | volume2 = -volume; 246 | } 247 | if (volume2/10 == 0) 248 | lcd.print(" "); 249 | if (volume2 == 0) lcd.print(" "); 250 | else 251 | if (plus == 0) 252 | { 253 | lcd.print("-"); 254 | } 255 | else 256 | { 257 | lcd.print("+"); 258 | } 259 | lcd.print(volume2); 260 | lcd.print("dB"); 261 | lcd.setPosition(2, 6); 262 | // lcd.print("level:"); 263 | if (radio.getLevel() < 100) 264 | lcd.print(" "); 265 | if (radio.getLevel() < 10) 266 | lcd.print(" "); 267 | lcd.print(radio.getLevel()); 268 | lcd.print("%"); 269 | lcd.setPosition(1, 13); 270 | if (radio.getStereoStatus() == 1) 271 | lcd.print("STEREO "); 272 | else 273 | lcd.print(" "); 274 | } 275 | 276 | void radioGui(bool force){ 277 | if (force || isNewPi() || isNewPs() || isNewPsUnsafe()) { 278 | //clrscr 279 | Serial.write(27); // ESC command 280 | Serial.print("[2J"); // clear screen command 281 | Serial.write(27); 282 | Serial.print("[H"); // cursor to home command 283 | 284 | //first line 285 | Serial.print(F("FM ")); 286 | Serial.print(frequency / 100); 287 | Serial.print(F(".")); 288 | Serial.print(frequency % 100 / 10); 289 | Serial.print(F(" MHz ")); 290 | 291 | Serial.print(frequency >= 10000 ? F("[ ") : F(" [ ")); 292 | showPS(); 293 | Serial.print(" ]"); 294 | 295 | //second line 296 | Serial.println(); 297 | Serial.print(F("PI: ")); 298 | showPI(); 299 | Serial.print(F(" ( ")); 300 | showPsUnsafe(); 301 | Serial.print(F(" ) ")); 302 | 303 | Serial.println(); 304 | Serial.print(F("PTY: ")); 305 | showPTY(); 306 | Serial.println(); 307 | Serial.print( ("radio text: ")); 308 | showRadioText(); 309 | Serial.println(); 310 | Serial.println(); 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /radio_serialLCD3a/test.txt: -------------------------------------------------------------------------------- 1 | original from https://github.com/makserge/tef6686_radio 2 | small changes by Nicu FLORICA (niq_ro) 3 | https://www.arduinotehniq.com 4 | -------------------------------------------------------------------------------- /tef6686_v3_LUXYFM.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tehniq3/TEF6686/a88e8937188dedbab6ab5d574bf41f35a68fbcbe/tef6686_v3_LUXYFM.jpg -------------------------------------------------------------------------------- /th0Dsgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tehniq3/TEF6686/a88e8937188dedbab6ab5d574bf41f35a68fbcbe/th0Dsgr.png --------------------------------------------------------------------------------