Mercurial > hg > beaglert
comparison examples/basic_libpd/render.cpp @ 353:bec5d43e4e7a prerelease
Digital channels are fully managed by Pd
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Wed, 08 Jun 2016 19:44:21 +0100 |
parents | 749aa016fa16 |
children | 1b23300f3e78 |
comparison
equal
deleted
inserted
replaced
352:749aa016fa16 | 353:bec5d43e4e7a |
---|---|
4 * Created on: Oct 24, 2014 | 4 * Created on: Oct 24, 2014 |
5 * Author: parallels | 5 * Author: parallels |
6 */ | 6 */ |
7 | 7 |
8 #include <Bela.h> | 8 #include <Bela.h> |
9 #include <DigitalToMessage.h> | 9 #include <DigitalChannelManager.h> |
10 #include <cmath> | 10 #include <cmath> |
11 #include <Utilities.h> | 11 #include <Utilities.h> |
12 #include <I2c_Codec.h> | 12 #include <I2c_Codec.h> |
13 #include <PRU.h> | 13 #include <PRU.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
43 usleep(1000); | 43 usleep(1000); |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 #define PARSE_MIDI | 47 #define PARSE_MIDI |
48 AuxiliaryTask libpdReadFilesTask; | 48 static AuxiliaryTask libpdReadFilesTask; |
49 Midi midi; | 49 static Midi midi; |
50 static DigitalChannelManager dcm; | |
50 //UdpServer udpServer; | 51 //UdpServer udpServer; |
51 | 52 |
52 static uint32_t clearDataOut; | |
53 static uint32_t setDataOut; | |
54 static uint16_t digitalModeClear; | |
55 static uint16_t digitalModeSet; | |
56 static uint16_t digitalRates; | |
57 | 53 |
58 | 54 |
59 void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){ | 55 void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){ |
60 libpd_float((char*)receiverName, (float)state); | 56 libpd_float((char*)receiverName, (float)state); |
61 // rt_printf("%s: %d\n", (char*)receiverName, state); | 57 // rt_printf("%s: %d\n", (char*)receiverName, state); |
66 void Bela_messageHook(const char *source, const char *symbol, int argc, t_atom *argv){ | 62 void Bela_messageHook(const char *source, const char *symbol, int argc, t_atom *argv){ |
67 if(strcmp(source, "bela_setDigital") == 0){ | 63 if(strcmp(source, "bela_setDigital") == 0){ |
68 // symbol is the direction, argv[0] is the channel, argv[1] (optional) | 64 // symbol is the direction, argv[0] is the channel, argv[1] (optional) |
69 // is signal(\"sig\" or \"~\") or message(\"mess\", default) rate | 65 // is signal(\"sig\" or \"~\") or message(\"mess\", default) rate |
70 bool error = false; | 66 bool error = false; |
71 bool signal = false; // defaults to message rate | 67 bool isMessageRate = true; // defaults to message rate |
72 bool direction; | 68 bool direction; |
73 if(strcmp(symbol, "in") == 0){ | 69 if(strcmp(symbol, "in") == 0){ |
74 direction = INPUT; | 70 direction = INPUT; |
75 } else if(strcmp(symbol, "out") == 0){ | 71 } else if(strcmp(symbol, "out") == 0){ |
76 direction = OUTPUT; | 72 direction = OUTPUT; |
90 if(argc >= 2){ | 86 if(argc >= 2){ |
91 t_atom* a = &argv[1]; | 87 t_atom* a = &argv[1]; |
92 if(libpd_is_symbol(a)){ | 88 if(libpd_is_symbol(a)){ |
93 char *s = libpd_get_symbol(a); | 89 char *s = libpd_get_symbol(a); |
94 if(strcmp(s, "~") == 0 || strncmp(s, "sig", 3) == 0){ | 90 if(strcmp(s, "~") == 0 || strncmp(s, "sig", 3) == 0){ |
95 signal = true; | 91 isMessageRate = false; |
96 } | 92 } |
97 } | 93 } |
98 } | 94 } |
99 digitalRates = changeBit(digitalRates, channel, signal); | 95 dcm.setPinMode(channel, direction, isMessageRate); |
100 if(direction == 1){ | |
101 digitalModeClear = setBit(digitalModeClear, channel); | |
102 digitalModeSet = clearBit(digitalModeSet, channel); | |
103 } else { | |
104 digitalModeSet = setBit(digitalModeSet, channel); | |
105 digitalModeClear = clearBit(digitalModeClear, channel); | |
106 } | |
107 // rt_printf("Channel: %d, input?: %d, ~?: %d\n", channel, direction==INPUT, signal); | |
108 // rt_printf("modeSet 0x%x modeClear 0x%x\n", digitalModeSet, digitalModeClear); | |
109 } | 96 } |
110 } | 97 } |
111 | 98 |
112 void Bela_floatHook(const char *source, float value){ | 99 void Bela_floatHook(const char *source, float value){ |
113 // rt_printf("received: %s %f\n", source, value); | 100 // rt_printf("received: %s %f\n", source, value); |
122 receiver += (source[prefixLength+1] - 48); | 109 receiver += (source[prefixLength+1] - 48); |
123 // rt_printf("received on digital %d value %.0f\n", receiver, value); | 110 // rt_printf("received on digital %d value %.0f\n", receiver, value); |
124 unsigned int channel = receiver - 11; // go back to the actual Bela digital channel number | 111 unsigned int channel = receiver - 11; // go back to the actual Bela digital channel number |
125 if(channel >= 0 && channel < 16){ //16 is the hardcoded value for the number of digital channels | 112 if(channel >= 0 && channel < 16){ //16 is the hardcoded value for the number of digital channels |
126 //TODO: here we should check if this channel has been registered as message-rate output | 113 //TODO: here we should check if this channel has been registered as message-rate output |
127 if(value == 0){ | 114 dcm.setOutput(channel, value); |
128 clearDataOut = setBit(clearDataOut, channel); | |
129 setDataOut = clearBit(setDataOut, channel); | |
130 } else { | |
131 setDataOut = setBit(setDataOut, channel); | |
132 clearDataOut = clearBit(clearDataOut, channel); | |
133 } | |
134 // rt_printf("clear 0x%x set 0x%x\n", clearDataOut, setDataOut); | 115 // rt_printf("clear 0x%x set 0x%x\n", clearDataOut, setDataOut); |
135 } | 116 } |
136 } | 117 } |
137 } | 118 } |
138 } | 119 } |
143 {"bela_digitalIn16"},{"bela_digitalIn17"},{"bela_digitalIn18"},{"bela_digitalIn19"},{"bela_digitalIn20"}, | 124 {"bela_digitalIn16"},{"bela_digitalIn17"},{"bela_digitalIn18"},{"bela_digitalIn19"},{"bela_digitalIn20"}, |
144 {"bela_digitalIn21"},{"bela_digitalIn22"},{"bela_digitalIn23"},{"bela_digitalIn24"},{"bela_digitalIn25"}, | 125 {"bela_digitalIn21"},{"bela_digitalIn22"},{"bela_digitalIn23"},{"bela_digitalIn24"},{"bela_digitalIn25"}, |
145 {"bela_digitalIn26"} | 126 {"bela_digitalIn26"} |
146 }; | 127 }; |
147 | 128 |
148 static DigitalToMessage** dtm; | |
149 static unsigned int analogChannelsInUse; | 129 static unsigned int analogChannelsInUse; |
150 static unsigned int gLibpdBlockSize; | 130 static unsigned int gLibpdBlockSize; |
151 static unsigned int gChannelsInUse = 26; | 131 static unsigned int gChannelsInUse = 26; |
152 | 132 |
153 bool setup(BelaContext *context, void *userData) | 133 bool setup(BelaContext *context, void *userData) |
154 { | 134 { |
135 dcm.setCallback(sendDigitalMessage); | |
155 analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels - context->digitalChannels); | 136 analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels - context->digitalChannels); |
156 dtm = new DigitalToMessage* [context->digitalChannels]; | |
157 if(context->digitalChannels > 0){ | 137 if(context->digitalChannels > 0){ |
158 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ | 138 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ |
159 dtm[ch] = new DigitalToMessage; | 139 dcm.setCallbackArgument(ch, receiverNames[ch]); |
160 dtm[ch]->setCallback(sendDigitalMessage, receiverNames[ch]); | |
161 if((ch%2) == 0 ) | |
162 pinMode(context, 0, ch, INPUT); | |
163 else | |
164 pinMode(context, 0, ch, OUTPUT); | |
165 } | 140 } |
166 } | 141 } |
167 midi.readFrom(0); | 142 midi.readFrom(0); |
168 midi.writeTo(0); | 143 midi.writeTo(0); |
169 #ifdef PARSE_MIDI | 144 #ifdef PARSE_MIDI |
197 libpd_add_float(1.0f); | 172 libpd_add_float(1.0f); |
198 libpd_finish_message("pd", "dsp"); | 173 libpd_finish_message("pd", "dsp"); |
199 | 174 |
200 gBufLength = max(gLibpdBlockSize, context->audioFrames); | 175 gBufLength = max(gLibpdBlockSize, context->audioFrames); |
201 | 176 |
202 char file[] = "_main.pd"; | |
203 char folder[] = "./"; | |
204 // open patch [; pd open file folder( | |
205 libpd_openfile(file, folder); | |
206 | 177 |
207 // bind your receivers here | 178 // bind your receivers here |
208 libpd_bind("bela_digitalOut11"); | 179 libpd_bind("bela_digitalOut11"); |
209 libpd_bind("bela_digitalOut12"); | 180 libpd_bind("bela_digitalOut12"); |
210 libpd_bind("bela_digitalOut13"); | 181 libpd_bind("bela_digitalOut13"); |
221 libpd_bind("bela_digitalOut24"); | 192 libpd_bind("bela_digitalOut24"); |
222 libpd_bind("bela_digitalOut25"); | 193 libpd_bind("bela_digitalOut25"); |
223 libpd_bind("bela_digitalOut26"); | 194 libpd_bind("bela_digitalOut26"); |
224 libpd_bind("bela_setDigital"); | 195 libpd_bind("bela_setDigital"); |
225 | 196 |
197 char file[] = "_main.pd"; | |
198 char folder[] = "./"; | |
199 // open patch [; pd open file folder( | |
200 libpd_openfile(file, folder); | |
226 libpdReadFilesTask = Bela_createAuxiliaryTask(libpdReadFilesLoop, 60, "libpdReadFiles"); | 201 libpdReadFilesTask = Bela_createAuxiliaryTask(libpdReadFilesLoop, 60, "libpdReadFiles"); |
227 Bela_scheduleAuxiliaryTask(libpdReadFilesTask); | 202 Bela_scheduleAuxiliaryTask(libpdReadFilesTask); |
228 | 203 |
229 | 204 |
230 return true; | 205 return true; |
357 } | 332 } |
358 } | 333 } |
359 } | 334 } |
360 | 335 |
361 //then digital | 336 //then digital |
362 //TODO: in multiple places below we assume that the number of digitals is same as number of audio | 337 // note: in multiple places below we assume that the number of digitals is same as number of audio |
363 // digital in at message-rate | 338 // digital in at message-rate |
364 for(unsigned int n = 0; n < context->digitalChannels; ++n){ | 339 dcm.processInput(&context->digital[audioFrameBase], gLibpdBlockSize); |
365 // note that we consider only the first sample of the block | 340 |
366 // considering all of them is notably more expensive | |
367 // TODO: only process the channels marked as such | |
368 dtm[n]->process(n + 16, &context->digital[audioFrameBase], 1); | |
369 } | |
370 // digital in at signal-rate | 341 // digital in at signal-rate |
371 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { | 342 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { |
343 unsigned int digitalFrame = audioFrameBase + j; | |
372 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); | 344 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); |
373 k < 16; ++k, p1 += gLibpdBlockSize) { | 345 k < 16; ++k, p1 += gLibpdBlockSize) { |
374 // note that we only write the last sample of the block | 346 if(dcm.isSignalRate(k) && dcm.isInput(k)){ // only process input channels that are handled at signal rate |
375 // writing all of them is notably more expensive. | 347 *p1 = digitalRead(context, digitalFrame, k); |
376 | 348 } |
377 // TODO: only process the channels marked as such | |
378 unsigned int digitalFrame = audioFrameBase + j; | |
379 *p1 = digitalRead(context, digitalFrame, k); | |
380 } | 349 } |
381 } | 350 } |
382 | 351 |
383 libpd_process_sys(); // process the block | 352 libpd_process_sys(); // process the block |
384 | 353 |
385 //digital out | 354 //digital out |
386 // digital out at signal-rate | 355 // digital out at signal-rate |
387 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { | 356 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { |
388 unsigned int digitalFrame = (audioFrameBase + j); | 357 unsigned int digitalFrame = (audioFrameBase + j); |
389 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); | 358 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); |
390 k < context->digitalChannels; k++, p1 += gLibpdBlockSize) { | 359 k < context->digitalChannels; k++, p1 += gLibpdBlockSize) { |
391 // TODO: only process the channels marked as such | 360 if(dcm.isSignalRate(k) && dcm.isOutput(k)){ // only process output channels that are handled at signal rate |
392 digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5); | 361 digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5); |
362 } | |
393 } | 363 } |
394 } | 364 } |
395 | 365 |
396 // digital out at message-rate | 366 // digital out at message-rate |
397 if(clearDataOut || setDataOut || digitalModeSet || digitalModeClear){ | 367 dcm.processOutput(&context->digital[audioFrameBase], gLibpdBlockSize); |
398 uint32_t orWord = ((setDataOut << 16) | digitalModeSet); | |
399 uint32_t andTildeWord = ((clearDataOut << 16) | digitalModeClear); | |
400 uint32_t outWord; | |
401 for (unsigned int frame = audioFrameBase; frame < audioFrameBase + gLibpdBlockSize; ++frame) { | |
402 outWord = context->digital[frame]; | |
403 outWord = outWord | orWord; | |
404 outWord = outWord &~ andTildeWord; | |
405 context->digital[frame] = outWord; | |
406 } | |
407 } | |
408 | 368 |
409 //audio | 369 //audio |
410 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { | 370 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { |
411 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { | 371 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { |
412 audioWrite(context, audioFrameBase + j, k, *p1); | 372 audioWrite(context, audioFrameBase + j, k, *p1); |
442 // cleanup() is called once at the end, after the audio has stopped. | 402 // cleanup() is called once at the end, after the audio has stopped. |
443 // Release any resources that were allocated in setup(). | 403 // Release any resources that were allocated in setup(). |
444 | 404 |
445 void cleanup(BelaContext *context, void *userData) | 405 void cleanup(BelaContext *context, void *userData) |
446 { | 406 { |
447 delete[] dtm; | 407 } |
448 } |