Merge pull request #153 from RobTillaart/develop

refactor; added tests
This commit is contained in:
Rob Tillaart 2020-05-20 09:54:30 +02:00 committed by GitHub
commit 6ece084dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 461 additions and 149 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,50 +1,59 @@
//
// FILE: PinOutGroup.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.1.1
// DATE: 2017-04-26
// PURPOSE: PinOutGroup library for Arduino
// goal is to easily change a group of pins that logically
// belong to each other e.g. 8 data pins of a parallel printer.
// these pins can be in any order.
// URL: http://forum.arduino.cc/index.php?topic=469599.0
// URL:
// http://forum.arduino.cc/index.php?topic=469599.0
//
// Released to the public domain
//
// 0.1.0 - initial version (based upon experimental pinGroup)
// 0.1.0 - 20-08-2017 initial version (based upon experimental pinGroup)
// 0.1.1 - 2020-05-19 main refactor;
// added tests; added clear(); added write(idx, value)
// renamed set to write() to be in line with digitalWrite()
//
//
#include "PinOutGroup.h"
PinOutGroup::PinOutGroup()
{
clear();
}
void PinOutGroup::clear()
{
// safety: set all to LOW before cleaning up.
for (uint8_t i = 0; i < _size; i++) digitalWrite(_pins[i], LOW);
_size = 0;
}
bool PinOutGroup::add(uint8_t s, int* ar, uint8_t value) // value = HIGH LOW
bool PinOutGroup::add(uint8_t sz, uint8_t* ar, uint8_t value)
{
bool b = true;
for (uint8_t i = 0; i < s; i++)
for (uint8_t i = 0; i < sz && b; i++)
{
b = b && add(ar[i], value);
}
return b;
}
bool PinOutGroup::add(uint8_t pin, uint8_t value) // value = HIGH LOW
bool PinOutGroup::add(uint8_t pin, uint8_t value)
{
if (_size < PINOUTGROUP_MAXSIZE)
{
_pins[_size] = pin; // BUG pin can be added multiple time.
pinMode(pin, OUTPUT);
digitalWrite(pin, value);
_size++;
return true;
}
return false;
if (_size >= PINOUTGROUP_MAXSIZE) return false;
_pins[_size] = pin;
pinMode(pin, OUTPUT);
digitalWrite(pin, value);
_size++;
return true;
}
uint8_t PinOutGroup::set(uint16_t value)
uint8_t PinOutGroup::write(uint16_t value)
{
uint16_t changed = _lastValue ^ value; // detect pins that changed
if (changed == 0) return 0;
@ -63,5 +72,19 @@ uint8_t PinOutGroup::set(uint16_t value)
_lastValue = value;
return changeCount;
}
uint8_t PinOutGroup::write(uint8_t idx, uint8_t value)
{
if (idx >= _size) return 0;
uint16_t mask = (1 << idx);
uint16_t lv = _lastValue & mask;
// --- END OF FILE ---
if ((value > 0) == (lv > 0)) return 0; // no change
digitalWrite(_pins[idx], value);
if (value == LOW) _lastValue &= ~mask;
else _lastValue |= mask;
return 1;
}
// --- END OF FILE ---

View File

@ -1,57 +1,55 @@
#ifndef PINOUTGROUP_H
#pragma once
// FILE: PinOutGroup.h
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// VERSION: 0.1.1
// DATE: 2017-04-26
// PURPOSE: PinOutGroup library for Arduino
// HISTORY: See pinGroup.cpp
//
// Released to the public domain
// HISTORY: See PinOutGroup.cpp
//
#include "Arduino.h"
#define PINOUTGROUP_LIB_VERSION "0.1.0"
#define PINOUTGROUP_LIB_VERSION "0.1.1"
// smaller MAXSIZE will reduce memory footprint with ditto bytes.
#ifndef PINOUTGROUP_MAXSIZE
#define PINOUTGROUP_MAXSIZE 16
#endif
// PINOUTGROUP_MAXSIZE = 16 ==> max value, smaller will reduce memory footprint with ditto bytes.
#define PINOUTGROUP_MAXSIZE 16
//
// a pinGroup is a number of output pins that can be set by means of
// one set command. The pinGroup remembers the last set value per pin
// and will not do a digitalWrite() if the pin is already in the right
// state. If a pin is updated often this can save some cpu cycles
// however this feature has some overhead which is contra productive
// when you toggle a group of pins. So use with care.
//
// <performance intermezzo>
// On average 50% of the pins are in the right state (assumption)
// This means that of a set only half the pins are changed, so 50%
// is the maximum theoretical gain we see on average.
// In testruns a gain of 20-25% is seen but this really depends on
// the data used.
//
class PinOutGroup
{
public:
PinOutGroup();
// adds a predefined array of pinnumbers to the PinOutGroup
// enables one to reset at he pinGroup and repopulate it
void clear();
// adds a predefined array of pin numbers to the PinOutGroup
// sets all to (LOW, HIGH)
bool add(uint8_t s, int* ar, uint8_t value = LOW);
bool add(uint8_t sz, uint8_t* ar, uint8_t value = LOW);
// adds a single pin to the PinOutGroup, default to LOW.
bool add(uint8_t pin, uint8_t value = LOW);
// set up to 16 pins "simultaneously" in one call.
uint8_t set(uint16_t value);
uint8_t write(uint16_t value);
// write to a single pin while maintaining internal admin
uint8_t write(uint8_t idx, uint8_t value);
// retrieve the last set value
uint16_t get() { return _lastValue; };
// get the current size
uint16_t read() { return _lastValue; };
uint8_t size() { return _size; };
// check how many free "slots" there are...
uint8_t free() { return PINOUTGROUP_MAXSIZE - _size; };
private:
uint16_t _lastValue = 0;
uint8_t _pins[PINOUTGROUP_MAXSIZE]; // should be malloced dynamically
uint8_t _pins[PINOUTGROUP_MAXSIZE];
uint8_t _size = 0;
};
#endif
// -- END OF FILE --

View File

@ -0,0 +1,43 @@
# PinOutGroup
Arduino library to group up to 16 outputs into one command
# Description
A PinOutGroup is a number of output pins that can be set by means of one **write()** command.
The PinOutGroup remembers the last values set per pin and will not do a digitalWrite()
if the pin is already in the right state. Think of it as caching the state.
If a (group of) pin(s) is updated often this saves cpu cycles however this feature
has overhead which works contra productive when you toggle the pins in a group. So use with care.
### performance intermezzo
Assume that on average 50% of the pins are in the right state in a group.
This means that on average half the pins are actually changed. By bypassing
the (relative) expensive **digitalWrite()** time is gained.
Actual performance gains depends very much on the data written.
It is worth to do a small investigation for this. See e.g. 7 segment demo.
### interface
**clear()** resets all pins in the group to LOW and sets the size ot zero
so one can repopulate.
**add()** adds a predefined array of pin numbers of a single pin to the group.
**write(value)** writes a 16 bits unsigned int to max 16 pins.
**write(idx, value)** sets a single pin of the internal array withindex
idx to value. This one is faster than writing to the whole group for a single
change. The user must keep track of the right index nr.
**read()** reads back the last written value to the pins as an unsigend int.
**size()** and **free()** give information about the group.
# Operation
See examples

View File

@ -0,0 +1,38 @@
// FILE: led13.ino
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// PURPOSE: demo pinGroup library for Arduino
// blink the build in led by means of a PinOutGroup
#include "PinOutGroup.h"
PinOutGroup led13;
uint8_t ar[1] = { 13 } ;
uint32_t start , stop;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print(F("PINOUTGROUP_LIB_VERSION: "));
Serial.println(PINOUTGROUP_LIB_VERSION);
led13.add(1, ar );
}
void loop()
{
Serial.println();
start = micros();
led13.write(0, HIGH); // could be led13.write(1); as there is just one in the group.
stop = micros();
Serial.println(stop - start);
delay(250);
led13.write(0, LOW); // could be led13.write(0); as there is just one in the group.
delay(250);
}
// -- END OF FILE --

View File

@ -0,0 +1,82 @@
// FILE: sevenSegment.ino
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// PURPOSE: demo PinOutGroup library for Arduino
//
#include "PinOutGroup.h"
// connect arduino pins 2.. 8 to pins A..G of a 7 segments display
uint8_t ar[7] = {2, 3, 4, 5, 6, 7, 8};
int ssc[16] = // seven segment char
{
63, 6, 91, 79, 102, 109, 125, 7, 127, 111, // 0 .. 9
119, 124, 57, 94, 121, 113 // A .. F
};
PinOutGroup display;
uint32_t start, stop, t1, t2;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print(F("PINOUTGROUP_LIB_VERSION: "));
Serial.println(PINOUTGROUP_LIB_VERSION);
Serial.println();
Serial.println("Without PinOutGroup");
delay(10);
start = micros();
for (int i = 0; i < 16; i++)
{
digitalWrite(2, ssc[i] & 0x01);
digitalWrite(3, ssc[i] & 0x02);
digitalWrite(4, ssc[i] & 0x04);
digitalWrite(5, ssc[i] & 0x08);
digitalWrite(6, ssc[i] & 0x10);
digitalWrite(7, ssc[i] & 0x20);
digitalWrite(8, ssc[i] & 0x40);
}
stop = micros();
Serial.println("cycling through 16 chars");
Serial.print("Time: ");
t1 = stop - start;
Serial.println(stop - start);
Serial.println();
delay(10);
Serial.println("With PinOutGroup");
delay(10);
display.add(7, ar);
start = micros();
for (int i = 0; i < 16; i++)
{
display.write(ssc[i]);
}
stop = micros();
Serial.println("cycling through 16 chars");
Serial.print("Time: ");
t2 = stop - start;
Serial.println(stop - start);
Serial.println();
Serial.print(" %: ");
Serial.println((1.0 * t2)/ t1);
Serial.println();
}
void loop()
{
for (int i = 0; i < 16; i++)
{
display.write(ssc[i]);
delay(250);
}
}
// -- END OF FILE --

View File

@ -1,20 +1,18 @@
// FILE: testPinOutGroup.ino
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// VERSION: 0.1.1
// PURPOSE: demo PinOutGroup library for Arduino
// HISTORY:
//
// Released to the public domain
//
#include "PinOutGroup.h"
int ar[4] = {2, 3, 4, 13};
uint8_t ar[4] = {2, 3, 4, 13};
void setup()
{
Serial.begin(115200);
Serial.print("PINOUTGROUP_LIB_VERSION: ");
Serial.println(__FILE__);
Serial.print(F("PINOUTGROUP_LIB_VERSION: "));
Serial.println(PINOUTGROUP_LIB_VERSION);
test0();
@ -27,16 +25,18 @@ void setup()
test7();
test8();
Serial.println("done...");
Serial.println(F("done..."));
}
void loop()
{
}
// TEST1 verifies and times basic working
void test0()
{
Serial.println(__FUNCTION__);
Serial.println(F("Time reference functionality.\n"));
int i = 3;
// CHANGE 1 PINS
pinMode(2, OUTPUT);
@ -47,14 +47,17 @@ void test0()
digitalWrite(2, i++ % 2);
uint32_t t2 = micros();
Serial.print(F("Time: "));
Serial.println(t2 - t1);
Serial.println("Test0 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
void test1()
{
Serial.println(__FUNCTION__);
Serial.println(F("Time to change # pins.\n"));
uint8_t n1, n2, n3, n4;
PinOutGroup POG;
POG.add(2);
@ -62,31 +65,32 @@ void test1()
POG.add(5);
POG.add(13);
Serial.print("size: ");
Serial.print(F("size: "));
Serial.println(POG.size());
Serial.println("\n#PINS\tTIME");
// CHANGE 1 PINS
uint32_t t1 = micros();
n1 = POG.set(B1000);
n1 = POG.write(B1000);
uint32_t t2 = micros();
// CHANGE 2 PINS
uint32_t t3 = micros();
n2 = POG.set(B0100);
n2 = POG.write(B0100);
uint32_t t4 = micros();
// CHANGE 3 PINS
uint32_t t5 = micros();
n3 = POG.set(B1010);
n3 = POG.write(B1010);
uint32_t t6 = micros();
// CHANGE 4 PINS
uint32_t t7 = micros();
n4 = POG.set(B0101);
n4 = POG.write(B0101);
uint32_t t8 = micros();
// RESET ALL
POG.set(B0000);
POG.write(B0000);
Serial.print(n1);
Serial.print('\t');
@ -100,13 +104,18 @@ void test1()
Serial.print(n4);
Serial.print('\t');
Serial.println(t8 - t7);
Serial.println("Test1 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST2 tests if a set() always matches a subsequent get().
void test2()
{
Serial.println(__FUNCTION__);
Serial.println(F("Does write() match subsequent read()."));
Serial.println(F("No output is good!\n"));
PinOutGroup POG;
POG.add(2);
POG.add(4);
@ -119,73 +128,94 @@ void test2()
for (int i = 0; i < 256; i++)
{
POG.set(i);
int x = POG.get();
if (x != i) Serial.println("fail test 2");
POG.write(i);
int x = POG.read();
if (x != i)
{
Serial.print("failed value: ");
Serial.println(i);
}
}
Serial.println("Test2 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST3 tests the adding of an array of pins
void test3()
{
Serial.println(__FUNCTION__);
Serial.println(F("Test adding an array of pins."));
PinOutGroup POG;
POG.add(4, ar );
Serial.print("size: ");
Serial.print(F("size: "));
Serial.println(POG.size());
Serial.println("Test3 done...");
POG.add(4, ar );
Serial.print(F("size: "));
Serial.println(POG.size());
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST 4 shows that a pin can be added multiple times
void test4()
{
Serial.println(__FUNCTION__);
Serial.println(F("Test adding a pin multiple times.\n"));
PinOutGroup POG;
Serial.print(F("size: "));
Serial.println(POG.size());
for (int i = 0; i < 8; i++)
{
POG.add(13);
Serial.print(F("size: "));
Serial.println(POG.size());
}
POG.set(B01010101);
Serial.print("size: ");
Serial.println(POG.size());
Serial.println("Test4 done...");
POG.write(B01010101);
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST 5 simulates a LCD display
void test5()
{
Serial.println(__FUNCTION__);
Serial.println(F("Simulates a 8 bit channel to LCD display.\n"));
PinOutGroup POG;
POG.add(4, ar);
POG.add(4, ar);
Serial.print("size: ");
Serial.print(F("size: "));
Serial.println(POG.size());
int cnt = 0;
char str[] = "Hello world. This is a test. The quick brown fox jumps over the lazy dog!";
for (uint8_t i = 0; i < strlen(str); i++)
int len = strlen(str);
for (uint8_t i = 0; i < len; i++)
{
cnt += POG.set((uint8_t)str[i]);
cnt += POG.write((uint8_t)str[i]);
}
Serial.print(" Printing: ");
Serial.print(F(" Printing: "));
Serial.println(str);
Serial.print(" Bits: ");
Serial.println(strlen(str) * 8);
Serial.print(" Changed: ");
Serial.println(cnt);
Serial.print(" AVG: ");
Serial.println(1.0 * cnt / (strlen(str) * 8), 3);
Serial.println("Test5 done...");
Serial.println("footnote: test 5 uses ascii that only change in 5-6 bits max, which decreases the average");
Serial.println(" That said, it is a real life application e.g. updating an LCD screen.");
Serial.print(F("Bits total: "));
Serial.println(strlen(str) * 8);
Serial.print(F(" Changed: "));
Serial.println(cnt);
Serial.print(F(" ratio: "));
Serial.println(1.0 * cnt / (len * 8), 3);
Serial.println();
Serial.println(F("footnote: test 5 uses ascii that only change in 5-6 bits max, which decreases the average"));
Serial.println(F(" That said, it is a real life application e.g. updating an LCD screen."));
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
//
// wrapper for test 6
//
// wrapper for test6()
void dw(const uint8_t pin, const uint8_t val)
{
static uint8_t preVal = -1;
@ -196,10 +226,11 @@ void dw(const uint8_t pin, const uint8_t val)
}
}
// TEST6 checks if cache trick works for digitalWrite too
void test6()
{
Serial.println(__FUNCTION__);
Serial.println(F("Check if cache trick works for digitalWrite.\n"));
uint8_t a[1000];
randomSeed(1);
for (int i = 0; i < 1000; i++) a[i] = random(2);
@ -219,67 +250,78 @@ void test6()
}
uint32_t t4 = micros();
Serial.println("random: average case");
Serial.print("ORG: ");
Serial.println(F("random: average case"));
Serial.print(F("ORG: "));
Serial.println(t2 - t1);
Serial.print("NEW: ");
Serial.print(F("NEW: "));
Serial.println(t4 - t3);
Serial.print(F(" %: "));
Serial.println(1.0 * (t4 - t3) / (t2 - t1));
Serial.println();
uint32_t t5 = micros();
t1 = micros();
for (int i = 0; i < 1000; i++)
{
digitalWrite(2, LOW);
}
uint32_t t6 = micros();
t2 = micros();
uint32_t t7 = micros();
t3 = micros();
for (int i = 0; i < 1000; i++)
{
dw(2, LOW);
}
uint32_t t8 = micros();
t4 = micros();
Serial.println("same: best case");
Serial.print("ORG: ");
Serial.println(t6 - t5);
Serial.print("NEW: ");
Serial.println(t8 - t7);
Serial.println(F("same: best case"));
Serial.print(F("ORG: "));
Serial.println(t2 - t1);
Serial.print(F("NEW: "));
Serial.println(t4 - t3);
Serial.print(F(" %: "));
Serial.println(1.0 * (t4 - t3) / (t2 - t1));
Serial.println();
t5 = micros();
t1 = micros();
for (int i = 0; i < 1000; i++)
{
digitalWrite(2, i % 2);
}
t6 = micros();
t2 = micros();
t7 = micros();
t3 = micros();
for (int i = 0; i < 1000; i++)
{
dw(2, i % 2);
}
t8 = micros();
t4 = micros();
Serial.println("toggle: worst case");
Serial.print("ORG: ");
Serial.println(t6 - t5);
Serial.print("NEW: ");
Serial.println(t8 - t7);
Serial.println(F("toggle: worst case"));
Serial.print(F("ORG: "));
Serial.println(t2 - t1);
Serial.print(F("NEW: "));
Serial.println(t4 - t3);
Serial.print(F(" %: "));
Serial.println(1.0 * (t4 - t3) / (t2 - t1));
Serial.println();
Serial.println("Test6 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST7 tests average gain
void test7()
{
Serial.println(__FUNCTION__);
Serial.println(F("Test average gain indication (simplified).\n"));
PinOutGroup POG;
// effectively 16 pins...
POG.add(4, ar);
POG.add(4, ar);
POG.add(4, ar);
POG.add(4, ar);
uint8_t a[1000];
randomSeed(1);
for (int i = 0; i < 1000; i++) a[i] = random(32768);
@ -297,38 +339,45 @@ void test7()
uint32_t t3 = micros();
for (int i = 0; i < 1000; i++)
{
POG.set(a[i]);
POG.write(a[i]);
}
uint32_t t4 = micros();
Serial.println("1000x random bit: average case");
Serial.print("ORG: ");
Serial.println(F("1000x random bit: average case"));
Serial.print(F("ORG: "));
Serial.println(t2 - t1);
Serial.print("NEW: ");
Serial.print(F("NEW: "));
Serial.println(t4 - t3);
Serial.print(F(" %: "));
Serial.println(1.0 * (t4 - t3) / (t2 - t1));
Serial.println();
Serial.println("Test7 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// TEST8 tests free()
void test8()
{
Serial.println(__FUNCTION__);
Serial.println(F("Test Free()...\n"));
PinOutGroup POG;
Serial.print("size: ");
Serial.print(F("size: "));
Serial.println(POG.size());
Serial.print("free: ");
Serial.print(F("free: "));
Serial.println(POG.free());
POG.add(4, ar );
Serial.print("size: ");
Serial.print(F("size: "));
Serial.println(POG.size());
Serial.print("free: ");
Serial.print(F("free: "));
Serial.println(POG.free());
Serial.println("Test8 done...");
Serial.print(__FUNCTION__);
Serial.println(F(" done..."));
Serial.println();
}
// END OF FILE
// -- END OF FILE --

View File

@ -0,0 +1,56 @@
// FILE: trafficLight.ino
// AUTHOR: Rob dot Tillaart at gmail dot com
// VERSION: 0.1.0
// PURPOSE: demo PinOutGroup library for Arduino
//
#include "PinOutGroup.h"
PinOutGroup trafficLight;
uint8_t lights[] = {11, 12, 13}; // connect 3 leds...
const int RED = 4;
const int YELLOW = 2;
const int GREEN = 1;
const int YELLOWRED = 6;
int state = 0;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print(F("PINOUTGROUP_LIB_VERSION: "));
Serial.println(PINOUTGROUP_LIB_VERSION);
Serial.println();
trafficLight.add(3, lights);
}
void loop()
{
switch (state)
{
default:
Serial.println("RED");
trafficLight.write(RED);
break;
case 1:
Serial.println("YELLOWRED");
trafficLight.write(YELLOWRED);
break;
case 2:
Serial.println("GREEN");
trafficLight.write(GREEN);
break;
case 3:
Serial.println("YELLOW");
trafficLight.write(YELLOW);
break;
}
state++;
if (state == 4) state = 0;
delay(1000);
}
// -- END OF FILE --

View File

@ -1,6 +1,6 @@
{
"name": "PinOutGroup",
"keywords": "PinOutGroup,pin,group",
"keywords": "PinOutGroup, pin, group, OUTPUT",
"description": "A class that groups output pins so they can be updated easier and slightly faster on average",
"authors":
[
@ -13,12 +13,12 @@
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/Arduino.git"
"url": "https://github.com/RobTillaart/PinOutGroup.git"
},
"version":"0.1.0",
"version":"0.1.1",
"frameworks": "arduino",
"platforms": "*",
"export": {
"include": "libraries/PinOutGroup
"include": "PinOutGroup
}
}

View File

@ -1,9 +1,11 @@
name=PinOutGroup
version=0.1.0
version=0.1.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=A class that groups output pins so they can be updates easier and slightly faster on average.
sentence=A class that groups output pins so they can be updated easier and slightly faster on average.
paragraph=
category=Uncategorized
url=https://github.com/RobTillaart/Arduino/tree/master/libraries
architectures=*
category=Communication
url=https://github.com/RobTillaart/PinOutGroup.git
architectures=*
includes=PinOutGroup.h
depends=