Tuesday, 30 October 2012

NaV-1 Arduino Soundgin-Babblebot Synth - Part 4b

Programming the 24LC256 EEPROM Chip

 

First, read and build the 24LC256 EEPROM circuit in Part 4a of this series. Or if you are new here, start at the beginning. If you want to jump ahead and start building the final hardware go HERE.

Now download the new code HERE, unzip the folder,  and open in Arduino IDE v1.0 or later.
(Make sure you only open the file named "NaV-1_EEPROM_Test.ino".)
The other files will open as tabs in the IDE. The code has been made with IDE version 1.0 and has not been tested in higher versions although it should work. Also, the code is in very early stages so excuse the appearance.

Burn the code on to your Arduino and fire it up. You should see a brief loading page then the main screen of the NaV-1 interface. Since you have not saved anything to the EEPROM yet, it will be full of nonsense values that the synth won't understand. That's ok, there is a Initialization procedure to format the chip. Instead of me writing a long and drawn out description of the procedure, please watch the following video that demonstrates the operation of the NaV-1 in its current state.





We will now take a look at the code that will allow the synth to save its patch data on the 24LC256 EEPROM chip. First, a bit about how the chip works.

The 24LC256 Chip


I suggest that you take a look at this article that does a great job describing the 24LC256 chip and the I2C bus. The important points to take from the article are:

-The chip is an I2C controlled, 32K Byte, EEPROM storage device.
-It uses a control code (in our case Hex 50) to identify the chip.
-The 24LC256 breaks its memory into "Pages". Each page is 64 bytes long.
-You can only write to one page at a time.

The anatomy of the NaV-1 Patch


To make things simple, each Patch on the NaV-1 synth is 192 Bytes long (three eeprom pages). This will allow us to write a patch with three page write calls. The Bytes are arranged as follows.

|---------------------------------|-----------------------|-----------------------------------------|
   144 Soundgin registers      16 Byte name       32 Byte NaV-1 parameters

The first 144 bytes store a snapshot of the Soundgin's 144 registers. This is followed by a 16 byte character array that holds the patch name. The remaining 32 bytes are reserved for parameters that the NaV-1 may want to store in future updates. The software is still in it's early stages so it is nice to have those 32 bytes available.

Arduino EEPROM Functions


The NaV-1 software uses two functions to make the eeprom talk to the Arduino, patchRead() and patchWrite() . Both functions take a one byte argument called 'patchNum'. As you may have guessed, this is simply the number of the patch you are trying to deal with. The patchNum variable is then multiplied by 192 to get the starting address of the 192 Byte block of memory we are going to access. The result is stored in the 'address' variable which is a two byte integer. The address must be sent to the eeprom one byte at a time so the code isolates the high byte - sends it - then isolates and sends the low byte.

The patchWrite() function uses a do-while loop to send the 144 Soundgin data register values in 16 Byte blocks to the eeprom. The data is broken up in this way due to the size of the Arduino data buffer. Next, a final 16 Byte block of data is sent containing the letters of the patch name.

void patchWrite(byte patchNum)
{

  byte i; //Loop Counter
  byte data = 0; //Array Index
  unsigned int address = (patchNum * 192);
  // Write Soundgin data
  do{
    Wire.beginTransmission(EEPROM1);
    Wire.write((int)((address) >> 8));   // High Byte
    Wire.write((int)((address) & 0xFF)); // Low Byte
    for (i=0; i < 16; i++){ //Write 16 Byte block of data
      Wire.write(patch[data]);
      data++;
    }
    Wire.endTransmission();
    address = address + 16; //Move to next 16 Byte block
    delay(10);
  }
  while (data < 144); //Write 16 Bytes until all sent
  // Write Patch name
  Wire.beginTransmission(EEPROM1);
  Wire.write((int)((address) >> 8));   // High Byte
  Wire.write((int)((address) & 0xFF)); // Low Byte
  for (i=0; i < 16; i++){
    Wire.write((byte) patchName[i]);
  }
  Wire.endTransmission();
  delay(10);
}


The patchRead() function works similarly except the data is read from the eeprom.

void patchRead(byte patchNum)
{
  byte data = 0; // Array Index
  byte i; // Loop Counter
  unsigned int address = (patchNum * 192);

  for (i=0; i < 9; i++){ // Read 9 Blocks of 16 Bytes
    Wire.beginTransmission(EEPROM1);
    Wire.write((int)(address >> 8)); // High Byte
    Wire.write((int)(address & 0xFF)); // Low Byte
    Wire.endTransmission();

    Wire.requestFrom(EEPROM1, 16);
    while(Wire.available())
    {
      patch[data] = Wire.read();
      data++;
    }
    address = address + 16;
    delay(10);
  }
  //Read Patch Name
  data = 0;
  Wire.beginTransmission(EEPROM1);
  Wire.write((int)(address >> 8)); // High Byte
  Wire.write((int)(address & 0xFF)); // Low Byte
  Wire.endTransmission();

  Wire.requestFrom(EEPROM1, 16);
  while(Wire.available())
  {
    patchName[data] = Wire.read();
    data++;
  }
}

Have some fun experimenting with the synth. Remember, you can use 'Raw' mode to change any register you like. Just make sure you download and read the Soundgin datasheet so you know what you are changing.

This completes the basic hardware of the NaV-1. Next, we are going to work on removing the Arduino  development board from the equation and making a 'stand alone' version of the circuit.

1 comment:

  1. FYI - you can get the SoundGin chip on an existing Arduino shield here:

    www.ginsingsound.com

    ReplyDelete