'Static' libraries {SOLVED}

Hello again,

Before we start, a quick disclaimer: I come from Java where - as I’ve already figured out - programming works quite differently than in C++. So some things I will be saying may not make much sense.

To keep it short: I want to make a library that can be used like ‘Seriel’ or ‘Wire’. That means:

Classname.begin(...);
Classname.dtStuff();

So, no instantiation, just the library name. In Java, you would make things static to achieve this (so make all library methods static). I’ve tried this, but that doesn’t help. I’ve also looked at some libraries that work this way, and they just have an empty constructor and ‘normal’ methods. Which also doesn’t work for me.

If anyone needs it, the code is down here:

Header:

#ifndef AnalogSignalAquisition_h
#define AnalogSignalAquisition_h

#include <Arduino.h>

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

Source:

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

AnalogSignalAquisition::AnalogSignalAquisition(){
}

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
  // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
  // for Arduino Uno ADC clock is 16 MHz and a conversion takes 13 clock cycles
  // due to if inside ISR, actual results may vary by a bit. Sampling rate is
  // therefore returned with every sample
  //ADCSRA |= (1 << ADPS2) | (1 << ADPS0);    // 32 prescaler for 38.5 KHz
  //ADCSRA |= (1 << ADPS2);                     // 16 prescaler for 76.9 KHz
  //ADCSRA |= (1 << ADPS1) | (1 << ADPS0);    // 8 prescaler for 153.8 KHz
  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
}

static uint32_t AnalogSignalAquisition::getSamples(uint8_t *samples, uint16_t numSamples) {
  long t = micros();
  for(uint16_t i = 0; i < numSamples; i++){
    ADCSRA |= (1 << ADSC);  // start ADC measurements
    while(!(ADCSRA&(0|(1<<ADIF))));
    samples[i] = ADCH;
  }
  t = micros()-t;
  return (uint32_t)((float)((numSamples*1000000.0) / t));
}

Test program:

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

void setup()
{
  Serial.begin(115200);
  AnalogSignalAquisition.begin(A0);
}

void loop()
{
  uint8_t samples[256];
Serial.println(AnalogSignalAquisition.getSamples(samples, 256));
delay(1000);
}

Error message:

C:\Users\...\DA\Code\Libs\In progress\AnalogSignalAquisition\AnalogSignalAquisition.ino: In function 'void setup()':

AnalogSignalAquisition:7:25: error: expected unqualified-id before '.' token

   AnalogSignalAquisition.begin(A0);

                         ^

C:\Users\Daniel\Documents\Backed Up\Material_HTL\5AHBG_19-20\DA\Code\Libs\In progress\AnalogSignalAquisition\AnalogSignalAquisition.ino: In function 'void loop()':

AnalogSignalAquisition:13:38: error: expected primary-expression before '.' token

 Serial.println(AnalogSignalAquisition.getSamples(samples, 256));

                                      ^

exit status 1
expected unqualified-id before '.' token

First, to clear up your misconception -- both Serial and Wire are, in fact, instances of classes. Assuming an AVR processor, Serial is an instance of the class HardwareSerial and Wire is an instance of the class TwoWire.

On to your question; if all of the functions and member variables of your class are static, you can access them as:

ClassName::memberVaraible
ClassName::memberFunction()

Or, you can put this inside your .h file but outside of the class declaration:
extern ClassName xxx;

Then, you can access the variables and functions as:
xxx.memberVaraible
xxx.memberFunction()

Since the entire class is static, you don’t actually have to define xxx, just declare it.

Finally, you can make the default constructor for your class 'private' so no user code will be able to instantiate its own object of the type.

Thank you very much!
Declaring the 'extern' (whatever that is, gonna have to look into that) made it work, and the private constructor is great advise.