AceTMI  0.1.0
Unified interface for selecting different implementations for communicating with a TM1637 LED controller chip on Arduino platforms
SoftTmiFastInterface.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_SOFT_TMI_FAST_INTERFACE_H
26 #define ACE_TMI_SOFT_TMI_FAST_INTERFACE_H
27 
28 // This header file requires the digitalWriteFast library on AVR, or the
29 // EpoxyMockDigitalWriteFast library on EpoxyDuino.
30 #if defined(ARDUINO_ARCH_AVR) || defined(EPOXY_DUINO)
31 
32 #include <stdint.h>
33 #include <Arduino.h> // delayMicroseconds()
34 
35 namespace ace_tmi {
36 
75 template <
76  uint8_t T_DIO_PIN,
77  uint8_t T_CLK_PIN,
78  uint8_t T_DELAY_MICROS
79 >
80 class SoftTmiFastInterface {
81  public:
82  explicit SoftTmiFastInterface() = default;
83 
92  void begin() const {
93  digitalWriteFast(T_CLK_PIN, LOW);
94  digitalWriteFast(T_DIO_PIN, LOW);
95 
96  // Begin with both lines at HIGH.
97  clockHigh();
98  dataHigh();
99  }
100 
102  void end() const {
103  clockHigh();
104  dataHigh();
105  }
106 
108  void startCondition() const {
109  clockHigh();
110  dataHigh();
111 
112  dataLow();
113  clockLow();
114  }
115 
117  void stopCondition() const {
118  // clock will always be LOW when this is called
119  dataLow();
120  clockHigh();
121  dataHigh();
122  }
123 
135  uint8_t sendByte(uint8_t data) const {
136  for (uint8_t i = 0; i < 8; ++i) {
137  if (data & 0x1) {
138  dataHigh();
139  } else {
140  dataLow();
141  }
142  clockHigh();
143  clockLow();
144  data >>= 1;
145  }
146 
147  return readAck();
148  }
149 
150  private:
155  uint8_t readAck() const {
156  // Go into INPUT mode, reusing dataHigh(), saving 6 flash bytes on AVR.
157  dataHigh();
158  uint8_t ack = digitalReadFast(T_DIO_PIN);
159 
160  // Device releases DIO upon falling edge of the 9th CLK.
161  clockHigh();
162  clockLow();
163  return ack;
164  }
165 
166  // The following methods use compile-time constants from the template
167  // parameters. The compiler will optimize away the 'this' pointer so that
168  // these methods become identical to calling static functions.
169 
170  void bitDelay() const { delayMicroseconds(T_DELAY_MICROS); }
171 
172  void clockHigh() const { pinModeFast(T_CLK_PIN, INPUT); bitDelay(); }
173 
174  void clockLow() const { pinModeFast(T_CLK_PIN, OUTPUT); bitDelay(); }
175 
176  void dataHigh() const { pinModeFast(T_DIO_PIN, INPUT); bitDelay(); }
177 
178  void dataLow() const { pinModeFast(T_DIO_PIN, OUTPUT); bitDelay(); }
179 };
180 
181 } // ace_tmi
182 
183 #endif // defined(ARDUINO_ARCH_AVR)
184 
185 #endif