MySensors Library & Examples  2.3.1
MCP355X.h
1 #ifndef MCP355X_h
2 #define MCP355X_h
3 #include <DigitalIO.h>
4 // Overflow values.
5 const int32_t MCP355X_OVH = 2097152L;
6 const int32_t MCP355X_OVL = -2097153L;
7 const int32_t MCP355X_ERR = 0X80000000;
8 const uint8_t MCP355X_TO_MS = 100;
9 //==============================================================================
10 template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin>
12 class MCP355X
13 {
14 public:
15  //----------------------------------------------------------------------------
17  void begin(bool singleMode = true)
18  {
19  m_singleMode = singleMode;
20  fastPinMode(SdoPin, 0);
21  fastPinMode(SckPin, 1);
22  fastDigitalWrite(SckPin, 1);
23  fastPinMode(CsPin, 1);
24  fastDigitalWrite(CsPin, 1);
25  if (!m_singleMode) {
26  // Wait for conversion to complete.
27  delay(100);
28  // Start continuous conversion mode.
29  fastDigitalWrite(CsPin, 0);
30  }
31  }
32  //----------------------------------------------------------------------------
36  inline __attribute__((always_inline))
37  int32_t read()
38  {
39  uint8_t t = 0;
40  uint8_t v3 = 0;
41  if (m_singleMode) {
42  // Start conversion.
43  fastDigitalWrite(CsPin, 0);
44  // Delay at least 10 usec to avoid RDY glitch on exit from Shutdown.
45  delay(1);
46  // Toggle CsPin to indicate single conversion mode.
47  fastDigitalWrite(CsPin, 1);
48  // Wait for conversion to complete.
49  while (1) {
50  delay(1);
51  fastDigitalWrite(CsPin, 0);
52  // Delay while RDY settles.
53  delayCycles(4);
54  if (!fastDigitalRead(SdoPin)) {
55  break;
56  }
57  fastDigitalWrite(CsPin, 1);
58  if (t++ > MCP355X_TO_MS) {
59  return MCP355X_ERR;
60  }
61  }
62  } else {
63  while (1) {
64  if (!fastDigitalRead(SdoPin)) {
65  break;
66  }
67  delay(1);
68  if (t++ > MCP355X_TO_MS) {
69  return MCP355X_ERR;
70  }
71  }
72  }
73  uint8_t v2 = readByte();
74  uint8_t v1 = readByte();
75  uint8_t v0 = readByte();
76 
77  // The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode.
78  uint8_t dummy = 0;
79  readBit(dummy, 0);
80 
81  if (m_singleMode) {
82  fastDigitalWrite(CsPin, 1);
83  }
84  if ((v2 & 0XE0) == 0X20) {
85  // Negative in range so extend sign bit.
86  v2 |= 0XC0;
87  v3 = 0XFF;
88  } else if (v2 & 0X40) {
89  // Overflow high. Cause value to be >= MCP355X_OVH.
90  if (v2 & 0X20) {
91  v2 &= 0X3F;
92  }
93  } else if (v2 & 0X80) {
94  // Overflow low. Cause value to be <= MCP355X_OVH.
95  if ((v2 & 0X20) == 0) {
96  v2 |= 0X40;
97  }
98  v3 = 0XFF;
99  }
100  uint16_t v_high = (v3 << 8) | v2;
101  uint16_t v_low = (v1 << 8) | v0;
102  return ((uint32_t)v_high << 16) | v_low;
103  }
104 private:
105  //----------------------------------------------------------------------------
109  inline __attribute__((always_inline))
110  void delayCycles(uint8_t n)
111  {
112  if (n & 1) {
113  asm volatile("nop\n\t");
114  }
115  if (n & 2) {
116  asm volatile("nop\n\t" "nop\n\t");
117  }
118  if (n & 4) {
119  asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
120  }
121  }
122  //----------------------------------------------------------------------------
123  // Default delay yields about 2 MHz clock.
124  inline __attribute__((always_inline))
125  void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0)
126  {
127  fastDigitalWrite(SckPin, 0);
128  delayCycles(2 + delayRead);
129  fastDigitalWrite(SckPin, 1);
130  if (fastDigitalRead(SdoPin)) {
131  v |= (1 << b);
132  }
133  delayCycles(delayRead);
134  }
135  //----------------------------------------------------------------------------
136  inline __attribute__((always_inline))
137  uint8_t readByte()
138  {
139  uint8_t v = 0;
140  readBit(v, 7);
141  readBit(v, 6);
142  readBit(v, 5);
143  readBit(v, 4);
144  readBit(v, 3);
145  readBit(v, 2);
146  readBit(v, 1);
147  readBit(v, 0);
148  return v;
149  }
150  //----------------------------------------------------------------------------
151  bool m_singleMode;
152 };
153 #endif // MCP355X_h
Fast Digital I/O functions.
Definition: MCP355X.h:12
void begin(bool singleMode=true)
Definition: MCP355X.h:17
__attribute__((always_inline)) int32_t read()
Definition: MCP355X.h:36