Mozzi  version v1.1.0
sound synthesis library for Arduino
MozziGuts_impl_STM32.hpp
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 #include "HardwareTimer.h"
14 
15 ////// BEGIN analog input code ////////
16 #define MOZZI_FAST_ANALOG_IMPLEMENTED
17 //#include <STM32ADC.h> // Disabled, here. See AudioConfigSTM32.h
18 STM32ADC adc(ADC1);
19 uint8_t stm32_current_adc_pin; // TODO: this is actually a "channel" according to our terminology, but "channel" and "pin" are equal on this platform
20 #define getADCReading() adc.getData()
21 #define channelNumToIndex(channel) STM32PinMap(channel)
22 uint8_t adcPinToChannelNum(uint8_t pin) {
23  return pin;
24 }
25 
26 void adcStartConversion(uint8_t channel) {
27  stm32_current_adc_pin = channel;
28  adc.setPins(&stm32_current_adc_pin, 1);
29  adc.startConversion();
30 }
31 
32 static void startSecondADCReadOnCurrentChannel() {
33  adc.setPins(&stm32_current_adc_pin, 1);
34  adc.startConversion();
35 }
36 
37 void stm32_adc_eoc_handler() {
38  advanceADCStep();
39 }
40 
41 void setupFastAnalogRead(int8_t speed) {
42  // NOTE: These picks are pretty arbitrary. Further available options are 7_5, 28_5, 55_5, 71_5 and 239_5 (i.e. 7.5 ADC cylces, etc.)
43  if (speed == FASTEST_ADC) adc.setSampleRate(ADC_SMPR_1_5);
44  else if (speed == FASTER_ADC) adc.setSampleRate(ADC_SMPR_13_5);
45  else (adc.setSampleRate(ADC_SMPR_41_5));
46 }
47 
48 void setupMozziADC(int8_t speed) {
49  adc.attachInterrupt(stm32_adc_eoc_handler);
50 }
51 
52 
53 inline uint8_t STM32PinMap(uint8_t pin)
54 {
55  if (pin > 15) return pin-8;
56  else return pin;
57 }
58 
59 ////// END analog input code ////////
60 
61 
62 
63 //// BEGIN AUDIO OUTPUT code ///////
64 #if (EXTERNAL_AUDIO_OUTPUT == true)
65 HardwareTimer audio_update_timer(2);
66 #else
67 HardwareTimer audio_update_timer(AUDIO_UPDATE_TIMER);
68 HardwareTimer audio_pwm_timer(AUDIO_PWM_TIMER);
69 
70 #include "AudioConfigSTM32.h"
71 inline void audioOutput(const AudioOutput f) {
72 # if (AUDIO_MODE == HIFI)
73  pwmWrite(AUDIO_CHANNEL_1_PIN, (f.l()+AUDIO_BIAS) & ((1 << AUDIO_BITS_PER_CHANNEL) - 1));
75 # else
76  pwmWrite(AUDIO_CHANNEL_1_PIN, f.l()+AUDIO_BIAS);
77 # if (AUDIO_CHANNELS > 1)
78  pwmWrite(AUDIO_CHANNEL_2_PIN, f.r()+AUDIO_BIAS);
79 # endif
80 #endif
81 }
82 #endif
83 
84 static void startAudio() {
85  audio_update_timer.pause();
86  //audio_update_timer.setPeriod(1000000UL / AUDIO_RATE);
87  // Manually calculate prescaler and overflow instead of using setPeriod, to avoid rounding errors
88  uint32_t period_cyc = F_CPU / AUDIO_RATE;
89  uint16_t prescaler = (uint16_t)(period_cyc / 65535 + 1);
90  uint16_t overflow = (uint16_t)((period_cyc + (prescaler / 2)) / prescaler);
91  audio_update_timer.setPrescaleFactor(prescaler);
92  audio_update_timer.setOverflow(overflow);
93  audio_update_timer.setChannel1Mode(TIMER_OUTPUT_COMPARE);
94  audio_update_timer.setCompare(TIMER_CH1,
95  1); // Interrupt 1 count after each update
96  audio_update_timer.attachCompare1Interrupt(defaultAudioOutput);
97  audio_update_timer.refresh();
98  audio_update_timer.resume();
99 
100 #if (EXTERNAL_AUDIO_OUTPUT != true)
101  pinMode(AUDIO_CHANNEL_1_PIN, PWM);
102 # if (AUDIO_MODE == HIFI)
103  pinMode(AUDIO_CHANNEL_1_PIN_HIGH, PWM);
104 # elif (AUDIO_CHANNELS > 1)
105  pinMode(AUDIO_CHANNEL_2_PIN, PWM);
106 # endif
107 
108 # define MAX_CARRIER_FREQ (F_CPU / (1 << AUDIO_BITS_PER_CHANNEL))
109 # if MAX_CARRIER_FREQ < AUDIO_RATE
110 # error Configured audio resolution is definitely too high at the configured audio rate (and the given CPU speed)
111 # elif MAX_CARRIER_FREQ < (AUDIO_RATE * 3)
112 # warning Configured audio resolution may be higher than optimal at the configured audio rate (and the given CPU speed)
113 # endif
114 
115 # if MAX_CARRIER_FREQ < (AUDIO_RATE * 5)
116  // Generate as fast a carrier as possible
117  audio_pwm_timer.setPrescaleFactor(1);
118 # else
119  // No point in generating arbitrarily high carrier frequencies. In fact, if
120  // there _is_ any headroom, give the PWM pin more time to swing from HIGH to
121  // LOW and BACK, cleanly
122  audio_pwm_timer.setPrescaleFactor((int)MAX_CARRIER_FREQ / (AUDIO_RATE * 5));
123 # endif
124  audio_pwm_timer.setOverflow(
125  1 << AUDIO_BITS_PER_CHANNEL); // Allocate enough room to write all
126  // intended bits
127 #endif
128 }
129 
130 void stopMozzi() {
131  audio_update_timer.pause();
132 }
133 
134 //// END AUDIO OUTPUT code ///////
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
#define AUDIO_BITS_PER_CHANNEL
#define AUDIO_CHANNEL_1_PIN
#define AUDIO_CHANNEL_1_PIN_HIGH
void setupFastAnalogRead(int8_t speed)
NOTE: Code needed to set up faster than usual analog reads, e.g.
#define AUDIO_BIAS
Definition: MozziGuts.h:229