Mercurial > hg > beaglert
changeset 55:41d24dba6b74 newapi
Add cape test project and make rt_printf (rtdk.h) part of standard BeagleRT.h include
author | andrewm |
---|---|
date | Mon, 15 Jun 2015 18:16:00 +0100 |
parents | a6d223473ea2 |
children | 3c3a1357657d |
files | .cproject include/BeagleRT.h projects/cape_test/main.cpp projects/cape_test/render.cpp |
diffstat | 4 files changed, 241 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Sun May 31 02:13:39 2015 -0500 +++ b/.cproject Mon Jun 15 18:16:00 2015 +0100 @@ -92,7 +92,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/oscillator_bank"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/cape_test"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -183,7 +183,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/oscillator_bank"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/cape_test"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration>
--- a/include/BeagleRT.h Sun May 31 02:13:39 2015 -0500 +++ b/include/BeagleRT.h Mon Jun 15 18:16:00 2015 +0100 @@ -29,6 +29,7 @@ #define BEAGLERT_H_ #include <stdint.h> +#include <rtdk.h> #include "digital_gpio_mapping.h" // Useful constants
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/cape_test/main.cpp Mon Jun 15 18:16:00 2015 +0100 @@ -0,0 +1,97 @@ +/* + * main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ +#include <unistd.h> +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include "../../include/BeagleRT.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 << " --frequency [-f] frequency: Set the frequency of the oscillator\n"; + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + float frequency = 440.0; // Frequency of oscillator + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {"frequency", 1, NULL, 'f'}, + {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, "hf:", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case 'f': + frequency = atof(optarg); + break; + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, &frequency) != 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 and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, 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/cape_test/render.cpp Mon Jun 15 18:16:00 2015 +0100 @@ -0,0 +1,141 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + + +#include "../../include/BeagleRT.h" +#include <cmath> + +#define ANALOG_LOW (2048.0 / 65536.0) +#define ANALOG_HIGH (50000.0 / 65536.0) + +const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7}; + +uint64_t gLastErrorFrame = 0; +uint32_t gEnvelopeSampleCount = 0; +float gEnvelopeValue = 0.5; +float gEnvelopeDecayRate = 0.9995; + +// 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(BeagleRTContext *context, void *userData) +{ + 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(BeagleRTContext *context, void *userData) +{ + static float phase = 0.0; + static int sampleCounter = 0; + static int invertChannel = 0; + float frequency = 0; + + // Play a sine wave on the audio output + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = context->audioOut[2*n + 1] = gEnvelopeValue * sinf(phase); + + // If one second has gone by with no error, play one sound, else + // play another + if(context->audioSampleCount + n - gLastErrorFrame > 44100) { + gEnvelopeValue *= gEnvelopeDecayRate; + gEnvelopeSampleCount++; + if(gEnvelopeSampleCount > 22050) { + gEnvelopeValue = 0.5; + gEnvelopeSampleCount = 0; + } + frequency = 880.0; + } + else { + gEnvelopeValue = 0.5; + frequency = 220.0; + } + + phase += 2.0 * M_PI * frequency / 44100.0; + if(phase >= 2.0 * M_PI) + phase -= 2.0 * M_PI; + } + + for(unsigned int n = 0; n < context->analogFrames; n++) { + // Change outputs every 512 samples + if(sampleCounter < 512) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) + context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; + else + context->analogOut[n*8 + gDACPinOrder[k]] = 0; + } + } + else { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) + context->analogOut[n*8 + gDACPinOrder[k]] = 0; + else + context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; + } + } + + // Read after 256 samples: input should be low + if(sampleCounter == 256) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) { + if(context->analogIn[n*8 + k] < ANALOG_HIGH) { + rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + else { + if(context->analogIn[n*8 + k] > ANALOG_LOW) { + rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + } + } + else if(sampleCounter == 768) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) { + if(context->analogIn[n*8 + k] > ANALOG_LOW) { + rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + else { + if(context->analogIn[n*8 + k] < ANALOG_HIGH) { + rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + } + } + + if(++sampleCounter >= 1024) { + sampleCounter = 0; + invertChannel++; + if(invertChannel >= 8) + invertChannel = 0; + } + } +} + +// 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(BeagleRTContext *context, void *userData) +{ + +}