changeset 41:4255ecbb9bec ultra-staging

Timers to measure performances, ultra experimental
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 19 May 2015 16:41:07 +0100
parents 419ce4ebfc4c
children 24af9a14b203
files .cproject core/PRU.cpp core/RTAudio.cpp core/client.cpp include/PRU.h include/client.h projects/basic_network/render.cpp
diffstat 7 files changed, 123 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Wed May 13 12:23:37 2015 +0100
+++ b/.cproject	Tue May 19 16:41:07 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" kind="sourcePath" name="projects/analogDigitalDemo"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/basic_network"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
@@ -177,7 +177,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" kind="sourcePath" name="projects/analogDigitalDemo"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/basic_network"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
--- a/core/PRU.cpp	Wed May 13 12:23:37 2015 +0100
+++ b/core/PRU.cpp	Tue May 19 16:41:07 2015 +0100
@@ -20,6 +20,7 @@
 #include "../include/GPIOcontrol.h"
 #include "../include/render.h"
 #include "../include/pru_rtaudio_bin.h"
+#include "../include/intervals.h"
 
 #include <iostream>
 #include <stdlib.h>
@@ -99,12 +100,14 @@
 const unsigned int PRU::kPruGPIOTestPin2 = 31;	// GPIO0(31); P9-13
 const unsigned int PRU::kPruGPIOTestPin3 = 26;	// GPIO0(26); P8-14
 
-extern int gShouldStop;
+//extern int gShouldStop;
 extern int gRTAudioVerbose;
+extern PRU *gPRU;
 
 // Constructor: specify a PRU number (0 or 1)
 PRU::PRU()
-: pru_number(0), running(false), spi_enabled(false), gpio_enabled(false), led_enabled(false),
+:  renderTimer(100,0,44100.0,"renderTimer"), sleepTimer(100,0,44100.0,"sleepTimer"),
+  pru_number(0), running(false), spi_enabled(false), gpio_enabled(false), led_enabled(false),
   gpio_test_pin_enabled(false), spi_num_channels(0), xenomai_gpio_fd(-1), xenomai_gpio(0)
 {
 
@@ -435,7 +438,6 @@
 	float *audioInBuffer, *audioOutBuffer;
 	float *analogInBuffer, *analogOutBuffer, *lastAnalogOutFrame;
 	uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer;
-
 	audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
 	audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
 	analogInBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
@@ -447,7 +449,6 @@
     																	// - embed in the digitalWrite/Read macros a check whether digital is enabled
     																	// - allocate some memory in ARM just to allow render() to run regardless.
     																	//     in this case it can be digitalBuffer0 == digitalBuffer1
-	printf("digital_buffer_frames: %d;\n",digital_buffer_frames);
     lastDigitalBuffer = (uint32_t *)malloc(digital_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states
 	if(audioInBuffer == 0 || audioOutBuffer == 0) {
 		rt_printf("Error: couldn't allocate audio buffers\n");
@@ -462,17 +463,25 @@
 		return;
 	}
 
-	for(unsigned int n=0; n<digital_buffer_frames; n++){ //initialize lastDigitalFrames to all inputs
-		lastDigitalBuffer[n]= 0x0000ffff;
-	}
+    if(digital_enabled){
+		for(unsigned int n=0; n<digital_buffer_frames; n++){ //initialize lastDigitalFrames to all inputs
+			lastDigitalBuffer[n]= 0x0000ffff;
+		}
+    }
+	int count=0;
+	sleepTimer.setNumFrames(audio_buffer_frames);
+	renderTimer.setNumFrames(audio_buffer_frames);
 	while(!gShouldStop) {
 		// Wait for PRU to move to buffer 1
+		sleepTimer.start();
 		while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) {
 			rt_task_sleep(sleepTime);
 		}
+		sleepTimer.split();
+
 		if(gShouldStop)
 			break;
-
+		renderTimer.start();
 		if(xenomai_gpio != 0) {
 			// Set the test pin high
 			xenomai_gpio[GPIO_SETDATAOUT] = TEST_PIN_MASK;
@@ -489,9 +498,10 @@
 			//initialize the output buffer with the values that were in the last frame of the previous output
 			for(int n = 0; n < spi_num_channels; n++){
 				for(unsigned int j = 0; j < spi_buffer_frames; j++){
-					analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
+					analogOutBuffer[j*spi_num_channels + n] = lastAnalogOutFrame[n];
 				}
 			}
+
         //use past digital values to initialize the array properly.
 		//For each frame:
         //- pins previously set as outputs will keep the output value they had in the last frame of the previous buffer,
@@ -539,15 +549,17 @@
 			// Set the test pin high
 			xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK;
 		}
-
+		renderTimer.split();
 		// Wait for PRU to move to buffer 0
+		sleepTimer.start();
 		while(pru_buffer_comm[PRU_CURRENT_BUFFER] != 0 && !gShouldStop) {
 			rt_task_sleep(sleepTime);
 		}
-
+		sleepTimer.split();
 		if(gShouldStop)
 			break;
 
+		renderTimer.start();
 		if(xenomai_gpio != 0) {
 			// Set the test pin high
 			xenomai_gpio[GPIO_SETDATAOUT] = TEST_PIN_MASK;
@@ -567,7 +579,7 @@
 			//initialize the output buffer with the values that were in the last frame of the previous output
 			for(int n = 0; n < spi_num_channels; n++){
 				for(unsigned int j = 0; j < spi_buffer_frames; j++){
-					analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
+					analogOutBuffer[j*spi_num_channels + n] = lastAnalogOutFrame[n];
 				}
 			}
             if(digital_enabled){
@@ -614,15 +626,19 @@
 			// Set the test pin high
 			xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK;
 		}
+		renderTimer.split();
+		count+=audio_buffer_frames;
+		if((count&32767)==0){
+			scheduleAuxiliaryTask(gPRU->printIntervalsTask);
+		}
 	}
 
 	// Tell PRU to stop
 	pru_buffer_comm[PRU_SHOULD_STOP] = 1;
-
 	free(analogOutBuffer);
+	free(analogInBuffer);
+	free(audioOutBuffer);
 	free(audioInBuffer);
-	free(audioOutBuffer);
-	free(analogInBuffer);
 	free(lastAnalogOutFrame);
     free(lastDigitalBuffer);
 }
--- a/core/RTAudio.cpp	Wed May 13 12:23:37 2015 +0100
+++ b/core/RTAudio.cpp	Tue May 19 16:41:07 2015 +0100
@@ -70,6 +70,13 @@
 int gNumAnalogChannels = 0;
 int gNumDigitalChannels = 0;
 
+
+void printIntervals(){
+	rt_printf("\n");
+	gPRU->renderTimer.print();
+	gPRU->sleepTimer.print();
+}
+
 // initAudio() prepares the infrastructure for running PRU-based real-time
 // audio, but does not actually start the calculations.
 // periodSize indicates the number of _sensor_ frames per period: the audio period size
@@ -190,7 +197,7 @@
 		cout << "Couldn't initialise audio rendering\n";
 		return 1;
 	}
-
+	gPRU->printIntervalsTask=createAuxiliaryTaskLoop(*printIntervals, 10, "transmit-receive-data");
 	return 0;
 }
 
@@ -213,7 +220,7 @@
 	}
 	else {
 		if(gPRU->start(gPRUFilename)) {
-			rt_printf("Error: unable to start PRU from file %s\n", gPRUFilename);
+			rt_printf("Error: unable to start PRU %s\n", gPRUFilename);
 			gShouldStop = 1;
 		}
 		else {
--- a/core/client.cpp	Wed May 13 12:23:37 2015 +0100
+++ b/core/client.cpp	Tue May 19 16:41:07 2015 +0100
@@ -7,7 +7,7 @@
 #include <unistd.h>
 #include <rtdk.h>
 
-#define BUFF_LEN 1024
+#define MESSAGE_BUFF_LEN 1024
 #define MAX_VAR_STRING 20
 
 struct sockaddr_in outServer, inServer;
@@ -47,13 +47,13 @@
 int sendMessage(networkData message)
 {
    unsigned int length;
-   char buffer[BUFF_LEN];
+   char buffer[MESSAGE_BUFF_LEN];
    length=sizeof(struct sockaddr_in);
    int k=0;
    k=sprintf(buffer+k, "%8d;",*message.counter);
    for(int j=0; j<message.numVariables; j++){
 	   k+=sprintf(buffer+k, "%.3f;",*message.variables[j]);
-	   if(k>BUFF_LEN - 20) //safety margin
+	   if(k>MESSAGE_BUFF_LEN - 20) //safety margin
 		   continue;
    }
    sprintf(buffer+k,"\n");
@@ -63,16 +63,18 @@
    if (n < 0) error("Sendto");
    return 0;
 }
-/*
-int receiveMessage()
+
+int sendAudio(networkAudio *audio)
 {
-   int n = recvfrom(inSock,inBuffer,1024,0,(struct sockaddr *)&from,&fromlen);
-   if (n < 0) error("recvfrom");
-   printf("Received a datagram: ");
-   printf(inBuffer);
- }
-*/
-
+   unsigned int length;
+   length=sizeof(struct sockaddr_in);
+//   for(int k=0; k<NETWORK_AU	DIO_BUFFER_SIZE; k++)
+//	   printf("%f\n",audio.buffers[!audio.currentBuffer][k]);
+   n=sendto(outSock,audio->buffers[!audio->currentBuffer],NETWORK_AUDIO_BUFFER_SIZE*sizeof(float),0,(const struct sockaddr *)&outServer,length);
+   if (n < 0) error("Sendto");
+   audio->doneOnTime=1;
+   return 0;
+}
 
 int receiveMessage(networkData message){
 	struct timeval stTimeOut;
@@ -101,7 +103,7 @@
 			//the worst parser ever
 			int previousN=0;
 			int currentVariable=0;
-			for(int n=0; inBuffer[n]!=0 && currentVariable<message.numVariables && n-previousN<MAX_VAR_STRING && n<BUFF_LEN; n++){ //scan the string
+			for(int n=0; inBuffer[n]!=0 && currentVariable<message.numVariables && n-previousN<MAX_VAR_STRING && n<MESSAGE_BUFF_LEN; n++){ //scan the string
 				if(inBuffer[n]==';'||inBuffer[n]==0||inBuffer[n]=='\n'){ // if you find a separator or you are at the end of the string, parse the variable
 					int j=0;
 					inBuffer[n]=0;	 //set the semicolon to 0 ...
--- a/include/PRU.h	Wed May 13 12:23:37 2015 +0100
+++ b/include/PRU.h	Tue May 19 16:41:07 2015 +0100
@@ -9,7 +9,8 @@
 #define PRU_H_
 
 #include <stdint.h>
-
+#include "../include/RTAudio.h"	// to schedule lower prio parallel process
+#include "../include/intervals.h"
 class PRU
 {
 private:
@@ -51,6 +52,9 @@
 	// For debugging:
 	void setGPIOTestPin();
 	void clearGPIOTestPin();
+	Interval renderTimer;
+	Interval sleepTimer;
+	AuxiliaryTask printIntervalsTask;
 
 private:
 	int pru_number;		// Which PRU we use
@@ -74,6 +78,7 @@
 
 	int xenomai_gpio_fd;	// File descriptor for /dev/mem for fast GPIO
 	uint32_t *xenomai_gpio;	// Pointer to GPIO registers
+
 };
 
 
--- a/include/client.h	Wed May 13 12:23:37 2015 +0100
+++ b/include/client.h	Tue May 19 16:41:07 2015 +0100
@@ -14,9 +14,18 @@
 	float *variables[16];
 	int numVariables;
 };
+#define NETWORK_AUDIO_BUFFER_SIZE 100 //1400/4 //maximum payload for a UDP datagram over ethernet is 1472 bytes, I leave some headroom and divide by 4 to get the number of floats
+struct networkAudio{
+	int timestamp;
+	int currentBuffer;
+	int index;
+	float buffers[2][NETWORK_AUDIO_BUFFER_SIZE];
+	int doneOnTime;
+};
 
 void error(const char *);
 int setupSockets(int receivePort, int transmitPort, char const*serverName);
 int sendMessage(networkData message);
+int sendAudio(networkAudio *audio);
 int receiveMessage(networkData message);
 void closeSockets();
--- a/projects/basic_network/render.cpp	Wed May 13 12:23:37 2015 +0100
+++ b/projects/basic_network/render.cpp	Tue May 19 16:41:07 2015 +0100
@@ -11,23 +11,32 @@
 #include "../../include/client.h"
 #include "../../include/RTAudio.h"	// to schedule lower prio parallel process
 #include <rtdk.h>
+#include <native/timer.h>
+#include "../../include/PRU.h"
 float gFrequency;
 float gPhase;
 float gInverseSampleRate;
 int gCount=0;
 networkData networkObject;
-AuxiliaryTask transmitReceiveDataTask;
+networkAudio netAudio;
+extern PRU *gPRU;
+AuxiliaryTask printIntervalTask;
+AuxiliaryTask transmitReceiveAudioTask;
+void transmitReceiveData(){ //transmit and receive asynchronous messages
+//   	printf("transmitReceiveData auxiliary task has started\n");
+//	while(!gShouldStop){
+//		sendMessage(&networkObject);
+//		receiveMessage(networkObject);
+//		usleep(1000);
+//	}
+//	closeSockets();
+}
 
-void transmitReceiveData(){
-   	printf("transmitReceiveData auxiliary task has started\n");
-	while(!gShouldStop){
-		sendMessage(networkObject);
-		receiveMessage(networkObject);
-		usleep(1000);
-	}
-	closeSockets();
+void transmitReceiveAudio(){ //transmit and receive audio buffers
+	sendAudio(&netAudio);
 }
 
+
 // 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.
@@ -48,13 +57,17 @@
 	gInverseSampleRate = 1.0 / audioSampleRate;
 	gPhase = 0.0;
 
-	networkObject.counter=&gCount;
-	networkObject.variables[0]=&gFrequency;
-	networkObject.variables[1]=&gPhase;
-	networkObject.numVariables=2;
-	setupSockets(settings->receivePort, settings->transmitPort, settings->serverName);
-	transmitReceiveDataTask=createAuxiliaryTaskLoop(*transmitReceiveData, 80, "transmit-receive-data");
-	//scheduleAuxiliaryTask(transmitReceiveDataTask); //here it does not work
+//	networkObject.counter=&gCount;
+//	networkObject.variables[0]=&gFrequency;
+//	networkObject.variables[1]=&gPhase;
+//	networkObject.numVariables=2;
+//	netAudio.doneOnTime=1;
+//	netAudio.index=0;
+//	netAudio.currentBuffer=0;
+//	setupSockets(settings->receivePort, settings->transmitPort, settings->serverName);
+////	transmitReceiveDataTask=createAuxiliaryTaskLoop(*transmitReceiveData, 10, "transmit-receive-data");
+////	scheduleAuxiliaryTask(transmitReceiveDataTask); //here it does not work
+//	transmitReceiveAudioTask=createAuxiliaryTaskLoop(*transmitReceiveAudio, 98, "transmit-receive-audio");
 	return true;
 }
 
@@ -68,15 +81,32 @@
 {
 	for(int n = 0; n < numAudioFrames; n++) {
 		float out = 0.7f * sinf(gPhase);
+		float fake=0.1;
+		for(int a=0; a<24; a++){
+			fake = 0.7f * sinf(fake+out);
+		}
+		fake/=1000000000000000;
 		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
 		if(gPhase > 2.0 * M_PI)
 			gPhase -= 2.0 * M_PI;
 
-		for(int channel = 0; channel < gNumAudioChannels; channel++)
-			audioOut[n * gNumAudioChannels + channel] = out;
-		if(gCount==0){
-			scheduleAuxiliaryTask(transmitReceiveDataTask);
+//		for(int channel = 0; channel < gNumAudioChannels; channel++)
+//			audioOut[n * gNumAudioChannels + channel] = audioIn[n * gNumAudioChannels + 0]+audioIn[n * gNumAudioChannels + 1];
+		audioOut[n * gNumAudioChannels] = fake*0.0000000001;
+		audioOut[n * gNumAudioChannels+1]=out;
+		if(0==gCount){
+//			scheduleAuxiliaryTask(transmitReceiveDataTask);
 		}
+//		if(netAudio.index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ...
+//			netAudio.index=0; //reset the counter
+//			if(netAudio.doneOnTime==0)
+//				rt_printf("Network buffer underrun :-{\n");
+//			netAudio.timestamp=gCount;
+//			netAudio.currentBuffer=!netAudio.currentBuffer; //switch buffer
+//			netAudio.doneOnTime=0;
+//			scheduleAuxiliaryTask(transmitReceiveAudioTask); //send the buffer
+//		}
+//		netAudio.buffers[netAudio.currentBuffer][netAudio.index++]=audioOut[n*gNumAudioChannels + 0];//copy channel 0 to the buffer
 		gCount++;
 	}
 }
@@ -86,4 +116,5 @@
 
 void cleanup_render()
 {
+//	closeSockets();
 }