Copying small audio files from SD Card to FRAM Breakout

I’ve run out of space on my arduino nano. My sketch plays some very small WAV files and I was going to use an SD Card library to store them, until I realized how much space it takes up. Then that got me thinking… I have a 32K Adafruit FRAM breakout. Would it be feasible to use another arduino with SD Card an FRAM breakout to copy the sound files over byte by byte, and then use that FRAM breakout with my project and avoid the need for an SD Card and library all together? I figure I would need to know the addresses for the beginning and end of each file on the FRAM module, which wouldn’t be a deal-breaker.

So my first question is about feasibility. I’m wondering if this approach might work or if there is another option. I want to avoid a dedicated wav breakout board if possible.

I put together the sketch below that seems to copy each byte over to the FRAM successfully (I think(I can read back bytes off the FRAM).

It’s the second part where I attempt to read each byte off the FRAM and save it back to a new SD Card file, that isn’t working. It creates the file, “copy.wav” but doesn’t save anything in it.

Where am I going wrong with it? I’d appreciate any suggestions.

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include "Adafruit_FRAM_I2C.h"
Adafruit_FRAM_I2C fram     = Adafruit_FRAM_I2C();
uint16_t          framAddr = 0;

void setup() {
  Serial.begin(9600);

  // setup SD-card
  Serial.print("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println(" failed!");
    while(true);
  }
  if (fram.begin()) {  
    Serial.println("Found I2C FRAM");
  } else {
    Serial.println("I2C FRAM not identified ... check your connections?\r\n");
  }
  
  Serial.println(" done.");
delay(4000);
}
  uint8_t count = 0x0;
void loop() {

  File myFile = SD.open("4418.wav");
  if (!myFile) {
    // if the file didn't open, print an error and stop
    Serial.println("error opening");
    while (true);
  }
Serial.println("Copying file from SD to FRAM.");
  const int S = 1; 
  byte buffer[S];
  myFile = SD.open("copy.wav", FILE_WRITE);

  while (myFile.available()) {
    // read from the file into buffer
    myFile.read(buffer, sizeof(buffer));

 Serial.print("0x"); Serial.print(count,HEX); Serial.print(": ");
Serial.println(buffer[count]);

    
fram.write8((count),buffer[count]);

count = count+1;

  }
  myFile.close();
Serial.println ("Copy to FRAM complete");



myFile = SD.open("copy.wav");
  if (myFile) {
    Serial.println("copy.wav:");

    while (myFile.available()) {
uint8_t value;
  for (uint16_t a = 0; a < 32768; a++) {
    value = fram.read8(a);
myFile.print( a, HEX);    

  }
}

  }
    // close the file:
    myFile.close();
  
  Serial.println("Copy to SD Complete");
   while (true) ;
 
  }

The adafruit FRAM lib is here.

nonlinearmind:
Where am I going wrong with it? I’d appreciate any suggestions.

#include <SD.h>

#include <SPI.h>
#include <Wire.h>
#include “Adafruit_FRAM_I2C.h”
Adafruit_FRAM_I2C fram     = Adafruit_FRAM_I2C();
uint16_t          framAddr = 0;

void setup() {
 Serial.begin(9600);

// setup SD-card
 Serial.print(“Initializing SD card…”);
 if (!SD.begin(4)) {
   Serial.println(" failed!");
   while(true);
 }
 if (fram.begin()) {  
   Serial.println(“Found I2C FRAM”);
 } else {
   Serial.println(“I2C FRAM not identified … check your connections?\r\n”);
 }
 
 Serial.println(" done.");
delay(4000);
}
 uint8_t count = 0x0;
void loop() {

File myFile = SD.open(“4418.wav”);
 if (!myFile) {
   // if the file didn’t open, print an error and stop
   Serial.println(“error opening”);
   while (true);
 }

Why do you open “4418.wav”, then using the same “inuse” File variable open “copy.wav” for WRITE?

nonlinearmind:

Serial.println("Copying file from SD to FRAM.");

const int S = 1;
 byte buffer[S];
 myFile = SD.open(“copy.wav”, FILE_WRITE);

And create a ONE byte buffer?

nonlinearmind:

  while (myFile.available()) {

// read from the file into buffer
   myFile.read(buffer, sizeof(buffer));

Serial.print(“0x”); Serial.print(count,HEX); Serial.print(": ");
Serial.println(buffer[count]);

fram.write8((count),buffer[count]);

count = count+1;

}

And loop around trying to read data from a file you have opened for WRITE?

The:

while(myFile.available()){

will always return false!!

And, you are using buffer like it is big enough to hold your entire wave file? BUT you only defined it to be ONE byte in length?

Look at this code:

uint16_t adrs,ofs;  //fram 
uint16_t bufLen;
#define BUFMAX 256;

void loop() {
  adrs=0; // fram location where file starts, you can change this value for your 'other' files
  ofs=0; // fram offset from adrs for each byte
  File myFile = SD.open("4418.wav");
  if (!myFile) {
    // if the file didn't open, print an error and stop
    Serial.println("error opening");
    while (true);
  }

Serial.println("Copying file from SD to FRAM.");
  byte buffer[BUFMAX];

while (myFile.available()) {
    // read from the file into buffer
  bufLen=myFile.read(buffer,BUFMAX); // read up to BUFMAX bytes, actual count in bufLen

  Serial.print("0x"); Serial.print((adrs+ofs),HEX); Serial.print(": ");
  for (uint16_t i=0;i<bufLen;i++){
    if(buffer[i]<10)Serial.print('0');
    Serial.print(buffer[i],HEX);
    }
  Serial.println();

  for(uint16_t i=0;i<bufLen;i++){    
    fram.write8((adrs+ofs+i),buffer[i]);
    }
  ofs = ofs +bufLen;

  }
myFile.close();
}

Chuck.

Thanks, that’s exactly what I was trying to do. How would I go about reading it back into a buffer? I’m using the SimpleSDAudio library and it allows the use of a user-defined work buffer.

The FRAM library example reads back the contents of the FRAM like this:

  uint8_t value;
  for (uint16_t a = 0; a < 32768; a++) {
    value = fram.read8(a);
    if ((a % 32) == 0) {
      Serial.print("\n 0x"); Serial.print(a, HEX); Serial.print(": ");
    }
    Serial.print("0x"); 
    if (value < 0x1) 
      Serial.print('0');
    Serial.print(value, HEX); Serial.print(" ");
  }

How would I take what it reads and store it into a buffer?