Mozzi  version v1.1.0
sound synthesis library for Arduino
MozziGuts_impl_template.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 /** README!
14  * This file is meant to be used as a template when adding support for a new platform. Please read these instructions, first.
15  *
16  * Files involved:
17  * 1. Modify hardware_defines.h, adding a macro to detect your target platform
18  * 2. Modify MozziGuts.cpp to include MozziGuts_impl_YOURPLATFORM.hpp
19  * 3. Modify MozziGuts.h to include AudioConfigYOURPLATFORM.h
20  * 4. Copy this file to MozziGuts_impl_YOURPLATFORM.hpp and adjust as necessary
21  * (If your platform is very similar to an existing port, it may instead be better to modify the existing MozziGuts_impl_XYZ.hpp/AudioConfigYOURPLATFORM.h,
22  * instead of steps 2-3.).
23  * Some platforms may need small modifications to other files as well, e.g. mozzi_pgmspace.h
24  *
25  * How to implement MozziGuts_impl_YOURPLATFORM.hpp:
26  * - Follow the NOTEs provided in this file
27  * - Read the doc at the top of AudioOutput.h for a better understanding of the basic audio output framework
28  * - Take a peek at existing implementations for other hardware (e.g. TEENSY3/4 is rather complete while also simple at the time of this writing)
29  * - Wait for more documentation to arrive
30  * - Ask when in doubt
31  * - Don't forget to provide a PR when done (it does not have to be perfect; e.g. many ports skip analog input, initially)
32  */
33 
34 // The main point of this check is to document, what platform & variants this implementation file is for.
35 #if !(IS_MYPLATFORM())
36 # error "Wrong implementation included for this platform"
37 #endif
38 // Add platform specific includes and declarations, here
39 
40 
41 ////// BEGIN analog input code ////////
42 
43 /** NOTE: This section deals with implementing (fast) asynchronous analog reads, which form the backbone of mozziAnalogRead(), but also of USE_AUDIO_INPUT (if enabled).
44  * This template provides empty/dummy implementations to allow you to skip over this section, initially. Once you have an implementation, be sure to enable the
45  * #define, below: */
46 //#define MOZZI_FAST_ANALOG_IMPLEMENTED
47 
48 // Insert here code to read the result of the latest asynchronous conversion, when it is finished.
49 // You can also provide this as a function returning unsigned int, should it be more complex on your platform
50 #define getADCReading() 0
51 
52 /** NOTE: On "pins" vs. "channels" vs. "indices"
53  * "Pin" is the pin number as would usually be specified by the user in mozziAnalogRead().
54  * "Channel" is an internal ADC channel number corresponding to that pin. On many platforms this is simply the same as the pin number, on others it differs.
55  * In other words, this is an internal representation of "pin".
56  * "Index" is the index of the reading for a certain pin/channel in the array of analog_readings, ranging from 0 to NUM_ANALOG_PINS. This, again may be the
57  * same as "channel" (e.g. on AVR), however, on platforms where ADC-capable "channels" are not numbered sequentially starting from 0, the channel needs
58  * to be converted to a suitable index.
59  *
60  * In summary, the semantics are roughly
61  * mozziAnalogRead(pin) -> _ADCimplementation_(channel) -> analog_readings[index]
62  * Implement adcPinToChannelNum() and channelNumToIndex() to perform the appropriate mapping.
63  */
64 // NOTE: Theoretically, adcPinToChannelNum is public API for historical reasons, thus cannot be replaced by a define
65 #define channelNumToIndex(channel) channel
66 uint8_t adcPinToChannelNum(uint8_t pin) {
67  return pin;
68 }
69 
70 /** NOTE: Code needed to trigger a conversion on a new channel */
71 void adcStartConversion(uint8_t channel) {
72 #warning Fast analog read not implemented on this platform
73 }
74 
75 /** NOTE: Code needed to trigger a subsequent conversion on the latest channel. If your platform has no special code for it, you should store the channel from
76  * adcStartConversion(), and simply call adcStartConversion(previous_channel), here. */
77 void startSecondADCReadOnCurrentChannel() {
78 #warning Fast analog read not implemented on this platform
79 }
80 
81 /** NOTE: Code needed to set up faster than usual analog reads, e.g. specifying the number of CPU cycles that the ADC waits for the result to stabilize.
82  * This particular function is not super important, so may be ok to leave empty, at least, if the ADC is fast enough by default. */
83 void setupFastAnalogRead(int8_t speed) {
84 #warning Fast analog read not implemented on this platform
85 }
86 
87 /** NOTE: Code needed to initialize the ADC for asynchronous reads. Typically involves setting up an interrupt handler for when conversion is done, and
88  * possibly calibration. */
89 void setupMozziADC(int8_t speed) {
90 #warning Fast analog read not implemented on this platform
91 }
92 
93 /* NOTE: Most platforms call a specific function/ISR when conversion is complete. Provide this function, here.
94  * From inside its body, simply call advanceADCStep(). E.g.:
95 void stm32_adc_eoc_handler() {
96  advanceADCStep();
97 }
98 */
99 ////// END analog input code ////////
100 
101 ////// BEGIN audio output code //////
102 /* NOTE: Some platforms rely on control returning from loop() every so often. However, updateAudio() may take too long (it tries to completely fill the output buffer,
103  * which of course is being drained at the same time, theoretically it may not return at all). If you set this define, it will be called once per audio frame to keep things
104  * running smoothly. */
105 //#define LOOP_YIELD yield();
106 
107 #if (EXTERNAL_AUDIO_OUTPUT != true) // otherwise, the last stage - audioOutput() - will be provided by the user
108 /** NOTE: This is the function that actually write a sample to the output. In case of EXTERNAL_AUDIO_OUTPUT == true, it is provided by the library user, instead. */
109 inline void audioOutput(const AudioOutput f) {
110  // e.g. analogWrite(AUDIO_CHANNEL_1_PIN, f.l()+AUDIO_BIAS);
111 #if (AUDIO_CHANNELS > 1)
112  // e.g. analogWrite(AUDIO_CHANNEL_2_PIN, f.r()+AUDIO_BIAS);
113 #endif
114 }
115 #endif
116 
117 static void startAudio() {
118  // Add here code to get audio output going. This usually involves:
119  // 1) setting up some DAC mechanism (e.g. setting up a PWM pin with appropriate resolution
120  // 2a) setting up a timer to call defaultAudioOutput() at AUDIO_RATE
121  // OR 2b) setting up a buffered output queue such as I2S (see ESP32 / ESP8266 for examples for this setup)
122 #if (EXTERNAL_AUDIO_OUTPUT != true)
123  // remember that the user may configure EXTERNAL_AUDIO_OUTPUT, in which case, you'll want to provide step 2a), and only that.
124 #endif
125 }
126 
127 void stopMozzi() {
128  // Add here code to pause whatever mechanism moves audio samples to the output
129 }
130 ////// END audio output code //////
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
void setupFastAnalogRead(int8_t speed)
NOTE: Code needed to set up faster than usual analog reads, e.g.