PU2CLR RDA5807 Arduino Library 1.1.8
Arduino Library for RDA5807 Devices - By Ricardo Lima Caratti
Loading...
Searching...
No Matches
RDA5807.cpp
Go to the documentation of this file.
1/**
2 * @mainpage RDA5807 Arduino Library implementation
3 * @details RDA5807 Arduino Library implementation. This is an Arduino library for the RDA5807, BROADCAST RECEIVER.
4 * @details It works with I2C protocol and can provide an easier interface to control the RDA5807 device.<br>
5 * @details This library was built based on "RDA5807M - SINGLE-CHIP BROADCAST FM RADIO TUNER - Rev.1.1–Aug.2015"
6 * @details and RDA microelectronics RDA5807FP - SINGLE-CHIP BROADCAST FM RADIO TUNER
7 * @details This library can be freely distributed using the MIT Free Software model.
8 * @copyright Copyright (c) 2020 Ricardo Lima Caratti.
9 * @author Ricardo LIma Caratti (pu2clr@gmail.com)
10 */
11
12#include <RDA5807.h>
13
14/**
15 * @defgroup GA02 Basic Functions
16 * @section GA02 Basic Functions
17 */
18
19/**
20 * @ingroup GA02
21 * @brief Sets the Device GPIO pins
22 * @details This method is useful to add control to the system via GPIO RDA devive pins.
23 * @details For example: You can use these pins to control RDS and SEEK via interrupt.
24 * @details GPIOs are General Purpose I/O pin.
25 * @details GPIO setup
26 * @details When GPIO1 (#1), gpioSetup can be: 00 = High impedance; 01 = Reserved; 10 = Low; 11 = High
27 * @details When GPIO2 (#2), gpioSetup can be: 00 = High impedance; 01 = Interrupt (INT) 10 = Low; 11 = High
28 * @details When GPIO3 (#3), gpioSetup can be: 00 = High impedance; 01 = Mono/Stereo indicator (ST) = Low; 11 = High
29 *
30 * @param gpioPin gpio number (1, 2 or 3)
31 * @param gpioSetup See description above
32 * @param mcuPip MCU (Arduino) pin connected to the gpio
33 */
34void RDA5807::setGpio(uint8_t gpioPin, uint8_t gpioSetup, int mcuPin)
35{
36 switch (gpioPin)
37 {
38 case 1:
39 this->gpio1Control = mcuPin;
40 reg04->refined.GPIO1 = gpioSetup;
41 break;
42 case 2:
43 this->gpio2Control = mcuPin;
44 reg04->refined.GPIO2 = gpioSetup;
45 break;
46 case 3:
47 this->gpio3Control = mcuPin;
48 reg04->refined.GPIO3 = gpioSetup;
49 break;
50 default:
51 gpio1Control = gpio2Control = gpio3Control = -1;
52 }
53 setRegister(REG04, reg04->raw);
54}
55
56/**
57 * @ingroup GA02
58 * @brief Sets Interrupt Mode
59 * @details GPIO2 could be programmed to output a low interrupt (interrupt will be generated only with interrupt enable bit STCIEN is set to high) when seek/tune process completes
60 * @details Setting STCIEN = 1 will generate a low pulse on GPIO2 when the interrupt occurs.
61 * @details ATTENTION: This function affects the behavior of the GPIO2 pin. The register 0x04 GPIO2 attribute will be setted to 1
62 * @param value 0 = disable; 1 = enqble
63 * @see setGpio
64 */
65void RDA5807::setInterruptMode(uint8_t value)
66{
67 reg04->refined.GPIO2 = value; // Sets the GPIO2 to deal with interrupt
68 reg04->refined.STCIEN = value; // Enable or disable interrupr
69 setRegister(REG04, reg04->raw);
70}
71
72/**
73 * @ingroup GA02
74 * @brief Gets all current device status and RDS information registers (From 0x0A to 0x0F)
75 * @see RDA5807M - SINGLE-CHIP BROADCAST FMRADIO TUNER; pages 5, 9, 12 and 13.
76 * @see rda_reg0a, rda_reg0b, rda_reg0c, rda_reg0d, rda_reg0e, rda_reg0f
77 * @see shadowStatusRegisters;
78 */
80{
81 word16_to_bytes aux;
82 int i;
83
84 Wire.requestFrom(this->deviceAddressFullAccess, 12); // This call starts reading from 0x0A register
85 for (i = 0; i < 6; i++)
86 {
87 aux.refined.highByte = Wire.read();
88 aux.refined.lowByte = Wire.read();
89 shadowStatusRegisters[i] = aux.raw;
90 }
91 Wire.endTransmission();
92}
93
94/**
95 * @ingroup GA02
96 * @brief Gets the register content via direct access
97 * @details this method is useful to deal with a specific register.
98 * @param uint8_t register number
99 * @return word16_to_bytes register content
100 * @see word16_to_bytes datatype in RDA5807.h
101 */
102word16_to_bytes RDA5807::getDirectRegister(uint8_t reg)
103{
104
105 word16_to_bytes aux;
106 Wire.beginTransmission(this->deviceAddressDirectAccess);
107 Wire.write(reg);
108 Wire.endTransmission(false);
109 Wire.requestFrom(this->deviceAddressDirectAccess, 2);
110 aux.refined.highByte = Wire.read();
111 aux.refined.lowByte = Wire.read();
112 Wire.endTransmission();
113
114 return aux;
115}
116
117/**
118 * @ingroup GA02
119 * @brief Gets the register content of a given status register (from 0x0A to 0x0F)
120 * @details Useful when you need just a specific status register content.
121 * @details This methos update the first element of the shadowStatusRegisters linked to the register
122 * @return rdax_reg0a the reference to current value of the 0x0A register.
123 */
124void *RDA5807::getStatus(uint8_t reg)
125{
126 word16_to_bytes aux;
127
128 if (reg < 0x0A || reg > 0x0F)
129 return NULL; // Maybe not necessary.
130
131 Wire.beginTransmission(this->deviceAddressDirectAccess);
132 Wire.write(reg);
133 Wire.endTransmission(false);
134 Wire.requestFrom(this->deviceAddressDirectAccess, 2); // reading 0x0A register
135 delayMicroseconds(250);
136 aux.refined.highByte = Wire.read();
137 aux.refined.lowByte = Wire.read();
138 Wire.endTransmission(true);
139 shadowStatusRegisters[reg - 0x0A] = aux.raw;
140
141 return &shadowStatusRegisters[reg - 0x0A];
142}
143
144/**
145 * @ingroup GA02
146 * @brief Sets a given value to a specific device register
147 *
148 * @see RDA5807M - SINGLE-CHIP BROADCAST FMRADIO TUNER; pages 5, 9, 10 and 11.
149 * @see rda_reg02, rda_reg03, rda_reg04, rda_reg05, rda_reg06, rda_reg07
150 *
151 * @param reg register number (valid values is between 0x02 and 0x07)
152 * @param value the unsigned 16 bits word value (see rda_rec0x data types)
153 */
154void RDA5807::setRegister(uint8_t reg, uint16_t value)
155{
156 word16_to_bytes aux;
157 if (reg > 8)
158 return; // Maybe not necessary.
159 Wire.beginTransmission(this->deviceAddressDirectAccess);
160 Wire.write(reg);
161 aux.raw = value;
162 Wire.write(aux.refined.highByte);
163 Wire.write(aux.refined.lowByte);
164 Wire.endTransmission();
165 shadowRegisters[reg] = aux.raw; // Updates the shadowRegisters element
166 delayMicroseconds(3000); // Check
167}
168
169/**
170 * @ingroup GA02
171 * @brief Waits for Seek or Tune finish
172 */
174{
175 do
176 {
177 getStatus(REG0A);
178 } while (reg0a->refined.STC == 0);
179}
180
181/**
182 * @ingroup GA02
183 * @brief Resets the device
184 * @details The RDA5807M is RESET itself When VIO is Power up.
185 * @details Also, it support soft reset by triggering the 0x02 register (rda_reg02) bit 1 from 0 to 1.
186 */
188{
189 reg02->refined.SOFT_RESET = 1;
190 setRegister(REG02, reg02->raw);
191}
192
193/**
194 * @ingroup GA02
195 * @brief Powers the receiver on
196 */
198{
199 reg02->raw = 0;
200 reg02->refined.NEW_METHOD = 0;
201 reg02->refined.RDS_EN = 0; // RDS disable
202 reg02->refined.CLK_MODE = this->clockFrequency;
203 reg02->refined.RCLK_DIRECT_IN = this->oscillatorType;
204 reg02->refined.NON_CALIBRATE = this->rlckNoCalibrate;
205 reg02->refined.MONO = 1; // Force mono
206 reg02->refined.DMUTE = 1; // Normal operation
207 reg02->refined.DHIZ = 1; // Normal operation
208 reg02->refined.ENABLE = 1;
209 reg02->refined.BASS = 1;
210 reg02->refined.SEEK = 0;
211
212 setRegister(REG02, reg02->raw);
213
214 reg05->raw = 0x00;
215 reg05->refined.INT_MODE = 0;
216 reg05->refined.LNA_PORT_SEL = 2;
217 reg05->refined.LNA_ICSEL_BIT = 0;
218 reg05->refined.SEEKTH = 8; // 0b1000
219 reg05->refined.VOLUME = 0;
220
221 setRegister(REG05, reg05->raw);
222}
223
224/**
225 * @ingroup GA02
226 * @brief Sets new demodulate method. It can improve the receiver sensitivity about 1dB
227 *
228 * @param value true or false
229 */
231{
232 reg02->refined.NEW_METHOD = value;
233 setRegister(REG02, reg02->raw);
234}
235
236/**
237 * @ingroup GA02
238 * @brief Power the receiver off
239 */
241{
242 reg02->refined.SEEK = 0;
243 reg02->refined.ENABLE = 0;
244 setRegister(REG02, reg02->raw);
245}
246
247/**
248 * @ingroup GA02
249 * @brief Starts the device
250 * @details You can select the colck type and the frequency
251 * @details oscillator type: OSCILLATOR_TYPE_CRYSTAL = passive crystal; OSCILLATOR_TYPE_REFCLK = active crystal or signal generator
252 * @details Clock type: CLOCK_32K, CLOCK_12M, CLOCK_13M, CLOCK_19_2M, CLOCK_24M, CLOCK_26M and CLOCK_38_4M
253 * @code {.cpp}
254 * #include <RDA5807.h>
255 * RDA5807 rx;
256 * void setup() {
257 * rx.setup(); // Starts the receiver with default parameters
258 * // rx.setup(CLOCK_32K, OSCILLATOR_TYPE_ACTIVE); // 32.768kHz Active Crystal
259 * // rx.setup(CLOCK_12M, OSCILLATOR_TYPE_PASSIVE); // 12MHz passive crystal
260 * // rx.setup(CLOCK_38_4M, OSCILLATOR_TYPE_PASSIVE); // 38.4 MHz passive crystal
261 * rx.setFrequency(10390); // Tunes at 103.9 MHz
262 * }
263 * void loop() {
264 * }
265 * @endcode
266 *
267 * @param clock_frequency optional; Clock frequency. Default 32.768 kHz.
268 * @param oscillator_type optional; Sets the Oscillator type (passive or active crystal); default: passive Crystal.
269 * @param rlck_no_calibrate optional; if 0=RCLK clock is always supply; 1=RCLK clock is not always supply when FM work
270 * @see OSCILLATOR_TYPE_PASSIVE, OSCILLATOR_TYPE_ACTIVE, RLCK_NO_CALIBRATE_MODE_ON, RLCK_NO_CALIBRATE_MODE_OFF
271 * @see powerUp, rda_reg02
272 */
273void RDA5807::setup(uint8_t clock_frequency, uint8_t oscillator_type, uint8_t rlck_no_calibrate)
274{
275 this->oscillatorType = oscillator_type;
276 this->clockFrequency = clock_frequency;
277 this->rlckNoCalibrate = rlck_no_calibrate;
278
279 Wire.begin();
280
281 delay(10);
282 powerUp();
283 delay(this->maxDelayAftarCrystalOn);
284}
285
286/**
287 * @ingroup GA02
288 * @brief Gets the Device identification
289 * @return device number Id
290 */
292{
293 reg00->raw = getDirectRegister(0x0).raw;
294 return reg00->raw;
295}
296
297/**
298 * @defgroup GA03 FM Tune Functions
299 * @section GA03 FM Tune
300 */
301
302/**
303 * @ingroup GA03
304 * @brief Sets Soft Blend.
305 *
306 * @param value true or false
307 */
309{
310 reg07->refined.SOFTBLEND_EN = value;
311 setRegister(REG07, reg07->raw);
312}
313
314/**
315 * @ingroup GA03
316 * @brief Sets AFC true or false
317 *
318 * @param value true or false
319 */
320void RDA5807::setAFC(bool value)
321{
322 reg04->refined.AFCD = value;
323 setRegister(REG04, reg04->raw);
324}
325
326/**
327 * @ingroup GA03
328 * @brief Sets the channel
329 * @details This method tunes the rteceiver in a given channel.
330 * @details The channel can be calculated by using the follow formula
331 * @details channel = (desired frequency - start band frequency) / space channel in use / 10.0);
332 *
333 * @see setFrequency, setBand, setSpace
334 * @see RDA5807M - SINGLE-CHIP BROADCAST FM RADIO TUNER - Rev.1.1–Aug.2015; pages 9 and 12.
335 *
336 * @param channel
337 */
338void RDA5807::setChannel(uint16_t channel)
339{
340 reg03->refined.CHAN = channel;
341 reg03->refined.TUNE = 1;
342 reg03->refined.BAND = this->currentFMBand;
343 reg03->refined.SPACE = this->currentFMSpace;
344 reg03->refined.DIRECT_MODE = 0;
345 setRegister(REG03, reg03->raw);
347}
348
349/**
350 * @ingroup GA03
351 * @brief Sets the frequency
352 * @details Tunes the receiver at a given frequency. Example:
353 * @code {.cpp}
354 * #include <RDA5807.h>
355 * RDA5807 rx;
356 * void setup() {
357 * pinMode(4, INPUT_PULLUP); // Arduino pin 4 - Frequency Up
358 * pinMode(5, INPUT_PULLUP); // Arduino pin 5 - Frequency Down
359 * rx.setup();
360 * rx.setFrequency(10390); // Tunes at 103.9 MHz
361 * }
362 * void loop() {
363 * if (digitalRead(4) == LOW) rx.setFrequencyUp();
364 * if (digitalRead(5) == LOW) rx.setFrequencyDown();
365 * delay(200);
366 * }
367 * @endcode
368 *
369 * @param frequency - an integer with the frequency value (Example: 7600=76MHz, 10790 = 107,90MHz)
370 * @see setFrequencyUp, setFrequencyDown, getFrequency
371 */
372void RDA5807::setFrequency(uint16_t frequency)
373{
374 uint16_t channel = (frequency - this->startBand[currentFMBand]) / (this->fmSpace[this->currentFMSpace]);
375 setChannel(channel);
376 this->currentFrequency = frequency;
377}
378
379/**
380 * @ingroup GA03
381 * @brief Sets the frequency using the reg08 (direct frequency)
382 * @details valid when frequency mode is 1
383 * @param frequency
384 */
385void RDA5807::setDirectFrequency(uint16_t frequency)
386{
387 reg08->directFrequency = frequency;
388 setRegister(REG08, reg08->directFrequency);
389 this->currentFrequency = frequency;
390}
391
392/**
393 * @ingroup GA03
394 * @brief Sets the frequency mode. If 1, then freq setting changed.
395 * @param value ( default = 0 or 1)
396 */
397void RDA5807::setFrequencyMode(uint8_t value)
398{
399 reg07->refined.FREQ_MODE = value;
400 setRegister(REG07, reg07->raw);
401}
402
403/**
404 * @ingroup GA03
405 * @brief Increments the current frequency
406 * @details The increment uses the band space as step. See array: uint16_t fmSpace[4] = {100/10, 200/10, 50/10, 25/10};
407 * @code {.cpp}
408 * #include <RDA5807.h>
409 * RDA5807 rx;
410 * void setup() {
411 * pinMode(4, INPUT_PULLUP); // Arduino pin 4 - Frequency Up
412 * pinMode(5, INPUT_PULLUP); // Arduino pin 5 - Frequency Down
413 * rx.setup();
414 * rx.setFrequency(10390); // Tunes at 103.9 MHz
415 * }
416 * void loop() {
417 * if (digitalRead(4) == LOW) rx.setFrequencyUp();
418 * if (digitalRead(5) == LOW) rx.setFrequencyDown();
419 * delay(200);
420 * }
421 * @endcode
422 * @see setFrequency, getFrequency
423 */
425{
426 if (this->currentFrequency < this->endBand[this->currentFMBand])
427 this->currentFrequency += (this->fmSpace[currentFMSpace]);
428 else
429 this->currentFrequency = this->startBand[this->currentFMBand];
430
431 setFrequency(this->currentFrequency);
432}
433
434/**
435 * @ingroup GA03
436 * @brief Decrements the current frequency
437 * @details The drecrement uses the band space as step. See array: uint16_t fmSpace[4] = {20, 10, 5, 1};
438 */
440{
441 if (this->currentFrequency > this->startBand[this->currentFMBand])
442 this->currentFrequency -= (this->fmSpace[currentFMSpace]);
443 else
444 this->currentFrequency = this->endBand[this->currentFMBand];
445
446 setFrequency(this->currentFrequency);
447}
448
449/**
450 * @ingroup GA03
451 * @brief Gets the current frequency.
452 * @return uint16_t
453 */
455{
456 return this->currentFrequency;
457}
458
459/**
460 * @ingroup GA03
461 * @brief Gets the current channel stored in 0x0A status register.
462 *
463 * @see setChannel, setFrequency, setBand, setSpace
464 * @see RDA5807M - SINGLE-CHIP BROADCAST FM RADIO TUNER - Rev.1.1–Aug.2015; pages 9 and 12.
465 *
466 * @return uint16_t current channel value
467 */
469{
470 getStatus(REG0A);
471 return reg0a->refined.READCHAN;
472}
473
474/**
475 * @ingroup GA03
476 * @brief Gets the current frequency bases on the current channel.
477 * @details The current channel is stored in the 0x0A register. This value is updated after a tune or seek operation.
478 * @details The current frequency can be calculated by the formula below
479 *
480 * | Band | Formula |
481 * | ------ | ------- |
482 * | 0 | Frequency = Channel Spacing (kHz) x READCHAN[9:0]+ 87.0 MHz |
483 * | 1 or 2 | Frequency = Channel Spacing (kHz) x READCHAN[9:0]+ 76.0 MHz |
484 * | 3 | Frequency = Channel Spacing (kHz) x READCHAN[9:0]+ 65.0 MHz |
485 *
486 * @see setChannel, setFrequency, setBand, setSpace
487 * @see RDA5807M - SINGLE-CHIP BROADCAST FM RADIO TUNER - Rev.1.1–Aug.2015; pages 9 and 12.
488 * @return uint16_t
489 */
491{
492 return getRealChannel() * (this->fmSpace[this->currentFMSpace]) + this->startBand[currentFMBand];
493}
494
495/**
496 * @ingroup GA03
497 * @brief Seek function
498 * @details look for next or previous station available. Example:
499 * @code {.cpp}
500 * #include <RDA5807.h>
501 * RDA5807 rx;
502 * void setup() {
503 * pinMode(4, INPUT_PULLUP); // Arduino pin 4 - Seek station down
504 * pinMode(5, INPUT_PULLUP); // Arduino pin 5 - Seek station up
505 * rx.setup(); // Starts the receiver with default parameters
506 * rx.setFrequency(10390); // Tunes at 103.9 MHz - Switch to your local favorite station
507 * }
508 * void loop() {
509 * if (digitalRead(4) == LOW) rx.seek(RDA_SEEK_WRAP,RDA_SEEK_DOWN);
510 * if (digitalRead(5) == LOW) rx.seek(RDA_SEEK_WRAP,RDA_SEEK_UP);
511 * delay(200);
512 * }
513 * @endcode
514 *
515 * @param seek_mode if 0, wrap at the upper or lower band limit and continue seeking; 1 = stop seeking at the upper or lower band limit
516 * @param direction if 0, seek down; if 1, seek up.
517 */
518void RDA5807::seek(uint8_t seek_mode, uint8_t direction)
519{
520 reg02->refined.SEEK = 1;
521 reg02->refined.SKMODE = seek_mode;
522 reg02->refined.SEEKUP = direction;
523 setRegister(REG02, reg02->raw);
524 setFrequency(getRealFrequency());
525}
526
527/**
528 * @ingroup GA03
529 * @brief Seek function
530 * @details Seeks a station up or down.
531 * @details Seek up or down a station and call a function defined by the user to show the frequency during the seek process.
532 * @details Seek begins at the current channel, and goes in the direction specified with the SEEKUP bit. Seek operation stops when a channel is qualified as valid according to the seek parameters, the entire band has been searched (SKMODE = 0), or the upper or lower band limit has been reached (SKMODE = 1).
533 * @details The STC bit is set high when the seek operation completes and/or the SF/BL bit is set high if the seek operation was unable to find a channel qualified as valid according to the seek parameters. The STC and SF/BL bits must be set low by setting the SEEK bit low before the next seek or tune may begin.
534 * @details The SEEK bit is set low and the STC bit is set high when the seek operation completes.
535 * @details It is important to say you have to implement a show frequency function. This function have to get the frequency via getFrequency function.
536 * @details Example:
537 * @code
538 *
539 * SI470X rx;
540 *
541 * void showFrequency() {
542 * uint16_t freq = rx.getFrequency();
543 * Serial.print(freq);
544 * Serial.println("MHz ");
545 * }
546 *
547 * void loop() {
548 * .
549 * .
550 * rx.seek(RDA_SEEK_WRAP, RDA_SEEK_UP, showFrequency); // Seek Up
551 * .
552 * .
553 * }
554 * @endcode
555 * @param seek_mode Seek Mode; 0 = Wrap at the upper or lower band limit and continue seeking (default); 1 = Stop seeking at the upper or lower band limit.
556 * @param direction Seek Direction; 0 = Seek down (default); 1 = Seek up.
557 * @param showFunc function that you have to implement to show the frequency during the seeking process. Set NULL if you do not want to show the progress.
558 */
559void RDA5807::seek(uint8_t seek_mode, uint8_t direction, void (*showFunc)())
560{
561 getStatus(REG0A);
562 do
563 {
564 reg02->refined.SEEK = 1;
565 reg02->refined.SKMODE = seek_mode;
566 reg02->refined.SEEKUP = direction;
567 setRegister(REG02, reg02->raw);
568 this->currentFrequency = getRealFrequency(); // gets the current seek frequency
569 if (showFunc != NULL)
570 {
571 showFunc();
572 }
573 delay(10);
574 getStatus(REG0A);
575 } while (reg0a->refined.STC == 0);
577 setFrequency(getRealFrequency()); // Fixes station found.
578}
579
580/**
581 * @ingroup GA03
582 * @brief Sets RSSI Seek Threshold
583 * @param value
584 */
585void RDA5807::setSeekThreshold(uint8_t value)
586{
587 reg05->refined.SEEKTH = value;
588 setRegister(REG05, reg05->raw);
589}
590
591/**
592 * @ingroup GA03
593 * @brief Sets the FM band. See table below.
594 *
595 * FM band table
596 *
597 * | Value | Decimal | Description |
598 * | ----- | ------- | --------------------------- |
599 * | 00 | 0 | 87–108 MHz (US/Europe) |
600 * | 01 | 1 | 76–91 MHz (Japan) |
601 * | 10 | 2 | 76–108 MHz (world wide) |
602 * | 11 | 3 | 65 –76 MHz (East Europe) or 50-65MHz (see bit 9 of gegister 0x07) |
603 *
604 * @details if you are using the band 3 with 50 to 65 MHz setup, the setFrequencyUp, setFrequencyDown, setFrequencyToBeginBand and setFrequencyToEndBand
605 * @details will not work properly. In this case, you have control the limits of the band by yourself.
606 * @code {.cpp}
607 * #include <RDA5807.h>
608 * RDA5807 rx;
609 * void setup() {
610 * rx.setup();
611 * rx.setBand(2); // Sets band: 76–108 MHz (world wide)
612 * rx.setFrequency(10390); // Tunes at 103.9 MHz
613 * }
614 * void loop() {
615 * }
616 * @endcode
617 *
618 * @param band FM band index. See table above.
619 * @see setBand3_50_65_Mode, getBand3Status
620 */
621void RDA5807::setBand(uint8_t band)
622{
623 reg03->refined.BAND = this->currentFMBand = band; // Adjusted by anonimous developer
624 setRegister(REG03, reg03->raw);
625}
626
627/**
628 * @ingroup GA03
629 * @brief Sets the band 3 mode: 50 to 65 MHZ or 65 to 76 MHz
630 * @details It works only for Band 3. So if you are on band 3 (default 65 – 76 MHz East Europe) you can change the range to 50-65MHz.
631 * @details ATTENTION: The functions setFrequencyToBeginBand and setFrequencyToEnBand do not work for 50-65MHz setup. You have to control it by yourself.
632 * @details ATTENTION: Also, you must control the band limits from 50 to 65 MHz. The setFrequencyUp and setFrequencyDown do not work properly.
633 * @param band3Mode if 1, 65 – 76 MHz; if 0, 50-65MHz
634 */
635void RDA5807::setBand3_50_65_Mode(uint8_t band3Mode)
636{
637 if (this->currentFMBand != 3)
638 return; // Do not do anything if the current band is not 3
639 reg07->refined.MODE_50_60 = band3Mode;
640 setRegister(REG07, reg07->raw);
641}
642
643/**
644 * @ingroup GA03
645 * @brief Gets the status of the Band3
646 * @details Gets the status of the Band3
647 * @return 1 if setup is 65 to 76 MHz; 0 if setup is 50 to 65 MHz
648 */
650{
651 rda_reg07 tmp;
652 tmp.raw = getDirectRegister(0x07).raw;
653 return tmp.refined.MODE_50_60;
654}
655
656/**
657 * @ingroup GA03
658 * @brief Sets the FM channel space.
659 * @details You can define the frequency step in kHz (see table below)
660 *
661 * Channel space table
662 *
663 * | Value | Decimal | Description |
664 * | ----- | ------- | --------------------------- |
665 * | 00 | 0 | 100KHz |
666 * | 01 | 1 | 200KHz |
667 * | 10 | 2 | 50KHz |
668 * | 11 | 3 | 25KHz |
669 *
670 * @code {.cpp}
671 * #include <RDA5807.h>
672 * RDA5807 rx;
673 * void setup() {
674 * pinMode(4, INPUT_PULLUP); // Arduino pin 4 - Frequency Up
675 * pinMode(5, INPUT_PULLUP); // Arduino pin 5 - Frequency Down
676 * rx.setup();
677 * rx.setBandSpace(2); // 50 kHz Step
678 * rx.setFrequency(10390); // Tunes at 103.9 MHz
679 * }
680 * void loop() {
681 * if (digitalRead(4) == LOW) rx.setFrequencyUp(); // Up 50 kHz
682 * if (digitalRead(5) == LOW) rx.setFrequencyDown(); // Down 50 kHz
683 * delay(200);
684 * }
685 * @endcode
686 *
687 * @param space FM channel space. See table above.
688 * @todo make the space 01 (200kHz) work.
689 * @see setStep
690 */
691void RDA5807::setSpace(uint8_t space)
692{
693 reg03->refined.SPACE = space;
694 this->currentFMSpace = space;
695 setRegister(REG03, reg03->raw);
696}
697
698/**
699 * @ingroup GA03 - Frequency step
700 * @brief Sets the FM Step;
701 * @details Converts the step frequency (25, 50, 100 or 200 kHz) to Space. Invalid values will be converted to 0 (100 kHz)
702 * @param step 25, 50, 100 or 200 kHz
703 * @todo Make the step 200kHz work well
704 */
705void RDA5807::setStep(uint8_t step)
706{
707 uint8_t space;
708 switch (step)
709 {
710 case 100:
711 space = 0; // b00
712 break;
713 case 200:
714 space = 1; // b01
715 break;
716 case 50:
717 space = 2; // b10
718 break;
719 case 25:
720 space = 3; // b11
721 break;
722 default:
723 space = 0;
724 }
725 this->setSpace(space);
726}
727
728/**
729 * @ingroup GA03
730 * @brief Sets De-emphasis.
731 * @details Default is 75 μs (used in USA); 50 μs is used in Europe, Australia, Japan.
732 * @code {.cpp}
733 * #include <RDA5807.h>
734 * RDA5807 rx;
735 * void setup() {
736 * rx.setup();
737 * rx.setFrequency(10390); // Tunes at 103.9 MHz
738 * rx.setFmDeemphasis(1); // Sets to 50 μs. Used in Europe, Australia, Japan.
739 * }
740 * void loop() {
741 * }
742 * @endcode
743 *
744 * @param de 0 = 75 μs; 1 = 50 μs
745 */
746void RDA5807::setFmDeemphasis(uint8_t de)
747{
748 reg04->refined.DE = de;
749 setRegister(REG04, reg04->raw);
750}
751
752/**
753 * @defgroup GA04 RDS Functions
754 * @section GA04 RDS/RBDS
755 * @details Is important to mention that almost all the essential methods required to implement RDS are already implemented here.
756 * @details Begin working with RDS, simply invoke the setRDS or setRBDS methods.
757 * @details Querying a set of RDS information, please ensure to call getRdsReady before.
758 */
759
760/**
761 * @ingroup GA04
762 * @brief Sets the RDS operation
763 * @details Enable or Disable the RDS
764 * @details You must call this function before stating deal with RDS.
765 * @code {.cpp}
766 * #include <RDA5807.h>
767 * RDA5807 rx;
768 * void setup()
769 * rx.setup(); // Starts the receiver with default parameters
770 * rx.setRDS(true);
771 * rx.setRdsFifo(true);
772 * rx.setFrequency(10390); // Station with RDS service
773 * }
774 * @endcode
775 * @param true = turns the RDS ON; false = turns the RDS OFF
776 * @see setRdsFifo
777 */
778void RDA5807::setRDS(bool value)
779{
780 this->oldTextABFlag = reg02->refined.SEEK = 0;
781 reg02->refined.RDS_EN = value;
782 setRegister(REG02, reg02->raw);
783}
784
785/**
786 * @ingroup GA04
787 * @brief Sets the RBDS operation
788 * @details Enable or Disable the RDS
789 *
790 * @param true = turns the RBDS ON; false = turns the RBDS OFF
791 */
792void RDA5807::setRBDS(bool value)
793{
794 this->oldTextABFlag = reg02->refined.SEEK = 0;
795 reg02->refined.RDS_EN = 1;
796 setRegister(REG02, reg02->raw);
797 reg04->refined.RBDS = value;
798 setRegister(REG04, reg04->raw);
799}
800
801/**
802 * @ingroup GA04
803 * @brief Returns true if RDS Ready
804 * @details Read address 0Ah and check the bit RDSR.
805 * @details When using the polling method, it is best not to poll continuously. The data will appear in intervals.
806 * @details ATTENTION: You must call this function before calling any RDS query
807 * @code {.cpp}
808 * if (rx.getRdsReady()) {
809 * if (rx.hasRdsInfo() ) {
810 * rdsMsg = rx.getRdsProgramInformation();
811 * stationName = rx.getRdsStationName();
812 * rdsTime = rx.getRdsTime(); // Gets the UTC Time. Check the getRdsTime documentation for more details. Some stations do not broadcast the right time.
813 * }
814 * }
815 * @endcode
816 *
817 * @return true or false
818 * @see setRDS, setInterruptMode, getRdsAllData, getRdsSync, setRdsFifo
819 * @see [2wcom - RDS BasicsRDS](https://www.2wcom.com/fileadmin/redaktion/dokumente/Company/RDS_Basics.pdf)
820 *
821 */
823{
824 // getStatus(REG0A);
826
827 return reg0a->refined.RDSR;
828}
829
830/**
831 * @ingroup GA04
832 * @brief Returns the current Text Flag A/B
833 * @details ATTENTION: You must call getRdsReady before calling this function.
834 * @return uint8_t current Text Flag A/B
835 * @see getRdsReady
836 */
838{
839 rds_blockb blkb;
840 blkb.blockB = reg0d->RDSB;
841 return blkb.refined.textABFlag;
842}
843
844/**
845 * @ingroup GA04
846 *
847 * @brief Returns true if the Text Flag A/B has changed
848 * @details This function returns true if a new FlagAB has chenged. Also it clears the Station Name buffer in that condition.
849 * @details It is useful to check and show the RDS Text in your application.
850 * @details You must call getRdsReady before calling this function.
851 *
852 * @return True or false
853 */
855{
856 rds_blockb blkb;
857 blkb.blockB = reg0d->RDSB;
858 if (blkb.refined.textABFlag != this->oldTextABFlag)
859 {
860 this->oldTextABFlag = blkb.refined.textABFlag; // saves the latest value
861 memset(rds_buffer0A, 0, sizeof(rds_buffer0A));
862
863 return true;
864 }
865 return false;
866}
867
868/**
869 * @ingroup GA04
870 * @brief Gets Station Name, Station Information, Program Information and utcTime
871 * @details This function populates four char pointer variable parameters with Station Name, Station Information, Programa Information and UTC time.
872 * @details You must call setRDS(true), setRdsFifo(true) before calling getRdsAllData(...)
873 * @details ATTENTION: the parameters below are point to point to array of char.
874 * @details the right way to call this function is shown below.
875 * @code {.cpp}
876 *
877 * char *stationName, *stationInfo, *programInfo, *rdsTime;
878 * // The char pointers above will be populate by the call below. So, the char pointers need to be passed by reference (pointer to pointer).
879 * if (rx.getRdsAllData(&stationName, &stationInfo , &programInfo, &rdsTime) ) {
880 * showProgramaInfo(programInfo);
881 * showStationName(stationName);
882 * showStationInfo(stationInfo);
883 * showUtcTime(rdsTime);
884 * }
885 * @endcode
886 * @param stationName (reference) - if NOT NULL, point to Name of the Station (char array - 9 bytes)
887 * @param stationInformation (reference) - if NOT NULL, point to Station information (char array - 33 bytes)
888 * @param programInformation (reference) - if NOT NULL, point to program information (char array - 65 nytes)
889 * @param utcTime (reference) - if NOT NULL, point to char array containing the current UTC time (format HH:MM:SS +HH:MM)
890 * @return True if found at least one valid data
891 * @see setRDS, setRdsFifo, getRdsAllData
892 */
893bool RDA5807::getRdsAllData(char **stationName, char **stationInformation, char **programInformation, char **utcTime) {
894
895 if ( !this->getRdsReady() ) return false;
896 if ( !this->hasRdsInfoAB() ) return false;
897 *stationName = this->getRdsText0A(); // returns NULL if no information
898 *stationInformation = this->getRdsText2B(); // returns NULL if no information
899 *programInformation = this->getRdsText2A(); // returns NULL if no information
900 *utcTime = this->getRdsTime(); // returns NULL if no information
901
902 return (bool)stationName | (bool)stationInformation | (bool) programInformation | (bool) utcTime;
903}
904
905
906/**
907 * @ingroup GA04
908 * @brief Return the group type
909 * @details ATTENTION: You must call getRdsReady before calling this function.
910 * @return uint16_t
911 * @see getRdsReady
912 */
914{
915 rds_blockb blkb;
916 blkb.blockB = reg0d->RDSB;
917 return blkb.group0.groupType;
918}
919
920/**
921 * @ingroup GA04
922 * @brief Gets the version code (extracted from the Block B)
923 * @details ATTENTION: You must call getRdsReady before calling this function.
924 * @returns 0=A or 1=B
925 * @see getRdsReady
926 */
928{
929 rds_blockb blkb;
930 blkb.blockB = reg0d->RDSB;
931 return blkb.refined.versionCode;
932}
933
934/**
935 * @ingroup GA04
936 * @brief Returns the Program Type (extracted from the Block B)
937 * @details ATTENTION: You must call getRdsReady before calling this function.
938 * @see https://en.wikipedia.org/wiki/Radio_Data_System
939 * @see [2wcom RDS Basics](https://www.2wcom.com/fileadmin/redaktion/dokumente/Company/RDS_Basics.pdf)
940 * @see getRdsReady
941 * @return program type (an integer betwenn 0 and 31)
942 */
944{
945 rds_blockb blkb;
946 blkb.blockB = reg0d->RDSB;
947 return blkb.refined.programType;
948}
949
950/**
951 * @ingroup GA04
952 *
953 * @brief Process data received from group 2B
954 * @param c char array reference to the "group 2B" text
955 */
956void RDA5807::getNext2Block(char *c)
957{
958 char raw[2];
959 int i, j;
960 word16_to_bytes blk;
961
962 blk.raw = reg0f->RDSD;
963
964 raw[1] = blk.refined.lowByte;
965 raw[0] = blk.refined.highByte;
966
967 for (i = j = 0; i < 2; i++)
968 {
969 if (raw[i] == 0xD || raw[i] == 0xA)
970 {
971 c[j] = '\0';
972 return;
973 }
974 if (raw[i] >= 32)
975 {
976 c[j] = raw[i];
977 j++;
978 }
979 else
980 {
981 c[i] = ' ';
982 }
983 }
984}
985
986/**
987 * @ingroup GA04
988 *
989 * @brief Process data received from group 2A
990 *
991 * @param c char array reference to the "group 2A" text
992 */
993void RDA5807::getNext4Block(char *c)
994{
995 char raw[4];
996 int i, j;
997 word16_to_bytes blk_c, blk_d;
998
999 blk_c.raw = reg0e->RDSC;
1000 blk_d.raw = reg0f->RDSD;
1001
1002 raw[0] = blk_c.refined.highByte;
1003 raw[1] = blk_c.refined.lowByte;
1004 raw[2] = blk_d.refined.highByte;
1005 raw[3] = blk_d.refined.lowByte;
1006
1007 for (i = j = 0; i < 4; i++)
1008 {
1009 if (raw[i] == 0xD || raw[i] == 0xA)
1010 {
1011 c[j] = '\0';
1012 return;
1013 }
1014 if (raw[i] >= 32)
1015 {
1016 c[j] = raw[i];
1017 j++;
1018 }
1019 else
1020 {
1021 c[i] = ' ';
1022 }
1023 }
1024}
1025
1026
1027/**
1028 * @ingroup GA04
1029 * @brief Gets the station name and other messages.
1030 * @details ATTENTION: You must call getRdsReady before calling this function.
1031 * @return char* should return a string with the station name.
1032 * However, some stations send other kind of messages
1033 * @see getRdsReady
1034 */
1036{
1037 static int rdsTextAdress0A;
1038 rds_blockb blkb;
1039
1040 blkb.blockB = reg0d->RDSB;
1041
1042 if (blkb.group0.groupType == 0)
1043 {
1044 // Process group type 0
1045 rdsTextAdress0A = blkb.group0.address;
1046 if (rdsTextAdress0A >= 0 && rdsTextAdress0A < 4)
1047 {
1048 getNext2Block(&rds_buffer0A[rdsTextAdress0A * 2]);
1049 rds_buffer0A[8] = '\0';
1050 return rds_buffer0A;
1051 }
1052 }
1053 return NULL;
1054}
1055
1056/**
1057 * @ingroup @ingroup GA04
1058 *
1059 * @brief Gets the Program Information
1060 * @details Process the program information data.
1061 * @details ATTENTION: You must call getRdsReady before calling this function.
1062 * @return char array with the program information (63 bytes)
1063 * @see getRdsReady
1064 */
1066{
1067 static int rdsTextAdress2A;
1068 rds_blockb blkb;
1069
1070 blkb.blockB = reg0d->RDSB;
1071 rdsTextAdress2A = blkb.group2.address;
1072
1073 if (blkb.group2.groupType == 2)
1074 {
1075 // Process group 2A
1076 // Decode B block information
1077 if (rdsTextAdress2A >= 0 && rdsTextAdress2A < 16)
1078 {
1079 getNext4Block(&rds_buffer2A[rdsTextAdress2A * 4]);
1080 rds_buffer2A[63] = '\0';
1081 return rds_buffer2A;
1082 }
1083 }
1084 return NULL;
1085}
1086
1087/**
1088 * @ingroup GA04
1089 * @todo Under construction... To be checked.
1090 * @brief Gets the Station Information.
1091 * @details ATTENTION: You must call getRdsReady before calling this function.
1092 * @return char array with the Text of Station Information (33 bytes)
1093 * @see getRdsReady
1094 */
1096{
1097 static int rdsTextAdress2B;
1098 rds_blockb blkb;
1099
1100 blkb.blockB = reg0d->RDSB;
1101 if (blkb.group2.groupType == 1)
1102 {
1103 // Process group 2B
1104 rdsTextAdress2B = blkb.group2.address;
1105 if (rdsTextAdress2B >= 0 && rdsTextAdress2B < 16)
1106 {
1107 getNext2Block(&rds_buffer2B[rdsTextAdress2B * 2]);
1108 return rds_buffer2B;
1109 }
1110 }
1111 return NULL;
1112}
1113
1114/**
1115 * @ingroup GA04
1116 * @brief Gets the RDS UTC time and date when the Group type is 4
1117 * @details ATTENTION: You must call getRdsReady before calling this function.
1118 * @details ATTENTION: Some stations broadcast wrong time.
1119 * @return char* a string with hh:mm +/- offset
1120 * @see getRdsReady
1121 */
1123{
1124 rds_date_time dt;
1125 word16_to_bytes blk_b, blk_c, blk_d;
1126 rds_blockb blkb;
1127
1128 blk_b.raw = blkb.blockB = reg0d->RDSB;
1129 blk_c.raw = reg0e->RDSC;
1130 blk_d.raw = reg0f->RDSD;
1131
1132 uint16_t minute;
1133 uint16_t hour;
1134
1135 if (blkb.group0.groupType == 4)
1136 {
1137 char offset_sign;
1138 int offset_h;
1139 int offset_m;
1140
1141 // uint16_t y, m, d;
1142
1143 dt.raw[4] = blk_b.refined.lowByte;
1144 dt.raw[5] = blk_b.refined.highByte;
1145
1146 dt.raw[2] = blk_c.refined.lowByte;
1147 dt.raw[3] = blk_c.refined.highByte;
1148
1149 dt.raw[0] = blk_d.refined.lowByte;
1150 dt.raw[1] = blk_d.refined.highByte;
1151
1152 minute = dt.refined.minute;
1153 hour = dt.refined.hour;
1154
1155 offset_sign = (dt.refined.offset_sense == 1) ? '+' : '-';
1156 offset_h = (dt.refined.offset * 30) / 60;
1157 offset_m = (dt.refined.offset * 30) - (offset_h * 60);
1158
1159 // sprintf(rds_time, "%02u:%02u %c%02u:%02u", hour, minute, offset_sign, offset_h, offset_m);
1160 this->convertToChar(hour, rds_time, 2, 0, ' ', false);
1161 rds_time[2] = ':';
1162 this->convertToChar(minute, &rds_time[3], 2, 0, ' ', false);
1163 rds_time[5] = ' ';
1164 rds_time[6] = offset_sign;
1165 this->convertToChar(offset_h, &rds_time[7], 2, 0, ' ', false);
1166 rds_time[9] = ':';
1167 this->convertToChar(offset_m, &rds_time[10], 2, 0, ' ', false);
1168 rds_time[12] = '\0';
1169
1170 return rds_time;
1171 }
1172
1173 return NULL;
1174}
1175
1176/**
1177 * @ingroup GA04
1178 * @todo Need to check.
1179 * @brief Gets the RDS time converted to local time.
1180 * @details ATTENTION: You must call getRdsReady before calling this function.
1181 * @details ATTENTION: Some stations broadcast wrong time.
1182 * @return char* a string with hh:mm
1183 * @see getRdsReady
1184 */
1186{
1187 rds_date_time dt;
1188 word16_to_bytes blk_b, blk_c, blk_d;
1189 rds_blockb blkb;
1190
1191 blk_b.raw = blkb.blockB = reg0d->RDSB;
1192 blk_c.raw = reg0e->RDSC;
1193 blk_d.raw = reg0f->RDSD;
1194
1195 uint16_t minute;
1196 uint16_t hour;
1197 uint16_t localTime;
1198
1199 if (blkb.group0.groupType == 4)
1200 {
1201 int offset_h;
1202 int offset_m;
1203
1204 dt.raw[4] = blk_b.refined.lowByte;
1205 dt.raw[5] = blk_b.refined.highByte;
1206
1207 dt.raw[2] = blk_c.refined.lowByte;
1208 dt.raw[3] = blk_c.refined.highByte;
1209
1210 dt.raw[0] = blk_d.refined.lowByte;
1211 dt.raw[1] = blk_d.refined.highByte;
1212
1213 minute = dt.refined.minute;
1214 hour = dt.refined.hour;
1215
1216 offset_h = (dt.refined.offset * 30) / 60;
1217 offset_m = (dt.refined.offset * 30) - (offset_h * 60);
1218
1219 localTime = (hour * 60 + minute);
1220 if ( dt.refined.offset_sense == 1)
1221 localTime -= (offset_h * 60 + offset_m);
1222 else
1223 localTime += (offset_h * 60 + offset_m);
1224
1225 hour = localTime / 60;
1226 minute = localTime - (hour * 60);
1227
1228 this->convertToChar(hour, rds_time, 2, 0, ' ', false);
1229 rds_time[2] = ':';
1230 this->convertToChar(minute, &rds_time[3], 2, 0, ' ', false);
1231 rds_time[5] = '\0';
1232
1233 return rds_time;
1234 }
1235
1236 return NULL;
1237}
1238
1239
1240
1241
1242/**
1243 * @ingroup GA04
1244 * @brief Sets RDS fifo mode enable
1245 *
1246 * @param value If true, it makes the the fifo mode enable.
1247 * @return true or false
1248 */
1249void RDA5807::setRdsFifo(bool value)
1250{
1251 reg04->refined.RDS_FIFO_EN = value;
1252 setRegister(REG04, reg04->raw);
1253}
1254
1255/**
1256 * @ingroup GA04
1257 * @brief Clear RDS fifo
1258 *
1259 * @param value If true, clears the RDS fifo
1260 * @return true or false
1261 */
1262void RDA5807::clearRdsFifo(bool value)
1263{
1264 reg04->refined.RDS_FIFO_CLR = value;
1265 setRegister(REG04, reg04->raw);
1266}
1267
1268
1269/**
1270 * @ingroup GA04
1271 * @brief Clear RDS Information (Station Name, Station Information, Program Information and Time)
1272 * @details Clear the buffer with latest RDS information
1273 */
1275{
1276 memset(rds_buffer0A, 0, sizeof(rds_buffer0A));
1277 memset(rds_buffer2A , 0, sizeof(rds_buffer2A));
1278 memset(rds_buffer2B, 0, sizeof(rds_buffer2B));
1279 memset(rds_time, 0, sizeof(rds_time));
1280}
1281
1282
1283
1284/** @defgroup G05 Tools method
1285 * @details A set of functions used to support other functions
1286 */
1287
1288/**
1289 * @ingroup G05 Covert numbers to char array
1290 * @brief Converts a number to a char array
1291 * @details It is useful to mitigate memory space used by functions like sprintf or othetr generic similar functions
1292 * @details You can use it to format frequency using decimal or tousand separator and also to convert smalm numbers.
1293 *
1294 * @param value value to be converted
1295 * @param strValue char array that will be receive the converted value
1296 * @param len final string size (in bytes)
1297 * @param dot the decimal or tousand separator position
1298 * @param separator symbol "." or ","
1299 * @param remove_leading_zeros if true removes up to two leading zeros (default is true)
1300 */
1301void RDA5807::convertToChar(uint16_t value, char *strValue, uint8_t len, uint8_t dot, uint8_t separator, bool remove_leading_zeros)
1302{
1303 char d;
1304 for (int i = (len - 1); i >= 0; i--)
1305 {
1306 d = value % 10;
1307 value = value / 10;
1308 strValue[i] = d + 48;
1309 }
1310 strValue[len] = '\0';
1311 if (dot > 0)
1312 {
1313 for (int i = len; i >= dot; i--)
1314 {
1315 strValue[i + 1] = strValue[i];
1316 }
1317 strValue[dot] = separator;
1318 }
1319
1320 if (remove_leading_zeros)
1321 {
1322 if (strValue[0] == '0')
1323 {
1324 strValue[0] = ' ';
1325 if (strValue[1] == '0')
1326 strValue[1] = ' ';
1327 }
1328 }
1329}
1330
1331/**
1332 * @ingroup G05 Check the I2C buss address
1333 * @brief Check the I2C bus address
1334 *
1335 * @param uint8_t address Array - this array will be populated with the I2C bus addresses found (minimum three elements)
1336 * @return 0 if no i2c device is found; -1 if error is found or n > 0, where n is the number of I2C bus address found
1337 */
1338int RDA5807::checkI2C(uint8_t *addressArray)
1339{
1340 Wire.begin();
1341 int error, address;
1342 int idx = 0;
1343 for (address = 1; address < 127; address++)
1344 {
1345 Wire.beginTransmission(address);
1346 error = Wire.endTransmission();
1347 if (error == 0)
1348 {
1349 addressArray[idx] = address;
1350 idx++;
1351 }
1352 else if (error == 4)
1353 return -1;
1354 }
1355 return idx;
1356}
1357
1358/**
1359 * @defgroup GA06 I2S Functions
1360 * @section GA06 I2S
1361 * @details When setting I2S_ENABLE (register 04) bit is high, the RDA5807FP can get the output signals SCK, WS, SD signals from GPIO3, GPIO1 and GPIO2 (I2S master)
1362 */
1363
1364/**
1365 * @ingroup GA06 set I2S
1366 * @brief Configures all parameters for I2S
1367 * @details I2S setup must be enabled
1368 * @details I2S_SW_CNT can be: I2S_WS_STEP_48, I2S_WS_STEP_44_1, I2S_WS_STEP_32, I2S_WS_STEP_24, I2S_WS_STEP_22_05, I2S_WS_STEP_16, I2S_WS_STEP_12, I2S_WS_STEP_11_025 or I2S_WS_STEP_8
1369 *
1370 * @param R_DELY If 1, R channel data delay 1T
1371 * @param L_DELY If 1, L channel data delay 1T
1372 * @param SCLK_O_EDGE If 1, invert sclk output when as master
1373 * @param SW_O_EDGE If 1, invert ws output when as master
1374 * @param I2S_SW_CNT Only valid in master mode. See table above
1375 * @param WS_I_EDGE If 0, use normal ws internally; If 1, inverte ws internally
1376 * @param DATA_SIGNED If 0, I2S output unsigned 16-bit audio data. If 1, I2S output signed 16-bit audio data.
1377 * @param SCLK_I_EDGE If 0, use normal sclk internally;If 1, inverte sclk internally
1378 * @param WS_LR Ws relation to l/r channel; If 0, ws=0 ->r, ws=1 ->l; If 1, ws=0 ->l, ws=1 ->r
1379 * @param SLAVE_MASTER I2S slave or master; 1 = slave; 0 = master
1380 * @param OPEN_MODE Open reserved register mode; 11=open behind registers writing function others: only open behind registers reading function
1381 *
1382 * @see RDA microelectronics RDA5807FP - SINGLE-CHIP BROADCAST FM RADIO TUNER pages 11 and 12
1383 *
1384 * @see setI2SOn
1385 */
1386void RDA5807::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)
1387{
1388 reg06->refined.R_DELY = R_DELY;
1389 reg06->refined.L_DELY = L_DELY;
1390 reg06->refined.SCLK_O_EDGE = SCLK_O_EDGE;
1391 reg06->refined.SW_O_EDGE = SW_O_EDGE;
1392 reg06->refined.I2S_SW_CNT = I2S_SW_CNT;
1393 reg06->refined.WS_I_EDGE = WS_I_EDGE;
1394 reg06->refined.DATA_SIGNED = DATA_SIGNED;
1395 reg06->refined.SCLK_I_EDGE = SCLK_I_EDGE;
1396 reg06->refined.WS_LR = WS_LR;
1397 reg06->refined.SLAVE_MASTER = SLAVE_MASTER;
1398 reg06->refined.OPEN_MODE = OPEN_MODE;
1399
1400 setRegister(REG06, reg06->raw);
1401}
1402
1403/**
1404 * @ingroup GA06 set I2S on or off
1405 * @brief Enables I2S setup
1406 * @details When setting I2S_ENABLE (register 04) bit is high, the RDA5807FP you can get the output signals SCK, WS, SD signals from GPIO3, GPIO1 and GPIO2 (I2S master)
1407 *
1408 * @param value true or false
1409 */
1410void RDA5807::setI2SOn(bool value)
1411{
1412 reg04->refined.I2S_ENABLE = value;
1413 setRegister(REG04, reg04->raw);
1414}
1415
1416/**
1417 * @ingroup GA06 Sets I2S Slave or Master
1418 * @brief
1419 *
1420 * @param value true or false
1421 */
1422void RDA5807::setI2SMaster(bool value)
1423{
1424 reg06->refined.SLAVE_MASTER = !value;
1425 setRegister(REG06, reg06->raw);
1426}
1427
1428/**
1429 * @ingroup GA06 Sets I2S STEP/SPEED
1430 * @brief Sets the speed in kbps. You can use the predefined constantes: I2S_WS_STEP_48, I2S_WS_STEP_44_1, I2S_WS_STEP_32,
1431 * @brief I2S_WS_STEP_24, I2S_WS_STEP_22_05, I2S_WS_STEP_16, I2S_WS_STEP_12, I2S_WS_STEP_11_025 or I2S_WS_STEP_8
1432 *
1433 * @param value value
1434 */
1435void RDA5807::setI2SSpeed(uint8_t value)
1436{
1437 reg06->refined.I2S_SW_CNT = value;
1438 setRegister(REG06, reg06->raw);
1439}
1440
1441/**
1442 * @ingroup GA06 Sets I2S Data Signed
1443 * @brief If 0, I2S output unsigned 16-bit audio data. If 1, I2S output signed 16-bit audio data.
1444 *
1445 * @param value true (1) or false (0)
1446 */
1447void RDA5807::setI2SDataSigned(bool value)
1448{
1449 reg06->refined.DATA_SIGNED = value;
1450 setRegister(REG06, reg06->raw);
1451}
1452
1453/**
1454 * @defgroup GA07 Audio Functions
1455 * @section GA07 Audio
1456 */
1457
1458/**
1459 * @ingroup GA07
1460 * @brief Sets Soft Mute Enable or disable
1461 * @param value true = enable; false=disable
1462 */
1463void RDA5807::setSoftmute(bool value)
1464{
1465 reg04->refined.SOFTMUTE_EN = value;
1466 setRegister(REG04, reg04->raw);
1467}
1468
1469/**
1470 * @ingroup GA07
1471 * @brief Sets Audio mute or unmute
1472 * @param value TRUE = mute; FALSE = unmute
1473 */
1474void RDA5807::setMute(bool value)
1475{
1476 reg02->refined.SEEK = 0;
1477 reg02->refined.DMUTE = !value; // 1 = Normal operation; 0 = Mute
1478 setRegister(REG02, reg02->raw);
1479}
1480
1481/**
1482 * @ingroup GA07
1483 * @brief Sets audio output impedance high ow low
1484 * @details Useful to setup high impedance headphones
1485 * @param value TRUE = High; FALSE = Low
1486 */
1488{
1489 reg02->refined.SEEK = 0;
1490 reg02->refined.DHIZ = !value; // 0 = High impedance; 1 = Normal operation
1491 setRegister(REG02, reg02->raw);
1492}
1493
1494/**
1495 * @ingroup GA07
1496 * @brief Sets audio Mono or stereo
1497 *
1498 * @param value TRUE = Mono; FALSE force stereo
1499 */
1500void RDA5807::setMono(bool value)
1501{
1502 reg02->refined.SEEK = 0;
1503 reg02->refined.MONO = value;
1504 setRegister(REG02, reg02->raw);
1505}
1506
1507/**
1508 * @ingroup GA07
1509 * @brief Sets Bass Boost
1510 *
1511 * @param value FALSE = Disable; TRUE = Enable
1512 */
1513void RDA5807::setBass(bool value)
1514{
1515 reg02->refined.SEEK = 0;
1516 reg02->refined.BASS = value;
1517 setRegister(REG02, reg02->raw);
1518}
1519
1520/**
1521 * @ingroup GA07
1522 * @brief Gets the current Stereo status
1523 *
1524 * @return TRUE if stereo;
1525 */
1527{
1528 getStatus(REG0A);
1529 return reg0a->refined.ST;
1530}
1531
1532/**
1533 * @ingroup GA07
1534 * @brief Sets the audio volume level
1535 * @details You can use values between 0 and 15.
1536 * @code {.cpp}
1537 * #include <RDA5807.h>
1538 * RDA5807 rx;
1539 * void setup() {
1540 * pinMode(4, INPUT_PULLUP); // Arduino pin 4 - Volume Up
1541 * pinMode(5, INPUT_PULLUP); // Arduino pin 5 - Volume Down
1542 * rx.setup();
1543 * rx.setFrequency(10390); // Tunes at 103.9 MHz
1544 * rx.setVolume(7);
1545 * }
1546 * void loop() {
1547 * if (digitalRead(4) == LOW) rx.setVolumeUp();
1548 * if (digitalRead(5) == LOW) rx.setVolumeDown();
1549 * delay(200);
1550 * }
1551 * @endcode
1552 *
1553 * @param value (from 0 to 15)
1554 * @see setVolumeUp, setVolumeDown, setMute, getVolume
1555 */
1556void RDA5807::setVolume(uint8_t value)
1557{
1558 if (value > 15)
1559 value = 15;
1560
1561 reg05->refined.VOLUME = this->currentVolume = value;
1562 setRegister(REG05, reg05->raw);
1563}
1564
1565/**
1566 * @ingroup GA07
1567 * @brief Gets the current audio volume level
1568 *
1569 * @return uint8_t 0 to 15
1570 */
1572{
1573 return this->currentVolume;
1574}
1575
1576/**
1577 * @ingroup GA07
1578 * @brief Increments the audio volume
1579 *
1580 */
1582{
1583 if (this->currentVolume < 15)
1584 {
1585 this->currentVolume++;
1586 setVolume(this->currentVolume);
1587 }
1588}
1589
1590/**
1591 * @ingroup GA07
1592 * @brief Decrements the audio volume
1593 *
1594 */
1596{
1597 if (this->currentVolume > 0)
1598 {
1599 this->currentVolume--;
1600 setVolume(this->currentVolume);
1601 }
1602}
1603
1604/**
1605 * @defgroup GA08 LNA setup and Signal status
1606 * @section GA08 LNA and Signal
1607 */
1608
1609/**
1610 * @ingroup GA08
1611 * @brief Sets LNA_ICSEL_BIT
1612 * @details Lna working current bit: 0=1.8mA; 1=2.1mA; 2=2.5mA; 3=3.0mA (default 0).
1613 * @param value - 0=1.8mA; 1=2.1mA; 2=2.5mA; 3=3.0mA
1614 */
1615void RDA5807::setLnaIcSel(uint8_t value)
1616{
1617 reg05->refined.LNA_ICSEL_BIT = value;
1618 setRegister(REG05, reg05->raw);
1619}
1620
1621/**
1622 * @ingroup GA08
1623 * @brief Sets LNA input port selection bit
1624 * @details YOu can select: 0 = no input; 1 = LNAN; 2 = LNAP; 3: dual port input
1625 * @param value - 0 = no input; 1 = LNAN; 2 = LNAP; 3: dual port input
1626 */
1627void RDA5807::setLnaPortSel(uint8_t value)
1628{
1629 reg05->refined.LNA_PORT_SEL = value;
1630 setRegister(REG05, reg05->raw);
1631}
1632
1633/**
1634 * @ingroup GA08
1635 * @brief Gets the current Rssi
1636 * @details RSSI; 000000 = min; 111111 = max; RSSI scale is logarithmic.
1637 *
1638 * @return int
1639 */
1641{
1642 getStatus(REG0B);
1643 return reg0b->refined.RSSI;
1644}
#define REG02
Register 0x02.
Definition: RDA5807.h:63
#define REG07
Register 0x07.
Definition: RDA5807.h:68
#define REG0A
Register 0x0A.
Definition: RDA5807.h:70
#define REG0B
Register 0x0B.
Definition: RDA5807.h:71
#define REG05
Register 0x05.
Definition: RDA5807.h:66
#define REG04
Register 0x04.
Definition: RDA5807.h:65
#define REG08
Register 0x08.
Definition: RDA5807.h:69
#define REG03
Register 0x03.
Definition: RDA5807.h:64
#define REG06
Register 0x06.
Definition: RDA5807.h:67
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:1301
int checkI2C(uint8_t *addressArray)
Check the I2C bus address.
Definition: RDA5807.cpp:1338
char rds_buffer0A[9]
PS - RDS Basic tuning and switching information (Type 0 groups) - Station Name.
Definition: RDA5807.h:599
char rds_time[25]
CT - RDS date time received information - UTC Time.
Definition: RDA5807.h:600
char rds_buffer2B[33]
RDS Radio Text buffer - Station Information.
Definition: RDA5807.h:598
char rds_buffer2A[65]
RT - RDS Radio Text buffer - Program Information.
Definition: RDA5807.h:597
KT0915 Class.
Definition: RDA5807.h:568
void * getStatus(uint8_t reg)
Gets the register content of a given status register (from 0x0A to 0x0F)
Definition: RDA5807.cpp:124
void powerDown()
Power the receiver off.
Definition: RDA5807.cpp:240
void setup(uint8_t clock_frequency=CLOCK_32K, uint8_t oscillator_type=OSCILLATOR_TYPE_PASSIVE, uint8_t rlck_no_calibrate=RLCK_NO_CALIBRATE_MODE_OFF)
Starts the device.
Definition: RDA5807.cpp:273
void powerUp()
Powers the receiver on.
Definition: RDA5807.cpp:197
void setRegister(uint8_t reg, uint16_t value)
Sets a given value to a specific device register.
Definition: RDA5807.cpp:154
void softReset()
Resets the device.
Definition: RDA5807.cpp:187
void waitAndFinishTune()
Waits for Seek or Tune finish.
Definition: RDA5807.cpp:173
void setGpio(uint8_t gpioPin, uint8_t gpioSetup=0, int mcuPin=-1)
Sets the Device GPIO pins.
Definition: RDA5807.cpp:34
void setNewDemodulateMethod(bool value)
Sets new demodulate method. It can improve the receiver sensitivity about 1dB.
Definition: RDA5807.cpp:230
void getStatusRegisters()
Gets all current device status and RDS information registers (From 0x0A to 0x0F)
Definition: RDA5807.cpp:79
void setInterruptMode(uint8_t value)
Sets Interrupt Mode.
Definition: RDA5807.cpp:65
uint16_t getDeviceId()
Gets the Device identification.
Definition: RDA5807.cpp:291
void setBand3_50_65_Mode(uint8_t band3Mode)
Sets the band 3 mode: 50 to 65 MHZ or 65 to 76 MHz.
Definition: RDA5807.cpp:635
uint16_t getRealFrequency()
Gets the current frequency bases on the current channel.
Definition: RDA5807.cpp:490
uint16_t getRealChannel()
Gets the current channel stored in 0x0A status register.
Definition: RDA5807.cpp:468
void setSeekThreshold(uint8_t value)
Sets RSSI Seek Threshold.
Definition: RDA5807.cpp:585
void setDirectFrequency(uint16_t frequency)
Sets the frequency using the reg08 (direct frequency)
Definition: RDA5807.cpp:385
void setFrequencyUp()
Increments the current frequency.
Definition: RDA5807.cpp:424
void setFmDeemphasis(uint8_t de)
Sets De-emphasis.
Definition: RDA5807.cpp:746
uint16_t getFrequency()
Gets the current frequency.
Definition: RDA5807.cpp:454
void setSoftBlendEnable(bool value)
Sets Soft Blend.
Definition: RDA5807.cpp:308
void setSpace(uint8_t space=0)
Sets the FM channel space.
Definition: RDA5807.cpp:691
void seek(uint8_t seek_mode, uint8_t direction)
Seek function.
Definition: RDA5807.cpp:518
void setBand(uint8_t band=0)
Sets the FM band. See table below.
Definition: RDA5807.cpp:621
void setStep(uint8_t step=100)
Sets the FM Step;.
Definition: RDA5807.cpp:705
void setAFC(bool value)
Sets AFC true or false.
Definition: RDA5807.cpp:320
void setChannel(uint16_t channel)
Sets the channel.
Definition: RDA5807.cpp:338
void setFrequency(uint16_t frequency)
Sets the frequency.
Definition: RDA5807.cpp:372
void setFrequencyDown()
Decrements the current frequency.
Definition: RDA5807.cpp:439
void seek(uint8_t seek_mode, uint8_t direction, void(*showFunc)())
Seek function.
Definition: RDA5807.cpp:559
void setFrequencyMode(uint8_t value)
Sets the frequency mode. If 1, then freq setting changed.
Definition: RDA5807.cpp:397
uint8_t getBand3Status()
Gets the status of the Band3.
Definition: RDA5807.cpp:649
uint8_t getRdsFlagAB(void)
Returns the current Text Flag A/B.
Definition: RDA5807.cpp:837
void clearRdsFifo(bool value=1)
Clear RDS fifo.
Definition: RDA5807.cpp:1262
void clearRdsBuffer()
Clear RDS Information (Station Name, Station Information, Program Information and Time)
Definition: RDA5807.cpp:1274
uint16_t getRdsGroupType()
Return the group type.
Definition: RDA5807.cpp:913
void getNext4Block(char *c)
Process data received from group 2A.
Definition: RDA5807.cpp:993
char * getRdsText2A(void)
Gets the Program Information.
Definition: RDA5807.cpp:1065
void setRDS(bool value)
Sets the RDS operation.
Definition: RDA5807.cpp:778
char * getRdsText0A(void)
Gets the station name and other messages.
Definition: RDA5807.cpp:1035
void getNext2Block(char *c)
Process data received from group 2B.
Definition: RDA5807.cpp:956
char * getRdsLocalTime()
Gets the RDS time converted to local time.
Definition: RDA5807.cpp:1185
bool hasRdsInfoAB()
Returns true when the RDS system has valid information.
Definition: RDA5807.h:969
char * getRdsText2B(void)
Gets the Station Information.
Definition: RDA5807.cpp:1095
bool getRdsReady()
Returns true if RDS Ready.
Definition: RDA5807.cpp:822
bool isNewRdsFlagAB(void)
Returns true if the Text Flag A/B has changed.
Definition: RDA5807.cpp:854
uint8_t getRdsVersionCode(void)
Gets the version code (extracted from the Block B)
Definition: RDA5807.cpp:927
bool getRdsAllData(char **stationName, char **stationInformation, char **programInformation, char **utcTime)
Gets Station Name, Station Information, Program Information and utcTime.
Definition: RDA5807.cpp:893
void setRdsFifo(bool value)
Sets RDS fifo mode enable.
Definition: RDA5807.cpp:1249
uint8_t getRdsProgramType(void)
Returns the Program Type (extracted from the Block B)
Definition: RDA5807.cpp:943
void setRBDS(bool value)
Sets the RBDS operation.
Definition: RDA5807.cpp:792
char * getRdsTime()
Gets the RDS UTC time and date when the Group type is 4.
Definition: RDA5807.cpp:1122
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:1386
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:1435
void setI2SMaster(bool value)
Definition: RDA5807.cpp:1422
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:1447
void setI2SOn(bool value)
Enables I2S setup.
Definition: RDA5807.cpp:1410
bool isStereo()
Gets the current Stereo status.
Definition: RDA5807.cpp:1526
void setVolume(uint8_t value)
Sets the audio volume level.
Definition: RDA5807.cpp:1556
uint8_t getVolume()
Gets the current audio volume level.
Definition: RDA5807.cpp:1571
void setBass(bool value)
Sets Bass Boost.
Definition: RDA5807.cpp:1513
void setVolumeUp()
Increments the audio volume.
Definition: RDA5807.cpp:1581
void setVolumeDown()
Decrements the audio volume.
Definition: RDA5807.cpp:1595
void setAudioOutputHighImpedance(bool value)
Sets audio output impedance high ow low.
Definition: RDA5807.cpp:1487
void setMono(bool value)
Sets audio Mono or stereo.
Definition: RDA5807.cpp:1500
void setSoftmute(bool value)
Sets Soft Mute Enable or disable.
Definition: RDA5807.cpp:1463
void setMute(bool value)
Sets Audio mute or unmute.
Definition: RDA5807.cpp:1474
void setLnaIcSel(uint8_t value)
Sets LNA_ICSEL_BIT.
Definition: RDA5807.cpp:1615
int getRssi()
Gets the current Rssi.
Definition: RDA5807.cpp:1640
void setLnaPortSel(uint8_t value)
Sets LNA input port selection bit.
Definition: RDA5807.cpp:1627