Extended MaximInterface
Dependents: mbed_DS28EC20_GPIO
Diff: Devices/DS2480B.cpp
- Revision:
- 6:a8c83a2e6fa4
- Parent:
- 3:f818ea5172ed
--- a/Devices/DS2480B.cpp Fri Jan 19 10:25:02 2018 -0600 +++ b/Devices/DS2480B.cpp Wed Jan 23 13:11:04 2019 -0600 @@ -160,516 +160,23 @@ #define PARMSET_PullUp3p0us 0x0C #define PARMSET_PullUp3p5us 0x0E +// Baud rate bits +#define PARMSET_9600 0x00 +#define PARMSET_19200 0x02 +#define PARMSET_57600 0x04 +#define PARMSET_115200 0x06 + // DS2480B program voltage available #define DS2480BPROG_MASK 0x20 namespace MaximInterface { error_code DS2480B::initialize() { - // reset modes level = NormalLevel; - baud = Baud9600bps; mode = MODSEL_COMMAND; - speed = SPEEDSEL_FLEX; - - // set the baud rate to 9600 - error_code result = setComBaud(baud); - if (result) { - return result; - } - - // send a break to reset the DS2480B - result = breakCom(); - if (result) { - return result; - } - - // delay to let line settle - (*sleep)(2); - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the timing byte - uint_least8_t packet[5]; - packet[0] = 0xC1; - result = uart->writeBlock(packet, 1); - if (result) { - return result; - } - - // delay to let line settle - (*sleep)(2); - - // set the FLEX configuration parameters - // default PDSRC = 1.37Vus - int packetLen = 0; - packet[packetLen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; - // default W1LT = 10us - packet[packetLen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us; - // default DSO/WORT = 8us - packet[packetLen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us; - - // construct the command to read the baud rate (to test command block) - packet[packetLen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); - - // also do 1 bit operation (to test 1-Wire block) - packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | baud | BITPOL_ONE; - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the response - result = uart->readBlock(packet, sizeof(packet) / sizeof(packet[0])); - if (result) { - return result; - } - - // look at the baud rate and bit operation - // to see if the response makes sense - if (!(((packet[3] & 0xF1) == 0x00) && ((packet[3] & 0x0E) == baud) && - ((packet[4] & 0xF0) == 0x90) && ((packet[4] & 0x0C) == baud))) { - result = make_error_code(HardwareError); - } - - return result; -} - -error_code DS2480B::reset() { - uint_least8_t packet[2]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // construct the command - packet[packetLen++] = (CMD_COMM | FUNCTSEL_RESET | speed); - - // flush the buffers - error_code result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the 1 byte response - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - // make sure this byte looks like a reset byte - if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) { - result = make_error_code(ShortDetectedError); - } - else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) { - result = make_error_code(NoSlaveError); - } - - return result; -} - -error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { - uint_least8_t packet[2]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // construct the command - packet[packetLen++] = (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | CMD_COMM | - FUNCTSEL_BIT | speed; - - // flush the buffers - error_code result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the response - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - // interpret the response - if ((packet[0] & 0xE0) == 0x80) { - sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE); - result = setLevel(afterLevel); - } else { - result = make_error_code(HardwareError); - } - - return result; -} - -error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - uint_least8_t packet[3]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // add the byte to send - packet[packetLen++] = sendByte; - - // check for duplication of data that looks like COMMAND mode - if (sendByte == MODE_COMMAND) { - packet[packetLen++] = sendByte; - } - - // flush the buffers - error_code result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the 1 byte response - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - if (packet[0] == sendByte) { - result = setLevel(afterLevel); - } else { - result = make_error_code(HardwareError); - } - - return result; -} - -error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - uint_least8_t packet[2]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // add the byte to send - packet[packetLen++] = 0xFF; - - // flush the buffers - error_code result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the 1 byte response - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - recvByte = packet[0]; - result = setLevel(afterLevel); - - return result; -} + speed = SPEEDSEL_STD; -error_code DS2480B::setSpeed(Speed newSpeed) { - error_code result; - bool setSpeed = false; - - // check if supported speed - switch (newSpeed) { - case OverdriveSpeed: - // check if change from current mode - if (speed != SPEEDSEL_OD) { - result = changeBaud(Baud115200bps); - if (!result) { - speed = SPEEDSEL_OD; - setSpeed = true; - } - } - break; - - case StandardSpeed: - // check if change from current mode - if (speed != SPEEDSEL_STD) { - result = changeBaud(Baud9600bps); - if (!result) { - speed = SPEEDSEL_STD; - setSpeed = true; - } - } - break; - - default: - result = make_error_code(InvalidSpeedError); - break; - } - - // if baud rate is set correctly then change DS2480 speed - if (setSpeed) { - uint_least8_t packet[2]; - int packetLen = 0; - - // check if correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // proceed to set the DS2480 communication speed - packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed; - - // send the packet - result = uart->writeBlock(packet, packetLen); - } - - return result; -} - -error_code DS2480B::setLevel(Level newLevel) { - error_code result; - // check if need to change level - if (newLevel != level) { - uint_least8_t packet[4]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - switch (newLevel) { - case NormalLevel: - // stop pulse command - packet[packetLen++] = MODE_STOP_PULSE; - - // add the command to begin the pulse WITHOUT prime - packet[packetLen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | - BITPOL_5V | PRIME5V_FALSE; - - // stop pulse command - packet[packetLen++] = MODE_STOP_PULSE; - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the 1 byte response - result = uart->readBlock(packet, 2); - if (result) { - return result; - } - - // check response byte - if (((packet[0] & 0xE0) == 0xE0) && ((packet[1] & 0xE0) == 0xE0)) { - level = NormalLevel; - } else { - result = make_error_code(HardwareError); - } - break; - - case StrongLevel: - // set the SPUD time value - packet[packetLen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; - // add the command to begin the pulse - packet[packetLen++] = - CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V; - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // read back the 1 byte response from setting time limit - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - // check response byte - if ((packet[0] & 0x81) == 0) { - level = newLevel; - } else { - result = make_error_code(HardwareError); - } - break; - - default: - result = make_error_code(InvalidLevelError); - break; - } - } - return result; -} - -error_code DS2480B::sendCommand(uint_least8_t command) { - uint_least8_t packet[2]; - int packetLen = 0; - - // check for correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // add command - packet[packetLen++] = command; - - // send the packet - return uart->writeBlock(packet, packetLen); -} - -error_code DS2480B::changeBaud(BaudRate newBaud) { - error_code result; - - //see if different then current baud rate - if (baud != newBaud) { - uint_least8_t packet[2]; - int packetLen = 0; - - // build the command packet - // check for correct mode - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - // build the command - const uint_least8_t baudByte = CMD_CONFIG | PARMSEL_BAUDRATE | newBaud; - packet[packetLen++] = baudByte; - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, packetLen); - if (result) { - return result; - } - - // make sure buffer is flushed - (*sleep)(5); - - // change our baud rate - result = setComBaud(newBaud); - if (result) { - return result; - } - baud = newBaud; - - // wait for things to settle - (*sleep)(5); - - // build a command packet to read back baud rate - packet[0] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); - - // flush the buffers - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // send the packet - result = uart->writeBlock(packet, 1); - if (result) { - return result; - } - - // read back the 1 byte response - result = uart->readBlock(packet, 1); - if (result) { - return result; - } - - // verify correct baud - if (!((packet[0] & 0x0E) == (baudByte & 0x0E))) { - result = make_error_code(HardwareError); - } - } - - return result; -} - -error_code DS2480B::setComBaud(BaudRate newBaud) { - switch (newBaud) { - case Baud115200bps: - return uart->setBaudRate(115200); - - case Baud57600bps: - return uart->setBaudRate(57600); - - case Baud19200bps: - return uart->setBaudRate(19200); - - case Baud9600bps: - default: - return uart->setBaudRate(9600); - } -} - -error_code DS2480B::breakCom() { + // Send a break to reset the DS2480B. // Switch to lower baud rate to ensure break is longer than 2 ms. error_code result = uart->setBaudRate(4800); if (result) { @@ -679,10 +186,358 @@ if (result) { return result; } - result = setComBaud(baud); + result = uart->setBaudRate(9600); + if (result) { + return result; + } + + // Wait for master reset. + sleep->invoke(1); + + // Flush the read buffer. + result = uart->clearReadBuffer(); + if (result) { + return result; + } + + // Send the timing byte. + result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD); + if (result) { + return result; + } + + // Change the DS2480 baud rate. + result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200); + if (result) { + return result; + } + + // Change our baud rate. + result = uart->setBaudRate(115200); + if (result) { + return result; + } + + uint_least8_t response; + + // Verify response. + result = uart->readByte(response); + if (result) { + return result; + } + if ((response & (PARMSEL_MASK | PARMSET_MASK)) != + (PARMSEL_BAUDRATE | PARMSET_115200)) { + return make_error_code(HardwareError); + } + + // Set the SPUD time value. + result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite); + if (result) { + return result; + } + + // Verify response. + result = uart->readByte(response); + if (result) { + return result; + } + if ((response & (PARMSEL_MASK | PARMSET_MASK)) != + (PARMSEL_5VPULSE | PARMSET_infinite)) { + return make_error_code(HardwareError); + } + + return result; +} + +error_code DS2480B::reset() { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Construct the command. + packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed; + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Make sure this byte looks like a reset byte. + if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) { + result = make_error_code(ShortDetectedError); + } else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) { + result = make_error_code(NoSlaveError); + } + return result; +} + +error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[3]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Construct the command. + packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | + (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed; + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + // Add the command to begin the pulse. + packet[packetLen++] = + CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; + break; + + default: + return make_error_code(InvalidLevelError); + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if ((packet[0] & 0xE0) == 0x80) { + sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE); + level = afterLevel; + } else { + result = make_error_code(HardwareError); + } return result; } +error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + return OneWireMaster::writeByteSetLevel(sendByte, afterLevel); + + default: + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[3]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_DATA) { + mode = MODSEL_DATA; + packet[packetLen++] = MODE_DATA; + } + + // Add the byte to send. + packet[packetLen++] = sendByte; + + // Check for duplication of data that looks like COMMAND mode. + if (sendByte == MODE_COMMAND) { + packet[packetLen++] = sendByte; + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if (packet[0] != sendByte) { + result = make_error_code(HardwareError); + } + return result; +} + +error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + return OneWireMaster::readByteSetLevel(recvByte, afterLevel); + + default: + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_DATA) { + mode = MODSEL_DATA; + packet[packetLen++] = MODE_DATA; + } + + // Add the byte to send. + packet[packetLen++] = 0xFF; + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(recvByte); + return result; +} + +error_code DS2480B::setSpeed(Speed newSpeed) { + uint_least8_t newSpeedByte; + switch (newSpeed) { + case OverdriveSpeed: + newSpeedByte = SPEEDSEL_OD; + break; + + case StandardSpeed: + newSpeedByte = SPEEDSEL_STD; + break; + + default: + return make_error_code(InvalidSpeedError); + } + if (speed == newSpeedByte) { + return error_code(); + } + speed = newSpeedByte; + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Change DS2480 speed. + packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed; + + // Send the packet. + return uart->writeBlock(make_span(packet, packetLen)); +} + +error_code DS2480B::setLevel(Level newLevel) { + if (level == newLevel) { + return error_code(); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + switch (newLevel) { + case NormalLevel: + // Stop pulse command. + packet[packetLen++] = MODE_STOP_PULSE; + break; + + case StrongLevel: + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Add the command to begin the pulse. + packet[packetLen++] = + CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; + break; + + default: + return make_error_code(InvalidLevelError); + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + if (newLevel == NormalLevel) { + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if ((packet[0] & 0xE0) != 0xE0) { + return make_error_code(HardwareError); + } + } + + level = newLevel; + return result; +} + +error_code DS2480B::sendCommand(uint_least8_t command) { + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Add command. + packet[packetLen++] = command; + + // Send the packet. + return uart->writeBlock(make_span(packet, packetLen)); +} + const error_category & DS2480B::errorCategory() { static class : public error_category { public: