0.1.1 refactor & testing

This commit is contained in:
rob tillaart 2020-05-22 16:00:06 +02:00
parent 65f3ec50f4
commit 490f7ad6e3
7 changed files with 375 additions and 88 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017-2020 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,57 +1,59 @@
//
// FILE: PinInGroup.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.1.1
// DATE: 2017-04-26
// PURPOSE: PinInGroup library for Arduino
// goal is to easily change a group of pins that logically
// goal is to easily read a group of pins that logically
// belong to each other.
// The pins can be in any order.
// URL: http://forum.arduino.cc/index.php?topic=469599.0
// URL: https://github.com/RobTillaart/PinInGroup
// http://forum.arduino.cc/index.php?topic=469599.0
//
// Released to the public domain
//
// 0.1.0 - initial version (based upon pinGroup)
//
// 0.1.0 2017-08-20 initial version (based upon pinGroup)
// 0.1.1 2020-05-19 refactor; added clear(); added param for INPUT or INPUT_PULLUP
#include "PinInGroup.h"
PinInGroup::PinInGroup()
{
clear();
}
void PinInGroup::clear()
{
_size = 0;
}
bool PinInGroup::add(uint8_t size, int* ar)
uint8_t PinInGroup::add(uint8_t sz, uint8_t * ar, uint8_t value)
{
bool b = true;
for (uint8_t i = 0; i < size; i++)
int n = 0;
for (uint8_t i = 0; i < sz; i++)
{
b = b && add(ar[i]);
n += add(ar[i], value);
}
return b;
return n;
}
bool PinInGroup::add(uint8_t pin)
uint8_t PinInGroup::add(uint8_t pin, uint8_t value)
{
if (_size < PININGROUP_MAXSIZE)
{
_pins[_size] = pin;
pinMode(pin, INPUT);
_size++;
return true;
}
return false;
if (_size >= PININGROUP_MAXSIZE) return 0;
_pins[_size] = pin;
pinMode(pin, value);
_size++;
return 1;
}
uint16_t PinInGroup::read()
{
uint16_t value = 0;
uint16_t mask = 0x01;
for (uint8_t i = 0; i < _size; i++)
{
value <<= 1;
value = value | (digitalRead(_pins[i]) > 0 ? 1: 0);
if (digitalRead(_pins[i])) value |= mask;
mask <<= 1;
}
return value;
}
// --- END OF FILE ---
// --- END OF FILE ---

View File

@ -1,41 +1,55 @@
#ifndef PININGROUP_H
#pragma once
// FILE: PinInGroup.h
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// VERSION: 0.1.1
// DATE: 2017-04-26
// PURPOSE: PinInGroup library for Arduino
// HISTORY: See PinInGroup.cpp
//
// Released to the public domain
// Note: ESP32 has some dedicated IO pins that cannot be used in a group.
// FLASH: pin 6 - 11 (maybe more)
//
#include "Arduino.h"
#define PININGROUP_LIB_VERSION "0.1.0"
#define PININGROUP_MAXSIZE 16
#define PININGROUP_LIB_VERSION "0.1.1"
// smaller MAXSIZE will reduce memory footprint with ditto bytes.
#ifndef PININGROUP_MAXSIZE
#define PININGROUP_MAXSIZE 16
#endif
//
// a PinInGroup is a group of up to sixteen input pins that can be read
// by means of one read command and combined into one uint16_t.
//
class PinInGroup
{
public:
PinInGroup();
// adds a predefined array of pinnumbers to the PinInGroup
bool add(uint8_t s, int* ar);
// adds a single pin to the PinInGroup
bool add(uint8_t pin);
public:
PinInGroup();
// read up to 8 pins "simultaneously" into one byte.
uint16_t read();
// enables one to reset the pinGroup and repopulate it
void clear();
// get the current size of the PinInGroup.
uint8_t size() { return _size; };
// check how many free slots there are...
uint8_t free() { return PININGROUP_MAXSIZE - _size; };
private:
uint8_t _pins[PININGROUP_MAXSIZE]; // should be malloced dynamically
uint8_t _size = 0;
// adds a predefined array of pin numbers to the PinInGroup
// sets all to either INPUT or INPUT_PULLUP.
uint8_t add(uint8_t sz, uint8_t * ar, uint8_t value = INPUT);
// adds a single pin to the PinInGroup
uint8_t add(uint8_t pin, uint8_t value = INPUT);
// read up to 16 pins "simultaneously" in one call.
uint16_t read();
uint8_t size() {
return _size;
};
// check how many free "slots" there are...
uint8_t free() {
return PININGROUP_MAXSIZE - _size;
};
private:
uint8_t _pins[PININGROUP_MAXSIZE];
uint8_t _size = 0;
};
#endif
// -- END OF FILE --

View File

@ -0,0 +1,37 @@
# PinInGroup
Arduino library to group reading to 16 input pins in one command
# Description
A PinInGroup holds a number of input pins that can be read by means of a single **read()** command.
The PinInGroup makes it easier to work with a number of inputs that are a logical unit,
e.g. think of reading a parallel bus or read 4 lines from a matrix keyboard, or just
read an array of switches.
### Performace
The PinInGroup is not much more efficient as reading the pins in a loopyourself.
Hoewever it is less programming and gives clearer code.
There exist some ideas to optimize the low level reading e.g. only reading
the registers only once, or hold register and bit info per pin.
These ideas will be explored when time permits.
Note: The current ideas are platform specific.
### interface
**clear()** sets the size to zero so one can repopulate.
**add()** adds a predefined array of pins of a single pin to the group.
Note one can set a 2nd parameter mode to **INPUT**(default) or **INPUT_PULLUP**.
**read(value)** reads a 16 bits unsigned int from max 16 pins.
**size()** and **free()** give information about the group.
# Operation
See examples

View File

@ -2,26 +2,34 @@
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// PURPOSE: demo PinInGroup library for Arduino
// HISTORY: 20-08-2017
// HISTORY: 20-08-2017
//
// Released to the public domain
//
#include "PinInGroup.h"
int ar[4] = {2, 3, 4, 13};
uint8_t ar[4] = {2, 3, 4, 23};
uint8_t alt[] = {23, 22, 1, 3, 21, 19, 18, 5, 23, 22, 1, 3, 21, 19, 18, 5};
void setup()
{
Serial.begin(115200);
Serial.print("\nPININGROUP_LIB_VERSION: ");
Serial.println(__FILE__);
Serial.print(F("\nPININGROUP_LIB_VERSION: "));
Serial.println(PININGROUP_LIB_VERSION);
Serial.println();
test0();
test1();
test2();
Serial.println("done...");
test3();
test4();
test5();
test6();
Serial.println(F("done..."));
}
void loop()
@ -31,24 +39,38 @@ void loop()
// TEST1 verifies and times basic working
void test0()
{
pinMode(2, INPUT);
Serial.println();
Serial.println(__FUNCTION__);
delay(20);
uint16_t n1 = 0;
uint32_t t1 = micros();
digitalRead(2);
digitalRead(2);
digitalRead(2);
digitalRead(2);
n1 = digitalRead(2) > 0;
n1 <<= 1;
n1 |= digitalRead(3) > 0;
n1 <<= 1;
n1 |= digitalRead(4) > 0;
n1 <<= 1;
n1 |= digitalRead(13) > 0;
uint32_t t2 = micros();
Serial.print("time: ");
Serial.print(F(" val: "));
Serial.println(n1, BIN);
Serial.print(F("time: "));
Serial.println(t2 - t1);
Serial.println("Test0 done...");
Serial.print(F("time: "));
Serial.println((1.0 * (t2 - t1)) / 4, 1);
Serial.println(F("Test0 done..."));
Serial.println();
}
void test1()
{
Serial.println();
Serial.println(__FUNCTION__);
uint16_t n1;
PinInGroup PIG;
PIG.add(2);
PIG.add(4);
@ -59,41 +81,230 @@ void test1()
Serial.println(PIG.size());
Serial.print("free: ");
Serial.println(PIG.free());
delay(20);
uint32_t t1 = micros();
n1 = PIG.read();
uint32_t t2 = micros();
Serial.print(" val: ");
Serial.println(n1);
Serial.print("time: ");
Serial.print(F(" val: "));
Serial.println(n1, BIN);
Serial.print(F("time: "));
Serial.println(t2 - t1);
Serial.println("Test1 done...");
Serial.print(F("time: "));
Serial.println((1.0 * (t2 - t1)) / PIG.size(), 1);
Serial.println(F("Test1 done..."));
Serial.println();
}
void test2()
{
uint16_t n1;
PinInGroup PIG;
for (int p=2; p<14; p++) PIG.add(p);
Serial.println();
Serial.println(__FUNCTION__);
Serial.print("size: ");
uint16_t n1;
PinInGroup PIG;
#if defined(ESP32) || defined(ESP8266)
// be carefull which pins you use for ESP32 (and probably 8266 too, not tested)
// note: GPIO06 through GPIO11 are reserved for the FLASH.
// You cannot use them. ==> pinMode() fails.
// https://github.com/espressif/arduino-esp32/issues/1411
//
for (uint8_t p = 20; p < 36; p++) PIG.add(p);
#else
for (uint8_t p = 2; p < 14; p++) PIG.add(p);
#endif
Serial.print(F("size: "));
Serial.println(PIG.size());
Serial.print("free: ");
Serial.print(F("free: "));
Serial.println(PIG.free());
delay(20);
uint32_t t1 = micros();
n1 = PIG.read();
uint32_t t2 = micros();
Serial.print(" val: ");
Serial.println(n1);
Serial.print("time: ");
Serial.print(F(" val: "));
Serial.println(n1, BIN);
Serial.print(F("time: "));
Serial.println(t2 - t1);
Serial.println("Test1 done...");
Serial.print(F("time: "));
Serial.println((1.0 * (t2 - t1)) / PIG.size(), 1);
Serial.println(F("Test2 done..."));
Serial.println();
}
// END OF FILE
void test3()
{
Serial.println();
Serial.println(__FUNCTION__);
uint16_t n1;
PinInGroup PIG;
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
Serial.print(F("size: "));
Serial.println(PIG.size());
Serial.print(F("free: "));
Serial.println(PIG.free());
PIG.add(4, ar, INPUT_PULLUP); // should not be added
Serial.print(F("size: "));
Serial.println(PIG.size());
Serial.print(F("free: "));
Serial.println(PIG.free());
Serial.println();
delay(20);
PIG.clear();
for (int i = 1; i <= 16; i++)
{
PIG.add(23);
uint32_t t1 = micros();
n1 = PIG.read();
uint32_t t2 = micros();
float timePerPin2 = (1.0 * t2 - t1) / i;
Serial.print(i);
Serial.print('\t');
Serial.print(t2 - t1);
Serial.print('\t');
Serial.print(timePerPin2);
Serial.print('\t');
Serial.println(n1, BIN);
delay(20);
}
Serial.println(F("Test3 done..."));
Serial.println();
}
void test4()
{
Serial.println();
Serial.println(__FUNCTION__);
uint16_t n1;
PinInGroup PIG;
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
PIG.add(4, ar, INPUT_PULLUP);
Serial.print(F("size: "));
Serial.println(PIG.size());
Serial.print(F("free: "));
Serial.println(PIG.free());
PIG.clear();
PIG.add(4, ar, INPUT_PULLUP); // should not be added
Serial.print(F("size: "));
Serial.println(PIG.size());
Serial.print(F("free: "));
Serial.println(PIG.free());
delay(20);
uint32_t t1 = micros();
n1 = PIG.read();
uint32_t t2 = micros();
Serial.print(F(" val: "));
Serial.println(n1, BIN);
Serial.print(F("time: "));
Serial.println(t2 - t1);
Serial.print(F("time: "));
Serial.println((1.0 * (t2 - t1)) / PIG.size(), 1);
Serial.println(F("Test4 done..."));
Serial.println();
}
void test5()
{
Serial.println();
Serial.println(__FUNCTION__);
uint16_t n1 = 0;
uint32_t t1 = micros();
n1 = digitalRead(2) > 0;
n1 <<= 1;
n1 |= digitalRead(3) > 0;
n1 <<= 1;
n1 |= digitalRead(4) > 0;
n1 <<= 1;
n1 |= digitalRead(13) > 0;
uint32_t t2 = micros();
float timePerPin = (1.0 * t2 - t1) / 4;
Serial.print(F(" val: "));
Serial.println(n1, BIN);
Serial.print(F("time: "));
Serial.println(t2 - t1);
Serial.print(F("time: "));
Serial.println(timePerPin);
Serial.println();
PinInGroup PIG;
for (int i = 1; i <= 16; i++)
{
PIG.add(2);
t1 = micros();
n1 = PIG.read();
t2 = micros();
float timePerPin2 = (1.0 * t2 - t1) / i;
Serial.print(i);
Serial.print('\t');
Serial.print(t2 - t1);
Serial.print('\t');
Serial.print(timePerPin2);
Serial.print('\t');
Serial.println(timePerPin2 / timePerPin * 100.0);
delay(20);
}
Serial.println(F("Test5 done..."));
Serial.println();
}
void test6()
{
Serial.println();
Serial.println(__FUNCTION__);
uint16_t n1 = 0;
PinInGroup PIG;
// verify pin stays same place in output.
// connect selected pin to GND and it should stay on same spot.
// even when pins are added.
for (int i = 1; i <= 10; i++)
{
PIG.add(i, INPUT_PULLUP);
n1 = PIG.read() + 32768;
Serial.print(i);
Serial.print('\t');
Serial.print(n1, BIN);
Serial.print('\n');
}
Serial.println(F("Test6 done..."));
Serial.println();
}
// -- END OF FILE --

View File

@ -1,6 +1,6 @@
{
"name": "PinInGroup",
"keywords": "PinInGroup,pin,group",
"keywords": "PinInGroup, pin, group, INPUT",
"description": "A class that groups input pins so they can be read in one logical step",
"authors":
[
@ -13,12 +13,12 @@
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/Arduino.git"
"url": "https://github.com/RobTillaart/PinInGroup.git"
},
"version":"0.1.0",
"version":"0.1.1",
"frameworks": "arduino",
"platforms": "*",
"export": {
"include": "libraries/PinInGroup
"include": "PinInGroup
}
}

View File

@ -1,9 +1,11 @@
name=pinGroup
version=0.1.0
name=PinInGroup
version=0.1.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=A class that groups input pins so they can be read in one logical step.
paragraph=
category=Uncategorized
url=https://github.com/RobTillaart/Arduino/tree/master/libraries
architectures=*
category=Communication
url=https://github.com/RobTillaart/PinInGroup
architectures=*
includes=PinInGroup.h
depends=