Learning How To Interrupt Anything & Everything
So I decided to go back to the Uno after readying about interrupts. The Atmel ARM chips are great when needing
to do things within the Arduino IDE, but the minute you need to get under it, everything begins to suck.
I read these tutorials for some insight into using interrupts with the Uno:
In a first pass I was able to match a high D on the 66 key piano (about 1179hz). Not great,
but a start (this being a fully timer based process).
Here is the code:
/* Synth.ino
----------------------------------------------------------
Description:
A sketch to generate sound waves for audio processing
with an arduino uno.
State:
Sound is being produced, but not in a wide range of
frequencies. Further optimization is needed.
-----------------------------------
References:
http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/
http://forum.arduino.cc/index.php?topic=45562.0
https://arduino-info.wikispaces.com/Timers-Arduino
http://www.instructables.com/id/Arduino-Waveform-Generator/?ALLSTEPS
http://www.instructables.com/id/Arduino-Timer-Interrupts/
----------------------------------------------------------
Contact: ldavis@marlboro.edu
https://github.com/SafeCamp
https://safecamp.github.io/
Logan Davis | 4/22/16 | Arduino 1.6.7
*
*
*
*/
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
//-----WAVE FORM NAMES-----//
#define TRIANGLE 0
#define SAW 1
#define SQUARE 2
#define WHITENOISE 3
#define SINE 4
//-----PIN NAMES------//
#define WAVESELECT A0
#define FREQ A1
#define AUDIO_PORT 9
/*------------------------WAVE FORMS------------------------------------*/
const PROGMEM byte saw_wave[256] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
42, 44, 46, 48, 50, 52, 54, 56, 58, 60,
62, 64, 66, 68, 70, 72, 74, 76, 78, 80,
82, 84, 86, 88, 90, 92, 94, 96, 98, 100,
102, 104, 106, 108, 110, 112, 114, 116,
118, 120, 122, 124, 126, 128, 130, 132,
134, 136, 138, 140, 142, 144, 146, 148,
150, 152, 154, 156, 158, 160, 162, 164,
166, 168, 170, 172, 174, 176, 178, 180,
182, 184, 186, 188, 190, 192, 194, 196,
198, 200, 202, 204, 206, 208, 210, 212,
214, 216, 218, 220, 222, 224, 226, 228,
230, 232, 234, 236, 238, 240, 242, 244,
246, 248, 250, 252, 0, 2, 4, 6, 8, 10,
12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50,
52, 54, 56, 58, 60, 62, 64, 66, 68, 70,
72, 74, 76, 78, 80, 82, 84, 86, 88, 90,
92, 94, 96, 98, 100, 102, 104, 106, 108,
110, 112, 114, 116, 118, 120, 122, 124,
126, 128, 130, 132, 134, 136, 138, 140,
142, 144, 146, 148, 150, 152, 154, 156,
158, 160, 162, 164, 166, 168, 170, 172,
174, 176, 178, 180, 182, 184, 186, 188,
190, 192, 194, 196, 198, 200, 202, 204,
206, 208, 210, 212, 214, 216, 218, 220,
222, 224, 226, 228, 230, 232, 234, 236,
238, 240, 242, 244, 246, 248, 250, 252,
254, 255};
const PROGMEM byte square_wave[256] = {255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 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, 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, 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, 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, 0};
const PROGMEM byte triangle[256] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40,
44, 48, 52, 56, 60, 64, 68, 72, 76, 80,
84, 88, 92, 96, 100, 104, 108, 112, 116,
120, 124, 128, 132, 136, 140, 144, 148,
152, 156, 160, 164, 168, 172, 176, 180,
184, 188, 192, 196, 200, 204, 208, 212,
216, 220, 224, 228, 232, 236, 240, 244,
248, 252, 254, 255, 248, 244, 240, 236,
232, 228, 224, 220, 216, 212, 208, 204,
200, 196, 192, 188, 184, 180, 176, 172,
168, 164, 160, 156, 152, 148, 144, 140,
136, 132, 128, 124, 120, 116, 112, 108,
104, 100, 96, 92, 88, 84, 80, 76, 72,
68, 64, 60, 56, 52, 48, 44, 40, 36, 32,
28, 24, 20, 16, 12, 8, 40, 4, 8, 12, 16,
20, 24, 28, 32, 36, 40, 44, 48, 52, 56,
60, 64, 68, 72, 76, 80, 84, 88, 92, 96,
100, 104, 108, 112, 116, 120, 124, 128,
132, 136, 140, 144, 148, 152, 156, 160,
164, 168, 172, 176, 180, 184, 188, 192,
196, 200, 204, 208, 212, 216, 220, 224,
228, 232, 236, 240, 244, 248, 252, 254,
255, 248, 244, 240, 236, 232, 228, 224,
220, 216, 212, 208, 204, 200, 196, 192,
188, 184, 180, 176, 172, 168, 164, 160,
156, 152, 148, 144, 140, 136, 132, 128,
124, 120, 116, 112, 108, 104, 100, 96,
92, 88, 84, 80, 76, 72, 68, 64, 60, 56,
52, 48, 44, 40, 36, 32, 28, 24, 20, 16,
12, 8, 4};
const PROGMEM byte white_noise[256] = {104, 33, 220, 229, 128, 215, 44, 104,
212, 96, 63, 131, 36, 76, 27, 134, 138,
188, 67, 105, 149, 131, 116, 234, 175,
165, 198, 33, 2, 33, 240, 234, 16, 228,
135, 144, 80, 31, 240, 84, 190, 208, 101,
126, 137, 234, 155, 8, 0, 222, 55, 228,
219, 164, 3, 144, 233, 207, 13, 161, 198,
195, 241, 249, 219, 223, 33, 36, 223, 70,
119, 232, 32, 20, 219, 230, 16, 215, 63,
21, 163, 127, 54, 146, 133, 39, 237, 166,
78, 38, 199, 162, 167, 245, 207, 101, 195,
111, 21, 211, 224, 98, 11, 129, 254, 199,
29, 243, 144, 13, 253, 52, 223, 222, 10,
209, 251, 3, 146, 38, 41, 86, 39, 229, 88,
82, 5, 246, 156, 103, 21, 181, 67, 243, 193,
108, 85, 119, 176, 125, 114, 122, 116, 43,
104, 238, 136, 109, 139, 73, 120, 93, 35,
29, 97, 56, 141, 33, 123, 141, 56, 87, 167,
185, 195, 147, 40, 147, 135, 5, 124, 178,
150, 59, 163, 172, 223, 249, 95, 227, 57,
209, 156, 116, 219, 98, 226, 218, 100, 14,
246, 80, 140, 206, 43, 180, 45, 45, 34, 76,
61, 170, 216, 200, 97, 135, 150, 247, 82,
184, 50, 180, 199, 122, 23, 44, 74, 104,
14, 229, 213, 203, 1, 91, 220, 242, 171,
114, 60, 42, 2, 71, 161, 174, 153, 147, 67,
127, 189, 94, 83, 85, 62, 95, 22, 42, 153,
100, 180, 139, 165, 7, 136, 71, 74, 114};
const PROGMEM byte sine_wave[256] = {128, 131, 134, 137, 140, 143, 146, 149, 152,
155, 158, 161, 164, 167, 170, 173, 176, 179,
182, 185, 187, 190, 193, 195, 198, 201, 203,
206, 208, 210, 213, 215, 217, 219, 222, 224,
226, 228, 230, 231, 233, 235, 236, 238, 240,
241, 242, 244, 245, 246, 247, 248, 249, 250,
251, 251, 252, 253, 253, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 253, 253,
252, 251, 251, 250, 249, 248, 247, 246, 245,
244, 242, 241, 240, 238, 236, 235, 233, 231,
230, 228, 226, 224, 222, 219, 217, 215, 213,
210, 208, 206, 203, 201, 198, 195, 193, 190,
187, 185, 182, 179, 176, 173, 170, 167, 164,
161, 158, 155, 152, 149, 146, 143, 140, 137,
134, 131, 128, 124, 121, 118, 115, 112, 109,
106, 103, 100, 97, 94, 91, 88, 85, 82, 79,
76, 73, 70, 68, 65, 62, 60, 57, 54, 52, 49,
47, 45, 42, 40, 38, 36, 33, 31, 29, 27, 25,
24, 22, 20, 19, 17, 15, 14, 13, 11, 10, 9,
8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7,
8, 9, 10, 11, 13, 14, 15, 17, 19, 20, 22,
24, 25, 27, 29, 31, 33, 36, 38, 40, 42, 45,
47, 49, 52, 54, 57, 60, 62, 65, 68, 70, 73,
76, 79, 82, 85, 88, 91, 94, 97, 100, 103,
106, 109, 112, 115, 118, 121, 124};
byte current_wave_form[256] = {0};
volatile byte i = 0; //set to volatile due to being mutated by an interrupt
void setup(){
/* Set PWM pin to OUTPUT */
choose_wave(SINE);
DDRD = 0xFF; //SET 0-7 as OUTPUT
cli();
TCCR1A = 0;// clear some regs that could have been set by Arduino IDE
TCCR1B = 0;
OCR1A = 0; // Set frequency of interrupt
TCCR1B |= (1 << WGM12); // Set CTC mode
TCCR1B |= (1 << CS10); // Prescale = 1
TIMSK1 |= (1 << OCIE1A); //link interrupt
sei();//enable interrupts
}
void loop() {}
ISR(TIMER1_COMPA_vect){//timer 1 interrupt
PORTD = current_wave_form[i++]; //direct write out to ports 0-7
}
void choose_wave(byte choice){
/* Check to see what wave the user is choosing
* then call swap_wave() on it.
*/
switch(choice){
case TRIANGLE:
swap_waves(triangle);
break;
case SAW:
swap_waves(saw_wave);
break;
case SQUARE:
swap_waves(square_wave);
break;
case WHITENOISE:
swap_waves(white_noise);
break;
case SINE:
swap_waves(sine_wave);
break;
}
}
void swap_waves(const byte stored_wave[]){
/* Read a given waveform from programmable
* memory into a global array stored in ram
*/
int i= 0;
for(i = 0;i < 256;i++){
current_wave_form[i] = pgm_read_word_near(&stored_wave[i]);
}
}