#pragma once //ThreeWire command Read/Write flag const uint8_t THREEWIRE_READFLAG = 0x01; class ThreeWire { public: ThreeWire(uint8_t ioPin, uint8_t clkPin, uint8_t cePin) : _ioPin(ioPin), _clkPin(clkPin), _cePin(cePin) { } void begin() { resetPins(); } void end() { resetPins(); } void beginTransmission(uint8_t command) { digitalWrite(_cePin, LOW); // default, not enabled pinMode(_cePin, OUTPUT); digitalWrite(_clkPin, LOW); // default, clock low pinMode(_clkPin, OUTPUT); pinMode(_ioPin, OUTPUT); digitalWrite(_cePin, HIGH); // start the session delayMicroseconds(4); // tCC = 4us write(command, (command & THREEWIRE_READFLAG) == THREEWIRE_READFLAG); } void endTransmission() { digitalWrite(_cePin, LOW); delayMicroseconds(4); // tCWH = 4us } void write(uint8_t value, bool isDataRequestCommand = false) { for (uint8_t bit = 0; bit < 8; bit++) { digitalWrite(_ioPin, value & 0x01); delayMicroseconds(1); // tDC = 200ns // clock up, data is read by DS1302 digitalWrite(_clkPin, HIGH); delayMicroseconds(1); // tCH = 1000ns, tCDH = 800ns // for the last bit before a read // Set IO line for input before the clock down if (bit == 7 && isDataRequestCommand) { pinMode(_ioPin, INPUT); } digitalWrite(_clkPin, LOW); delayMicroseconds(1); // tCL=1000ns, tCDD=800ns value >>= 1; } } uint8_t read() { uint8_t value = 0; for (uint8_t bit = 0; bit < 8; bit++) { // first bit is present on io pin, so only clock the other // bits value |= (digitalRead(_ioPin) << bit); // Clock up, prepare for next digitalWrite(_clkPin, HIGH); delayMicroseconds(1); // Clock down, value is ready after some time. digitalWrite(_clkPin, LOW); delayMicroseconds(1); // tCL=1000ns, tCDD=800ns } return value; } private: const uint8_t _ioPin; const uint8_t _clkPin; const uint8_t _cePin; void resetPins() { // just making sure they are in a default low power use state // as required state is set when transmissions are started // three wire devices have internal pull downs so they will be low pinMode(_clkPin, INPUT); pinMode(_ioPin, INPUT); pinMode(_cePin, INPUT); } };