AceTMI  0.6
Interfaces for communicating with the TM1637 and TM1638 LED controllers on Arduino platforms
SimpleTmi1638Interface.h
1 /*
2 MIT License
3 
4 Copyright (c) 2022 Brian T. Park
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 #ifndef ACE_TMI_SIMPLE_TMI_1638_INTERFACE_H
26 #define ACE_TMI_SIMPLE_TMI_1638_INTERFACE_H
27 
28 #include <Arduino.h>
29 
30 namespace ace_tmi {
31 
62  public:
77  uint8_t dioPin,
78  uint8_t clkPin,
79  uint8_t stbPin,
80  uint8_t delayMicros
81  ) :
82  mDioPin(dioPin),
83  mClkPin(clkPin),
84  mStbPin(stbPin),
85  mDelayMicros(delayMicros)
86  {}
87 
97  void begin() const {
98  clockHigh();
99  strobeHigh();
100  pinMode(mClkPin, OUTPUT);
101  pinMode(mStbPin, OUTPUT);
102  dataHigh(); // open-drain HIGH
103  }
104 
106  void end() const {
107  pinMode(mClkPin, INPUT);
108  pinMode(mStbPin, INPUT);
109  dataHigh(); // open-drain HIGH
110  }
111 
113  void beginTransaction() const {
114  clockHigh();
115  strobeLow();
116  dataHigh(); // open-drain HIGH
117  }
118 
120  void endTransaction() const {
121  clockHigh();
122  strobeHigh();
123  dataHigh(); // open-drain HIGH
124  }
125 
135  void write(uint8_t data) const {
136  for (uint8_t i = 0; i < 8; ++i) {
137  clockLow();
138  if (data & 0x1) {
139  dataHigh();
140  } else {
141  dataLow();
142  }
143 
144  // Device reads DIO on the rising edge of CLK.
145  clockHigh();
146  // The CLK LOW is twice as long as HIGH. An extra bitDelay() right after
147  // the clockHigh() would make the HIGH and LOW symmetric in duration (if
148  // digitalWrite() is assumed to be infinitely fast, which it is
149  // definitely not). But actual devices that I have tested seem to
150  // support the absence of that extra delay. So let's ignore it to make
151  // the transfer speed faster.
152 
153  data >>= 1;
154  }
155  }
156 
168  uint8_t read() const {
169  // Make sure mDioPin is in INPUT mode because the previous write() may
170  // have put mDioPin into open-drain OUTPUT mode.
171  dataHigh();
172 
173  uint8_t data = 0x0;
174  for (uint8_t i = 0; i < 8; ++i) {
175  // Device sets the DIO pin on the falling edge of CLK.
176  clockLow();
177  uint8_t bit = dataRead();
178  clockHigh();
179  data >>= 1;
180  data |= (bit & 0x1) ? 0x80 : 0x00;
181  }
182  return data;
183  }
184 
185  // Use default copy constructor and assignment operator.
187  SimpleTmi1638Interface& operator=(const SimpleTmi1638Interface&) = default;
188 
189  private:
190  void bitDelay() const { delayMicroseconds(mDelayMicros); }
191 
192  void clockHigh() const { digitalWrite(mClkPin, HIGH); bitDelay(); }
193 
194  void clockLow() const { digitalWrite(mClkPin, LOW); bitDelay(); }
195 
196  void dataHigh() const { pinMode(mDioPin, INPUT); bitDelay(); }
197 
198  void dataLow() const { pinMode(mDioPin, OUTPUT); bitDelay(); }
199 
200  void strobeHigh() const { digitalWrite(mStbPin, HIGH); bitDelay(); }
201 
202  void strobeLow() const { digitalWrite(mStbPin, LOW); bitDelay(); }
203 
204  uint8_t dataRead() const {
205  uint8_t data = digitalRead(mDioPin);
206  bitDelay();
207  return data;
208  }
209 
210  private:
211  uint8_t const mDioPin;
212  uint8_t const mClkPin;
213  uint8_t const mStbPin;
214  uint8_t const mDelayMicros;
215 };
216 
217 } // ace_tmi
218 
219 #endif
ace_tmi::SimpleTmi1638Interface::end
void end() const
Set pins to INPUT mode.
Definition: SimpleTmi1638Interface.h:106
ace_tmi::SimpleTmi1638Interface::endTransaction
void endTransaction() const
Generate the SPI-like stop condition.
Definition: SimpleTmi1638Interface.h:120
ace_tmi::SimpleTmi1638Interface::read
uint8_t read() const
Read the data byte on the data bus, with LSB first instead of the usual MSB first for SPI.
Definition: SimpleTmi1638Interface.h:168
ace_tmi::SimpleTmi1638Interface
Class that knows how to communicate with a TM1638 chip.
Definition: SimpleTmi1638Interface.h:61
ace_tmi::SimpleTmi1638Interface::SimpleTmi1638Interface
SimpleTmi1638Interface(uint8_t dioPin, uint8_t clkPin, uint8_t stbPin, uint8_t delayMicros)
Constructor.
Definition: SimpleTmi1638Interface.h:76
ace_tmi::SimpleTmi1638Interface::begin
void begin() const
Initialize the DIO, CLK and STB pins.
Definition: SimpleTmi1638Interface.h:97
ace_tmi::SimpleTmi1638Interface::write
void write(uint8_t data) const
Send the data byte on the data bus, with LSB first instead of the usual MSB first for SPI.
Definition: SimpleTmi1638Interface.h:135
ace_tmi::SimpleTmi1638Interface::beginTransaction
void beginTransaction() const
Generate the SPI-like start condition.
Definition: SimpleTmi1638Interface.h:113