changeset 114:7b351b7d8770 scope-refactoring

Merged ultra-staging into scope-refactoring
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 19 Aug 2015 23:11:34 +0100
parents 7dfae7b7ab12 (current diff) 3068421c0737 (diff)
children a0e24514fc97
files .cproject core/client.cpp include/client.h projects/basic_network/render.cpp
diffstat 8 files changed, 420 insertions(+), 150 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/UdpServer.cpp	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,88 @@
+/*
+ * udpServer.cpp
+ *
+ *  Created on: 19 May 2015
+ *      Author: giulio moro
+ */
+#include "../include/UdpServer.h"
+
+UdpServer::UdpServer(int aPort){
+	init(aPort);
+};
+UdpServer::UdpServer(){
+	init(0);
+}
+UdpServer::~UdpServer(){
+	//TODO: unbind from port. AFAIK, this involves closing the socket, therefore creating the socket should become part of bindToPort
+};
+bool UdpServer::init(int aPort){
+	enabled=true;
+	stTimeOut.tv_sec = 0; //set timeout to 0
+	stTimeOut.tv_usec = 0;
+	inSocket=socket(AF_INET, SOCK_DGRAM, 0);
+	if (inSocket < 0){
+		enabled=false;
+	}
+	length = sizeof(server);
+	server.sin_family=AF_INET;
+	server.sin_addr.s_addr=INADDR_ANY;
+	enabled=bindToPort(aPort);
+	wasteBufferSize=2048;
+	wasteBuffer=malloc(wasteBufferSize);
+	return enabled;
+}
+
+bool UdpServer::bindToPort(int aPort){
+	port=aPort;
+	if(port<1){
+		enabled=false;
+		return false;
+	}
+	server.sin_port=htons(port);
+	if (bind(inSocket,(struct sockaddr *)&server,length)<0){
+		enabled=false;
+		return false;
+	}
+	enabled=true;
+	return true;
+};
+int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error.
+					void *destBuffer,
+					int maxBytesToRead){
+	if(enabled==false)
+		return -1;
+	FD_ZERO(&stReadFDS);
+	FD_SET(inSocket, &stReadFDS);
+	int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut);
+	if(descriptorReady<0){ //an error occurred
+		return -1;
+	}
+	int numberOfBytes=0;
+	if (FD_ISSET(inSocket, &stReadFDS)) {
+		numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength);
+		if(numberOfBytes<0)
+			return -1;
+	}
+	return numberOfBytes;
+};
+int UdpServer::emptySocket(){
+	return emptySocket(0);
+}
+int UdpServer::emptySocket(int maxBytes){//discards up to maxBytes from the socket. Returns the number of bytes discarded.
+	if(wasteBuffer==NULL)
+		return -1;
+	int numberOfBytes=0;
+	while(int n=read(wasteBuffer, wasteBufferSize)){// calls the read function until it does not return any more bytes (i.e.: socket is empty)
+		if(n>0)
+			numberOfBytes+=n;
+		if(n<0)
+			return -1;
+		if(maxBytes>0 && numberOfBytes>=maxBytes)
+			break;
+	};
+	return numberOfBytes;
+}
+void* UdpServer::getWaste(){ //returns the last datagram retrieved by emptySocket()
+	return wasteBuffer;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/intervals.cpp	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,94 @@
+/*
+ * intervals.h
+ *
+ *  Created on: 18 May 2015
+ *      Author: unmanaged
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <native/timer.h>
+#include <rtdk.h>
+
+#include "../include/intervals.h"
+void Interval::init(int aNumAverages, int aNumFrames, float aSamplingRate, const char *aName){
+	enabled=false;
+	numAverages=aNumAverages;
+	intervals=(RTIME *)malloc(sizeof(RTIME)*numAverages);
+	samplingRate=aSamplingRate;
+	numFrames=aNumFrames;
+	maxTimeus=0;
+	intervalsPointer=0;
+	sum=0;
+	startTime=0;
+
+	if(intervals!=0)
+		enabled=true;
+	int len=strlen(aName);
+	name=(char *)malloc(sizeof(char)*(len+1));
+	strcpy(name, aName);
+	if(name == 0)
+		enabled=false;
+};
+Interval::Interval(){
+	init(100,1,44100,"");
+}
+Interval::Interval(int aNumAverages){
+	init(aNumAverages,1,44100,"");
+}
+Interval::Interval(int aNumAverages, int aNumFrames, float aSamplingRate, const char *aName){
+	init(aNumAverages,aNumFrames,aSamplingRate,aName);
+}
+Interval::~Interval(){
+	free(intervals);
+//			free(name);
+}
+void Interval::setNumFrames(int aNumFrames){
+	numFrames=aNumFrames;
+};
+
+int Interval::start(){
+//	printf("start: intervals: 0x%x, intervalsPointer: %d, numAverages: %d\n", intervals,intervalsPointer,numAverages);
+	if(!enabled)
+		return 0;
+	startTime=rt_timer_read();
+	return 1;
+}
+int Interval::resetMax(){
+	maxTimeus=0;
+	return 1;
+}
+int Interval::split(){ //updates
+	if(!enabled)
+		return 0;
+	int currentInterval=rt_timer_read()-startTime;
+	RTIME *currentPointer=&(intervals[intervalsPointer]);
+	sum-=*currentPointer; //take out the oldest value from the sum
+	*currentPointer=currentInterval;
+	sum+=*currentPointer; //add the new value to the sum
+	timeus=((float)sum)/numAverages/1000.0;
+	maxTimeus=timeus>maxTimeus?timeus:maxTimeus;
+	intervalsPointer++;
+	if(intervalsPointer>=(numAverages-1)){
+		intervalsPointer=0;
+	}
+	return 1;
+}
+void Interval::setEnabled(bool aActive){
+	enabled=aActive;
+}
+float Interval::getTimeus(){
+	return timeus;
+}
+float Interval::getMaxTimeus(){
+	return maxTimeus;
+}
+void Interval::print(){
+	rt_printf(//"sleepTimer time: 29.484us, (1.30 samples, numFrames: 2, 65.01%%). MaxTime: 30.439us, (1.34 samples, 67.12%%)\n");
+"%s time: %.3fus, (%.2f samples, numFrames: %d, %.2f%%). MaxTime: %.3fus, (%.2f samples, %.2f%%)\n",
+			name,
+			timeus, timeus/1000000.0*samplingRate, numFrames, timeus/1000000.0*samplingRate/numFrames * 100,
+			maxTimeus, maxTimeus/1000000.0*samplingRate, maxTimeus/1000000.0*samplingRate/numFrames * 100);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/UdpServer.h	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,51 @@
+/*
+ * udpServer.h
+ *
+ *  Created on: 19 May 2015
+ *      Author: giulio moro
+ */
+
+#ifndef UDPSERVER_H_
+#define UDPSERVER_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+class UdpServer{
+	private:
+		int port;
+		int enabled;
+		int inSocket;
+		struct sockaddr_in server;
+		struct timeval stTimeOut;
+		fd_set stReadFDS;
+		int size;
+		void *wasteBuffer;
+		int wasteBufferSize;
+		int length;
+		socklen_t fromLength;
+		struct sockaddr_in from;
+	public:
+		UdpServer();
+		UdpServer(int aPort);
+		~UdpServer();
+		bool init(int aPort);
+		bool bindToPort(int aPort);
+		int getBoundPort() const;
+		int read(void *destBuffer,
+				int maxBytesToRead);
+		int emptySocket();
+		int emptySocket(int maxBytes);
+		void *getWaste();
+};
+
+
+
+#endif /* UDPSERVER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/intervals.h	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * intervals.h
+ *
+ *  Created on: 18 May 2015
+ *      Author: unmanaged
+ */
+
+#ifndef INTERVALS_H_
+#define INTERVALS_H_
+
+#define TEN_POW_9 1000000000
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <native/timer.h>
+#include <rtdk.h>
+
+class Interval
+{
+	private:
+		int intervalsPointer;
+		long sum;
+		RTIME startTime;
+		RTIME *intervals;
+		float maxTimeus;
+		float timeus;
+		float samplingRate; //used for getPrint()
+		int numFrames;
+		bool enabled; //whether it actually reads the clock or not
+		int numAverages;
+		char *name;
+		void init(int aNumAverages, int aNumFrames, float aSamplingRate, const char *aName);
+	public:
+		Interval();
+		Interval(int aNumAverages);
+		Interval(int aNumAverages, int aNumFrames, float aSamplingRate, const char *aName);
+		~Interval();
+		void setNumFrames(int aNumFrames);
+		int start();
+		int resetMax();
+		int split();
+		void setEnabled(bool aActive);
+		float getTimeus();
+		float getMaxTimeus();
+		void print();
+};
+
+#endif /* INTERVALS_H_ */
--- a/projects/basic_network/render.cpp	Wed Aug 19 23:03:52 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <BeagleRT.h>
-//#include <rtdk.h>
-#include <cmath>
-#include <UdpClient.h>
-#include <Utilities.h>
-
-AuxiliaryTask transmitReceiveDataTask;
-
-#define NETWORK_AUDIO_BUFFER_SIZE 400 //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;
-	bool toBeSent;
-	UdpClient udpClient;
-};
-
-float gFrequency;
-float gPhase;
-float gInverseSampleRate;
-int gCount=0;
-//networkData networkObject;
-#define numNetAudio 3
-networkAudio netAudio[numNetAudio];
-AuxiliaryTask printIntervalTask;
-AuxiliaryTask transmitReceiveAudioTask;
-
-void transmitReceiveAudio(){ //transmit and receive audio buffers
-	for(int n=0;n<numNetAudio; n++){
-		if(netAudio[n].toBeSent){
-			netAudio[n].toBeSent=false;
-			netAudio[n].udpClient.send(netAudio[n].buffers[!netAudio[n].currentBuffer],NETWORK_AUDIO_BUFFER_SIZE*sizeof(float));
-			netAudio[n].doneOnTime=1;
-		}
-	}
-}
-
-// setup() 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 setup(BeagleRTContext *context, void *userData)
-{
-	// Retrieve a parameter passed in from the initAudio() call
-	gFrequency = *(float *)userData;
-
-	gInverseSampleRate = 1.0 / context->audioSampleRate;
-	gPhase = 0.0;
-
-//	networkObject.counter=&gCount;
-//	networkObject.variables[0]=&gFrequency;
-//	networkObject.variables[1]=&gPhase;
-//	networkObject.numVariables=2;
-	for(int n=0; n<numNetAudio; n++){
-		netAudio[n].doneOnTime=1;
-		netAudio[n].index=0;
-		netAudio[n].currentBuffer=0;
-		netAudio[n].toBeSent=false;
-//		netAudio[n].udpClient.setPort(settings->transmitPort+n);
-//		netAudio[n].udpClient.setServer(settings->serverName);
-		netAudio[n].udpClient.setPort(9999+n);
-		netAudio[n].udpClient.setServer("192.168.7.1");
-	}
-//	setupSockets(settings->receivePort, settings->transmitPort, settings->serverName);
-
-//	transmitReceiveDataTask=createAuxiliaryTask(*transmitReceiveData, 10, "transmit-receive-data");
-//	scheduleAuxiliaryTask(transmitReceiveDataTask); //here it does not work
-	transmitReceiveAudioTask=BeagleRT_createAuxiliaryTask(*transmitReceiveAudio, 98, "transmit-receive-audio");
-	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)
-{/*
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		float out = 0.7f * sinf(gPhase);
-		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = out;
-
-		if(gCount == 0){
-			BeagleRT_scheduleAuxiliaryTask(transmitReceiveDataTask);
-		}
-		gCount++;
-	}
-
-
-*/
-	for(int n = 0; n < context->audioFrames; n++) {
-		float out = 0.7f * sinf(gPhase);
-		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-
-//		for(int channel = 0; channel < context->audioChannels; channel++)
-//			context->audioOut[n * context->audioChannels + channel] = context->audioIn[n * context->audioChannels + 0]+context->audioIn[n * context->audioChannels + 1];
-		context->audioOut[n * context->audioChannels] = context->audioIn[n*context->audioChannels+0];
-		context->audioOut[n * context->audioChannels+1]=out;
-		if(0==gCount){
-//			scheduleAuxiliaryTask(transmitReceiveDataTask);
-		}
-		for(int j=0; j<numNetAudio; j++){
-			if(netAudio[j].index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ...
-				netAudio[j].toBeSent=true;
-				netAudio[j].index=0; //reset the counter
-				if(netAudio[j].doneOnTime==0)
-					rt_printf("Network buffer underrun :-{\n");
-				netAudio[j].timestamp=gCount;
-				netAudio[j].currentBuffer=!netAudio[j].currentBuffer; //switch buffer
-				netAudio[j].doneOnTime=0;
-				BeagleRT_scheduleAuxiliaryTask(transmitReceiveAudioTask); //send the buffer
-			}
-		}
-		if((gCount&1)==0){
-			netAudio[1].buffers[netAudio[1].currentBuffer][netAudio[1].index++]=analogReadFrame(context,n/2,0)+context->audioOut[n*context->audioChannels + 0];
-			netAudio[2].buffers[netAudio[2].currentBuffer][netAudio[2].index++]=analogReadFrame(context,n/2,1)+context->audioOut[n*context->audioChannels + 0];
-		}
-		netAudio[0].buffers[netAudio[0].currentBuffer][netAudio[0].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]);//copy channel 0 to the buffer
-//		netAudio[1].buffers[netAudio[1].currentBuffer][netAudio[1].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]);
-//		netAudio[2].buffers[netAudio[2].currentBuffer][netAudio[2].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]);
-		gCount++;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BeagleRTContext *context, void *userData)
-{
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resources/tests/UdpClientUdpServerTest.cpp	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,128 @@
+#include "../../include/UdpServer.h"
+#include "../../include/UdpClient.h"
+#include <unistd.h>
+
+int test1(UdpServer *server, UdpClient *client){
+	int buffer;
+	int tot=100;
+	int errors=0;
+	for(int n=0; n<tot; n++){
+		if(client->send(&n,sizeof(int))!=1){
+			printf("error: while sending\n");
+			errors++;
+		}
+	}
+	for(int n=0; n<tot; n++){
+		if(server->read(&buffer,sizeof(int))<0){
+			printf("error: unable to read\n");
+			errors++;
+			continue;
+		};
+		if(n!=buffer){
+			printf("error: %d!=%d\n",n,buffer);
+			errors++;
+		}
+	}
+	int n=server->emptySocket();
+	if(n!=0)
+		printf("Error: the socket had %d bytes\n",n);
+	return errors;
+}
+int compareStrings(char * str1, char * str2){
+	if(strlen(str1)!=strlen(str2))
+		return -1;
+	for(int n=0; n<strlen(str1); n++){
+		if(str1[n]!=str2[n])
+			return -1;
+	}
+	return 0;
+}
+
+int test2(UdpServer *server, UdpClient *client){
+	char buffer[1000];
+	int tot=100;
+	int errors=0;
+	for(int n=0; n<tot; n++){
+		int num=sprintf(buffer,"%08.8f",n/1000.0);
+		client->send(&buffer,sizeof(char)*(num+1));
+	}
+	char auxBuffer[100];
+	for(int n=0; n<tot; n++){
+		int num=sprintf(auxBuffer,"%08.8f",n/1000.0);
+		server->read(&buffer,num*sizeof(char));
+		if(compareStrings(auxBuffer,buffer)==-1){
+			printf("error: %s!=%s\n",auxBuffer,buffer);
+			errors++;
+		}
+	}
+
+	return errors;
+}
+
+int test3(UdpServer *server, UdpClient *client){
+	char buffer[1000];
+	int tot=100;
+	int errors=0;
+    int totNum=0;
+	for(int n=0; n<tot; n++){
+		int num=sprintf(buffer,"%.8f",n/1000.0);
+		client->send(&buffer,sizeof(char)*(num+1));
+        totNum+=1+num;
+	}
+    int n=server->emptySocket();
+    if(n!=totNum){
+        errors=1;
+        printf("retrieved bytes differs from sent bytes: %d!=%d\n",n,totNum);
+    }
+	return errors;
+}
+
+
+int main(){
+	int port=1234;
+	char serverName[]="127.0.0.1";
+	UdpServer server(port);
+	UdpClient client(port,serverName);
+	int errors=0;
+	int ret=0;
+	ret=test1(&server,&client);
+	errors+=ret;
+	if(ret)
+		printf("test1 failed with %d errors\n", ret);
+	else
+		printf("test1 passed\n");
+
+	ret=test2(&server,&client);
+	errors+=ret;
+	if(ret)
+		printf("test2 failed with %d errors\n", ret);
+	else
+		printf("test2 passed\n");
+
+	ret=test3(&server,&client);
+	errors+=ret;
+	if(ret)
+		printf("test3 failed with %d errors\n", ret);
+	else
+		printf("test3 passed\n");
+//now test if the setPort and setServer methods work
+	client.~UdpClient();
+	server.~UdpServer();
+	port=1235;
+	UdpServer server1;
+	UdpClient client1;
+	client1.setPort(port);
+	client1.setServer(serverName);
+	if(server1.bindToPort(port)==false){
+		printf("unable to bind to port %d\n",port);
+		errors+=1;
+	}
+	ret=test1(&server1, &client1);
+	errors+=ret;
+	if(ret)
+		printf("test1 failed with %d errors\n", ret);
+	else
+		printf("test1 passed\n");
+
+	return errors;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resources/tests/make_tests.sh	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,7 @@
+#!/bin/bash
+mkdir -p build
+mkdir -p bin
+g++ -o build/UdpServer.o -O2 -c ../../core/UdpServer.cpp &&\
+g++ -O2 -o build/UdpClient.o -c ../../core/UdpClient.cpp && \
+g++ -O2 -o build/UdpClientUdpServerTest.o -c UdpClientUdpServerTest.cpp && \
+g++ -o bin/UdpClientUdpServerTest build/UdpClientUdpServerTest.o build/UdpClient.o build/UdpServer.o 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resources/tests/run_tests.sh	Wed Aug 19 23:11:34 2015 +0100
@@ -0,0 +1,2 @@
+#!/bin/bash
+bin/*