Mercurial > hg > beaglert
changeset 13:6adb088196a7
Fixed ADC bug; added a simple passthrough test
author | andrewm |
---|---|
date | Fri, 23 Jan 2015 15:17:09 +0000 |
parents | a6beeba3a648 |
children | 06f93bef7dd2 |
files | .cproject core/RTAudio.cpp include/Utilities.h include/render.h projects/basic/render.cpp projects/basic_analog_output/render.cpp projects/basic_passthru/main.cpp projects/basic_passthru/render.cpp projects/basic_sensor/render.cpp pru_rtaudio.bin pru_rtaudio.p |
diffstat | 11 files changed, 191 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Thu Jan 22 19:00:22 2015 +0000 +++ b/.cproject Fri Jan 23 15:17:09 2015 +0000 @@ -73,7 +73,7 @@ <sourceEntries> <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_analog_output"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/> </sourceEntries> </configuration> </storageModule> @@ -147,7 +147,7 @@ <sourceEntries> <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_analog_output"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/> </sourceEntries> </configuration> </storageModule>
--- a/core/RTAudio.cpp Thu Jan 22 19:00:22 2015 +0000 +++ b/core/RTAudio.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -61,6 +61,12 @@ int gAmplifierMutePin = -1; int gAmplifierShouldBeginMuted = 0; +// Number of audio and matrix channels, globally accessible +// At least gNumMatrixChannels needs to be global to be used +// by the analogRead() and analogWrite() macros without creating +// extra confusion in their use cases by passing this argument +int gNumAudioChannels = 0; +int gNumMatrixChannels = 0; // initAudio() prepares the infrastructure for running PRU-based real-time // audio, but does not actually start the calculations. @@ -170,8 +176,10 @@ matrixSampleRate = audioSampleRate * 4.0 / (float)settings->numMatrixChannels; } - if(!initialise_render(settings->useMatrix ? settings->numMatrixChannels : 0, /* matrix channels */ - 2, /* audio channels */ + gNumAudioChannels = 2; + gNumMatrixChannels = settings->useMatrix ? settings->numMatrixChannels : 0; + + if(!initialise_render(gNumMatrixChannels, gNumAudioChannels, settings->useMatrix ? settings->periodSize : 0, /* matrix period size */ audioPeriodSize, matrixSampleRate, audioSampleRate,
--- a/include/Utilities.h Thu Jan 22 19:00:22 2015 +0000 +++ b/include/Utilities.h Fri Jan 23 15:17:09 2015 +0000 @@ -8,12 +8,15 @@ #ifndef UTILITIES_H_ #define UTILITIES_H_ +extern int gNumAudioChannels; // How many audio channels are present +extern int gNumMatrixChannels; // How many matrix channels are present + // Macros for accessing the matrix values: usable _only_ within render() // Read an analog input from input pin p at frame f -#define analogRead(p, f) (matrixIn[(f)*8 + (p)]) +#define analogRead(p, f) (matrixIn[(f)*gNumMatrixChannels + (p)]) // Write an analog output frame at output pin p, frame f, to value v -#define analogWrite(p, f, v) (matrixOut[(f)*8 + (p)] = (uint16_t)(v)) +#define analogWrite(p, f, v) (matrixOut[(f)*gNumMatrixChannels + (p)] = (uint16_t)(v)) float map(float x, float in_min, float in_max, float out_min, float out_max); float constrain(float x, float min_val, float max_val);
--- a/include/render.h Thu Jan 22 19:00:22 2015 +0000 +++ b/include/render.h Fri Jan 23 15:17:09 2015 +0000 @@ -33,6 +33,9 @@ #define MATRIX_MAX 65535.0 +extern int gNumAudioChannels; // How many audio channels are present +extern int gNumMatrixChannels; // How many matrix channels are present + bool initialise_render(int numMatrixChannels, int numAudioChannels, int numMatrixFramesPerPeriod, int numAudioFramesPerPeriod,
--- a/projects/basic/render.cpp Thu Jan 22 19:00:22 2015 +0000 +++ b/projects/basic/render.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -12,7 +12,6 @@ float gFrequency; float gPhase; float gInverseSampleRate; -int gNumChannels; // initialise_render() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent @@ -32,7 +31,6 @@ // Retrieve a parameter passed in from the initAudio() call gFrequency = *(float *)userData; - gNumChannels = numAudioChannels; gInverseSampleRate = 1.0 / audioSampleRate; gPhase = 0.0; @@ -53,8 +51,8 @@ if(gPhase > 2.0 * M_PI) gPhase -= 2.0 * M_PI; - for(int channel = 0; channel < gNumChannels; channel++) - audioOut[n * gNumChannels + channel] = out; + for(int channel = 0; channel < gNumAudioChannels; channel++) + audioOut[n * gNumAudioChannels + channel] = out; } }
--- a/projects/basic_analog_output/render.cpp Thu Jan 22 19:00:22 2015 +0000 +++ b/projects/basic_analog_output/render.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -19,8 +19,6 @@ float gPhase; float gInverseSampleRate; -int gMatrixChannels; - // initialise_render() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. @@ -44,7 +42,6 @@ return false; } - gMatrixChannels = numMatrixChannels; gInverseSampleRate = 1.0 / matrixSampleRate; gPhase = 0.0; @@ -62,13 +59,12 @@ for(int n = 0; n < numMatrixFrames; n++) { // Set LED to different phase for each matrix channel float relativePhase = 0.0; - for(int channel = 0; channel < gMatrixChannels; channel++) { + for(int channel = 0; channel < gNumMatrixChannels; channel++) { float out = kMinimumAmplitude + kAmplitudeRange * 0.5f * (1.0f + sinf(gPhase + relativePhase)); if(out > MATRIX_MAX) out = MATRIX_MAX; - matrixOut[n * gMatrixChannels + channel] = (uint16_t)out; - //analogWrite(channel, n, out); + analogWrite(channel, n, out); // Advance by pi/4 (1/8 of a full rotation) for each channel relativePhase += M_PI * 0.25;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_passthru/main.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -0,0 +1,90 @@ +/* + * main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include "../../include/RTAudio.h" + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + RTAudioSettings settings; // Standard audio settings + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "h", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, 0) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C + signal(SIGINT, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_passthru/render.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -0,0 +1,68 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + + +#include "../../include/render.h" +#include "../../include/Utilities.h" +#include <rtdk.h> + +// initialise_render() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. + +bool initialise_render(int numMatrixChannels, int numAudioChannels, + int numMatrixFramesPerPeriod, + int numAudioFramesPerPeriod, + float matrixSampleRate, float audioSampleRate, + void *userData) +{ + // Nothing to do here... + + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numMatrixFrames +// will be 0. + +void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, + uint16_t *matrixIn, uint16_t *matrixOut) +{ + // Simplest possible case: pass inputs through to outputs + for(int n = 0; n < numAudioFrames; n++) { + for(int ch = 0; ch < gNumAudioChannels; ch++) + audioOut[n * gNumAudioChannels + ch] = audioIn[n * gNumAudioChannels + ch]; + } + + // Same with matrix, only if matrix is enabled + if(numMatrixFrames != 0) { + for(int n = 0; n < numMatrixFrames; n++) { + for(int ch = 0; ch < gNumMatrixChannels; ch++) { + // Two equivalent ways to write this code + // The long way, using the buffers directly: + // matrixOut[n * gNumMatrixChannels + ch] = matrixIn[n * gNumMatrixChannels + ch]; + + // Or using the macros: + analogWrite(ch, n, analogRead(ch, n)); + } + } + } +} + +// cleanup_render() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in initialise_render(). + +void cleanup_render() +{ + +}
--- a/projects/basic_sensor/render.cpp Thu Jan 22 19:00:22 2015 +0000 +++ b/projects/basic_sensor/render.cpp Fri Jan 23 15:17:09 2015 +0000 @@ -13,7 +13,7 @@ float gPhase; float gInverseSampleRate; -int gNumChannels; +int gMatrixFramesPerAudioFrame; // These settings are carried over from main.cpp // Setting global variables is an alternative approach @@ -37,12 +37,12 @@ float matrixSampleRate, float audioSampleRate, void *userData) { - if(numMatrixFramesPerPeriod*2 != numAudioFramesPerPeriod) { - rt_printf("Error: this example needs the matrix enabled, running at half audio rate\n"); + if(numMatrixFramesPerPeriod == 0 || numMatrixFramesPerPeriod > numAudioFramesPerPeriod) { + rt_printf("Error: this example needs the matrix enabled, with 4 or 8 channels\n"); return false; } - gNumChannels = numAudioChannels; + gMatrixFramesPerAudioFrame = numAudioFramesPerPeriod / numMatrixFramesPerPeriod; gInverseSampleRate = 1.0 / audioSampleRate; gPhase = 0.0; @@ -64,16 +64,16 @@ // is twice as high for(int n = 0; n < numAudioFrames; n++) { - if(!(n % 2)) { + if(!(n % gMatrixFramesPerAudioFrame)) { // Even audio samples: update frequency and amplitude from the matrix - frequency = map((float)analogRead(gSensorInputFrequency, n/2), 0, MATRIX_MAX, 100, 1000); - amplitude = (float)analogRead(gSensorInputAmplitude, n/2) / MATRIX_MAX; + frequency = map(analogRead(gSensorInputFrequency, n/gMatrixFramesPerAudioFrame), 0, MATRIX_MAX, 100, 1000); + amplitude = (float)analogRead(gSensorInputAmplitude, n/gMatrixFramesPerAudioFrame) / MATRIX_MAX; } float out = amplitude * sinf(gPhase); - for(int channel = 0; channel < gNumChannels; channel++) - audioOut[n * gNumChannels + channel] = out; + for(int channel = 0; channel < gNumAudioChannels; channel++) + audioOut[n * gNumAudioChannels + channel] = out; gPhase += 2.0 * M_PI * frequency * gInverseSampleRate; if(gPhase > 2.0 * M_PI)
--- a/pru_rtaudio.p Thu Jan 22 19:00:22 2015 +0000 +++ b/pru_rtaudio.p Fri Jan 23 15:17:09 2015 +0000 @@ -672,7 +672,6 @@ // Read ADC channels: result is always 2 commands behind // Start by reading channel 2 (result is channel 0) and go // to N+2, but masking the channel number to be between 0 and N-1 - LDI reg_adc_data, 0 ADD r8, r1, 2 SUB r7, reg_num_channels, 1 AND r8, r8, r7