/// /// \file SerialRadio.ino /// \brief Radio implementation using the Serial communication. /// /// \author Matthias Hertel, http://www.mathertel.de /// \copyright Copyright (c) 2014 by Matthias Hertel.\n /// This work is licensed under a BSD style license.\n /// See http://www.mathertel.de/License.aspx /// /// \details /// This is a full function radio implementation that uses a LCD display to show the current station information.\n /// It can be used with various chips after adjusting the radio object definition.\n /// Open the Serial console with 57600 baud to see current radio information and change various settings. /// /// Wiring /// ------ /// The necessary wiring of the various chips are described in the Testxxx example sketches. /// The boards have to be connected by using the following connections: /// /// Arduino port | SI4703 signal | RDA5807M signal /// :----------: | :-----------: | :-------------: /// GND (black) | GND | GND /// 3.3V (red) | VCC | VCC /// 5V (red) | - | - /// A5 (yellow) | SCLK | SCLK /// A4 (blue) | SDIO | SDIO /// D2 | RST | - /// /// /// More documentation and source code is available at http://www.mathertel.de/Arduino /// /// History: /// -------- /// * 05.08.2014 created. /// * 04.10.2014 working. #include #include #include //#include #include //#include //#include #include #include // Please, install the TinyOLED-Fonts library //#include "Rotary.h" #include // Define some stations available at your locations here: // 89.40 MHz as 8940 RADIO_FREQ preset[] = { 8770, 8810, // hr1 8820, 8850, // Bayern2 8890, // ??? 9760, // * hr3 8980, 9180, 9220, 9350, 9440, // * hr1 9510, // - Antenne Frankfurt 9530, 9560, // Bayern 1 9680, 9880, 10020, // planet 10090, // ffh 10110, // SWR3 10030, 10260, 10380, 10400, 10500 // * FFH }; int i_sidx = 5; ///< Start at Station with index=5 float freq; int v = 4; long x; long x1; long result; int frekans ; int frekansNew; /// The radio object has to be defined by using the class corresponding to the used chip. /// by uncommenting the right radio object definition. // RADIO radio; ///< Create an instance of a non functional radio. //RDA5807M radio; ///< Create an instance of a RDA5807 chip radio SI4703 radio; ///< Create an instance of a SI4703 chip radio. //SI4705 radio; ///< Create an instance of a SI4705 chip radio. // TEA5767 radio; ///< Create an instance of a TEA5767 chip radio. /// get a RDS parser RDSParser rds; /// State definition for this radio implementation. enum RADIO_STATE { STATE_PARSECOMMAND, ///< waiting for a new command character. STATE_PARSEINT, ///< waiting for digits for the parameter. STATE_EXEC ///< executing the command. }; RADIO_STATE state; ///< The state variable is used for parsing input characters. // - - - - - - - - - - - - - - - - - - - - - - - - - - /// Setup a FM only radio configuration with I/O for commands and debugging on the Serial port. void setup() { // You may use 4 Tactile buttons to ground or 4 way Joystick type one button (like me) pinMode(4,INPUT_PULLUP); //Seek up pinMode(5,INPUT_PULLUP); //Seek down pinMode(6,INPUT_PULLUP); //Volume + pinMode(7,INPUT_PULLUP); //Volume - frekans = EEPROM.read(207); // read value of last frequency and volume v = EEPROM.read(202); oled.begin(); oled.clear(); oled.on(); oled.setFont(FONT6X8); // Splash - Change orit for your introduction text or remove the splash code. oled.setCursor(40, 0); oled.print("SI4703"); oled.setCursor(20, 1); oled.print("Arduino Radio"); delay(100); oled.setCursor(15, 2); oled.print("Mustafa Peker"); delay(100); oled.setCursor(10, 3); oled.print("V1.0.4-By PEKER"); delay(1000); oled.clear(); // open the Serial port Serial.begin(57600); Serial.print("Radio..."); delay(500); // Initialize the Radio radio.init(); // Enable information to the Serial port radio.debugEnable(); radio.setBandFrequency(RADIO_BAND_FM, preset[i_sidx]); // 5. preset. // delay(100); radio.setMono(false); radio.setMute(false); // radio._wireDebug(); radio.setVolume(2); Serial.write('>'); state = STATE_PARSECOMMAND; // setup the information chain for RDS data. radio.attachReceiveRDS(RDS_process); rds.attachServicenNameCallback(DisplayServiceName); runSerialCommand('?', 0); oled.setCursor(85,3); //print volume oled.print("Vol "); v = 2; oled.print(v); oled.print(" "); } // Setup void loop() { readVcc(); //Serial.println(x); oled.setCursor(64,0); //print voltage oled.print("Batt % "); x1 = map(x, 280, 420, 0, 100); if (x1 < 0){ x1 = 0; } if (x1 > 100){ x1 = 100; } //oled.setCursor(0, 75); oled.print(x1); oled.print(" "); if (digitalRead(4) == LOW){ radio.seekUp(true); delay(100); } if (digitalRead(5) == LOW){ radio.seekDown(true); delay(100); } v = radio.getVolume(); if (digitalRead(6) == LOW){ radio.setVolume(++v); oled.setCursor(85,3); //print volume oled.print("Vol "); oled.print(v); oled.print(" "); delay(100); } if (digitalRead(7) == LOW){ if (v <= 1){ v = 1; } radio.setVolume(--v); oled.setCursor(85,3); //print volume oled.print("Vol "); oled.print(v); oled.print(" "); delay(100); } int newPos; unsigned long now = millis(); static unsigned long nextFreqTime = 0; static unsigned long nextRadioInfoTime = 0; // some internal static values for parsing the input static char command; static int16_t value; static RADIO_FREQ lastf = 0; RADIO_FREQ f = 0; char c; if (Serial.available() > 0) { // read the next char from input. c = Serial.peek(); if ((state == STATE_PARSECOMMAND) && (c < 0x20)) { // ignore unprintable chars Serial.read(); } else if (state == STATE_PARSECOMMAND) { // read a command. command = Serial.read(); state = STATE_PARSEINT; } else if (state == STATE_PARSEINT) { if ((c >= '0') && (c <= '9')) { // build up the value. c = Serial.read(); value = (value * 10) + (c - '0'); } else { // not a value -> execute runSerialCommand(command, value); command = ' '; state = STATE_PARSECOMMAND; value = 0; } // if } // if } // if // check for RDS data radio.checkRDS(); // update the display from time to time if (now > nextFreqTime) { f = radio.getFrequency(); if (f != lastf) { // print current tuned frequency DisplayFrequency(f); lastf = f; } // if nextFreqTime = now + 400; } // if } // loop /// Update the Frequency on the LCD display. void DisplayFrequency(RADIO_FREQ f) { char s[12]; radio.formatFrequency(s, sizeof(s)); Serial.print("FREQ:"); Serial.println(s); oled.setCursor(5, 0); oled.print("F M"); oled.setCursor(30, 1); oled.setFont(FONT8X16); oled.print((float)f/100, 1); oled.print(" "); oled.setFont(FONT6X8); oled.setCursor(70, 2); oled.print(" MHz "); oled.setCursor(10, 3); oled.print(" "); } // DisplayFrequency() /// Update the ServiceName text on the LCD display. void DisplayServiceName(char *name) { Serial.print("RDS:"); Serial.println(name); oled.setCursor(10, 3); oled.print(name); oled.print(" "); } // DisplayServiceName() // - - - - - - - - - - - - - - - - - - - - - - - - - - void RDS_process(uint16_t block1, uint16_t block2, uint16_t block3, uint16_t block4) { rds.processData(block1, block2, block3, block4); } /// Execute a command identified by a character and an optional number. /// See the "?" command for available commands. /// \param cmd The command character. /// \param value An optional parameter for the command. void runSerialCommand(char cmd, int16_t value) { if (cmd == '?') { Serial.println(); Serial.println("? Help"); Serial.println("+ increase volume"); Serial.println("- decrease volume"); Serial.println("> next preset"); Serial.println("< previous preset"); Serial.println(". scan up : scan up to next sender"); Serial.println(", scan down ; scan down to next sender"); Serial.println("fnnnnn: direct frequency input"); Serial.println("i station status"); Serial.println("s mono/stereo mode"); Serial.println("b bass boost"); Serial.println("u mute/unmute"); } // ----- control the volume and audio output ----- else if (cmd == '+') { // increase volume int v = radio.getVolume(); if (v < 15) radio.setVolume(++v); } else if (cmd == '-') { // decrease volume int v = radio.getVolume(); if (v > 0) radio.setVolume(--v); } else if (cmd == 'u') { // toggle mute mode radio.setMute(!radio.getMute()); } // toggle stereo mode else if (cmd == 's') { radio.setMono(!radio.getMono()); } // toggle bass boost else if (cmd == 'b') { radio.setBassBoost(!radio.getBassBoost()); } // ----- control the frequency ----- else if (cmd == '>') { // next preset if (i_sidx < (sizeof(preset) / sizeof(RADIO_FREQ)) - 1) { i_sidx++; radio.setFrequency(preset[i_sidx]); } // if } else if (cmd == '<') { // previous preset if (i_sidx > 0) { i_sidx--; radio.setFrequency(preset[i_sidx]); } // if } else if (cmd == 'f') { radio.setFrequency(value); } else if (cmd == '.') { radio.seekUp(false); } else if (cmd == ':') { radio.seekUp(true); } else if (cmd == ',') { radio.seekDown(false); } else if (cmd == ';') { radio.seekDown(true); } // not in help: else if (cmd == '!') { if (value == 0) radio.term(); if (value == 1) radio.init(); } else if (cmd == 'i') { char s[12]; radio.formatFrequency(s, sizeof(s)); Serial.print("Station:"); Serial.println(s); Serial.print("Radio:"); radio.debugRadioInfo(); Serial.print("Audio:"); radio.debugAudioInfo(); } // info else if (cmd == 'x') { radio.debugStatus(); // print chip specific data. } } // runSerialCommand() /// Constantly check for serial input commands and trigger command execution. void readVcc() { // Read 1.1V reference against AVcc ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate AVcc in mV x = result; x = x /10; x = x * 0.97; // Calibration value return result; } // End.