Compilation error but why?

D

DeletedUser

Guest
Hello
I already posted this but don't see it on the new post so I'll post again. I am trying to compile some code . I have the error msg:


c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: address 0x200842c0 of C:\Users\chris\AppData\Local\Temp\arduino_build_881826/evdist.ino.elf section `.bss' is not within region `DTCM'
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: address 0x200842c0 of C:\Users\chris\AppData\Local\Temp\arduino_build_881826/evdist.ino.elf section `.bss' is not within region `DTCM'
collect2.exe: error: ld returned 1 exit status


I don't know what this means.

This code is a homemade FFT with an order (ORD=32768). When I use ORD <= 16384 it works. Any ideas? Thanks.

Below is my code:

Code:
evdist.ino
-----------

//#define DEBUG
#include <LiquidCrystal_I2C.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=317.74999618530273,462.77778816223145
AudioRecordQueue         queue1;         //xy=565.75,439
AudioRecordQueue         queue2;         //xy=569.75,494
AudioPlayQueue           queue3;         //xy=760.25,442.7500305175781
AudioPlayQueue           queue4;         //xy=760.25,500.2500305175781
AudioOutputI2S           i2s1;           //xy=1067.7500190734863,459.27777194976807
AudioConnection          patchCord1(playSdWav1, 0, queue1, 0);
AudioConnection          patchCord2(playSdWav1, 1, queue2, 0);
AudioConnection          patchCord3(queue3, 0, i2s1, 0);
AudioConnection          patchCord4(queue4, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=313.75,572
// GUItool: end automatically generated code

#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

//-------------Button-----------------------------
int buttonPin=4;
int buttonNew=1;
int buttonOld=0;
unsigned long BounceStart=millis();
unsigned long BounceDelay=100UL;
//----------- Stream parameters ---
unsigned long startstream;
unsigned long startstreamdelay=1000UL;
unsigned long stopstream;
unsigned long stopstreamdelay=1000UL;
int streamstate=5;//idle
int iterL=0,iterR=0;
//----------Algorithm-----------------------------
#define ORD 32768
#define pi 3.14159265358979
#define Epsilon 1.e-10
#define fs 44100
#define sigthresh .1 //need at least -20dB THD
#define NUMFREQ 6
#include "windowcoefs.h" //chebwin 
float fftinL[2*ORD];
float fftinR[2*ORD];
float *fftoutL;
float *fftoutR;
float ThdL,ThdR;
int NumfreqL,NumfreqR;
//------LCD------------
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup(void)
{
  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP); 
  AudioMemory(64);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  
  lcd.init();                      // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  delay(500);
  lcd.home();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Push Button for"); 
  lcd.setCursor(0,1);
  lcd.print("thd analysis");  
}

void loop(void)
{
  if (chkButton())
  {
    playSdWav1.play("sine.wav");
    streamstate=0;
    startstream=millis();
  }
  stateAudio(); 
  if (streamstate==1)
  {
    queue1.begin();
    queue2.begin();
  }
  if (streamstate==2)
  {
    if (queue1.available() >= 1) //Left Channel
    {
      passthru(queue1.readBuffer(),queue3.getBuffer(),&iterL,fftinL);
      queue1.freeBuffer();
      queue3.playBuffer();
    }
    if (queue2.available() >= 1) //Right Channel
    {
      passthru(queue2.readBuffer(),queue4.getBuffer(),&iterR,fftinR);
      queue2.freeBuffer();
      queue4.playBuffer();
    }
  }
  if (streamstate==3)
  { 
    playSdWav1.stop();
    iterL=0;
    iterR=0;
  }
  if (streamstate==4)
  { 
#ifdef DEBUG
    Serial.println("----------- Left Channel Spectrum ---------------");
#endif
    lcd.clear();
    lcd.setCursor(0,0);
    FFTCALC(fftinL, fftoutL);
    if (FINDSPECTRUMS(fftinL,&NumfreqL,&ThdL))
    {
      lcd.print("NfL=");
      lcd.print(NumfreqL);
      lcd.print(" ThdL=");
      lcd.print(round(ThdL));
    }
    else lcd.print("FAIL ThdLcalc");
#ifdef DEBUG
    Serial.println("----------- Right Channel Spectrum ---------------");
#endif
    lcd.setCursor(0,1);
    FFTCALC(fftinR, fftoutR); 
    if (FINDSPECTRUMS(fftinR,&NumfreqR,&ThdR))
    {
      lcd.print("NfR=");
      lcd.print(NumfreqR);
      lcd.print(" ThdR=");
      lcd.print(round(ThdR));
    }
    else lcd.print("FAIL ThdRcalc");
    streamstate=5;
  }
}

void passthru(int16_t *inbuf,int16_t *outbuf,int *iter,float *fftin)
{
  int16_t *bp1,*bp2;
  int indx=*iter;
  bp1=inbuf;
  bp2=outbuf;
  for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) 
  {
    if (indx<ORD) fftin[indx++]=(float)*bp1/32768.;
    *bp2++ = *bp1++; 
  }
  *iter=indx;
}
int     fftcalc(float *in,float *out,int ord)
{
  int     NPASS,inptr,outptr,tempin,i,nset,nbut,pass,setno,butter,indxa,indxb;
  float theta,Wr,Wi,*inr,*ini,*outr,*outi,tempra,tempia,temprb,tempib;
  inr=in;ini=in+ord;outr=out;outi=out+ord;
  //---------------- Bit Reverse -----------------------
  NPASS=(int)(log10((float)ord)/log10(2.));
  for     (inptr=0;inptr<ord;inptr++)
  {
    tempin=inptr;
    outptr=0;
    for     (i=0;i<NPASS;i++)
    {
      outptr=(2*outptr)+tempin%2;
      tempin/=2;
    }
    inr[outptr+ord]=inr[inptr];
  }
  for     (i=0;i<ord;i++)
  {
    inr[i]=inr[i+ord];
    ini[i]=0.0;
  }
  //-------------- Radix 2 FFT -----------------------
  nset=ord/2;
  nbut=1;
  for     (pass=1;pass<=NPASS;pass++)
  {
    for     (setno=1;setno<=nset;setno++)
    {
      for     (butter=0;butter<nbut;butter++)
      {
        theta=((float)(nset*butter))*pi/((float)(ord/2));
        Wr=cos(theta);Wi=-sin(theta);
        indxa=butter+((setno-1)*2*nbut);indxb=indxa+nbut;
        tempra=inr[indxa]+Wr*inr[indxb]-Wi*ini[indxb];
        tempia=ini[indxa]+Wr*ini[indxb]+Wi*inr[indxb];
        temprb=inr[indxa]-Wr*inr[indxb]+Wi*ini[indxb];
        tempib=ini[indxa]-Wr*ini[indxb]-Wi*inr[indxb];
        outr[indxa]=tempra;
        outi[indxa]=tempia;
        outr[indxb]=temprb;
        outi[indxb]=tempib;
      }
    }
    nbut*=2;nset/=2;
    for     (i=0;i<ord;i++)
    {
      inr[i]=outr[i];
      ini[i]=outi[i];
    }
  }
  return(1);
}

void FFTCALC(float *fftin, float *fftout)
{
  for  (int i=0;i<ORD-1;i++)
  {
    fftin[i]=fftin[i]*Chebycoefs[i];
  }
  fftin[ORD-1]=0.0;
  fftout=fftin;
  fftcalc(fftin,fftout,ORD);
  for (int i=0;i<ORD/2;i++)
  {
    fftout[i]=(4./ORD)*sqrt((fftout[i]*fftout[i])+(fftout[i+ORD]*fftout[i+ORD]));
#ifdef DEBUG
    Serial.print((float)i*(float)fs/(float)ORD);
    Serial.print("    ");
    Serial.println(20.*log10(fftout[i]+1e-10));
#endif
  }   
}
int FINDSPECTRUMS(float *fftout,int *Numfreq,float *Thd)
{
  float maxres=0.0,thresh=sigthresh,ampl,maxlvl;
  float sigNRG,noiseNRG;
  int i,existval,numfreq,startindx,endindx=0,indx=0;
  long iter;
  float fsig[NUMFREQ];
  int sigindx[NUMFREQ];
  //------- compute total signal NRG --------
  sigNRG=0.0;
  for (i=0;i<ORD/2;i++)
  {
    sigNRG+=fftout[i]*fftout[i];
  }
  //-----  calculate threshold ----
  for  (i=0;i<ORD/2;i++)
  {
    if (fftout[i]>maxres) maxres=fftout[i];
  }
  maxres*=thresh;
  existval=0;
  for  (i=0;i<ORD/2;i++)
  {
    if (fftout[i]>maxres) existval=1;
  }
  if (existval==0)
  {
    Serial.println("********** NO SIGNAL FOUND ********");
    return 0;
  }
  iter=0;
  //--------  find signal frequencies -------------
  while (existval>0)
  {
    numfreq=iter+1;
    if (numfreq>NUMFREQ)
    {
        Serial.println("******* SIGNAL TOO NOISY FOR FURTHER ANALYSIS *******");
        return 0;
    }
    i=0;
    //---- look for indx rising lvl of first spectral  line ----
    while (i<ORD/2)
    {
      if (fftout[i]>maxres)
      {
        indx=i;
        maxlvl=fftout[i];
        break;
      }
      i++;
    }
    i++;
    //find indx of maxlvl of this spectral line
    while (i<ORD/2)
    {
      if (fftout[i]>maxlvl)
      {
        indx=i;
        maxlvl=fftout[i];
        i++;
      }
      else break;
    }
    //---------for display------------
    sigindx[iter]=indx;
    fsig[iter]=((float)((float)(sigindx[iter])/ORD))*fs;
    //-----  remove this set of spectral lines from the total ----
    endindx=indx+5;
    startindx=indx-5;
    ampl=0.0;
    for (i=startindx;i<=endindx;i++)
    {
      if (fftout[i]>ampl)
      ampl=fftout[i];
      fftout[i]=0;
    }
    Serial.print("signal no: ");
    Serial.print((int)iter+1);
    Serial.print(" freq: ");
    Serial.print(fsig[iter]);
    Serial.print(" Hz magnitudedB: ");
    Serial.println(20.*log10(ampl));
    //----- continue if there are any remaining spectral lines ------
    iter++;
    existval=0;
    for (i=0;i<ORD/2;i++)
    {
      if (fftout[i]>maxres) existval=1;
    }
  }
  //------- compute total noise NRG --------
  noiseNRG=0.0;
  for (i=0;i<ORD/2;i++)
  {
    noiseNRG+=fftout[i]*fftout[i];
  }
  //------- compute spectral thd --------
  *Thd=-10.*log10((sigNRG/noiseNRG)+1.0e-10);
  Serial.print("spectral thd=");
  Serial.println(*Thd);
  *Numfreq=numfreq;
  return 1;
}
int chkButton()
{
  int retval=0;
  if ((millis()-BounceStart)>BounceDelay)
  {
    BounceStart=millis();
    buttonNew=digitalRead(buttonPin);
    if(buttonOld==1 && buttonNew==0) retval=1;
    buttonOld=buttonNew;
  }
  return retval;
}
void stateAudio()
{
  if (streamstate==0)
  {
    if (millis()-startstream>startstreamdelay) //waiting to start stream
    { 
      streamstate=1;
    }
  }
  else if  (streamstate==1) //start stream
  {
    //audioOn();
    stopstream=millis();
    streamstate=2;
  }
  else if (streamstate==2) //run stream
  {
    if (millis()-stopstream>stopstreamdelay) streamstate=3; 
  }
  else if (streamstate==3) //stop stream
  {
    //audioOff();
    streamstate=4;
  }
  else if (streamstate==4) //calculate spectrum
  {
        //calculate spectrum
  }
  else if (streamstate==5) //idle
  {
    //idle
  }
}

windowcoefs.h
----------------
const double PROGMEM Chebycoefs[]={
//there are 32768 values here but I can't show them as I depass the message text size
};
 
And for info below the message after succesfully compiling with ORD=16384:


Opening Teensy Loader...
Memory Usage on Teensy 4.0:
FLASH: code:56120, data:136376, headers:8204 free for files:1830916
RAM1: variables:279232, code:53896, padding:11640 free for local variables:179520
RAM2: variables:29536 free for malloc/new:494752
 
This error means your variables + code are too large for RAM1.

Try adding DMAMEM to one of the large arrays, like this:

Code:
DMAMEM float fftinL[2*ORD];
float fftinR[2*ORD];

When ORD is 32768, each array takes 256K.
 
Trying to allocate 512kbytes of float arrays as well as other stuff in, er, 512k of RAM?

EDIT: Paul beat me to it!
 
I tried your suggestion and I get:

c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\chris\AppData\Local\Temp\arduino_build_447240/evdist.ino.elf section `.bss.dma' will not fit in region `RAM'
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: region `RAM' overflowed by 29536 bytes
collect2.exe: error: ld returned 1 exit status
 
So I'll stick with the fft order of 16384. Resolution is 2.7 Hz at fs=44100 which is OK for my project.
Thanks
 
BTW, I would be interested in any suggestions. I am making a portable THD audio signal analyzer using a Teensy 4.0. Looking around for a good screen to display my 16384-point FFT output. The typical tht screen doesn't have enough resolution to do the job, I'm afraid. See attached items of what I want to display. Thanks

----------------------- evdist ------------------------------------------
signal no: 1 freq: 441.430664 Hz magnitudedB: -10.656883
signal no: 2 freq: 18001.757813 Hz magnitudedB: -10.403691
CHANNEL 0 THD+N is: -90.242973 dB on 44100 samples
-------------------------------------------------------------------------



sine.jpg
 
Well 16384 wide displays aren't available at all to my knowledge - this is why spectrum analyzers often have a span function (basically the ability to zoom in on a sub range). You could look at how 'scopes do a split timebase to present both fullscale and zoomed-in waveforms simultaneously.
 
The problem for the tft is that it only has 320x480 pixels. My display shown above has 16384 x-axis frequencies. The width of my spectral lines are about 30 Hz. The resolution of the 320-pixel tft x-axis has 69 Hz between pixels. I might not even see those tones on the full-scale view. To remain portable, I was thinking it might be possible to use a smart-phone screen which has more pixels. One could then zoom in on the screen. But can the Teensy 4.0 USB send the spectral data to my phone and can the phone convert the data to an image on the display? I imagine so but I don't yet know how.
 
I'm here for advice. So what is your advice? I have 8192 points on my FFT over a range of 22050 Hz. The tone width is about 30 Hz. For a display of 320 pixels that means 22050Hz/320 or 689Hz between pixels. For a display of 1080 pixels that means 22050/1080 or 20Hz between pixels. I should see that tone on the full-scale un-zoomed image. Is my reasoning OK? Maybe not. I want to know how to display this frequency response. I repeat. I'm just trying to learn something here. If not, then I'll get off the forum.
 
Although you may have 689Hz between pixels any data shown there will be one pixel wide. You won't miss any signals, you just won't be able to resolve them. The 320 display output will look nearly the same to a 'Senior Members' eye :)
Here's a screen dump from a 320

View attachment gfft4096.bmp
 
to Paul
Thanks for your smart remark. I'll remember that for a long time!
I don't need 4 4K monitors, just a smartphone connected to my usb port.
This forum is more a contest of intelligence rather than a helpful one to obtain useful information.WhatsApp Image 2023-06-14 at 02.11.23.jpg
 
Thanks for your smart remark. I'll remember that for a long time!

DeletedUser:

It seems that you are taking offense where (I believe) none was intended. If I understand what you are describing, you want to take a 16384-sample FFT & somehow display it "intelligently" on your display device (phone, TFT, etc.) with far less pixels. How that data is displayed should be entirely up to you. If you're looking for a "typical average" across a particular FFT data set (I'm a general software guy, not a DSP software guy, so my terminology may be wacky), you'd need to down-sample the data, averaging several bins together, averaging across a moving window, etc. If peaks are more important (which you seem to imply), then I'd expect that you'd do peak detection as you analyze several bins together, or peak detection across a moving window, etc. Whatever your intent, you'd still need to be able to either display the entire data set at limited resolution, or to be able to zoom in, all the way down to the maximum resolution, but the width of your window will most certainly be a smaller portion of your overall data set. Of course, that still leaves the responsibility for where to do that down-sampling data reduction (on the Teensy, thereby only sending a reduced set of data to the display device, or in/on the display device itself, if it has the smarts to do so), as well as how to send the resulting data (either the full data set, or the reduced data set) to the display device.

You've clearly stated how much raw data that you have in your data set. You've also clearly stated that you want to display that data. However, for me, the clarity gets muddy from there. Are you looking for suggestions on what kind of display, how to get the data to that display, how to make sure that whatever is displayed doesn't lose some aspect of the raw data ?? Try to ask your question in a way that conveys the "what" or the "how" of what you are looking for & that will assist in guiding anyone who is attempting to answer your question(s), & maybe, with that further clarification, we can collectively get you working towards your ultimate goal.

Hope that helps . . .

Mark J Culross
KD5RXT
 
Last edited by a moderator:
Not clear or just defending Paul? I don't accept smart-ass remarks like his!
 
DeletedUser:

I don't need to, nor am I intending to defend anyone. If you truly want help, put away the defensiveness & try to see the problem from an outsider's (our) point of view. Unless we are able to determine exactly what you're looking for, our answers/suggestions/questions "could" come across very differently from how they were actually intended !! You already know that nobody on this forum gets paid for offering their help. There are lots of very experienced Teensy users on this forum & lots of users have posted seeking help, and better yet, lots of users have found the help that they were looking for. Sorry that you aren't currently seeing it this way.

Speaking only for myself, I'll try to help, in any way that I can. I am, by no means, a Teensy expert, but I am pleased with having successfully created several personal projects based upon the T4.x.

However, in order to help you in the specific way that you are looking for, I (we) really do need your help to do so !! If you are not able/willing to provide that help as requested, then I just have to apologize, step out, and finish with "Sorry, I am unable to help".

Mark J Culross
KD5RXT
 
Last edited by a moderator:
Back
Top