Mercurial > hg > beaglert
comparison core/PRU.cpp @ 81:92145ba7aabf
Updated PRU code to allow pinModeFrame() and [untested] digitalWriteFrame() and analogWriteFrame() to be called from setup(). Updated basic_blink example accordingly.
author | andrewm |
---|---|
date | Fri, 17 Jul 2015 22:16:53 +0100 |
parents | 3c3a1357657d |
children | 3068421c0737 c0bf6157f67e |
comparison
equal
deleted
inserted
replaced
79:90e0c7750df3 | 81:92145ba7aabf |
---|---|
385 xenomai_gpio_fd = -1; | 385 xenomai_gpio_fd = -1; |
386 } | 386 } |
387 } | 387 } |
388 } | 388 } |
389 | 389 |
390 // Allocate audio buffers | |
391 context->audioIn = (float *)malloc(2 * context->audioFrames * sizeof(float)); | |
392 context->audioOut = (float *)malloc(2 * context->audioFrames * sizeof(float)); | |
393 if(context->audioIn == 0 || context->audioOut == 0) { | |
394 rt_printf("Error: couldn't allocate audio buffers\n"); | |
395 return 1; | |
396 } | |
397 | |
398 // Allocate analog buffers | |
399 if(analog_enabled) { | |
400 context->analogIn = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | |
401 context->analogOut = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | |
402 last_analog_out_frame = (float *)malloc(context->analogChannels * sizeof(float)); | |
403 | |
404 if(context->analogIn == 0 || context->analogOut == 0 || last_analog_out_frame == 0) { | |
405 rt_printf("Error: couldn't allocate analog buffers\n"); | |
406 return 1; | |
407 } | |
408 | |
409 memset(last_analog_out_frame, 0, context->analogChannels * sizeof(float)); | |
410 } | |
411 | |
412 // Allocate digital buffers | |
413 digital_buffer0 = pru_buffer_digital; | |
414 digital_buffer1 = pru_buffer_digital + MEM_DIGITAL_BUFFER1_OFFSET / sizeof(uint32_t); | |
415 if(digital_enabled) { | |
416 last_digital_buffer = (uint32_t *)malloc(context->digitalFrames * sizeof(uint32_t)); //temp buffer to hold previous states | |
417 if(last_digital_buffer == 0) { | |
418 rt_printf("Error: couldn't allocate digital buffers\n"); | |
419 return 1; | |
420 } | |
421 | |
422 for(unsigned int n = 0; n < context->digitalFrames; n++){ | |
423 // Initialize lastDigitalFrames to all inputs | |
424 last_digital_buffer[n] = 0x0000ffff; | |
425 } | |
426 } | |
427 | |
428 context->digital = digital_buffer0; | |
429 | |
390 return 0; | 430 return 0; |
391 } | 431 } |
392 | 432 |
393 // Run the code image in the specified file | 433 // Run the code image in the specified file |
394 int PRU::start(char * const filename) | 434 int PRU::start(char * const filename) |
425 #else | 465 #else |
426 // Polling interval is 1/4 of the period | 466 // Polling interval is 1/4 of the period |
427 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; | 467 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; |
428 #endif | 468 #endif |
429 | 469 |
430 float *lastAnalogOutFrame; | |
431 uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer; | |
432 uint32_t pru_audio_offset, pru_spi_offset; | 470 uint32_t pru_audio_offset, pru_spi_offset; |
433 | 471 |
434 // Allocate audio buffers | 472 // Before starting, look at the last state of the analog and digital outputs which might |
435 context->audioIn = (float *)malloc(2 * context->audioFrames * sizeof(float)); | 473 // have been changed by the user during the setup() function. This lets us start with pin |
436 context->audioOut = (float *)malloc(2 * context->audioFrames * sizeof(float)); | 474 // directions and output values at something other than defaults. |
437 if(context->audioIn == 0 || context->audioOut == 0) { | 475 |
438 rt_printf("Error: couldn't allocate audio buffers\n"); | |
439 return; | |
440 } | |
441 | |
442 // Allocate analog buffers | |
443 if(analog_enabled) { | 476 if(analog_enabled) { |
444 context->analogIn = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | 477 if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { |
445 context->analogOut = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | 478 // Remember the content of the last_analog_out_frame |
446 lastAnalogOutFrame = (float *)malloc(context->analogChannels * sizeof(float)); | 479 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ |
447 | 480 last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; |
448 if(context->analogIn == 0 || context->analogOut == 0 || lastAnalogOutFrame == 0) { | 481 } |
449 rt_printf("Error: couldn't allocate analog buffers\n"); | 482 } |
450 return; | 483 } |
451 } | 484 |
452 | |
453 memset(lastAnalogOutFrame, 0, context->analogChannels * sizeof(float)); | |
454 } | |
455 | |
456 // Allocate digital buffers | |
457 digitalBuffer0 = pru_buffer_digital; | |
458 digitalBuffer1 = pru_buffer_digital + MEM_DIGITAL_BUFFER1_OFFSET / sizeof(uint32_t); | |
459 if(digital_enabled) { | 485 if(digital_enabled) { |
460 lastDigitalBuffer = (uint32_t *)malloc(context->digitalFrames * sizeof(uint32_t)); //temp buffer to hold previous states | |
461 if(lastDigitalBuffer == 0) { | |
462 rt_printf("Error: couldn't allocate digital buffers\n"); | |
463 return; | |
464 } | |
465 | |
466 for(unsigned int n = 0; n < context->digitalFrames; n++){ | 486 for(unsigned int n = 0; n < context->digitalFrames; n++){ |
467 // Initialize lastDigitalFrames to all inputs | 487 last_digital_buffer[n] = context->digital[n]; |
468 lastDigitalBuffer[n] = 0x0000ffff; | |
469 } | 488 } |
470 } | 489 } |
471 | 490 |
472 // TESTING | 491 // TESTING |
473 // uint32_t testCount = 0; | 492 // uint32_t testCount = 0; |
516 if(pru_buffer_comm[PRU_CURRENT_BUFFER] == 1) { | 535 if(pru_buffer_comm[PRU_CURRENT_BUFFER] == 1) { |
517 // PRU is on buffer 1. We read and write to buffer 0 | 536 // PRU is on buffer 1. We read and write to buffer 0 |
518 pru_audio_offset = 0; | 537 pru_audio_offset = 0; |
519 pru_spi_offset = 0; | 538 pru_spi_offset = 0; |
520 if(digital_enabled) | 539 if(digital_enabled) |
521 context->digital = digitalBuffer0; | 540 context->digital = digital_buffer0; |
522 } | 541 } |
523 else { | 542 else { |
524 // PRU is on buffer 0. We read and write to buffer 1 | 543 // PRU is on buffer 0. We read and write to buffer 1 |
525 pru_audio_offset = context->audioFrames * 2; | 544 pru_audio_offset = context->audioFrames * 2; |
526 pru_spi_offset = context->analogFrames * context->analogChannels; | 545 pru_spi_offset = context->analogFrames * context->analogChannels; |
527 if(digital_enabled) | 546 if(digital_enabled) |
528 context->digital = digitalBuffer1; | 547 context->digital = digital_buffer1; |
529 } | 548 } |
530 | 549 |
531 // FIXME: some sort of margin is needed here to prevent the audio | 550 // FIXME: some sort of margin is needed here to prevent the audio |
532 // code from completely eating the Linux system | 551 // code from completely eating the Linux system |
533 // testCount++; | 552 // testCount++; |
551 | 570 |
552 if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { | 571 if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { |
553 // Initialize the output buffer with the values that were in the last frame of the previous output | 572 // Initialize the output buffer with the values that were in the last frame of the previous output |
554 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ | 573 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ |
555 for(unsigned int n = 0; n < context->analogFrames; n++){ | 574 for(unsigned int n = 0; n < context->analogFrames; n++){ |
556 context->analogOut[n * context->analogChannels + ch] = lastAnalogOutFrame[ch]; | 575 context->analogOut[n * context->analogChannels + ch] = last_analog_out_frame[ch]; |
557 } | 576 } |
558 } | 577 } |
559 } | 578 } |
560 else { | 579 else { |
561 // Outputs are 0 unless set otherwise | 580 // Outputs are 0 unless set otherwise |
568 // For each frame: | 587 // For each frame: |
569 // - pins previously set as outputs will keep the output value they had in the last frame of the previous buffer, | 588 // - pins previously set as outputs will keep the output value they had in the last frame of the previous buffer, |
570 // - pins previously set as inputs will carry the newly read input value | 589 // - pins previously set as inputs will carry the newly read input value |
571 | 590 |
572 for(unsigned int n = 0; n < context->digitalFrames; n++){ | 591 for(unsigned int n = 0; n < context->digitalFrames; n++){ |
573 uint16_t inputs = lastDigitalBuffer[n] & 0xffff; // half-word, has 1 for inputs and 0 for outputs | 592 uint16_t inputs = last_digital_buffer[n] & 0xffff; // half-word, has 1 for inputs and 0 for outputs |
574 | 593 |
575 uint16_t outputs = ~inputs; // half-word has 1 for outputs and 0 for inputs; | 594 uint16_t outputs = ~inputs; // half-word has 1 for outputs and 0 for inputs; |
576 context->digital[n] = (lastDigitalBuffer[context->digitalFrames - 1] & (outputs << 16)) | // keep output values set in the last frame of the previous buffer | 595 context->digital[n] = (last_digital_buffer[context->digitalFrames - 1] & (outputs << 16)) | // keep output values set in the last frame of the previous buffer |
577 (context->digital[n] & (inputs << 16)) | // inputs from current context->digital[n]; | 596 (context->digital[n] & (inputs << 16)) | // inputs from current context->digital[n]; |
578 (lastDigitalBuffer[n] & (inputs)); // keep pin configuration from previous context->digital[n] | 597 (last_digital_buffer[n] & (inputs)); // keep pin configuration from previous context->digital[n] |
579 // context->digital[n]=digitalBufferTemp[n]; //ignores inputs | 598 // context->digital[n]=digitalBufferTemp[n]; //ignores inputs |
580 } | 599 } |
581 } | 600 } |
582 | 601 |
583 // Call user render function | 602 // Call user render function |
585 render(context, userData); | 604 render(context, userData); |
586 // *********************** | 605 // *********************** |
587 | 606 |
588 if(analog_enabled) { | 607 if(analog_enabled) { |
589 if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { | 608 if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { |
590 // Remember the content of the lastAnalogOutFrame | 609 // Remember the content of the last_analog_out_frame |
591 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ | 610 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ |
592 lastAnalogOutFrame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; | 611 last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; |
593 } | 612 } |
594 } | 613 } |
595 | 614 |
596 // Convert float back to short for SPI output | 615 // Convert float back to short for SPI output |
597 for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { | 616 for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { |
602 } | 621 } |
603 } | 622 } |
604 | 623 |
605 if(digital_enabled) { // keep track of past digital values | 624 if(digital_enabled) { // keep track of past digital values |
606 for(unsigned int n = 0; n < context->digitalFrames; n++){ | 625 for(unsigned int n = 0; n < context->digitalFrames; n++){ |
607 lastDigitalBuffer[n] = context->digital[n]; | 626 last_digital_buffer[n] = context->digital[n]; |
608 } | 627 } |
609 } | 628 } |
610 | 629 |
611 // Convert float back to short for audio | 630 // Convert float back to short for audio |
612 // TODO: NEON | 631 // TODO: NEON |
651 free(context->audioOut); | 670 free(context->audioOut); |
652 | 671 |
653 if(analog_enabled) { | 672 if(analog_enabled) { |
654 free(context->analogIn); | 673 free(context->analogIn); |
655 free(context->analogOut); | 674 free(context->analogOut); |
656 free(lastAnalogOutFrame); | 675 free(last_analog_out_frame); |
657 } | 676 } |
658 | 677 |
659 if(digital_enabled) { | 678 if(digital_enabled) { |
660 free(lastDigitalBuffer); | 679 free(last_digital_buffer); |
661 } | 680 } |
662 | 681 |
663 context->audioIn = context->audioOut = 0; | 682 context->audioIn = context->audioOut = 0; |
664 context->analogIn = context->analogOut = 0; | 683 context->analogIn = context->analogOut = 0; |
665 context->digital = 0; | 684 context->digital = 0; |