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