Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

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: