Upgraded RF24 to latest version which supports SoftSPI. Added DigitalIO and UTFT libraries to support the new example. Fix problem reported in RelayWithButtonActuator example.
126 lines
3.9 KiB
C++
126 lines
3.9 KiB
C++
#ifndef MCP355X_h
|
|
#define MCP355X_h
|
|
#include <DigitalIO.h>
|
|
// Overflow values.
|
|
const int32_t MCP355X_OVH = 2097152L;
|
|
const int32_t MCP355X_OVL = -2097153L;
|
|
const int32_t MCP355X_ERR = 0X80000000;
|
|
const uint8_t MCP355X_TO_MS = 100;
|
|
//==============================================================================
|
|
template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin>
|
|
class MCP355X {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/** Set pin modes and initial levels. */
|
|
void begin(bool singleMode = true) {
|
|
m_singleMode = singleMode;
|
|
fastPinMode(SdoPin, 0);
|
|
fastPinMode(SckPin, 1);
|
|
fastDigitalWrite(SckPin, 1);
|
|
fastPinMode(CsPin, 1);
|
|
fastDigitalWrite(CsPin, 1);
|
|
if (!m_singleMode) {
|
|
// Wait for conversion to complete.
|
|
delay(100);
|
|
// Start continuous conversion mode.
|
|
fastDigitalWrite(CsPin, 0);
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Read MCP355X 22-bit ADC
|
|
* \return 22-bit value.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
int32_t read() {
|
|
uint8_t t = 0;
|
|
uint8_t v3 = 0;
|
|
if (m_singleMode) {
|
|
// Start conversion.
|
|
fastDigitalWrite(CsPin, 0);
|
|
// Delay at least 10 usec to avoid RDY glitch on exit from Shutdown.
|
|
delay(1);
|
|
// Toggle CsPin to indicate single conversion mode.
|
|
fastDigitalWrite(CsPin, 1);
|
|
// Wait for conversion to complete.
|
|
while (1) {
|
|
delay(1);
|
|
fastDigitalWrite(CsPin, 0);
|
|
// Delay while RDY settles.
|
|
delayCycles(4);
|
|
if (!fastDigitalRead(SdoPin)) break;
|
|
fastDigitalWrite(CsPin, 1);
|
|
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
|
}
|
|
} else {
|
|
while (1) {
|
|
if (!fastDigitalRead(SdoPin)) break;
|
|
delay(1);
|
|
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
|
}
|
|
}
|
|
uint8_t v2 = readByte();
|
|
uint8_t v1 = readByte();
|
|
uint8_t v0 = readByte();
|
|
|
|
// The 25th falling edge of SCK changes SDO/RDY from Data mode to RDY mode.
|
|
uint8_t dummy = 0;
|
|
readBit(dummy, 0);
|
|
|
|
if (m_singleMode) {
|
|
fastDigitalWrite(CsPin, 1);
|
|
}
|
|
if ((v2 & 0XE0) == 0X20) {
|
|
// Negative in range so extend sign bit.
|
|
v2 |= 0XC0;
|
|
v3 = 0XFF;
|
|
} else if (v2 & 0X40) {
|
|
// Overflow high. Cause value to be >= MCP355X_OVH.
|
|
if (v2 & 0X20) v2 &= 0X3F;
|
|
} else if (v2 & 0X80) {
|
|
// Overflow low. Cause value to be <= MCP355X_OVH.
|
|
if ((v2 & 0X20) == 0) v2 |= 0X40;
|
|
v3 = 0XFF;
|
|
}
|
|
uint16_t v_high = (v3 << 8) | v2;
|
|
uint16_t v_low = (v1 << 8) | v0;
|
|
return ((uint32_t)v_high << 16) | v_low;
|
|
}
|
|
private:
|
|
//----------------------------------------------------------------------------
|
|
/** delay n nops
|
|
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
void delayCycles(uint8_t n) {
|
|
if (n & 1) asm volatile("nop\n\t");
|
|
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
|
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
// Default delay yields about 2 MHz clock.
|
|
inline __attribute__((always_inline))
|
|
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) {
|
|
fastDigitalWrite(SckPin, 0);
|
|
delayCycles(2 + delayRead);
|
|
fastDigitalWrite(SckPin, 1);
|
|
if (fastDigitalRead(SdoPin)) v |= (1 << b);
|
|
delayCycles(delayRead);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
uint8_t readByte() {
|
|
uint8_t v = 0;
|
|
readBit(v, 7);
|
|
readBit(v, 6);
|
|
readBit(v, 5);
|
|
readBit(v, 4);
|
|
readBit(v, 3);
|
|
readBit(v, 2);
|
|
readBit(v, 1);
|
|
readBit(v, 0);
|
|
return v;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
bool m_singleMode;
|
|
};
|
|
#endif // MCP355X_h
|