problem with memcpy (p, b, 128)?

Lukashuk

Well-known member
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:
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...
 
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
 
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
 
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..
 
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.
 
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
 
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 [COLOR=#ff0000]int16[/COLOR]. 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[COLOR=#ff0000] words[/COLOR] should be written before calling playBuffer(). Only a single buffer should be requested at a time.
 [COLOR=#ff0000]This function may return NULL if no memory is av[/COLOR][COLOR=#ff0000]ailable.[/COLOR]
:)

So, it's needed to add a null pointer check.
 
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
}
 
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
 
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
 
Does this one digitalWrite (22, !digitalRead(22)) in adc0_isr indicate that the interrupt is occurring at the correct rate?

Pete
 
it turned out to insert a photo
IRQ.png
 
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 ())
 
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
 
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
 
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
 
Back
Top