C ISR in library

Hello,

I am currently working on a library to generate arrays of sampled data to be put into an FFT.
Because the standard analogRead is too slow for this purpose (i need to get a good-enough representation of the signal up to 2 kHz), i want to do it using DPM and the ADC in Free-running mode.
This - of course - requires an ISR(ADC_vect), which is no problem in a normal project. But because my code is quite big (the Arduino will serve as the nerve center of a bigger project), I want to pack it into a library.
But I have absolutely no clue how to use C- interrupts in there (and I can also not find any existing threads - they are all using the Arduino methods). Any suggestions?

Thanks in advance!

I think I understand the problem, but I don't understand your question.

What have you tried?

I have very little expierience in library programming, so this might be stupid:

AnalogSignalAquisition.h

#ifndef AnalogSignalAquisition_h
#define AnalogSignalAquisition_h

#include <Arduino.h>

class AnalogSignalAquisition{
  public:
  static void begin(uint8_t signalPin);
  static uint32_t getSamples(uint8_t *samples, uint16_t numSamples);
  static uint8_t *_samples;
  static uint16_t _numSamples;
};
#endif

AnalogSignalAquisition.cpp

#include <Arduino.h>
#include "AnalogSignalAquisition.h"

static void AnalogSignalAquisition::begin(uint8_t signalPin) {
  signalPin = (signalPin - 14); // A0 is 14
  if (signalPin > 5) signalPin = 0b1111; // Set to 0V (ATmega 328 datasheet page 249)
  // ADC prepwork
  ADCSRA = 0;             // clear ADCSRA register
  ADCSRB = 0;             // clear ADCSRB register
  ADMUX = 0;              // clear ADMUX register
  ADMUX |= signalPin;     // set analog input pin
  ADMUX |= (1 << REFS0);  // set reference voltage to internal 5V
  ADMUX |= (1 << ADLAR);  // left align ADC value to 8 bits from ADCH register
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // 128 prescaler for ~9615 Hz

  ADCSRA |= (1 << ADATE); // enable auto trigger
  ADCSRA |= (1 << ADIE);  // enable interrupts when measurement complete
  //ADCSRA |= (1 << ADEN);  // enable ADC
  //ADCSRA |= (1 << ADSC);  // start ADC measurements
}

static uint32_t AnalogSignalAquisition::getSamples(uint8_t *samples, uint16_t numSamples) {
  _samples = samples;
  _numSamples = 0;
}

ISR(ADC_vect)
  {
    AnalogSignalAquisition::_samples[AnalogSignalAquisition::_numSamples] = ADCH;  // read 8 bit value from ADC
  }

Test program:

#include <Arduino.h>
#include "AnalogSignalAquisition.h";
void setup()
{
  Serial.begin(115200);
  uint8_t samples[128];
  Serial.println(asa.getSamples(samples, 128));
}

void loop()
{

}

I have not actually pressed upload, I just compiled and got an error saying the ISR can not find the two public variables.

Have you noticed that you promised getSamples would return a uint32_t, but doesn't?

Post your error messages, please.
They contain a lot of useful information.

I would have probably noticed once the compiler got to it, but thank you.

Error message is (put into braces because yes):

C:\Users\------\AppData\Local\Temp\ccqQfOMg.ltrans0.ltrans.o: In function `__vector_21':

sketch/AnalogSignalAquisition.cpp:29: undefined reference to `AnalogSignalAquisition::_samples'

sketch/AnalogSignalAquisition.cpp:29: undefined reference to `AnalogSignalAquisition::_samples'

sketch/AnalogSignalAquisition.cpp:29: undefined reference to `AnalogSignalAquisition::_numSamples'

sketch/AnalogSignalAquisition.cpp:29: undefined reference to `AnalogSignalAquisition::_numSamples'

C:\Users\Daniel\AppData\Local\Temp\ccqQfOMg.ltrans0.ltrans.o: In function `getSamples':

sketch/AnalogSignalAquisition.cpp:23: undefined reference to `AnalogSignalAquisition::_samples'

sketch/AnalogSignalAquisition.cpp:23: undefined reference to `AnalogSignalAquisition::_samples'

sketch/AnalogSignalAquisition.cpp:24: undefined reference to `AnalogSignalAquisition::_numSamples'

sketch/AnalogSignalAquisition.cpp:24: undefined reference to `AnalogSignalAquisition::_numSamples'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino Uno.

FYI: __vector_21 is ADC_vect

Also, I just noticed that all access to those variables is unsuccessful. I can't remember this being the case earlier, but I don't know how to solve it, so I guess it's part of the question now...

EDIT: To get this error message, I also removed the static modifiers from the two methods (not from the variables, tho)!

You have a .begin() method but your test program doesn't call it.

I can't find where you declare the instance asa.

Your ISR attempt cannot call the method of the class until there is an instance. What you have is like saying int = 3;

I might have found a workaround without using the ISR.

I will have to look a bit more into Arduino library programming, as you can see, I don't really know what I'm doing...

Still, if anyone has resources about using an ISR inside a library (or just tips if it's just like any other method), I'm open for suggestions.

Thank you for all your help!

EDIT: I am just an idiot. The giant drop in sampling frequency didn't come from the lack of the ISR (even though that did slow things down a bit), but from me printing every time a sample was collected instead of waiting till the end.

Your .cpp file is missing the needed instantiation of the static variables.

uint8_t *AnalogSignalAquisition::_samples = nullptr;
uint16_t AnalogSignalAquisition::_numSamples = 0;