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;