This music synthesizer accepts user input via a keyboard using a PS/2 interface. The user has the ability to control two parameters: waveforms and octaves. Waveforms are generated by means of the direct digital synthesis algorithm. The user may select from six waveforms: sine, square, sawtooth, triangle, EKG, and sinc. The synthesizer covers the seven octaves present on an 88-key piano in addition to the two incomplete octaves for a total of nine octaves.

Dependencies:   mbed PS2

Files at this revision

API Documentation at this revision

Comitter:
lbaddam3
Date:
Mon Feb 28 16:55:00 2011 +0000
Commit message:

Changed in this revision

PS2.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbed_synth.c Show annotated file Show diff for this revision Revisions of this file
mbed_synth.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 175ad26d17ce PS2.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PS2.lib	Mon Feb 28 16:55:00 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/PS2/#a57bbbec16b1
diff -r 000000000000 -r 175ad26d17ce mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Feb 28 16:55:00 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
diff -r 000000000000 -r 175ad26d17ce mbed_synth.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_synth.c	Mon Feb 28 16:55:00 2011 +0000
@@ -0,0 +1,592 @@
+/***************************************************************************/
+/* mbed_synth.c                                                            */
+/*                                                                         */
+/* ----------------------------------------------------------------------- */
+/* This file defines the lookup tables for sine, square, sawtooth, reverse */
+/* reverse sawtooth, triangle, ekg, and sinc waveforms. This file also     */
+/* defines the functions needed to implement an interrupt-based DDS        */
+/* algorithm.                                                              */
+/*                                                                         */
+/* ----------------------------------------------------------------------- */
+/* The lookup tables are to be read based on the desired frequency by the  */
+/* user of the synthesizer (waveFreq). The waveFreq variable will be       */
+/* used to create what's known as a frequency tuning word (freqTun). This  */
+/* variable inn turn is used to increment the 32-bit phase accumulator     */
+/* (phaseAcc) every 40kHz generated by an interrupt.                       */
+/* The calculation of freqTun is as follows:                               */
+/*                                                                         */
+/*       freqTun = ((waveFreq * SAMP_NUM) * (SHFT_FCTR / SAMP_FREQ))       */
+/*                                                                         */
+/* In this instance, SAMP_NUM is 256, SAMP_FREQ is 40000 and the shift     */
+/* factor (SHFT_FCTR) is determined by setting the least significant bit   */
+/* of the lookup address to 1. As the top 8 bits of the phase accumulator  */
+/* serve as the lookup address. This means SHFT_FCTR must be equal to      */
+/* 0x01000000.                                                             */
+/*                                                                         */
+/* ----------------------------------------------------------------------- */
+/* Credit goes to John Luciani for his interrupt-based approach to the DDS */
+/* algorithm. It helped massively with this project!                       */
+/*                                                                         */
+/* Find more about John's project here:                                    */
+/* <http://wiblocks.luciani.org/docs/app-notes/nb1a-nco.html>              */
+/*                                                                         */
+/* Credit goes to Jesper Hansen for his wavetables (sine, square,          */
+/* sawtooth, reverse sawtooth, and triangle).                              */
+/*                                                                         */
+/* Find out more about Jesper's project here:                              */
+/* <http://www.myplace.nu/avr/minidds/index.htm>                           */
+/*                                                                         */
+/* Credit also goes to SPman for his modifications (ekg wavetable).        */
+/*                                                                         */
+/* Find out more about SPman's project here:                               */
+/* <http://www.scienceprog.com/avr-dds-signal-generator-v20/>              */
+/*                                                                         */
+/* ----------------------------------------------------------------------- */
+/* Author: Ron Grier, Lakshmi Baddam                                       */
+/* Target: nxp lpc1768                                                     */
+/*                                                                         */
+/***************************************************************************/
+#include "mbed_synth.h"
+
+/* Globals */
+volatile uint16_t waveFreq; // Frequency of waveform
+volatile uint32_t phaseAcc; // Used to store phase accumulators
+volatile uint32_t freqTun; // Frequency tuning words
+volatile uint8_t waveIndex; // Top 8 bits of phase accumulator
+const uint8_t *waveTable; // Ptr to wavetables
+Wave myWave = SAWTOOTH;
+volatile Bool rnd; // Rounding to next sample can reduce SNR
+volatile Bool sendVals; // When to send next value(s) to DAC(s) set by ISR
+volatile Bool waveChange; // Whether waveform has changed
+volatile Bool noise;
+volatile Wave newWave; // New waveform
+volatile Bool freqChange; // Whether frequency has changed
+volatile uint16_t newFreq; // New frequency
+volatile Bool noteOn = FALSE;
+Ticker synth_tick;
+AnalogOut synthPin(p18);
+PS2Keyboard ps2kb(p12, p11); // CLK, DAT
+int octave = 4; // Default to 4th octave
+
+/* Values for Sine Wave */
+const uint8_t sinVals[SAMP_NUM] = {
+  0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,
+  0x98,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,
+  0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
+  0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,
+  0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
+  0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,
+  0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
+  0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,
+  0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
+  0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,
+  0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
+  0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
+  0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,
+  0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
+  0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,
+  0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
+  0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,
+  0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c
+};
+
+/* Values for Square Wave */
+const uint8_t sqVals[SAMP_NUM] = {
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+  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
+};
+
+/* Values for Sawtooth Wave */
+const uint8_t sawVals[SAMP_NUM] = {
+  0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+  0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+  0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+  0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
+  0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+  0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
+  0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+  0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+  0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+  0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
+  0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+  0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
+  0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+  0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
+  0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
+  0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
+  0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+  0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+  0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+  0x98,0x99,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
+};
+
+/* Values for Reverse Sawtooth Wave */
+const uint8_t revSawVals[SAMP_NUM] = {
+  0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,
+  0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
+  0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,
+  0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,
+  0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,
+  0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,
+  0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,
+  0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0,
+  0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,
+  0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,
+  0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,
+  0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0,
+  0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,
+  0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90,
+  0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,
+  0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,
+  0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,
+  0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
+  0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,
+  0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
+  0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,
+  0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
+  0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,
+  0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
+  0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,
+  0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
+  0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,
+  0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
+  0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,
+  0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
+  0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,
+  0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
+};
+
+/* Values for Triangle Wave */
+const uint8_t triVals[SAMP_NUM] = {
+  0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,
+  0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
+  0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,
+  0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
+  0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,
+  0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
+  0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,
+  0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
+  0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,
+  0x90,0x92,0x94,0x96,0x98,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,0x99,0x97,0x95,0x93,0x91,
+  0x8f,0x8f,0x8b,0x89,0x87,0x85,0x83,0x81,
+  0x7f,0x7d,0x7b,0x79,0x77,0x75,0x73,0x71,
+  0x6f,0x6f,0x6b,0x69,0x67,0x65,0x63,0x61,
+  0x5f,0x5d,0x5b,0x59,0x57,0x55,0x53,0x51,
+  0x4f,0x4f,0x4b,0x49,0x47,0x45,0x43,0x41,
+  0x3f,0x3d,0x3b,0x39,0x37,0x35,0x33,0x31,
+  0x2f,0x2f,0x2b,0x29,0x27,0x25,0x23,0x21,
+  0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x11,
+  0x0f,0x0f,0x0b,0x09,0x07,0x05,0x03,0x01
+};
+
+/* Values for EKG Wave */
+const uint8_t ekgVals[SAMP_NUM] = {
+  0x49,0x4a,0x4b,0x4b,0x4a,0x49,0x49,0x49,
+  0x49,0x48,0x47,0x45,0x44,0x43,0x43,0x43,
+  0x44,0x44,0x43,0x41,0x3e,0x3d,0x3b,0x39,
+  0x38,0x37,0x37,0x36,0x36,0x36,0x37,0x37,
+  0x37,0x37,0x37,0x37,0x36,0x35,0x33,0x32,
+  0x31,0x31,0x34,0x3d,0x4d,0x65,0x84,0xa9,
+  0xcf,0xee,0xff,0xfe,0xea,0xc6,0x9a,0x6d,
+  0x44,0x25,0x11,0x05,0x00,0x01,0x06,0x0d,
+  0x14,0x1c,0x24,0x2d,0x34,0x39,0x3d,0x40,
+  0x41,0x42,0x43,0x44,0x44,0x45,0x46,0x47,
+  0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x48,
+  0x48,0x48,0x49,0x49,0x4a,0x4b,0x4b,0x4e,
+  0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,
+  0x56,0x58,0x5B,0x5D,0x60,0x62,0x64,0x66,
+  0x68,0x6b,0x6d,0x70,0x73,0x74,0x79,0x7b,
+  0x7d,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7e,
+  0x7d,0x7c,0x79,0x77,0x74,0x71,0x6d,0x69,
+  0x66,0x62,0x5f,0x5c,0x59,0x57,0x54,0x51,
+  0x4f,0x4d,0x4e,0x4b,0x4a,0x49,0x48,0x46,
+  0x45,0x44,0x43,0x43,0x43,0x44,0x44,0x44,
+  0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x46,
+  0x47,0x48,0x49,0x49,0x4a,0x4a,0x4b,0x4b,
+  0x4b,0x4b,0x4b,0x4b,0x4a,0x4a,0x49,0x49,
+  0x49,0x49,0x48,0x48,0x48,0x47,0x47,0x47,
+  0x47,0x47,0x47,0x47,0x46,0x46,0x46,0x45,
+  0x45,0x45,0x45,0x45,0x46,0x46,0x46,0x45,
+  0x44,0x44,0x43,0x43,0x43,0x43,0x42,0x42,
+  0x42,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
+  0x41,0x40,0x40,0x3f,0x3f,0x40,0x40,0x41,
+  0x41,0x41,0x41,0x41,0x41,0x41,0x40,0x40,
+  0x40,0x40,0x40,0x40,0x40,0x40,0x41,0x41,
+  0x41,0x42,0x43,0x44,0x45,0x47,0x48,0x49
+};
+
+/* Values for Sinc Wave */
+const uint8_t sincVals[SAMP_NUM] = {
+  0x2d,0x2f,0x31,0x32,0x32,0x32,0x31,0x30,
+  0x2e,0x2d,0x2b,0x2a,0x29,0x29,0x29,0x2a,
+  0x2c,0x2e,0x2f,0x31,0x32,0x33,0x33,0x32,
+  0x30,0x2e,0x2c,0x2a,0x29,0x28,0x28,0x28,
+  0x2a,0x2c,0x2e,0x30,0x32,0x33,0x34,0x34,
+  0x32,0x31,0x2e,0x2c,0x2a,0x28,0x27,0x27,
+  0x27,0x29,0x2b,0x2e,0x31,0x33,0x35,0x35,
+  0x35,0x33,0x31,0x2e,0x2b,0x28,0x26,0x25,
+  0x25,0x26,0x28,0x2b,0x2e,0x32,0x35,0x37,
+  0x38,0x37,0x35,0x32,0x2e,0x2a,0x26,0x23,
+  0x22,0x21,0x23,0x26,0x2a,0x2f,0x34,0x38,
+  0x3b,0x3c,0x3b,0x39,0x34,0x2e,0x28,0x22,
+  0x1e,0x1b,0x1b,0x1d,0x22,0x29,0x31,0x39,
+  0x41,0x46,0x48,0x47,0x42,0x3a,0x2e,0x21,
+  0x15,0x0a,0x02,0x00,0x04,0x0f,0x21,0x3a,
+  0x57,0x78,0x9a,0xba,0xd6,0xec,0xfa,0xff,
+  0xfa,0xec,0xd6,0xba,0x9a,0x78,0x57,0x3a,
+  0x21,0x0f,0x04,0x00,0x02,0x0a,0x15,0x21,
+  0x2e,0x3a,0x42,0x47,0x48,0x46,0x41,0x39,
+  0x31,0x29,0x22,0x1d,0x1b,0x1b,0x1e,0x22,
+  0x28,0x2e,0x34,0x39,0x3b,0x3c,0x3b,0x38,
+  0x34,0x2f,0x2a,0x26,0x23,0x21,0x22,0x23,
+  0x26,0x2a,0x2e,0x32,0x35,0x37,0x38,0x37,
+  0x35,0x32,0x2e,0x2b,0x28,0x26,0x25,0x25,
+  0x26,0x28,0x2b,0x2e,0x31,0x33,0x35,0x35,
+  0x35,0x33,0x31,0x2e,0x2b,0x29,0x27,0x27,
+  0x27,0x28,0x2a,0x2c,0x2e,0x31,0x32,0x34,
+  0x34,0x33,0x32,0x30,0x2e,0x2c,0x2a,0x28,
+  0x28,0x28,0x29,0x2a,0x2c,0x2e,0x30,0x32,
+  0x33,0x33,0x32,0x31,0x2f,0x2e,0x2c,0x2a,
+  0x29,0x29,0x29,0x2a,0x2b,0x2d,0x2e,0x30,
+  0x31,0x32,0x32,0x32,0x31,0x2f,0x2d,0x2d
+};
+
+/* Notes */
+const uint16_t notes[OCT_NUM][NOTE_NUM] = { // Array of Notes
+  {C_0, Cs_0, D_0, Ds_0, E_0, F_0, Fs_0, G_0, Gs_0, A_0, As_0, B_0},
+  {C_1, Cs_1, D_1, Ds_1, E_1, F_1, Fs_1, G_1, Gs_1, A_1, As_1, B_1},
+  {C_2, Cs_2, D_2, Ds_2, E_2, F_2, Fs_2, G_2, Gs_2, A_2, As_2, B_2},
+  {C_3, Cs_3, D_3, Ds_3, E_3, F_3, Fs_3, G_3, Gs_3, A_3, As_3, B_3},
+  {C_4, Cs_4, D_4, Ds_4, E_4, F_4, Fs_4, G_4, Gs_4, A_4, As_4, B_4},
+  {C_5, Cs_5, D_5, Ds_5, E_5, F_5, Fs_5, G_5, Gs_5, A_5, As_5, B_5},
+  {C_6, Cs_6, D_6, Ds_6, E_6, F_6, Fs_6, G_6, Gs_6, A_6, As_6, B_6},
+  {C_7, Cs_7, D_7, Ds_7, E_7, F_7, Fs_7, G_7, Gs_7, A_7, As_7, B_7},
+  {C_8, Cs_8, D_8, Ds_8, E_8, F_8, Fs_8, G_8, Gs_8, A_8, As_8, B_8}
+};
+
+/* Function Definitions */
+
+/**
+ * This function adds the frequency tuning word present @ index to the 
+ * phase accumulator present @ index.
+ *
+ * param: index - the channel number of oscillator
+ */
+//inline void acc_inc(const uint8_t index) {
+void acc_inc(void) {
+  phaseAcc += freqTun;
+}
+
+/**
+ * This function resets the phase accumulator for the oscillator present
+ * @ index. Should be called when switching frequencies.
+ *
+ * param: index - the channel number of oscillator
+ */
+//inline void acc_reset(const uint8_t index) {
+void acc_reset(void) {
+  phaseAcc = 0;
+}
+
+/**
+ * This function calculates the frequency tuning word of the oscillator
+ * present @ index.
+ *
+ * param: index - the channel number of oscillator
+ */
+//inline void set_wave(const Wave waveType, const uint8_t index) {
+void set_wave(const Wave waveType) {
+  switch(waveType) {
+  case SINE:
+    waveTable = sinVals;
+    break;
+  case SQUARE:
+    waveTable = sqVals;
+    break;
+  case SAWTOOTH:
+    waveTable = sawVals;
+    break;
+  case REV_SAWTOOTH:
+    waveTable = revSawVals;
+    break;
+  case TRIANGLE:
+    waveTable = triVals;
+    break;
+  case EKG:
+    waveTable = ekgVals;
+    break;
+  case SINC:
+    waveTable = sincVals;
+    break;
+  default:
+    break;
+  }
+}
+
+/**
+ * This function calculates the frequency tuning word of the oscillator
+ */
+void set_freq_tun(void) {
+  freqTun = ((((uint32_t)waveFreq) * SAMP_NUM) *
+            (SHFT_FCTR / SAMP_FREQ));
+}
+
+/**
+ * This function sets the frequency of the oscillator. In
+ * addition, this function calculates the corresponding frequency tuning word.
+ *
+ * param: freq - frequency of waveform
+ */
+//inline void set_freq(const uint16_t freq, const uint8_t index) {
+void set_freq(const uint16_t freq) {
+  acc_reset();
+  waveFreq = freq;
+  set_freq_tun();
+}
+
+/**
+ * This function sends the current waveform value for each channel
+ * to the appropriate output port. Checks are made to ensure frequency
+ * and waveform values are up to date.
+ */
+void send_vals(void) {
+    if (freqChange == TRUE) {
+      set_freq(newFreq); // Set new frequency
+      freqChange = FALSE; // Reset freqChange
+    }
+    
+    if (waveChange == TRUE) {
+      set_wave(newWave); // Set new waveform
+      waveChange = FALSE; // Reset waveChange
+    }
+    
+    acc_inc(); // Increment phase accumulator
+    waveIndex = phaseAcc >> 24; // Get address into wavetable    
+    
+    if (noteOn == TRUE)
+      synthPin = waveTable[waveIndex]/((float)(SAMP_NUM-1));
+}
+
+void init_synth(void) {
+  // Setup initial waveforms
+  acc_reset(); // Set all accumulators to 0 initially
+  set_wave(myWave); // Set all waveforms to sine wave
+  set_freq(notes[octave][A_NOTE]);
+  rnd = waveChange = freqChange = FALSE;
+}
+
+int main(void) {
+  PS2Keyboard::keyboard_event_t evt_kb;
+  init_synth(); // Initialize synth
+
+  int samp_us = 1.0/SAMP_FREQ*1e6; // Determine sample period in microseconds
+
+  synth_tick.attach_us(&send_vals, samp_us); // Call send_vals every samp_us
+  while (1) { // Loop here forever
+    // Process keys and determine which waveform, octave, and note should be
+    // played
+    if (ps2kb.processing(&evt_kb)) {
+      if (!evt_kb.type) {
+    switch(evt_kb.scancode[0]) {
+    case 0xe0:
+      switch(evt_kb.scancode[1]) {
+      case Right_key:
+        ++octave;
+        break;
+      case Left_key:
+        --octave;
+        break;
+      default:
+        printf("Invalid Octave Entry\n\r");
+        break;
+      }
+    case A_key:
+      set_freq(notes[octave][C_NOTE]);
+      noteOn = TRUE;
+      break;
+    case W_key:
+      set_freq(notes[octave][Cs_NOTE]);
+      noteOn = TRUE;
+      break;
+    case S_key:
+      set_freq(notes[octave][D_NOTE]);
+      noteOn = TRUE;
+      break;
+    case E_key:
+      set_freq(notes[octave][Ds_NOTE]);
+      noteOn = TRUE;
+      break;
+    case D_key:
+      set_freq(notes[octave][E_NOTE]);
+      noteOn = TRUE;
+      break;
+    case F_key:
+      set_freq(notes[octave][F_NOTE]);
+      noteOn = TRUE;
+      break;
+    case T_key:
+      set_freq(notes[octave][Fs_NOTE]);
+      noteOn = TRUE;
+      break;
+    case J_key:
+      set_freq(notes[octave][G_NOTE]);
+      noteOn = TRUE;
+      break;
+    case I_key:
+      set_freq(notes[octave][Gs_NOTE]);
+      noteOn = TRUE;
+      break;
+    case K_key:
+      set_freq(notes[octave][A_NOTE]);
+      noteOn = TRUE;
+      break;
+    case O_key:
+      set_freq(notes[octave][As_NOTE]);
+      noteOn = TRUE;
+      break;
+    case L_key:
+      set_freq(notes[octave][B_NOTE]);
+      noteOn = TRUE;
+      break;
+    case Sc_key:
+      if (octave < OCT_NUM-2) {
+        set_freq(notes[octave+1][C_NOTE]);
+        noteOn = TRUE;
+        break;
+      }
+    case Plus_key:
+      switch (myWave){
+        case SINE:
+          myWave = SQUARE;
+          break;
+        case SQUARE:
+          myWave = SAWTOOTH;
+          break;
+        case SAWTOOTH:
+          myWave = TRIANGLE;
+          break;
+        case TRIANGLE:
+          myWave = EKG;
+          break;
+        case EKG:
+          myWave = SINC;
+          break;
+        case SINC:
+          myWave = SINC;
+          break;
+        default:
+          break;
+      }
+      set_wave(myWave);
+      break;
+    case Minus_key:
+      switch (myWave){
+        case SINE:
+          myWave = SINE;
+          break;
+        case SQUARE:
+          myWave = SINE;
+          break;
+        case SAWTOOTH:
+          myWave = SQUARE;
+          break;
+        case TRIANGLE:
+          myWave = SAWTOOTH;
+          break;
+        case EKG:
+          myWave = TRIANGLE;
+          break;
+        case SINC:
+          myWave = EKG;
+          break;
+        default:
+          break;
+      }
+      set_wave(myWave);
+      break;
+    default:
+      printf("Invalid Key Entry\n\r");
+      break;
+    }
+      }
+      else {
+        noteOn = FALSE;
+      }
+      if (octave < 0)
+        octave = 0;
+      else if (octave > OCT_NUM-1)
+        octave = OCT_NUM-1;
+    }
+  }
+  
+  return 0;
+}
diff -r 000000000000 -r 175ad26d17ce mbed_synth.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_synth.h	Mon Feb 28 16:55:00 2011 +0000
@@ -0,0 +1,187 @@
+/***************************************************************************/
+/* mbed_synth.h                                                            */
+/*                                                                         */
+/* ----------------------------------------------------------------------- */
+/* Author: Ron Grier, Lakshmi Baddam                                       */
+/* Target: nxp lpc1768                                                     */
+/*                                                                         */
+/***************************************************************************/
+#ifndef MBED_SYNTH_H
+#define MBED_SYNTH_H
+
+#include "mbed.h"
+#include "PS2Keyboard.h"
+
+/* Macros */
+#define SAMP_FREQ   (40000.0) // Sampling frequency
+#define SAMP_NUM    (256) // Number of samples per wavetable
+#define SHFT_FCTR   (0x01000000) // Used to shift result of frequency
+                                 // tuning word to the top8 bits
+
+#define OCT_NUM  (9)
+#define NOTE_NUM (12)
+
+/* Declaration of Notes as Frequencies*/
+/////////////////
+#define C_0  (16)
+#define Cs_0 (17)
+#define D_0  (18)
+#define Ds_0 (19)
+#define E_0  (21)
+#define F_0  (22)
+#define Fs_0 (23)
+#define G_0  (25)
+#define Gs_0 (26)
+/////////////////
+#define A_0  (28)
+#define As_0 (29)
+#define B_0  (31)
+
+#define C_1  (33)
+#define Cs_1 (35)
+#define D_1  (37)
+#define Ds_1 (39)
+#define E_1  (41)
+#define F_1  (44)
+#define Fs_1 (46)
+#define G_1  (49)
+#define Gs_1 (52)
+#define A_1  (55)
+#define As_1 (58)
+#define B_1  (62)
+
+#define C_2  (65)
+#define Cs_2 (69)
+#define D_2  (73)
+#define Ds_2 (78)
+#define E_2  (82)
+#define F_2  (87)
+#define Fs_2 (93)
+#define G_2  (98)
+#define Gs_2 (104)
+#define A_2  (110)
+#define As_2 (117)
+#define B_2  (125)
+
+#define C_3  (131)
+#define Cs_3 (139)
+#define D_3  (147)
+#define Ds_3 (156)
+#define E_3  (165)
+#define F_3  (175)
+#define Fs_3 (185)
+#define G_3  (196)
+#define Gs_3 (208)
+#define A_3  (220)
+#define As_3 (233)
+#define B_3  (247)
+
+#define C_4  (262)
+#define Cs_4 (277)
+#define D_4  (294)
+#define Ds_4 (311)
+#define E_4  (330)
+#define F_4  (349)
+#define Fs_4 (367)
+#define G_4  (392)
+#define Gs_4 (415)
+#define A_4  (440)
+#define As_4 (466)
+#define B_4  (494)
+
+#define C_5  (523)
+#define Cs_5 (554)
+#define D_5  (587)
+#define Ds_5 (622)
+#define E_5  (659)
+#define F_5  (698)
+#define Fs_5 (740)
+#define G_5  (784)
+#define Gs_5 (831)
+#define A_5  (880)
+#define As_5 (932)
+#define B_5  (988)
+
+#define C_6  (1047)
+#define Cs_6 (1109)
+#define D_6  (1175)
+#define Ds_6 (1245)
+#define E_6  (1319)
+#define F_6  (1397)
+#define Fs_6 (1480)
+#define G_6  (1568)
+#define Gs_6 (1661)
+#define A_6  (1760)
+#define As_6 (1865)
+#define B_6  (1976)
+
+#define C_7  (2093)
+#define Cs_7 (2218)
+#define D_7  (2349)
+#define Ds_7 (2489)
+#define E_7  (2637)
+#define F_7  (2794)
+#define Fs_7 (2960)
+#define G_7  (3136)
+#define Gs_7 (3322)
+#define A_7  (3520)
+#define As_7 (3729)
+#define B_7  (3951)
+
+#define C_8  (4186)
+///////////////////
+#define Cs_8 (4435)
+#define D_8  (4698)
+#define Ds_8 (4978)
+#define E_8  (5274)
+#define F_8  (5588)
+#define Fs_8 (5920)
+#define G_8  (6272)
+#define Gs_8 (6645)
+#define A_8  (7040)
+#define As_8 (7459)
+#define B_8  (7902)
+///////////////////
+
+/* Keyboard Bindings */
+#define KEY_ON  (0x0)
+#define KEY_OFF (0x1)
+
+#define A_key     (0x1c)
+#define S_key     (0x1b)
+#define D_key     (0x23)
+#define F_key     (0x2b)
+#define J_key     (0x3b)
+#define K_key     (0x42)
+#define L_key     (0x4b)
+#define Sc_key    (0x4c)
+#define W_key     (0x1d)
+#define E_key     (0x24)
+#define T_key     (0x2c)
+#define I_key     (0x43)
+#define O_key     (0x44)
+#define Left_key  (0x6b)
+#define Right_key (0x74)
+#define Minus_key (0x4e)
+#define Plus_key  (0x55)
+
+#define C_NOTE  (0x0)
+#define Cs_NOTE (0x1)
+#define D_NOTE  (0x2)
+#define Ds_NOTE (0x3)
+#define E_NOTE  (0x4)
+#define F_NOTE  (0x5)
+#define Fs_NOTE (0x6)
+#define G_NOTE  (0x7)
+#define Gs_NOTE (0x8)
+#define A_NOTE  (0x9)
+#define As_NOTE (0xA)
+#define B_NOTE  (0xB)
+
+/* Typedefs and Enums */
+typedef enum _wave {SINE, SQUARE, SAWTOOTH,
+            REV_SAWTOOTH, TRIANGLE, EKG,
+            SINC, NOISE} Wave;
+typedef enum _bool {FALSE, TRUE} Bool;
+
+#endif // MBED_SYNTH_H