Introduction

Theory

Hardware

Software

Design/ Testing

Conclusion

Appendix

References

MCU Synthesizer
Appendixs
  • Appendix with cost details with all part numbers and their price. This cost will include components as described in the Budget Considerations section.

 

Appendix I - Cost

Item Quantity Cost
Mega32 1 $0.00 donated by Marcelo Garza(last semester project)
custom PC board 1 $5
6N138 optoisolator 1 $1 digikey
10KOhm Potentiometers 4 $1.00 allelectronics
LCD 1 $8.00 lab
3904 npn BJT 1 $0.00 lab
project box 1 $0.00 previous year box
audio out jack 1 $0.00 previous year box
midi Din-5 connector 1 $0.00 previous year box
assorted resistors 10+ $0.00 lab
assorted capacitors 2+ $0.00 lab
midi keyboard 1 $0 Donated by TA(Idan)
speaker 1 $0 Previously Owned
push buttons 3 $0 Previously year box
Total $15

 

Appendix II - Logic Diagram

Appendix III - Schematic

 

Appendix IV - Division of Task

Min:

DDS Code
Main State machines
Filtering
Waveform Creation/operation
H halftone coding
Demo Songs coding

Franco:

Midi Keyboard to MPU interface
Midi signal Decoding algorithm
Box/Board/Potentiometers/Push button creation.
LCD interface

Appendix V - Code

#include <Mega32.h>
#include <delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h> // for sine

//I like these definitions
#define begin {
#define end }
#define countMS 8 //ticks/mSec
#define IncAdjust 8.3886
#define oscNUM 8
#define keysize 49

#define A 440
#define Asharp 466.1637
#define B 493.8833
#define C 523.2511
#define Csharp 554.3652
#define D 587.3295
#define Dsharp 622.2540
#define E 659.2551
#define F 698.4565
#define Fsharp 739.9888
#define G 783.9909
#define Gsharp 830.6094

//Notes State Machine
//#define wait 0
//#define playnote 1

//Settings State Machine
//settingstate

#define ADSR 0
#define osc1 1
#define osc2 2
#define operator 3
#define special 4

//Operator State
#define off 0
#define add 1
#define subtract 2
#define multiply 3

//Wavestate
//#define off 0
#define sinewave 1
#define triwave 2
#define squarewave 3
#define sawwave 4

//SpecialState
#define demo 0
#define freqshift 1
#define filter 2

//filterstate
//#define off
#define highpass 1
#define lowpass 2

//Envelope State Machine
#define getAttack 0
#define getDecay 1
#define getSustain 2
#define getRelease 3

//which byte is being read in from uart
//midi sends 3 bytes per message, status byte, note byte, velocity byte
#define status_byte 0
#define note_byte 1
#define vel_byte 2

//fixedpoint math
#define float2fix(a) ((int)((a)*256.0))
#define fix2float(a) ((float)(a)/256.0)
#define int2fix(a) (((int)(a))<<8) //Convert char to fix. a is a char
#define fix2int(a) ((signed char)((a)>>8)) //Convert fix to char. a is an int

//initialize LCD
#asm
.equ __lcd_port=0x15
#endasm
#include <lcd.h> // LCD driver routine

char lcd_buffer[17]; // LCD display buffer

//IIR stuff
#pragma regalloc-
int alpha, yn_1 ;
#pragma regalloc+

#pragma regalloc-
int b1,a2,a3,xn, xn_1, xn_2, yn, yn_2 ;
#pragma regalloc+
// int Butter2low(int);
int Butter2high(int);
void PrintSpecialType(char);
void PrintOperatorType(char);//Print Operator to LCD
void PrintWaveType(char);//Print Wave type to LCD
void updatewave(void);
int multfix(int,int); //fast fixpoint mult
void initialize(void); //all the usual mcu stuff
void setting_state_machine(void); //notes state machine
void envelope_state_machine(void); //envelope state machine
int OnePoleLow(int);

unsigned int attack, decay, release;
unsigned int attack_old, decay_old, release_old, sustain_old;
unsigned int time[8], sustain[8], increment[8];
unsigned char sustain_flag ;
int sustainamp_fix;
float sustainamp_float;
int amp[8];

flash float keyboard[keysize] = {C/8,Csharp/8,D/8,Dsharp/8,E/8,F/8,Fsharp/8,G/8,Gsharp/8,A/4,Asharp/4,B/4,
C/4,Csharp/4,D/4,Dsharp/4,E/4,F/4,Fsharp/4,G/4,Gsharp/4,A/2,Asharp/2,B/2,
C/2,Csharp/2,D/2,Dsharp/2,E/2,F/2,Fsharp/2,G/2,Gsharp/2,A,Asharp,B,
C,Csharp,D,Dsharp,E,F,Fsharp,G,Gsharp,A*2,Asharp*2,B*2, C*2};

//general counters
unsigned int i, ii , j;

//Oscillator Variables
unsigned char count, oscReady, oscCounter;
int songcounter, songtimer;
unsigned char restcounter;
int hitamp[8];
unsigned char Held[keysize];

 

//envelope state machine variables
unsigned char envelopestate_timer;
unsigned char envelopestate;

//filter variables
unsigned char filterflag;
int yn_temp[8];

//Setting State Machine Variables
unsigned char settingstate, ADSRdisplay, operatorstate, specialstate, demostate, filterstate;
signed char freqshiftstate;
unsigned char oscstate[2];
unsigned char settingstate_timer;
unsigned char debounce0, debounce1, debounce2;

//buffers and temps
signed int wavebuffer;
signed int tempwave[2];

//Midi decoder Variables
unsigned char velocity_array[keysize];
unsigned char status,note; //the 3 bytes of a midi message
unsigned char current_byte; //byte currently being read in the rxc interrupt

//floating point shortcuts
int amp_temp;
int pointone_fix = float2fix(.1);
int sustainamp_ten_int;
unsigned int accumulator[8] @0x5f0;
unsigned char highbyte[16] @0x5f0;
/*
unsigned char highbyte0 @0x5f1; //the HIGH byte of the accumulator variable
unsigned char highbyte1 @0x5f3; //the HIGH byte of the accumulator variable
unsigned char highbyte2 @0x5f5; //the HIGH byte of the accumulator variable
unsigned char highbyte3 @0x5f7; //the HIGH byte of the accumulator variable
unsigned char highbyte4 @0x5f9; //the HIGH byte of the accumulator variable
unsigned char highbyte5 @0x5fb; //the HIGH byte of the accumulator variable
unsigned char highbyte6 @0x5fd; //the HIGH byte of the accumulator variable
unsigned char highbyte7 @0x5ff; //the HIGH byte of the accumulator variable
*/
signed int finalwave[256] @0x600; //need loc to avoid glitch
eeprom signed int sineTable[256] = {0};
//eeprom int squareTable[256] = {0};
//eeprom signed int triTable[256] = {0};
//mary had a little lamb
//float song[] = {E,D,C,D,E,E,E,D,D,D,E,G,G,E,D,C,D,E,E,E,D,D,E,D,C};

//twinkle twinkle little start
//float song[] = {C,C,G,G,A*2,A*2,G, 0,F,F,E,E,D,D,C,0,G,G,F,F,E,E,D,0,G,G,F,F,E,E,D,0,C,C,G,G,A*2,A*2,G,0,F,F,E,E,D,D,C,0};

//canon
flash float canon[] = {A*2,0, Fsharp, G, A*2,0,Fsharp, G, A*2,A,B,Csharp,D,E,Fsharp,G,Fsharp,0,D,E,Fsharp,0,Fsharp/2,G/2,A,B,A,G/2,A,Fsharp/2,G/2,A,G/2,0,B,A,G/2,0,Fsharp/2,E/2,Fsharp/2,E/2,D/2,E/2,Fsharp/2,G/2,A,B,A,0,B,A,B,0,Csharp,D,A,B,Csharp,D,E,Fsharp,G,A*2,Fsharp,0,D,E,Fsharp,0,E,D,E,Csharp,D,E,Fsharp,E,D,Csharp,D,0,B,Csharp,D,0,D/2,E/2,Fsharp/2,G/2,Fsharp/2,E/2,Fsharp/2,D,Csharp,D,B,0,D,Csharp,B,0,A,G/2,A,G/2,Fsharp/2,G/2,A,B,Csharp,D,B,0,D,Csharp,D,0,Csharp,B,Csharp,D,E,D,Csharp,D,B,Csharp,64000};

//mario
//float canon[] = {E,E,0,E,0,C,E,0,G,0,0,0,G/2,0,0,0,C,0,G/2,0,E/2,0,A,0,B,0,Asharp,A,0,G/2,E,G,A*2,0,F,G,0,E,0,C,D,B, 64000};

//row row row your boat round
flash float row1[] ={0,C,0,0,C,0,0,C,0,D,E,0,0,E,0,D,E,0,F,G,0,0,0,0,0,C*2,C*2,C*2,G,G,G,E,E,E,C,C,C,G,0,F,E,0,D,C,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64000};
flash float row2[] ={0,0,0,0,0,0,0,0,0,0,0,0,0,C,0,0,C,0,0,C,0,D,E,0,0,E,0,D,E,0,F,G,0,0,0,0,0,C*2,C*2,C*2,G,G,G,E,E,E,C,C,C,G,0,F,E,0,D,C,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64000};
flash float row3[] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,C,0,0,C,0,0,C,0,D,E,0,0,E,0,D,E,0,F,G,0,0,0,0,0,C*2,C*2,C*2,G,G,G,E,E,E,C,C,C,G,0,F,E,0,D,C,0,0,0,0,0,64000};

//multi notes
//flash float poly1[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Fsharp,0,E,0,D,0,Csharp,0,B,0,A,0,B,0,Csharp,0,D,0,Csharp,0,B,0,A,0,G/2,0,Fsharp/2,0,G/2,0,E/2,0, D/2,Fsharp/2,A,G/2,Fsharp/2,D/2,Fsharp/2,E/2,D/2,B/2,D/2, A,G/2, B,A,G/2,Fsharp/2,D/2,E/2,Csharp,D,Fsharp, A*2,A,64000};
//flash float poly2[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Fsharp,0,E,0,D,0,Csharp,0,B,0,A,0,B,0,Csharp,0,D,0,Csharp,0,B,0,A,0,G/2,0,Fsharp/2,0,G/2,0,E/2,0, D/2,Fsharp/2,A,G/2,Fsharp/2,D/2,Fsharp/2,E/2,64000};
//flash float poly3[] = {B,0,Fsharp/2,0,G/2,0,D/2,0,E/2,0,B/2,0,E/2,0,Fsharp/2,0,B,0,Fsharp/2,0,G/2,0,D/2,0,E/2,0,B/2,0,E/2,0,Fsharp/2,0,B/2,0,Fsharp/2,0,G/2,0,D/2,0,E/2,0,B/2,0,E/2,0,Fsharp/2,0,B,0,E/2,0,G/2,0,D/2,0,E/2,0,B/2,0,E/2,0,Fsharp/2,0,B/2,0,Fsharp/2,0,G/2,0,D/2,0,64000};
flash float poly1[] ={E, Dsharp, E, Dsharp, E, B, D, C, A, 0, 1, C/2, E/2, A, B, 0 , 1, E/2, Gsharp/2, B, C,0, 1, E/2, E, Dsharp, E, Dsharp,
E, B, D, C, A, 0, 1, C/2, E/2, A, B, 0 , 1, E/2, C, B, A,0, 0,0, E, Dsharp, E, Dsharp, E, B, D, C,
A, 0, 1, C/2, E/2, A, B, 0 , 1, E/2, Gsharp/2, B, C,0, 1, E/2, E, Dsharp, E, Dsharp, E, B, D, C, A, 0, 1, C/2, E/2, A,
B, 0 , 1, E/2, C, B, A,0, 1, B, C, D,
E, 0, 0 , G/2, F,E,D,0,0,F/2, E,D,C,0,0,E/2,D,C,B,0, 1, E/2, E, 1, 1, E, E*2,1, 1,1, Dsharp,0, E, 1,1, Dsharp, E, Dsharp,
E, Dsharp, E, B, D, C, A, 0, 1, C/2, E/2, A, B, 0, 1, E/2, Gsharp/2, B, C, 0, 1, E/2,E, Dsharp, E, Dsharp, E, B, D, C,
A, 0, 1, C/2, E/2, A, B, 0 , 1, E/2, C, B, A, 0 , 0, 0, 0 ,0,0,0,64000};
flash float poly2[] ={1,1,1,1,1,1,1,1,A/4, E/4, A/2, 1, 1, 1, E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
A/4, E/4, A/2, 1, 1, 1,E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/2, 1,1,1,1,1,1,1,1,1,A/4, E/4, A/2, 1, 1, 1, E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
A/4, E/4, A/2, 1, 1, 1,E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, C/4, G/4,C/2, 1, 1, 1,
G/8, G/4, B/2, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, E/8, E/4, E/2, 1, 1, E/2, E, 1, 1, Dsharp, E,0, 1,1,1, Dsharp,E, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/2, 1, 1, 1, 1, 1, 1, 1, 1,
A/4, E/4, A/2, 1, 1, 1, E/8, E/4, Gsharp/4, 1, 1, 1, A/4, E/4, A/4, 0, 0, 0,0,0};
//flash float poly3[] ={0};

//float song[3] = {Asharp, 440, 440};

//frequencyshift table
flash float shift[25] ={.5, .529732, .561231, .594604, .629961, .66742, .707107, .749154, .793701, .840896, .890899, .943874, 1, //shiftdown (12-1)twelthroot(2)
1.05946, 1.12246, 1.18921, 1.25992, 1.33484, 1.41421, 1.49831, 1.5874, 1.68179, 1.7818, 1.88775, 2}; //shiftup (1-12)twelthroot(2)

 

//interrupt [TIM0_OVF] void sgen(void)
interrupt [TIM1_COMPA] void timer1_compareA(void)
begin


//the DDR code and scaling
wavebuffer = 0;

//update Accumulators
accumulator[0] = accumulator[0] + increment[0];
accumulator[1] = accumulator[1] + increment[1];
accumulator[2] = accumulator[2] + increment[2];
accumulator[3] = accumulator[3] + increment[3];
accumulator[4] = accumulator[4] + increment[4];
accumulator[5] = accumulator[5] + increment[5];
accumulator[6] = accumulator[6] + increment[6];
accumulator[7] = accumulator[7] + increment[7];
/*
if(increment[0]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[1]],amp[0]);
if(increment[1]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[3]],amp[1]);
if(increment[2]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[5]],amp[2]);
if(increment[3]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[7]],amp[3]);
if(increment[4]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[9]],amp[4]);
if(increment[5]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[11]],amp[5]);
if(increment[6]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[13]],amp[6]);
if(increment[7]) wavebuffer = wavebuffer + multfix(finalwave[highbyte[15]],amp[7]);
*/

//setup accumulators
if(increment[0])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[1]],amp[0]),hitamp[0]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[0];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[1]])>>(amp[0])));
yn_temp[0] = yn_1;
break;
end
end
if(increment[1])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[3]],amp[1]),hitamp[1]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[1];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[3]])>>(amp[1])));
yn_temp[1] = yn_1;
break;
end
end

if(increment[2])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[5]],amp[2]),hitamp[2]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[2];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[5]])>>(amp[2])));
yn_temp[2] = yn_1;
break;
end
end
if(increment[3])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[7]],amp[3]),hitamp[3]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[3];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[7]])>>(amp[3])));
yn_temp[3] = yn_1;
break;
end
end
if(increment[4])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[9]],amp[4]),hitamp[4]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[4];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[9]])>>(amp[4])));
yn_temp[4] = yn_1;
break;
end
end
if(increment[5])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[11]],amp[5]),hitamp[5]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[5];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[11]])>>(amp[5])));
yn_temp[5] = yn_1;
break;
end
end
if(increment[6])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[13]],amp[6]),hitamp[6]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[6];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[13]])>>(amp[6])));
yn_temp[6] = yn_1;
break;
end
end
if(increment[7])
begin
switch(filterstate)
begin
case off:
wavebuffer = wavebuffer + multfix(multfix(finalwave[highbyte[15]],amp[7]),hitamp[7]);
break;
case highpass:
break;
case lowpass:
yn_1 = yn_temp[7];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[15]])>>(amp[7])));
yn_temp[7] = yn_1;
break;
end
end

//output wave
OCR0 = (char)(fix2int(wavebuffer)) + 128;
/*
for (i = 0; i <8; i++)
begin
accumulator[i] = accumulator[i] + increment[i];
end

//finalamp = 0;

for (i = 0; i <8; i++)
begin
//accumulator[i] = accumulator[i] + increment[i];
if(increment[i])
begin

wavebuffer = wavebuffer + ((finalwave[highbyte[i*2 + 1]]>>(amp[i])));
finalamp++;
end
end

//Oscilators

if(filterflag)
begin
yn_1 = yn_temp[i];
wavebuffer = wavebuffer + ((OnePoleLow(finalwave[highbyte[i*2 + 1]])>>(amp[i])));
yn_temp[i] = yn_1;
end
else */

//generate rising amplitude
// 8 counts is about 1 mSec
count--;
if (0 == count )
begin
count=countMS;
for(i = 0; i < 8; i++)
begin
time[i]++;
// sustain[ii]++;
end
if (songtimer>0) --songtimer;
if (settingstate_timer>0) --settingstate_timer;
if (envelopestate_timer>0) --envelopestate_timer;
end
end
/*****************************************
Recieve Interrupt
Recieve Notes From Midi Controller
*****************************************/
interrupt [USART_RXC] void uart_rec(void)
begin

 

//collect the proper byte of a midi message
switch (current_byte)
begin

case status_byte:
status = UDR;
if(((status & 0xF0) == 0x90)) //read the 1st byte of a message
begin
current_byte = note_byte;
//PORTC.1 = 1;
end
/*
else if( (status & 0xF0) != 0xE0)
begin
note = status;
current_byte = vel_byte;
//PORTC.1 = 1;
end
*/
/*
else if( (status & 0xF0) == 0xE0)
begin
//PORTC.1 = 0;
end
*/
break;
case note_byte: //read the 2nd byte of a message
note = UDR;
if((note & 0xF0) == 0x90)current_byte = note_byte;
else if(note & 0x80) current_byte = status_byte;
else current_byte = vel_byte;

break;
case vel_byte: //read the 3rd byte of a message
//if(velocity_array[note - 36] == 0)
velocity_array[note - 36] = UDR;
//else velocity_array[note - 36] = 0;
// for(ii = 0; ii < keysize; ii++)
// begin
//ii = 24;
// if(~PINC & (0b00000001<<ii))

//if(velocity_array[ii] != 0)

//find note
if(velocity_array[note - 36] != 0)
begin
if(Held[note - 36] == 9)
begin
time[oscCounter] = 0;
hitamp[oscCounter] = float2fix((float)velocity_array[note - 36]/127);
increment[oscCounter] = (int)((float)keyboard[note - 36]*IncAdjust);
sustain_flag = sustain_flag | (0b00000001 << oscCounter);//ready now
sustain[oscCounter] = 0;
Held[note - 36] = oscCounter;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end

if(freqshiftstate && oscReady)
begin

time[oscCounter] = 0;
hitamp[oscCounter] = float2fix((float)velocity_array[note - 36]/127);
increment[oscCounter] = (int)((float)keyboard[(signed int)(note - 36 + freqshiftstate)]*IncAdjust);
sustain_flag = sustain_flag | (0b00000001 << oscCounter);//ready now
sustain[oscCounter] = 0;
Held[(signed int)(note - 36 + freqshiftstate)] = oscCounter;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end
end
end
else
begin
sustain_flag = sustain_flag & ~(0b00000001 << Held[note-36]);
Held[note-36] = 9;
end
//end
current_byte = note_byte;
//PORTC = ~note;
break;

end

end
/*****************************************
Main Function
*****************************************/
void main(void)
begin

initialize();

while(1)
begin
if (settingstate_timer==0) setting_state_machine();
if (envelopestate_timer==0) envelope_state_machine();

// attack = 200 ;

// ii = 0;
// if((time[ii] == ((int)(10*fix2float(amp[ii])) + 1)*(attack/10)) && (amp[ii]<float2fix(1))) amp[ii]= amp[ii] + float2fix(.1);
/* if((time[ii] == (attack + (11 - (int)(10*fix2float(amp[ii])))*(decay/((int)(10*fix2float(float2fix(1) - sustainamp_fix)))))) && (amp[ii]>(sustainamp_fix))) amp[ii]= amp[ii] - float2fix(.1);
if((time[ii] == (attack + decay + sustain[ii] + ((int)(10*fix2float(sustainamp_fix - amp[ii])) + 1)*(release/((int)(10*fix2float(sustainamp_fix)))))) && (amp[ii]>float2fix(0))) amp[ii]= amp[ii] - float2fix(.1);
if(time[ii] >= (attack + decay + sustain[ii] + release))//end note
begin
increment[ii]= 0;
oscReady = oscReady | (0b00000001 << ii);//ready now
amp[ii] = float2fix(0);
end
*/

//ii = 0;

//if (~(sustain_flag | ~(0b00000001 << ii)) == 0) sustain[ii]++;
// sustain[ii] = 1000;

 

for (ii = 0; ii <8; ii++)//check all 8 channels
begin

amp_temp = (int)(10*fix2float(amp[ii]));//fix2float(amp[ii]);

if(time[ii] <= attack)
begin
if((time[ii] >= (amp_temp + 1)*(attack/10))
&& (time[ii] <= (amp_temp + 2)*(attack/10))
&& (amp[ii]<float2fix(1))) amp[ii]= amp[ii] + pointone_fix;
end
else if(time[ii] <= (attack + decay))
begin
if((time[ii] >= (attack + (11 - amp_temp)*(decay/(10 - sustainamp_ten_int))))
&& (time[ii] <= (attack + (12 - amp_temp)*(decay/(10 - sustainamp_ten_int))))
&& (amp[ii]>(sustainamp_fix))) amp[ii]= amp[ii] - pointone_fix;
end
else if(time[ii] <= (attack + decay + sustain[ii] + release))
begin
if((time[ii] >= (attack + decay + sustain[ii] + (sustainamp_ten_int - amp_temp + 1)*(release/(sustainamp_ten_int))))
&& (time[ii] <= (attack + decay + sustain[ii] + (sustainamp_ten_int - amp_temp + 2)*(release/(sustainamp_ten_int))))
&& (amp[ii]>0)) amp[ii]= amp[ii] - pointone_fix;
end
else
// if(time[ii] >= (attack + decay + sustain[ii] + release))
begin
increment[ii]= 0;
oscReady = oscReady | (0b00000001 << ii);//ready now
amp[ii] = float2fix(0);
hitamp[ii] = int2fix(1);
sustain[ii] = 0;
end

/*
amp_temp = fix2float(amp[ii]);
// if(time[ii] <= attack)
// begin
if((time[ii] == (amp_temp + 1)*(attack/10)) && (amp[ii]<float2fix(1))) amp[ii]= amp[ii] + pointone_fix;
// end
// else if(time[ii] <= (attack + decay))
// begin
if((time[ii] == (attack + (11 - amp_temp)*(decay/((int)(10*(1 - sustainamp_float)))))) && (amp[ii]>(sustainamp_fix))) amp[ii]= amp[ii] - pointone_fix;
// end
// else if(time[ii] <= (attack + decay + sustain[ii] + release))
// begin
if((time[ii] == (attack + decay + sustain[ii] + ((int)(10*(sustainamp_float - amp_temp)) + 1)*(release/((int)(10*(sustainamp_float)))))) && (amp[ii]>0)) amp[ii]= amp[ii] - pointone_fix;
// end
// else
if(time[ii] >= (attack + decay + sustain[ii] + release))
begin
increment[ii]= 0;
oscReady = oscReady | (0b00000001 << ii);//ready now
amp[ii] = float2fix(0);
end
*/

end


//Song Generator
if(songtimer == 0)
begin

switch(demostate)
begin

case 1://song 1
songtimer = 300;
increment[oscCounter] = (int)((float)(canon[songcounter])*IncAdjust);
while(canon[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;

time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(canon[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(canon[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end

songcounter++;
if (canon[songcounter] == 64000)songcounter = 0;
break;
case 2: //song 2
songtimer = 250;
increment[oscCounter] = (int)((float)(poly1[songcounter])*IncAdjust);
while(poly1[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(poly1[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(poly1[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end


increment[oscCounter] = (int)((float)(poly2[songcounter])*IncAdjust);
while(poly2[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end

if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(poly2[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(poly2[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end

/* increment[oscCounter] = (int)((float)(poly3[songcounter])*IncAdjust);
while(poly3[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end


if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(poly3[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(poly3[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end
*/
songcounter++;
if (poly1[songcounter] == 64000)demostate = off;
break;
case 3://song 3
songtimer = 250;
increment[oscCounter] = (int)((float)(row1[songcounter]/2)*IncAdjust);
while(row1[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(row1[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(row1[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end

increment[oscCounter] = (int)((float)(row2[songcounter])*IncAdjust);
while(row2[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end


if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(row2[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(row2[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end

increment[oscCounter] = (int)((float)(row3[songcounter]*2)*IncAdjust);
while(row3[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end

if((freqshiftstate != 0) && oscReady)
begin
increment[oscCounter] = (int)((float)(row3[songcounter])*shift[(signed int)(12 + freqshiftstate)]*IncAdjust);
while(row3[songcounter+restcounter + 1] == 0 )
begin
restcounter++;
end
sustain[oscCounter] = songtimer*restcounter;
restcounter = 0;
time[oscCounter] = 0;
oscReady = oscReady & ~(0b00000001 << oscCounter);//turn off
while(~(oscReady | ~(0b00000001 << oscCounter)))
begin
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
if (oscReady == 0) break;
end
end

songcounter++;
if(row1[songcounter] == 64000) demostate = off;
break;
end
// sustain[oscCounter] = 500;
// oscCounter++;
/*
if (oscCounter > 7) oscCounter = 0;
increment[oscCounter] = (int)((float)(song[songcounter])*IncAdjust);
time[oscCounter] = 0;//25;
// sustain[oscCounter] = 250;
oscCounter++;
if (oscCounter > 7) oscCounter = 0;
increment[oscCounter] = (int)((float)(song[songcounter]*2)*IncAdjust);
time[oscCounter] = 0;
sustain[oscCounter] = 0;
*/

// increment[1] = (int)((float)(song2[songcounter])*IncAdjust);
//increment[2] = (int)((float)(song3[songcounter]*2)*IncAdjust);
// increment2 = (int)((float)(song[songcounter]*2)*IncAdjust);
// increment2 = (int)((float)(song[songcounter])*IncAdjust);
// increment3 = (int)((float)(song[songcounter])*IncAdjust);

end



 

// if (time==34) TCCR0=0b00000001 ;

end // end while
end //end main

//***************************************************
//Fast fixed multiply
//***************************************************
int multfix(int a,int b)
begin
#asm
;******************************************************************************
;*
;* FUNCTION
;* muls16x16_24
;* DECRIPTION
;* Signed multiply of two 16bits numbers with 24bits result.
;* USAGE
;* r31:r30:rxx = r23:r22 * r21:r20

;******************************************************************************
push r20
push r21

LDD R22,Y+2 ;load a
LDD R23,Y+3

LD R20,Y ;load b
LDD R21,Y+1

muls r23, r21 ; (signed)ah * (signed)bh
mov r31, r0 ;r18, r0
mul r22, r20 ; al * bl
mov r30, r1 ;movw r17:r16, r1:r0
;mov r16, r0
mulsu r23, r20 ; (signed)ah * bl
add r30, r0 ;r17, r0
adc r31, r1 ;r18, r1
mulsu r21, r22 ; (signed)bh * al
add r30, r0 ;r17, r0
adc r31, r1 ;r18, r1

pop r21
pop r20
#endasm
end
/*****************************************
One Pole Lowpass filter
*****************************************/
int OnePoleLow(int xx)
// xx is the current input signal sample
// returns the current filtered output sample
begin
#asm
.macro mult_acc ;r31:r30:r24 += r23:r22 * r21:r20
muls r23, r21 ; (signed)ah * (signed)bh
add r31, r0
mul r22, r20 ; al * bl
add r24, r0
adc r30, r1
adc r31, r27
mulsu r23, r20 ; (signed)ah * bl
add r30, r0
adc r31, r1
mulsu r21, r22 ; (signed)bh * al
add r30, r0
adc r31, r1
.endm

push r20 ;save parameter regs
push r21

clr r27 ;permanent zero
clr r24 ;clear 24 bit result reg; msb to lsb => r31:r30:r24

ld R30, Y ;load input parameter xx from stack
ldd R31, Y+1 ; and put in result location

lds R20, _yn_1 ;load y(n-1) from RAM
lds R21, _yn_1+1
sub r20, r30 ;form y(n-1) - xx
sbc r21, r31
lds R22, _alpha ;load alpha from RAM
lds R23, _alpha+1
mult_acc ; alpha*(yn_1 - xx)) + xx

sts _yn_1, r30 ;store new output as y(n-1) to RAM
sts _yn_1+1, r31

pop r21 ;restore parameter regs
pop r20

#endasm

end
/*****************************************
Two Pole Highpass filter
*****************************************/
int Butter2high(int xx)
// xx is the current input signal sample
// returns the current filtered output sample
begin
#asm
.macro mult_acc ;r31:r30:r24 += r23:r22 * r21:r20
muls r23, r21 ; (signed)ah * (signed)bh
add r31, r0
mul r22, r20 ; al * bl
add r24, r0
adc r30, r1
adc r31, r27
mulsu r23, r20 ; (signed)ah * bl
add r30, r0
adc r31, r1
mulsu r21, r22 ; (signed)bh * al
add r30, r0
adc r31, r1
.endm
push r20 ;save parameter regs
push r21

clr r27 ;permanent zero
clr r24 ;clear 24 bit result reg; msb to lsb => r31:r30:r24
clr r30
clr r31

lds R22, _xn_1 ;load x(n-1) from RAM
lds R23, _xn_1+1
lsl r22 ;mult by two
rol r23
ld R20, Y ;load input parameter xx from stack
ldd R21, Y+1
sub r20, r22 ;form xx-2x(n-1)
sbc r21, r23
lds R22, _xn_2 ;load x(n-2) from RAM
lds R23, _xn_2+1
add r20, r22 ;form xx-2x(n-1)+x(n-2)
adc r21, r23
lds R22, _b1 ;load b1 from RAM
lds R23, _b1+1
mult_acc ; b1*(xx-2*x(n-1)+x(n-2))

lds R22, _a2 ;load -a2 from RAM
lds R23, _a2+1
lds R20, _yn_1 ;load y(n-1) from RAM
lds R21, _yn_1+1
mult_acc ; -a2*y(n-1)

lds R22, _a3 ;load -a3 from RAM
lds R23, _a3+1
lds R20, _yn_2 ;load y(n-2) from RAM
lds R21, _yn_2+1
mult_acc ; -a3*y(n-2)

lds R20, _xn_1 ;load x(n-1) from RAM
lds R21, _xn_1+1
sts _xn_2, r20 ;store x(n-2) to RAM
sts _xn_2+1, R21
ld R20, Y ;load input parameter xx from stack
ldd R21, Y+1
sts _xn_1, r20 ;store x(n-1) to RAM
sts _xn_1+1, R21
lds R20, _yn_1 ;load y(n-1) from RAM
lds R21, _yn_1+1
sts _yn_2, R20 ;store y(n-2) to RAM
sts _yn_2+1, R21
sts _yn_1, r30 ;store new output as y(n-1) to RAM
sts _yn_1+1, r31

pop r21 ;restore parameter regs
pop r20

#endasm

end

/*****************************************
Setting State Machine
Determine what settings are being changed
*****************************************/
void setting_state_machine(void)
begin
settingstate_timer = 30;

if(~PIND.6) debounce0 = 0;
if(PIND.5) debounce1 = 0;
if(PIND.4) debounce2 = 0;
// if(!debounce0 && (~PIND.4 || ~PIND.5 || ~PIND.6))
// debounce0 = 1;
switch(settingstate)
begin
case ADSR://Get ADSR
if(ADSRdisplay & 0x01)
begin
sprintf(lcd_buffer,"A:%04d",attack);
lcd_gotoxy(0,0);
lcd_puts(lcd_buffer);
ADSRdisplay = ADSRdisplay & ~(0x01);
end
if(ADSRdisplay & 0x02)
begin
sprintf(lcd_buffer,"D:%04d",decay);
lcd_gotoxy(10,0);
lcd_puts(lcd_buffer);
ADSRdisplay = ADSRdisplay & ~(0x02);
end
if(ADSRdisplay & 0x04)
begin
sprintf(lcd_buffer,"S:.%01d",sustainamp_ten_int);
lcd_gotoxy(0,1);
lcd_puts(lcd_buffer);
ADSRdisplay = ADSRdisplay & ~(0x04);
end
if(ADSRdisplay & 0x08)
begin
sprintf(lcd_buffer,"R:%04d", release);
lcd_gotoxy(10,1);
lcd_puts(lcd_buffer);
ADSRdisplay = ADSRdisplay & ~(0x08);
end
//transition
if(!debounce0 && (PIND.6))
begin
settingstate = osc1;
debounce0 = 1;
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("Oscillator 1:");
PrintWaveType(oscstate[0]);
end
break;

case osc1:
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
switch(oscstate[0])
begin
case off:
oscstate[0] = sinewave;
break;
case sinewave:
oscstate[0] = triwave;
break;
case triwave:
oscstate[0] = squarewave;
break;
case squarewave:
oscstate[0] = sawwave;
break;
case sawwave:
oscstate[0] = off;
break;
end
PrintWaveType(oscstate[0]);
updatewave();
end
//transition
if(!debounce0 && (PIND.6))
begin
settingstate = osc2;
debounce0 = 1;
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("Oscillator 2:");
PrintWaveType(oscstate[1]);

end

break;
case osc2:
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
switch(oscstate[1])
begin
case off:
oscstate[1] = sinewave;
break;
case sinewave:
oscstate[1] = triwave;
break;
case triwave:
oscstate[1] = squarewave;
break;
case squarewave:
oscstate[1] = sawwave;
break;
case sawwave:
oscstate[1] = off;
break;
end
PrintWaveType(oscstate[1]);
updatewave();
end
//transition
if(!debounce0 && (PIND.6))
begin
settingstate = operator;
debounce0 = 1;
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("Operator:");
PrintOperatorType(operatorstate);
end
break;

case operator:
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
switch(operatorstate)
begin
case off:
operatorstate = add;
break;
case add:
operatorstate = subtract;
break;
case subtract:
operatorstate = multiply;
break;
case multiply:
operatorstate = off;
break;
end
PrintOperatorType(operatorstate);
updatewave();
end
//transition
if(!debounce0 && (PIND.6))
begin
settingstate = special;
debounce0 = 1;
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("Special Functs:");
PrintSpecialType(specialstate);
end
break;
case special:

switch(specialstate)
begin
case demo:
if(!debounce2 && (~PIND.4))
begin
debounce2 = 1;
demostate++;
songcounter = 0;
if (demostate>3) demostate = 0;
if(!demostate)
begin
lcd_gotoxy(10,1);
lcd_putsf("Off");
end
else
begin
sprintf(lcd_buffer,"%d ",demostate);
lcd_gotoxy(10,1);
lcd_puts(lcd_buffer);
end
end

//transition
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
specialstate = freqshift;
PrintSpecialType(specialstate);
end
break;

case freqshift:
if(!debounce2 && (~PIND.4))
begin
debounce2 = 1;
freqshiftstate++;
if (freqshiftstate>12) freqshiftstate = -12;
sprintf(lcd_buffer,"%d ",freqshiftstate);
lcd_gotoxy(11,1);
lcd_puts(lcd_buffer);
end
//transition
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
specialstate = filter;
PrintSpecialType(specialstate);
end
break;
case filter:
if(!debounce2 && (~PIND.4))
begin
debounce2 = 1;
switch(filterstate)
begin
case off:
filterstate = highpass;
lcd_gotoxy(7,1);
lcd_putsf("High ");
break;
case highpass:
filterstate = lowpass;
lcd_gotoxy(7,1);
lcd_putsf("Low ");
break;
case lowpass:
filterstate = off;
lcd_gotoxy(7,1);
lcd_putsf("Off ");
break;
end
end
//transition
if(!debounce1 && (~PIND.5))
begin
debounce1 = 1;
specialstate = demo;
PrintSpecialType(specialstate);
end
break;
end
//transition
if(!debounce0 && (PIND.6))
begin
settingstate = ADSR;
debounce0 = 1;
ADSRdisplay = 0x0F;
lcd_clear();
end

break;
end
end

/*****************************************
Wave State Machine
Determine the wave type used
*****************************************/
/*
void wave_state_machine(void)
begin
wavestate_timer = 50;
switch(wavestate)
begin
case wait:
//if(~PINB.7)
if(0)
begin
wavetype[0]++;
if (wavetype[0] > 4) wavetype[0] = 0;
wavestate = updatewave;
end

// if(~PINB.6)
if(0)
begin
wavetype[1]++;
if (wavetype[1] > 4) wavetype[1] = 0;
wavestate = updatewave;
end

//if(~PINB.5)
if(0)

begin
operatortype++;
if (operatortype > 3) operatortype = 0;
wavestate = updatewave;
end

// if(~PINB.4)
if(0)

begin
if(filterflag) filterflag = 0;
else filterflag = 1;
wavestate = updatewave;
end

break;
case
*/
void updatewave(void)
begin
for(ii = 0; ii<256; ii++)
begin
for (j = 0; j<2; j++)
begin
switch (oscstate[j])
begin
case off:
tempwave[j] = 0;
break;
case sinewave:
tempwave[j] = sineTable[ii];
break;
case triwave:
if(ii<128)
begin
tempwave[j] = float2fix((float)(2*ii-127)/8);//float2fix(2*(float)ii*(float)16/(float)255-16);
end
else
begin
tempwave[j] = float2fix((float)(384-2*ii-1)/8);//float2fix(48-2*(float)ii*(float)16/(float)255-1);
end
// tempwave[j] = triTable[ii];
break;
case squarewave:
if(ii<128)
begin
tempwave[j] = int2fix(-16);
end
else
begin
tempwave[j] = int2fix(16);
end
//tempwave[j] = squareTable[ii];
break;
case sawwave:
tempwave[j] = float2fix(32*(float)ii/255 - 16);
break;
end
end

switch(operatorstate)
begin
case off:
finalwave[ii]= tempwave[0];
break;
case add:
finalwave[ii]= multfix((tempwave[0] + tempwave[1]),float2fix(.5));
break;
case subtract:
finalwave[ii]= multfix((tempwave[0] - tempwave[1]),float2fix(.5));
break;
case multiply:
finalwave[ii]= multfix((multfix(tempwave[0], tempwave[1])),float2fix(.1));
break;
end
end

end

/*****************************************
PrintsSpecialType(char)
Prints out Special Func to LCD
*****************************************/
void PrintSpecialType(char specialstate)
begin
switch(specialstate)
begin
case demo:
lcd_gotoxy(0,1);
lcd_putsf("Song Demo: ");
if(!demostate)
begin
lcd_gotoxy(10,1);
lcd_putsf("Off");
end
else
begin
sprintf(lcd_buffer,"%d ",demostate);
lcd_gotoxy(10,1);
lcd_puts(lcd_buffer);
end
break;
case freqshift:

sprintf(lcd_buffer,"Tone shift:%d ",freqshiftstate);
lcd_gotoxy(0,1);
lcd_puts(lcd_buffer);
break;
case filter:
lcd_gotoxy(0,1);
lcd_putsf("Filter: ");
switch(filterstate)
begin
case off:
lcd_gotoxy(7,1);
lcd_putsf("Off ");
break;
case highpass:
lcd_gotoxy(7,1);
lcd_putsf("High ");
break;
case lowpass:
lcd_gotoxy(7,1);
lcd_putsf("Low ");
break;
end
break;
end
end
/*****************************************
PrintsWaveType(char)
Prints out Wave Type to LCD
*****************************************/
void PrintWaveType(char oscstate)
begin
switch(oscstate)
begin
case off:
lcd_gotoxy(0,1);
lcd_putsf("Off ");
break;
case sinewave:
lcd_gotoxy(0,1);
lcd_putsf("Sine Wave ");
break;
case triwave:
lcd_gotoxy(0,1);
lcd_putsf("Triangle Wave ");
break;
case squarewave:
lcd_gotoxy(0,1);
lcd_putsf("Square Wave ");
break;
case sawwave:
lcd_gotoxy(0,1);
lcd_putsf("Saw Tooth Wave");
break;
end
end
/*****************************************
PrintsOperatorType(char)
Prints out Operator Type to LCD
*****************************************/
void PrintOperatorType(char operatorstate)
begin
switch(operatorstate)
begin
case off:
lcd_gotoxy(0,1);
lcd_putsf("Off ");
break;
case add:
lcd_gotoxy(0,1);
lcd_putsf("Addition ");
break;
case subtract:
lcd_gotoxy(0,1);
lcd_putsf("Subtraction ");
break;
case multiply:
lcd_gotoxy(0,1);
lcd_putsf("Multiplication");
break;
end
end
/*****************************************
Envelope State Machine
Determine attack, decay, sustain and release time
*****************************************/
void envelope_state_machine(void)
begin
envelopestate_timer = 50;
switch(envelopestate)
begin
case getAttack:
attack = (unsigned int)((float)ADCH*1000/255 + 10);
if(abs(attack_old - attack) > 8) ADSRdisplay = ADSRdisplay | 0x01;
attack_old = attack;
ADMUX = 0b01100001;
envelopestate = getDecay;
break;

case getDecay:
decay = (int)((float)ADCH*1000/255 + (10*(1 - sustainamp_float)));
if(abs(decay_old - decay) > 8 ) ADSRdisplay = ADSRdisplay | 0x02;
decay_old = decay;

ADMUX = 0b01100010;
envelopestate = getSustain;
break;
case getSustain:
sustainamp_ten_int = (unsigned int)(1 + (float)ADCH*8/255);
if(sustain_old != sustainamp_ten_int) ADSRdisplay = ADSRdisplay | 0x04;
sustain_old = sustainamp_ten_int;

sustainamp_fix = float2fix((float)(.1*((float)sustainamp_ten_int)));
sustainamp_float = .1*((float)sustainamp_ten_int);

ADMUX = 0b01100011;
envelopestate = getRelease;
break;
case getRelease:
release = (unsigned int)((float)ADCH*2000/255 + (float)(sustainamp_ten_int));
if(abs(release_old - release) > 8) ADSRdisplay = ADSRdisplay | 0x08;
release_old = release;

ADMUX = 0b01100000;
envelopestate = getAttack;
break;
end
ADCSR.6=1;
end

//**********************************************************
//initialization
void initialize(void)
begin
DDRB=0xff;

//init
// DDRB=0xff; //PORTB.0
// DDRC=0xff; // PORT C is an out for LCD
//DDRC=0x00; // PORT D is an input for switches
DDRC=0x00; // PORT C is an input for switches
//PORTC = 0x00;

//UART Recieve from midi keyboard
UCSRB = 0b10010000;
UBRRL = 31;

//fast PWM mode, full clock rate, toggle oc0 (pin B3)
//16 microsec per PWM cycle implies max freq for 16 samples of
// 1/(16e-6*16) = 3900 Hz.
//TCCR0 = 0b01101001 ;
//turn on timer 0 overflow ISR
TIMSK = 0b00010000 ;
OCR1A = 256; //set the compare re to 250 time ticks
//prescalar to 64 and turn on clear-on-match
TCCR0 = 0b01101001 ;
TCCR1A=0b00000000;
TCCR1B=0b00001010;

//init the A to D converter
//channel zero/ left adj /EXTERNAL Aref
//!!!CONNECT Aref jumper!!!!
ADMUX = 0b00100000;
//enable ADC and set prescaler to 1/128*16MHz=125,000
//and clear interupt enable
//and start a conversion
ADCSR = 0b11000111;

//init the wave tables
for (i=0; i<256; i++)
begin
sineTable[i] = float2fix((16.0 * sin(6.283*((float)i)/256.0))) ;
// finalwave[i] = (char)(32.0 * sin(6.283*((float)i)/256.0)) ;
/*
if(i<128)
begin
// squareTable[i] = -127;
//triTable[i] = 2*i-127;
end
else
begin
//squareTable[i] = 127;
//triTable[i] = 384-2*i-1;
end
*/
end


//init variables
//init the DDS phase increment and filter variables
for (i = 0; i < oscNUM; i++)
begin
accumulator[i]= 0;
increment[i] = 0;
time[i]=0;
yn_temp[i] = 0;
amp[i] = 0;
end
// increment[0] = (int)((float)song[songcounter]*IncAdjust);
// increment[1] = (int)((float)song2[songcounter]*IncAdjust);
// increment[2] = (int)((float)song3[songcounter]*IncAdjust);
// increment2 = (int)((float)song[songcounter]*2*IncAdjust);
// increment2 = (int)((float)(song2[songcounter])*IncAdjust);
// increment3 = (int)((float)(song3[songcounter])*IncAdjust);
//increment = (int)((float)C*IncAdjust);
//increment2 = (int)((float)E*IncAdjust);
//songcounter++;

//init notes and oscillator variables
for( ii = 0; ii<keysize; ii++)
begin
Held[ii] = 9;
end
oscstate[0] = 1;
oscCounter = 0;
oscReady = 0b11111111;
filterflag = 0;

//initial states
settingstate = ADSR;
envelopestate = getAttack;
ADSRdisplay = 0x0f;
demostate =0;
updatewave();

//1-pole RC lowpass, cutoff=0.0424 (1/4 Nyquist freq), gain=1
alpha = float2fix(0.390) ;

//2-pole butterworth highpass, cutoff=0.25
b1 = float2fix(0.569) ;
a2 = float2fix(0.943) ; //note that sign is negated from design input
a3 = float2fix(-.333) ; //note that sign is negated from design input

//LCD init
lcd_init(16);
lcd_clear(); //clear the display

#asm
sei
#endasm

end