comparison core/PRU.cpp @ 16:670be80463a3 matrix_gpio

- analog matrixIn/matrixOut are now mapped as floats from 0 to 1 - use of an external PRU code can be enabled with -P <filename> - 16 channels of programmable GPIO can be accessed straight from render() either writing directly to the matrixGpio[] array or using digitalWrite(), digitalRead(), setDigitalDirection() macros from Utilities.h .
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 27 Apr 2015 13:01:57 +0100
parents 901d205d1a3c
children c98863e63174
comparison
equal deleted inserted replaced
15:901d205d1a3c 16:670be80463a3
14 */ 14 */
15 15
16 #include "../include/PRU.h" 16 #include "../include/PRU.h"
17 #include "../include/prussdrv.h" 17 #include "../include/prussdrv.h"
18 #include "../include/pruss_intc_mapping.h" 18 #include "../include/pruss_intc_mapping.h"
19 #include "../include/matrix_gpio_mapping.h"
19 #include "../include/GPIOcontrol.h" 20 #include "../include/GPIOcontrol.h"
20 #include "../include/render.h" 21 #include "../include/render.h"
21 #include "../include/pru_rtaudio_bin.h" 22 #include "../include/pru_rtaudio_bin.h"
22 23
23 #include <iostream> 24 #include <iostream>
24 #include <stdlib.h> 25 #include <stdlib.h>
25 #include <cstdio> 26 #include <cstdio>
26 #include <cerrno> 27 #include <cerrno>
27 #include <fcntl.h> 28 #include <fcntl.h>
28 #include <sys/mman.h> 29 #include <sys/mman.h>
30 #include <unistd.h>
29 31
30 // Xenomai-specific includes 32 // Xenomai-specific includes
31 #include <sys/mman.h> 33 #include <sys/mman.h>
32 #include <native/task.h> 34 #include <native/task.h>
33 #include <native/timer.h> 35 #include <native/timer.h>
38 #define PRU_MEM_MCASP_OFFSET 0x2000 // Offset within PRU-SHARED RAM 40 #define PRU_MEM_MCASP_OFFSET 0x2000 // Offset within PRU-SHARED RAM
39 #define PRU_MEM_MCASP_LENGTH 0x2000 // Length of McASP memory, in bytes 41 #define PRU_MEM_MCASP_LENGTH 0x2000 // Length of McASP memory, in bytes
40 #define PRU_MEM_DAC_OFFSET 0x0 // Offset within PRU0 RAM 42 #define PRU_MEM_DAC_OFFSET 0x0 // Offset within PRU0 RAM
41 #define PRU_MEM_DAC_LENGTH 0x2000 // Length of ADC+DAC memory, in bytes 43 #define PRU_MEM_DAC_LENGTH 0x2000 // Length of ADC+DAC memory, in bytes
42 #define PRU_MEM_COMM_OFFSET 0x0 // Offset within PRU-SHARED RAM 44 #define PRU_MEM_COMM_OFFSET 0x0 // Offset within PRU-SHARED RAM
43 45 #define PRU_MEM_MATRIX_GPIO_OFFSET 0x1000 //Offset within PRU-SHARED RAM
46 #define MEM_MATRIX_GPIO_BUFFER1_OFFSET 0x400 //Start pointer to MATRIX_GPIO_BUFFER1, which is 256 words.
47 // 256 is the maximum number of frames allowed
44 #define PRU_SHOULD_STOP 0 48 #define PRU_SHOULD_STOP 0
45 #define PRU_CURRENT_BUFFER 1 49 #define PRU_CURRENT_BUFFER 1
46 #define PRU_BUFFER_FRAMES 2 50 #define PRU_BUFFER_FRAMES 2
47 #define PRU_SHOULD_SYNC 3 51 #define PRU_SHOULD_SYNC 3
48 #define PRU_SYNC_ADDRESS 4 52 #define PRU_SYNC_ADDRESS 4
50 #define PRU_LED_ADDRESS 6 54 #define PRU_LED_ADDRESS 6
51 #define PRU_LED_PIN_MASK 7 55 #define PRU_LED_PIN_MASK 7
52 #define PRU_FRAME_COUNT 8 56 #define PRU_FRAME_COUNT 8
53 #define PRU_USE_SPI 9 57 #define PRU_USE_SPI 9
54 #define PRU_SPI_NUM_CHANNELS 10 58 #define PRU_SPI_NUM_CHANNELS 10
59 #define PRU_USE_GPIO_MATRIX 11
60
61 short int matrixGpioPins[NUM_MATRIX_GPIOS]={
62 GPIO_NO_BIT_0,
63 GPIO_NO_BIT_1,
64 GPIO_NO_BIT_2,
65 GPIO_NO_BIT_3,
66 GPIO_NO_BIT_4,
67 GPIO_NO_BIT_5,
68 GPIO_NO_BIT_6,
69 GPIO_NO_BIT_7,
70 GPIO_NO_BIT_8,
71 GPIO_NO_BIT_9,
72 GPIO_NO_BIT_10,
73 GPIO_NO_BIT_11,
74 GPIO_NO_BIT_12,
75 GPIO_NO_BIT_13,
76 GPIO_NO_BIT_14,
77 GPIO_NO_BIT_15,
78 };
55 79
56 #define PRU_SAMPLE_INTERVAL_NS 11338 // 88200Hz per SPI sample = 11.338us 80 #define PRU_SAMPLE_INTERVAL_NS 11338 // 88200Hz per SPI sample = 11.338us
57 81
58 #define GPIO0_ADDRESS 0x44E07000 82 #define GPIO0_ADDRESS 0x44E07000
59 #define GPIO1_ADDRESS 0x4804C000 83 #define GPIO1_ADDRESS 0x4804C000
101 // If include_test_pin is set, the GPIO output 125 // If include_test_pin is set, the GPIO output
102 // is also prepared for an output which can be 126 // is also prepared for an output which can be
103 // viewed on a scope. If include_led is set, 127 // viewed on a scope. If include_led is set,
104 // user LED 3 on the BBB is taken over by the PRU 128 // user LED 3 on the BBB is taken over by the PRU
105 // to indicate activity 129 // to indicate activity
106 int PRU::prepareGPIO(int use_spi, int include_test_pin, int include_led) 130 int PRU::prepareGPIO(int use_spi, int use_matrix_gpio, int include_test_pin, int include_led)
107 { 131 {
108 if(use_spi) { 132 if(use_spi) {
109 // Prepare DAC CS/ pin: output, high to begin 133 // Prepare DAC CS/ pin: output, high to begin
110 if(gpio_export(kPruGPIODACSyncPin)) { 134 if(gpio_export(kPruGPIODACSyncPin)) {
111 if(gRTAudioVerbose) 135 if(gRTAudioVerbose)
137 cout << "Couldn't set value on ADC sync pin\n"; 161 cout << "Couldn't set value on ADC sync pin\n";
138 return -1; 162 return -1;
139 } 163 }
140 164
141 spi_enabled = true; 165 spi_enabled = true;
166 }
167
168 if(use_matrix_gpio){
169 printf("gNumMatrixGpioChannels: %d;\n",gNumMatrixGpioChannels);
170 for(int i=0; i<gNumMatrixGpioChannels; i++){
171 if(gpio_export(matrixGpioPins[i])) {
172 if(gRTAudioVerbose)
173 cout << "Warning: couldn't export matrix GPIO pin " << matrixGpioPins[i] << "\n";
174 }
175 if(gpio_set_dir(matrixGpioPins[i], OUTPUT_PIN)) {
176 if(gRTAudioVerbose)
177 cout << "Couldn't set direction on matrix GPIO pin " << matrixGpioPins[i] << "\n";
178 return -1;
179 }
180 if(gpio_set_value(matrixGpioPins[i], HIGH)) {
181 if(gRTAudioVerbose)
182 cout << "Couldn't set value on matrix GPIO pin " << matrixGpioPins[i] << "\n";
183 return -1;
184 }
185 }
186 matrix_gpio_enabled=true;
142 } 187 }
143 188
144 if(include_test_pin) { 189 if(include_test_pin) {
145 // Prepare GPIO test output (for debugging), low to begin 190 // Prepare GPIO test output (for debugging), low to begin
146 if(gpio_export(kPruGPIOTestPin)) { 191 if(gpio_export(kPruGPIOTestPin)) {
208 return; 253 return;
209 if(spi_enabled) { 254 if(spi_enabled) {
210 gpio_unexport(kPruGPIODACSyncPin); 255 gpio_unexport(kPruGPIODACSyncPin);
211 gpio_unexport(kPruGPIOADCSyncPin); 256 gpio_unexport(kPruGPIOADCSyncPin);
212 } 257 }
258 if(matrix_gpio_enabled){
259 for(int i=0; i<gNumMatrixGpioChannels; i++){
260 gpio_unexport(matrixGpioPins[i]);
261 }
262 }
213 if(gpio_test_pin_enabled) { 263 if(gpio_test_pin_enabled) {
214 gpio_unexport(kPruGPIOTestPin); 264 gpio_unexport(kPruGPIOTestPin);
215 gpio_unexport(kPruGPIOTestPin2); 265 gpio_unexport(kPruGPIOTestPin2);
216 gpio_unexport(kPruGPIOTestPin3); 266 gpio_unexport(kPruGPIOTestPin3);
217 } 267 }
219 // Set LED back to default eMMC status 269 // Set LED back to default eMMC status
220 // TODO: make it go back to its actual value before this program, 270 // TODO: make it go back to its actual value before this program,
221 // rather than the system default 271 // rather than the system default
222 led_set_trigger(3, "mmc1"); 272 led_set_trigger(3, "mmc1");
223 } 273 }
224
225 gpio_enabled = gpio_test_pin_enabled = false; 274 gpio_enabled = gpio_test_pin_enabled = false;
226 } 275 }
227 276
228 // Initialise and open the PRU 277 // Initialise and open the PRU
229 int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, bool xenomai_test_pin) 278 int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, bool xenomai_test_pin)
258 /* Map PRU's INTC */ 307 /* Map PRU's INTC */
259 prussdrv_pruintc_init(&pruss_intc_initdata); 308 prussdrv_pruintc_init(&pruss_intc_initdata);
260 309
261 spi_buffer_frames = frames_per_buffer; 310 spi_buffer_frames = frames_per_buffer;
262 audio_buffer_frames = spi_buffer_frames * spi_num_channels / 4; 311 audio_buffer_frames = spi_buffer_frames * spi_num_channels / 4;
312 matrix_gpio_buffer_frames = audio_buffer_frames;
263 313
264 /* Map PRU memory to pointers */ 314 /* Map PRU memory to pointers */
265 prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem); 315 prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem);
266 pru_buffer_comm = (uint32_t *)&pruMem[PRU_MEM_COMM_OFFSET/sizeof(uint32_t)]; 316 pru_buffer_comm = (uint32_t *)&pruMem[PRU_MEM_COMM_OFFSET/sizeof(uint32_t)];
267 pru_buffer_audio_dac = (int16_t *)&pruMem[PRU_MEM_MCASP_OFFSET/sizeof(uint32_t)]; 317 pru_buffer_audio_dac = (int16_t *)&pruMem[PRU_MEM_MCASP_OFFSET/sizeof(uint32_t)];
278 } 328 }
279 else { 329 else {
280 pru_buffer_spi_dac = pru_buffer_spi_adc = 0; 330 pru_buffer_spi_dac = pru_buffer_spi_adc = 0;
281 } 331 }
282 332
333 if(matrix_gpio_enabled) {
334 prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem);
335 pru_buffer_matrix_gpio = (uint32_t *)&pruMem[PRU_MEM_MATRIX_GPIO_OFFSET/sizeof(uint32_t)];
336 }
337 else {
338 pru_buffer_matrix_gpio = 0;
339 }
283 /* Set up flags */ 340 /* Set up flags */
284 pru_buffer_comm[PRU_SHOULD_STOP] = 0; 341 pru_buffer_comm[PRU_SHOULD_STOP] = 0;
285 pru_buffer_comm[PRU_CURRENT_BUFFER] = 0; 342 pru_buffer_comm[PRU_CURRENT_BUFFER] = 0;
286 pru_buffer_comm[PRU_BUFFER_FRAMES] = spi_buffer_frames; 343 pru_buffer_comm[PRU_BUFFER_FRAMES] = spi_buffer_frames;
287 pru_buffer_comm[PRU_SHOULD_SYNC] = 0; 344 pru_buffer_comm[PRU_SHOULD_SYNC] = 0;
301 } 358 }
302 else { 359 else {
303 pru_buffer_comm[PRU_USE_SPI] = 0; 360 pru_buffer_comm[PRU_USE_SPI] = 0;
304 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0; 361 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0;
305 } 362 }
363 if(matrix_gpio_enabled) {
364 pru_buffer_comm[PRU_USE_GPIO_MATRIX] = 1;
365 pru_buffer_comm[NUM_MATRIX_GPIOS] = spi_num_channels;
366 }
367 else {
368 pru_buffer_comm[PRU_USE_GPIO_MATRIX] = 0;
369 pru_buffer_comm[NUM_MATRIX_GPIOS] = 0;
370 }
306 371
307 /* Clear ADC and DAC memory */ 372 /* Clear ADC and DAC memory */
308 if(spi_enabled) { 373 if(spi_enabled) {
309 for(int i = 0; i < PRU_MEM_DAC_LENGTH / 2; i++) 374 for(int i = 0; i < PRU_MEM_DAC_LENGTH / 2; i++)
310 pru_buffer_spi_dac[i] = 0; 375 pru_buffer_spi_dac[i] = 0;
311 } 376 }
312 for(int i = 0; i < PRU_MEM_MCASP_LENGTH / 2; i++) 377 for(int i = 0; i < PRU_MEM_MCASP_LENGTH / 2; i++)
313 pru_buffer_audio_dac[i] = 0; 378 pru_buffer_audio_dac[i] = 0;
314 379 //TODO: maybe the lines below are to be deleted, as we removed the test code from pru_rtaudio.p ?
315 /* If using GPIO test pin for Xenomai (for debugging), initialise the pointer now */ 380 /* If using GPIO test pin for Xenomai (for debugging), initialise the pointer now */
316 if(xenomai_test_pin && xenomai_gpio_fd < 0) { 381 if(xenomai_test_pin && xenomai_gpio_fd < 0) {
317 xenomai_gpio_fd = open("/dev/mem", O_RDWR); 382 xenomai_gpio_fd = open("/dev/mem", O_RDWR);
318 if(xenomai_gpio_fd < 0) 383 if(xenomai_gpio_fd < 0)
319 rt_printf("Unable to open /dev/mem for GPIO test pin\n"); 384 rt_printf("Unable to open /dev/mem for GPIO test pin\n");
330 395
331 return 0; 396 return 0;
332 } 397 }
333 398
334 // Run the code image in the specified file 399 // Run the code image in the specified file
335 int PRU::start() 400 int PRU::start(char * const filename)
336 { 401 {
337 /* Clear any old interrupt */ 402 /* Clear any old interrupt */
338 if(pru_number == 0) 403 if(pru_number == 0)
339 prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); 404 prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
340 else 405 else
341 prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT); 406 prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT);
342 407 /* Load and execute binary on PRU */
343 /* Load and execute binary on PRU */ 408 if(filename[0] == '\0') { //if the string is empty, load the embedded code
344 if(prussdrv_exec_code(pru_number, PRUcode, sizeof(PRUcode))) { 409 if(gRTAudioVerbose)
345 rt_printf("Failed to execute PRU code\n"); 410 rt_printf("Using embedded PRU code\n");
346 return 1; 411 if(prussdrv_exec_code(pru_number, PRUcode, sizeof(PRUcode))) {
347 } 412 rt_printf("Failed to execute PRU code\n");
413 return 1;
414 }
415 } else {
416 if(gRTAudioVerbose)
417 rt_printf("Using PRU code from %s\n",filename);
418 if(prussdrv_exec_program(pru_number, filename)) {
419 rt_printf("Failed to execute PRU code from %s\n", filename);
420 return 1;
421 }
422 }
348 423
349 running = true; 424 running = true;
350 return 0; 425 return 0;
351 } 426 }
427 uint32_t empty[1024]={0x0};
352 428
353 // Main loop to read and write data from/to PRU 429 // Main loop to read and write data from/to PRU
354 void PRU::loop() 430 void PRU::loop()
355 { 431 {
356 // Polling interval is 1/4 of the period 432 // Polling interval is 1/4 of the period
357 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (spi_num_channels / 2) * spi_buffer_frames / 4; 433 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (spi_num_channels / 2) * spi_buffer_frames / 4;
358 float *audioInBuffer, *audioOutBuffer; 434 float *audioInBuffer, *audioOutBuffer;
435 float *matrixInBuffer, *matrixOutBuffer;
436 uint32_t *matrixGpioBuffer0, *matrixGpioBuffer1, *matrixGpioBufferTemp;
359 437
360 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 438 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
361 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 439 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
362 440 matrixInBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
441 matrixOutBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
442 matrixGpioBuffer0 = pru_buffer_matrix_gpio;
443 matrixGpioBuffer1 = pru_buffer_matrix_gpio+MEM_MATRIX_GPIO_BUFFER1_OFFSET/sizeof(uint32_t);
444 matrix_gpio_buffer_frames = matrix_gpio_enabled ? audio_buffer_frames : 0; //TODO: find a more elegant solution for when the matrix_gpio is disabled e.g.:
445 // - embed in the digitalWrite/Read macros a check whether matrix_gpio is enabled
446 // - allocate some memory in ARM just to allow render() to run regardless.
447 // in this case it can be matrixGpioBuffer0 == matrixGpioBuffer1
448 printf("matrix_gpio_buffer_frames: %d;\n",matrix_gpio_buffer_frames);
449 matrixGpioBufferTemp = (uint32_t *)malloc(matrix_gpio_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states
363 if(audioInBuffer == 0 || audioOutBuffer == 0) { 450 if(audioInBuffer == 0 || audioOutBuffer == 0) {
364 rt_printf("Error: couldn't allocated audio buffers\n"); 451 rt_printf("Error: couldn't allocate audio buffers\n");
365 return; 452 return;
366 } 453 }
367 454 if(matrixInBuffer == 0 || matrixOutBuffer == 0) {
455 rt_printf("Error: couldn't allocate matrix buffers\n");
456 return;
457 }
458 if(matrixGpioBufferTemp == 0) {
459 rt_printf("Error: couldn't allocate matrix GPIO buffers\n");
460 return;
461 }
462
368 while(!gShouldStop) { 463 while(!gShouldStop) {
369 // Wait for PRU to move to buffer 1 464 // Wait for PRU to move to buffer 1
370 while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) { 465 while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) {
371 rt_task_sleep(sleepTime); 466 rt_task_sleep(sleepTime);
372 } 467 }
381 // Render from/to buffer 0 476 // Render from/to buffer 0
382 477
383 // Convert short (16-bit) samples to float 478 // Convert short (16-bit) samples to float
384 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) 479 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++)
385 audioInBuffer[n] = (float)pru_buffer_audio_adc[n] / 32768.0; 480 audioInBuffer[n] = (float)pru_buffer_audio_adc[n] / 32768.0;
386 481 if(spi_enabled) {
387 if(spi_enabled) 482 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++)
388 render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, 483 matrixInBuffer[n] = (float)pru_buffer_spi_adc[n] / 65536.0;
389 pru_buffer_spi_adc, pru_buffer_spi_dac); 484 //use past matrix_gpio values to initialize the array properly:
485 //- pins previously set as outputs will keep their previously set output value,
486 //- pins previously set as inputs will carry the newly read input value
487 if(matrix_gpio_enabled){
488 for(unsigned int n = 0; n < matrix_gpio_buffer_frames; n++){
489 uint16_t inputs=matrixGpioBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
490 // printf("inputs: 0x%x\n",inputs);
491 uint16_t outputs=~inputs; //half-word has 1 for outputs and 0 for inputs;
492 matrixGpioBuffer0[n]=(matrixGpioBufferTemp[n]&(outputs<<16))| //keep output values set in previous matrixGpioBuffer1[n]
493 (matrixGpioBuffer0[n]&(inputs<<16)) | //inputs from current matrixGpioBuffer0[n];
494 (matrixGpioBufferTemp[n]&(inputs)); //keep pin configuration from previous matrixGpioBuffer1[n]
495 // matrixGpioBuffer0[n]=matrixGpioBufferTemp[n]; //ignores inputs
496 }
497 }
498 render(spi_buffer_frames, matrix_gpio_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
499 matrixInBuffer, matrixOutBuffer, matrixGpioBuffer0);
500 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
501 int out = matrixOutBuffer[n] * 65536.0;
502 if(out < 0) out = 0;
503 else if(out > 65535) out = 65535;
504 pru_buffer_spi_dac[n] = (uint16_t)out;
505 }
506 if(matrix_gpio_enabled){ // keep track of past matrix_gpio values
507 for(unsigned int n = 0; n < matrix_gpio_buffer_frames; n++){
508 matrixGpioBufferTemp[n]=matrixGpioBuffer0[n];
509 }
510 }
511 }
390 else 512 else
391 render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0); 513 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass matrixGpioBuffer, just it is unused
392 514 // Convert float back to short
393 // Convert float back to short
394 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) { 515 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) {
395 int out = audioOutBuffer[n] * 32768.0; 516 int out = audioOutBuffer[n] * 32768.0;
396 if(out < -32768) out = -32768; 517 if(out < -32768) out = -32768;
397 else if(out > 32767) out = 32767; 518 else if(out > 32767) out = 32767;
398 pru_buffer_audio_dac[n] = (int16_t)out; 519 pru_buffer_audio_dac[n] = (int16_t)out;
420 541
421 // Convert short (16-bit) samples to float 542 // Convert short (16-bit) samples to float
422 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) 543 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++)
423 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0; 544 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0;
424 545
425 if(spi_enabled) 546 if(spi_enabled) {
426 render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, 547 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++)
427 &pru_buffer_spi_adc[spi_buffer_frames * spi_num_channels], &pru_buffer_spi_dac[spi_buffer_frames * spi_num_channels]); 548 matrixInBuffer[n] = (float)pru_buffer_spi_adc[n + spi_buffer_frames * spi_num_channels] / 65536.0;
549
550 //use past matrix_gpio values to initialize the array properly:
551 //- pins previously set as outputs will keep their previously set output value,
552 //- pins previously set as inputs will carry the newly read input value
553 if(matrix_gpio_enabled){
554 for(unsigned int n = 0; n < matrix_gpio_buffer_frames; n++){
555 uint16_t inputs=matrixGpioBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
556 uint16_t outputs=~inputs; //half-word has 1 for outputs and one for inputs;
557 matrixGpioBuffer1[n]=(matrixGpioBufferTemp[n]&(outputs<<16))| //keep output values set in previous matrixGpioBuffer1[n]
558 (matrixGpioBuffer1[n]&(inputs<<16)) | //inputs from current matrixGpioBuffer1[n];
559 (matrixGpioBufferTemp[n]&(inputs)); //keep pin configuration from previous matrixGpioBuffer1[n]
560 // matrixGpioBuffer1[n]=matrixGpioBufferTemp[n]; //ignores inputs
561 }
562 }
563 render(spi_buffer_frames, matrix_gpio_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
564 matrixInBuffer, matrixOutBuffer, matrixGpioBuffer1);
565 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
566 int out = matrixOutBuffer[n] * 65536.0;
567 if(out < 0) out = 0;
568 else if(out > 65535) out = 65535;
569 pru_buffer_spi_dac[n + spi_buffer_frames * spi_num_channels] = (uint16_t)out;
570 }
571 if(matrix_gpio_enabled){ // keep track of past matrix_gpio values
572 for(unsigned int n = 0; n < matrix_gpio_buffer_frames; n++){
573 matrixGpioBufferTemp[n]=matrixGpioBuffer1[n];
574 }
575 }
576 }
428 else 577 else
429 render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0); 578 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass matrixGpioBuffer, just it is unused
430 579
431 // Convert float back to short 580 // Convert float back to short
432 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) { 581 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) {
433 int out = audioOutBuffer[n] * 32768.0; 582 int out = audioOutBuffer[n] * 32768.0;
434 if(out < -32768) out = -32768; 583 if(out < -32768) out = -32768;
443 } 592 }
444 593
445 // Tell PRU to stop 594 // Tell PRU to stop
446 pru_buffer_comm[PRU_SHOULD_STOP] = 1; 595 pru_buffer_comm[PRU_SHOULD_STOP] = 1;
447 596
597 free(matrixOutBuffer);
448 free(audioInBuffer); 598 free(audioInBuffer);
449 free(audioOutBuffer); 599 free(audioOutBuffer);
600 free(matrixInBuffer);
601 free(matrixGpioBufferTemp);
450 } 602 }
451 603
452 // Wait for an interrupt from the PRU indicate it is finished 604 // Wait for an interrupt from the PRU indicate it is finished
453 void PRU::waitForFinish() 605 void PRU::waitForFinish()
454 { 606 {