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)
Binary file pru_rtaudio.bin has changed
--- 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