changeset 345:0e1e0dfe24c5 prerelease

Added embryonal support for digital messages with libpd. TODO: test it, only process used channels, add defines. It is quite CPU-intensive
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 07 Jun 2016 03:40:01 +0100
parents 1c35a5d0ce32
children c6a15a8dee02 d2ce15eed8c1
files examples/basic_libpd/render.cpp include/DigitalToMessage.h
diffstat 2 files changed, 137 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/examples/basic_libpd/render.cpp	Tue Jun 07 02:06:49 2016 +0100
+++ b/examples/basic_libpd/render.cpp	Tue Jun 07 03:40:01 2016 +0100
@@ -6,6 +6,7 @@
  */
 
 #include <Bela.h>
+#include <DigitalToMessage.h>
 #include <cmath>
 #include <Utilities.h>
 #include <I2c_Codec.h>
@@ -16,13 +17,11 @@
 #include "s_stuff.h"
 #include <UdpServer.h>
 #include <Midi.h>
-
-// if you are 100% sure of what value that was used to compile libpd/puredata, then
-// you could define this, instead of getting it at runtime. It has proved to give some 0.3%
+//extern t_sample* sys_soundin;
+//extern t_sample* sys_soundout;
+// if you are 100% sure of what value was used to compile libpd/puredata, then
+// you could #define this instead of getting it at runtime. It has proved to give some 0.3%
 // performance boost when it is 8 (thanks to vectorize optimizations I guess).
-unsigned int gLibpdBlockSize;
-
-unsigned int gChannelsInUse = 10;
 int gBufLength;
 
 float* gInBuf;
@@ -53,8 +52,33 @@
 Midi midi;
 //UdpServer udpServer;
 
+void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){
+	libpd_float((char*)receiverName, (float)state);
+//	rt_printf("%s: %d\n", (char*)receiverName, state);
+}
+char receiverNames[16][21]={
+	{"bela_digitalIn11"},{"bela_digitalIn12"},{"bela_digitalIn13"},{"bela_digitalIn14"},{"bela_digitalIn15"},
+	{"bela_digitalIn16"},{"bela_digitalIn17"},{"bela_digitalIn18"},{"bela_digitalIn19"},{"bela_digitalIn20"},
+	{"bela_digitalIn21"},{"bela_digitalIn22"},{"bela_digitalIn23"},{"bela_digitalIn24"},{"bela_digitalIn25"},
+	{"bela_digitalIn26"}
+};
+
+static DigitalToMessage** dtm;
+static unsigned int analogChannelsInUse;
+static unsigned int gLibpdBlockSize;
+static unsigned int gChannelsInUse = 26;
+
 bool setup(BelaContext *context, void *userData)
 {
+	analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels - context->digitalChannels);
+	dtm = new DigitalToMessage* [context->digitalChannels];
+	if(context->digitalChannels > 0){
+		for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){
+			dtm[ch] = new DigitalToMessage;
+			dtm[ch]->setCallback(sendDigitalMessage, receiverNames[ch]);
+			pinMode(context, 0, ch, OUTPUT);
+		}
+	}
 	midi.readFrom(0);
 	midi.writeTo(0);
 #ifdef PARSE_MIDI
@@ -62,7 +86,7 @@
 #else
 	midi.enableParser(false);
 #endif /* PARSE_MIDI */
-	gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
+//	gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
 //	udpServer.bindToPort(1234);
 
 	gLibpdBlockSize = libpd_blocksize();
@@ -105,7 +129,7 @@
 // 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.
-BelaContext *c;
+
 void render(BelaContext *context, void *userData)
 {
 	int num;
@@ -192,17 +216,16 @@
  *	 do not need the for loops before and after libpd_process_float, so you can save quite some
  *	 memory operations.
  */
-	static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
 	static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize;
 	for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){
-		unsigned int audioOutFrameBase = gLibpdBlockSize * tick;
+		unsigned int audioFrameBase = gLibpdBlockSize * tick;
 		unsigned int j;
 		unsigned int k;
 		float* p0;
 		float* p1;
 		for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
 			for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
-				*p1 = audioRead(context, audioOutFrameBase + j, k);
+				*p1 = audioRead(context, audioFrameBase + j, k);
 			}
 		}
 		// then analogs
@@ -210,51 +233,73 @@
 		if(context->analogChannels == 8 ){ //hold the value for two frames
 			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
 				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					unsigned int analogFrame = (audioOutFrameBase + j) / 2;
+					unsigned int analogFrame = (audioFrameBase + j) / 2;
 					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		} else if(context->analogChannels == 4){ //write every frame
 			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
 				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					unsigned int analogFrame = audioOutFrameBase + j;
+					unsigned int analogFrame = audioFrameBase + j;
 					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		} else if(context->analogChannels == 2){ //drop every other frame
 			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
 				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					unsigned int analogFrame = (audioOutFrameBase + j) * 2;
+					unsigned int analogFrame = (audioFrameBase + j) * 2;
 					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		}
+
+		//then digital
+		 //TODO: in multiple places we assume that the number of digitals is same as number of audio
+		for(unsigned int n = 0; n < context->digitalChannels; ++n){
+			// TODO: note that we consider only the first sample of the block
+			// considering all of them is notably more expensive
+			// TODO: only process the channels marked as such
+			dtm[n]->process(n + 16, &context->digital[audioFrameBase], 1);
+		}
+
 		libpd_process_sys(); // process the block
+
+		//digital
+		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
+			unsigned int digitalFrame = (audioFrameBase + j);
+			for (k = 0, p1 = p0  + gLibpdBlockSize * (context->audioChannels + 8);
+					k < context->digitalChannels; k++, p1 += gLibpdBlockSize) {
+				// TODO: only process the channels marked as such
+				digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5);
+			}
+		}
+		//audio
 		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
 			for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
-				audioWrite(context, audioOutFrameBase + j, k, *p1);
+				audioWrite(context, audioFrameBase + j, k, *p1);
 			}
 		}
+		//analog
 		if(context->analogChannels == 8){
 			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j += 2, p0 += 2) { //write every two frames
-				unsigned int analogFrame = (audioOutFrameBase + j) / 2;
+				unsigned int analogFrame = (audioFrameBase + j) / 2;
 				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					analogWrite(context, analogFrame, k, *p1);
+					analogWriteOnce(context, analogFrame, k, *p1);
 				}
 			}
 		} else if(context->analogChannels == 4){ //write every frame
 			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
-				unsigned int analogFrame = (audioOutFrameBase + j);
+				unsigned int analogFrame = (audioFrameBase + j);
 				for (k = 0, p1 = p0  + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					analogWrite(context, analogFrame, k, *p1);
+					analogWriteOnce(context, analogFrame, k, *p1);
 				}
 			}
 		} else if(context->analogChannels == 2){ //write every frame twice
 			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
 				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
-					int analogFrame = audioOutFrameBase * 2 + j * 2;
-					analogWrite(context, analogFrame, k, *p1);
-					analogWrite(context, analogFrame + 1, k, *p1);
+					int analogFrame = audioFrameBase * 2 + j * 2;
+					analogWriteOnce(context, analogFrame, k, *p1);
+					analogWriteOnce(context, analogFrame + 1, k, *p1);
 				}
 			}
 		}
@@ -269,4 +314,5 @@
 void cleanup(BelaContext *context, void *userData)
 {
 	libpd_queued_release();
+	delete[] dtm;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/DigitalToMessage.h	Tue Jun 07 03:40:01 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * DigitalStream.h
+ *
+ *  Created on: 7 Jun 2016
+ *      Author: giulio
+ */
+
+#ifndef DIGITALTOMESSAGE_H_
+#define DIGITALTOMESSAGE_H_
+#include <Bela.h>
+
+//class ProcessedDigitalChannel{
+//	ProcessedDigitalChannel(){
+//		digitalToMessageActive = false;
+//		messageToDigitalActive = false;
+//		analogToDigitalActive = false;
+//	};
+//	void processInput(unsigned int bit, uint32_t* array, unsigned int length){
+//		if(digitalToMessageActive){
+//			digitalToMessage.process(bit, array, length);
+//		}
+//	};
+//	void processOutput(unsigned int bit, uint32_t* digitalArray, float* analogArray, unsigned int length){
+//
+//	}
+//	DigitalToMessage* getDigitalToMessage(){
+//		return digitalToMessage;
+//	}
+//	DigitalToMessage digitalToMessage;
+//	bool digitalToMessageActive;
+//	bool messageToDigitalActive;
+//	bool analogToDigitalActive;
+//};
+
+class DigitalToMessage {
+public:
+	DigitalToMessage();
+	void setCallback(void (*newCallback)(bool, unsigned int, void*), void* arg){
+		callbackArg = arg;
+		stateChangedCallback = newCallback;
+		if(newCallback != NULL){
+			callbackEnabled = true;
+		} else {
+			callbackEnabled = false;
+		}
+	};
+	void process(unsigned int bit, uint32_t* array, unsigned int length){
+		if(callbackEnabled == false){
+			return;
+		}
+		for(unsigned int n = 0 ; n < length; ++n){
+			bool state = ((array[n]) >> (bit)) & 1;
+			if(state != lastState){ //TODO: use debounceLength
+				stateChangedCallback(state, n, callbackArg);
+			}
+			lastState = state;
+		}
+	};
+	void setDebounceLength(unsigned int length);
+	virtual ~DigitalToMessage();
+private:
+	unsigned int debounceLength;
+	bool callbackEnabled;
+	void* callbackArg;
+	void (*stateChangedCallback)(bool, unsigned int, void*);
+	bool lastState;
+};
+
+#endif /* DIGITALTOMESSAGE_H_ */