I am currently in the process of writing a synth for the Arduino development board. The project started as a school project on an 8051 development board but i soon figured out that this was way to slow. I am building the synth from an Arduino board and an 8bit R-2R DAC (plenty of circuits can be found at google).
The synth is based on the Direct Digital Synthesis method of producing waveforms digitally. I aim to get around 100Hz to ~4kHz operation out of it but im sure it is capable of frequencies up to around 50kHz. But this can be determined when the source has been verified and is working.
The source code for the Arduino has been written and attached below, but i have not verified it yet (my board is still in the mail). The DAC is intended to be connected to the Arduino board as follows:
Bit 0 (LSB) : Digital Pin 8
Bit 1 : Digital Pin 9
Bit 2 : Digital Pin 2
Bit 3 : Digital Pin 3
Bit 4 : Digital Pin 4
Bit 5 : Digital Pin 5
Bit 6 : Digital Pin 6
Bit 7 (MSB) : Digital Pin 7
I will provide more information and results when my board arrives
The source can be found by reading more
const byte SINE_TABLE[]=
{
0×80,0×83,0×86,0×89,0x8c,0x8f,0×92,0×95,0×98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0×98,0×95,0×92,0x8f,0x8c,0×89,0×86,0×83,
0×80,0x7c,0×79,0×76,0×73,0×70,0x6d,0x6a,0×67,0×63,0×60,0x5d,0x5a,0×57,0×54,0×51,
0x4f,0x4c,0×49,0×46,0×43,0×40,0x3e,0x3b,0×38,0×36,0×33,0×31,0x2e,0x2c,0x2a,0×27,
0×25,0×23,0×21,0x1f,0x1d,0x1b,0×19,0×17,0×15,0×13,0×12,0×10,0x0f,0x0d,0x0c,0x0a,
0×09,0×08,0×07,0×06,0×05,0×04,0×03,0×03,0×02,0×01,0×01,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×01,0×01,0×02,0×03,0×03,0×04,0×05,0×06,0×07,0×08,
0×09,0x0a,0x0c,0x0d,0x0f,0×10,0×12,0×13,0×15,0×17,0×19,0x1b,0x1d,0x1f,0×21,0×23,
0×25,0×27,0x2a,0x2c,0x2e,0×31,0×33,0×36,0×38,0x3b,0x3e,0×40,0×43,0×46,0×49,0x4c,
0x4f,0×51,0×54,0×57,0x5a,0x5d,0×60,0×63,0×67,0x6a,0x6d,0×70,0×73,0×76,0×79,0x7c
};const byte SAW_TABLE[]=
{
0×00,0×01,0×02,0×03,0×04,0×05,0×06,0×07,0×08,0×09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0×10,0×11,0×12,0×13,0×14,0×15,0×16,0×17,0×18,0×19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0×20,0×21,0×22,0×23,0×24,0×25,0×26,0×27,0×28,0×29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0×30,0×31,0×32,0×33,0×34,0×35,0×36,0×37,0×38,0×39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0×40,0×41,0×42,0×43,0×44,0×45,0×46,0×47,0×48,0×49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0×50,0×51,0×52,0×53,0×54,0×55,0×56,0×57,0×58,0×59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0×60,0×61,0×62,0×63,0×64,0×65,0×66,0×67,0×68,0×69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0×70,0×71,0×72,0×73,0×74,0×75,0×76,0×77,0×78,0×79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0×80,0×81,0×82,0×83,0×84,0×85,0×86,0×87,0×88,0×89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0×90,0×91,0×92,0×93,0×94,0×95,0×96,0×97,0×98,0×99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};const byte SQUARE_TABLE[]=
{
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};const byte TRIANGLE_TABLE[]=
{
0×00,0×02,0×04,0×06,0×08,0x0a,0x0c,0x0e,0×10,0×12,0×14,0×16,0×18,0x1a,0x1c,0x1e,
0×20,0×22,0×24,0×26,0×28,0x2a,0x2c,0x2e,0×30,0×32,0×34,0×36,0×38,0x3a,0x3c,0x3e,
0×40,0×42,0×44,0×46,0×48,0x4a,0x4c,0x4e,0×50,0×52,0×54,0×56,0×58,0x5a,0x5c,0x5e,
0×60,0×62,0×64,0×66,0×68,0x6a,0x6c,0x6e,0×70,0×72,0×74,0×76,0×78,0x7a,0x7c,0x7e,
0×80,0×82,0×84,0×86,0×88,0x8a,0x8c,0x8e,0×90,0×92,0×94,0×96,0×98,0x9a,0x9c,0x9e,
0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,
0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,
0xff,0xfd,0xfb,0xf9,0xf7,0xf5,0xf3,0xf1,0xef,0xef,0xeb,0xe9,0xe7,0xe5,0xe3,0xe1,
0xdf,0xdd,0xdb,0xd9,0xd7,0xd5,0xd3,0xd1,0xcf,0xcf,0xcb,0xc9,0xc7,0xc5,0xc3,0xc1,
0xbf,0xbd,0xbb,0xb9,0xb7,0xb5,0xb3,0xb1,0xaf,0xaf,0xab,0xa9,0xa7,0xa5,0xa3,0xa1,
0x9f,0x9d,0x9b,0×99,0×97,0×95,0×93,0×91,0x8f,0x8f,0x8b,0×89,0×87,0×85,0×83,0×81,
0x7f,0x7d,0x7b,0×79,0×77,0×75,0×73,0×71,0x6f,0x6f,0x6b,0×69,0×67,0×65,0×63,0×61,
0x5f,0x5d,0x5b,0×59,0×57,0×55,0×53,0×51,0x4f,0x4f,0x4b,0×49,0×47,0×45,0×43,0×41,
0x3f,0x3d,0x3b,0×39,0×37,0×35,0×33,0×31,0x2f,0x2f,0x2b,0×29,0×27,0×25,0×23,0×21,
0x1f,0x1d,0x1b,0×19,0×17,0×15,0×13,0×11,0x0f,0x0f,0x0b,0×09,0×07,0×05,0×03,0×01
};#define FREQ 2400
#define SAMP 65536 //2^16#include “TimerOne.h”
byte key;
byte wave;
byte x1;
byte y0;
byte y1;
byte m;
unsigned int phase;
unsigned int phaseDelta;
unsigned int note[] = {
0, 264,275,293.33,309.37,330,352,366.67,396,412.5,440.00,469.34,495};void setup()
{
//setup//portd (dac) setup
//portd uses digital pins 0 – 7
DDRD = DDRD | B11111100; //bits 2 – 7
DDRB = DDRB | B00000011; //bits 0 and 1//timer setup for 8khz (125us)
Timer1.initialize(125);
Timer1.attachInterrupt(Timer_ISR);//serial setup
Serial.begin(9600);
}void loop()
{
//main loop
if (Serial.available() > 0)
{
key = Serial.read();
}/*
COMAND STRUCTURE
Single byte commands are received my the uCbyte structure: xxyy zzzz
xx bits – command
- 00: note
: yy bits – octave
: zz bits – note
- 01: wave shape
: yy bits – wave shape
: zz bits – not used
- 10:
- 11:
*///note command
if(((key >> 6) & 0×03) == 0)
{
phaseDelta = calcPhaseDelta(note[key & 0x0F],(key >> 4) & 0×03);
}
if(((key >> 6) & 0×03) == 1)
{
wave = (key >> 4) & 0×03;
}}
void Timer_ISR()
{
//
byte index;phase += phaseDelta;
index = (byte)(phase>>8);if (wave == 0) //sine wave
{
x1 = SINE_TABLE[index];
}
else if (wave == 1) //saw tooth
{
x1 = SAW_TABLE[index];
}
else if (wave == 2) //square
{
x1 = SQUARE_TABLE[index];
}
else if (wave == 3) //triangle
{
x1 = TRIANGLE_TABLE[index];
}PORTD &= 0×03;
PORTD |= x1 & 0xFC;
PORTB &= 0xFC;
PORTB |= x1 & 0×03;
}unsigned int calcPhaseDelta(int note, byte oct)
{
//
unsigned int delta = 0;delta = (SAMP / FREQ) * note;
return delta;
}



0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
You must log in to post a comment.