Sunday 26 January 2014

Arduino MIDI Synth No.1

It isn't particularly elegant, cheap or clever, but it is a start. Done hundreds of other places as well, but it's my start. Arduino MIDI Synth starting position.

I've simply assembled the SparkFun MIDI Shield (without buttons) on top of the SparkFun Musical Instrument Shield which then sits on top of a Seeeduino. The Musical Instrument Shield has been soldered up with through headers (from Proto-PIC).

The input is from a Roland PC-300 keyboard that I picked up for a fiver on e-bay. This makes simple sounds, but now allows the keyboard to do something powering both from a dual USB wall-wart. The output is into headphones direct from the shield.

What it also allows me is a base to start playing around with some things (like the previously mentioned  Marmonizer) with just a few hours of evening assembly. 

The buttons were not wired up due to the well commented oversight from SparkFun of wiring the buttons to pins D3 + D4. Button D2 could have been wired up, but a single button is not all that exciting really. Shame that this was not thought of as the two make obvious companions. This can be worked around with a bit of hard wiring as show below from naught101. As he says, makes a nice hack-able synth for 60quid. 




I used naught101's code which he kindly posted up to get started with a few mods as Serial1 was not available. Please respect the Beerware license and by Nathan a beer if you see him.

I've included this for comprehensiveness and as I expect to use it as a basis for building future ideas.

BTW, I know the convention is to use K&R styling on the brackets for compactness etc... , but after having this beaten out of me during my industrial placement year over 20 years ago I still find it hard to write any code this way myself.

/////////////////////////////////////////////////////////////////////////////
// Code released under the Beerware license. Public domain, but if you meet
// any of the authors, feel free to buy them a drink.
//
// Authors:
//   Nathan Seidle: Spark Fun Music instrument shield example code,
//     https://www.sparkfun.com/products/10587
//   Unknown: Spark Fun MIDI shield, https://www.sparkfun.com/products/9595
//   naught101: arduino_midi_box,
//     https://bitbucket.org/naught101/arduino_midi_box
//   hondrou: modified to work with my basic setup
//     hondrouthoughts.blogspot.com 
//
// The code is desiged to work with the Spark Fun Music instrument shield
// (https://www.sparkfun.com/products/10587), and the Spark Fun MIDI shield
// (https://www.sparkfun.com/products/9595). The two shields have a couple of
// conflicting pins (digital 3 and 4, used for MIDI shield buttons, and Music
// shield MIDI in and reset). To get around this, the code assumes that the 
// buttons have not been wired up 
//
/////////////////////////////////////////////////////////////////////////////

// Standard Arduino Pins
#define PIN_LED 13
#define PIN_RX 0
#define PIN_TX 1

// defines pin setups for MIDI Shield components only
// knobs are analogue
#define MIDI_PIN_KNOB1  0
#define MIDI_PIN_KNOB2  1

// status lights
#define MIDI_PIN_STAT1  7
#define MIDI_PIN_STAT2  6

// Music shield pins - both digital
#define MUSIC_PIN_MIDI_IN  3 // soft serial TX -> VS1053 RX
#define MUSIC_PIN_RESET  4   // VS1053 RESET

// MIDI status
#define MIDI_STATUS_NOTE_ON 0x80
#define MIDI_STATUS_NOTE_OFF 0x90
#define MIDI_STATUS_CONTROL_CHANGE 0xB0
#define MIDI_STATUS_PROGRAM_CHANGE 0xC0

#include <SoftwareSerial.h>

SoftwareSerial MusicSerial(2, 3); //Soft TX on 3, we don't use RX in this code

/////////////////////////////////////////////////////////////////////////////
//  Setup routine             
/////////////////////////////////////////////////////////////////////////////

void setup() 
{
  pinMode(MIDI_PIN_STAT1, OUTPUT);
  pinMode(MIDI_PIN_STAT2, OUTPUT);

  for(int i = 0; i < 3; i++) // flash MIDI Sheild LED's on startup
  {
    digitalWrite(MIDI_PIN_STAT1, HIGH);
    digitalWrite(MIDI_PIN_STAT2, LOW);
    delay(100);
    digitalWrite(MIDI_PIN_STAT1, LOW);
    digitalWrite(MIDI_PIN_STAT2, HIGH);
    delay(100);
  }
  digitalWrite(MIDI_PIN_STAT1, HIGH);
  digitalWrite(MIDI_PIN_STAT2, HIGH);

  // start hardware serial with midi baudrate 31250
  Serial.begin(31250);

  // Setup soft serial for MIDI control of Music Shield
  MusicSerial.begin(31250);

  // Reset the VS1053
  pinMode(MUSIC_PIN_RESET, OUTPUT);
  digitalWrite(MUSIC_PIN_RESET, LOW);
  delay(100);
  digitalWrite(MUSIC_PIN_RESET, HIGH);
  delay(100);
}

/////////////////////////////////////////////////////////////////////////////
//  Main loop             
/////////////////////////////////////////////////////////////////////////////

void loop () 

{


  // MIDI to Music
  int byte_count = Serial.available();
  if (byte_count > 0) 
  {
    // If we have serial data incoming, record it.
    byte midi_bytes[byte_count];
    for (int i = 0; i < byte_count; i++) 
    {
      midi_bytes[i] = Serial.read();
    }
    
    //Send straight to the sound module:
    music_write_midi(midi_bytes, byte_count);
  }

}

/////////////////////////////////////////////////////////////////////////////
//  Functions             
/////////////////////////////////////////////////////////////////////////////



// Sends MIDI data to Music Instrument Sheild, and flashes the LED
void music_write_midi(byte* midi_bytes, int byte_count) 
{
  digitalWrite(MIDI_PIN_STAT1, LOW);
  for(int i = 0; i < byte_count; i++)
  {
     MusicSerial.write(midi_bytes[i]);
  }
  digitalWrite(MIDI_PIN_STAT1, HIGH);
}


Unfortunately the debugging to the Serial port is not possible with the Seeeduino I have so I had to remove those lines of code although very helpful.

When uploading this and running remember that the Tx/Rx pins are being used for the MIDI In/Out in the shield. There is a switch for toggling Prog mode and Run mode. Switch to Prog when uploading the program and Run obviously when running.


Now the playground is in place I'm ready for more experiments later in the week ....

No comments:

Post a Comment