Sunday, May 26, 2013

SN76489 USB MIDI 103 Firmware: Quad Support!

Overview
SN76489 USB MIDI now supports up to four SN76489 chips per one Teensy! This means controlling up to 12 pulse wave channels and up to 4 noise channels using MIDI.

Additionally, sample support has been added for the first SN76489 chip and is handled by the first three pulse channels.



Mapping 
The 16 MIDI channels of the SN76489 USB MIDI are mapped to up to four SN76489 chips in the following way:






The sample playback of up to sixteen samples are mapped in the following way:

Note: Whenever a sample is playing, pulse channels 1, 2 and 3 of SN76489 chip 1 cannot be used.

The SN76489 USB will respond to:
• Note on events
• Note off events
• Pitch bend
• MIDI CC 11: expression
• MIDI CC 81: bend amount in semitones (default 12)





Parts, Pinouts and Circuit
Required:
• 1 x Teensy 2.0
• 1 - 4 x SN76489
• 1 x Crystal oscillator (1.00 MHz - 3.00 MHz, typically 1.8432 MHz)



Here are the pinouts for the Teensy 2.0, the SN76489 and the crystal oscillator.




Here is how these components should be connected. Download the spreadsheet here.





Here is an example breadboard layout for a single SN76489 chip:

Here is a picture of a breadboard layout for all four SN76489 chips:




Code

Download the code here. Please feel free to modify as you see fit, and have fun making chiptunes.

If you are having trouble triggering the notes in terms of matching up the channel numbers, please read this post.

Note that there is a line of code in the program that reads: long clock = 1843200; Simply change the value of clock in Hz to support any value of crystal oscillator whilst staying in tune!

The default is 1843200 (i.e. a clock speed of 1.8432 MHz) as this is the crystal speed that I prefer, however the SN76489 can accept a wide range of clock speeds. If you want a bassier pitch range, simply use a lower value crystal oscillator.

Three SN76489 Pulse Channels for Sample Playback

I have updated the code for how my SN76489 USB MIDI plays back samples.

Previously, I would use a single pulse channel and then trigger samples using the volume of that single pulse channel using amplitude sample data.

The aim of using only one pulse channel was that it would free up the other channels for melodic and harmonic use.

However, the result is that the sample playback is very, very soft in volume, meaning that there is more overall unwanted noise, and that there is also a limit to how the other channels can be used velocity-wise in order to balance out the single pulse channel that is used for sample playback.

I have decided to try out using all three pulse channels for sample playback, and all though this limits the use of all pulse channels on that particular SN76489 chip whenever sample data is playing.

The effective outcome is a much more balanced sample function in terms of volume. Samples also seem to sound 'crisper', less gain is needed to bring the chip up to appropriate levels.


Saturday, May 25, 2013

Receiving Teensy MIDI Channels as Indexed from Zero

There are many instances when my Teensy / Arduino code may not work on standard Teensy installations as expected.

This applies to many cases where MIDI data is received by the Teensy.  This is because I prefer to deal with MIDI channels when indexed from zero instead of one.

If you would like to run my Teensy code on your install, one things you can do is update the Teensy MIDI API files.

To do this, right click on the Arduino app, go to Show Package Contents and navigate to the following file, and opening it in a text editor:
Arduino > Contents > Resources > Java > Hardware > Teensy > cores > usb_midi > usb_api.cpp

Find the following code:

type2 = b1 & 0xF0;
    c = (b1 & 0x0F) + 1;


And change it to:

type2 = b1 & 0xF0;
    c = (b1 & 0x0F);


Save the file. As a result, any MIDI data received will return channel numbers 0 - 15 instead of 1 - 16.

Piggybacked SN76489 Chips








One SN76489 is piggybacked on another. They share many pins and only a small number need to be isolated from each other.

• Removal of !READY pin
• Isolation of !WRITE_ENABLE pin
• Isolation of SOUND_OUT pin
• Shared data bus, ground and 5V pins

Quad SN76489 Prototype Demonstration


SN76489 USB MIDI Firmware 102: Linear Pitchbend, Clock-based Pitch

Overview
SN76489 USB MIDI Firmware 102 for the Teensy features the following changes:
• Pitchbend is musically linear, meaning that the same value pitch bend will give the same pitch distance no matter which pitch is played.

• CC71 on MIDI channels 1 - 4 sets the pitch bend range in semitones. The default is 12 semitones. 

• The frequency data for the SN76489 is calculated using a formula rather than a look up table.

• The advantage of this is there is a line of code in the program that reads: long clock = 1843200; Simply change the value of clock in Hz to support any value of crystal oscillator whilst staying in tune!

• The default is 1843200 (i.e. a clock speed of 1.8432 MHz) as this is the crystal speed that I prefer, however the SN76489 can accept a wide range of clock speeds. If you want a bassier pitch range, simply use a lower value crystal oscillator.


Download the firmware here: http://milkcrate.com.au/_other/downloads/teensy/SN76489_USB_MIDI_102/SN76489_USB_MIDI_102.ino



Example Breadboard Layout



Demonstration Video




Friday, May 24, 2013

Circuit Bending Basics 8: Independent Multi Button Triggering

Overview
This post assumes that you are familiar with the previous Circuit Bending Basics Posts.

Circuit bending is about the non-thereoretical exploration of sound making circuits via shorting different points together. Take a toy (that is battery powered - important!) and let's get to work!



Multi Button Triggering
A previous post demonstrated how to trigger a single button using a 4066 chip. The 4066 chip has four such functional blocks. This article demonstrates how to use all four of these blocks. It is a assumed that you have read the previous post in question.



Schematic

The red pair, yellow pair, green pair and orange pair of connections each represent a pair of points on a circuit board that triggers sounds and thus replaces buttons. 



Code


Download here: http://milkcrate.com.au/_other/downloads/projects/_4066_example/_4066_example.ino



Example - Toy Keyboard





Video Demonstration


Circuit Bending Jam (1)

This is an example of altering a circuit bent instrument in real time via MIDI data. 

Different sounds are triggered using MIDI note on and off events. The clock speed is altered using pitch bend

 

Circuit Bending Basics 7: MIDI-controlled Toy Pitch / Speed

Overview
This post assumes that you are familiar with the previous Circuit Bending Basics Posts.

Circuit bending is about the non-thereoretical exploration of sound making circuits via shorting different points together. Take a toy (that is battery powered - important!) and let's get to work!



Digital Pot and Toy Control
This article is based around the MCP4212 digital pot and the Teensy - so if you're not familiar with either, please visit the Teensy website,  read up a little on Arduino coding and check out my Teensy Basics series of posts. Also, be sure to check out the MCP4212 tutorial.

This article will provide a simple framework that can be used to control the pitch / speed of a toy using MIDI pitch data. The higher the pitch, the higher the speed of the toy.

In general, the process is like this:
• Build the barebones MCP4212 and Teensy setup as shown in the tutorial
• Find the clock resistor of a toy that you wish to control
Remove the resistor
• Connect the two resistive points on the toy's circuit to the P0A and P0W pins of the MCP4212
• Write some code to control pot 0 of the MCP4212 via MIDI



Connecting the Digital Pot to the Toy - Example
Once again, we revisit the musical mat toy from the previous Circuit Bending Basics.

The resistor in this particular toy is simple to remove. The two resistive connections on the board were soldered to two white wires, which were then connected to P0A and P0W pins of the MCP4212.

In the first image, these connections are highlighted in purple. 






Writing the Code
The code takes the pitch value of a note-on MIDI message, and sends that value to the digital pot. The digital pot then sets this as a resistance.

The code uses the same SPI library as in the MCP4212 example. The code uses the same user-defined MCP4212 function as in the MCP4212. The changes in the fact that the usbMIDI functions are connected to the digital pot.



Download the code here: http://milkcrate.com.au/_other/downloads/projects/MCP4241_104EP_Example_2/MCP4241_104EP_Example_2.ino



Example Video

How To: Interface with an MCP4241 Dual Digital Pot

Overview
The aim of this post is to present a basic practical understanding of interfacing with an MCP4241 dual digital pot. A digital pot is a digitally-controlled potentiometer, which is a very useful device. It allows a microcontroller to change a potential or a resistance using data values instead of having to turn a physical pot with a human hand. Many instances where a physical pot is used can be substituted with a digital pot.

Examples include: dimming LEDs, controlling the resistance of circuit bent toys, conditioning audio signals, setting the volume of audio signals, creating auto stereo panning devices, controlling an oscillator, creating a digital to analogue converter and so on.



The MCP4241
The MCP4241-104E is a chip with 100k digitally controlled pots that are accessed via an SPI bus. Additionally, the chip features both volatile and non-volatile memory and a number of other useful functions. The pots have 7-bits of resolution (i.e. 128 steps of resistance). It can be powered from 2.7V to 5.5V.

The MCP4241 comes from a larger family of chips, the MCP414X/416X/424X/426X family. More information can be found here.



The SPI Bus
The MCP4241 connects and communicates with a microcontroller (such as an Arduino or a Teensy) via the SPI Bus. SPI is a protocol that allows microcontrollers to interface easily with a large number of external chips and sensors.

SPI is a host / slave type bus. A single host microcontroller can interface with one or more slave chips or sensors.

SPI uses up to four pins for communication:
- CS (may also be called SS): chip select:
Used by the microcontroller to select each device. The host microcontroller has a CS output pin for every slave device that is to be used.

- SCK: serial clock:
Used by the host microcontroller to time the data that is moved to and from the slave device. There is one SCK connection that is shared amongst all SPI devices.

- SDI: slave data in:
Used by the host microcontroller to send data to a slave device. There is one SDI connection that is shared amongst all SPI devices.

- SDO: slave data out:
Used by the host microcontroller to receive data from a slave device. There is one SDO connection that is shared amongst all SPI devices.

All SPI slave devices require the CS and SCK pins. However, many device may not require both the SDI and SDO connections, as they might only either send or receive data.

With the MCP4241 chip, we want to set the resistance of a digital potentiometer using data from a host microntroller. As a result, we only need CS, SCK and SDI, because the information needs to travel only from the host to the slave device.

If you are using a Teensy, the following table shows the CS, SCK, SDI and SDO pins to use:


If you are using an Arduino, the following table shows the CS, SCK, SDI and SDO pins to use:





MCP4241 Physical Layout




The above diagram shows the layout of the 14-pin MCP4241 chip. Pin 1 is to the left of the half-circle indent. Pin 14 is to the right of the half-circle indent.

Pin 1 - CS - SPI Bus Chip Select
Pin 2 - SCK - SPI Bus Serial Clock
Pin 3 - SDI - SPI Bus Slave Digital In
Pin 4 - Vss - Connect to Ground
Pin 5 - P1B - Potentiometer Number 1, Terminal B
Pin 6 - P1W - Potentiometer Number 1, Wiper
Pin 7 - P1B - Potentiometer Number 1, Terminal A
Pin 8 - P0B - Potentiometer Number 0, Terminal A
Pin 9 - P0W - Potentiometer Number 0, Wiper
Pin 10 - P0B - Potentiometer Number 0, Terminal B
Pin 11 - WP - Write Protection - Connect to 5V for normal operation
Pin 12 - SHDN - Shutdown - Connect to 5V for normal operation
Pin 13 - SDO - SPI Bus Slave Digital Out
Pin 14 - Vdd - Connect to 5V



MCP4241 Breadboard Layout - Basic Functions - With Teensy
Set up the power for the MCP4241:
• Connect ground from the Teensy to the ground bus on the breadboard.
• Connect 5V from the Teensy to the 5V bus on the breadboard.
• Connect 5V to Vdd (pin 14) of the MCP4241.
• Connect ground to Vss (pin 4) of the MCP4241.


Initialise the additional function pins of the MCP4241:
• Connect 5V to SHDN (pin 12) of the MCP4241
• Connect 5V to WP (pin 11) of the MCP4241



Connect the SPI Bus to the MCP4241: 
• Connect Teensy digital pin 0 to CS (pin 1) of the MCP4241
• Connect Teensy digital pin 1 to SCK (pin 2) of the MCP4241
• Connect Teensy digital pin 2 to SDI (pin 3) of the MCP4241


Connect to MCP4241 potentiometer 0 for testing:
• Connect P0W (pin 9 of the MCP4241 to a probe of a multimeter
• Connect P0A (pin 9 of the MCP4241) to the other probe of a multimeter

 
Set up the multimeter: 
• Set the multimeter to the 2000Ω range of resistance. 



Programming the Digital Pot
In general, the digital pot is easy to program using the Arduino SPI library, which is included in the Arduino distribution. This library is compatible with Teensy. 

The library is very easy to use, but requires a little setting up as follows: 
• the CS / SS pin needs to be set up manually in the Arduino code
• the SCK, SDI and SDO do not need to be manually set up, as the library does this

A basic test program is shown below. 

Note that this includes a function called writeMCP4241. This function takes two arguments - address and value. The address sets which pot to control (either 0 or 1) and the value sets the value to write to the pot (0 - 127). 

The example simply moves through all 128 possible values for both pots. Measuring the resistance between P0A and P0W should change over time as all 128 values are cycled through.





Demonstration Video

Thursday, May 23, 2013

Circuit Bending Basics 6: Dual Multiplexing for Many Different Button Triggers

Overview
This post assumes that you are familiar with the previous Circuit Bending Basics Posts.

Circuit bending is about the non-thereoretical exploration of sound making circuits via shorting different points together. Take a toy (that is battery powered - important!) and let's get to work!



Dual Multiplexing Concept
This post builds on a previous example, which explored the use of multiplexing in the context of triggering buttons of a toy.

In the previous example, a monophonic toy had eight musical buttons and many other non-musical sounds. The eight musical buttons were triggered using a multiplexer.

This post extends that basic idea by adding a second multiplexer to the mix.

Let's go back and examine the musical mat, and the way that the buttons are wired:


Upon testing all of the button pins, a pattern emerged. Let's consider the button pins as either being a letter (for the horizontal ones) or a number (for the vertical ones), as shown in the above image.

By connecting any of the pins labeled with letters (in purple) with the pins labeled with numbers (in green), a sound is triggered. Interesting, the letter determines the sound "category" whilst the number determines the actual button pressed.

Connecting A to 1 is the same as pressing the physical toy button on the musical mat for the note C. Connecting A to 2 is the same as pressing the physical toy button on the musical mat for the note D. Connecting A to 3 is the same as pressing the physical toy button on the musical mat for the note E and so on.

Let's illustrate this with a diagram:


 A connection between point A and point 1 is the same as pressing the C note on the mat.


Now, we have already triggered all of the A button group buttons using a single multiplexer in the previous example. But, if we look at the structure, there are actually a total of 32 trigger points, if all connections between numbers and letters are considered, like this:

So, the aim of this blog post is to describe and practically explore ways of combining two multiplexers to be able to recreate any one of the 32 connections shown above at will.

In fact, if there were up eight letters and eight numbers (64 connections), then this would be possible too.




Dual Multiplexing
In the previous example, we looked at the concept of having 8 inputs multiplexed to one output, like so:





The good thing about the 4051 chip is that it doesn't care what is an input and what is an output. That is to say, we can reverse this action, like so, and take one input and send it to many outputs (one output at a time, of course, depending on control mechanism): 






Now, let's connect the normal multiplexer to the reverse mutliplexer,like so: 


In this way, we can have up to 64 independent signals travelling through and being controlled by two 8 channel multiplexers.



Bringing it Together
If we combine the desire to emulate all of those button presses between the letter and number combination with the concept of a dual stage multiplexing setup, then we can end up with a concept like this: 



Thus, any of the 32 possible sounds of the musical mat can be triggered!

Of course, in reality it looks a little messy...







Video


Code for Teensy
int INH = 5;
int ON_4066 = 6;

void setup() {
  usbMIDI.setHandleNoteOn(OnNoteOn);
  usbMIDI.setHandleNoteOff(OnNoteOff);
  DDRB = B00011111;
  pinMode(INH, OUTPUT);
  pinMode(ON_4066, OUTPUT);
  pinMode(11, OUTPUT);
  digitalWrite(INH, HIGH);
  digitalWrite(ON_4066, LOW);
  digitalWrite(11, HIGH);
}

void loop() {
  usbMIDI.read();
}

void OnNoteOn(byte channel, byte pitch, byte velocity) {
  if(velocity > 0) {
  PORTB = pitch % 32;
  delay(1);
  digitalWrite(INH, LOW);
  digitalWrite(ON_4066, HIGH);
  digitalWrite(11, HIGH); 
  }
  else {
    digitalWrite(INH, HIGH);
    digitalWrite(ON_4066, LOW);
    digitalWrite(11, LOW);
  }
}

void OnNoteOff(byte channel, byte pitch, byte velocity) {
    digitalWrite(INH, HIGH);
    digitalWrite(ON_4066, LOW);
    digitalWrite(11, LOW);
}

 





  
Toy Guitar Example
The same concept can be applied to other toys as well. Here is an example with a toy electric guitar:













Video


Code for Teensy
int INH = 5;

int delay_time = 100;

void setup() {
  usbMIDI.setHandleNoteOn(OnNoteOn);
  usbMIDI.setHandleNoteOff(OnNoteOff);
  DDRB = PINB & B00001111;
  pinMode(INH, OUTPUT);
  pinMode(11, OUTPUT);
  digitalWrite(INH, HIGH);
  digitalWrite(11, HIGH);
}

void loop() {
  usbMIDI.read();
}

void OnNoteOn(byte channel, byte pitch, byte velocity) {
  if(velocity > 0) {
  PORTB = pitch % 12;
  digitalWrite(INH, LOW);
  digitalWrite(11, HIGH);
  }
  else {
    digitalWrite(INH, HIGH);
    digitalWrite(11, LOW);
  }
}

void OnNoteOff(byte channel, byte pitch, byte velocity) {
    digitalWrite(INH, HIGH);
    digitalWrite(11, LOW);
}