Upgraded RF24 to latest version which supports SoftSPI. Added DigitalIO and UTFT libraries to support the new example. Fix problem reported in RelayWithButtonActuator example.
259 lines
7.9 KiB
C++
259 lines
7.9 KiB
C++
#ifndef MCP320X_h
|
|
#define MCP320X_h
|
|
#include <DigitalIO.h>
|
|
//==============================================================================
|
|
template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0>
|
|
class MCP3201 {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/** Set pin modes and initial levels. */
|
|
void begin() {
|
|
fastPinMode(ClkPin, 1);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
fastPinMode(CsPin, 1);
|
|
fastDigitalWrite(CsPin, 1);
|
|
fastPinMode(DoutPin, 0);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Read MCP3201 12-bit ADC
|
|
* \return 16-bit value read.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
uint16_t read() {
|
|
fastDigitalWrite(CsPin, 0);
|
|
// Start sample.
|
|
mcpAdcDummy(3);
|
|
// Extra sample time.
|
|
if (UsecDelay){
|
|
delayMicroseconds(UsecDelay);
|
|
}
|
|
// End sample.
|
|
mcpAdcDummy(3);
|
|
// Null bit.
|
|
mcpAdcDummy(3);
|
|
uint16_t v = 0;
|
|
readBit(v, 11);
|
|
readBit(v, 10);
|
|
readBit(v, 9);
|
|
readBit(v, 8);
|
|
readBit(v, 7);
|
|
readBit(v, 6);
|
|
readBit(v, 5);
|
|
readBit(v, 4);
|
|
readBit(v, 3);
|
|
readBit(v, 2);
|
|
readBit(v, 1);
|
|
readBit(v, 0);
|
|
fastDigitalWrite(CsPin, 1);
|
|
return v;
|
|
}
|
|
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");
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** clock for don't care bits
|
|
*\param[in] delayBefore if true, delay before raising clock*/
|
|
inline __attribute__((always_inline))
|
|
void mcpAdcDummy(uint8_t delayBefore) {
|
|
delayCycles(delayBefore);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(3);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) {
|
|
delayCycles(3);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(delayRead);
|
|
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
};
|
|
//==============================================================================
|
|
template<uint8_t CsPin, uint8_t ClkPin,
|
|
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
|
class MCP3202 {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/** Set pin modes and initial levels. */
|
|
void begin() {
|
|
fastPinMode(ClkPin, 1);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
fastPinMode(CsPin, 1);
|
|
fastDigitalWrite(CsPin, 1);
|
|
fastPinMode(DoutPin, 0);
|
|
fastPinMode(DinPin, 1);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Read MCP3202 12-bit ADC
|
|
* \return 16-bit value read.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
uint16_t read(uint8_t config) {
|
|
uint16_t v = 0;
|
|
fastDigitalWrite(CsPin, 0);
|
|
// Start bit.
|
|
writeBit(true);
|
|
// Mode bit.
|
|
writeBit(config & 2);
|
|
// Channel Selection and start sample.
|
|
writeBit(config & 1);
|
|
// Extra sample time.
|
|
if (UsecDelay){
|
|
delayMicroseconds(UsecDelay);
|
|
}
|
|
// MSB first format and end sample.
|
|
writeBit(true);
|
|
// Null bit.
|
|
writeBit(true);
|
|
// Data bits.
|
|
readBit(v, 11);
|
|
readBit(v, 10);
|
|
readBit(v, 9);
|
|
readBit(v, 8);
|
|
readBit(v, 7);
|
|
readBit(v, 6);
|
|
readBit(v, 5);
|
|
readBit(v, 4);
|
|
readBit(v, 3);
|
|
readBit(v, 2);
|
|
readBit(v, 1);
|
|
readBit(v, 0);
|
|
fastDigitalWrite(CsPin, 1);
|
|
return v;
|
|
}
|
|
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");
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** clock for don't care bits
|
|
*\param[in] delayBefore if true, delay before raising clock*/
|
|
inline __attribute__((always_inline))
|
|
void writeBit(bool value) {
|
|
fastDigitalWrite(DinPin, value);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(2);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
|
delayCycles(2);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(delayRead);
|
|
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
};
|
|
//==============================================================================
|
|
template<uint8_t CsPin, uint8_t ClkPin,
|
|
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
|
class MCP3204 {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/** Set pin modes and initial levels. */
|
|
void begin() {
|
|
fastPinMode(ClkPin, 1);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
fastPinMode(CsPin, 1);
|
|
fastDigitalWrite(CsPin, 1);
|
|
fastPinMode(DoutPin, 0);
|
|
fastPinMode(DinPin, 1);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Read MCP3204 12-bit ADC
|
|
* \return 16-bit value read.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
uint16_t read(uint8_t config) {
|
|
uint16_t v = 0;
|
|
fastDigitalWrite(CsPin, 0);
|
|
// Start bit.
|
|
writeBit(true);
|
|
// Mode bit.
|
|
writeBit(config & 8);
|
|
// D2 channel bit.
|
|
writeBit(config & 4);
|
|
// D1 channel bit.
|
|
writeBit(config & 2);
|
|
// D0 channel bit and start sample.
|
|
writeBit(config & 1);
|
|
// Extra sample time.
|
|
if (UsecDelay){
|
|
delayMicroseconds(UsecDelay);
|
|
}
|
|
// End sample cycle.
|
|
writeBit(true);
|
|
// Null bit.
|
|
writeBit(true);
|
|
// Data bits.
|
|
readBit(v, 11);
|
|
readBit(v, 10);
|
|
readBit(v, 9);
|
|
readBit(v, 8);
|
|
readBit(v, 7);
|
|
readBit(v, 6);
|
|
readBit(v, 5);
|
|
readBit(v, 4);
|
|
readBit(v, 3);
|
|
readBit(v, 2);
|
|
readBit(v, 1);
|
|
readBit(v, 0);
|
|
fastDigitalWrite(CsPin, 1);
|
|
return v;
|
|
}
|
|
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");
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** clock for don't care bits
|
|
*\param[in] delayBefore if true, delay before raising clock*/
|
|
inline __attribute__((always_inline))
|
|
void writeBit(bool value) {
|
|
fastDigitalWrite(DinPin, value);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(2);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
|
delayCycles(2);
|
|
fastDigitalWrite(ClkPin, 1);
|
|
delayCycles(delayRead);
|
|
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
|
fastDigitalWrite(ClkPin, 0);
|
|
}
|
|
};
|
|
//==============================================================================
|
|
// MCP3204 and MCP3208 use the same code.
|
|
template<uint8_t CsPin, uint8_t ClkPin,
|
|
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
|
class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay> {
|
|
};
|
|
#endif // MCP320X_h
|