18 #include <util/atomic.h>
19 #include "MozziGuts.h"
20 #include "mozzi_config.h"
21 #include "mozzi_analog.h"
22 #include "CircularBuffer.h"
25 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
26 #include "IntervalTimer.h"
28 #include "TimerZero.h"
30 #include "FrequencyTimer2.h"
34 #if !(F_CPU == 16000000 || F_CPU == 48000000)
35 #warning "Mozzi has been tested with a cpu clock speed of 16MHz on Arduino and 48MHz on Teensy 3! Results may vary with other speeds."
39 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
73 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
78 static uint8_t pre_mozzi_TCCR0A, pre_mozzi_TCCR0B, pre_mozzi_OCR0A, pre_mozzi_TIMSK0;
79 static uint8_t pre_mozzi_TCCR1A, pre_mozzi_TCCR1B, pre_mozzi_OCR1A, pre_mozzi_TIMSK1;
81 #if (AUDIO_MODE == HIFI)
83 static uint8_t pre_mozzi_TCCR2A, pre_mozzi_TCCR2B, pre_mozzi_OCR2A, pre_mozzi_TIMSK2;
85 static uint8_t pre_mozzi_TCCR2, pre_mozzi_OCR2, pre_mozzi_TIMSK;
87 static uint8_t pre_mozzi_TCCR4A, pre_mozzi_TCCR4B, pre_mozzi_TCCR4C, pre_mozzi_TCCR4D, pre_mozzi_TCCR4E, pre_mozzi_OCR4C, pre_mozzi_TIMSK4;
92 static void backupPreMozziTimer1()
95 pre_mozzi_TCCR1A = TCCR1A;
96 pre_mozzi_TCCR1B = TCCR1B;
97 pre_mozzi_OCR1A = OCR1A;
98 pre_mozzi_TIMSK1 = TIMSK1;
106 static uint8_t mozzi_TCCR0A, mozzi_TCCR0B, mozzi_OCR0A, mozzi_TIMSK0;
107 static uint8_t mozzi_TCCR1A, mozzi_TCCR1B, mozzi_OCR1A, mozzi_TIMSK1;
109 #if (AUDIO_MODE == HIFI)
111 static uint8_t mozzi_TCCR2A, mozzi_TCCR2B, mozzi_OCR2A, mozzi_TIMSK2;
113 static uint8_t mozzi_TCCR2, mozzi_OCR2, mozzi_TIMSK;
114 #elif defined(TCCR4A)
115 static uint8_t mozzi_TCCR4A, mozzi_TCCR4B, mozzi_TCCR4C, mozzi_TCCR4D, mozzi_TCCR4E, mozzi_OCR4C, mozzi_TIMSK4;
120 static void backupMozziTimer1()
123 mozzi_TCCR1A = TCCR1A;
124 mozzi_TCCR1B = TCCR1B;
126 mozzi_TIMSK1 = TIMSK1;
129 #endif // end of timer backups for non-Teensy 3 boards
132 #if (USE_AUDIO_INPUT==true)
137 static boolean audio_input_is_available;
138 static int audio_input;
139 uint8_t adc_count = 0;
148 static void startFirstAudioADC()
150 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
164 static void startSecondAudioADC()
166 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
169 ADCSRA |= (1 << ADSC);
175 static void receiveSecondAudioADC()
177 if (!input_buffer.isFull())
178 #
if defined(__MK20DX128__) || defined(__MK20DX256__)
179 input_buffer.write(adc->readSingle());
181 input_buffer.write(ADC);
186 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
189 ISR(ADC_vect, ISR_BLOCK)
195 receiveSecondAudioADC();
196 adcReadSelectedChannels();
202 startSecondControlADC();
207 receiveSecondControlADC();
208 startFirstAudioADC();
220 #endif // end main audio input section
226 #if (USE_AUDIO_INPUT==true)
227 if (!input_buffer.isEmpty())
228 audio_input = input_buffer.read();
231 if (!output_buffer.isFull()) {
232 output_buffer.write((
unsigned int) (
updateAudio() + AUDIO_BIAS));
241 #if (AUDIO_MODE == STANDARD) || (AUDIO_MODE == STANDARD_PLUS)
243 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
246 IntervalTimer timer1;
249 static void teensyAudioOutput()
252 #if (USE_AUDIO_INPUT==true)
254 startSecondAudioADC();
257 analogWrite(AUDIO_CHANNEL_1_PIN, (
int)output_buffer.read());
261 static void startAudioStandard()
265 analogWriteResolution(12);
266 adc->setAveraging(0);
267 adc->setConversionSpeed(ADC_MED_SPEED);
268 timer1.begin(teensyAudioOutput, 1000000UL/
AUDIO_RATE);
276 static void startAudioStandard()
278 backupPreMozziTimer1();
280 pinMode(AUDIO_CHANNEL_1_PIN, OUTPUT);
282 #if (AUDIO_MODE == STANDARD)
283 Timer1.initializeCPUCycles(16000000UL/
AUDIO_RATE, PHASE_FREQ_CORRECT);
284 #else // (AUDIO_MODE == STANDARD_PLUS)
285 Timer1.initializeCPUCycles(16000000UL/PWM_RATE, FAST);
287 Timer1.pwm(AUDIO_CHANNEL_1_PIN, AUDIO_BIAS);
311 ISR(TIMER1_OVF_vect, ISR_BLOCK)
314 #if (AUDIO_MODE == STANDARD_PLUS) && (AUDIO_RATE == 16384) // only update every second ISR, if lower audio rate
315 static boolean alternate;
316 alternate = !alternate;
321 #if (USE_AUDIO_INPUT==true)
323 startSecondAudioADC();
332 AUDIO_CHANNEL_1_OUTPUT_REGISTER = output_buffer.read();
343 #if (AUDIO_MODE == STANDARD_PLUS) && (AUDIO_RATE==16384) // all this conditional compilation is so clutsy!
353 #elif (AUDIO_MODE == HIFI)
355 static void startAudioHiFi()
357 backupPreMozziTimer1();
359 pinMode(AUDIO_CHANNEL_1_highByte_PIN, OUTPUT);
360 pinMode(AUDIO_CHANNEL_1_lowByte_PIN, OUTPUT);
361 Timer1.initializeCPUCycles(16000000UL/125000, FAST);
362 Timer1.pwm(AUDIO_CHANNEL_1_highByte_PIN, 0);
363 Timer1.pwm(AUDIO_CHANNEL_1_lowByte_PIN, 0);
373 static void backupPreMozziTimer2()
377 pre_mozzi_TCCR2A = TCCR2A;
378 pre_mozzi_TCCR2B = TCCR2B;
379 pre_mozzi_OCR2A = OCR2A;
380 pre_mozzi_TIMSK2 = TIMSK2;
382 pre_mozzi_TCCR2 = TCCR2;
383 pre_mozzi_OCR2 = OCR2;
384 pre_mozzi_TIMSK = TIMSK;
385 #elif defined(TCCR4A)
386 pre_mozzi_TCCR4B = TCCR4A;
387 pre_mozzi_TCCR4B = TCCR4B;
388 pre_mozzi_TCCR4B = TCCR4C;
389 pre_mozzi_TCCR4B = TCCR4D;
390 pre_mozzi_TCCR4B = TCCR4E;
391 pre_mozzi_OCR4C = OCR4C;
392 pre_mozzi_TIMSK4 = TIMSK4;
398 static void backupMozziTimer2()
401 mozzi_TCCR2A = TCCR2A;
402 mozzi_TCCR2B = TCCR2B;
404 mozzi_TIMSK2 = TIMSK2;
409 #elif defined(TCCR4A)
410 mozzi_TCCR4B = TCCR4A;
411 mozzi_TCCR4B = TCCR4B;
412 mozzi_TCCR4B = TCCR4C;
413 mozzi_TCCR4B = TCCR4D;
414 mozzi_TCCR4B = TCCR4E;
416 mozzi_TIMSK4 = TIMSK4;
422 static void setupTimer2()
424 backupPreMozziTimer2();
426 FrequencyTimer2::setPeriodCPUCycles(16000000UL/
AUDIO_RATE);
427 FrequencyTimer2::setOnOverflow(dummy);
428 FrequencyTimer2::enable();
436 #if defined(TIMER2_COMPA_vect)
437 ISR(TIMER2_COMPA_vect)
438 #elif defined(TIMER2_COMP_vect)
439 ISR(TIMER2_COMP_vect)
440 #elif defined(TIMER4_COMPA_vect)
441 ISR(TIMER4_COMPA_vect)
443 #error "This board does not have a hardware timer which is compatible with FrequencyTimer2"
444 void dummy_function(
void)
447 #if (USE_AUDIO_INPUT==true)
449 startSecondAudioADC();
455 unsigned int out = output_buffer.read();
459 unsigned int out_high = out<<1;
460 AUDIO_CHANNEL_1_highByte_REGISTER = out_high >> 8;
462 AUDIO_CHANNEL_1_lowByte_REGISTER = out & 127;
473 static void updateControlWithAutoADC()
491 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
492 IntervalTimer timer0;
496 static void startControl(
unsigned int control_rate_hz)
498 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
499 timer0.begin(updateControlWithAutoADC, 1000000/control_rate_hz);
502 pre_mozzi_TCCR0A = TCCR0A;
503 pre_mozzi_TCCR0B = TCCR0B;
504 pre_mozzi_OCR0A = OCR0A;
505 pre_mozzi_TIMSK0 = TIMSK0;
507 TimerZero::init(1000000/control_rate_hz,updateControlWithAutoADC);
511 mozzi_TCCR0A = TCCR0A;
512 mozzi_TCCR0B = TCCR0B;
514 mozzi_TIMSK0 = TIMSK0;
523 startControl(control_rate_hz);
524 #if (AUDIO_MODE == STANDARD) || (AUDIO_MODE == STANDARD_PLUS)
525 startAudioStandard();
526 #elif (AUDIO_MODE == HIFI)
533 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
537 TCCR0A = pre_mozzi_TCCR0A;
538 TCCR0B = pre_mozzi_TCCR0B;
539 OCR0A = pre_mozzi_OCR0A;
540 TIMSK0 = pre_mozzi_TIMSK0;
542 TCCR1A = pre_mozzi_TCCR1A;
543 TCCR1B = pre_mozzi_TCCR1B;
544 OCR1A = pre_mozzi_OCR1A;
545 TIMSK1 = pre_mozzi_TIMSK1;
547 #if (AUDIO_MODE == HIFI)
549 TCCR2A = pre_mozzi_TCCR2A;
550 TCCR2B = pre_mozzi_TCCR2B;
551 OCR2A = pre_mozzi_OCR2A;
552 TIMSK2 = pre_mozzi_TIMSK2;
554 TCCR2 = pre_mozzi_TCCR2;
555 OCR2 = pre_mozzi_OCR2;
556 TIMSK = pre_mozzi_TIMSK;
557 #elif defined(TCCR4A)
558 TCCR4B = pre_mozzi_TCCR4A;
559 TCCR4B = pre_mozzi_TCCR4B;
560 TCCR4B = pre_mozzi_TCCR4C;
561 TCCR4B = pre_mozzi_TCCR4D;
562 TCCR4B = pre_mozzi_TCCR4E;
563 OCR4C = pre_mozzi_OCR4C;
564 TIMSK4 = pre_mozzi_TIMSK4;
573 #if defined(__MK20DX128__) || defined(__MK20DX256__) // teensy 3, 3.1
574 timer1.begin(teensyAudioOutput, 1000000UL/
AUDIO_RATE);
577 TCCR0A = mozzi_TCCR0A;
578 TCCR0B = mozzi_TCCR0B;
580 TIMSK0 = mozzi_TIMSK0;
582 TCCR1A = mozzi_TCCR1A;
583 TCCR1B = mozzi_TCCR1B;
585 TIMSK1 = mozzi_TIMSK1;
587 #if (AUDIO_MODE == HIFI)
589 TCCR2A = mozzi_TCCR2A;
590 TCCR2B = mozzi_TCCR2B;
592 TIMSK2 = mozzi_TIMSK2;
597 #elif defined(TCCR4A)
598 TCCR4B = mozzi_TCCR4A;
599 TCCR4B = mozzi_TCCR4B;
600 TCCR4B = mozzi_TCCR4C;
601 TCCR4B = mozzi_TCCR4D;
602 TCCR4B = mozzi_TCCR4E;
604 TIMSK4 = mozzi_TIMSK4;
613 return output_buffer.count();
unsigned long mozziMicros()
A replacement for Arduino micros() which is disabled by Mozzi which takes over Timer 0 for control in...
void updateControl()
This is where you put your control code.
#define AUDIO_RATE
Holds the audio rate setting.
#define AUDIO_INPUT_PIN
This sets which analog input channel to use for audio input, if you have #define USE_AUDIO_INPUT true...
void audioHook()
This is required in Arduino's loop().
void unPauseMozzi()
Restores Mozzi audio and control interrupts, if they have been temporarily disabled with pauseMozzi()...
unsigned long audioTicks()
An alternative for Arduino time funcitions like micros() which are disabled by Mozzi when it takes ov...
void pauseMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
int getAudioInput()
This returns audio input from the input buffer, if #define USE_AUDIO_INPUT true is in the Mozzi/mozzi...
int updateAudio()
This is where you put your audio code.
void startMozzi(int control_rate_hz)
Sets up the timers for audio and control rate processes, storing the timer registers so they can be r...