andrewm@0: /* robert@269: ____ _____ _ _ robert@269: | __ )| ____| | / \ robert@269: | _ \| _| | | / _ \ robert@269: | |_) | |___| |___ / ___ \ robert@269: |____/|_____|_____/_/ \_\.io robert@269: robert@269: */ robert@269: robert@269: /* andrewm@0: * robert@269: * Andrew McPherson and Victor Zappi robert@269: * Queen Mary, University of London andrewm@0: */ andrewm@0: robert@269: /** robert@269: \example 3_analog_output robert@269: robert@269: Fading LEDs robert@269: ----------- robert@269: robert@269: This sketch uses a sine wave to drive the brightness of a series of LEDs robert@269: connected to the eight analog out pins. Again you can see the nested `for` loop robert@269: structure but this time for the analog output channels rather than the audio. robert@269: robert@269: Within the first `for` loop in render we cycle through each frame in the analog robert@269: output matrix. At each frame we then cycle through the analog output channels robert@269: with another `for` loop and set the output voltage according to the phase of a robert@269: sine tone that acts as an LFO. The analog output pins can provide a voltage of robert@269: ~4.092V. robert@269: robert@269: The output on each pin is set with `analogWriteFrame` within the `for` loop that robert@269: cycles through the analog output channels. This needs to be provided with robert@269: arguments as follows `analogWriteFrame(context, n, channel, out)`. Channel is robert@269: where the you give the address of the analog output pin (in this case we cycle robert@269: through each pin address in the for loop), out is the variable that holds the robert@269: desired output (in this case set by the sine wave). robert@269: robert@269: Notice that the phase of the brightness cycle for each led is different. This robert@269: is achieved by updating a variable that stores a relative phase value. This robert@269: variable is advanced by pi/4 (1/8 of a full rotation) for each channel giving robert@269: each of the eight LEDs a different phase. robert@269: robert@269: */ robert@269: andrewm@0: andrewm@56: #include andrewm@56: #include andrewm@0: #include andrewm@0: #include andrewm@0: andrewm@0: // Set range for analog outputs designed for driving LEDs andrewm@52: const float kMinimumAmplitude = (1.5 / 5.0); andrewm@52: const float kAmplitudeRange = 1.0 - kMinimumAmplitude; andrewm@0: andrewm@0: float gFrequency; andrewm@0: float gPhase; andrewm@0: float gInverseSampleRate; andrewm@0: andrewm@56: // setup() is called once before the audio rendering starts. andrewm@0: // Use it to perform any initialisation and allocation which is dependent andrewm@0: // on the period size or sample rate. andrewm@0: // andrewm@0: // userData holds an opaque pointer to a data structure that was passed andrewm@0: // in from the call to initAudio(). andrewm@0: // andrewm@0: // Return true on success; returning false halts the program. andrewm@0: andrewm@56: bool setup(BeagleRTContext *context, void *userData) andrewm@0: { andrewm@0: // Retrieve a parameter passed in from the initAudio() call andrewm@0: gFrequency = *(float *)userData; andrewm@0: andrewm@52: if(context->analogFrames == 0) { andrewm@12: rt_printf("Error: this example needs the matrix enabled\n"); andrewm@0: return false; andrewm@0: } andrewm@0: andrewm@52: gInverseSampleRate = 1.0 / context->analogSampleRate; andrewm@0: gPhase = 0.0; andrewm@0: andrewm@0: return true; andrewm@0: } andrewm@0: andrewm@0: // render() is called regularly at the highest priority by the audio engine. andrewm@0: // Input and output are given from the audio hardware and the other andrewm@0: // ADCs and DACs (if available). If only audio is available, numMatrixFrames andrewm@0: // will be 0. andrewm@0: andrewm@52: void render(BeagleRTContext *context, void *userData) andrewm@0: { andrewm@56: for(unsigned int n = 0; n < context->analogFrames; n++) { andrewm@0: // Set LED to different phase for each matrix channel andrewm@0: float relativePhase = 0.0; andrewm@56: for(unsigned int channel = 0; channel < context->analogChannels; channel++) { andrewm@0: float out = kMinimumAmplitude + kAmplitudeRange * 0.5f * (1.0f + sinf(gPhase + relativePhase)); andrewm@0: andrewm@52: analogWriteFrame(context, n, channel, out); andrewm@0: andrewm@0: // Advance by pi/4 (1/8 of a full rotation) for each channel andrewm@0: relativePhase += M_PI * 0.25; andrewm@0: } andrewm@0: andrewm@0: gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; andrewm@0: if(gPhase > 2.0 * M_PI) andrewm@0: gPhase -= 2.0 * M_PI; andrewm@0: } andrewm@0: } andrewm@0: andrewm@56: // cleanup() is called once at the end, after the audio has stopped. andrewm@56: // Release any resources that were allocated in setup(). andrewm@0: andrewm@56: void cleanup(BeagleRTContext *context, void *userData) andrewm@0: { andrewm@0: andrewm@0: }