#include "Arduino.h" #include "ihandlers.h" #include "mcpDac.h" #include "timer.h" #include "theremin_sintable.c" #include "theremin_sintable2.c" #include "theremin_sintable3.c" #include "theremin_sintable4.c" #include "theremin_sintable5.c" #include "theremin_sintable6.c" #include "theremin_sintable7.c" #include "theremin_sintable8.c" const int16_t* const wavetables[] PROGMEM = { sine_table, sine_table2, sine_table3, sine_table4, sine_table5, sine_table6, sine_table7, sine_table8 }; static const uint32_t MCP_DAC_BASE = 1748; #define INT0_STATE (PIND & (1<>6) & 0x3ff; // Read next wave table value (3.0us) // The slightly odd tactic here is to provide compile-time expressions for the wavetable // positions. Making addr1 the index into the wavtables array breaks the time limit for // the interrupt handler switch (vWavetableSelector) { case 1: waveSample = (int16_t) pgm_read_word_near(wavetables[1] + offset); break; case 2: waveSample = (int16_t) pgm_read_word_near(wavetables[2] + offset); break; case 3: waveSample = (int16_t) pgm_read_word_near(wavetables[3] + offset); break; case 4: waveSample = (int16_t) pgm_read_word_near(wavetables[4] + offset); break; case 5: waveSample = (int16_t) pgm_read_word_near(wavetables[5] + offset); break; case 6: waveSample = (int16_t) pgm_read_word_near(wavetables[6] + offset); break; case 7: waveSample = (int16_t) pgm_read_word_near(wavetables[7] + offset); break; default: waveSample = (int16_t) pgm_read_word_near(wavetables[0] + offset); break; }; if (waveSample > 0) { // multiply 16 bit wave number by 8 bit volume value (11.2us / 5.4us) scaledSample = MCP_DAC_BASE + (mul_16_8(waveSample, vScaledVolume) >> 9); } else { scaledSample = MCP_DAC_BASE - (mul_16_8(-waveSample, vScaledVolume) >> 9); } mcpDacSend(scaledSample); //Send result to Digital to Analogue Converter (audio out) (9.6 us) pointer = pointer + vPointerIncrement; // increment table pointer (ca. 2us) incrementTimer(); // update 32us timer if (PC_STATE) debounce_p++; if (debounce_p == 3) { noInterrupts(); pitch_counter = ICR1; // Get Timer-Counter 1 value pitch = (pitch_counter - pitch_counter_l); // Counter change since last interrupt -> pitch value pitch_counter_l = pitch_counter; // Set actual value as new last value }; if (debounce_p == 5) { pitchValueAvailable = true; }; if (INT0_STATE) debounce_v++; if (debounce_v == 3) { noInterrupts(); vol_counter = vol_counter_i; // Get Timer-Counter 1 value vol = (vol_counter - vol_counter_l); // Counter change since last interrupt vol_counter_l = vol_counter; // Set actual value as new last value }; if (debounce_v == 5) { volumeValueAvailable = true; }; noInterrupts(); enableInt1(); } /* VOLUME read - interrupt service routine for capturing volume counter value */ ISR (INT0_vect) { vol_counter_i = TCNT1; debounce_v = 0; }; /* PITCH read - interrupt service routine for capturing pitch counter value */ ISR (TIMER1_CAPT_vect) { debounce_p = 0; }; /* PITCH read absolute frequency - interrupt service routine for calibration measurement */ ISR(TIMER0_COMPA_vect) { timer_overflow_counter++; } /* VOLUME read absolute frequency - interrupt service routine for calibration measurement */ ISR(TIMER1_OVF_vect) { timer_overflow_counter++; }