Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 21 of 21

Thread: problem with memcpy (p, b, 128)?

  1. #1
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58

    problem with memcpy (p, b, 128)? Queue.playBuffer()?

    Hello everyone!
    I need your help! I am using Teensy3.2
    I am trying to analyze a low frequency signal and therefore for communication
    with the AudioAnalyzeFFT1024 object, I use the AudioPlayQueue object.
    My problem with initializing pointer variables and calling functions
    Queue.getBuffer () memcpy (p, b, 128) Queue.playBuffer ()

    Code:
    here are the code fragments that relate to the problem
    AudioPlayQueue Queue; // xy = 266.286
    AudioAnalyzeFFT1024 fft; // xy = 458.286
    AudioConnection patchCord1 (Queue, fft);
    
    #define BUFFER_SIZE 128
    unsigned short int buffer_0 [BUFFER_SIZE];
    uint16_t buffer_0_count = 0;
    
    void setup ()
    {
      AudioMemory (20);
      
      
    void timer0_callback (void)
    {
      adc-> adc0-> startSingleRead (A2);
      digitalWrite (22,! digitalRead (22)); // for test
    }
    
    void adc0_isr ()
    {
      buffer_0 [buffer_0_count] = adc-> adc0-> readSingle ();
      buffer_0_count ++;
      if (buffer_0_count> = 128) // ned 0-128
      {
        buffer_0_count = 0;
       int16_t * b = buffer_0;
       int16_t * p = Queue.getBuffer ();
        memcpy (p, b, 128); // is there a problem here?
        Queue.playBuffer (); // or maybe here?
      }
     digitalWrite (23,! digitalRead (23)); // for test
    }
    this error message
    ...... rRead.ino: 113: 16: warning: invalid conversion from 'short unsigned int *' to 'int16_t * {aka short int *}' [-fpermissive]
    Last edited by Lukashuk; 04-26-2021 at 03:46 PM.

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,612
    Arduino should show you the line?
    I'd guess it's here :
    int16_t * b = buffer_0; (because buffer 0 is "unsigned short int")

    But I'm not a compiler...
    That's why a complete program posted is more useful...

  3. #3
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    Code:
    #include <Wire.h>
    #include <SPI.h>
    #include "ILI9341_t3.h"
    #include "font_Arial.h"
    // For the Adafruit shield, these are the default.
    #define TFT_DC  9
    #define TFT_CS 10
    ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
    
    #include <Audio.h>
    
    // GUItool: begin automatically generated code
    //AudioInputAnalog         adc1; //xy=94,286 //if this is not inserted in the tool, it gives an error,
                                    // so I inserted and commented it, although it is possible 
                                    //to write everything with pens without a tool
    AudioPlayQueue           Queue;         //xy=266,286
    AudioAnalyzeFFT1024      fft;      //xy=458,286
    AudioConnection          patchCord1(Queue, fft);
    // GUItool: end automatically generated code
    
    #include <ADC.h>
    #include <IntervalTimer.h>
    //const int readPin1 = A2;
    const int readPeriod0 = 488; //
    ADC *adc = new ADC(); // adc object
    IntervalTimer timer0; // timer
    
    #define BUFFER_SIZE 128
    unsigned short int buffer_0[BUFFER_SIZE];
    uint16_t buffer_0_count = 0;
    
    void setup() 
    {
      AudioMemory(20);
       // adc->adc0->setReference (ADC_REFERENCE :: REF_3V3);//REF_3V3, REF_1V2, REF_EXT,
        adc->adc0->setAveraging(2); // 
        adc->adc0->setResolution(12); // 
        adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
        adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
    
    pinMode (22, OUTPUT); // 
    pinMode (23, OUTPUT); //
      tft.begin();
      tft.fillScreen(ILI9341_BLACK);
      tft.setRotation(3);
      tft.setTextSize(2);
      tft.setTextColor(ILI9341_RED);
      tft.setCursor(250, 200);
      tft.print("2 Gz");
      adc->adc0->enableInterrupts(adc0_isr);
      timer0.begin(timer0_callback, readPeriod0);
    }
    
    void loop() 
    {
      float f;
      int n;
      int i;
      int a;
      int b=0;
    int c =5;// display width of one sample
      if (fft.available())
      {    
        for (i=0; i<100; i++) // number of lines
        {
          f = fft.read(i);      
          //if ( g < f) g=f;    
          n = (int)(f*1000);
        
          for (a=0; a<(c-1); a++)
          {
            tft.drawLine(i+a+b, 240-n, i+a+b, 0, ILI9341_BLACK);// clearing the old line
            tft.drawLine(i+a+b, 240-n , i+a+b, 240, ILI9341_GREEN);//draw a line one pixel wide
          }
         b +=c;           
        }    
      }  
    }
    
    void timer0_callback(void)// We get here to start a new transformation
    {
      adc->adc0->startSingleRead(A2);  
      digitalWrite (22, !digitalRead(22));
    }
    
    void adc0_isr() //we get here as soon as the conversion of the ADC is over
    {
      buffer_0[buffer_0_count] = adc->adc0->readSingle();
      buffer_0_count++;
      if (buffer_0_count >= 128) //ned 0-128
      {
        buffer_0_count = 0;
        unsigned short int *b = buffer_0; //
        unsigned short int *p = Queue.getBuffer();   
        memcpy(p, b, 128); 
        Queue.playBuffer();    
      }
     digitalWrite (23, !digitalRead(23));
    }
    compiler message :
    Read_a.ino:96:44: warning: invalid conversion from 'int16_t* {aka short int*}' to 'short unsigned int*' [-fpermissive]
    sage

  4. #4
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    I changed
    short int buffer_0[BUFFER_SIZE];
    short int buffer_0_count = 0;
    now the compiler gave no errors but still doesn't work
    control digitalWrite (23,! digitalRead (23)); reports a problem

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,612
    YOu didn't say it does not work.. you mentioned a warning only..
    What does not work?

    note, memcpy copies 128 BYTES... for (u)int16 you may want 256?
    Queue.getBuffer(); may return NULL I think..

  6. #6
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    doesn't seem to work
    // Queue.playBuffer ();
    if you comment it out, the rest of it works
    Serial.print ((int) b, HEX); Serial.print (""); Serial.println ((int) p, HEX);

    result of receiving addresses
    1FFFBE5C 1FFF9550
    apparently the address "b' is not aligned. how to do it?

    from description AudioPlayQueue
    getBuffer();
    Returns a pointer to an array of 128 int16.

  7. #7
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    memcpy copies a number of bytes. The 128 int16 pointed to by getBuffer, is 256 bytes.

    You will probably have problems playing back the ADC data because the ADC only returns positive integers whereas the audio board works with signed 16-bit integers which are centred around zero.
    With a resolution of 12 bits, try this:
    Code:
      buffer_0[buffer_0_count] = adc->adc0->readSingle() - 2048;
    To allow this, you also have to change the declaration of buffer_0 to:
    Code:
    short int buffer_0[BUFFER_SIZE];
    and these:
    Code:
        short int *b = buffer_0; //
        short int *p = Queue.getBuffer();
    Pete

  8. #8
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,612
    Quote Originally Posted by Lukashuk View Post
    from description AudioPlayQueue
    getBuffer();
    Returns a pointer to an array of 128 int16.
    If you quote it, quote all...
    Code:
    Returns a pointer to an array of 128 int16. This buffer is within the audio library memory pool, providing the most efficient way to input data to the audio system. 
    The buffer is likely to be populated by previously used data, so the entire 128 words should be written before calling playBuffer(). Only a single buffer should be requested at a time.
     This function may return NULL if no memory is available.
    :-)

    So, it's needed to add a null pointer check.

  9. #9
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    changed the code adding control
    void setup ()
    {
    AudioMemory (20);
    p = Queue.getBuffer ();
    if (p == NULL)
    { while (1);} // ERROR
    and sorted all the code a little, now the compiler does not give errors and warnings, but the whole code continues to fail - it does not enter
    if (fft.available ())
    { digitalWrite (23,! digitalRead (23)); // for control yellow oscilloscope beam

    Code:
    #include <Wire.h>
    #include <SPI.h>
    #include "ILI9341_t3.h"
    #include "font_Arial.h"
    // For the Adafruit shield, these are the default.
    #define TFT_DC  9
    #define TFT_CS 10
    ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
    
    #include <Audio.h>
    
    // GUItool: begin automatically generated code
    //AudioInputAnalog         adc1; //xy=94,286 //if this is not inserted in the tool, it gives an error,
                                    // so I inserted and commented it, although it is possible 
                                    //to write everything with pens without a tool
    AudioPlayQueue           Queue;         //xy=266,286
    AudioAnalyzeFFT1024      fft;      //xy=458,286
    AudioConnection          patchCord1(Queue, fft);
    // GUItool: end automatically generated code
    
    #include <ADC.h>
    #include <IntervalTimer.h>
    //const int readPin1 = A2;
    const int readPeriod0 = 488; //
    ADC *adc = new ADC(); // adc object
    IntervalTimer timer0; // timer
    
    #define BUFFER_SIZE 128
    int16_t buffer_0[BUFFER_SIZE];
    int16_t buffer_0_count = 0;
    int16_t *b = buffer_0;
    int16_t *p;// = Queue.getBuffer();
    void setup() 
    {
      AudioMemory(20);
      p = Queue.getBuffer();
      if (p == NULL)
      {
        while(1);// ERROR
      }
       // adc->adc0->setReference (ADC_REFERENCE :: REF_3V3);//REF_3V3, REF_1V2, REF_EXT,
        adc->adc0->setAveraging(2); // 
        adc->adc0->setResolution(12); // 
        adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
        adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
    
       pinMode (22, OUTPUT); // 
       pinMode (23, OUTPUT); //
      tft.begin();
      tft.fillScreen(ILI9341_BLACK);
      tft.setRotation(3);
      tft.setTextSize(2);
      tft.setTextColor(ILI9341_RED);
      tft.setCursor(250, 200);
      tft.print("2 Gz");
      adc->adc0->enableInterrupts(adc0_isr);
      timer0.begin(timer0_callback, readPeriod0);
    }
    
    void loop() 
    {
      float f;
      int n;
      int i;
      int a;
      int b=0;
    int c =5;// display width of one sample
      if (fft.available())
      { 
        digitalWrite (23, !digitalRead(23));//for control  yellow oscilloscope beam 
        for (i=0; i<100; i++) // number of lines
        {
          f = fft.read(i);      
          //if ( g < f) g=f;    
          n = (int)(f*1000);
        
          for (a=0; a<(c-1); a++)
          {
            tft.drawLine(i+a+b, 240-n, i+a+b, 0, ILI9341_BLACK);// clearing the old line
            tft.drawLine(i+a+b, 240-n , i+a+b, 240, ILI9341_GREEN);//draw a line one pixel wide
          }
         b +=c;           
        }    
      }  
    }
    
    void timer0_callback(void)// We get here to start a new transformation
    {
      adc->adc0->startSingleRead(A2);  
     // digitalWrite (22, !digitalRead(22));// for control oscilloscope blue beam
    }
    
    void adc0_isr() //we get here as soon as the conversion of the ADC is over
    { 
      buffer_0[buffer_0_count] = adc->adc0->readSingle();
      buffer_0_count++;
      if (buffer_0_count >= BUFFER_SIZE) //ned 0-128
      {
        buffer_0_count = 0;    
       memcpy(p, b, BUFFER_SIZE); 
       Queue.playBuffer(); 
      }
     //digitalWrite (23, !digitalRead(23));//for control yellow oscilloscope beam
     digitalWrite (22, !digitalRead(22));// for control oscilloscope blue beam
    }

  10. #10
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    You have (at least) two problems.
    You are still copying only 128 of the 256 bytes in the audio buffer. Try this:
    Code:
        memcpy(p, b, BUFFER_SIZE*2);
    or a more robust way of doing this is:
    Code:
        memcpy(p, b, BUFFER_SIZE*sizeof(buffer_0[0]);
    The bigger problem is that you only call getBuffer once. The way the audio library handles these buffers is that playBuffer uses the buffer allocated by the most recent getBuffer. If you only call getBuffer once, playBuffer will play that one buffer and then do nothing after that which is why fft.available is always zero.
    One way to fix this is to add
    Code:
        p = Queue.getBuffer();
    immediately after the call to playBuffer.

    Pete

  11. #11
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    i made changes,
    // memcpy (p, b, BUFFER_SIZE);
    // memcpy (p, b, BUFFER_SIZE * 2);
    memcpy (p, b, BUFFER_SIZE * sizeof (buffer_0 [0]));
    Queue.playBuffer ();
    p = Queue.getBuffer ();
    but the effect hasn't changed -
    Don `t come in
    if (fft.available ())
    {
    digitalWrite (23,! digitalRead (23)); // for control yellow oscilloscope beam

  12. #12
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    Does this one digitalWrite (22, !digitalRead(22)) in adc0_isr indicate that the interrupt is occurring at the correct rate?

    Pete

  13. #13
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    Yes sir! I cannot insert a photo, but the period of this signal is similar to 488 μS

  14. #14
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    it turned out to insert a photo
    Click image for larger version. 

Name:	IRQ.png 
Views:	12 
Size:	143.8 KB 
ID:	24595

  15. #15
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    I also found out that the Queue.getBuffer () function produces new addresses each time and the number of them is the same as defined in AudioMemory (20).
    something is wrong? still doesn't work, doesn't go into if (fft.available ())

  16. #16
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    I think you may need to add this after the audioConnection statement.
    Code:
    AudioControlSGTL5000     sgtl5000;
    and in setup() add this:
    Code:
      sgtl5000.enable();
    Without it there's nothing to cause the audio library to call the update() function in the PlayQueue and FFT1024 objects .
    If that gets it going, you may have another problem because you are sampling data at 2048Hz whereas the audio library samples at 44.1kHz.
    But try setting up the sgtl5000 first and let's see what happens.

    Pete

  17. #17
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    I added as you said, although I do not have an audio shield. SGTL5000, it didn't help.
    I also found out interrupt adc0_isr () triggers = BUFFER_SIZE * AudioMemory (20) and does not go there anymore

  18. #18
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    OK, remove the sgtl. I'm stuck. I'll keep pondering the problem.

    Pete

  19. #19
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    I've been playing with your code on a T3.2 and it looks like it's not the output that's needed, it's the input.
    Add this before the declaration of AudioPlayQueue:
    Code:
    AudioInputI2S            i2s;
    Pete

  20. #20
    Member
    Join Date
    Oct 2017
    Location
    Ukraine
    Posts
    58
    Yes! it worked. Thank you!

  21. #21
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,691
    Excellent

    Pete

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •