AceTMI  0.2.0
Unified interface for selecting different implementations for communicating with a TM1637 LED controller chip on Arduino platforms
SimpleTmiFastInterface.h
1 /*
2 MIT License
3 
4 Copyright (c) 2021 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_FAST_INTERFACE_H
26 #define ACE_TMI_SIMPLE_TMI_FAST_INTERFACE_H
27 
28 #include <stdint.h>
29 #include <Arduino.h> // delayMicroseconds()
30 
31 namespace ace_tmi {
32 
70 template <
71  uint8_t T_DIO_PIN,
72  uint8_t T_CLK_PIN,
73  uint8_t T_DELAY_MICROS
74 >
76  public:
78  explicit SimpleTmiFastInterface() = default;
79 
88  void begin() const {
89  digitalWriteFast(T_CLK_PIN, LOW);
90  digitalWriteFast(T_DIO_PIN, LOW);
91 
92  // Begin with both lines at HIGH.
93  clockHigh();
94  dataHigh();
95  }
96 
98  void end() const {
99  clockHigh();
100  dataHigh();
101  }
102 
104  void startCondition() const {
105  clockHigh();
106  dataHigh();
107 
108  dataLow();
109  clockLow();
110  }
111 
113  void stopCondition() const {
114  // clock will always be LOW when this is called
115  dataLow();
116  clockHigh();
117  dataHigh();
118  }
119 
131  uint8_t sendByte(uint8_t data) const {
132  for (uint8_t i = 0; i < 8; ++i) {
133  if (data & 0x1) {
134  dataHigh();
135  } else {
136  dataLow();
137  }
138  clockHigh();
139  // An extra bitDelay() here would make the HIGH and LOW states symmetric
140  // in duration (if digitalWriteFast() is assumed to be infinitely fast,
141  // which it is definitely not). But actual devices that I have tested
142  // seem to support the absence of that extra delay. So let's ignore it
143  // to make the transfer speed faster.
144  clockLow();
145  data >>= 1;
146  }
147 
148  uint8_t ack = readAck();
149  return ack ^ 0x1; // invert the 0 and 1
150  }
151 
152  // Use default copy constructor and assignment operator.
154  SimpleTmiFastInterface& operator=(const SimpleTmiFastInterface&) = default;
155 
156  private:
163  uint8_t readAck() const {
164  // Go into INPUT mode, reusing dataHigh(), saving 6 flash bytes on AVR.
165  dataHigh();
166 
167  // DIO is supposed to remain stable after CLK is set HIGH.
168  clockHigh();
169 
170  uint8_t ack = digitalReadFast(T_DIO_PIN);
171 
172  // Device releases DIO upon falling edge of the 9th CLK.
173  clockLow();
174  return ack;
175  }
176 
177  // The following methods use compile-time constants from the template
178  // parameters. The compiler will optimize away the 'this' pointer so that
179  // these methods become identical to calling static functions.
180 
181  void bitDelay() const { delayMicroseconds(T_DELAY_MICROS); }
182 
183  void clockHigh() const { pinModeFast(T_CLK_PIN, INPUT); bitDelay(); }
184 
185  void clockLow() const { pinModeFast(T_CLK_PIN, OUTPUT); bitDelay(); }
186 
187  void dataHigh() const { pinModeFast(T_DIO_PIN, INPUT); bitDelay(); }
188 
189  void dataLow() const { pinModeFast(T_DIO_PIN, OUTPUT); bitDelay(); }
190 };
191 
192 } // ace_tmi
193 
194 #endif
ace_tmi::SimpleTmiFastInterface::startCondition
void startCondition() const
Generate the I2C start condition.
Definition: SimpleTmiFastInterface.h:104
ace_tmi::SimpleTmiFastInterface::begin
void begin() const
Initialize the dio and clk pins.
Definition: SimpleTmiFastInterface.h:88
ace_tmi::SimpleTmiFastInterface::SimpleTmiFastInterface
SimpleTmiFastInterface()=default
Constructor.
ace_tmi::SimpleTmiFastInterface
Exactly the same as SimpleTmiInterface except that this uses the digitalWriteFast library on AVR proc...
Definition: SimpleTmiFastInterface.h:75
ace_tmi::SimpleTmiFastInterface::stopCondition
void stopCondition() const
Generate the I2C stop condition.
Definition: SimpleTmiFastInterface.h:113
ace_tmi::SimpleTmiFastInterface::sendByte
uint8_t sendByte(uint8_t data) const
Send the data byte on the data bus, with LSB first instead of the usual MSB first for I2C.
Definition: SimpleTmiFastInterface.h:131
ace_tmi::SimpleTmiFastInterface::end
void end() const
Set dio and clk pins to INPUT mode.
Definition: SimpleTmiFastInterface.h:98