Audio
Gakken SX150 + drum loop
Tags
hardware arduino MIDI gakken dac 

 
Yet another MIDI-to-Gakken interface!

August, 02th 2009
Yet another MIDI-to-Gakken interface!

A couple of months ago, during Homework Festival I met a guy from Sofia who had a strange machine in his setup... he told me how cheap and funny it was, so I decided to order one on ebay. Last week I received my Gakken SX-150 and started searching around the net for hacks and mods, and I found several projects and articles describing possible ways of interfacing it with MIDI and various external sensors, but, since I was already doing some experiments with a DAC board and Arduino, I decided to try it with my freshly received Gakken.

I'm using a 16bit serial DAC from Analog Devices, the AD420 (you'll find the board details in my previous article), and, as you can see from the schematics below, the connections are really simple: you just need to solder four wires on the Gakken board, two for the audio output and two for the DAC input. I've also used the MIDI I/O board described in one of my previous articles, and the code below enables Arduino to receive note on/off events and forward them to the Gakken.
You can try some tuning by tweaking "GAKKEN_OFFSET" and "GAKKEN_NOTE_STEP"... enjoy :)

MIDI-to-Gakken Interface
  1. /*---------------------------------------------------------*/
  2. /*   MIDI-to-Gakken Interface                              */
  3. /*   Vincenzo Pacella - www.shaduzlabs.com                 */
  4. /*---------------------------------------------------------*/
  5.  
  6. //arduino output pins
  7. #define LATCH 7
  8. #define CLOCK 8
  9. #define DATA  9
  10. #define OPTOCOUPLER_ENABLE 10 //to MIDI I/O Board Vcc
  11.  
  12. //2 uS of clock period (sample rate = 30.3 KHz)
  13. #define HALF_CLOCK_PERIOD 1 //uS
  14.  
  15. //MIDI Input state machine definitions
  16. #define STATUS_IDLE 0
  17. #define STATUS_MIDI_NOTE_ON 1
  18. #define STATUS_MIDI_NOTE_OFF 2
  19. #define STATUS_MIDI_NOTE_VELOCITY 3
  20. int status = STATUS_IDLE;
  21.  
  22. //MIDI Input buffer
  23. byte midiByte;
  24.  
  25. //MIDI Channel (1-16)
  26. #define MIDI_CHANNEL 1
  27.  
  28. //MIDI Events
  29. #define NOTE_ON (0x90|(MIDI_CHANNEL-1))
  30. #define NOTE_OFF (0x80|(MIDI_CHANNEL-1))
  31.  
  32. //Tuning 8)
  33. #define GAKKEN_OFFSET 12000
  34. #define GAKKEN_NOTE_STEP 374
  35.  
  36. void setup()
  37. {
  38.  pinMode(DATA, OUTPUT);
  39.  pinMode(CLOCK,OUTPUT);
  40.  pinMode(LATCH,OUTPUT);
  41.  pinMode(OPTOCOUPLER_ENABLE,OUTPUT);
  42.  
  43.  digitalWrite(DATA,LOW);
  44.  digitalWrite(CLOCK,LOW);
  45.  digitalWrite(LATCH,LOW);
  46.  digitalWrite(OPTOCOUPLER_ENABLE,HIGH);
  47.  Serial.begin(31250);
  48. }
  49.  
  50. void writeValue(uint16_t value){
  51.  
  52.  //start of sequence
  53.  digitalWrite(LATCH,LOW);
  54.  digitalWrite(CLOCK,LOW);
  55.  
  56.  //send the 16 bit sample data
  57.  for(int i=15;i>=0;i--){
  58.  digitalWrite(DATA,((value&(1<<i)))>>i);
  59.  delayMicroseconds(HALF_CLOCK_PERIOD);
  60.  digitalWrite(CLOCK,HIGH);
  61.  delayMicroseconds(HALF_CLOCK_PERIOD);
  62.  digitalWrite(CLOCK,LOW);
  63.  }
  64.  
  65.  //latch enable, DAC output is set
  66.  digitalWrite(DATA,LOW);
  67.  digitalWrite(CLOCK,LOW);
  68.  digitalWrite(LATCH,HIGH);
  69.  delayMicroseconds(HALF_CLOCK_PERIOD);
  70.  digitalWrite(LATCH,LOW);
  71.  
  72. }
  73.  
  74. void loop()
  75. {
  76.  if (Serial.available() > 0) {
  77.  midiByte = Serial.read();  
  78.  switch(status){
  79.  case STATUS_IDLE:
  80.  if (midiByte== NOTE_ON){
  81.  status=STATUS_MIDI_NOTE_ON;
  82.  }
  83.  else if (midiByte== NOTE_OFF){
  84.  status=STATUS_MIDI_NOTE_OFF;
  85.  }
  86.  break;  
  87.  
  88.  case STATUS_MIDI_NOTE_ON:
  89.  writeValue(GAKKEN_OFFSET+(midiByte*GAKKEN_NOTE_STEP));
  90.  status=STATUS_MIDI_NOTE_VELOCITY;
  91.  break;
  92.  
  93.  case STATUS_MIDI_NOTE_OFF:
  94.  writeValue(0);
  95.  status=STATUS_MIDI_NOTE_VELOCITY;
  96.  break;
  97.  
  98.  case STATUS_MIDI_NOTE_VELOCITY:
  99.  //velocity data is not used!
  100.  status=STATUS_IDLE;
  101.  break;
  102.  
  103.  default:
  104.  break;  
  105.  }  
  106.  }
  107. }