FM Transmitter - Car MP3 Player | |
FM Transmitter - Car MP3 Player - Software
January 2016
The Arduino SoftwareDownload Software (Right-click link and "Save link as...")The FMTX library can be downloaded from here: http://www.elechouse.com/elechouse/.../FMTX.rar
................................................................................................................ NOTE: The FMTX library needs to be edited slightly in order to compile in later versions of the Ardiuno IDE: In FMTX.h at line 32 comment out typedef uint16_t u16 //typedef uint16_t u16; In FMTX.cpp at line 140: replace u16 with uint16_t at line 147: replace u16 with uint16_t Also, as noted in the comments in the sketch: in FMTX.h at line 71 uncomment : void fmtx_set_rfgain(u8 rfgain); ................................................................................................................ // FM Transmitter - Car MP3 Player. (c) 2016 vwlowen.co.uk #include <EEPROM.h> #include <SoftwareSerial.h> #include <SPI.h> // https://www.pjrc.com/teensy/td_libs_IRremote.html #include <IRremote.h> // http://www.elechouse.com/elechouse/images/product/FM%20Transmitter%20Module/FMTX.rar // http://www.elechouse.com/elechouse/index.php?main_page=product_info&cPath=168_170&products_id=2206 #include <FMTX.h> // https://github.com/adafruit/Adafruit-GFX-Library // https://github.com/adafruit/Adafruit-ST7735-Library #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific TFT Display library #define TFT_CS 10 // Define TFT SPI pins (11, 12 & 13 are implicit with SPI) #define TFT_RST A0 #define TFT_DC A1 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); #define txPin 2 // Software Serial Tx to MP3 Module Rx pin. #define rxPin 3 // Software Serial Rx from MP3 Module Tx pin. SoftwareSerial mp3(rxPin, txPin); // Create software serial for MP3 module. int RECV_PIN = A2; // IR sensor connected to A2 (as a digital input) IRrecv irrecv(RECV_PIN); // Create IR receiver. decode_results results; // Returned results codes from IR sensor. // Define the MP3 Module's Commands that we might use... #define cmdNextTrack 0x01 // Next track. (Not used) #define cmdPrevTrack 0x02 // Previous track. (Not used) #define cmdSetTrack 0x03 // Play track. Param = track number. #define cmdRepeatPlay 0x11 // Play/stop. Param: 1 = Play, 0 = Stop. #define cmdPlay 0x0d // Resume current track. #define cmdSetVolume 0x06 // Set Volume to a specified value. Param = volume 0-31. #define cmdSetEq 0x07 // Set Equalizer to a specified value. #define cmdReset 0x0c // Reset MP3 Module. #define cmdPause 0x0e // Pause current track. // Define some FM Transmitter parameters #define FREQ_MAX 108.0 // Set FM frequency limits and step size. #define FREQ_MIN 87.5 // MHz #define FREQ_STEP 0.05 // MHz #define RF_GAIN_MIN 4 #define RF_GAIN_MAX 15 // Define the codes returned from the IR remote control. The codes for your remote can be captured on the Serial monitor and entered here, #define IR_PAUSE 0xFD00FF // IR remote Pause #define IR_NEXT 0xFD50AF // IR remote 'Next' #define IR_PREV 0xFD906F // IR remote 'Previous' #define IR_VOL_UP 0xFD609F #define IR_VOL_DWN 0xFDA05F #define IR_EQU 0xFD20DF #define IR_CH_UP 0xFD40BF // Channel+ duplicate 'Next' command #define IR_CH_DWN 0xFD807F // Channel - duplicat 'Previous' command #define IR_0 0xFD10EF // Codes from number keys #define IR_1 0xFD30CF #define IR_2 0xFDB04F #define IR_3 0xFD708F #define IR_4 0xFD08F7 #define IR_5 0xFD8877 #define IR_6 0xFD48B7 #define IR_7 0xFD28D7 #define IR_8 0xFDA857 #define IR_9 0xFD6897 int PWM_LED = 9; // PWM output to TFT Backlight int pinBusy = 4; // Input from MP3 player. LOW = track playing (Busy). int pinButtonMode = 5; // Mode selection button int pinPrev = 6; // Back/Down button int pinPausePlay = 7; // Pause/Resume button int pinNext = 8; // Next/Up button char* equName[6] = {"NORMAL", "POP", "ROCK", "JAZZ", "CLASSICAL", "BASS"}; // Names for equalizer settings. byte equ = 0; // Equalizer setting 0-5 (Normal/Pop/Rock/Jazz/Classical/Bass) byte volume = 25; // Initial MP3 module volume (0 - 31). byte led = 255; // LED backlight brightness. 255 = full on. byte mode = 0; // 0-7. (or 0-6) Sets what Next/Previous buttons do. Track/FM Freq/Volume/Equalizer/Auto Start/RF Gain* // Uncomment line 71 [void fmtx_set_rfgain(u8 rfgain);] in FMTX.h to enable gain-setting function (Mode 7) byte modeMax = 7; // * or modeMax = 6 if fmtx_set_rfgain is not available, modes 0-6 only. unsigned int track; // Currently-playing track. unsigned long trackTimer; // Time interval between tracks when auto-incrementing unsigned long nextTimer; // Time interval between tracks when using Next button unsigned long modeTimer; // Time interval when not on normal playing mode (mode 0) unsigned long irTimer; unsigned long holdTimer; // Time how long the Next/Previous buttons are held down when adjusting frequency... int delayTimer; // ... and change loop delay timer. unsigned long trackTimerInterval = 2000; // Next track must start within 2 seconds on auto increment. unsigned long nextTimerInterval = 100; // Next track must start within this msec using Next button. unsigned long modeTimerInterval = 7000; // Return to mode 0 (normal playing), 7 seconds after no Next or Prev button press. unsigned long irTimerInterval = 2000; // Stop waiting for three-digit number from IR remote after this time. boolean volChanged = false; // Flags used to indicate Volume, FM Frequency, Equalization, AutoStart or RF Gain... boolean freqChanged = false; // ... has probably been changed using Next/Previous buttons. boolean equChanged = false; // Avoids unnecessary writing to EEPROM. boolean autoChanged = false; boolean rfGainChanged = false; boolean saveTrackChanged = false; boolean autoStart = false; boolean paused = false; boolean manualStarted = false; boolean saveTrack = false; boolean isNumber = false; boolean irMessage = false; int digit = -1; int numberOfDigits = 0; unsigned int number = 0; float freq = FREQ_MIN; // Initial FM Freq if EEPROM read fails. byte rfGain = 4; // Uncomment line 71 in FMTX.h - otherwise gain defaults to 4. // Initialize the send buffer for MP3 module command string. byte cmdBuff[10] = {0x7e, // Start Byte, always 0x7e. 0xff, // Version, always 0xff. 0x06, // Data length, always 0x06 for us. 0x00, // Command value. 0x00, // Feedback, always 0x00 ('No feedback') for us. 0x00, // Command parameter Hi Byte. 0x00, // Command paramemer Lo Byte. 0x00, // Checksum Hi Byte. 0x00, // Checksum Lo Byte. 0xef // End Byte, always 0xef. }; // Refresh entire display void updateDisplay(boolean clr) { if (clr) tft.fillScreen(ST7735_BLACK); // Clear screen first if 'clr' is true tft.setCursor(2, 25); tft.setTextColor(ST7735_GREEN); tft.setTextSize(2); tft.print("Track: "); tft.print(track); tft.setTextSize(1); tft.setTextColor(ST7735_YELLOW); tft.setCursor(2, 58); tft.print("Backlight: "); tft.print(led); tft.setCursor(2, 68); tft.print("Volume (0-31): "); tft.print(volume); tft.setCursor(2, 78); saveTrack ? tft.print("Save last track: ON"):tft.print("Save last track: OFF"); tft.setCursor(2, 88); tft.print("FM Freq (MHz): "); tft.print(freq, 2); tft.print("0"); tft.setCursor(2, 98); tft.print("Equalization: "); tft.print(equName[equ]); tft.setCursor(2, 108); autoStart ? tft.print("Auto Start: ON"):tft.print("Auto Start: OFF"); if (modeMax == 7) { tft.setCursor(2, 118); tft.print("RF Gain (0-15): "); tft.print(rfGain); } } // Update only a single value. The display does not overwrite previous values so it's necessary // to clear a small rectangle to wipe the original value before printing the new value. Clearing and // updating the entire screen is unnecessarily slow when changing an individual value. void updateValue(float value, byte dec) { byte y = (mode * 10) + 48; // Calculate vertical position of line on screen tft.fillRect(80, y, 178, 10, ST7735_BLACK); tft.setCursor(105, y); tft.setTextColor(ST7735_WHITE); tft.setTextSize(1); switch(mode) { case 0: tft.fillRect(2, 25, 178, 20, ST7735_BLACK); // New track paused ? tft.setTextColor(ST7735_RED) : tft.setTextColor(ST7735_GREEN); tft.setTextSize(2); tft.setCursor(2, 25); tft.print("Track: "); tft.print(track); break; case 3: saveTrack ? tft.print("Save last track: ON"):tft.print("Save last track: OFF"); break; case 5: tft.print(equName[equ]); // New equalization setting break; case 6: autoStart ? tft.print("ON"):tft.print("OFF"); // Auto Start setting changed break; default: tft.print(value, dec); // All other values not track, equ or Auto Start. break; } if (mode == 4) tft.print("0"); // If it's a new frequency, add a "0" to display (Hz). } // Highlight a single line in white to indicate which value the Next & Prev buttons will change. void updateLine() { updateDisplay(false); byte y = (mode * 10) + 48; // Calculate vertical position of line on screen tft.fillRect(2, y, 178, 10, ST7735_BLACK); tft.setCursor(2, y); tft.setTextColor(ST7735_WHITE); switch (mode) { case 0: break; case 1: tft.print("Backlight: "); tft.print(led); break; case 2: tft.print("Volume (0-31): "); tft.print(volume); break; case 3: saveTrack ? tft.print("Save last track: ON"):tft.print("Save last track: OFF"); break; case 4: tft.print("FM Freq (MHz): "); tft.print(freq, 2); tft.print("0"); break; case 5: tft.print("Equalization: "); tft.print(equName[equ]); break; case 6: autoStart ? tft.print("Auto Start: ON"):tft.print("Auto Start: OFF"); break; case 7: tft.print("RF Gain (0-15): "); tft.print(rfGain); break; } tft.setTextColor(ST7735_YELLOW); } // Routine to build 10-byte command buffer and write to software serial Tx (MP3 module Rx). void sendCommand(byte Cmd, unsigned int Param) { unsigned int sum = 0; cmdBuff[3] = Cmd; // Command. cmdBuff[5] = (byte) (Param >> 8); // Param Hi byte. cmdBuff[6] = (byte) (Param); // Param Lo byte. for (int i=1; i<7; i++) { // Calculate 16-bit checksum from buffer bytes 1 to 6. sum -= cmdBuff[i]; } cmdBuff[7] = (byte) (sum >> 8); // Add checksum Hi byte to buffer. cmdBuff[8] = (byte) sum; // Add checksum Lo byte to buffer. for (int i = 0; i<10; i++) { // Write entire buffer to software serial (mp3). mp3.write(cmdBuff[i]); } } // Long 'self-contained' function to handle the IR remote control. Omit if not required. void irRemoteHandler() { digit = -1; if (irrecv.decode(&results)) { Serial.println(results.value, HEX); // Show results on Serial monitor to get codes initially. irrecv.resume(); // Get ready for the next value. // Perform appropriate action depending on code received. switch (results.value) { case IR_PAUSE: track == 0 ? track = 1 : paused = !paused; // Pause playback. paused ? sendCommand(cmdPause, 0) : sendCommand(cmdPlay, 0); updateValue(track, 0); break; case IR_CH_UP: case IR_NEXT: manualStarted = true; // Next track paused = false; track++; sendCommand(cmdRepeatPlay, 0); // Stop the current rack delay(100); sendCommand(cmdSetTrack, track); updateValue(track, 0); nextTimer = millis(); while (digitalRead(pinBusy) == HIGH) { if (millis() > (nextTimer + nextTimerInterval)) { // If still "not busy" after interval, we must have reached track = 1; // the last track number that played successfully. sendCommand(cmdSetTrack, track); updateDisplay(true); break; } } break; case IR_CH_DWN: case IR_PREV: if (track == 0) track = 2; // Previous track if (track > 1) track--; paused = false; sendCommand(cmdSetTrack, track); updateValue(track, 0); break; case IR_VOL_UP: if (volume < 31) { // Increase volume from MP3 player to FM TX input. volume++; mode = 2; updateValue(volume, 0); modeTimer = millis(); sendCommand(cmdSetVolume, volume); } volChanged = true; break; case IR_VOL_DWN: if (volume > 0) { // Reduce volume from MP3 player to FM TX input. volume--; mode = 2; updateValue(volume, 0); modeTimer = millis(); sendCommand(cmdSetVolume, volume); } volChanged = true; break; case IR_EQU: equ < 5 ? equ++ : equ = 0; // Change equaization setting. sendCommand(cmdSetEq, equ); mode = 5; updateValue(equ, 0); equChanged = true; modeTimer = millis(); break; isNumber = false; digit = -1; case IR_0: digit = 0; break; // Set 'digit' to received numerical key code case IR_1: digit = 1; break; case IR_2: digit = 2; break; case IR_3: digit = 3; break; case IR_4: digit = 4; break; case IR_5: digit = 5; break; case IR_6: digit = 6; break; case IR_7: digit = 7; break; case IR_8: digit = 8; break; case IR_9: digit = 9; break; } } isNumber = ((digit > -1) && (digit < 10)); // Flag if the received code was from a number key. if (isNumber) { // Track numbers can only be changed in mode 0. if (mode != 0) { mode = 0; updateDisplay(true); } if (paused) { // Re-start playing if paused. paused = !paused; updateValue(track, 0); sendCommand(cmdRepeatPlay, 0); // Stop current track irMessage = true; // } // Build three-digit number from the three received number keys. if (numberOfDigits == 0) {number = digit; numberOfDigits = 1;} else if (numberOfDigits == 1) {number = (number * 10) + digit; numberOfDigits = 2;} else if (numberOfDigits == 2) {number = (number * 10) + digit; numberOfDigits = 3;} else if (numberOfDigits == 3) { track = number; // Stop currently-plaing track to create "not-busy" signal. This initiates 'Play track number' in main loop. sendCommand(cmdRepeatPlay, 0); // '0' parameter means 'Stop' tft.fillRect(90, 5, 50, 17, ST7735_BLACK); // Clear the BLUE prompt digits. delay(50); digit = -1; irMessage = true; numberOfDigits = 0; number = 0; } digit = -1; tft.fillRect(90, 5, 50, 17, ST7735_BLACK); tft.setTextColor(ST7735_BLUE); // Print each digit as it is entered from the remote tft.setTextSize(2); tft.setCursor(90, 5); if (number < 100) tft.print("0"); if (number < 10) tft.print("0"); tft.print(number); irTimer = millis(); // Set timer. This will over-ride having to enter 3 digits when it times out. } if ((number > 0) &&(millis() > (irTimer + irTimerInterval))) { // Can't wait for 3 digits so assume the missing... tft.fillRect(90, 5, 50, 17, ST7735_BLACK); // ... digits (100's and possibly 10's) are '0' track = number; irMessage = true; // Tell main loop not to increment previous track number sendCommand(cmdRepeatPlay, 0); // '0' parameter means 'Stop' playing current track. delay(50); digit = -1; numberOfDigits = 0; number = 0; } } void setup() { pinMode(PWM_LED, OUTPUT); pinMode(TFT_RST, OUTPUT); pinMode(TFT_DC, OUTPUT); pinMode(pinButtonMode, INPUT_PULLUP); // Set button pins as inputs and // enable internal pullups. pinMode(pinPrev, INPUT_PULLUP); pinMode(pinNext, INPUT_PULLUP); pinMode(pinPausePlay, INPUT_PULLUP); pinMode(pinBusy, INPUT_PULLUP); // Busy input from MP3 player. LOW = track playing. Serial.begin(9600); // Serial monitor used to capture IR remote's codes.... Serial.println("Start"); // .... Not required once the codes have been captured. randomSeed(analogRead(3)); irrecv.enableIRIn(); // Start IR the receiver analogWrite(PWM_LED, 255); // Backlight full on. tft.initR(INITR_BLACKTAB); // Initialize a ST7735S chip, black tab tft.setRotation(3); // Display horizontal fmtx_init(freq, EUROPE); // Initialize the FM transmitter. delay(500); mp3.begin(9600); // Initialise software serial mp3. // Initial values stored in EEPROM could be unpredictable so the values are constrained within sensible limits. // Once a value has been changed by the Next/Prev buttons, it's automatically saved to EEPROM. freq = constrain(eepromReadFloat(0), 87.5, 108.0); // Retrieve FM transmitter frequency if (isnan(freq)) freq=87.5; // not a valid floating point number volume = constrain(EEPROM.read(4), 0, 31); // Retrieve MP3 player volume setting equ = constrain(EEPROM.read(5), 0, 5); // Retrieve MP3 player equalization setting autoStart = constrain(EEPROM.read(6), 0, 1); // Retrieve Auto Start (Yes/no) saveTrack = constrain(EEPROM.read(8), 0, 1); if (saveTrack) { track = eepromReadInt(9) - 1; // Replay last track } else track = 0; fmtx_set_freq(freq); // Set the FM transmitter frequency delay(100); // Changing the RF Gain (ie output power) of the FM TX module requires that a funtion declaration in FMTX.h is un-commented. // The default RG Gain is set in the 'fmtx_init()' function to a value of 4. Any value between 0 and 15 is possible but the // manufacturers of the module may have had good reason to restrict it to 4 (besides possible interference to others) so it's your choice! if (modeMax == 7) { rfGain = EEPROM.read(7); // If the function is available, set the FM transmitter RF gain if ((rfGain < RF_GAIN_MIN) || (rfGain > RF_GAIN_MAX)){ rfGain = RF_GAIN_MIN; // Set default RF gain to minimum if invalid value is stored in EEPROM. } fmtx_set_rfgain(rfGain); // (4 - 15) ****** Uncomment line 71 in FMTX.h ******* delay(100); } sendCommand(cmdReset, 0); // Reset MP3 module (command, parameter). delay(1000); sendCommand(cmdSetVolume, volume); // Set the MP3 player volume. Adjusts how much audio the FMTX module is given.... delay(100); // ... set to highest value without distortion. sendCommand(cmdSetEq, equ); // Set the MP3 player equalization setting. (Normal/Pop/Rock/Jazz/Classical/Bass) delay(100); updateDisplay(true); // Clear display and print all labels and values. } void loop() { irRemoteHandler(); // Check if any valid code has been received by the IR sensor. // Check for MP3 "not busy" signal and increment track number but not if Paused. if ((digitalRead(pinBusy) == HIGH) && (!paused) && (autoStart || manualStarted)) { if (!irMessage) { track++; } irMessage = false; updateValue(track, 0); // Display new track number sendCommand(cmdSetTrack, track); // Play new track delay(100); trackTimer = millis(); while(digitalRead(pinBusy) == HIGH) { if (millis() > (trackTimer + trackTimerInterval)) { // Track number still not playing so must be greater than last track track = 1; // Reset track number to 1 and start again. sendCommand(cmdSetTrack, track); updateDisplay(true); // Completely refresh display. break; } } } if (digitalRead(pinButtonMode) == LOW) { // Mode button. Set mode to select what Next/Prev mode < modeMax ? mode++ : mode = 0; // buttons adjust. Track/FM Freq/Volume/Equalizer/Auto Start/RF Gain updateLine(); while (digitalRead(pinButtonMode) == LOW); delay(50); modeTimer = millis(); // Set mode timer to allow auto return to mode 0. (Normal mode) } if ((millis() > (modeTimer + modeTimerInterval)) & (mode != 0)){ // Auto reset mode button to mode 0 (track Next/Prev) mode = 0; // to avoid having to cycle through mode options manually. modeTimer = millis(); updateDisplay(true); } if (mode == 7) { // RF gain. Mode 7 is only available if FTMX.h line 71 if (digitalRead(pinNext) == LOW) { // has been uncommented. if (rfGain < RF_GAIN_MAX ) rfGain++ ; fmtx_set_rfgain(rfGain); updateValue(rfGain, 0); rfGainChanged = true; delay(200); modeTimer = millis(); } if (digitalRead(pinPrev) == LOW) { if (rfGain > RF_GAIN_MIN) rfGain-- ; fmtx_set_rfgain(rfGain); updateValue(rfGain, 0); rfGainChanged = true; delay(200); modeTimer = millis(); } } if (mode == 6) { // Auto Start on/off. Choose whther player starts playing as soon as if ((digitalRead(pinNext) == LOW) || (digitalRead(pinPrev) == LOW)) { // power is applied or if Next button needs to be pressed to start autoStart = !autoStart; // playing. while ((digitalRead(pinNext) == LOW) || (digitalRead(pinPrev) == LOW)); autoChanged = true; updateDisplay(true); mode = 0; delay(50); modeTimer = millis(); } } if (mode == 5) { // Adjust equalization. 0-5 = Normal/Pop/Rock/Jazz/Classical/Bass if (digitalRead(pinNext) == LOW) { equ < 5 ? equ++ : equ = 0; sendCommand(cmdSetEq, equ); updateValue(equ, 0); equChanged = true; delay(150); modeTimer = millis(); } if (digitalRead(pinPrev) == LOW) { equ > 0 ? equ-- : equ = 5; sendCommand(cmdSetEq, equ); updateValue(equ, 0); equChanged = true; delay(150); modeTimer = millis(); } } if (mode == 4) { // Adjust frequecncy of FM transmitter module holdTimer = millis(); while (digitalRead(pinNext) == LOW) { if (freq + FREQ_STEP <= FREQ_MAX + 0.01) { if (millis() > (holdTimer + 3000)) { // If temporary timer exceeds 3 seconds, button has been held delayTimer = 500; // down for 3 seconds or more so temporarily increase freq = freq + 1.0; // frequency increment to 1 MHz } else { delayTimer = 250; freq = freq + FREQ_STEP; } fmtx_set_freq(freq); updateValue(freq, 2); delay(delayTimer); } freqChanged = true; modeTimer = millis(); } while (digitalRead(pinPrev) == LOW) { if (freq - FREQ_STEP >= FREQ_MIN - 0.01) { if (millis() > (holdTimer + 3000)) { delayTimer = 500; freq = freq - 1.0; } else { delayTimer = 250; freq = freq - FREQ_STEP; } fmtx_set_freq(freq); updateValue(freq, 2); delay(delayTimer); } freqChanged = true; modeTimer = millis(); } } if (mode == 3) { // Save last track - ON/OFF if ((digitalRead(pinNext) == LOW) || (digitalRead(pinPrev) == LOW)) { // Select whether to resume from last-played track or saveTrack = !saveTrack; // restart from track 1 when power is next restored. while ((digitalRead(pinNext) == LOW) || (digitalRead(pinPrev) == LOW)); saveTrackChanged = true; updateDisplay(true); mode = 0; delay(50); modeTimer = millis(); } } if (mode == 2) { // Adjust Volume from MP3 player. if (digitalRead(pinNext) == LOW) { if (volume < 31) { volume++; updateValue(volume, 0); sendCommand(cmdSetVolume, volume); } delay(150); volChanged = true; modeTimer = millis(); } if (digitalRead(pinPrev) == LOW) { if (volume > 0) { volume--; updateValue(volume, 0); sendCommand(cmdSetVolume, volume); } delay(150); volChanged = true; modeTimer = millis(); } } if (mode == 1) { //. LED Backlight if (digitalRead(pinNext) == LOW) { if (led < 255) { led++; analogWrite(PWM_LED, led); updateValue(led, 0); } delay(10); modeTimer = millis(); } if (digitalRead(pinPrev) == LOW) { if (led > 0) { led--; analogWrite(PWM_LED, led); updateValue(led, 0); } delay(10); modeTimer = millis(); } } if (mode == 0) { if (digitalRead(pinNext) == LOW) { // Next Track button manualStarted = true; paused = false; track++; sendCommand(cmdRepeatPlay, 0); // Stop playing current track to create "not busy" signal from MP3 player. delay(100); while(digitalRead(pinNext) == LOW); sendCommand(cmdSetTrack, track); updateValue(track, 0); delay(150); nextTimer = millis(); // Set next-track timer. while (digitalRead(pinBusy) == HIGH) { if (millis() > (nextTimer + nextTimerInterval)) { // If still "not busy" after interval, we must have reached last track track = 1; sendCommand(cmdSetTrack, track); updateDisplay(true); break; } } modeTimer = millis(); } if (digitalRead(pinPrev) == LOW) { // Previous Track button if (track == 0) track = 2; if (track > 1) track--; sendCommand(cmdSetTrack, track); paused = false; updateValue(track, 0); while(digitalRead(pinPrev) == LOW); delay(150); modeTimer = millis(); } if (digitalRead(pinPausePlay) == LOW) { // Pause / Resume button track == 0 ? track = 1 : paused = !paused; paused ? sendCommand(cmdPause, 0) : sendCommand(cmdPlay, 0); updateValue(track, 0); while(digitalRead(pinPausePlay) == LOW); delay(150); modeTimer = millis(); } } if (freqChanged) { freqChanged = false; if (eepromReadFloat(0) != freq) eepromWriteFloat(0, freq); } if (volChanged) { // Save changes to Volume, Frequency, Equalization, AutoStart and RF gain volChanged = false; // in EEPROM to be recalled at power-on next time. if (EEPROM.read(4) != volume) EEPROM.write(4, volume); } if (equChanged) { equChanged = false; if (EEPROM.read(5) != equ) EEPROM.write(5, equ); } if (autoChanged) { autoChanged = false; if (EEPROM.read(6) != autoStart) EEPROM.write(6, autoStart); } if (rfGainChanged) { rfGainChanged = false; if (EEPROM.read(7) != rfGain) EEPROM.write(7, rfGain); } if (saveTrackChanged) { saveTrackChanged = false; if (EEPROM.read(8) != saveTrack) EEPROM.write(8, saveTrack); } if (saveTrack) { if (eepromReadInt(9) != track+1) eepromWriteInt(9, track+1); //9, 10 } } // http://www.elcojacobs.com/storing-settings-between-restarts-in-eeprom-on-arduino/ int eepromReadInt(int address){ int value = 0x0000; value = value | (EEPROM.read(address) << 8); value = value | EEPROM.read(address+1); return value; } void eepromWriteInt(int address, int value){ EEPROM.write(address, (value >> 8) & 0xFF ); EEPROM.write(address+1, value & 0xFF); } float eepromReadFloat(int address){ // Read/Write floating point numbers to EEPROM union u_tag { byte b[4]; float fval; } u; u.b[0] = EEPROM.read(address); u.b[1] = EEPROM.read(address+1); u.b[2] = EEPROM.read(address+2); u.b[3] = EEPROM.read(address+3); return u.fval; } void eepromWriteFloat(int address, float value){ union u_tag { byte b[4]; float fval; } u; u.fval=value; EEPROM.write(address , u.b[0]); EEPROM.write(address+1, u.b[1]); EEPROM.write(address+2, u.b[2]); EEPROM.write(address+3, u.b[3]); }
|