New Library - QuickPin

This library's main goal was to be as fast as possible for those applications that need speed. QuickPin is around twice as fast as the digitalRead and digitalWrite functions that it replaces. The library can be found Here.

Here are some samples on how the library is used:

** Analog Input**

#include <QuickPin.h>

QuickPin analogSensor(0, ANALOG, INPUT);

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

void loop() {
  int val = analogSensor.get();
  
  Serial.println(val, DEC);
  delay(500);
}

** Analog Output (PWM)**

#include <QuickPin.h>

QuickPin analogOutput(11, ANALOG, OUTPUT);

void setup() {
}

void loop() {
  for(int i=0; i<254; i++) {
    analogOutput.set(i);
    delay(20);
  }
}

** Digital Input**

#include <QuickPin.h>

QuickPin digitalInput(5, DIGITAL, INPUT);

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

void loop() {
  byte result;

  for(int i=0; i<20; i++) {
    result = digitalInput.get();
    Serial.print(result, DEC);
    delay(200);
  }
  Serial.print('\n');
}

** Digital Output**

#include <QuickPin.h>

QuickPin digitalOutput(13, DIGITAL, OUTPUT);

void setup() {
}

void loop() {
  byte result;

  for(int i=0; i<20; i++) {
    digitalOutput.set(HIGH);
    delay(200);
    digitalOutput.set(LOW);
    delay(200);
  }
}

If you have any comments or suggestions please let me know. I'm still tinkering with this, but I think at the very least the interface that exists will be compatible with future versions.

Cool. I like the idea of doing the pin number to port / bit translation once and caching it inside a class.

Some small comments / suggestions:

  • It looks like there a few cases where you can call a function that's not meaningful - e.g. set() on a QuickPin instance representing an analog input, or get() on analog output. If you split the library up into three classes (e.g. DigitalPin, AnalogInputPin, AnalogOutputPin), you could have each one only provide the functions that are meaningful for that type of pin. It would probably even speed things up, since you wouldn't need to check the pin type inside the get() and set() functions.
  • What about using read() and write() instead of get() and set() for better consistency with the existing API's (e.g. digitalRead(), digitalWrite())?
  • In open(), I think you want to call setError(ER_NONE) before re_initialize() - otherwise you mask initialization errors (like invalid pin numbers).

Other than that, it looks good. You should consider posting it on the playground, if you haven't already.

  • It looks like there a few cases where you can call a function that's not meaningful - e.g. set() on a QuickPin instance representing an analog input, or get() on analog output. If you split the library up into three classes (e.g. DigitalPin, AnalogInputPin, AnalogOutputPin), you could have each one only provide the functions that are meaningful for that type of pin. It would probably even speed things up, since you wouldn't need to check the pin type inside the get() and set() functions.

I certainly considered that idea. However, I opted for the consolidated approach; in favor of a more centralized point of entry for pin manipulation. My idea is that it's easier to remember and use a class of the same name, the same instantiation parameters, and the same methods. With everything in one spot if you want to manipulate a pin, QuickPin will do it for you.

  • What about using read() and write() instead of get() and set() for better consistency with the existing API's (e.g. digitalRead(), digitalWrite())?

This is a very good idea. I think that I will adopt this before anyone starts to use QuickPin.

  • In open(), I think you want to call setError(ER_NONE) before re_initialize() - otherwise you mask initialization errors (like invalid pin numbers).

I'll look into this. Thanks!

Another idea is to handle a consecutive row of pins on the same port.
Say you need to toggle 3 pins rapidly (e.g. with a 595) then the class could do the bit manipulations required.

That could be a parent class.