MySensors Library & Examples  2.3.1
MCP320X.h
1 #ifndef MCP320X_h
2 #define MCP320X_h
3 #include <DigitalIO.h>
4 //==============================================================================
5 template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0>
7 class MCP3201
8 {
9 public:
10  //----------------------------------------------------------------------------
12  void begin()
13  {
14  fastPinMode(ClkPin, 1);
15  fastDigitalWrite(ClkPin, 0);
16  fastPinMode(CsPin, 1);
17  fastDigitalWrite(CsPin, 1);
18  fastPinMode(DoutPin, 0);
19  }
20  //----------------------------------------------------------------------------
24  inline __attribute__((always_inline))
25  uint16_t read()
26  {
27  fastDigitalWrite(CsPin, 0);
28  // Start sample.
29  mcpAdcDummy(3);
30  // Extra sample time.
31  if (UsecDelay) {
32  delayMicroseconds(UsecDelay);
33  }
34  // End sample.
35  mcpAdcDummy(3);
36  // Null bit.
37  mcpAdcDummy(3);
38  uint16_t v = 0;
39  readBit(v, 11);
40  readBit(v, 10);
41  readBit(v, 9);
42  readBit(v, 8);
43  readBit(v, 7);
44  readBit(v, 6);
45  readBit(v, 5);
46  readBit(v, 4);
47  readBit(v, 3);
48  readBit(v, 2);
49  readBit(v, 1);
50  readBit(v, 0);
51  fastDigitalWrite(CsPin, 1);
52  return v;
53  }
54 private:
55  //----------------------------------------------------------------------------
59  inline __attribute__((always_inline))
60  void delayCycles(uint8_t n)
61  {
62  if (n & 1) {
63  asm volatile("nop\n\t");
64  }
65  if (n & 2) {
66  asm volatile("nop\n\t" "nop\n\t");
67  }
68  if (n & 4) {
69  asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
70  }
71  }
72  //----------------------------------------------------------------------------
75  inline __attribute__((always_inline))
76  void mcpAdcDummy(uint8_t delayBefore)
77  {
78  delayCycles(delayBefore);
79  fastDigitalWrite(ClkPin, 1);
80  delayCycles(3);
81  fastDigitalWrite(ClkPin, 0);
82  }
83  //----------------------------------------------------------------------------
84  inline __attribute__((always_inline))
85  void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2)
86  {
87  delayCycles(3);
88  fastDigitalWrite(ClkPin, 1);
89  delayCycles(delayRead);
90  if (fastDigitalRead(DoutPin)) {
91  v |= (1 << b);
92  }
93  fastDigitalWrite(ClkPin, 0);
94  }
95 };
96 //==============================================================================
97 template<uint8_t CsPin, uint8_t ClkPin,
98  uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
100 class MCP3202
101 {
102 public:
103  //----------------------------------------------------------------------------
105  void begin()
106  {
107  fastPinMode(ClkPin, 1);
108  fastDigitalWrite(ClkPin, 0);
109  fastPinMode(CsPin, 1);
110  fastDigitalWrite(CsPin, 1);
111  fastPinMode(DoutPin, 0);
112  fastPinMode(DinPin, 1);
113  }
114  //----------------------------------------------------------------------------
118  inline __attribute__((always_inline))
119  uint16_t read(uint8_t config)
120  {
121  uint16_t v = 0;
122  fastDigitalWrite(CsPin, 0);
123  // Start bit.
124  writeBit(true);
125  // Mode bit.
126  writeBit(config & 2);
127  // Channel Selection and start sample.
128  writeBit(config & 1);
129  // Extra sample time.
130  if (UsecDelay) {
131  delayMicroseconds(UsecDelay);
132  }
133  // MSB first format and end sample.
134  writeBit(true);
135  // Null bit.
136  writeBit(true);
137  // Data bits.
138  readBit(v, 11);
139  readBit(v, 10);
140  readBit(v, 9);
141  readBit(v, 8);
142  readBit(v, 7);
143  readBit(v, 6);
144  readBit(v, 5);
145  readBit(v, 4);
146  readBit(v, 3);
147  readBit(v, 2);
148  readBit(v, 1);
149  readBit(v, 0);
150  fastDigitalWrite(CsPin, 1);
151  return v;
152  }
153 private:
154  //----------------------------------------------------------------------------
158  inline __attribute__((always_inline))
159  void delayCycles(uint8_t n)
160  {
161  if (n & 1) {
162  asm volatile("nop\n\t");
163  }
164  if (n & 2) {
165  asm volatile("nop\n\t" "nop\n\t");
166  }
167  if (n & 4) {
168  asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
169  }
170  }
171  //----------------------------------------------------------------------------
174  inline __attribute__((always_inline))
175  void writeBit(bool value)
176  {
177  fastDigitalWrite(DinPin, value);
178  fastDigitalWrite(ClkPin, 1);
179  delayCycles(2);
180  fastDigitalWrite(ClkPin, 0);
181  }
182  //----------------------------------------------------------------------------
183  inline __attribute__((always_inline))
184  void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
185  {
186  delayCycles(2);
187  fastDigitalWrite(ClkPin, 1);
188  delayCycles(delayRead);
189  if (fastDigitalRead(DoutPin)) {
190  v |= (1 << b);
191  }
192  fastDigitalWrite(ClkPin, 0);
193  }
194 };
195 //==============================================================================
196 template<uint8_t CsPin, uint8_t ClkPin,
197  uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
199 class MCP3204
200 {
201 public:
202  //----------------------------------------------------------------------------
204  void begin()
205  {
206  fastPinMode(ClkPin, 1);
207  fastDigitalWrite(ClkPin, 0);
208  fastPinMode(CsPin, 1);
209  fastDigitalWrite(CsPin, 1);
210  fastPinMode(DoutPin, 0);
211  fastPinMode(DinPin, 1);
212  }
213  //----------------------------------------------------------------------------
217  inline __attribute__((always_inline))
218  uint16_t read(uint8_t config)
219  {
220  uint16_t v = 0;
221  fastDigitalWrite(CsPin, 0);
222  // Start bit.
223  writeBit(true);
224  // Mode bit.
225  writeBit(config & 8);
226  // D2 channel bit.
227  writeBit(config & 4);
228  // D1 channel bit.
229  writeBit(config & 2);
230  // D0 channel bit and start sample.
231  writeBit(config & 1);
232  // Extra sample time.
233  if (UsecDelay) {
234  delayMicroseconds(UsecDelay);
235  }
236  // End sample cycle.
237  writeBit(true);
238  // Null bit.
239  writeBit(true);
240  // Data bits.
241  readBit(v, 11);
242  readBit(v, 10);
243  readBit(v, 9);
244  readBit(v, 8);
245  readBit(v, 7);
246  readBit(v, 6);
247  readBit(v, 5);
248  readBit(v, 4);
249  readBit(v, 3);
250  readBit(v, 2);
251  readBit(v, 1);
252  readBit(v, 0);
253  fastDigitalWrite(CsPin, 1);
254  return v;
255  }
256 private:
257  //----------------------------------------------------------------------------
261  inline __attribute__((always_inline))
262  void delayCycles(uint8_t n)
263  {
264  if (n & 1) {
265  asm volatile("nop\n\t");
266  }
267  if (n & 2) {
268  asm volatile("nop\n\t" "nop\n\t");
269  }
270  if (n & 4) {
271  asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
272  }
273  }
274  //----------------------------------------------------------------------------
277  inline __attribute__((always_inline))
278  void writeBit(bool value)
279  {
280  fastDigitalWrite(DinPin, value);
281  fastDigitalWrite(ClkPin, 1);
282  delayCycles(2);
283  fastDigitalWrite(ClkPin, 0);
284  }
285  //----------------------------------------------------------------------------
286  inline __attribute__((always_inline))
287  void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
288  {
289  delayCycles(2);
290  fastDigitalWrite(ClkPin, 1);
291  delayCycles(delayRead);
292  if (fastDigitalRead(DoutPin)) {
293  v |= (1 << b);
294  }
295  fastDigitalWrite(ClkPin, 0);
296  }
297 };
298 //==============================================================================
299 // MCP3204 and MCP3208 use the same code.
300 template<uint8_t CsPin, uint8_t ClkPin,
301  uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
302 class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay>
303 {
304 };
305 #endif // MCP320X_h
Definition: config.h:27
__attribute__((always_inline)) uint16_t read(uint8_t config)
Definition: MCP320X.h:118
Fast Digital I/O functions.
__attribute__((always_inline)) uint16_t read()
Definition: MCP320X.h:24
Definition: MCP320X.h:7
Definition: MCP320X.h:302
__attribute__((always_inline)) uint16_t read(uint8_t config)
Definition: MCP320X.h:217
Definition: MCP320X.h:199
Definition: MCP320X.h:100
void begin()
Definition: MCP320X.h:204
void begin()
Definition: MCP320X.h:12
void begin()
Definition: MCP320X.h:105