PU2CLR RDA5807 Arduino Library 1.1.4
Arduino Library for RDA5807 Devices - By Ricardo Lima Caratti
Loading...
Searching...
No Matches
RDA5807.h
Go to the documentation of this file.
1
2/**
3 * @mainpage PU2CLR rda Arduino Library
4 * @brief PU2CLR rda Arduino Library implementation. <br>
5 * @details This library works with I2C protocol and can provide an easier interface for controlling the RDA5807M devices.<br>
6 * @details This is an Arduino library was implemented based on RDA5807M - SINGLE-CHIP BROADCAST FMRADIO TUNER document from RDA microeletronics.
7 * @details and RDA microelectronics RDA5807FP - SINGLE-CHIP BROADCAST FM RADIO TUNER
8 *
9 * @details IMPORTANT:
10 * @details The RDA5807M can be accessed by using two I2C bus address.
11 * @details If you need to access a specific register, use the 0x11 buss adress.
12 * @details If you need to access a set o register, use the 0x10 buss adress.
13 *
14 * @see RDA5807M - SINGLE-CHIP BROADCAST FMRADIO TUNER; page 5.
15 * @see the methods setRegister, getDirectRegister and getStatusRegisters
16 *
17 * This library can be freely distributed using the MIT Free Software model.
18 * Copyright(c) 2020 Ricardo Lima Caratti.
19 * Contact : pu2clr @gmail.com
20 *
21 */
22
23#ifndef _RDA5807_H // Prevent this file from being compiled more than once
24#define _RDA5807_H
25
26#include <Arduino.h>
27#include <Wire.h>
28
29#define MAX_DELAY_AFTER_OSCILLATOR 500 // Max delay after the crystal oscilator becomes active
30
31
32#define I2C_ADDR_DIRECT_ACCESS 0x11 //!< Can be used to access a given register at a time.
33#define I2C_ADDR_FULL_ACCESS 0x10 //!< Can be used to access a set of register at a time.
34
35
36#define OSCILLATOR_TYPE_CRYSTAL 0 //!< Crystal
37#define OSCILLATOR_TYPE_REFCLK 1 //!< Reference clock
38
39#define CLOCK_32K 0 //!< 32.768kHz
40#define CLOCK_12M 1 //!< 12Mhz
41#define CLOCK_13M 2 //!< 13Mhz
42#define CLOCK_19_2M 3 //!< 19.2Mhz
43#define CLOCK_24M 5 //!< 24Mhz
44#define CLOCK_26M 6 //!< 26Mhz
45#define CLOCK_38_4M 7 //!< 38.4Mhz
46
47#define RDS_STANDARD 0 //!< RDS Mode.
48#define RDS_VERBOSE 1 //!< RDS Mode.
49
50#define RDA_FM_BAND_USA_EU 0 //!< 87.5–108 MHz (US / Europe, Default)
51#define RDA_FM_BAND_JAPAN_WIDE 1 //!< 76–91 MHz (Japan wide band)
52#define RDA_FM_BAND_WORLD 2 //!< 76–108 MHz (world wide)
53#define RDA_FM_BAND_SPECIAL 3 //!< 65 –76 MHz(East Europe) or 50 - 65MHz(see bit 9 of gegister 0x06)
54
55#define RDA_SEEK_WRAP 0 //!< Wrap at the upper or lower band limit and continue seeking
56#define RDA_SEEK_STOP 1 //!< Stop seeking at the upper or lower band limit
57#define RDA_SEEK_DOWN 0 //!< Seek Up
58#define RDA_SEEK_UP 1 //!< Seek Down
59
60#define REG00 0x00
61#define REG02 0x02
62#define REG03 0x03
63#define REG04 0x04
64#define REG05 0x05
65#define REG06 0x06
66#define REG07 0x07
67#define REG0A 0x0A
68#define REG0B 0x0B
69#define REG0C 0x0C
70#define REG0D 0x0D
71#define REG0E 0x0E
72#define REG0F 0x0F
73
74#define SH_REG0A 0 // Shadow array position for register 0x0A
75#define SH_REG0B 1 // Shadow array position for register 0x0B
76#define SH_REG0C 2 // Shadow array position for register 0x0C - RDS Block A
77#define SH_REG0D 3 // Shadow array position for register 0x0D - RDS Block B
78#define SH_REG0E 4 // Shadow array position for register 0x0E - RDS Block C
79#define SH_REG0F 5 // Shadow array position for register 0x0F - RDS Block D
80
81
82#define I2S_WS_STEP_48 0b1000
83#define I2S_WS_STEP_44_1 0b0111
84#define I2S_WS_STEP_32 0b0110
85#define I2S_WS_STEP_24 0b0101
86#define I2S_WS_STEP_22_05 0b0100
87#define I2S_WS_STEP_16 0b0011
88#define I2S_WS_STEP_12 0b0010
89#define I2S_WS_STEP_11_025 0b0001
90#define I2S_WS_STEP_8 0b0000
91
92
93/**
94 * @defgroup GA01 Union, Structure and Defined Data Types
95 * @brief rda Defined Data Types
96 * @details Defined Data Types is a way to represent the rda registers information
97 * @details The information shown here was extracted from Datasheet:
98 * @details rda stereo FM digital tuning radio documentation.
99 */
100
101/**
102 * @ingroup GA01
103 * @brief Register 0x00
104 *
105 */
106 typedef union {
107 struct {
108 uint8_t LOW_CHIP_ID: 8; //!< Chip ifdef
109 uint8_t HIGH_CHIP_ID: 8;
110 } refined;
112} rda_reg00;
113
114/**
115 * @ingroup GA01
116 * @brief Register 0x01 - Dummy
117 * @details It is not documented by the RDA.
118 */
119typedef union
120{
121 struct
122 {
123 uint8_t lowByte;
124 uint8_t highByte;
125 } refined;
127} rda_reg01;
128
129/**
130 * @ingroup GA01
131 * @brief Register 0x02 - Basic setup: RESET configuration;
132 * @details Clock type configuration; seek operation; Sterio/Mono; Bass; and Audio configuration
133 * @details The RDA5807M is RESET itself when power up. You also can use soft reset by triggering SOFT_RESET bit to 1.
134 * @details Seek begins in the direction specified by SEEKUP and ends when a channel is found, or the entire band has been searched.
135 * @details The SEEK bit is set low and the STC bit is set high when the seek operation completes.
136 * @details RCLK NON-CALIBRATE MODE. if 0=RCLK clock is always supply; if 1=RCLK clock is not always supply when FM work ( when 1, RDA5807M can’t directly support -20 °C ~70 °C temperature.
137 * @details Only suppory ±20°C temperature swing from tune point).
138 *
139 * Clock CLK_MODE table
140 *
141 * | Value | Clock |
142 * | ----- | --------- |
143 * | 000 | 32.768kHz |
144 * | 001 | 12Mhz |
145 * | 101 | 24Mhz |
146 * | 010 | 13Mhz |
147 * | 110 | 26Mhz |
148 * | 011 | 19.2Mhz |
149 * | 111 | 38.4Mhz |
150 */
151typedef union {
152 struct
153 {
154 uint8_t ENABLE : 1; //!< Power Up Enable; 0 = Disabled; 1 = Enabled
155 uint8_t SOFT_RESET : 1; //!< Soft reset; If 0, not reset; If 1, reset.
156 uint8_t NEW_METHOD : 1; //!< New Demodulate Method Enable, can improve 0 the receive sensitivity about 1dB.
157 uint8_t RDS_EN : 1; //!< RDS/RBDS enable; If 1, rds/rbds enable
158 uint8_t CLK_MODE : 3; //!< See table above
159 uint8_t SKMODE : 1; //!< Seek Mode; 0 = wrap at the upper or lower band limit and continue seeking; 1 = stop seeking at the upper or lower band limit
160 uint8_t SEEK : 1; //!< Seek; 0 = Disable stop seek; 1 = Enable;
161 uint8_t SEEKUP : 1; //!< Seek Up; 0 = Seek down; 1 = Seek up
162 uint8_t RCLK_DIRECT_IN : 1; //!< RCLK clock use the directly input mode. 1 = enable
163 uint8_t NON_CALIBRATE : 1; //!< 0=RCLK clock is always supply; 1=RCLK clock is not always supply when FM work
164 uint8_t BASS : 1; //!< Bass Boost; 0 = Disabled; 1 = Bass boost enabled
165 uint8_t MONO : 1; //!< Mono Select; 0 = Stereo; 1 = Force mono
166 uint8_t DMUTE : 1; //!< Mute Disable; 0 = Mute; 1 = Normal operation
167 uint8_t DHIZ : 1; //!< Audio Output High-Z Disable; 0 = High impedance; 1 = Normal operation
168 } refined;
170} rda_reg02;
171
172/**
173 * @ingroup GA01
174 * @brief Register 0x03
175 * @details Receiver configuratio
176 * @details The tune operation begins when the TUNE bit is set high. The STC bit is set high when the tune operation completes.
177 * @details The tune bit is reset to low automatically when the tune operation completes
178 *
179 * Channel space table
180 *
181 * | Value | Description |
182 * | ----- | ----------- |
183 * | 00 | 100KHz |
184 * | 01 | 200KHz |
185 * | 10 | 50KHz |
186 * | 11 | 25KHz |
187 *
188 *
189 * FM band table
190 *
191 * | Value | Description |
192 * | ----- | --------------------------- |
193 * | 00 | 87–108 MHz (US/Europe) |
194 * | 01 | 76–91 MHz (Japan) |
195 * | 10 | 76–108 MHz (world wide) |
196 * | 11 | 65 –76 MHz (East Europe) or 50-65MHz (see bit 9 of gegister 0x06) |
197 *
198 * Channel select table
199 *
200 * | BAND | Description |
201 * | ------ | -------------------------------------------------- |
202 * | 0 | Frequency = Channel Spacing (kHz) x CHAN+ 87.0 MHz |
203 * | 1 or 2 | Frequency = Channel Spacing (kHz) x CHAN + 76.0 MHz |
204 * | 3 | Frequency = Channel Spacing (kHz) x CHAN + 65.0 MHz |
205 * IMPORTANT: CHAN is updated after a seek operation.
206 *
207 */
208typedef union {
209 struct
210 {
211 uint16_t SPACE: 2; //!< See Channel space table above
212 uint16_t BAND: 2; //!< Seet band table above
213 uint16_t TUNE : 1; //!< Tune; 0 = Disable; 1 = Enable
214 uint16_t DIRECT_MODE : 1; //!< Directly Control Mode, Only used when test
215 uint16_t CHAN : 10; //!< Channel Select.
216 } refined;
218} rda_reg03;
219
220/**
221 * @ingroup GA01
222 * @brief Register 0x04
223 * @details Receiver properties
224 * @details Volume scale is logarithmic When 0000, output mute and output impedance is very large
225 * @details Setting STCIEN = 1 will generate a low pulse on GPIO2 when the interrupt occurs.
226 */
227typedef union {
228 struct
229 {
230 uint8_t GPIO1 : 2; //!< General Purpose I/O 1. when gpio_sel=01; 00 = High impedance; 01 = Reserved; 10 = Low; 11 = High
231 uint8_t GPIO2 : 2; //!< General Purpose I/O 2. when gpio_sel=01; 00 = High impedance; 01 = Reserved; 10 = Low; 11 = High
232 uint8_t GPIO3 : 2; //!< General Purpose I/O 1. when gpio_sel=01; 00 = High impedance; 01 = Mono/Stereo indicator (ST); 10 = Low; 11 = High
233 uint8_t I2S_ENABLE : 1; //!< I2S enable; 0 = disabled; 1 = enabled.
234 uint8_t RSVD1 : 1;
235 uint8_t AFCD : 1; //!< AFC disable; If 0, afc work; If 1, afc disabled.
236 uint8_t SOFTMUTE_EN : 1; //!< If 1, softmute enable.
237 uint8_t RDS_FIFO_CLR : 1; //!< 1 = clear RDS fifo
238 uint8_t DE : 1; //!< De-emphasis; 0 = 75 μs; 1 = 50 μs
239 uint8_t RDS_FIFO_EN : 1; //!< 1 = RDS fifo mode enable.
240 uint8_t RBDS : 1; //!< 1 = RBDS mode enable; 0 = RDS mode only
241 uint8_t STCIEN : 1; //!< Seek/Tune Complete Interrupt Enable; 0 = Disable Interrupt; 1 = Enable Interrupt;
242 uint8_t RSVD2 : 1;
243 } refined;
245} rda_reg04;
246
247/**
248 * @ingroup GA01
249 * @brief Register 0x05
250 */
251typedef union {
252 struct
253 {
254 uint8_t VOLUME : 4; //!< DAC Gain Control Bits (Volume); 0000 = min volume; 1111 = max volume.
255 uint8_t LNA_ICSEL_BIT : 2; //!< Lna working current bit: 00=1.8mA; 01=2.1mA; 10=2.5mA; 11=3.0mA.
256 uint8_t LNA_PORT_SEL : 2; //!< LNA input port selection bit: 00: no input; 01: LNAN; 10: LNAP; 11: dual port input
257 uint8_t SEEKTH : 4; //!< Seek SNR Threshold value
258 uint8_t RSVD2 : 1;
259 uint8_t SEEK_MODE : 2; //!< Default value is 00; When = 10, will add the RSSI seek mode
260 uint8_t INT_MODE : 1; //!< If 0, generate 5ms interrupt; If 1, interrupt last until read reg0CH action occurs.
261 } refined;
263} rda_reg05;
264
265/**
266 * @ingroup GA01
267 * @brief Register 0x06
268 *
269 * I2S_SW_CNT values table
270 *
271 * | Value | Description |
272 * | ------- | ------------------ |
273 * | 0b1000 | WS_STEP_48 |
274 * | 0b0111 | WS_STEP=44.1kbps |
275 * | 0b0110 | WS_STEP=32kbps |
276 * | 0b0101 | WS_STEP=24kbps |
277 * | 0b0100 | WS_STEP=22.05kbps |
278 * | 0b0011 | WS_STEP=16kbps |
279 * | 0b0010 | WS_STEP=12kbps |
280 * | 0b0001 | WS_STEP=11.025kbps |
281 * | 0b0000 | WS_STEP=8kbps |
282 */
283typedef union {
284 struct
285 {
286 uint8_t R_DELY : 1; //!< If 1, R channel data delay 1T.
287 uint8_t L_DELY : 1; //!< If 1, L channel data delay 1T.
288 uint8_t SCLK_O_EDGE : 1; //!< If 1, invert sclk output when as master.
289 uint8_t SW_O_EDGE : 1; //!< If 1, invert ws output when as master.
290 uint8_t I2S_SW_CNT : 4; //!< Only valid in master mode. See table above
291 uint8_t WS_I_EDGE : 1; //!< If 0, use normal ws internally; If 1, inverte ws internally.
292 uint8_t DATA_SIGNED : 1; //!< If 0, I2S output unsigned 16-bit audio data. If 1, I2S output signed 16-bit audio data.
293 uint8_t SCLK_I_EDGE : 1; //!< If 0, use normal sclk internally;If 1, inverte sclk internally.
294 uint8_t WS_LR : 1; //!< Ws relation to l/r channel; If 0, ws=0 ->r, ws=1 ->l; If 1, ws=0 ->l, ws=1 ->r.
295 uint8_t SLAVE_MASTER : 1; //!< I2S slave or master; 1 = slave; 0 = master.
296 uint8_t OPEN_MODE : 2; //!< Open reserved register mode; 11=open behind registers writing function others: only open behind registers reading function.
297 uint8_t RSVD : 1;
298 } refined;
300} rda_reg06;
301
302/**
303 * @ingroup GA01
304 * @brief Register 0x07
305 */
306typedef union {
307 struct
308 {
309 uint8_t FREQ_MODE : 1; //!< If 1, then freq setting changed. Freq = 76000(or 87000) kHz + freq_direct (08H) kHz.
310 uint8_t SOFTBLEND_EN : 1; //!< If 1, Softblend enable
311 uint8_t SEEK_TH_OLD : 6; //!< Seek threshold for old seek mode, Valid when Seek_Mode=001
312 uint8_t RSVD1 : 1;
313 uint8_t MODE_50_60 : 1; //!< 1 = 65~76 MHz; 0 = 50~76MHz
314 uint8_t TH_SOFRBLEND : 5; //!< Threshold for noise soft blend setting, unit 2dB (default 0b10000).
315 uint8_t RSVD2 : 1;
316 } refined;
318} rda_reg07;
319
320/**
321 * @ingroup GA01
322 * @brief Register 0x08 - Direct Frequency
323 * @details Valid when freq_mode = 1
324 * @details Freq = 7600(or 8700) kHz + freq_direct (08H) kHz.
325 * @details Value to be stores is frequency - 7600 or 8700
326 */
327typedef union
328{
329 struct
330 {
331 uint8_t lowByte;
332 uint8_t highByte;
333 } refined;
335} rda_reg08;
336
337
338/**
339 * @ingroup GA01
340 * @brief Register 0x0A - Device current status
341 * @details The seek fail flag (SF) is set when the seek operation fails to find a channel with an RSSI level greater than SEEKTH[5:0].
342 * @details The seek/tune complete (STC) flag is set when the seek or tune operation completes.
343 *
344 *
345 * Channel table
346 *
347 * | BAND | Description |
348 * | ------ | -------------------------------------------------- |
349 * | 0 | Frequency = Channel Spacing (kHz) x CHAN+ 87.0 MHz |
350 * | 1 or 2 | Frequency = Channel Spacing (kHz) x CHAN + 76.0 MHz |
351 * | 3 | Frequency = Channel Spacing (kHz) x CHAN + 65.0 MHz |
352 *
353 */
354typedef union {
355 struct
356 {
357 uint16_t READCHAN : 10; //!< See Channel table . See table above
358 uint16_t ST : 1; //!< Stereo Indicator; 0 = Mono; 1 = Stereo
359 uint16_t BLK_E : 1; //!< When RDS enable: 1 = Block E has been found; 0 = no Block E has been found
360 uint16_t RDSS : 1; //!< RDS Synchronization; 0 = RDS decoder not synchronized(default); 1 = RDS decoder synchronized; Available only in RDS Verbose mode
361 uint16_t SF : 1; //!< Seek Fail. 0 = Seek successful; 1 = Seek failure;
362 uint16_t STC : 1; //!< Seek/Tune Complete. 0 = Not complete; 1 = Complete;
363 uint16_t RDSR : 1; //!< RDS ready; 0 = No RDS/RBDS group ready(default); 1 = New RDS/RBDS group ready.
364 } refined;
366} rda_reg0a;
367
368/**
369 * @ingroup GA01
370 * @brief Register 0x0B
371 * @details Current RDS and device status
372 *
373 * Errors Level table (Block Errors Level of RDS_DATA_0 and RDS_DATA_1.
374 * Always read as Errors Level of RDS BLOCKs A and B (in RDS mode ) or E (in RBDS mode when ABCD_E flag is 1).
375 *
376 * | Value | Description |
377 * | ----- | ----------- |
378 * | 00 | 0 errors requiring correction |
379 * | 01 | 1~2 errors requiring correction |
380 * | 10 | 3~5 errors requiring correction |
381 * | 10 | 6+ errors or error in checkword, correction not possible |
382 *
383 */
384typedef union {
385 struct
386 {
387 uint8_t BLERB : 2; //!< Block Errors Level of RDS_DATA_1
388 uint8_t BLERA : 2; //!< Block Errors Level of RDS_DATA_0
389 uint8_t ABCD_E : 1; //!< 1 = the block id of register 0cH,0dH,0eH,0fH is E; 0 = the block id of register 0cH, 0dH, 0eH,0fH is A, B, C, D
390 uint8_t RSVD1 : 2;
391 uint8_t FM_READY : 1; //!< 1=ready; 0=not ready.
392 uint8_t FM_TRUE : 1; //!< 1 = the current channel is a station; 0 = the current channel is not a station.
393 uint8_t RSSI : 7; //!< RSSI; 000000 = min; 111111 = max; RSSI scale is logarithmic.
394 } refined;
396} rda_reg0b;
397
398
399/**
400 * @ingroup GA01
401 * @brief Register 0x0C
402 * @details BLOCK A ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
403 *
404 */
405typedef union {
406 struct {
407 uint8_t lowByte;
408 uint8_t highByte;
409 } refined;
410 uint16_t RDSA; //!< BLOCK A ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
411} rda_reg0c;
412
413/**
414 * @ingroup GA01
415 * @brief Register 0x0D
416 * @details BLOCK B ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
417 *
418 */
419typedef union
420{
421 struct
422 {
423 uint8_t lowByte;
424 uint8_t highByte;
425 } refined;
427} rda_reg0d;
428
429
430/**
431 * @ingroup GA01
432 * @brief Register 0x0E
433 * @details BLOCK C ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
434 *
435 */
436typedef union
437{
438 struct
439 {
440 uint8_t lowByte;
441 uint8_t highByte;
442 } refined;
444} rda_reg0e;
445
446/**
447 * @ingroup GA01
448 * @brief Register 0x0F
449 * @details BLOCK D ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
450 *
451 */
452typedef union
453{
454 struct
455 {
456 uint8_t lowByte;
457 uint8_t highByte;
458 } refined;
460} rda_reg0f;
461
462/**
463 * @ingroup GA01
464 * @brief RDS Block B data type
465 *
466 * @details For GCC on System-V ABI on 386-compatible (32-bit processors), the following stands:
467 *
468 * 1) Bit-fields are allocated from right to left (least to most significant).
469 * 2) A bit-field must entirely reside in a storage unit appropriate for its declared type.
470 * Thus a bit-field never crosses its unit boundary.
471 * 3) Bit-fields may share a storage unit with other struct/union members, including members that are not bit-fields.
472 * Of course, struct members occupy different parts of the storage unit.
473 * 4) Unnamed bit-fields' types do not affect the alignment of a structure or union, although individual
474 * bit-fields' member offsets obey the alignment constraints.
475 *
476 * @see also https://en.wikipedia.org/wiki/Radio_Data_System
477 */
478typedef union {
479 // using uint16_t instead uint8_t to avoid Crossing boundary
480 struct
481 {
482 uint16_t address : 2; // Depends on Group Type and Version codes. If 0A or 0B it is the Text Segment Address.
483 uint16_t DI : 1; // Decoder Controll bit
484 uint16_t MS : 1; // Music/Speech
485 uint16_t TA : 1; // Traffic Announcement
486 uint16_t programType : 5; // PTY (Program Type) code
487 uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
488 uint16_t versionCode : 1; // (B0) => 0=A; 1=B
489 uint16_t groupType : 4; // Group Type code.
490 } group0;
491 struct
492 {
493 uint16_t address : 4; // Depends on Group Type and Version codes. If 2A or 2B it is the Text Segment Address.
494 uint16_t textABFlag : 1; // Do something if it chanhes from binary "0" to binary "1" or vice-versa
495 uint16_t programType : 5; // PTY (Program Type) code
496 uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
497 uint16_t versionCode : 1; // (B0) => 0=A; 1=B
498 uint16_t groupType : 4; // Group Type code.
499 } group2;
500 struct
501 {
502 uint16_t content : 4; // Depends on Group Type and Version codes.
503 uint16_t textABFlag : 1; // Do something if it chanhes from binary "0" to binary "1" or vice-versa
504 uint16_t programType : 5; // PTY (Program Type) code
505 uint16_t trafficProgramCode : 1; // (TP) => 0 = No Traffic Alerts; 1 = Station gives Traffic Alerts
506 uint16_t versionCode : 1; // (B0) => 0=A; 1=B
507 uint16_t groupType : 4; // Group Type code.
508 } refined;
510} rds_blockb;
511
512/**
513 * @ingroup GA01
514 * Group RDS type 4A ( RDS Date and Time)
515 * When group type 4A is used by the station, it shall be transmitted every minute according to EN 50067.
516 * This Structure uses blocks 2,3 and 5 (B,C,D)
517 *
518 * ATTENTION:
519 * To make it compatible with 8, 16 and 32 bits platforms and avoid Crossing boundary, it was necessary to
520 * split minute and hour representation.
521 */
522typedef union {
523 struct
524 {
525 uint8_t offset : 5; // Local Time Offset
526 uint8_t offset_sense : 1; // Local Offset Sign ( 0 = + , 1 = - )
527 uint8_t minute1 : 2; // UTC Minutes - 2 bits less significant (avoid Crossing boundary”).
528 uint8_t minute2 : 4; // UTC Minutes - 4 bits more significant (avoid Crossing boundary”)
529 uint8_t hour1 : 4; // UTC Hours - 4 bits less significant (avoid Crossing boundary”)
530 uint8_t hour2 : 1; // UTC Hours - 4 bits more significant (avoid Crossing boundary”)
531 uint32_t mjd : 17; // Modified Julian Day Code
532 } refined;
534} rds_date_time;
535
536/**
537 * @ingroup GA01
538 * @brief Converts 16 bits word to two bytes
539 */
540typedef union {
541 struct
542 {
543 uint8_t lowByte;
544 uint8_t highByte;
545 } refined;
547} word16_to_bytes;
548
549/**
550 * @ingroup GA01
551 * @brief KT0915 Class
552 * @details This class implements all functions that will help you to control the KT0915 devices.
553 *
554 * @author PU2CLR - Ricardo Lima Caratti
555 */
556class RDA5807 {
557
558 private:
559
560 uint16_t shadowStatusRegisters[6]; //!< shadow status registers
561 uint16_t shadowRegisters[9]; //!< shadow configuration registers
562
563 // Shadow device configuration register references (writable registers)
564 rda_reg00 *reg00 = (rda_reg00 *)&shadowRegisters[0]; // REG00;
565 rda_reg01 *reg01 = (rda_reg01 *)&shadowRegisters[1]; // REG01;
566 rda_reg02 *reg02 = (rda_reg02 *)&shadowRegisters[2]; // REG02;
567 rda_reg03 *reg03 = (rda_reg03 *)&shadowRegisters[3]; // REG03;
568 rda_reg04 *reg04 = (rda_reg04 *)&shadowRegisters[4]; // REG04;
569 rda_reg05 *reg05 = (rda_reg05 *)&shadowRegisters[5]; // REG05;
570 rda_reg06 *reg06 = (rda_reg06 *)&shadowRegisters[6]; // REG06;
571 rda_reg07 *reg07 = (rda_reg07 *)&shadowRegisters[7]; // REG07;
572 rda_reg08 *reg08 = (rda_reg08 *)&shadowRegisters[8]; // REG08;
573
574 // Shadow device status register references (read only registers)
575 rda_reg0a *reg0a = (rda_reg0a *)&shadowStatusRegisters[0]; // SH_REG0A;
576 rda_reg0b *reg0b = (rda_reg0b *)&shadowStatusRegisters[1]; // SH_REG0B;
577 rda_reg0c *reg0c = (rda_reg0c *)&shadowStatusRegisters[2]; // SH_REG0C;
578 rda_reg0d *reg0d = (rda_reg0d *)&shadowStatusRegisters[3]; // SH_REG0D;
579 rda_reg0e *reg0e = (rda_reg0e *)&shadowStatusRegisters[4]; // SH_REG0E;
580 rda_reg0f *reg0f = (rda_reg0f *)&shadowStatusRegisters[5]; // SH_REG0F;
581
582
583 uint16_t startBand[4] = {8700, 7600, 7600, 6500};
584 uint16_t endBand[4] = {10800, 9100, 10800, 7600}; //!< End FM band limit
585 uint16_t fmSpace[4] = {10, 20, 5, 1}; // Actually 100, 200, 50 and 25 kHz Channel Spacing. Just 100 and 50 kHz is working well.
586
587 char rds_buffer2A[65]; //!< RDS Radio Text buffer - Program Information
588 char rds_buffer2B[33]; //!< RDS Radio Text buffer - Station Informaation
589 char rds_buffer0A[9]; //!< RDS Basic tuning and switching information (Type 0 groups)
590 char rds_time[20]; //!< RDS date time received information
591
592
593 protected:
596
602
603 int gpio1Control = -1; //!< Can be used to add control to the system via GPIO1 pin
604 int gpio2Control = -1; //!< Can be used to add control to the system via GPIO2 pin
605 int gpio3Control = -1; //!< Can be used to add control to the system via GPIO3 pin
606
609
611
612 public :
613
614 /**
615 * @ingroup GA02
616 * @brief Set the Delay After Crystal On (default 500ms)
617 * @details Minimum time required for the oscillator to become stable
618 * @param ms_value Value in milliseconds
619 */
620 inline void setDelayAfterCrystalOn(uint8_t ms_value) { maxDelayAftarCrystalOn = ms_value; };
621
622 /**
623 * @ingroup GA02
624 * @brief Sets alternatives I2C bus address
625 * @details You do not need use this function on RDA5807M
626 * @param directAccess
627 * @param fullAccess
628 */
629 inline void setI2CBusAddrs(int directAccess, int fullAccess) {
630 this->deviceAddressDirectAccess = directAccess;
631 this->deviceAddressFullAccess = fullAccess;
632 }
633
634
635 void getStatusRegisters();
636 word16_to_bytes getDirectRegister(uint8_t reg);
637 void *getStatus(uint8_t reg);
638 void setRegister(uint8_t reg, uint16_t value);
639
640 void setGpio(uint8_t gpioPin, uint8_t gpioSetup = 0, int mcuPin = -1);
641
642 void waitAndFinishTune();
643
644 void softReset();
645
646 void powerUp();
647 void powerDown();
648
649 void setup(uint8_t clock_type = CLOCK_32K, uint8_t oscillator_type = OSCILLATOR_TYPE_CRYSTAL);
650
651 void setNewDemodulateMethod(bool value);
652
653 void setAFC(bool value);
654
655 void setLnaIcSel(uint8_t value );
656 void setLnaPortSel(uint8_t value );
657 /**
658 * @ingroup GA08
659 * @brief Gets LNA_ICSEL_BIT current value
660 * @details Lna working current bit: 0=1.8mA; 1=2.1mA; 2=2.5mA; 3=3.0mA (default 0).
661 * @return 0=1.8mA; 1=2.1mA; 2=2.5mA; 3=3.0mA
662 *
663 * @return uint8_t
664 */
665 inline uint8_t getLnaIcSel() {return reg05->refined.LNA_ICSEL_BIT;};
666 /**
667 * @ingroup GA08
668 * @brief Gets current vaue of the LNA input port selection bit
669 * @details Values: 0 = no input; 1 = LNAN; 2 = LNAP; 3: dual port input
670 * @return 0 = no input; 1 = LNAN; 2 = LNAP; 3: dual port input
671 */
672 inline uint8_t getLnaPortSel() {return reg05->refined.LNA_PORT_SEL;};
673
674
675 void setFrequency(uint16_t frequency);
676
677
678 /**
679 * @ingroup GA03
680 * @brief Tunes the receiver at the first channel/frequency of the current band
681 * @details If the current band is 0, the lowest frequency is 87Mhz (8700)
682 * @see startBand, setFrequency
683 */
684 inline void setFrequencyToBeginBand() { this->setFrequency(startBand[currentFMBand]); };
685
686 /**
687 * @ingroup GA03
688 * @brief Tunes the receiver at the last channel/frequency of the current band
689 * @details If the current band is 0, the highest frequency is 108MHz (10800)
690 * @see endBand, setFrequency
691 */
692 inline void setFrequencyToEndBand(){this->setFrequency(endBand[currentFMBand]);};
693
695 void setFrequencyUp();
696 void setFrequencyDown();
697
700 void setChannel(uint16_t channel);
701 void seek(uint8_t seek_mode, uint8_t direction);
702 void seek(uint8_t seek_mode, uint8_t direction, void (*showFunc)());
703 void setSeekThreshold(uint8_t value);
704
705 void setBand(uint8_t band = 0);
706 void setSpace(uint8_t space = 0);
707 void setStep(uint8_t step = 100);
708 /**
709 * @ingroup GA03
710 * @brief Returns the current Band Space
711 * @return uint8_t value (0 = 100kHz, 1 = 200kHz, 2 = 50kHz e 3 = 25kHz)
712 */
713 inline uint8_t getSpace() { return reg03->refined.SPACE; };
714
715
716 int getRssi();
717
718 /**
719 * @ingroup GA03
720 * @brief Returns true if the current channel is a station.
721 * @return true or false
722 */
723 inline bool isFmTrue() { return reg0b->refined.FM_TRUE;};
724
725 /**
726 * @ingroup GA03
727 * @brief Returns true if the FM is ready.
728 * @return true or false
729 */
730 inline bool isFmReady() { return reg0b->refined.FM_READY;};
731
733
734 // Audio setup
735
736 void setSoftmute(bool value);
737 /**
738 * @ingroup GA07
739 * @brief Gets the softmute status
740 * @return true if enabled
741 */
742 inline bool isSoftmuted() { return reg04->refined.SOFTMUTE_EN; };
743
744 void setMono(bool value);
745 void setBass(bool value);
746 bool isStereo();
747
748
749 void setMute(bool value);
750 /**
751 * @ingroup GA07
752 * @brief Gets Audio Mute Status
753 * @return True if muted
754 */
755 inline bool isMuted() {return !reg02->refined.DMUTE;};
756
757 /**
758 * @ingroup GA07
759 * @brief Gets true if the output audio impedance is high
760 * @return True or false
761 */
762 inline bool isAudioOutputHighImpedance() {return !reg02->refined.DHIZ;};
763
764
765 void setAudioOutputHighImpedance(bool value);
766 void setSoftBlendEnable(bool value);
767
768 void setVolume(uint8_t value);
770 void setVolumeUp();
771 void setVolumeDown();
772
773 void setFmDeemphasis(uint8_t de);
774
775 //******** RDS methods
776 void setRDS(bool value);
777 void setRBDS(bool value);
778 void setRdsFifo(bool value);
779 void clearRdsFifo();
780
781 bool getRdsReady();
782 uint8_t getRdsFlagAB(void);
786 void getNext2Block(char *c);
787 void getNext4Block(char *c);
788 char *getRdsText(void);
789 char *getRdsText0A(void);
790 char *getRdsText2A(void);
791 char *getRdsText2B(void);
792 char *getRdsTime();
793 bool getRdsSync();
796 bool hasRdsInfo();
797
798 // I2S
799 void setI2SOn(bool value);
800 void setI2SAllParameters(uint8_t R_DELY, uint8_t L_DELY, uint8_t SCLK_O_EDGE, uint8_t SW_O_EDGE, uint8_t I2S_SW_CNT, uint8_t WS_I_EDGE, uint8_t DATA_SIGNED, uint8_t SCLK_I_EDGE, uint8_t WS_LR, uint8_t SLAVE_MASTER, uint8_t OPEN_MODE );
801 void setI2SMaster(bool value);
802 void setI2SSpeed(uint8_t value);
803 void setI2SDataSigned(bool value);
804
805 // Tools (Helper)
806 void convertToChar(uint16_t value, char *strValue, uint8_t len, uint8_t dot, uint8_t separator, bool remove_leading_zeros = true );
807
808 /**
809 * @ingroup G05 Format the Frequency
810 * @brief Convert a numeric frequency to a formated string (char *) frequency
811 *
812 * @param uint16_t value - Frequency to be formated
813 * @param char *strValue - Formated frequency (Exe: 103,90) - Array of char ( minimal 7 elements )
814 * @param char decimalSeparator - the symbol that separates the decimal part (Exe: . or ,)
815 * @return point of strValue
816 */
817 inline char *formatFrequency(uint16_t value, char *strValue, char decimalSeparator) {
818 this->convertToChar(value, strValue, 5, 3, decimalSeparator, true);
819 return strValue;
820 };
821
822 int checkI2C(uint8_t *addressArray);
823};
824
825#endif // _RDA5807_H
#define REG02
Definition: RDA5807.h:61
#define REG07
Definition: RDA5807.h:66
#define I2C_ADDR_DIRECT_ACCESS
Can be used to access a given register at a time.
Definition: RDA5807.h:32
#define REG0A
Definition: RDA5807.h:67
#define REG0B
Definition: RDA5807.h:68
#define REG05
Definition: RDA5807.h:64
#define REG04
Definition: RDA5807.h:63
#define CLOCK_32K
32.768kHz
Definition: RDA5807.h:39
#define REG03
Definition: RDA5807.h:62
#define REG06
Definition: RDA5807.h:65
#define I2C_ADDR_FULL_ACCESS
Can be used to access a set of register at a time.
Definition: RDA5807.h:33
#define OSCILLATOR_TYPE_CRYSTAL
Crystal.
Definition: RDA5807.h:36
#define MAX_DELAY_AFTER_OSCILLATOR
Definition: RDA5807.h:29
void convertToChar(uint16_t value, char *strValue, uint8_t len, uint8_t dot, uint8_t separator, bool remove_leading_zeros=true)
Converts a number to a char array.
Definition: RDA5807.cpp:1028
int checkI2C(uint8_t *addressArray)
Check the I2C bus address.
Definition: RDA5807.cpp:1065
char * formatFrequency(uint16_t value, char *strValue, char decimalSeparator)
Convert a numeric frequency to a formated string (char *) frequency.
Definition: RDA5807.h:817
int gpio1Control
Can be used to add control to the system via GPIO1 pin.
Definition: RDA5807.h:603
uint16_t raw
Definition: RDA5807.h:395
uint16_t currentFrequency
Definition: RDA5807.h:598
int deviceAddressDirectAccess
Definition: RDA5807.h:594
uint16_t raw
Definition: RDA5807.h:169
uint16_t raw
Definition: RDA5807.h:334
uint16_t raw
Definition: RDA5807.h:317
uint8_t currentVolume
Definition: RDA5807.h:601
uint16_t raw
Definition: RDA5807.h:111
uint16_t RDSD
Definition: RDA5807.h:459
uint16_t raw
Definition: RDA5807.h:365
uint8_t oscillatorType
Definition: RDA5807.h:608
uint16_t RDSC
Definition: RDA5807.h:443
int resetPin
Definition: RDA5807.h:597
uint16_t raw
Definition: RDA5807.h:126
uint16_t raw
Definition: RDA5807.h:244
uint16_t blockB
Definition: RDA5807.h:509
uint16_t raw
Definition: RDA5807.h:299
uint8_t clockType
Definition: RDA5807.h:607
int deviceAddressFullAccess
Definition: RDA5807.h:595
uint16_t raw
Definition: RDA5807.h:217
uint16_t maxDelayAftarCrystalOn
Definition: RDA5807.h:610
uint16_t RDSB
Definition: RDA5807.h:426
uint16_t RDSA
BLOCK A ( in RDS mode) or BLOCK E (in RBDS mode when ABCD_E flag is 1)
Definition: RDA5807.h:410
uint16_t raw
Definition: RDA5807.h:262
uint8_t currentFMBand
Definition: RDA5807.h:599
int gpio2Control
Can be used to add control to the system via GPIO2 pin.
Definition: RDA5807.h:604
uint8_t raw[6]
Definition: RDA5807.h:533
uint16_t raw
Definition: RDA5807.h:546
uint8_t currentFMSpace
Definition: RDA5807.h:600
int gpio3Control
Can be used to add control to the system via GPIO3 pin.
Definition: RDA5807.h:605
KT0915 Class.
Definition: RDA5807.h:556
void setDelayAfterCrystalOn(uint8_t ms_value)
Set the Delay After Crystal On (default 500ms)
Definition: RDA5807.h:620
void * getStatus(uint8_t reg)
Gets the register content of a given status register (from 0x0A to 0x0F)
Definition: RDA5807.cpp:108
void powerDown()
Power the receiver off.
Definition: RDA5807.cpp:220
void powerUp()
Powers the receiver on.
Definition: RDA5807.cpp:179
void setRegister(uint8_t reg, uint16_t value)
Sets a given value to a specific device register.
Definition: RDA5807.cpp:138
void softReset()
Resets the device.
Definition: RDA5807.cpp:169
void waitAndFinishTune()
Waits for Seek or Tune finish.
Definition: RDA5807.cpp:156
void setGpio(uint8_t gpioPin, uint8_t gpioSetup=0, int mcuPin=-1)
Sets the Device GPIO pins.
Definition: RDA5807.cpp:34
word16_to_bytes getDirectRegister(uint8_t reg)
Gets the register content via direct access.
Definition: RDA5807.cpp:86
void setNewDemodulateMethod(bool value)
Sets new demodulate method. It can improve the receiver sensitivity about 1dB.
Definition: RDA5807.cpp:211
void getStatusRegisters()
Gets all current device status and RDS information registers (From 0x0A to 0x0F)
Definition: RDA5807.cpp:64
void setup(uint8_t clock_type=CLOCK_32K, uint8_t oscillator_type=OSCILLATOR_TYPE_CRYSTAL)
Starts the device.
Definition: RDA5807.cpp:237
uint16_t getDeviceId()
Gets the Device identification.
Definition: RDA5807.cpp:253
void setI2CBusAddrs(int directAccess, int fullAccess)
Sets alternatives I2C bus address.
Definition: RDA5807.h:629
uint16_t getRealFrequency()
Gets the current frequency bases on the current channel.
Definition: RDA5807.cpp:399
uint16_t getRealChannel()
Gets the current channel stored in 0x0A status register.
Definition: RDA5807.cpp:377
void setSeekThreshold(uint8_t value)
Sets RSSI Seek Threshold.
Definition: RDA5807.cpp:478
bool isFmReady()
Returns true if the FM is ready.
Definition: RDA5807.h:730
void setFrequencyUp()
Increments the current frequency.
Definition: RDA5807.cpp:331
void setFmDeemphasis(uint8_t de)
Sets De-emphasis.
Definition: RDA5807.cpp:566
uint16_t getFrequency()
Gets the current frequency.
Definition: RDA5807.cpp:363
void setSoftBlendEnable(bool value)
Sets Soft Blend.
Definition: RDA5807.cpp:274
void setSpace(uint8_t space=0)
Sets the FM channel space.
Definition: RDA5807.cpp:522
void setFrequencyToEndBand()
Tunes the receiver at the last channel/frequency of the current band.
Definition: RDA5807.h:692
bool isFmTrue()
Returns true if the current channel is a station.
Definition: RDA5807.h:723
void seek(uint8_t seek_mode, uint8_t direction)
Seek function.
Definition: RDA5807.cpp:410
void setBand(uint8_t band=0)
Sets the FM band. See table below.
Definition: RDA5807.cpp:499
void setStep(uint8_t step=100)
Sets the FM Step;.
Definition: RDA5807.cpp:536
void setAFC(bool value)
Sets AFC true or false.
Definition: RDA5807.cpp:285
void setChannel(uint16_t channel)
Sets the channel.
Definition: RDA5807.cpp:303
uint8_t getSpace()
Returns the current Band Space.
Definition: RDA5807.h:713
void setFrequencyToBeginBand()
Tunes the receiver at the first channel/frequency of the current band.
Definition: RDA5807.h:684
void setFrequency(uint16_t frequency)
Sets the frequency.
Definition: RDA5807.cpp:319
void setFrequencyDown()
Decrements the current frequency.
Definition: RDA5807.cpp:346
void seek(uint8_t seek_mode, uint8_t direction, void(*showFunc)())
Seek function.
Definition: RDA5807.cpp:450
uint8_t getRdsFlagAB(void)
Returns the current Text Flag A/B
Definition: RDA5807.cpp:629
bool hasRdsInfo()
Returns true when the RDS system has valid information.
Definition: RDA5807.cpp:977
bool getRdsSync()
Gets the Rds Sync.
Definition: RDA5807.cpp:930
uint8_t getBlockId()
Gets the current Block ID.
Definition: RDA5807.cpp:943
uint16_t getRdsGroupType()
Return the group type.
Definition: RDA5807.cpp:643
void getNext4Block(char *c)
Process data received from group 2A.
Definition: RDA5807.cpp:723
char * getRdsText2A(void)
Gets the Text processed for the 2A group.
Definition: RDA5807.cpp:817
void setRDS(bool value)
Sets the RDS operation.
Definition: RDA5807.cpp:584
char * getRdsText0A(void)
Gets the station name and other messages.
Definition: RDA5807.cpp:788
void getNext2Block(char *c)
Process data received from group 2B.
Definition: RDA5807.cpp:686
char * getRdsText(void)
Gets the RDS Text when the message is of the Group Type 2 version A.
Definition: RDA5807.cpp:762
void clearRdsFifo()
Clear RDS fifo.
Definition: RDA5807.cpp:1001
char * getRdsText2B(void)
Gets the Text processed for the 2B group.
Definition: RDA5807.cpp:846
bool getRdsReady()
Returns true if RDS Ready.
Definition: RDA5807.cpp:616
uint8_t getRdsVersionCode(void)
Gets the version code (extracted from the Block B)
Definition: RDA5807.cpp:658
uint8_t getErrorBlockB()
Gets the current Status of block B.
Definition: RDA5807.cpp:965
void setRdsFifo(bool value)
Sets RDS fifo mode enable.
Definition: RDA5807.cpp:989
uint8_t getRdsProgramType(void)
Returns the Program Type (extracted from the Block B)
Definition: RDA5807.cpp:672
void setRBDS(bool value)
Sets the RBDS operation.
Definition: RDA5807.cpp:598
char * getRdsTime()
Gets the RDS time and date when the Group type is 4.
Definition: RDA5807.cpp:872
void setI2SAllParameters(uint8_t R_DELY, uint8_t L_DELY, uint8_t SCLK_O_EDGE, uint8_t SW_O_EDGE, uint8_t I2S_SW_CNT, uint8_t WS_I_EDGE, uint8_t DATA_SIGNED, uint8_t SCLK_I_EDGE, uint8_t WS_LR, uint8_t SLAVE_MASTER, uint8_t OPEN_MODE)
Configures all parameters for I2S.
Definition: RDA5807.cpp:1114
void setI2SSpeed(uint8_t value)
Sets the speed in kbps. You can use the predefined constantes: I2S_WS_STEP_48, I2S_WS_STEP_44_1,...
Definition: RDA5807.cpp:1165
void setI2SMaster(bool value)
Definition: RDA5807.cpp:1151
void setI2SDataSigned(bool value)
If 0, I2S output unsigned 16-bit audio data. If 1, I2S output signed 16-bit audio data.
Definition: RDA5807.cpp:1177
void setI2SOn(bool value)
Enables I2S setup.
Definition: RDA5807.cpp:1139
bool isStereo()
Gets the current Stereo status.
Definition: RDA5807.cpp:1263
bool isSoftmuted()
Gets the softmute status
Definition: RDA5807.h:742
bool isAudioOutputHighImpedance()
Gets true if the output audio impedance is high.
Definition: RDA5807.h:762
void setVolume(uint8_t value)
Sets the audio volume level.
Definition: RDA5807.cpp:1277
uint8_t getVolume()
Gets the current audio volume level.
Definition: RDA5807.cpp:1291
void setBass(bool value)
Sets Bass Boost.
Definition: RDA5807.cpp:1250
void setVolumeUp()
Increments the audio volume.
Definition: RDA5807.cpp:1301
void setVolumeDown()
Decrements the audio volume.
Definition: RDA5807.cpp:1315
void setAudioOutputHighImpedance(bool value)
Sets audio output impedance high ow low.
Definition: RDA5807.cpp:1223
void setMono(bool value)
Sets audio Mono or stereo.
Definition: RDA5807.cpp:1237
void setSoftmute(bool value)
Sets Soft Mute Enable or disable.
Definition: RDA5807.cpp:1197
bool isMuted()
Gets Audio Mute Status.
Definition: RDA5807.h:755
void setMute(bool value)
Sets Audio mute or unmute.
Definition: RDA5807.cpp:1211
void setLnaIcSel(uint8_t value)
Sets LNA_ICSEL_BIT.
Definition: RDA5807.cpp:1336
int getRssi()
Gets the current Rssi.
Definition: RDA5807.cpp:1360
uint8_t getLnaIcSel()
Gets LNA_ICSEL_BIT current value.
Definition: RDA5807.h:665
void setLnaPortSel(uint8_t value)
Sets LNA input port selection bit.
Definition: RDA5807.cpp:1347
uint8_t getLnaPortSel()
Gets current vaue of the LNA input port selection bit.
Definition: RDA5807.h:672