Skip to content

Commit cd2ae50

Browse files
authored
Merge pull request #17 from lathoub/master
Syntactical rewrite using C++ templates to avoid heap fragmentation
2 parents ae69a4d + 11d2f9d commit cd2ae50

5 files changed

Lines changed: 141 additions & 149 deletions

File tree

examples/example/example.ino

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include <ShiftRegister74HC595.h>
99

1010
// create a global shift register object
11-
// parameters: (number of shift registers, data pin, clock pin, latch pin)
12-
ShiftRegister74HC595 sr (1, 0, 1, 2);
11+
// parameters: <number of shift registers> (data pin, clock pin, latch pin)
12+
ShiftRegister74HC595<1> sr(0, 1, 2);
1313

1414
void setup() {
1515
}
@@ -40,11 +40,12 @@ void loop() {
4040

4141
// read pin (zero based, i.e. 6th pin)
4242
uint8_t stateOfPin5 = sr.get(5);
43+
sr.set(6, stateOfPin5);
4344

4445

4546
// set pins without immediate update
4647
sr.setNoUpdate(0, HIGH);
4748
sr.setNoUpdate(1, LOW);
4849
// at this point of time, pin 0 and 1 did not change yet
4950
sr.updateRegisters(); // update the pins to the set values
50-
}
51+
}

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=ShiftRegister74HC595
2-
version=1.2
2+
version=1.3.0
33
author=Timo Denk (timodenk.com)
44
maintainer=Timo Denk (timodenk.com)
55
sentence=Simplifies usage of shift registers, designed for the 74HC595.

src/ShiftRegister74HC595.cpp

Lines changed: 2 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -5,135 +5,6 @@
55
Released into the public domain.
66
*/
77

8-
#include "Arduino.h"
9-
#include "ShiftRegister74HC595.h"
10-
11-
12-
// ShiftRegister74HC595 constructor
13-
ShiftRegister74HC595::ShiftRegister74HC595(int numberOfShiftRegisters, int serialDataPin, int clockPin, int latchPin)
14-
{
15-
// set attributes
16-
_numberOfShiftRegisters = numberOfShiftRegisters;
17-
18-
_clockPin = clockPin;
19-
_serialDataPin = serialDataPin;
20-
_latchPin = latchPin;
21-
22-
// define pins as outputs
23-
pinMode(clockPin, OUTPUT);
24-
pinMode(serialDataPin, OUTPUT);
25-
pinMode(latchPin, OUTPUT);
26-
27-
// set pins low
28-
digitalWrite(clockPin, LOW);
29-
digitalWrite(serialDataPin, LOW);
30-
digitalWrite(latchPin, LOW);
31-
32-
// allocates the specified number of bytes and initializes them to zero
33-
_digitalValues = (uint8_t *)malloc(numberOfShiftRegisters * sizeof(uint8_t));
34-
memset(_digitalValues, 0, numberOfShiftRegisters * sizeof(uint8_t));
35-
36-
updateRegisters(); // reset shift register
37-
}
38-
39-
40-
// ShiftRegister74HC595 destructor
41-
// The memory allocated in the constructor is also released.
42-
ShiftRegister74HC595::~ShiftRegister74HC595()
43-
{
44-
free(_digitalValues);
45-
}
46-
47-
48-
// Set all pins of the shift registers at once.
49-
// digitalVAlues is a uint8_t array where the length is equal to the number of shift registers.
50-
void ShiftRegister74HC595::setAll(const uint8_t * digitalValues)
51-
{
52-
memcpy( _digitalValues, digitalValues, _numberOfShiftRegisters); // dest, src, size
53-
updateRegisters();
54-
}
55-
56-
57-
// Experimental
58-
// The same as setAll, but the data is located in PROGMEM
59-
// For example with:
60-
// const uint8_t myFlashData[] PROGMEM = { 0x0F, 0x81 };
61-
#ifdef __AVR__
62-
void ShiftRegister74HC595::setAll_P(const uint8_t * digitalValuesProgmem)
63-
{
64-
PGM_VOID_P p = reinterpret_cast<PGM_VOID_P>(digitalValuesProgmem);
65-
memcpy_P( _digitalValues, p, _numberOfShiftRegisters);
66-
updateRegisters();
67-
}
68-
#endif
8+
#include <Arduino.h>
699

70-
71-
// Retrieve all states of the shift registers' output pins.
72-
// The returned array's length is equal to the numbe of shift registers.
73-
uint8_t * ShiftRegister74HC595::getAll()
74-
{
75-
return _digitalValues;
76-
}
77-
78-
79-
// Set a specific pin to either HIGH (1) or LOW (0).
80-
// The pin parameter is a positive, zero-based integer, indicating which pin to set.
81-
void ShiftRegister74HC595::set(int pin, uint8_t value)
82-
{
83-
setNoUpdate(pin, value);
84-
updateRegisters();
85-
}
86-
87-
88-
// Updates the shift register pins to the stored output values.
89-
// This is the function that actually writes data into the shift registers of the 74HC595
90-
void ShiftRegister74HC595::updateRegisters()
91-
{
92-
for (int i = _numberOfShiftRegisters - 1; i >= 0; i--) {
93-
shiftOut(_serialDataPin, _clockPin, MSBFIRST, _digitalValues[i]);
94-
}
95-
96-
digitalWrite(_latchPin, HIGH);
97-
digitalWrite(_latchPin, LOW);
98-
}
99-
100-
101-
// Equivalent to set(int pin, uint8_t value), except the physical shift register is not updated.
102-
// Should be used in combination with updateRegisters().
103-
void ShiftRegister74HC595::setNoUpdate(int pin, uint8_t value)
104-
{
105-
if (value == 1) {
106-
_digitalValues[pin / 8] |= 1 << (pin % 8);
107-
}
108-
else {
109-
_digitalValues[pin / 8] &= ~(1 << (pin % 8));
110-
}
111-
}
112-
113-
114-
// Returns the state of the given pin.
115-
// Either HIGH (1) or LOW (0)
116-
uint8_t ShiftRegister74HC595::get(int pin)
117-
{
118-
return (_digitalValues[pin / 8] >> (pin % 8)) & 1;
119-
}
120-
121-
122-
// Sets all pins of all shift registers to HIGH (1).
123-
void ShiftRegister74HC595::setAllHigh()
124-
{
125-
for (int i = 0; i < _numberOfShiftRegisters; i++) {
126-
_digitalValues[i] = 255;
127-
}
128-
updateRegisters();
129-
}
130-
131-
132-
// Sets all pins of all shift registers to LOW (0).
133-
void ShiftRegister74HC595::setAllLow()
134-
{
135-
for (int i = 0; i < _numberOfShiftRegisters; i++) {
136-
_digitalValues[i] = 0;
137-
}
138-
updateRegisters();
139-
}
10+
#include "ShiftRegister74HC595.h"

src/ShiftRegister74HC595.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,34 @@
55
Released into the public domain.
66
*/
77

8-
#ifndef ShiftRegister74HC595_h
9-
#define ShiftRegister74HC595_h
8+
#pragma once
109

11-
#include "Arduino.h"
10+
#include <Arduino.h>
1211

12+
template<uint8_t Size>
1313
class ShiftRegister74HC595
1414
{
1515
public:
16-
ShiftRegister74HC595(int numberOfShiftRegisters, int serialDataPin, int clockPin, int latchPin);
17-
~ShiftRegister74HC595();
16+
ShiftRegister74HC595(const uint8_t serialDataPin, const uint8_t clockPin, const uint8_t latchPin);
17+
1818
void setAll(const uint8_t * digitalValues);
1919
#ifdef __AVR__
2020
void setAll_P(const uint8_t * digitalValuesProgmem); // Experimental, PROGMEM data
2121
#endif
2222
uint8_t * getAll();
23-
void set(int pin, uint8_t value);
24-
void setNoUpdate(int pin, uint8_t value);
23+
void set(const uint8_t pin, const uint8_t value);
24+
void setNoUpdate(const uint8_t pin, uint8_t value);
2525
void updateRegisters();
2626
void setAllLow();
2727
void setAllHigh();
28-
uint8_t get(int pin);
28+
uint8_t get(const uint8_t pin);
2929

3030
private:
31-
int _numberOfShiftRegisters;
32-
int _clockPin;
33-
int _serialDataPin;
34-
int _latchPin;
35-
uint8_t * _digitalValues;
31+
uint8_t _clockPin;
32+
uint8_t _serialDataPin;
33+
uint8_t _latchPin;
34+
35+
uint8_t _digitalValues[Size];
3636
};
3737

38-
#endif
38+
#include "ShiftRegister74HC595.hpp"

src/ShiftRegister74HC595.hpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
ShiftRegister74HC595.hpp - Library for simplified control of 74HC595 shift registers.
3+
Created by Timo Denk (www.timodenk.com), Nov 2014.
4+
Additional information is available at http://shiftregister.simsso.de/
5+
Released into the public domain.
6+
*/
7+
8+
// ShiftRegister74HC595 constructor
9+
template<uint8_t Size>
10+
ShiftRegister74HC595<Size>::ShiftRegister74HC595(const uint8_t serialDataPin, const uint8_t clockPin, const uint8_t latchPin)
11+
{
12+
// set attributes
13+
_clockPin = clockPin;
14+
_serialDataPin = serialDataPin;
15+
_latchPin = latchPin;
16+
17+
// define pins as outputs
18+
pinMode(clockPin, OUTPUT);
19+
pinMode(serialDataPin, OUTPUT);
20+
pinMode(latchPin, OUTPUT);
21+
22+
// set pins low
23+
digitalWrite(clockPin, LOW);
24+
digitalWrite(serialDataPin, LOW);
25+
digitalWrite(latchPin, LOW);
26+
27+
// allocates the specified number of bytes and initializes them to zero
28+
memset(_digitalValues, 0, Size * sizeof(uint8_t));
29+
30+
updateRegisters(); // reset shift register
31+
}
32+
33+
// Set all pins of the shift registers at once.
34+
// digitalVAlues is a uint8_t array where the length is equal to the number of shift registers.
35+
template<uint8_t Size>
36+
void ShiftRegister74HC595<Size>::setAll(const uint8_t * digitalValues)
37+
{
38+
memcpy( _digitalValues, digitalValues, Size); // dest, src, size
39+
updateRegisters();
40+
}
41+
42+
// Experimental
43+
// The same as setAll, but the data is located in PROGMEM
44+
// For example with:
45+
// const uint8_t myFlashData[] PROGMEM = { 0x0F, 0x81 };
46+
#ifdef __AVR__
47+
template<uint8_t Size>
48+
void ShiftRegister74HC595<Size>::setAll_P(const uint8_t * digitalValuesProgmem)
49+
{
50+
PGM_VOID_P p = reinterpret_cast<PGM_VOID_P>(digitalValuesProgmem);
51+
memcpy_P( _digitalValues, p, Size);
52+
updateRegisters();
53+
}
54+
#endif
55+
56+
// Retrieve all states of the shift registers' output pins.
57+
// The returned array's length is equal to the number of shift registers.
58+
template<uint8_t Size>
59+
uint8_t * ShiftRegister74HC595<Size>::getAll()
60+
{
61+
return _digitalValues;
62+
}
63+
64+
// Set a specific pin to either HIGH (1) or LOW (0).
65+
// The pin parameter is a positive, zero-based integer, indicating which pin to set.
66+
template<uint8_t Size>
67+
void ShiftRegister74HC595<Size>::set(const uint8_t pin, const uint8_t value)
68+
{
69+
setNoUpdate(pin, value);
70+
updateRegisters();
71+
}
72+
73+
// Updates the shift register pins to the stored output values.
74+
// This is the function that actually writes data into the shift registers of the 74HC595
75+
template<uint8_t Size>
76+
void ShiftRegister74HC595<Size>::updateRegisters()
77+
{
78+
for (int i = Size - 1; i >= 0; i--) {
79+
shiftOut(_serialDataPin, _clockPin, MSBFIRST, _digitalValues[i]);
80+
}
81+
82+
digitalWrite(_latchPin, HIGH);
83+
digitalWrite(_latchPin, LOW);
84+
}
85+
86+
// Equivalent to set(int pin, uint8_t value), except the physical shift register is not updated.
87+
// Should be used in combination with updateRegisters().
88+
template<uint8_t Size>
89+
void ShiftRegister74HC595<Size>::setNoUpdate(const uint8_t pin, const uint8_t value)
90+
{
91+
(value) ? bitSet(_digitalValues[pin / 8], pin % 8) : bitClear(_digitalValues[pin / 8], pin % 8);
92+
}
93+
94+
// Returns the state of the given pin.
95+
// Either HIGH (1) or LOW (0)
96+
template<uint8_t Size>
97+
uint8_t ShiftRegister74HC595<Size>::get(const uint8_t pin)
98+
{
99+
return (_digitalValues[pin / 8] >> (pin % 8)) & 1;
100+
}
101+
102+
// Sets all pins of all shift registers to HIGH (1).
103+
template<uint8_t Size>
104+
void ShiftRegister74HC595<Size>::setAllHigh()
105+
{
106+
for (int i = 0; i < Size; i++) {
107+
_digitalValues[i] = 255;
108+
}
109+
updateRegisters();
110+
}
111+
112+
// Sets all pins of all shift registers to LOW (0).
113+
template<uint8_t Size>
114+
void ShiftRegister74HC595<Size>::setAllLow()
115+
{
116+
for (int i = 0; i < Size; i++) {
117+
_digitalValues[i] = 0;
118+
}
119+
updateRegisters();
120+
}

0 commit comments

Comments
 (0)