Mozzi  version v1.1.0
sound synthesis library for Arduino
MozziGuts.cpp
1 /*
2  * MozziGuts.cpp
3  *
4  * Copyright 2012 Tim Barrass.
5  *
6  * This file is part of Mozzi.
7  *
8  * Mozzi by Tim Barrass is licensed under a Creative Commons
9  * Attribution-NonCommercial-ShareAlike 4.0 International License.
10  *
11  */
12 
13 #if ARDUINO >= 100
14 #include "Arduino.h"
15 #else
16 #include "WProgram.h"
17 #endif
18 
19 #include "CircularBuffer.h"
20 #include "MozziGuts.h"
21 #include "mozzi_analog.h"
22 #include "mozzi_config.h" // at the top of all MozziGuts and analog files
23 //#include "mozzi_utils.h"
24 #include "AudioOutput.h"
25 
26 
27 #if IS_AVR()
28 #include "FrequencyTimer2.h"
29 #include "TimerOne.h"
30 #elif IS_TEENSY3()
31 // required from http://github.com/pedvide/ADC for Teensy 3.*
32 #include "IntervalTimer.h"
33 #include <ADC.h>
34 #elif IS_STM32()
35 #include "HardwareTimer.h"
36 //#include <STM32ADC.h> // Disabled, here. See AudioConfigSTM32.h
37 #elif IS_ESP8266()
38 #include <uart.h>
39 #include <i2s.h>
40 uint16_t output_buffer_size = 0;
41 #elif IS_ESP32()
42 #include <driver/i2s.h> // for I2S-based output modes
43 #include <driver/timer.h> // for EXTERNAL_AUDIO_OUTPUT
44 #endif
45 
46 
47 #if (IS_TEENSY3() && F_CPU != 48000000) || (IS_AVR() && F_CPU != 16000000)
48 #warning
49  "Mozzi has been tested with a cpu clock speed of 16MHz on Arduino and 48MHz on Teensy 3! Results may vary with other speeds."
50 #endif
51 
52 #if IS_TEENSY3()
53 ADC *adc; // adc object
54 uint8_t teensy_pin;
55 #elif IS_STM32()
56 STM32ADC adc(ADC1);
57 uint8_t stm32_current_adc_pin;
58 #endif
59 
60 /*
61 ATmega328 technical manual, Section 12.7.4:
62 The dual-slope operation [of phase correct pwm] has lower maximum operation
63 frequency than single slope operation. However, due to the symmetric feature
64 of the dual-slope PWM modes, these modes are preferred for motor control
65 applications.
66 Due to the single-slope operation, the operating frequency of the
67 fast PWM mode can be twice as high as the phase correct PWM mode that use
68 dual-slope operation. This high frequency makes the fast PWM mode well suited
69 for power regulation, rectification, and DAC applications. High frequency allows
70 physically small sized external components (coils, capacitors)..
71 
72 DAC, that's us! Fast PWM.
73 
74 PWM frequency tests
75 62500Hz, single 8 or dual 16 bits, bad aliasing
76 125000Hz dual 14 bits, sweet
77 250000Hz dual 12 bits, gritty, if you're gonna have 2 pins, have 14 bits
78 500000Hz dual 10 bits, grittier
79 16384Hz single nearly 9 bits (original mode) not bad for a single pin, but
80 carrier freq noise can be an issue
81 */
82 
83 #if BYPASS_MOZZI_OUTPUT_BUFFER == true
84 uint64_t samples_written_to_buffer = 0;
85 #else
86 //-----------------------------------------------------------------------------------------------------------------
87 // ring buffer for audio output
88 #if (STEREO_HACK == true)
89 CircularBuffer<StereoOutput> output_buffer; // fixed size 256
90 #else
91 CircularBuffer<AudioOutput_t> output_buffer; // fixed size 256
92 #endif
93 //-----------------------------------------------------------------------------------------------------------------
94 #endif
95 
96 #if IS_AVR() // not storing backups, just turning timer on and off for pause for
97  // teensy 3.*, other ARMs
98 
99 // to store backups of timer registers so Mozzi can be stopped and pre_mozzi
100 // timer values can be restored
101 static uint8_t pre_mozzi_TCCR1A, pre_mozzi_TCCR1B, pre_mozzi_OCR1A,
102  pre_mozzi_TIMSK1;
103 
104 #if (AUDIO_MODE == HIFI)
105 #if defined(TCCR2A)
106 static uint8_t pre_mozzi_TCCR2A, pre_mozzi_TCCR2B, pre_mozzi_OCR2A,
107  pre_mozzi_TIMSK2;
108 #elif defined(TCCR2)
109 static uint8_t pre_mozzi_TCCR2, pre_mozzi_OCR2, pre_mozzi_TIMSK;
110 #elif defined(TCCR4A)
111 static uint8_t pre_mozzi_TCCR4A, pre_mozzi_TCCR4B, pre_mozzi_TCCR4C,
112  pre_mozzi_TCCR4D, pre_mozzi_TCCR4E, pre_mozzi_OCR4C, pre_mozzi_TIMSK4;
113 #endif
114 #endif
115 
116 static void backupPreMozziTimer1() {
117  // backup pre-mozzi register values for pausing later
118  pre_mozzi_TCCR1A = TCCR1A;
119  pre_mozzi_TCCR1B = TCCR1B;
120  pre_mozzi_OCR1A = OCR1A;
121  pre_mozzi_TIMSK1 = TIMSK1;
122 }
123 
124 //-----------------------------------------------------------------------------------------------------------------
125 
126 #if (AUDIO_MODE == HIFI)
127 #if defined(TCCR2A)
128 static uint8_t mozzi_TCCR2A, mozzi_TCCR2B, mozzi_OCR2A, mozzi_TIMSK2;
129 #elif defined(TCCR2)
130 static uint8_t mozzi_TCCR2, mozzi_OCR2, mozzi_TIMSK;
131 #elif defined(TCCR4A)
132 static uint8_t mozzi_TCCR4A, mozzi_TCCR4B, mozzi_TCCR4C, mozzi_TCCR4D,
133  mozzi_TCCR4E, mozzi_OCR4C, mozzi_TIMSK4;
134 #endif
135 #endif
136 
137 #endif // end of timer backups for non-Teensy 3 boards
138 //-----------------------------------------------------------------------------------------------------------------
139 
140 ////// BEGIN AUDIO INPUT code ////////
141 #if (USE_AUDIO_INPUT == true)
142 
143 // ring buffer for audio input
144 CircularBuffer<unsigned int> input_buffer; // fixed size 256
145 
146 static boolean audio_input_is_available;
147 static int audio_input; // holds the latest audio from input_buffer
148 uint8_t adc_count = 0;
149 
150 int getAudioInput() { return audio_input; }
151 
152 static void startFirstAudioADC() {
153 #if IS_TEENSY3()
154  adc->startSingleRead(
155  AUDIO_INPUT_PIN); // ADC lib converts pin/channel in startSingleRead
156 #elif IS_STM32()
157  uint8_t dummy = AUDIO_INPUT_PIN;
158  adc.setPins(&dummy, 1);
159  adc.startConversion();
160 #else
161  adcStartConversion(adcPinToChannelNum(AUDIO_INPUT_PIN));
162 #endif
163 }
164 
165 /*
166 static void receiveFirstAudioADC()
167 {
168  // nothing
169 }
170 */
171 
172 static void startSecondAudioADC() {
173 #if IS_TEENSY3()
174  adc->startSingleRead(AUDIO_INPUT_PIN);
175 #elif IS_STM32()
176  uint8_t dummy = AUDIO_INPUT_PIN;
177  adc.setPins(&dummy, 1);
178  adc.startConversion();
179 #else
180  ADCSRA |= (1 << ADSC); // start a second conversion on the current channel
181 #endif
182 }
183 
184 static void receiveSecondAudioADC() {
185  if (!input_buffer.isFull())
186 #if IS_TEENSY3()
187  input_buffer.write(adc->readSingle());
188 #elif IS_STM32()
189  input_buffer.write(adc.getData());
190 #else
191  input_buffer.write(ADC);
192 #endif
193 }
194 
195 #if IS_TEENSY3() || IS_STM32() || IS_AVR()
196 #if IS_TEENSY3()
197 void adc0_isr(void)
198 #elif IS_STM32()
199 void stm32_adc_eoc_handler()
200 #else
201 ISR(ADC_vect, ISR_BLOCK)
202 #endif
203 {
204  switch (adc_count) {
205  case 0:
206  // 6us
207  receiveSecondAudioADC();
208  adcReadSelectedChannels();
209  break;
210 
211  case 1:
212  // <2us, <1us w/o receive
213  // receiveFirstControlADC();
214  startSecondControlADC();
215  break;
216 
217  case 2:
218  // 3us
219  receiveSecondControlADC();
220  startFirstAudioADC();
221  break;
222 
223  // case 3:
224  // invisible
225  // receiveFirstAudioADC();
226  // break;
227  }
228  adc_count++;
229 }
230 #endif // end main audio input section
231 #endif
232 ////// END AUDIO INPUT code ////////
233 
234 
235 #if IS_SAMD21()
236 // These are ARM SAMD21 Timer 5 routines to establish a sample rate interrupt
237 static bool tcIsSyncing() {
238  return TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY;
239 }
240 
241 static void tcReset() {
242  // Reset TCx
243  TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
244  while (tcIsSyncing())
245  ;
246  while (TC5->COUNT16.CTRLA.bit.SWRST)
247  ;
248 }
249 /* Not currently used, and does not compile with EXTERNAL_AUDIO_OUTPUT
250 static void tcEnd() {
251  // Disable TC5
252  TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
253  while (tcIsSyncing())
254  ;
255  tcReset();
256  analogWrite(AUDIO_CHANNEL_1_PIN, 0);
257 } */
258 
259 static void tcConfigure(uint32_t sampleRate) {
260  // Enable GCLK for TCC2 and TC5 (timer counter input clock)
261  GCLK->CLKCTRL.reg = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 |
262  GCLK_CLKCTRL_ID(GCM_TC4_TC5));
263  while (GCLK->STATUS.bit.SYNCBUSY)
264  ;
265 
266  tcReset();
267 
268  // Set Timer counter Mode to 16 bits
269  TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
270 
271  // Set TC5 mode as match frequency
272  TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
273 
274  TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE;
275 
276  TC5->COUNT16.CC[0].reg = (uint16_t)(SystemCoreClock / sampleRate - 1);
277  while (tcIsSyncing())
278  ;
279 
280  // Configure interrupt request
281  NVIC_DisableIRQ(TC5_IRQn);
282  NVIC_ClearPendingIRQ(TC5_IRQn);
283  NVIC_SetPriority(TC5_IRQn, 0);
284  NVIC_EnableIRQ(TC5_IRQn);
285 
286  // Enable the TC5 interrupt request
287  TC5->COUNT16.INTENSET.bit.MC0 = 1;
288  while (tcIsSyncing())
289  ;
290 }
291 #endif
292 
293 #if (IS_ESP8266() && (ESP_AUDIO_OUT_MODE == PDM_VIA_SERIAL) && (EXTERNAL_AUDIO_OUTPUT != true))
294 void CACHED_FUNCTION_ATTR esp8266_serial_audio_output() {
295  // Note: That unreadble mess is an optimized version of Serial1.availableForWrite()
296  while ((UART_TX_FIFO_SIZE - ((U1S >> USTXC) & 0xff)) > (PDM_RESOLUTION * 4)) {
297  audioOutput(output_buffer.read());
298  }
299 }
300 #endif
301 
302 #if BYPASS_MOZZI_OUTPUT_BUFFER == true
303 inline void bufferAudioOutput(const AudioOutput_t f) {
304  audioOutput(f);
305  ++samples_written_to_buffer;
306 }
307 #else
308 #define canBufferAudioOutput() (!output_buffer.isFull())
309 #define bufferAudioOutput(f) output_buffer.write(f)
310 #endif
311 
312 static uint16_t update_control_timeout;
313 static uint16_t update_control_counter;
314 
315 inline void advanceControlLoop() {
316  if (!update_control_counter) {
317  update_control_counter = update_control_timeout;
319  adcStartReadCycle();
320  } else {
321  --update_control_counter;
322  }
323 }
324 
325 void audioHook() // 2us on AVR excluding updateAudio()
326 {
327 // setPin13High();
328 #if (USE_AUDIO_INPUT == true)
329  if (!input_buffer.isEmpty())
330  audio_input = input_buffer.read();
331 #endif
332 
333  if (canBufferAudioOutput()) {
334  advanceControlLoop();
335 #if (STEREO_HACK == true)
336  updateAudio(); // in hacked version, this returns void
337  bufferAudioOutput(StereoOutput(audio_out_1, audio_out_2));
338 #else
339  bufferAudioOutput(updateAudio());
340 #endif
341 
342 #if IS_ESP8266()
343  yield();
344 #endif
345  }
346  // setPin13Low();
347 }
348 
349 #if IS_SAMD21()
350 void TC5_Handler(void) __attribute__((weak, alias("samd21AudioOutput")));
351 #endif
352 
353 //-----------------------------------------------------------------------------------------------------------------
355 #if IS_TEENSY3()
356 IntervalTimer timer1;
357 #elif IS_STM32() && (EXTERNAL_AUDIO_OUTPUT == true)
358 HardwareTimer audio_update_timer(2);
359 #elif IS_STM32()
360 HardwareTimer audio_update_timer(AUDIO_UPDATE_TIMER);
361 HardwareTimer audio_pwm_timer(AUDIO_PWM_TIMER);
362 #endif
363 
364 #if (BYPASS_MOZZI_OUTPUT_BUFFER != true)
365 static void CACHED_FUNCTION_ATTR defaultAudioOutput() {
366 #if (USE_AUDIO_INPUT == true)
367  adc_count = 0;
368  startSecondAudioADC();
369 #endif
370  audioOutput(output_buffer.read());
371 }
372 #endif
373 
374 #if (IS_ESP32() && (BYPASS_MOZZI_OUTPUT_BUFFER != true))
375 void CACHED_FUNCTION_ATTR timer0_audio_output_isr(void *) {
376  TIMERG0.int_clr_timers.t0 = 1;
377  TIMERG0.hw_timer[0].config.alarm_en = 1;
378  defaultAudioOutput();
379 }
380 #endif
381 
382 #if IS_SAMD21()
383 #ifdef __cplusplus
384 extern "C" {
385 #endif
386 void samd21AudioOutput() {
387  defaultAudioOutput();
388  TC5->COUNT16.INTFLAG.bit.MC0 = 1;
389 }
390 #ifdef __cplusplus
391 }
392 #endif
393 #endif
394 
395 #if !IS_AVR()
396 static void startAudioStandard() {
397 
398 #if IS_TEENSY3()
399  adc->setAveraging(0);
400  adc->setConversionSpeed(
401  ADC_CONVERSION_SPEED::MED_SPEED); // could be HIGH_SPEED, noisier
402 
403  analogWriteResolution(12);
404  timer1.begin(defaultAudioOutput, 1000000UL / AUDIO_RATE);
405 #elif IS_SAMD21()
406 #ifdef ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS
407  {
408  static const int CPLAY_SPEAKER_SHUTDOWN = 11;
409  pinMode(CPLAY_SPEAKER_SHUTDOWN, OUTPUT);
410  digitalWrite(CPLAY_SPEAKER_SHUTDOWN, HIGH);
411  }
412 
413 #endif
414  analogWriteResolution(10);
415 #if (EXTERNAL_AUDIO_OUTPUT != true)
416  analogWrite(AUDIO_CHANNEL_1_PIN, 0);
417 #endif
418  tcConfigure(AUDIO_RATE);
419 
420 #elif IS_ESP32() && (BYPASS_MOZZI_OUTPUT_BUFFER != true) // for external audio output, set up a timer running a audio rate
421  static intr_handle_t s_timer_handle;
422  timer_config_t config = {
423  .alarm_en = true,
424  .counter_en = false,
425  .intr_type = TIMER_INTR_LEVEL,
426  .counter_dir = TIMER_COUNT_UP,
427  .auto_reload = true,
428  .divider = 1 // For max available precision: The APB_CLK clock signal is running at 80 MHz, i.e. 1/80 uS per tick
429  };
430  timer_init(TIMER_GROUP_0, TIMER_0, &config);
431  timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
432  timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 80000000UL / AUDIO_RATE);
433  timer_enable_intr(TIMER_GROUP_0, TIMER_0);
434  timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer0_audio_output_isr, nullptr, 0, &s_timer_handle);
435  timer_start(TIMER_GROUP_0, TIMER_0);
436 
437 #elif IS_ESP32()
438  static const i2s_config_t i2s_config = {
439 #if (ESP32_AUDIO_OUT_MODE == PT8211_DAC) || (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S)
440  .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
441 #elif (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC)
442  .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
443 #endif
444  .sample_rate = AUDIO_RATE * PDM_RESOLUTION,
445  .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // only the top 8 bits will actually be used by the internal DAC, but using 8 bits straight away seems buggy
446  .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // always use stereo output. mono seems to be buggy, and the overhead is insignifcant on the ESP32
447  .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB), // this appears to be the correct setting for internal DAC and PT8211, but not for other dacs
448  .intr_alloc_flags = 0, // default interrupt priority
449  .dma_buf_count = 8, // 8*128 bytes of buffer corresponds to 256 samples (2 channels, see above, 2 bytes per sample per channel)
450  .dma_buf_len = 128,
451  .use_apll = false
452  };
453 
454  i2s_driver_install(i2s_num, &i2s_config, 0, NULL);
455  #if (ESP32_AUDIO_OUT_MODE == PT8211_DAC) || (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S)
456  static const i2s_pin_config_t pin_config = {
457  .bck_io_num = ESP32_I2S_BCK_PIN,
458  .ws_io_num = ESP32_I2S_WS_PIN,
459  .data_out_num = ESP32_I2S_DATA_PIN,
460  .data_in_num = -1
461  };
462  i2s_set_pin((i2s_port_t)i2s_num, &pin_config);
463  #elif (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC)
464  i2s_set_pin((i2s_port_t)i2s_num, NULL);
465  i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
466  #endif
467  i2s_zero_dma_buffer((i2s_port_t)i2s_num);
468 
469 #elif IS_STM32()
470  audio_update_timer.pause();
471  //audio_update_timer.setPeriod(1000000UL / AUDIO_RATE);
472  // Manually calculate prescaler and overflow instead of using setPeriod, to avoid rounding errors
473  uint32_t period_cyc = F_CPU / AUDIO_RATE;
474  uint16_t prescaler = (uint16_t)(period_cyc / 65535 + 1);
475  uint16_t overflow = (uint16_t)((period_cyc + (prescaler / 2)) / prescaler);
476  audio_update_timer.setPrescaleFactor(prescaler);
477  audio_update_timer.setOverflow(overflow);
478  audio_update_timer.setChannel1Mode(TIMER_OUTPUT_COMPARE);
479  audio_update_timer.setCompare(TIMER_CH1,
480  1); // Interrupt 1 count after each update
481  audio_update_timer.attachCompare1Interrupt(defaultAudioOutput);
482  audio_update_timer.refresh();
483  audio_update_timer.resume();
484 
485 #if (EXTERNAL_AUDIO_OUTPUT != true)
486  pinMode(AUDIO_CHANNEL_1_PIN, PWM);
487 #if (AUDIO_MODE == HIFI)
488  pinMode(AUDIO_CHANNEL_1_PIN_HIGH, PWM);
489 #elif (STEREO_HACK == true)
490  pinMode(AUDIO_CHANNEL_2_PIN, PWM);
491 #endif
492 
493 #define MAX_CARRIER_FREQ (F_CPU / (1 << AUDIO_BITS_PER_CHANNEL))
494 #if MAX_CARRIER_FREQ < AUDIO_RATE
495 #error Configured audio resolution is definitely too high at the configured audio rate (and the given CPU speed)
496 #elif MAX_CARRIER_FREQ < (AUDIO_RATE * 3)
497 #warning Configured audio resolution may be higher than optimal at the configured audio rate (and the given CPU speed)
498 #endif
499 
500 #if MAX_CARRIER_FREQ < (AUDIO_RATE * 5)
501  // Generate as fast a carrier as possible
502  audio_pwm_timer.setPrescaleFactor(1);
503 #else
504  // No point in generating arbitrarily high carrier frequencies. In fact, if
505  // there _is_ any headroom, give the PWM pin more time to swing from HIGH to
506  // LOW and BACK, cleanly
507  audio_pwm_timer.setPrescaleFactor((int)MAX_CARRIER_FREQ / (AUDIO_RATE * 5));
508 #endif
509  audio_pwm_timer.setOverflow(
510  1 << AUDIO_BITS_PER_CHANNEL); // Allocate enough room to write all
511  // intended bits
512 #endif
513 
514 #elif IS_ESP8266() && (EXTERNAL_AUDIO_OUTPUT == true) && (BYPASS_MOZZI_OUTPUT_BUFFER != true) // for external audio output, set up a timer running a audio rate
515  timer1_isr_init();
516  timer1_attachInterrupt(defaultAudioOutput);
517  timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP);
518  timer1_write(F_CPU / AUDIO_RATE);
519 #elif IS_ESP8266()
520 #if (ESP_AUDIO_OUT_MODE == PDM_VIA_SERIAL)
521  Serial1.begin(
522  AUDIO_RATE * (PDM_RESOLUTION * 40), SERIAL_8N1,
523  SERIAL_TX_ONLY); // Note: PDM_RESOLUTION corresponds to packets of 32
524  // encoded bits However, the UART (unfortunately) adds a
525  // start and stop bit each around each byte, thus sending
526  // a total to 40 bits per audio sample per
527  // PDM_RESOLUTION.
528  // set up a timer to copy from Mozzi output_buffer into Serial TX buffer
529  timer1_isr_init();
530  timer1_attachInterrupt(esp8266_serial_audio_output);
531  // UART FIFO buffer size is 128 bytes. To be on the safe side, we keep the
532  // interval to the time needed to write half of that. PDM_RESOLUTION * 4 bytes
533  // per sample written.
534  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
535  timer1_write(F_CPU / (AUDIO_RATE * PDM_RESOLUTION));
536 #else
537  i2s_begin();
538 #if (ESP_AUDIO_OUT_MODE == PDM_VIA_I2S)
539  pinMode(2, INPUT); // Set the two unneeded I2S pins to input mode, to reduce
540  // side effects
541  pinMode(15, INPUT);
542 #endif
543  i2s_set_rate(AUDIO_RATE * PDM_RESOLUTION);
544  if (output_buffer_size == 0)
545  output_buffer_size =
546  i2s_available(); // Do not reset count when stopping / restarting
547 #endif
548 #endif
549 }
550 
551 #elif IS_AVR() && (EXTERNAL_AUDIO_OUTPUT == true)
552 static void startAudioStandard() {
553  backupPreMozziTimer1();
554  Timer1.initializeCPUCycles(
555  F_CPU / AUDIO_RATE,
556  PHASE_FREQ_CORRECT); // set period, phase and frequency correct
557  TIMSK1 = _BV(TOIE1); // Overflow Interrupt Enable (when not using
558  // Timer1.attachInterrupt())
559 }
560 
561 ISR(TIMER1_OVF_vect, ISR_BLOCK) {
562  defaultAudioOutput();
563 }
564 
565 #else
566 
567 // avr architecture
568 static void startAudioStandard() {
569  backupPreMozziTimer1();
570 
571  pinMode(AUDIO_CHANNEL_1_PIN, OUTPUT); // set pin to output for audio
572  // pinMode(AUDIO_CHANNEL_2_PIN, OUTPUT); // set pin to output for audio
573 #if (AUDIO_MODE == STANDARD)
574  Timer1.initializeCPUCycles(
575  F_CPU / AUDIO_RATE,
576  PHASE_FREQ_CORRECT); // set period, phase and frequency correct
577 #else // (AUDIO_MODE == STANDARD_PLUS)
578  Timer1.initializeCPUCycles(F_CPU / PWM_RATE,
579  FAST); // fast mode enables higher PWM rate
580 #endif
581  Timer1.pwm(AUDIO_CHANNEL_1_PIN,
582  AUDIO_BIAS); // pwm pin, 50% of Mozzi's duty cycle, ie. 0 signal
583 #if (STEREO_HACK == true)
584  Timer1.pwm(AUDIO_CHANNEL_2_PIN, AUDIO_BIAS); // sets pin to output
585 #endif
586  TIMSK1 = _BV(TOIE1); // Overflow Interrupt Enable (when not using
587  // Timer1.attachInterrupt())
588 }
589 
590 /* Interrupt service routine moves sound data from the output buffer to the
591 Arduino output register, running at AUDIO_RATE. */
592 
593 ISR(TIMER1_OVF_vect, ISR_BLOCK) {
594 
595 #if (AUDIO_MODE == STANDARD_PLUS) &&
596  (AUDIO_RATE == 16384) // only update every second ISR, if lower audio rate
597  static boolean alternate;
598  alternate = !alternate;
599  if (alternate) return;
600 #endif
601 
602  defaultAudioOutput();
603 }
604 // end avr
605 #endif
606 // end STANDARD
607 
608 //-----------------------------------------------------------------------------------------------------------------
609 #elif IS_AVR() && (AUDIO_MODE == HIFI)
610 
611 static void startAudioHiFi() {
612  backupPreMozziTimer1();
613  // pwm on timer 1
614  pinMode(AUDIO_CHANNEL_1_highByte_PIN,
615  OUTPUT); // set pin to output for audio, use 3.9k resistor
616  pinMode(AUDIO_CHANNEL_1_lowByte_PIN,
617  OUTPUT); // set pin to output for audio, use 499k resistor
618  Timer1.initializeCPUCycles(
619  F_CPU / 125000,
620  FAST); // set period for 125000 Hz fast pwm carrier frequency = 14 bits
621  Timer1.pwm(AUDIO_CHANNEL_1_highByte_PIN,
622  0); // pwm pin, 0% duty cycle, ie. 0 signal
623  Timer1.pwm(AUDIO_CHANNEL_1_lowByte_PIN,
624  0); // pwm pin, 0% duty cycle, ie. 0 signal
625  // audio output interrupt on timer 2, sets the pwm levels of timer 1
626  setupTimer2();
627 }
628 
629 /* set up Timer 2 using modified FrequencyTimer2 library */
630 void dummy() {}
631 
632 static void backupPreMozziTimer2() {
633  // backup Timer2 register values
634 #if defined(TCCR2A)
635  pre_mozzi_TCCR2A = TCCR2A;
636  pre_mozzi_TCCR2B = TCCR2B;
637  pre_mozzi_OCR2A = OCR2A;
638  pre_mozzi_TIMSK2 = TIMSK2;
639 #elif defined(TCCR2)
640  pre_mozzi_TCCR2 = TCCR2;
641  pre_mozzi_OCR2 = OCR2;
642  pre_mozzi_TIMSK = TIMSK;
643 #elif defined(TCCR4A)
644  pre_mozzi_TCCR4B = TCCR4A;
645  pre_mozzi_TCCR4B = TCCR4B;
646  pre_mozzi_TCCR4B = TCCR4C;
647  pre_mozzi_TCCR4B = TCCR4D;
648  pre_mozzi_TCCR4B = TCCR4E;
649  pre_mozzi_OCR4C = OCR4C;
650  pre_mozzi_TIMSK4 = TIMSK4;
651 #endif
652 }
653 
654 // audio output interrupt on timer 2 (or 4 on ATMEGA32U4 cpu), sets the pwm
655 // levels of timer 2
656 static void setupTimer2() {
657  backupPreMozziTimer2(); // to reset while pausing
658  unsigned long period = F_CPU / AUDIO_RATE;
659  FrequencyTimer2::setPeriodCPUCycles(period);
660  FrequencyTimer2::setOnOverflow(dummy);
661  FrequencyTimer2::enable();
662 }
663 
664 #if defined(TIMER2_COMPA_vect)
665 ISR(TIMER2_COMPA_vect)
666 #elif defined(TIMER2_COMP_vect)
667 ISR(TIMER2_COMP_vect)
668 #elif defined(TIMER4_COMPA_vect)
669 ISR(TIMER4_COMPA_vect)
670 #else
671 #error
672  "This board does not have a hardware timer which is compatible with FrequencyTimer2"
673 void dummy_function(void)
674 #endif
675 {
676  defaultAudioOutput();
677 }
678 
679 // end of HIFI
680 
681 #endif
682 
683 //-----------------------------------------------------------------------------------------------------------------
684 
685 static void startControl(unsigned int control_rate_hz) {
686  update_control_timeout = AUDIO_RATE / control_rate_hz;
687 }
688 
689 void startMozzi(int control_rate_hz) {
690  setupMozziADC(); // you can use setupFastAnalogRead() with FASTER or FASTEST
691  // in setup() if desired (not for Teensy 3.* )
692  // delay(200); // so AutoRange doesn't read 0 to start with
693  startControl(control_rate_hz);
694 #if (AUDIO_MODE == STANDARD) || (AUDIO_MODE == STANDARD_PLUS) ||
695  IS_STM32() // Sorry, this is really hacky. But on STM32 regular and HIFI
696  // audio modes are so similar to set up, that we do it all in one
697  // function.
698  startAudioStandard();
699 #elif (AUDIO_MODE == HIFI)
700  startAudioHiFi();
701 #endif
702 }
703 
704 void stopMozzi() {
705 #if IS_TEENSY3()
706  timer1.end();
707 #elif IS_STM32()
708  audio_update_timer.pause();
709 #elif IS_ESP8266()
710 #if (ESP_AUDIO_OUT_MODE != PDM_VIA_SERIAL)
711  i2s_end();
712 #else
713  timer1_disable();
714 #endif
715 #elif IS_SAMD21()
716 #elif IS_ESP32()
717 #else
718 
719  noInterrupts();
720 
721  // restore backed up register values
722  TCCR1A = pre_mozzi_TCCR1A;
723  TCCR1B = pre_mozzi_TCCR1B;
724  OCR1A = pre_mozzi_OCR1A;
725 
726  TIMSK1 = pre_mozzi_TIMSK1;
727 
728 #if (AUDIO_MODE == HIFI)
729 #if defined(TCCR2A)
730  TCCR2A = pre_mozzi_TCCR2A;
731  TCCR2B = pre_mozzi_TCCR2B;
732  OCR2A = pre_mozzi_OCR2A;
733  TIMSK2 = pre_mozzi_TIMSK2;
734 #elif defined(TCCR2)
735  TCCR2 = pre_mozzi_TCCR2;
736  OCR2 = pre_mozzi_OCR2;
737  TIMSK = pre_mozzi_TIMSK;
738 #elif defined(TCCR4A)
739  TCCR4B = pre_mozzi_TCCR4A;
740  TCCR4B = pre_mozzi_TCCR4B;
741  TCCR4B = pre_mozzi_TCCR4C;
742  TCCR4B = pre_mozzi_TCCR4D;
743  TCCR4B = pre_mozzi_TCCR4E;
744  OCR4C = pre_mozzi_OCR4C;
745  TIMSK4 = pre_mozzi_TIMSK4;
746 #endif
747 #endif
748 #endif
749  interrupts();
750 }
751 
752 unsigned long audioTicks() {
753 #if (BYPASS_MOZZI_OUTPUT_BUFFER != true)
754  return output_buffer.count();
755 #elif IS_ESP32()
756  // TODO: This is not entirely accurate, as it does not account for samples still in the buffer
757  // and not yet written to output. There does not seem to be an API to retrieve I2S-buffer
758  // fill state on ESP32.
759  return samples_written_to_buffer;
760 #elif (IS_ESP8266() && (ESP_AUDIO_OUT_MODE == PDM_VIA_I2S) && (PDM_RESOLUTION != 1))
761  return (samples_written_to_buffer -
762  ((output_buffer_size - i2s_available()) / PDM_RESOLUTION));
763 #else
764  return (samples_written_to_buffer - (output_buffer_size - i2s_available()));
765 #endif
766 }
767 
768 unsigned long mozziMicros() { return audioTicks() * MICROS_PER_AUDIO_TICK; }
769 
770 // Unmodified TimerOne.cpp has TIMER3_OVF_vect.
771 // Watch out if you update the library file.
772 // The symptom will be no sound.
773 // ISR(TIMER1_OVF_vect)
774 // {
775 // Timer1.isrCallback();
776 // }
unsigned long mozziMicros()
An alternative for Arduino time functions like micros() and millis().
Definition: MozziGuts.cpp:768
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
Definition: MozziGuts.cpp:704
#define AUDIO_MODE
AUDIO_MODE holds the audio mode setting.
Definition: mozzi_config.h:28
#define HIFI
Definition: MozziGuts.h:155
#define STEREO_HACK
This sets an option for stereo output, a hack which requires variables audio_signal_1 and audio_signa...
Definition: mozzi_config.h:92
#define IS_SAMD21()
void updateControl()
This is where you put your control code.
#define AUDIO_RATE
Holds the audio rate setting.
Definition: mozzi_config.h:62
Circular buffer object.
#define IS_STM32()
#define STANDARD_PLUS
Definition: MozziGuts.h:154
void audioHook()
This is required in Arduino&#39;s loop().
Definition: MozziGuts.cpp:325
#define IS_AVR()
#define IS_TEENSY3()
unsigned long audioTicks()
An alternative for Arduino time functions like micros() and millis().
Definition: MozziGuts.cpp:752
#define AudioOutput_t
Definition: AudioOutput.h:59
#define MICROS_PER_AUDIO_TICK
Definition: MozziGuts.h:172
#define CACHED_FUNCTION_ATTR
void startMozzi(int control_rate_hz=CONTROL_RATE)
Sets up the timers for audio and control rate processes, storing the timer registers so they can be r...
Definition: MozziGuts.cpp:689
#define STANDARD
Used to set AUDIO_MODE to STANDARD, STANDARD_PLUS, or HIFI.
Definition: MozziGuts.h:153
#define EXTERNAL_AUDIO_OUTPUT
Defining this option as true in mozzi_config.h allows to completely customize the audio output...
Definition: mozzi_config.h:99
#define IS_ESP8266()
#define IS_ESP32()