comparison core/PRU.cpp @ 23:182ae9367104 matrix_gpio

- persistency: the last frame of each digital and analogOut buffers is used to initialize all the frames in the next buffer. This means that once a value is set, the pin will hold the value until you change it - AnalogXyz macros have been renamed to analogXyz - the short option -P has been removed. The long option --pru-file has to be used instead
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 05 May 2015 17:28:00 +0100
parents c98863e63174
children a9af130097e8
comparison
equal deleted inserted replaced
22:fbfeb5895efd 23:182ae9367104
430 void PRU::loop() 430 void PRU::loop()
431 { 431 {
432 // Polling interval is 1/4 of the period 432 // Polling interval is 1/4 of the period
433 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;
434 float *audioInBuffer, *audioOutBuffer; 434 float *audioInBuffer, *audioOutBuffer;
435 float *analogInBuffer, *analogOutBuffer; 435 float *analogInBuffer, *analogOutBuffer, *lastAnalogOutFrame;
436 uint32_t *digitalBuffer0, *digitalBuffer1, *digitalBufferTemp; 436 uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer;
437 437
438 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 438 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
439 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 439 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
440 analogInBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float)); 440 analogInBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
441 analogOutBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float)); 441 analogOutBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
442 lastAnalogOutFrame = (float *)malloc(spi_num_channels * sizeof(float));
442 digitalBuffer0 = pru_buffer_digital; 443 digitalBuffer0 = pru_buffer_digital;
443 digitalBuffer1 = pru_buffer_digital+MEM_DIGITAL_BUFFER1_OFFSET/sizeof(uint32_t); 444 digitalBuffer1 = pru_buffer_digital+MEM_DIGITAL_BUFFER1_OFFSET/sizeof(uint32_t);
444 digital_buffer_frames = digital_enabled ? audio_buffer_frames : 0; //TODO: find a more elegant solution for when the digital is disabled e.g.: 445 digital_buffer_frames = digital_enabled ? audio_buffer_frames : 0; //TODO: find a more elegant solution for when the digital is disabled e.g.:
445 // - embed in the digitalWrite/Read macros a check whether digital is enabled 446 // - embed in the digitalWrite/Read macros a check whether digital is enabled
446 // - allocate some memory in ARM just to allow render() to run regardless. 447 // - allocate some memory in ARM just to allow render() to run regardless.
447 // in this case it can be digitalBuffer0 == digitalBuffer1 448 // in this case it can be digitalBuffer0 == digitalBuffer1
448 printf("digital_buffer_frames: %d;\n",digital_buffer_frames); 449 printf("digital_buffer_frames: %d;\n",digital_buffer_frames);
449 digitalBufferTemp = (uint32_t *)malloc(digital_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states 450 lastDigitalBuffer = (uint32_t *)malloc(digital_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states
450 if(audioInBuffer == 0 || audioOutBuffer == 0) { 451 if(audioInBuffer == 0 || audioOutBuffer == 0) {
451 rt_printf("Error: couldn't allocate audio buffers\n"); 452 rt_printf("Error: couldn't allocate audio buffers\n");
452 return; 453 return;
453 } 454 }
454 if(analogInBuffer == 0 || analogOutBuffer == 0) { 455 if(analogInBuffer == 0 || analogOutBuffer == 0 || lastAnalogOutFrame == 0) {
455 rt_printf("Error: couldn't allocate analog buffers\n"); 456 rt_printf("Error: couldn't allocate analog buffers\n");
456 return; 457 return;
457 } 458 }
458 if(digitalBufferTemp == 0) { 459 if(lastDigitalBuffer == 0) {
459 rt_printf("Error: couldn't allocate digital buffers\n"); 460 rt_printf("Error: couldn't allocate digital buffers\n");
460 return; 461 return;
461 } 462 }
462 463
463 while(!gShouldStop) { 464 while(!gShouldStop) {
464 // Wait for PRU to move to buffer 1 465 // Wait for PRU to move to buffer 1
465 while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) { 466 while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) {
466 rt_task_sleep(sleepTime); 467 rt_task_sleep(sleepTime);
479 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) 480 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++)
480 audioInBuffer[n] = (float)pru_buffer_audio_adc[n] / 32768.0; 481 audioInBuffer[n] = (float)pru_buffer_audio_adc[n] / 32768.0;
481 if(spi_enabled) { 482 if(spi_enabled) {
482 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) 483 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++)
483 analogInBuffer[n] = (float)pru_buffer_spi_adc[n] / 65536.0; 484 analogInBuffer[n] = (float)pru_buffer_spi_adc[n] / 65536.0;
484 //use past digital values to initialize the array properly: 485 //initialize the output buffer with the values that were in the last frame of the previous output
485 //- pins previously set as outputs will keep their previously set output value, 486 for(int n = 0; n < spi_num_channels; n++){
487 for(unsigned int j = 0; j < spi_buffer_frames; j++){
488 analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
489 }
490 }
491 //use past digital values to initialize the array properly.
492 //For each frame:
493 //- pins previously set as outputs will keep the output value they had in the last frame of the previous buffer,
486 //- pins previously set as inputs will carry the newly read input value 494 //- pins previously set as inputs will carry the newly read input value
487 if(digital_enabled){ 495 if(digital_enabled){
488 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 496 for(unsigned int n = 0; n < digital_buffer_frames; n++){
489 uint16_t inputs=digitalBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs 497 uint16_t inputs=lastDigitalBuffer[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
490 // printf("inputs: 0x%x\n",inputs); 498 // printf("inputs: 0x%x\n",inputs);
491 uint16_t outputs=~inputs; //half-word has 1 for outputs and 0 for inputs; 499 uint16_t outputs=~inputs; //half-word has 1 for outputs and 0 for inputs;
492 digitalBuffer0[n]=(digitalBufferTemp[n]&(outputs<<16))| //keep output values set in previous digitalBuffer1[n] 500 digitalBuffer0[n]=(lastDigitalBuffer[digital_buffer_frames-1]&(outputs<<16))| //keep output values set in the last frame of the previous buffer
493 (digitalBuffer0[n]&(inputs<<16)) | //inputs from current digitalBuffer0[n]; 501 (digitalBuffer0[n]&(inputs<<16)) | //inputs from current digitalBuffer0[n];
494 (digitalBufferTemp[n]&(inputs)); //keep pin configuration from previous digitalBuffer1[n] 502 (lastDigitalBuffer[n]&(inputs)); //keep pin configuration from previous digitalBuffer1[n]
495 // digitalBuffer0[n]=digitalBufferTemp[n]; //ignores inputs 503 // digitalBuffer0[n]=digitalBufferTemp[n]; //ignores inputs
496 } 504 }
497 } 505 }
498 render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, 506 render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
499 analogInBuffer, analogOutBuffer, digitalBuffer0); 507 analogInBuffer, analogOutBuffer, digitalBuffer0);
508 //remember the content of the lastAnalogOutFrame
509 for(int n = 0; n < spi_num_channels; n++){
510 lastAnalogOutFrame[n] = analogOutBuffer[spi_buffer_frames*(spi_buffer_frames-1) + n];
511 }
500 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) { 512 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
501 int out = analogOutBuffer[n] * 65536.0; 513 int out = analogOutBuffer[n] * 65536.0;
502 if(out < 0) out = 0; 514 if(out < 0) out = 0;
503 else if(out > 65535) out = 65535; 515 else if(out > 65535) out = 65535;
504 pru_buffer_spi_dac[n] = (uint16_t)out; 516 pru_buffer_spi_dac[n] = (uint16_t)out;
505 } 517 }
506 if(digital_enabled){ // keep track of past digital values 518 if(digital_enabled){ // keep track of past digital values
507 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 519 for(unsigned int n = 0; n < digital_buffer_frames; n++){
508 digitalBufferTemp[n]=digitalBuffer0[n]; 520 lastDigitalBuffer[n]=digitalBuffer0[n];
509 } 521 }
510 } 522 }
511 } 523 }
512 else 524 else
513 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass digitalBuffer, just it is unused 525 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass digitalBuffer, just it is unused
542 // Convert short (16-bit) samples to float 554 // Convert short (16-bit) samples to float
543 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) 555 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++)
544 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0; 556 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0;
545 557
546 if(spi_enabled) { 558 if(spi_enabled) {
547 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) 559 //convert input values TODO: move to PRU
560 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++){
548 analogInBuffer[n] = (float)pru_buffer_spi_adc[n + spi_buffer_frames * spi_num_channels] / 65536.0; 561 analogInBuffer[n] = (float)pru_buffer_spi_adc[n + spi_buffer_frames * spi_num_channels] / 65536.0;
549 562 }
550 //use past digital values to initialize the array properly: 563 //initialize the output buffer with the values that were in the last frame of the previous output
551 //- pins previously set as outputs will keep their previously set output value, 564 for(int n = 0; n < spi_num_channels; n++){
552 //- pins previously set as inputs will carry the newly read input value 565 for(unsigned int j = 0; j < spi_buffer_frames; j++){
566 analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
567 }
568 }
553 if(digital_enabled){ 569 if(digital_enabled){
554 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 570 for(unsigned int n = 0; n < digital_buffer_frames; n++){
555 uint16_t inputs=digitalBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs 571 uint16_t inputs=lastDigitalBuffer[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; 572 uint16_t outputs=~inputs; //half-word has 1 for outputs and one for inputs;
557 digitalBuffer1[n]=(digitalBufferTemp[n]&(outputs<<16))| //keep output values set in previous digitalBuffer1[n] 573 digitalBuffer1[n]=(lastDigitalBuffer[digital_buffer_frames-1]&(outputs<<16))| //keep output values set in the last frame of the previous buffer
558 (digitalBuffer1[n]&(inputs<<16)) | //inputs from current digitalBuffer1[n]; 574 (digitalBuffer1[n]&(inputs<<16)) | //inputs from current digitalBuffer1[n];
559 (digitalBufferTemp[n]&(inputs)); //keep pin configuration from previous digitalBuffer1[n] 575 (lastDigitalBuffer[n]&(inputs)); //keep pin configuration from previous digitalBuffer1[n]
560 // digitalBuffer1[n]=digitalBufferTemp[n]; //ignores inputs 576 // digitalBuffer1[n]=digitalBufferTemp[n]; //ignores inputs
561 } 577 }
562 } 578 }
563 render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, 579 render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
564 analogInBuffer, analogOutBuffer, digitalBuffer1); 580 analogInBuffer, analogOutBuffer, digitalBuffer1);
581 //remember the content of the lastAnalogOutFrame
582 for(int n = 0; n < spi_num_channels; n++){
583 lastAnalogOutFrame[n] = analogOutBuffer[spi_buffer_frames*(spi_buffer_frames-1) + n];
584 }
585
565 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) { 586 for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
566 int out = analogOutBuffer[n] * 65536.0; 587 int out = analogOutBuffer[n] * 65536.0;
567 if(out < 0) out = 0; 588 if(out < 0) out = 0;
568 else if(out > 65535) out = 65535; 589 else if(out > 65535) out = 65535;
569 pru_buffer_spi_dac[n + spi_buffer_frames * spi_num_channels] = (uint16_t)out; 590 pru_buffer_spi_dac[n + spi_buffer_frames * spi_num_channels] = (uint16_t)out;
570 } 591 }
571 if(digital_enabled){ // keep track of past digital values 592 if(digital_enabled){ // keep track of past digital values
572 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 593 for(unsigned int n = 0; n < digital_buffer_frames; n++){
573 digitalBufferTemp[n]=digitalBuffer1[n]; 594 lastDigitalBuffer[n]=digitalBuffer1[n];
574 } 595 }
575 } 596 }
576 } 597 }
577 else 598 else
578 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass digitalBuffer, just it is unused 599 render(0, 0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0, 0); // we still pass digitalBuffer, just it is unused
596 617
597 free(analogOutBuffer); 618 free(analogOutBuffer);
598 free(audioInBuffer); 619 free(audioInBuffer);
599 free(audioOutBuffer); 620 free(audioOutBuffer);
600 free(analogInBuffer); 621 free(analogInBuffer);
601 free(digitalBufferTemp); 622 free(lastAnalogOutFrame);
623 free(lastDigitalBuffer);
602 } 624 }
603 625
604 // Wait for an interrupt from the PRU indicate it is finished 626 // Wait for an interrupt from the PRU indicate it is finished
605 void PRU::waitForFinish() 627 void PRU::waitForFinish()
606 { 628 {