Wednesday, January 30, 2008

Programmable auto filter interface for C64 using Arduino

Demo video: http://www.youtube.com/watch?v=kKADOmFqRMs


Overview

A software / hardware combo that allows for control of the analog filter inside a Commodore 64 that is running Cynthcart from a host computer (eg, Macbok, PC).


Software
• 16-step filter sequencer
• Set the speed of the filter sequence (with intervals between values reaching 2ms)
• Set the length of the sequence from 1 to 16 beats
• Offset value allows for shifting the filter values up or down on a larger scale
• MIDI mode allows sending data directly to control the filter (this mode disables the sequencer)

Download the Max/MSP patch here:
http://milkcrate.com.au/_other/downloads/max_patches/C64_FILTER.zip

It requires Max/MSP runtime which can be downloaded from http://www.cycling74.com/.


Screenshot

Interface
The hardware is very simple, and is based around an Arduino board that is using a bit-banging SPI technique to write data to a 100KΩ digital pot (model MCP42100). Approximately 7 of the 8 bits of data actually change the value of the filter (this could be due to the resistance value of the pot).

Any microcontroller that can either do SPI natively or through bit-banging should be able to handle this simple operation.




Schematic
Notes:
• J1 1 to 14 refers to Arduino digital pins 0 to 13
• The datasheet for the MCP42100 recommends a 0.1uF or similar capacitor to smooth out the power supply. However, this has not been an issue.


Arduino Code

/* INITIALISATION */

int SS1 = 2; // set slave select 1 pin


int CLK = 3; // set clock pin


int MOUT = 4; // set master out, slave in pin


byte cmd_byte0 = B00010001; // command byte to write to pot 0, from the MCP42XXX datasheet


byte cmd_byte1 = B00010010; // command byte to write to pot 1, from the MCP42XXX datasheet


byte cmd_byte2 = B00010011; // command byte to write to pots 0 and 1, from the MCP42XXX datasheet


byte work; // setup a working byte, used to bit shift the data out


byte data;


/* SETUP */


void setup() { // setup function begins here

Serial.begin(57600);


pinMode(SS1, OUTPUT); // set CS pin to output


pinMode(CLK, OUTPUT); // set SCK pin to output


pinMode(MOUT, OUTPUT); // set MOSI pin to output


digitalWrite(SS1, HIGH); // hold slave select 1 pin high, so that chip is not selected to begin with


}


void spi_transfer(byte working) {


; // function to actually bit shift the data byte out


for(int i = 1; i <= 8; i++) { // setup a loop of 8 iterations, one for each bit


if (working > 127) { // test the most significant bit


digitalWrite (MOUT,HIGH); // if it is a 1 (ie. B1XXXXXXX), set the master out pin high


}


else {


digitalWrite (MOUT, LOW); // if it is not 1 (ie. B0XXXXXXX), set the master out pin low


}


digitalWrite (CLK,HIGH); // set clock high, the pot IC will read the bit into its register


working = working << 1;


digitalWrite(CLK,LOW); // set clock low, the pot IC will stop reading and prepare for the next iteration (next significant bit


}


}


void spi_out(int SS, byte cmd_byte, byte data_byte) { // SPI tranfer out function begins here


digitalWrite (SS, LOW); // set slave select low for a certain chip, defined in the argument in the main loop. selects the chip


work = cmd_byte; // let the work byte equal the cmd_byte, defined in the argument in the main loop


spi_transfer(work); // transfer the work byte, which is equal to the cmd_byte, out using spi


work = data_byte; // let the work byte equal the data for the pot


spi_transfer(work); // transfer the work byte, which is equal to the data for the pot


digitalWrite(SS, HIGH); // set slave select high for a certain chip, defined in the argument in the main loop. deselcts the chip


}


void loop () {


if(Serial.available() > 0) {


data = Serial.read();


spi_out(SS1, cmd_byte0, data); // send out data to chip 1, pot 0


delay(2); // set a short delay

}


}


5 comments:

Anonymous said...

this is ideal! definitely my next project.

Sebastian Tomczak said...

thanks!
im glad you like it.

Anonymous said...

sebastian, do you have aim or msn? if so could you drop me an im next time you're online? aim: firebrandboy msn: nae_baws_mcgraw@hotmail.com. i'd like to ask you a couple of questions if you dont mind.

Anonymous said...

Finally!
A blog worth reading on forward until the end! :) I really admire the wording in this blog, quite precise to the details and I wont change anything! never-the-less, bravo on well choiced words mate.. p.s.>> Thanks for sharing, I totally picked up some knowledge on this one :)
-Have an amazing day!

Naku said...

Wow! This is awesome! Can't wait to start building it.