Mercurial > hg > beaglert
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 { |