1+ /* ShiftIn.h - Arduino library that reads in values from an 8 bit shift register (74HC165).
2+ * You can daisy-chain several shift register in order to read in up to 64 buttons by only using 4 Arduino pins.
3+ *
4+ * Created by Henrik Heine, July 24, 2016
5+ *
6+ LICENSE
7+ The MIT License (MIT)
8+
9+ Copyright (c) 2016 Henrik
10+
11+ Permission is hereby granted, free of charge, to any person obtaining a copy
12+ of this software and associated documentation files (the "Software"), to deal
13+ in the Software without restriction, including without limitation the rights
14+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+ copies of the Software, and to permit persons to whom the Software is
16+ furnished to do so, subject to the following conditions:
17+
18+ The above copyright notice and this permission notice shall be included in all
19+ copies or substantial portions of the Software.
20+
21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+ SOFTWARE.
28+ */
29+ #ifndef ShiftIn_h
30+ #define ShiftIn_h
31+
32+ #include " Arduino.h"
33+
34+ template <byte chipCount, typename ShiftType>
35+ class _ShiftIn {
36+ private:
37+ byte ploadPin;
38+ byte clockEnablePin;
39+ byte dataPin;
40+ byte clockPin;
41+
42+ const uint16_t dataWidth;
43+ uint8_t pulseWidth;
44+
45+ ShiftType lastState;
46+ ShiftType currentState;
47+ public:
48+ _ShiftIn () : dataWidth(chipCount * 8 ), pulseWidth(5 ), lastState(0 ), currentState(0 ) {}
49+
50+ // setup all pins
51+ void begin (int pload, int clockEN, int data, int clock) {
52+ pinMode (ploadPin = pload, OUTPUT);
53+ pinMode (clockEnablePin = clockEN, OUTPUT);
54+ pinMode (dataPin = data, INPUT);
55+ pinMode (clockPin = clock, OUTPUT);
56+ }
57+
58+ inline uint8_t getPulseWidth () { return pulseWidth; }
59+ inline void setPulseWidth (uint8_t value) { pulseWidth = value; }
60+ inline uint16_t getDataWidth () { return dataWidth; }
61+ // whether some value has changed
62+ inline boolean hasChanged () { return lastState != currentState; }
63+ // whether the value with index 'id' has changed
64+ inline boolean hasChanged (int id) { return state (id) != last (id); }
65+ // returns the state from the last frame
66+ inline ShiftType getLast () { return lastState; }
67+ // returns the current state
68+ inline ShiftType getCurrent () { return currentState; }
69+ // whether button 'id' is pressed or not
70+ inline boolean state (int id) { return bitRead (currentState, id); }
71+ // whether button 'id' was pressed in the last frame
72+ inline boolean last (int id) { return bitRead (lastState, id); }
73+ // whether button 'id' is now pressed, but wasn't pressed in the last frame
74+ inline boolean pressed (int id) { return !last (id) && state (id); }
75+ // whether button 'id' is now released, but was pressed in the last frame
76+ inline boolean released (int id) { return last (id) && !state (id); }
77+
78+ // read in data from shift register and return the new value
79+ ShiftType read () {
80+ lastState = currentState;
81+ ShiftType result = 0 ;
82+
83+ digitalWrite (clockEnablePin, HIGH);
84+ digitalWrite (ploadPin, LOW);
85+ delayMicroseconds (pulseWidth);
86+ digitalWrite (ploadPin, HIGH);
87+ digitalWrite (clockEnablePin, LOW);
88+
89+ for (int i = 0 ; i < dataWidth; i++) {
90+ ShiftType value = digitalRead (dataPin);
91+ result |= (value << ((dataWidth-1 ) - i));
92+ digitalWrite (clockPin, HIGH);
93+ delayMicroseconds (pulseWidth);
94+ digitalWrite (clockPin, LOW);
95+ }
96+ currentState = result;
97+ return result;
98+ }
99+
100+ // same as read, but it returns whether something has changed or not
101+ boolean update () {
102+ return read () != lastState;
103+ }
104+ };
105+
106+ // fallback with 64 bit state (up to 8 shift registers)
107+ template <byte chipCount>
108+ class ShiftIn : public _ShiftIn <chipCount, uint64_t > {};
109+ // single shift register (8 bit state)
110+ template <>
111+ class ShiftIn <1 > : public _ShiftIn<1 , uint8_t > {};
112+ // two shift registers (16 bit state)
113+ template <>
114+ class ShiftIn <2 > : public _ShiftIn<2 , uint16_t > {};
115+ // three shift registers (32 bit state)
116+ template <>
117+ class ShiftIn <3 > : public _ShiftIn<3 , uint32_t > {};
118+ // four shift registers (32 bit state)
119+ template <>
120+ class ShiftIn <4 > : public _ShiftIn<4 , uint32_t > {};
121+
122+ #endif
0 commit comments