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)
+{
+
+}