Mercurial > hg > beaglert
comparison core/PRU.cpp @ 528:5c8f46fcd4d0 API-update
Updated BelaContext to use separate values for in/ou channels
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Thu, 23 Jun 2016 18:17:35 +0100 |
parents | 3a28a4eb948d |
children |
comparison
equal
deleted
inserted
replaced
527:1c68ad13bbe4 | 528:5c8f46fcd4d0 |
---|---|
332 if(analog_enabled) { | 332 if(analog_enabled) { |
333 prussdrv_map_prumem (pru_number == 0 ? PRUSS0_PRU0_DATARAM : PRUSS0_PRU1_DATARAM, (void **)&pruMem); | 333 prussdrv_map_prumem (pru_number == 0 ? PRUSS0_PRU0_DATARAM : PRUSS0_PRU1_DATARAM, (void **)&pruMem); |
334 pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)]; | 334 pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)]; |
335 | 335 |
336 /* ADC memory starts after N(ch)*2(buffers)*bufsize samples */ | 336 /* ADC memory starts after N(ch)*2(buffers)*bufsize samples */ |
337 pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * context->analogChannels * context->analogFrames]; | 337 pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * context->analogInChannels * context->analogFrames]; |
338 } | 338 } |
339 else { | 339 else { |
340 pru_buffer_spi_dac = pru_buffer_spi_adc = 0; | 340 pru_buffer_spi_dac = pru_buffer_spi_adc = 0; |
341 } | 341 } |
342 | 342 |
374 pru_buffer_comm[PRU_LED_ADDRESS] = 0; | 374 pru_buffer_comm[PRU_LED_ADDRESS] = 0; |
375 pru_buffer_comm[PRU_LED_PIN_MASK] = 0; | 375 pru_buffer_comm[PRU_LED_PIN_MASK] = 0; |
376 } | 376 } |
377 if(analog_enabled) { | 377 if(analog_enabled) { |
378 pru_buffer_comm[PRU_USE_SPI] = 1; | 378 pru_buffer_comm[PRU_USE_SPI] = 1; |
379 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = context->analogChannels; | 379 if(context->analogInChannels != context->analogOutChannels){ |
380 printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n"); | |
381 return 1; | |
382 } | |
383 unsigned int analogChannels = context->analogInChannels; | |
384 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = analogChannels; | |
380 } | 385 } |
381 else { | 386 else { |
382 pru_buffer_comm[PRU_USE_SPI] = 0; | 387 pru_buffer_comm[PRU_USE_SPI] = 0; |
383 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0; | 388 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0; |
384 } | 389 } |
458 if(last_analog_out_frame == 0) { | 463 if(last_analog_out_frame == 0) { |
459 rt_printf("Error: couldn't allocate analog persistence buffer\n"); | 464 rt_printf("Error: couldn't allocate analog persistence buffer\n"); |
460 return 1; | 465 return 1; |
461 } | 466 } |
462 #else | 467 #else |
463 context->analogIn = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | 468 context->analogIn = (float *)malloc(context->analogInChannels * context->analogFrames * sizeof(float)); |
464 context->analogOut = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); | 469 context->analogOut = (float *)malloc(context->analogOutChannels * context->analogFrames * sizeof(float)); |
465 last_analog_out_frame = (float *)malloc(context->analogChannels * sizeof(float)); | 470 last_analog_out_frame = (float *)malloc(context->analogOutChannels * sizeof(float)); |
466 | 471 |
467 if(context->analogIn == 0 || context->analogOut == 0 || last_analog_out_frame == 0) { | 472 if(context->analogIn == 0 || context->analogOut == 0 || last_analog_out_frame == 0) { |
468 rt_printf("Error: couldn't allocate analog buffers\n"); | 473 rt_printf("Error: couldn't allocate analog buffers\n"); |
469 return 1; | 474 return 1; |
470 } | 475 } |
471 #endif | 476 #endif |
472 | 477 |
473 memset(last_analog_out_frame, 0, context->analogChannels * sizeof(float)); | 478 memset(last_analog_out_frame, 0, context->analogOutChannels * sizeof(float)); |
474 } | 479 } |
475 | 480 |
476 // Allocate digital buffers | 481 // Allocate digital buffers |
477 digital_buffer0 = pru_buffer_digital; | 482 digital_buffer0 = pru_buffer_digital; |
478 digital_buffer1 = pru_buffer_digital + MEM_DIGITAL_BUFFER1_OFFSET / sizeof(uint32_t); | 483 digital_buffer1 = pru_buffer_digital + MEM_DIGITAL_BUFFER1_OFFSET / sizeof(uint32_t); |
526 { | 531 { |
527 #ifdef BELA_USE_XENOMAI_INTERRUPTS | 532 #ifdef BELA_USE_XENOMAI_INTERRUPTS |
528 RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period | 533 RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period |
529 #else | 534 #else |
530 // Polling interval is 1/4 of the period | 535 // Polling interval is 1/4 of the period |
531 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; | 536 if(context->analogInChannels != context->analogOutChannels){ |
537 printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n"); | |
538 return; | |
539 } | |
540 unsigned int analogChannels = context->analogInChannels; | |
541 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (analogChannels / 2) * context->analogFrames / 4; | |
532 #endif | 542 #endif |
533 | 543 |
534 uint32_t pru_audio_offset, pru_spi_offset; | 544 uint32_t pru_audio_offset, pru_spi_offset; |
535 | 545 |
536 // Before starting, look at the last state of the analog and digital outputs which might | 546 // Before starting, look at the last state of the analog and digital outputs which might |
538 // directions and output values at something other than defaults. | 548 // directions and output values at something other than defaults. |
539 | 549 |
540 if(analog_enabled) { | 550 if(analog_enabled) { |
541 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { | 551 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { |
542 // Remember the content of the last_analog_out_frame | 552 // Remember the content of the last_analog_out_frame |
543 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ | 553 for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){ |
544 last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; | 554 last_analog_out_frame[ch] = context->analogOut[context->analogOutChannels * (context->analogFrames - 1) + ch]; |
545 } | 555 } |
546 } | 556 } |
547 } | 557 } |
548 | 558 |
549 if(digital_enabled) { | 559 if(digital_enabled) { |
603 if(digital_enabled) | 613 if(digital_enabled) |
604 context->digital = digital_buffer0; | 614 context->digital = digital_buffer0; |
605 } | 615 } |
606 else { | 616 else { |
607 // PRU is on buffer 0. We read and write to buffer 1 | 617 // PRU is on buffer 0. We read and write to buffer 1 |
608 pru_audio_offset = context->audioFrames * 2; | 618 if(context->audioInChannels != context->audioOutChannels){ |
609 pru_spi_offset = context->analogFrames * context->analogChannels; | 619 printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n"); |
620 return; | |
621 } | |
622 unsigned int audioChannels = context->audioInChannels; | |
623 pru_audio_offset = context->audioFrames * audioChannels; | |
624 if(context->analogInChannels != context->analogOutChannels){ | |
625 printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n"); | |
626 return; | |
627 } | |
628 unsigned int analogChannels = context->analogInChannels; | |
629 pru_spi_offset = context->analogFrames * analogChannels; | |
610 if(digital_enabled) | 630 if(digital_enabled) |
611 context->digital = digital_buffer1; | 631 context->digital = digital_buffer1; |
612 } | 632 } |
613 | 633 |
614 // FIXME: some sort of margin is needed here to prevent the audio | 634 // FIXME: some sort of margin is needed here to prevent the audio |
642 | 662 |
643 #ifdef USE_NEON_FORMAT_CONVERSION | 663 #ifdef USE_NEON_FORMAT_CONVERSION |
644 int16_to_float_analog(context->analogChannels * context->analogFrames, | 664 int16_to_float_analog(context->analogChannels * context->analogFrames, |
645 &pru_buffer_spi_adc[pru_spi_offset], context->analogIn); | 665 &pru_buffer_spi_adc[pru_spi_offset], context->analogIn); |
646 #else | 666 #else |
647 for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { | 667 for(unsigned int n = 0; n < context->analogInChannels * context->analogFrames; n++) { |
648 context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0f; | 668 context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0f; |
649 } | 669 } |
650 #endif | 670 #endif |
651 | 671 |
652 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { | 672 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { |
653 // Initialize the output buffer with the values that were in the last frame of the previous output | 673 // Initialize the output buffer with the values that were in the last frame of the previous output |
654 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ | 674 for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){ |
655 for(unsigned int n = 0; n < context->analogFrames; n++){ | 675 for(unsigned int n = 0; n < context->analogFrames; n++){ |
656 context->analogOut[n * context->analogChannels + ch] = last_analog_out_frame[ch]; | 676 context->analogOut[n * context->analogOutChannels + ch] = last_analog_out_frame[ch]; |
657 } | 677 } |
658 } | 678 } |
659 } | 679 } |
660 else { | 680 else { |
661 // Outputs are 0 unless set otherwise | 681 // Outputs are 0 unless set otherwise |
662 memset(context->analogOut, 0, context->analogChannels * context->analogFrames * sizeof(float)); | 682 memset(context->analogOut, 0, context->analogOutChannels * context->analogFrames * sizeof(float)); |
663 } | 683 } |
664 } | 684 } |
665 | 685 |
666 if(digital_enabled){ | 686 if(digital_enabled){ |
667 // Use past digital values to initialize the array properly. | 687 // Use past digital values to initialize the array properly. |
686 // *********************** | 706 // *********************** |
687 | 707 |
688 if(analog_enabled) { | 708 if(analog_enabled) { |
689 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { | 709 if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) { |
690 // Remember the content of the last_analog_out_frame | 710 // Remember the content of the last_analog_out_frame |
691 for(unsigned int ch = 0; ch < context->analogChannels; ch++){ | 711 for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){ |
692 last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; | 712 last_analog_out_frame[ch] = context->analogOut[context->analogOutChannels * (context->analogFrames - 1) + ch]; |
693 } | 713 } |
694 } | 714 } |
695 | 715 |
696 // Convert float back to short for SPI output | 716 // Convert float back to short for SPI output |
697 #ifdef USE_NEON_FORMAT_CONVERSION | 717 #ifdef USE_NEON_FORMAT_CONVERSION |
698 float_to_int16_analog(context->analogChannels * context->analogFrames, | 718 float_to_int16_analog(context->analogChannels * context->analogFrames, |
699 context->analogOut, (uint16_t*)&pru_buffer_spi_dac[pru_spi_offset]); | 719 context->analogOut, (uint16_t*)&pru_buffer_spi_dac[pru_spi_offset]); |
700 #else | 720 #else |
701 for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { | 721 for(unsigned int n = 0; n < context->analogOutChannels * context->analogFrames; n++) { |
702 int out = context->analogOut[n] * 65536.0f; | 722 int out = context->analogOut[n] * 65536.0f; |
703 if(out < 0) out = 0; | 723 if(out < 0) out = 0; |
704 else if(out > 65535) out = 65535; | 724 else if(out > 65535) out = 65535; |
705 pru_buffer_spi_dac[n + pru_spi_offset] = (uint16_t)out; | 725 pru_buffer_spi_dac[n + pru_spi_offset] = (uint16_t)out; |
706 } | 726 } |
715 | 735 |
716 // Convert float back to short for audio | 736 // Convert float back to short for audio |
717 #ifdef USE_NEON_FORMAT_CONVERSION | 737 #ifdef USE_NEON_FORMAT_CONVERSION |
718 float_to_int16_audio(2 * context->audioFrames, context->audioOut, &pru_buffer_audio_dac[pru_audio_offset]); | 738 float_to_int16_audio(2 * context->audioFrames, context->audioOut, &pru_buffer_audio_dac[pru_audio_offset]); |
719 #else | 739 #else |
720 for(unsigned int n = 0; n < 2 * context->audioFrames; n++) { | 740 for(unsigned int n = 0; n < context->audioOutChannels * context->audioFrames; n++) { |
721 int out = context->audioOut[n] * 32768.0f; | 741 int out = context->audioOut[n] * 32768.0f; |
722 if(out < -32768) out = -32768; | 742 if(out < -32768) out = -32768; |
723 else if(out > 32767) out = 32767; | 743 else if(out > 32767) out = 32767; |
724 pru_buffer_audio_dac[n + pru_audio_offset] = (int16_t)out; | 744 pru_buffer_audio_dac[n + pru_audio_offset] = (int16_t)out; |
725 } | 745 } |
733 xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK; | 753 xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK; |
734 } | 754 } |
735 | 755 |
736 Bela_autoScheduleAuxiliaryTasks(); | 756 Bela_autoScheduleAuxiliaryTasks(); |
737 | 757 |
738 // FIXME: TESTING!! | |
739 // if(testCount > 100000) | |
740 // break; | |
741 } | 758 } |
742 | 759 |
743 #ifdef BELA_USE_XENOMAI_INTERRUPTS | 760 #ifdef BELA_USE_XENOMAI_INTERRUPTS |
744 // Turn off the interrupt for the PRU if it isn't already off | 761 // Turn off the interrupt for the PRU if it isn't already off |
745 rt_intr_disable(pru_interrupt); | 762 rt_intr_disable(pru_interrupt); |
746 #endif | 763 #endif |
747 | |
748 // FIXME: TESTING | |
749 // RTIME endTime = rt_timer_read(); | |
750 // RTIME diffTime = endTime - startTime; | |
751 // rt_printf("%d blocks elapsed in %f seconds, %f Hz block rate\n", testCount, ((float)diffTime / 1.0e9), (float)testCount / ((float)diffTime / 1.0e9)); | |
752 | 764 |
753 // Tell PRU to stop | 765 // Tell PRU to stop |
754 pru_buffer_comm[PRU_SHOULD_STOP] = 1; | 766 pru_buffer_comm[PRU_SHOULD_STOP] = 1; |
755 | 767 |
756 // Wait two buffer lengths for the PRU to finish | 768 // Wait two buffer lengths for the PRU to finish |