// **************************************************** // Melodien aus EEPROM vom 27. 09. 2025 // **************************************************** const /*PROGMEM*/ char title[] = { // List of text for melody-titles new 30.06.2025 - change number_mel too! "Asa Branca " // 1 Asa Branca 0 text-length 14 all titles full length "Take on me " // 2 Take on me "Starwars " // 3 Starwars "Cantina-Band " // 4 Cantina-Band "Game of Throne" // 5 Game of Thrones "Fuer Elise " // 6 Für Elise "Greensleeves " // 7 Greensleeves "Silent Night " // 8 Silent Night "Happy Birthday" // 9 Happy Birthday "Nokia Ringtone" // 10 Nokia Ringtone "Pacman " // 11 Pacman "Super-Mario " // 12 Super-Mario "Tetris " // 13 Tetris "Imperial March" // 14 Imperial March "Zelda " // 15 Zelda "Ode of Joy " // 16 Ode of Joy "Pink Panther " // 17 Pink Panther "Lullaby " // 18 Lullaby (Brahms Wiegenlied) "Keyboard Cat " // 19 Keyboard cat "MII Channel " // 20 MII Channel "Greenhill " // 21 Greenhill "Song of Storms" // 22 Song of storms "Minuet in G " // 23 Minuet in G "Pulo da gaita " // 24 Pulo da gaita "Badinerie " // 25 Badinerie "Baby elephant " // 26 Empty "Cannon in D " // 27 Cannon in D "No data " // 28 Empty "No data " // 29 Empty "No data " // 30 Empty "No data " // 31 Empty "No data " // 32 Empty "No data " // 33 Empty "No data " // 34 Empty "No data " // 35 Empty "No data " // 36 Empty "No data " // 37 Empty "No data " // 38 Empty "No data " // 39 Empty "No data " // 40 Empty "No data " // 41 Empty "No data " // 42 Empty "No data " // 43 Empty "No data " // 44 Empty "No data " // 45 Empty "No data " // 46 Empty "No data " // 47 Empty "No data " // 48 Empty }; const /*PROGMEM*/ int tempis[] = { // Tempi for songs 120,140,108,140,85,80,70,140,140,140, // Values Song 1 - 10 Asa Branca, Take on me, Starwars,Cantina Band, Game of thrones, Fuer Elise, Greensleeves Silent night, Happy birthday, Nokia Ringtone 105,200,144,120,114,88,120,76,160,114, // 11 - 20 Pacman, Super Mario, Tetris,Imperial, Zelda, Ode of Joy, Pink Panther, Lullaby, Keyboard cat, MII Channel 140,108,140,100,120,132,100,99,99,99, // 21 - 30 Greenhill, Song of storms, minuet in G,Pulo da gaita, Badinerie, Baby epelpaht walk, Cannon in D 99,99,99,99,99,99,99,99,99,99, // 31 - 40 99,99,99,99,99,99,99,99,99,99 // 41 - 50 }; #define EXT_EE_MELODY_R 0 // Melody original data start address in external eeprom 0 -> 9.000 -> 30 songs (current length 215 - later 300) #define EXT_EE_ADDR 0x50 // I2C address of 1. external eeprom #define EXT_EE_SIZE 32768 // Max address for 32k-eeprom #define BUZZER 8 // Buzzer-Pin #define REST 0 // Pause between notes #include // I2C #include // I2C-Display LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display #include "pitches.h" // Pitches for notes #include "melody.h" // Notes for melody byte snd = 0; // Music title number int tempo = 150; // Tempo old 180 int ofset = 0; // Offset between melodies int note = 0; // Current note byte length = 50; // Length of melodies char myChar = '-'; // Character for song title void setup() { // put your setup code here, to run once: lcd.init(); // Initialize the lcd lcd.backlight(); // Backlight on Serial.begin(19200); // opens serial port, sets data rate to 9600 / 19200 / 38400 / 57600 / 115200 bps lcd.clear(); // Clear = column 0 row 0 lcd.print(F("Melody Uno R4 Test ")); // Print Menu No i2c_scan(); // Scan available devices ext_ee_melody_copy(); // Copy melody from flash to ext. eeprom //int tempo = 120; // change this to make the song slower or faster //int buzzer = 11; // change this to whichever pin you want to use //int notes = sizeof(melody) / sizeof(melody[0]) / 2; // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits) int divider = 0, noteDuration = 0; // int notes = 50; // All songs are shortened to 60 notes for (snd = 1; snd < 10;snd++){ // Play melody 8 + 9 //tempo = tempis[snd-1]; // Melody tempo for this melody from flash ofset = (snd-1) * ((length*4) +15); // Offset = 0*50*2= 0, 1*50*2 = 100 integers! *2 -> *4 int ext_ee_adr = EXT_EE_MELODY_R+1 + ofset; // Address base + offset - ignore first byte which is the data-type - moved to here 26-09-2025 tempo=read_ext_eeprom(ext_ee_adr + 14); // Melody tempo starts at address +14 Serial.print("Title: "); ;Serial.print(snd); // Print title no + text Serial.print(" "); // Blank for (byte i=0;i<14;i++){ // Tiltle length 14 Chars myChar=read_ext_eeprom(EXT_EE_MELODY_R+1+ofset+i);// Get title text from external eeprom Serial.print(myChar);} // Print char to lcd Serial.print(" tempo: ");Serial.print(tempo); // Print tempo Serial.print(" "); // Blank Serial.print(" Addr: ");Serial.print(ext_ee_adr); // Print tempo Serial.print(" Notes: "); int wholenote = (60000 * 4) / tempo; // Calculate the duration of a whole note in ms for (int thisNote=0;thisNote +2 if (divider > 0) { // regular note, just proceed noteDuration = (wholenote) / divider; } // Calculate regular note duration else if (divider < 0) { // dotted notes are represented with negative durations!! noteDuration = (wholenote) / abs(divider); // Calculate dotted note duration noteDuration *= 1.5; } // increases the duration in half for dotted notes note = read_integer(ext_ee_adr+15+thisNote); // note globaly defined! Serial.print(note); // Print the note Serial.print(" "); // Blank //tone(BUZZER, melody[thisNote], noteDuration * 0.9); // we only play the note for 90% of the duration, leaving 10% as a pause //tone(BUZZER, melody[ofset+thisNote], noteDuration * 0.9); // we only play the note for 90% of the duration, leaving 10% as a pause tone(BUZZER, note, noteDuration * 0.9); // Play note for tone() - play only 90% of the duration, leaving 10% as a pause 23-09-2025 delay(noteDuration); // Wait for the specified duration before playing the next note. noTone(BUZZER); // stop the waveform generation before the next note. } Serial.println(); } } void loop() { // put your main code here, to run repeatedly: } void ext_ee_melody_copy(){ // Copy melody from flash to external eeprom - Menu 18 key old 2 new 6 Serial.println(); Serial.println(F("Copy flash to eeprom ")); // Message copy int ext_ee_adr = EXT_EE_MELODY_R; // External eeprom address for melody changed to received update_ext_eeprom(ext_ee_adr,'M'); // Add data type M = melody ext_ee_adr++; // Increment address for (byte snd=1; snd < 28; snd++){ // melody title 1-27 Serial.print(ext_ee_adr); // Print address Serial.print(F("\t")); // Print blank //int x=43; byte y=snd-1;byte z=14; // text-address x=43, element y=1, length z, unit u 30.06.2025 int x=0; byte y=snd-1;byte z=14; // text-address x=43, element y=1, length z, unit u int i; // Index for (i=0; i < 14; i++){ // Melody title text starts at 43, length is 14 -> 43 zo 57 int w = x+(y*z)+i; // Calculate address base x + char * length + i //myChar=pgm_read_byte_near(title+w); // Read text from title 30.06.2025 myChar=title[w]; // Read text from title 27-09-2025 Serial.print(myChar); // Debug update_ext_eeprom(ext_ee_adr,myChar); // Write melody title to external eeprom address ext_ee_adr++;} // Increment address //byte b = pgm_read_byte_near(tempis+snd-1);// Get tempo from flash byte byte b = tempis[snd-1]; // Get tempo from flash byte Serial.print(b); // Print tempo Serial.print(F(" ")); // Add a blank update_ext_eeprom(ext_ee_adr,b); // Write tempo to external eeprom ext_ee_adr++; // Increment address // if (snd < 9){length = 50;} // Melody 0-8 normal length 21.05.2025 melody.h modified! // else {length=25;} // Sound > 8 half length length = 50; // All songs with same length - melody.h modified! ofset = (snd-1) * length *2; // Ofset = 0*50*2= 0, 1*50*2 = 100 integer for (i=0; i < length*2; i++){ // Melody notes 100 integers song = 200 byte ofset = (8*50*2)+((snd-9) * length *2); // ofset = base + //int ni=pgm_read_word_near(melody+ofset+i);// DEBUG! read integer int ni=melody[ofset+i]; // DEBUG! read integer - 27-09-2025 Serial.print(ni); Serial.print(" "); // Print note integer //byte n=pgm_read_byte_near(melody+ofset+i);// First byte of note //Serial.print(n); Serial.print(" "); // Debug! Print note first byte update_ext_eeprom(ext_ee_adr,ni>>8); // Melody integer high ext_ee_adr++; // Increment address //n=pgm_read_byte_near(melody+ofset+i+1); // Second byte of note //Serial.print(n); Serial.print(" "); // Debug! Print note second byte update_ext_eeprom(ext_ee_adr,ni & 0xFF); // Melody integer low ext_ee_adr++;} // Increment address Serial.println(); // CR LF } } void i2c_scan(void){ bool error = true; // Flag for I2C-error int addressFound = false; // Flag for valid adress for(int i2ad=1; i2ad<128; i2ad++){ // I2C adress-range Wire.beginTransmission(i2ad); // Start transmission error = Wire.endTransmission(); // Check status if(error == 0){ // No error addressFound ++; // Adress found //lcd.print(F("0x")); // Preambel skipped Serial.print(i2ad,HEX); // Adress Serial.print(F(" "));}} // Space //lcd.setCursor(0,2); // Column 0 row 2 if(!addressFound){ // No adress Serial.print(F("No I2C Address found "));} // Message else{Serial.print(addressFound); // Number Serial.print(F(" Adresses found "));} // Text Serial.println(F(" ")); } byte read_byte(int ext_ee_adr){ // Read byte from external eeprom return (read_ext_eeprom(ext_ee_adr));} // Return byte byte from external eeprom byte read_ext_eeprom(unsigned int addr){ // Read external eeprom byte byteToRead = 0; // Define byte to read ! if (addr < EXT_EE_SIZE){ // Address is valid Wire.beginTransmission(EXT_EE_ADDR); // Start transmission Address of external eeprom Wire.write((byte)(addr>>8)); // Address high Wire.write((byte)(addr&0xFF)); // Address low Wire.endTransmission(); // End transmission Wire.requestFrom(EXT_EE_ADDR, 1); // Allow multiple requests byteToRead = Wire.read(); // Read byte //return byteToRead; // Return value } return byteToRead; // Return value !!!! warning: 'byteToRead' may be used uninitialized in this function } int read_integer(int ext_ee_adr){ // Read integer from external eeprom byte ms = read_ext_eeprom(ext_ee_adr); // read melody note byte 1 byte ls = read_ext_eeprom(ext_ee_adr+1); // Melody note byte 2 return (ms<<8 | ls); // Return integer } void update_ext_eeprom(unsigned int addr, byte byteToWrite){ if (read_ext_eeprom(addr) != byteToWrite){ // Check eeprom content write_ext_eeprom(addr,byteToWrite);}} // Write byte void write_ext_eeprom(unsigned int addr, byte byteToWrite){ if (addr < EXT_EE_SIZE){ // Address is valid Wire.beginTransmission(EXT_EE_ADDR); // Start transmission Address of external eeprom Wire.write((byte)(addr>>8)); // Address high Wire.write((byte)(addr&0xFF)); // Address low Wire.write(byteToWrite); // Write byte Wire.endTransmission(); // End transmission delay(5);}} // important!