diff --git a/MozziGuts.h b/MozziGuts.h index 4453ab6fe..eb3bb9689 100644 --- a/MozziGuts.h +++ b/MozziGuts.h @@ -136,7 +136,15 @@ are called. */ void audioHook(); +/** @ingroup analog + +See getAudioInput(). The template parameter specifies the desired value range in bits. */ +template uint16_t getAudioInput(); + +/** @ingroup analog +See getAudioInput(). Equivalent to getAudioInput<16>(). */ +template inline uint16_t getAudioInput16() { return getAudioInput<16>(); } /** @ingroup analog This returns audio input from the input buffer, if @@ -150,10 +158,19 @@ and http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/ . A circuit and instructions for amplifying and biasing a microphone signal can be found at http://www.instructables.com/id/Arduino-Audio-Input/?ALLSTEPS + +@note The value range returned by this function follows the same rules as detailed in the documentation + for mozziAnalogRead(): For portable code, define MOZZI_ANALGO_READ_RESOLUTION at the top of your + sketch, or use the templated version of this function. + @return audio data from the input buffer */ -#if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) -int getAudioInput(); +#if defined(FOR_DOXYGEN_ONLY) || (!MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)) +#if defined(FOR_DOXYGEN_ONLY) || defined(MOZZI_ANALOG_READ_RESOLUTION) +inline uint16_t getAudioInput() { return getAudioInput(); }; +#else +MOZZI_DEPRECATED("2.0", "This use of getAudioInput() is not portable. Refer to the API documentation for suggested alternatives") inline uint16_t getAudioInput() { return getAudioInput(); }; +#endif #endif diff --git a/examples/02.Control/Control_Echo_Theremin/Control_Echo_Theremin.ino b/examples/02.Control/Control_Echo_Theremin/Control_Echo_Theremin.ino index 47d1626e6..96b874063 100644 --- a/examples/02.Control/Control_Echo_Theremin/Control_Echo_Theremin.ino +++ b/examples/02.Control/Control_Echo_Theremin/Control_Echo_Theremin.ino @@ -57,7 +57,7 @@ void setup(){ void updateControl(){ - int bumpy_input = mozziAnalogRead(INPUT_PIN); + int bumpy_input = mozziAnalogRead<10>(INPUT_PIN); // request reading at 10-bit resolution, i.e. 0-1023 averaged = kAverage.next(bumpy_input); aSin0.setFreq(averaged); aSin1.setFreq(kDelay.next(averaged)); diff --git a/examples/03.Sensors/Knob_LDR_x2_WavePacket/Knob_LDR_x2_WavePacket.ino b/examples/03.Sensors/Knob_LDR_x2_WavePacket/Knob_LDR_x2_WavePacket.ino index 4be6ea6b8..2dc1e569a 100644 --- a/examples/03.Sensors/Knob_LDR_x2_WavePacket/Knob_LDR_x2_WavePacket.ino +++ b/examples/03.Sensors/Knob_LDR_x2_WavePacket/Knob_LDR_x2_WavePacket.ino @@ -37,6 +37,8 @@ Tim Barrass 2013, CC by-nc-sa. */ +#define MOZZI_ANALOG_READ_RESOLUTION 10 // code below assumes readings to be in the classic 10-bit (0-1023) range +#include #include #include #include diff --git a/examples/03.Sensors/Knob_LightLevel_FMsynth/Knob_LightLevel_FMsynth.ino b/examples/03.Sensors/Knob_LightLevel_FMsynth/Knob_LightLevel_FMsynth.ino index 0ac2b9ab0..bd60891ed 100644 --- a/examples/03.Sensors/Knob_LightLevel_FMsynth/Knob_LightLevel_FMsynth.ino +++ b/examples/03.Sensors/Knob_LightLevel_FMsynth/Knob_LightLevel_FMsynth.ino @@ -68,7 +68,7 @@ void setup(){ void updateControl(){ // read the knob - int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023 + int knob_value = mozziAnalogRead<10>(KNOB_PIN); // value is 0-1023 // map the knob to carrier frequency int carrier_freq = kMapCarrierFreq(knob_value); @@ -81,7 +81,7 @@ void updateControl(){ aModulator.setFreq(mod_freq); // read the light dependent resistor on the Analog input pin - int light_level= mozziAnalogRead(LDR_PIN); // value is 0-1023 + int light_level= mozziAnalogRead<10>(LDR_PIN); // value is 0-1023 // print the value to the Serial monitor for debugging Serial.print("light_level = "); diff --git a/examples/03.Sensors/Knob_LightLevel_x2_FMsynth/Knob_LightLevel_x2_FMsynth.ino b/examples/03.Sensors/Knob_LightLevel_x2_FMsynth/Knob_LightLevel_x2_FMsynth.ino index 6aba9b6cf..364cca099 100644 --- a/examples/03.Sensors/Knob_LightLevel_x2_FMsynth/Knob_LightLevel_x2_FMsynth.ino +++ b/examples/03.Sensors/Knob_LightLevel_x2_FMsynth/Knob_LightLevel_x2_FMsynth.ino @@ -36,6 +36,7 @@ Tim Barrass 2013, CC by-nc-sa. */ +#define MOZZI_ANALOG_READ_RESOLUTION 10 // code below assumes readings to be in the classic 10-bit (0-1023) range #include #include // oscillator #include // table for Oscils to play diff --git a/examples/03.Sensors/Light_Temperature_Detuned/Light_Temperature_Detuned.ino b/examples/03.Sensors/Light_Temperature_Detuned/Light_Temperature_Detuned.ino index 5d051071b..20f30ec0f 100644 --- a/examples/03.Sensors/Light_Temperature_Detuned/Light_Temperature_Detuned.ino +++ b/examples/03.Sensors/Light_Temperature_Detuned/Light_Temperature_Detuned.ino @@ -102,8 +102,8 @@ void loop(){ void updateControl(){ // read analog inputs - int temperature = mozziAnalogRead(THERMISTOR_PIN); // not calibrated to degrees! - int light_input = mozziAnalogRead(LDR_PIN); + int temperature = mozziAnalogRead<10>(THERMISTOR_PIN); // not calibrated to degrees! Simply a 10-bit voltage reading (0-1023) + int light_input = mozziAnalogRead<10>(LDR_PIN); float base_freq_offset = OFFSET_SCALE*temperature; float divergence = DIVERGENCE_SCALE*light_input; diff --git a/examples/03.Sensors/Light_Temperature_Multi_Oscil/Light_Temperature_Multi_Oscil.ino b/examples/03.Sensors/Light_Temperature_Multi_Oscil/Light_Temperature_Multi_Oscil.ino index 48b84aafb..663b6d866 100644 --- a/examples/03.Sensors/Light_Temperature_Multi_Oscil/Light_Temperature_Multi_Oscil.ino +++ b/examples/03.Sensors/Light_Temperature_Multi_Oscil/Light_Temperature_Multi_Oscil.ino @@ -94,8 +94,8 @@ void updateControl(){ static float previous_pulse_freq; // read analog inputs - int temperature = mozziAnalogRead(THERMISTOR_PIN); // not calibrated to degrees! - int light = mozziAnalogRead(LDR_PIN); + int temperature = mozziAnalogRead<10>(THERMISTOR_PIN); // not calibrated to degrees! + int light = mozziAnalogRead<10>(LDR_PIN); // map light reading to volume pulse frequency float pulse_freq = (float)light/256; diff --git a/examples/03.Sensors/Piezo_Frequency/Piezo_Frequency.ino b/examples/03.Sensors/Piezo_Frequency/Piezo_Frequency.ino index 8a0aed82d..dcf4fd51b 100644 --- a/examples/03.Sensors/Piezo_Frequency/Piezo_Frequency.ino +++ b/examples/03.Sensors/Piezo_Frequency/Piezo_Frequency.ino @@ -47,7 +47,9 @@ void setup(){ void updateControl(){ - // read the piezo + // read the piezo. We request 12-bits resolution, here, for values of 0-4095. Some boards + // will actually provide that much accuracy, for others the readings are simply shifted to a + // larger range. int piezo_value = mozziAnalogRead(PIEZO_PIN); // value is 0-1023 // print the value to the Serial monitor for debugging @@ -55,8 +57,6 @@ void updateControl(){ Serial.print(piezo_value); Serial.print("\t \t"); // prints 2 tabs - int frequency = piezo_value*3; // calibrate - // print the frequency to the Serial monitor for debugging Serial.print("frequency = "); Serial.print(frequency); diff --git a/examples/03.Sensors/Piezo_SampleScrubber/Piezo_SampleScrubber.ino b/examples/03.Sensors/Piezo_SampleScrubber/Piezo_SampleScrubber.ino index bcbfddc4c..3ddf9c7ff 100644 --- a/examples/03.Sensors/Piezo_SampleScrubber/Piezo_SampleScrubber.ino +++ b/examples/03.Sensors/Piezo_SampleScrubber/Piezo_SampleScrubber.ino @@ -59,7 +59,7 @@ void setup(){ void updateControl(){ // read the pot - int sensor_value = mozziAnalogRead(INPUT_PIN); // value is 0-1023 + int sensor_value = mozziAnalogRead<10>(INPUT_PIN); // value is 0-1023 // map it to an 8 bit range for efficient calculations in updateAudio int target = ((long) sensor_value * BLAHBLAH4B_NUM_CELLS) >> 10; // >> 10 is / 1024 diff --git a/examples/03.Sensors/Piezo_SampleTrigger/Piezo_SampleTrigger.ino b/examples/03.Sensors/Piezo_SampleTrigger/Piezo_SampleTrigger.ino index 2adffe0ef..d218fdc3f 100644 --- a/examples/03.Sensors/Piezo_SampleTrigger/Piezo_SampleTrigger.ino +++ b/examples/03.Sensors/Piezo_SampleTrigger/Piezo_SampleTrigger.ino @@ -55,7 +55,7 @@ void setup(){ void updateControl(){ // read the knob - int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023 + int knob_value = mozziAnalogRead<10>(KNOB_PIN); // value is 0-1023 // map it to values between 0.1 and about double the recorded pitch float pitch = (recorded_pitch * (float) knob_value / 512.f) + 0.1f; @@ -64,7 +64,7 @@ void updateControl(){ aSample.setFreq(pitch); // read the piezo - int piezo_value = mozziAnalogRead(PIEZO_PIN); // value is 0-1023 + int piezo_value = mozziAnalogRead<10>(PIEZO_PIN); // value is 0-1023 // print the value to the Serial monitor for debugging Serial.print("piezo value = "); diff --git a/examples/03.Sensors/Piezo_Switch_Pitch/Piezo_Switch_Pitch.ino b/examples/03.Sensors/Piezo_Switch_Pitch/Piezo_Switch_Pitch.ino index 4dded0b8f..b63a6c7a2 100644 --- a/examples/03.Sensors/Piezo_Switch_Pitch/Piezo_Switch_Pitch.ino +++ b/examples/03.Sensors/Piezo_Switch_Pitch/Piezo_Switch_Pitch.ino @@ -79,7 +79,7 @@ void buttonChangePitch(){ void updateControl(){ // read the piezo - int piezo_value = mozziAnalogRead(PIEZO_PIN); // value is 0-1023 + int piezo_value = mozziAnalogRead<10>(PIEZO_PIN); // value is 0-1023 // print the value to the Serial monitor for debugging Serial.print("piezo value = "); diff --git a/examples/03.Sensors/Volume_Knob/Volume_Knob.ino b/examples/03.Sensors/Volume_Knob/Volume_Knob.ino index fd21e715f..7863d53f9 100644 --- a/examples/03.Sensors/Volume_Knob/Volume_Knob.ino +++ b/examples/03.Sensors/Volume_Knob/Volume_Knob.ino @@ -53,11 +53,9 @@ void setup(){ void updateControl(){ - // read the variable resistor for volume - int sensor_value = mozziAnalogRead(INPUT_PIN); // value is 0-1023 - - // map it to an 8 bit range for efficient calculations in updateAudio - volume = map(sensor_value, 0, 1023, 0, 255); + // read the variable resistor for volume. We specifically request only 8 bits of resolution, here, which + // is less than the default on most platforms, but a convenient range to work with, where accuracy is not too important. + volume = mozziAnalogRead<8>(INPUT_PIN); // print the value to the Serial monitor for debugging Serial.print("volume = "); diff --git a/examples/03.Sensors/Volume_Knob_LightLevel_Frequency/Volume_Knob_LightLevel_Frequency.ino b/examples/03.Sensors/Volume_Knob_LightLevel_Frequency/Volume_Knob_LightLevel_Frequency.ino index 98a9d7bd2..3edcc2f91 100644 --- a/examples/03.Sensors/Volume_Knob_LightLevel_Frequency/Volume_Knob_LightLevel_Frequency.ino +++ b/examples/03.Sensors/Volume_Knob_LightLevel_Frequency/Volume_Knob_LightLevel_Frequency.ino @@ -56,11 +56,8 @@ void setup(){ void updateControl(){ - // read the potentiometer - int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023 - - // map it to an 8 bit volume range for efficient calculations in updateAudio - volume = knob_value >> 2; // 10 bits (0->1023) shifted right by 2 bits to give 8 bits (0->255) + // read the potentiometer as only 8 bit volume range for efficient calculations in updateAudio + volume = mozziAnalogRead<8>(KNOB_PIN); // value is 0-255 // print the value to the Serial monitor for debugging Serial.print("volume = "); @@ -68,7 +65,7 @@ void updateControl(){ Serial.print("\t"); // prints a tab // read the light dependent resistor - int light_level = mozziAnalogRead(LDR_PIN); // value is 0-1023 + int light_level = mozziAnalogRead<10>(LDR_PIN); // We request 10 bits, here, however. Value is 0-1023 // print the value to the Serial monitor for debugging Serial.print("light level = "); diff --git a/examples/04.Audio_Input/Audio_Input_with_Knob_Filter/Audio_Input_with_Knob_Filter.ino b/examples/04.Audio_Input/Audio_Input_with_Knob_Filter/Audio_Input_with_Knob_Filter.ino index 8c87b88ef..c78ccc8bc 100644 --- a/examples/04.Audio_Input/Audio_Input_with_Knob_Filter/Audio_Input_with_Knob_Filter.ino +++ b/examples/04.Audio_Input/Audio_Input_with_Knob_Filter/Audio_Input_with_Knob_Filter.ino @@ -44,8 +44,7 @@ void setup(){ void updateControl(){ - int knob = mozziAnalogRead(KNOB_PIN); - byte cutoff_freq = knob>>2; // range 0-255 + byte cutoff_freq = mozziAnalogRead<8>(KNOB_PIN); // range 0-255 lpf.setCutoffFreq(cutoff_freq); } diff --git a/examples/04.Audio_Input/Audio_and_Control_Input/Audio_and_Control_Input.ino b/examples/04.Audio_Input/Audio_and_Control_Input/Audio_and_Control_Input.ino index a7bf65823..f56764127 100644 --- a/examples/04.Audio_Input/Audio_and_Control_Input/Audio_and_Control_Input.ino +++ b/examples/04.Audio_Input/Audio_and_Control_Input/Audio_and_Control_Input.ino @@ -44,7 +44,7 @@ void setup() { void updateControl(){ for (int i=1;i(sensorPin); Serial.print(sensorValue); Serial.print(" Filtered = "); Serial.println(dcFiltered.next(sensorValue)); diff --git a/examples/05.Control_Filters/Line_vs_Smooth/Line_vs_Smooth.ino b/examples/05.Control_Filters/Line_vs_Smooth/Line_vs_Smooth.ino index 4d88d3c3e..76d42c0de 100644 --- a/examples/05.Control_Filters/Line_vs_Smooth/Line_vs_Smooth.ino +++ b/examples/05.Control_Filters/Line_vs_Smooth/Line_vs_Smooth.ino @@ -69,9 +69,9 @@ void setup(){ volatile unsigned int freq1; // global so it can be used in updateAudio, volatile to stop it getting changed while being used void updateControl(){ - Q16n16 freq0 = Q16n0_to_Q16n16(mozziAnalogRead(0)); // 0 to 1023, scaled up to Q16n16 format - freq1 = (unsigned int) mozziAnalogRead(1); // 0 to 1023 - aInterpolate.set(freq0, AUDIO_STEPS_PER_CONTROL); + Q16n16 freq0 = Q16n0_to_Q16n16(mozziAnalogRead<10>(0)); // 0 to 1023, scaled up to Q16n16 format + freq1 = (unsigned int) mozziAnalogRead<10>(1); // 0 to 1023 + aInterpolate.set(freq0, AUDIO_STEPS_PER_CONTROL); } diff --git a/examples/05.Control_Filters/RollingAverage/RollingAverage.ino b/examples/05.Control_Filters/RollingAverage/RollingAverage.ino index a9d58d7f0..e5993973b 100644 --- a/examples/05.Control_Filters/RollingAverage/RollingAverage.ino +++ b/examples/05.Control_Filters/RollingAverage/RollingAverage.ino @@ -42,7 +42,7 @@ void setup(){ void updateControl(){ - int bumpy_input = mozziAnalogRead(INPUT_PIN); + int bumpy_input = mozziAnalogRead<10>(INPUT_PIN); averaged = kAverage.next(bumpy_input); Serial.print("bumpy \t"); diff --git a/examples/05.Control_Filters/Thermistor_OverSample/Thermistor_OverSample.ino b/examples/05.Control_Filters/Thermistor_OverSample/Thermistor_OverSample.ino index 8ca4aa52f..c8a3147ef 100644 --- a/examples/05.Control_Filters/Thermistor_OverSample/Thermistor_OverSample.ino +++ b/examples/05.Control_Filters/Thermistor_OverSample/Thermistor_OverSample.ino @@ -69,7 +69,7 @@ void updateControl(){ static int counter, old_oversampled; // read the variable resistor - int sensor_value = mozziAnalogRead(INPUT_PIN); // value is 0-1023 + int sensor_value = mozziAnalogRead<10>(INPUT_PIN); // value is 0-1023 // get the next oversampled sensor value int oversampled = overSampler.next(sensor_value); diff --git a/examples/06.Synthesis/PDresonant/PDresonant.ino b/examples/06.Synthesis/PDresonant/PDresonant.ino index 3b78b47d8..436f80cae 100644 --- a/examples/06.Synthesis/PDresonant/PDresonant.ino +++ b/examples/06.Synthesis/PDresonant/PDresonant.ino @@ -120,13 +120,13 @@ void updateControl(){ //MIDI.read(); // analog joystick for controlling speed of modulation: assigned to attack, decay times and sustain level - //x_axis = mozziAnalogRead(X); - //y_axis = mozziAnalogRead(Y); + //x_axis = mozziAnalogRead<10>(X); + //y_axis = mozziAnalogRead<10>(Y); // for testing/demo without external input fakeMidiRead(); - x_axis = 512; //mozziAnalogRead(X); - y_axis = 512; // mozziAnalogRead(Y); + x_axis = 512; //mozziAnalogRead<10>(X); + y_axis = 512; // mozziAnalogRead<10>(Y); voice.update(); } diff --git a/examples/06.Synthesis/WavePacket_Double/WavePacket_Double.ino b/examples/06.Synthesis/WavePacket_Double/WavePacket_Double.ino index 4d1638599..850248468 100644 --- a/examples/06.Synthesis/WavePacket_Double/WavePacket_Double.ino +++ b/examples/06.Synthesis/WavePacket_Double/WavePacket_Double.ino @@ -52,9 +52,9 @@ void setup(){ void updateControl(){ - wavey.set(kAverageF.next(mozziAnalogRead(FUNDAMENTAL_PIN))+1, - kAverageBw.next(mozziAnalogRead(BANDWIDTH_PIN)), - kAverageCf.next(2*mozziAnalogRead(CENTREFREQ_PIN))); + wavey.set(kAverageF.next(mozziAnalogRead<10>(FUNDAMENTAL_PIN))+1, // 1-1024 + kAverageBw.next(mozziAnalogRead<10>(BANDWIDTH_PIN)), // 0-1023 + kAverageCf.next(mozziAnalogRead<11>(CENTREFREQ_PIN))); // 0-2047 } diff --git a/examples/06.Synthesis/WavePacket_Sample/WavePacket_Sample.ino b/examples/06.Synthesis/WavePacket_Sample/WavePacket_Sample.ino index d85114b07..88bf4d545 100644 --- a/examples/06.Synthesis/WavePacket_Sample/WavePacket_Sample.ino +++ b/examples/06.Synthesis/WavePacket_Sample/WavePacket_Sample.ino @@ -60,9 +60,9 @@ void setup(){ void updateControl(){ - int f = kAverageF.next(mozziAnalogRead(FUNDAMENTAL_PIN))+1; - int b = kAverageBw.next(mozziAnalogRead(BANDWIDTH_PIN)); - int cf = kAverageCf.next(2*mozziAnalogRead(CENTREFREQ_PIN)); + int f = kAverageF.next(mozziAnalogRead<10>(FUNDAMENTAL_PIN))+1; + int b = kAverageBw.next(mozziAnalogRead<10>(BANDWIDTH_PIN)); + int cf = kAverageCf.next(mozziAnalogRead<11>(CENTREFREQ_PIN)); wavey.set(f, b, cf); } diff --git a/examples/06.Synthesis/WavePacket_Single/WavePacket_Single.ino b/examples/06.Synthesis/WavePacket_Single/WavePacket_Single.ino index 6e58e4d7b..16a0a32b0 100644 --- a/examples/06.Synthesis/WavePacket_Single/WavePacket_Single.ino +++ b/examples/06.Synthesis/WavePacket_Single/WavePacket_Single.ino @@ -53,9 +53,9 @@ void setup(){ void updateControl(){ - wavey.set(kAverageF.next(mozziAnalogRead(FUNDAMENTAL_PIN))+1, - kAverageBw.next(mozziAnalogRead(BANDWIDTH_PIN)), - kAverageCf.next(2*mozziAnalogRead(CENTREFREQ_PIN))); + wavey.set(kAverageF.next(mozziAnalogRead<10>(FUNDAMENTAL_PIN))+1, + kAverageBw.next(mozziAnalogRead<10>(BANDWIDTH_PIN)), + kAverageCf.next(mozziAnalogRead<11>(CENTREFREQ_PIN))); } diff --git a/internal/MozziGuts.hpp b/internal/MozziGuts.hpp index 53b7251ae..4e8bcf15c 100644 --- a/internal/MozziGuts.hpp +++ b/internal/MozziGuts.hpp @@ -27,6 +27,11 @@ static void advanceADCStep(); // to be provided by platfor static void startSecondADCReadOnCurrentChannel(); // to be provided by platform implementation static uint8_t adc_count = 0; // needed below #endif + +// TODO: make this helper public? +template constexpr T smartShift(T value) { + return (BITS_IN > BITS_OUT) ? value >> (BITS_IN - BITS_OUT) : (BITS_IN < BITS_OUT) ? value << (BITS_OUT - BITS_IN) : value; +} } // Include the appropriate implementation @@ -126,20 +131,20 @@ __attribute__((noinline)) void adcStartReadCycle() { } } -int mozziAnalogRead(uint8_t pin) { +uint16_t mozziAnalogRead(uint8_t pin) { pin = adcPinToChannelNum(pin); // allow for channel or pin numbers; on most platforms other than AVR this has no effect. See note on pins/channels adc_channels_to_read.push(pin); return analog_readings[channelNumToIndex(pin)]; } #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) -static AudioOutputStorage_t audio_input; // holds the latest audio from input_buffer -AudioOutputStorage_t getAudioInput() { return audio_input; } +static uint16_t audio_input; // holds the latest audio from input_buffer +uint16_t getAudioInput() { return audio_input; } #endif #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1) // ring buffer for audio input -CircularBuffer input_buffer; // fixed size 256 +CircularBuffer input_buffer; // fixed size 256 #define audioInputAvailable() (!input_buffer.isEmpty()) #define readAudioInput() (input_buffer.read()) /** NOTE: Triggered at MOZZI_AUDIO_RATE via defaultAudioOutput(). In addition to the AUDIO_INPUT_PIN, at most one reading is taken for mozziAnalogRead(). */ @@ -190,7 +195,7 @@ inline void advanceADCStep() { #else MOZZI_ASSERT_EQUAL(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE) -int mozziAnalogRead(uint8_t pin) { +uint16_t mozziAnalogRead(uint8_t pin) { return analogRead(pin); } @@ -282,16 +287,17 @@ uint32_t MozziRandPrivate::z=521288629; #undef MOZZI__LEGACY_AUDIO_INPUT_IMPL // "export" publicly accessible functions defined in this file -// NOTE: unfortunately, we cannot just write using MozziPrivate::mozziMicros(), and that will conflict with, rather than define mozziMicros() -// we might want to rethink how this is done. What matters is that these functions are user accessible, though, while most of what we +// NOTE: unfortunately, we cannot just write "using MozziPrivate::mozziMicros()", etc. as that would conflict with, rather than define mozziMicros(). +// Instead, for now, we forward the global-scope functions to their implementations inside MozziPrivate. +// We might want to rethink how this is done. What matters is that these functions are user accessible, though, while most of what we // now keep in MozziPrivate is hidden away. -//unsigned long mozziMicros() { return MozziPrivate::mozziMicros(); }; +unsigned long mozziMicros() { return MozziPrivate::mozziMicros(); }; unsigned long audioTicks() { return MozziPrivate::audioTicks(); }; void startMozzi(int control_rate_hz) { MozziPrivate::startMozzi(control_rate_hz); }; void stopMozzi() { MozziPrivate::stopMozzi(); }; -int mozziAnalogRead(uint8_t pin) { return MozziPrivate::mozziAnalogRead(pin); }; +template uint16_t mozziAnalogRead(uint8_t pin) { return MozziPrivate::smartShift(MozziPrivate::mozziAnalogRead(pin));}; #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) -AudioOutputStorage_t getAudioInput() { return MozziPrivate::getAudioInput(); }; +template uint16_t getAudioInput() { return MozziPrivate::smartShift(MozziPrivate::getAudioInput()); }; #endif #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD) void setupMozziADC(int8_t speed) { MozziPrivate::setupMozziADC(speed); }; diff --git a/internal/config_checks_avr.h b/internal/config_checks_avr.h index a5033c760..25f59c0f7 100644 --- a/internal/config_checks_avr.h +++ b/internal/config_checks_avr.h @@ -133,6 +133,8 @@ #define MOZZI_AUDIO_BITS (2*MOZZI_AUDIO_BITS_PER_CHANNEL) #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 10 + // Step 2: Check // NOTE: This step is not technically required, but a good idea in any port diff --git a/internal/config_checks_esp32.h b/internal/config_checks_esp32.h index 2108bde9c..5a01959df 100644 --- a/internal/config_checks_esp32.h +++ b/internal/config_checks_esp32.h @@ -131,4 +131,6 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE) # define BYPASS_MOZZI_OUTPUT_BUFFER true #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 12 + #endif // #ifndef CONFIG_CHECK_ESP32_H diff --git a/internal/config_checks_esp8266.h b/internal/config_checks_esp8266.h index 3e6ab227b..ffa0a20aa 100644 --- a/internal/config_checks_esp8266.h +++ b/internal/config_checks_esp8266.h @@ -105,4 +105,6 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_BITS, 16) #define BYPASS_MOZZI_OUTPUT_BUFFER true #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 10 + #endif // #ifndef CONFIG_CHECK_ESP8266_H diff --git a/internal/config_checks_generic.h b/internal/config_checks_generic.h index 42ee55774..795081b97 100644 --- a/internal/config_checks_generic.h +++ b/internal/config_checks_generic.h @@ -119,6 +119,13 @@ MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE, MOZZI_ANALOG_RE # undef MOZZI__ANALOG_READ_NOT_CONFIGURED #endif +#if defined(MOZZI_ANALOG_READ_RESOLUTION) +# if (MOZZI_ANALOG_READ_RESOLUTION < 1) || (MOZZI_ANALOG_READ_RESOLUTION > 16) +// NOTE: We could certainly allow more than 16 bits, but then the data type would need to be adjusted/adjustable, accrodingly. +# error MOZZI_ANALOG_READ_RESOLUTION must be between 1 and 16 bits +# endif +#endif + /// Step 4: Init Read-only defines that depend on other values #if !defined(MOZZI_AUDIO_BIAS) #define MOZZI_AUDIO_BIAS ((uint16_t) 1<<(MOZZI_AUDIO_BITS-1)) diff --git a/internal/config_checks_mbed.h b/internal/config_checks_mbed.h index 46c26a288..e57543b49 100644 --- a/internal/config_checks_mbed.h +++ b/internal/config_checks_mbed.h @@ -111,4 +111,7 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE, MOZZI_AUDIO_INP # define BYPASS_MOZZI_OUTPUT_BUFFER true #endif +// TODO: This value is correct for Arduino Giga and Arduino Portenta, but not necessarily everywhere else +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 16 + #endif // #ifndef CONFIG_CHECK_MBED_H diff --git a/internal/config_checks_renesas.h b/internal/config_checks_renesas.h index 59f88f94e..c4ece446b 100644 --- a/internal/config_checks_renesas.h +++ b/internal/config_checks_renesas.h @@ -67,4 +67,6 @@ MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE, MOZZI_ANALOG_RE MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, 1) #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 14 + #endif // #ifndef CONFIG_CHECK_RENESAS_H diff --git a/internal/config_checks_rp2040.h b/internal/config_checks_rp2040.h index 270e1af49..fa51bf67e 100644 --- a/internal/config_checks_rp2040.h +++ b/internal/config_checks_rp2040.h @@ -108,6 +108,8 @@ MOZZI_CHECK_SUPPORTED(MOZZI_I2S_FORMAT, MOZZI_I2S_FORMAT_PLAIN, MOZZI_I2S_FORMAT # define MOZZI_ANALOG_READ MOZZI_ANALOG_READ_STANDARD #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 12 + MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE, MOZZI_ANALOG_READ_STANDARD) MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE, MOZZI_ANALOG_READ_STANDARD) diff --git a/internal/config_checks_samd21.h b/internal/config_checks_samd21.h index 225771ead..f94abd5c0 100644 --- a/internal/config_checks_samd21.h +++ b/internal/config_checks_samd21.h @@ -66,4 +66,6 @@ MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE) MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, 1) #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 12 + #endif // #ifndef CONFIG_CHECK_SAMD21_H diff --git a/internal/config_checks_stm32duino.h b/internal/config_checks_stm32duino.h index 2efbbdd5d..06597b91a 100644 --- a/internal/config_checks_stm32duino.h +++ b/internal/config_checks_stm32duino.h @@ -129,5 +129,6 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, 1) #define MOZZI_ANALOG_READ MOZZI_ANALOG_READ_STANDARD #endif +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION ADC_RESOLUTION #endif // #ifndef CONFIG_CHECKS_STM32DUINO_H diff --git a/internal/config_checks_stm32maple.h b/internal/config_checks_stm32maple.h index 507f93b31..cd5118d86 100644 --- a/internal/config_checks_stm32maple.h +++ b/internal/config_checks_stm32maple.h @@ -13,7 +13,7 @@ * * @section stm32_maple_status Status and peculiarities of this port * Compiles for and runs on a STM32F103C8T6 blue pill board, with a bunch of caveats (see below), i.e. on a board _without_ a - * real DAC. Should probably run on any other board supported by [Roger Clark's libmaple-based core](https://github.com/rogerclarkmelbourne/Arduino_STM32) (although this theory is untested). + * real DAC. Should probably run on any other board supported by [Roger Clark's libmaple-based core](https://github.com/rogerclarkmelbourne/Ardu0ino_STM32) (although this theory is untested). * * @note that at the time of this writing, [Stev Strong's slightliy more recent fork of this core](https://github.com/stevstrong/Arduino_STM32/) does *not* work with * Mozzi, apparently due to a bug in pwmWrite(). @@ -120,5 +120,7 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, 1) #define MOZZI_ANALOG_READ MOZZI_ANALOG_READ_STANDARD #endif +// TODO: This probably isn't correct for all boards! +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 12 #endif // #ifndef CONFIG_CHECKS_STM32MAPLE_H diff --git a/internal/config_checks_teensy.h b/internal/config_checks_teensy.h index 3358363f5..a4d70c996 100644 --- a/internal/config_checks_teensy.h +++ b/internal/config_checks_teensy.h @@ -138,4 +138,7 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, 1) # endif #endif +//TODO: Not 100% sure this is correct in all cases. +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 10 + #endif // #ifndef CONFIG_CHECK_TEENSY_H diff --git a/internal/config_checks_template.h b/internal/config_checks_template.h index 8227934a7..14e026b78 100644 --- a/internal/config_checks_template.h +++ b/internal/config_checks_template.h @@ -31,6 +31,30 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM, MOZZI_OUTPUT_EXTERNAL_ /** NOTE: *Otherwise* you may additionally document that as not-yet-supported like so: */ // MOZZI_CHECK_SUPPORTED(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ) +/** NOTE: This should be set to whichever resolution (in bits) mozziAnalogRead() returns values in by default in your implementation. + * mozziAnalogRead() will shift the return value accordingly. Generally you will set this to the default hardware resolution for this platform. + * + * @em Optionally, you could to set this to the user configurable MOZZI_ANALOG_READ_RESOLUTION (if it has been defined), and configure your ADC reads, + * accordingly, avoiding the extra shift operation: + * + * @code +#ifdef MOZZI_ANALOG_READ_RESOLUTION +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION MOZZI_ANALOG_READ_RESOLUTION +#define MOZZI__IMPL_SET_ANALOG_READ_RESOLUTION +#else +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 16 +#endif + +[...] + +//inside MozziGuts_impl_MPLATFORM, function setupMozziADC(): +#ifdef MOZZI__IMPL_SET_ANALOG_READ_RESOLUTION +analogReadResolution(MOZZI_ANALOG_READ_RESOLUTION); +#endif + * @endcode +*/ +#define MOZZI__INTERNAL_ANALOG_READ_RESOLUTION 10 + /** NOTE: Example for additional config options depending on a specific output mode: */ #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_INTERNAL_DAC) # if !defined(MOZZI_AUDIO_PIN_1) @@ -45,6 +69,7 @@ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PWM, MOZZI_OUTPUT_EXTERNAL_ MOZZI_CHECK_SUPPORTED(MOZZI_AUDIO_CHANNELS, MOZZI_MONO) #endif + /** NOTE: You may also set further, implementation-specific defines, here. E.g. BYPASS_MOZZI_OUTPUT_BUFFER. Defines that are purely * specific to your port (i.e. only needed inside MozziGuts_impt_YOURPLATFORM.h, should be #undef'ed at the end of that file. */ diff --git a/mozzi_analog.h b/mozzi_analog.h index fae9221c7..d6a274339 100644 --- a/mozzi_analog.h +++ b/mozzi_analog.h @@ -134,19 +134,41 @@ Use adcPinToChannelNum() to convert the pin number to its channel number. */ void adcStartConversion(uint8_t channel); +/** @ingroup analog +See mozziAnalogRead(). The template parameter RES specifies the number of bits to return. +*/ +template uint16_t mozziAnalogRead(uint8_t pin); +/** @ingroup analog +See mozziAnalogRead() but always returns the value shifted to 16 bit range. THis is exactly +equivalent to mozziAnalogRead<16>(pin); +*/ +inline uint16_t mozziAnalogRead16(uint8_t pin) { return mozziAnalogRead<16>(pin); }; +#if defined(FOR_DOXYGEN_ONLY) || defined(MOZZI_ANALOG_READ_RESOLUTION) /** @ingroup analog Reads the analog input of a chosen channel, without blocking other operations from running. It actually returns the most recent analog reading and puts the chosen pin or channel on the stack of channels to be read in the background before the next control interrupt. + +@note Analog reads have different hardware resolution on different platforms. E.g. an analog read + on an Arduino Uno R3 will return a value in the range 0-1023 (10 bits), on a Raspberry Pi Pico + it will return 0-4095 (12 bits). For portable code, it is thus necessary to specify the desired + resolution of reads. This can be done by setting MOZZI_ANALOG_READ_RESOLUTION to the resolution + in bits, near the top of your sketch. All reads will then be adjusted to that range, automatically + (using a simple bit-shift). Alternatively, the templated version of mozziAanalogRead() allows + to specifiy the target resolution per read. + If MOZZI_ANALOG_READ_RESOLUTION is not defined, this (non-templated) function returns a value + in the default hardware resolution, with a warning. + @param pin_or_channel the analog pin or channel number. -@return the digitised value of the voltage on the chosen channel, in the range 0-1023. @Note that non-AVR -hardware may return a different range, e.g. 0-4095 on STM32 boards. +@return the digitised value of the voltage on the chosen channel. See the note above regarding the output range! */ -int mozziAnalogRead(uint8_t pin); - +inline uint16_t mozziAnalogRead(uint8_t pin) { return mozziAnalogRead(pin); } +#else +MOZZI_DEPRECATED("2.0", "This use of mozziAnalogRead() is not portable. Refer to the API documentation for suggested alternatives.") inline uint16_t mozziAnalogRead(uint8_t pin) { return mozziAnalogRead(pin); } +#endif uint8_t adcPinToChannelNum(uint8_t pin);