Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_DS28EC20_GPIO
Revision 8:211d1b8f730c, committed 2019-04-03
- Comitter:
- reARMnimator
- Date:
- Wed Apr 03 12:33:10 2019 +0000
- Parent:
- 5:3523abdda8ed
- Parent:
- 7:471901a04573
- Child:
- 9:aeda90624ad0
- Commit message:
- Merge with version 1.7;
Changed in this revision
--- a/CMakeLists.txt Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-#[[*****************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-******************************************************************************]]
-
-cmake_minimum_required(VERSION 3.10)
-
-include("clr.cmake")
-
-project("MaximInterface" VERSION 1.1)
-option(BUILD_SHARED_LIBS "Build ${CMAKE_PROJECT_NAME} as a shared library." ON)
-set(MaximInterface_Platforms "" CACHE STRING
- "List of platforms to build. Available platforms are dotnet and Qt.")
-
-if("dotnet" IN_LIST MaximInterface_Platforms)
- # Require shared library for the dotnet platform.
- if(NOT BUILD_SHARED_LIBS)
- message(SEND_ERROR "BUILD_SHARED_LIBS must be enabled to build the dotnet platform.")
- endif()
-
- # Initialize CLR compilation flags that all targets should use.
- initializeClr()
-endif()
-
-# Search in parent directory for includes.
-get_filename_component(baseIncludeDir ${CMAKE_SOURCE_DIR} DIRECTORY)
-include_directories(${baseIncludeDir})
-
-# Prepend a path to all items in a list.
-macro(prependPath var path)
- unset(${var})
- foreach(arg ${ARGN})
- list(APPEND ${var} "${path}/${arg}")
- endforeach()
-endmacro(prependPath)
-
-# Add base components.
-set(resourceDirs "Devices" "Links" "Utilities")
-prependPath(DevicesSources "Devices"
- "DS18B20.cpp"
- "DS28C36_DS2476.cpp"
- "DS28E15_22_25.cpp"
- "DS28E17.cpp"
- "DS28E38.cpp"
- "DS1920.cpp"
- "DS2413.cpp"
- "DS2431.cpp"
- "DS2465.cpp"
- "DS2480B.cpp"
- "DS2482_DS2484.cpp"
- "DS9400.cpp"
- "DS9481P_300.cpp")
-prependPath(LinksSources "Links"
- "I2CMaster.cpp"
- "I2CMasterDecorator.cpp"
- "LoggingI2CMaster.cpp"
- "LoggingOneWireMaster.cpp"
- "LoggingSleep.cpp"
- "OneWireMaster.cpp"
- "OneWireMasterDecorator.cpp"
- "RomCommands.cpp"
- "SelectRom.cpp"
- "SleepDecorator.cpp"
- "Uart.cpp")
-prependPath(UtilitiesSources "Utilities"
- "crc.cpp"
- "Ecc256.cpp"
- "Error.cpp"
- "HexConversions.cpp"
- "system_error.cpp")
-add_library(${CMAKE_PROJECT_NAME} ${DevicesSources} ${LinksSources} ${UtilitiesSources})
-
-# Add selected platforms.
-foreach(platform ${MaximInterface_Platforms})
- if(platform STREQUAL "dotnet")
- # Add CLR support to target.
- enableClr(${CMAKE_PROJECT_NAME} "v4.5"
- "System.dll"
- "${CMAKE_SOURCE_DIR}/Platforms/dotnet/OneWireLinkLayer/OneWireLinkLayer.dll")
-
- # Add files to top-level target since CLR objects do not support static linking.
- list(APPEND resourceDirs "Platforms/dotnet")
- prependPath(dotnetSources "Platforms/dotnet"
- "OneWireLinkLayerMaster.cpp"
- "SerialPort.cpp"
- "Sleep.cpp")
- target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${dotnetSources})
- elseif(platform STREQUAL "Qt")
- find_package(Qt5 COMPONENTS Core SerialPort)
- list(APPEND resourceDirs "Platforms/Qt")
- prependPath(QtSources "Platforms/Qt"
- "SerialPort.cpp"
- "Sleep.cpp")
- add_library(Qt OBJECT ${QtSources})
- target_include_directories(Qt PRIVATE ${Qt5Core_INCLUDE_DIRS} ${Qt5SerialPort_INCLUDE_DIRS})
- target_sources(${CMAKE_PROJECT_NAME} PRIVATE $<TARGET_OBJECTS:Qt>)
- target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Qt5::Core Qt5::SerialPort)
- else()
- message(SEND_ERROR "\"${platform}\" is not a supported platform.")
- endif()
-endforeach()
-
-# Set up build and install exports.
-target_include_directories(${CMAKE_PROJECT_NAME} INTERFACE
- $<BUILD_INTERFACE:${baseIncludeDir}>
- $<INSTALL_INTERFACE:.>)
-foreach(resourceDir ${resourceDirs})
- get_filename_component(resourceInstallDir "${CMAKE_PROJECT_NAME}/${resourceDir}" DIRECTORY)
- install(DIRECTORY ${resourceDir} DESTINATION ${resourceInstallDir}
- FILES_MATCHING PATTERN "*.h*" PATTERN "*.dll")
-endforeach()
-install(TARGETS ${CMAKE_PROJECT_NAME} EXPORT "${CMAKE_PROJECT_NAME}Config"
- ARCHIVE DESTINATION $<CONFIG>
- LIBRARY DESTINATION $<CONFIG>
- RUNTIME DESTINATION $<CONFIG>)
-install(EXPORT "${CMAKE_PROJECT_NAME}Config" DESTINATION "cmake")
-export(TARGETS ${CMAKE_PROJECT_NAME} FILE "${CMAKE_PROJECT_NAME}Config.cmake")
-
-# Set up source groups.
-get_property(${CMAKE_PROJECT_NAME}Sources TARGET ${CMAKE_PROJECT_NAME} PROPERTY SOURCES)
-source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${${CMAKE_PROJECT_NAME}Sources})
\ No newline at end of file
--- a/Devices/DS18B20.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS18B20.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,27 +36,22 @@
namespace MaximInterface {
-enum DS18B20_CMDS {
- WRITE_SCRATCHPAD = 0x4E,
- READ_SCRATCHPAD = 0xBE,
- COPY_SCRATCHPAD = 0x48,
- CONV_TEMPERATURE = 0x44,
- READ_POWER_SUPPY = 0xB4,
- RECALL = 0xB8
-};
+const uint_least8_t DS18B20::nineBitResolution;
+const uint_least8_t DS18B20::tenBitResolution;
+const uint_least8_t DS18B20::elevenBitResolution;
+const uint_least8_t DS18B20::twelveBitResolution;
error_code DS18B20::initialize() {
- Scratchpad scratchpad;
+ Scratchpad::array scratchpad;
return readScratchpad(scratchpad);
}
error_code DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl,
- uint_least8_t res) {
+ uint_least8_t res) {
error_code result = selectRom(*master);
if (!result) {
- const uint_least8_t sendBlock[] = {WRITE_SCRATCHPAD, th, tl, res};
- result =
- master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
+ const uint_least8_t sendBlock[] = {0x4E, th, tl, res};
+ result = master->writeBlock(sendBlock);
if (!result) {
resolution = res;
}
@@ -64,17 +59,16 @@
return result;
}
-error_code DS18B20::readScratchpad(Scratchpad & scratchpad) {
+error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) {
error_code result = selectRom(*master);
if (result) {
return result;
}
- result =
- master->writeByteSetLevel(READ_SCRATCHPAD, OneWireMaster::NormalLevel);
+ result = master->writeByte(0xBE);
if (result) {
return result;
}
- result = master->readBlock(scratchpad.data(), scratchpad.size());
+ result = master->readBlock(scratchpad);
if (result) {
return result;
}
@@ -83,7 +77,7 @@
if (result) {
return result;
}
- if (receivedCrc == calculateCrc8(scratchpad.data(), scratchpad.size())) {
+ if (receivedCrc == calculateCrc8(scratchpad)) {
resolution = scratchpad[4];
} else {
result = make_error_code(CrcError);
@@ -91,21 +85,22 @@
return result;
}
-error_code DS18B20::readPowerSupply(bool & localPower) {
+error_code DS18B20::readPowerSupply(bool & localPower) {
error_code result = selectRom(*master);
if (result) {
return result;
}
- result =
- master->writeByteSetLevel(READ_POWER_SUPPY, OneWireMaster::NormalLevel);
+ result = master->writeByte(0xB4);
if (result) {
return result;
}
- result = master->touchBitSetLevel(localPower, OneWireMaster::NormalLevel);
+ result = master->touchBit(localPower);
return result;
}
error_code DS18B20::copyScratchpad() {
+ const uint_least8_t copyScratchpadCmd = 0x48;
+
bool hasLocalPower;
error_code result = readPowerSupply(hasLocalPower);
if (result) {
@@ -116,17 +111,16 @@
return result;
}
if (hasLocalPower) {
- result =
- master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::NormalLevel);
+ result = master->writeByte(copyScratchpadCmd);
bool recvbit = 0;
while (!recvbit && !result) {
- result = master->touchBitSetLevel(recvbit, OneWireMaster::NormalLevel);
+ result = master->touchBit(recvbit);
}
} else {
- result =
- master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::StrongLevel);
+ result = master->writeByteSetLevel(copyScratchpadCmd,
+ OneWireMaster::StrongLevel);
if (!result) {
- (*sleep)(10);
+ sleep->invoke(10);
result = master->setLevel(OneWireMaster::NormalLevel);
}
}
@@ -134,6 +128,8 @@
}
error_code DS18B20::convertTemperature() {
+ const uint_least8_t convertTemperatureCmd = 0x44;
+
bool hasLocalPower;
error_code result = readPowerSupply(hasLocalPower);
if (result) {
@@ -144,15 +140,14 @@
return result;
}
if (hasLocalPower) {
- result =
- master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::NormalLevel);
+ result = master->writeByte(convertTemperatureCmd);
bool recvbit = 0;
while (!result && !recvbit) {
- result = master->touchBitSetLevel(recvbit, OneWireMaster::NormalLevel);
+ result = master->touchBit(recvbit);
}
} else {
- result =
- master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::StrongLevel);
+ result = master->writeByteSetLevel(convertTemperatureCmd,
+ OneWireMaster::StrongLevel);
if (!result) {
int sleepTime;
switch (resolution) {
@@ -173,17 +168,17 @@
sleepTime = 750;
break;
}
- (*sleep)(sleepTime);
+ sleep->invoke(sleepTime);
result = master->setLevel(OneWireMaster::NormalLevel);
}
}
return result;
}
-error_code DS18B20::recallEeprom() {
+error_code DS18B20::recallEeprom() {
error_code result = selectRom(*master);
if (!result) {
- result = master->writeByte(RECALL);
+ result = master->writeByte(0xB8);
}
return result;
}
@@ -214,13 +209,13 @@
if (result) {
return result;
}
- DS18B20::Scratchpad scratchpad;
+ DS18B20::Scratchpad::array scratchpad;
result = ds18b20.readScratchpad(scratchpad);
if (result) {
return result;
}
- unsigned int tempData =
+ const unsigned int tempData =
(static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
const unsigned int signMask = 0xF800;
if ((tempData & signMask) == signMask) {
--- a/Devices/DS18B20.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS18B20.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,11 +35,12 @@
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
#include <MaximInterface/Utilities/Export.h>
namespace MaximInterface {
-/// DS18B20 Programmable Resolution 1-Wire Digital Thermometer
+/// @brief DS18B20 Programmable Resolution 1-Wire Digital Thermometer
/// @details The DS18B20 digital thermometer provides 9-bit to 12-bit
/// Celsius temperature measurements and has an alarm function with
/// nonvolatile user-programmable upper and lower trigger points. The
@@ -58,14 +59,15 @@
static const uint_least8_t twelveBitResolution = 0x7F;
/// Holds the contents of the device scratchpad.
- typedef array<uint_least8_t, 8> Scratchpad;
+ typedef array_span<uint_least8_t, 8> Scratchpad;
- DS18B20(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
+ DS18B20(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
: selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {}
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
@@ -88,7 +90,7 @@
/// Read Scratchpad Command
/// @param[out] scratchpad Contents of scratchpad.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & scratchpad);
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad);
/// Copy Scratchpad Command
/// @details This command copies from the scratchpad into the
@@ -123,7 +125,8 @@
};
/// Reads the current temperature as an integer value with decimal.
-/// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
+/// @param ds18b20 Device to read.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
MaximInterface_EXPORT error_code readTemperature(DS18B20 & ds18b20,
int & temperature);
--- a/Devices/DS1920.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS1920.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,35 +36,25 @@
namespace MaximInterface {
-enum DS1920_CMDS {
- WRITE_SCRATCHPAD = 0x4E,
- READ_SCRATCHPAD = 0xBE,
- COPY_SCRATCHPAD = 0x48,
- CONV_TEMPERATURE = 0x44,
- RECALL = 0xB8
-};
-
-error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
+error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
error_code result = selectRom(*master);
if (!result) {
- const uint_least8_t sendBlock[] = {WRITE_SCRATCHPAD, th, tl};
- result =
- master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
+ const uint_least8_t sendBlock[] = {0x4E, th, tl};
+ result = master->writeBlock(sendBlock);
}
return result;
}
-error_code DS1920::readScratchpad(Scratchpad & scratchpad) {
+error_code DS1920::readScratchpad(Scratchpad::span scratchpad) {
error_code result = selectRom(*master);
if (!result) {
- result = master->writeByte(READ_SCRATCHPAD);
+ result = master->writeByte(0xBE);
if (!result) {
- result = master->readBlock(scratchpad.data(), scratchpad.size());
+ result = master->readBlock(scratchpad);
if (!result) {
uint_least8_t receivedCrc;
result = master->readByte(receivedCrc);
- if (!result && (receivedCrc !=
- calculateCrc8(scratchpad.data(), scratchpad.size()))) {
+ if (!result && (receivedCrc != calculateCrc8(scratchpad))) {
result = make_error_code(CrcError);
}
}
@@ -73,36 +63,34 @@
return result;
}
-error_code DS1920::copyScratchpad() {
+error_code DS1920::copyScratchpad() {
error_code result = selectRom(*master);
if (!result) {
- result =
- master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::StrongLevel);
+ result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel);
if (!result) {
- (*sleep)(10);
+ sleep->invoke(10);
result = master->setLevel(OneWireMaster::NormalLevel);
}
}
return result;
}
-error_code DS1920::convertTemperature() {
+error_code DS1920::convertTemperature() {
error_code result = selectRom(*master);
if (!result) {
- result =
- master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::StrongLevel);
+ result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel);
if (!result) {
- (*sleep)(750);
+ sleep->invoke(750);
result = master->setLevel(OneWireMaster::NormalLevel);
}
}
return result;
}
-error_code DS1920::recallEeprom() {
+error_code DS1920::recallEeprom() {
error_code result = selectRom(*master);
if (!result) {
- result = master->writeByte(RECALL);
+ result = master->writeByte(0xB8);
}
return result;
}
@@ -133,7 +121,7 @@
if (result) {
return result;
}
- DS1920::Scratchpad scratchpad;
+ DS1920::Scratchpad::array scratchpad;
result = ds1920.readScratchpad(scratchpad);
if (result) {
return result;
--- a/Devices/DS1920.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS1920.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,11 +35,12 @@
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
#include <MaximInterface/Utilities/Export.h>
namespace MaximInterface {
-/// DS1920 1-Wire Temperature iButton
+/// @brief DS1920 1-Wire Temperature iButton
/// @details The iButton® temperature logger (DS1920) provides
/// direct-to-digital 9-bit temperature readings over a range of
/// -55°C to +100°C in 0.5° increments. The iButton communicates with
@@ -54,19 +55,20 @@
enum ErrorValue { CrcError = 1, DataError };
/// Holds the contents of the device scratchpad.
- typedef array<uint_least8_t, 8> Scratchpad;
+ typedef array_span<uint_least8_t, 8> Scratchpad;
- DS1920(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
+ DS1920(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
: selectRom(selectRom), master(&master), sleep(&sleep) {}
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
- /// Write Scratchpad Command
+ /// @brief Write Scratchpad Command
/// @details If the result of a temperature measurement is higher
/// than TH or lower than TL, an alarm flag inside the device is
/// set. This flag is updated with every temperature measurement.
@@ -77,21 +79,21 @@
MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th,
uint_least8_t tl);
- /// Read Scratchpad Command
+ /// @brief Read Scratchpad Command
/// @param[out] scratchpad Contents of scratchpad.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & scratchpad);
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad);
- /// Copy Scratchpad Command
+ /// @brief Copy Scratchpad Command
/// @details This command copies from the scratchpad into the
/// EEPROM of the DS1920, storing the temperature trigger bytes
/// in nonvolatile memory.
MaximInterface_EXPORT error_code copyScratchpad();
- /// Convert Temperature Command
+ /// @brief Convert Temperature Command
/// @details This command begins a temperature conversion.
MaximInterface_EXPORT error_code convertTemperature();
- /// Recall Command
+ /// @brief Recall Command
/// @details This command recalls the temperature trigger values
/// stored in EEPROM to the scratchpad.
MaximInterface_EXPORT error_code recallEeprom();
@@ -104,8 +106,9 @@
const Sleep * sleep;
};
-/// Reads the current temperature as an integer value.
-/// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
+/// @brief Reads the current temperature as an integer value.
+/// @param ds1920 Device to read.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
MaximInterface_EXPORT error_code readTemperature(DS1920 & ds1920,
int & temperature);
--- a/Devices/DS2413.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2413.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -40,10 +40,7 @@
uint_least8_t val;
const error_code result = pioAccessRead(val);
if (!result) {
- status.pioAInputState = (val & 0x1) == 0x1;
- status.pioAOutputState = (val & 0x2) == 0x2;
- status.pioBInputState = (val & 0x4) == 0x4;
- status.pioBOutputState = (val & 0x8) == 0x8;
+ status = val;
}
return result;
}
@@ -77,7 +74,7 @@
error_code result = selectRom(*master);
if (!result) {
uint_least8_t block[] = {0x5A, val, static_cast<uint_least8_t>(val ^ 0xFF)};
- result = master->writeBlock(block, sizeof(block) / sizeof(block[0]));
+ result = master->writeBlock(block);
if (!result) {
result = master->readByte(block[0]);
if (!result && block[0] != 0xAA) {
@@ -97,10 +94,8 @@
switch (condition) {
case CommunicationError:
return "Communication Error";
-
- default:
- return defaultErrorMessage(condition);
}
+ return defaultErrorMessage(condition);
}
} instance;
return instance;
@@ -109,8 +104,9 @@
error_code writePioAOutputState(DS2413 & ds2413, bool pioAState) {
DS2413::Status status;
error_code result = ds2413.readStatus(status);
- if (!result && pioAState != status.pioAOutputState) {
- result = ds2413.writeOutputState(pioAState, status.pioBOutputState);
+ if (!result && pioAState != status[DS2413::PioAOutputState]) {
+ result =
+ ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]);
}
return result;
}
@@ -118,8 +114,9 @@
error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) {
DS2413::Status status;
error_code result = ds2413.readStatus(status);
- if (!result && pioBState != status.pioBOutputState) {
- result = ds2413.writeOutputState(status.pioAOutputState, pioBState);
+ if (!result && pioBState != status[DS2413::PioBOutputState]) {
+ result =
+ ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState);
}
return result;
}
--- a/Devices/DS2413.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2413.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,10 +36,11 @@
#include <stdint.h>
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/FlagSet.hpp>
namespace MaximInterface {
-/// DS2413 1-Wire Dual Channel Addressable Switch
+/// @brief DS2413 1-Wire Dual Channel Addressable Switch
/// @details The DS2413 is a dual-channel programmable I/O 1-Wire®
/// chip. The PIO outputs are configured as open-drain and provide up
/// to 20mA continuous sink capability and off-state operating voltage
@@ -53,17 +54,19 @@
public:
enum ErrorValue { CommunicationError = 1 };
- struct Status {
- bool pioAInputState;
- bool pioAOutputState;
- bool pioBInputState;
- bool pioBOutputState;
+ enum StatusFlags {
+ PioAInputState = 0x1,
+ PioAOutputState = 0x2,
+ PioBInputState = 0x4,
+ PioBOutputState = 0x8
};
+ typedef FlagSet<StatusFlags, 4> Status;
DS2413(OneWireMaster & master, const SelectRom & selectRom)
: selectRom(selectRom), master(&master) {}
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
@@ -85,13 +88,13 @@
OneWireMaster * master;
};
-/// @{
-/// Write the output logic state for only a single PIO pin.
+/// Write the output logic state for only PIOA.
MaximInterface_EXPORT error_code writePioAOutputState(DS2413 & ds2413,
bool pioAState);
+
+/// Write the output logic state for only PIOB.
MaximInterface_EXPORT error_code writePioBOutputState(DS2413 & ds2413,
bool pioBState);
-/// @}
inline error_code make_error_code(DS2413::ErrorValue e) {
return error_code(e, DS2413::errorCategory());
--- a/Devices/DS2431.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2431.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -37,20 +37,13 @@
namespace MaximInterface {
-enum Command {
- WriteScratchpad = 0x0F,
- ReadScratchpad = 0xAA,
- CopyScratchpad = 0x55,
- ReadMemory = 0xF0
-};
-
error_code writeMemory(DS2431 & device, DS2431::Address targetAddress,
- const DS2431::Scratchpad & data) {
+ DS2431::Scratchpad::const_span data) {
error_code result = device.writeScratchpad(targetAddress, data);
if (result) {
return result;
}
- DS2431::Scratchpad readData;
+ DS2431::Scratchpad::array readData;
uint_least8_t esByte;
result = device.readScratchpad(readData, esByte);
if (result) {
@@ -60,107 +53,105 @@
return result;
}
-error_code DS2431::readMemory(Address beginAddress, uint_least8_t * data,
- size_t dataLen) const {
- error_code owmResult = selectRom(*master);
- if (owmResult) {
- return owmResult;
+error_code DS2431::readMemory(Address beginAddress,
+ span<uint_least8_t> data) const {
+ error_code result = selectRom(*master);
+ if (result) {
+ return result;
}
- const uint_least8_t sendBlock[] = {ReadMemory, beginAddress, 0x00};
- owmResult =
- master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
- if (owmResult) {
- return owmResult;
+ const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00};
+ result = master->writeBlock(sendBlock);
+ if (result) {
+ return result;
}
- owmResult = master->readBlock(data, dataLen);
- return owmResult;
+ result = master->readBlock(data);
+ return result;
}
error_code DS2431::writeScratchpad(Address targetAddress,
- const Scratchpad & data) {
- error_code owmResult = selectRom(*master);
- if (owmResult) {
- return owmResult;
+ Scratchpad::const_span data) {
+ error_code result = selectRom(*master);
+ if (result) {
+ return result;
}
- array<uint_least8_t, 3 + Scratchpad::csize> block = {WriteScratchpad,
- targetAddress, 0x00};
- std::copy(data.begin(), data.end(), block.begin() + 3);
- owmResult = master->writeBlock(block.data(), block.size());
- if (owmResult) {
- return owmResult;
+ uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00};
+ std::copy(data.begin(), data.end(), block + 3);
+ result = master->writeBlock(block);
+ if (result) {
+ return result;
}
- const uint_fast16_t calculatedCrc =
- calculateCrc16(block.data(), block.size()) ^ 0xFFFFU;
- owmResult = master->readBlock(block.data(), 2);
- if (owmResult) {
- return owmResult;
+ const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFU;
+ result = master->readBlock(make_span(block, 2));
+ if (result) {
+ return result;
}
if (calculatedCrc !=
((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
- owmResult = make_error_code(CrcError);
+ result = make_error_code(CrcError);
}
- return owmResult;
+ return result;
}
-error_code DS2431::readScratchpad(Scratchpad & data, uint_least8_t & esByte) {
- typedef array<uint_least8_t, 6 + Scratchpad::csize> Block;
+error_code DS2431::readScratchpad(Scratchpad::span data,
+ uint_least8_t & esByte) {
+ typedef array<uint_least8_t, 6 + Scratchpad::size> Block;
- error_code owmResult = selectRom(*master);
- if (owmResult) {
- return owmResult;
+ error_code result = selectRom(*master);
+ if (result) {
+ return result;
}
- Block block = {ReadScratchpad};
- owmResult = master->writeByte(block.front());
- if (owmResult) {
- return owmResult;
+ Block block = {0xAA};
+ result = master->writeByte(block.front());
+ if (result) {
+ return result;
}
- owmResult = master->readBlock(block.data() + 1, block.size() - 1);
- if (owmResult) {
- return owmResult;
+ result = master->readBlock(make_span(block).subspan(1));
+ if (result) {
+ return result;
}
Block::const_iterator blockIt = block.end();
uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8;
receivedCrc |= *(--blockIt);
const uint_fast16_t expectedCrc =
- calculateCrc16(block.data(), block.size() - 2) ^ 0xFFFFU;
+ calculateCrc16(make_span(block.data(), block.size() - 2)) ^ 0xFFFFU;
if (expectedCrc == receivedCrc) {
Block::const_iterator blockItEnd = blockIt;
blockIt -= data.size();
std::copy(blockIt, blockItEnd, data.begin());
esByte = *(--blockIt);
} else {
- owmResult = make_error_code(CrcError);
+ result = make_error_code(CrcError);
}
- return owmResult;
+ return result;
}
-error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {
- error_code owmResult = selectRom(*master);
- if (owmResult) {
- return owmResult;
+error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {
+ error_code result = selectRom(*master);
+ if (result) {
+ return result;
}
- uint_least8_t block[] = {CopyScratchpad, targetAddress, 0x00};
- owmResult = master->writeBlock(block, sizeof(block) / sizeof(block[0]));
- if (owmResult) {
- return owmResult;
+ uint_least8_t block[] = {0x55, targetAddress, 0x00};
+ result = master->writeBlock(block);
+ if (result) {
+ return result;
}
- owmResult = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
- if (owmResult) {
- return owmResult;
+ result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
+ if (result) {
+ return result;
}
- (*sleep)(10);
- owmResult = master->setLevel(OneWireMaster::NormalLevel);
- if (owmResult) {
- return owmResult;
+ sleep->invoke(10);
+ result = master->setLevel(OneWireMaster::NormalLevel);
+ if (result) {
+ return result;
}
- owmResult = master->readByte(block[0]);
- if (owmResult) {
- return owmResult;
+ result = master->readByte(block[0]);
+ if (result) {
+ return result;
}
if (block[0] != 0xAA) {
- owmResult = make_error_code(OperationFailure);
+ result = make_error_code(OperationFailure);
}
- return owmResult;
+ return result;
}
const error_category & DS2431::errorCategory() {
@@ -174,11 +165,9 @@
return "CRC Error";
case OperationFailure:
- return "Operation Failure";
-
- default:
- return defaultErrorMessage(condition);
+ return "Operation Failure";
}
+ return defaultErrorMessage(condition);
}
} instance;
return instance;
--- a/Devices/DS2431.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2431.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,11 +35,12 @@
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
#include <MaximInterface/Utilities/Export.h>
namespace MaximInterface {
-/// DS2431 1024-bit 1-Wire EEPROM
+/// @brief DS2431 1024-bit 1-Wire EEPROM
/// @details The DS2431 is a 1024-bit, 1-Wire® EEPROM chip organized
/// as four memory pages of 256 bits each. Data is written to an 8-byte
/// scratchpad, verified, and then copied to the EEPROM memory. As a
@@ -55,41 +56,41 @@
public:
enum ErrorValue { CrcError = 1, OperationFailure };
- typedef array<uint_least8_t, 8> Scratchpad;
+ typedef array_span<uint_least8_t, 8> Scratchpad;
typedef uint_least8_t Address;
- DS2431(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
+ DS2431(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
: selectRom(selectRom), master(&master), sleep(&sleep) {}
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
- /// Reads block of data from EEPROM memory.
+ /// @brief Reads block of data from EEPROM memory.
/// @param[in] beginAddress EEPROM memory address to start reading from.
/// @param[out] data EEPROM data read from the device.
- /// @param[in] dataLen Length of data parameter and number of bytes to read.
MaximInterface_EXPORT error_code readMemory(Address beginAddress,
- uint_least8_t * data,
- size_t dataLen) const;
+ span<uint_least8_t> data) const;
- /// Writes 8 bytes to the scratchpad.
- /// @param[in] targetAddress EEPROM memory address that this data.
- /// will be copied to. Must be on row boundary.
+ /// @brief Writes 8 bytes to the scratchpad.
+ /// @param[in] targetAddress
+ /// EEPROM memory address that this data will be copied to.
+ /// Must be on row boundary.
/// @param[in] data Data to write to scratchpad.
MaximInterface_EXPORT error_code writeScratchpad(Address targetAddress,
- const Scratchpad & data);
+ Scratchpad::const_span data);
- /// Reads contents of scratchpad.
+ /// @brief Reads contents of scratchpad.
/// @param[out] data Data read from scratchpad.
/// @param[out] esByte E/S byte read before scratchpad data.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data,
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data,
uint_least8_t & esByte);
- /// Copies contents of scratchpad to EEPROM.
+ /// @brief Copies contents of scratchpad to EEPROM.
/// @param[in] targetAddress EEPROM memory address that scratchpad
/// will be copied to. Must be on row boundary.
/// @param[in] esByte E/S byte from preceding Read Scratchpad command.
@@ -104,13 +105,15 @@
const Sleep * sleep;
};
+/// @brief
/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad,
/// and Copy Scratchpad commands.
+/// @param device Device to write.
/// @param[in] targetAddress EEPROM memory address to start writing at.
/// @param[in] data Data to write to EEPROM.
MaximInterface_EXPORT error_code writeMemory(DS2431 & device,
DS2431::Address targetAddress,
- const DS2431::Scratchpad & data);
+ DS2431::Scratchpad::const_span data);
inline error_code make_error_code(DS2431::ErrorValue e) {
return error_code(e, DS2431::errorCategory());
--- a/Devices/DS2465.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2465.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -37,24 +37,6 @@
using namespace Sha256;
-enum MemoryAddress {
- Scratchpad = 0x00,
- CommandReg = 0x60,
- StatusReg = 0x61,
- ReadDataReg = 0x62,
- MacReadoutReg = 0x63,
- MemoryProtectionReg = 0x64,
- ConfigReg = 0x67,
- tRSTL_Reg = 0x68,
- tMSP_Reg = 0x69,
- tW0L_Reg = 0x6A,
- tREC0_Reg = 0x6B,
- RWPU_Reg = 0x6C,
- tW1L_Reg = 0x6D,
- UserMemoryPage0 = 0x80,
- UserMemoryPage1 = 0xA0
-};
-
/// Delay required after writing an EEPROM segment.
static const int eepromSegmentWriteDelayMs = 10;
/// Delay required after writing an EEPROM page such as the secret memory.
@@ -62,26 +44,12 @@
/// Delay required for a SHA computation to complete.
static const int shaComputationDelayMs = 2;
-/// DS2465 Commands
-enum Command {
- DeviceResetCmd = 0xF0,
- WriteDeviceConfigCmd = 0xD2,
- OwResetCmd = 0xB4,
- OwWriteByteCmd = 0xA5,
- OwReadByteCmd = 0x96,
- OwSingleBitCmd = 0x87,
- OwTripletCmd = 0x78,
- OwTransmitBlockCmd = 0x69,
- OwReceiveBlockCmd = 0xE1,
- CopyScratchpadCmd = 0x5A,
- ComputeSlaveSecretCmd = 0x4B,
- ComputeSlaveAuthMacCmd = 0x3C,
- ComputeSlaveWriteMacCmd = 0x2D,
- ComputeNextMasterSecretCmd = 0x1E,
- SetProtectionCmd = 0x0F
-};
+static const uint_least8_t scratchpad = 0x00;
+static const uint_least8_t commandReg = 0x60;
-/// DS2465 Status Bits
+static const uint_least8_t owTransmitBlockCmd = 0x69;
+
+/// DS2465 Status bits.
enum StatusBit {
Status_1WB = 0x01,
Status_PPD = 0x02,
@@ -93,7 +61,10 @@
Status_DIR = 0x80
};
-static const size_t maxBlockSize = 63;
+static const int maxBlockSize = 63;
+
+const int DS2465::memoryPages;
+const int DS2465::segmentsPerPage;
error_code DS2465::initialize(Config config) {
// reset DS2465
@@ -109,12 +80,10 @@
PageRegion region) {
error_code result = make_error_code(ArgumentOutOfRangeError);
if (pageNum >= 0) {
- uint_least8_t command[] = {
- ComputeNextMasterSecretCmd,
- static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
- : 0xBF)};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ const uint_least8_t command[] = {
+ 0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+ : 0xBF)};
+ result = writeMemory(commandReg, command);
}
return result;
}
@@ -123,14 +92,12 @@
int segmentNum) const {
error_code result = make_error_code(ArgumentOutOfRangeError);
if (pageNum >= 0 && segmentNum >= 0) {
- uint_least8_t command[] = {
- ComputeSlaveWriteMacCmd,
- static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
- (pageNum << 4) | segmentNum)};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ const uint_least8_t command[] = {
+ 0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
+ (pageNum << 4) | segmentNum)};
+ result = writeMemory(commandReg, command);
if (!result) {
- (*sleep)(shaComputationDelayMs);
+ sleep->invoke(shaComputationDelayMs);
}
}
return result;
@@ -140,14 +107,12 @@
PageRegion region) const {
error_code result = make_error_code(ArgumentOutOfRangeError);
if (pageNum >= 0) {
- uint_least8_t command[] = {
- ComputeSlaveAuthMacCmd,
- static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
- : 0xBF)};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ const uint_least8_t command[] = {
+ 0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+ : 0xBF)};
+ result = writeMemory(commandReg, command);
if (!result) {
- (*sleep)(shaComputationDelayMs * 2);
+ sleep->invoke(shaComputationDelayMs * 2);
}
}
return result;
@@ -157,65 +122,62 @@
PageRegion region) {
error_code result = make_error_code(ArgumentOutOfRangeError);
if (pageNum >= 0) {
- uint_least8_t command[] = {
- ComputeSlaveSecretCmd,
- static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
- : 0xBF)};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ const uint_least8_t command[] = {
+ 0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+ : 0xBF)};
+ result = writeMemory(commandReg, command);
if (!result) {
- (*sleep)(shaComputationDelayMs * 2);
+ sleep->invoke(shaComputationDelayMs * 2);
}
}
return result;
}
-error_code DS2465::readPage(int pageNum, Page & data) const {
+error_code DS2465::readPage(int pageNum, Page::span data) const {
uint_least8_t addr;
switch (pageNum) {
case 0:
- addr = UserMemoryPage0;
+ addr = 0x80;
break;
case 1:
- addr = UserMemoryPage1;
+ addr = 0xA0;
break;
default:
return make_error_code(ArgumentOutOfRangeError);
}
- return readMemory(addr, data.data(), data.size());
+ return readMemory(addr, data);
}
-error_code DS2465::writePage(int pageNum, const Page & data) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code DS2465::writePage(int pageNum, Page::const_span data) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = copyScratchpad(false, pageNum, false, 0);
}
if (!result) {
- (*sleep)(eepromPageWriteDelayMs);
+ sleep->invoke(eepromPageWriteDelayMs);
}
return result;
}
error_code DS2465::writeSegment(int pageNum, int segmentNum,
- const Segment & data) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+ Segment::const_span data) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = copyScratchpad(false, pageNum, true, segmentNum);
}
if (!result) {
- (*sleep)(eepromSegmentWriteDelayMs);
+ sleep->invoke(eepromSegmentWriteDelayMs);
}
return result;
}
-error_code DS2465::writeMasterSecret(const Hash & masterSecret) {
- error_code result =
- writeMemory(Scratchpad, masterSecret.data(), masterSecret.size());
+error_code DS2465::writeMasterSecret(Hash::const_span masterSecret) {
+ error_code result = writeMemory(scratchpad, masterSecret);
if (!result) {
result = copyScratchpad(true, 0, false, 0);
}
if (!result) {
- (*sleep)(eepromPageWriteDelayMs);
+ sleep->invoke(eepromPageWriteDelayMs);
}
return result;
}
@@ -224,13 +186,12 @@
int segmentNum) {
error_code result = make_error_code(ArgumentOutOfRangeError);
if (pageNum >= 0 && segmentNum >= 0) {
- uint_least8_t command[] = {
- CopyScratchpadCmd,
+ const uint_least8_t command[] = {
+ 0x5A,
static_cast<uint_least8_t>(destSecret ? 0
: (0x80 | (pageNum << 4) |
(notFull << 3) | segmentNum))};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ result = writeMemory(commandReg, command);
}
return result;
}
@@ -245,9 +206,7 @@
return error_code();
}
// Set the level
- Config newConfig = curConfig;
- newConfig.setSPU(level == StrongLevel);
- return writeConfig(newConfig);
+ return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
}
error_code DS2465::setLevel(Level newLevel) {
@@ -268,9 +227,7 @@
return error_code();
}
// Set the speed
- Config newConfig = curConfig;
- newConfig.set1WS(newSpeed == OverdriveSpeed);
- return writeConfig(newConfig);
+ return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
}
error_code DS2465::triplet(TripletData & data) {
@@ -282,9 +239,8 @@
// SS indicates byte containing search direction bit value in msbit
const uint_least8_t command[] = {
- OwTripletCmd, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)};
- error_code result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ 0x78, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)};
+ error_code result = writeMemory(commandReg, command);
if (!result) {
uint_least8_t status;
result = pollBusy(&status);
@@ -298,54 +254,54 @@
return result;
}
-error_code DS2465::readBlock(uint_least8_t * recvBuf, size_t recvLen) {
+error_code DS2465::readBlock(span<uint_least8_t> recvBuf) {
// 1-Wire Receive Block (Case A)
// S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P
// [] indicates from slave
// PR indicates byte containing parameter
error_code result;
- while ((recvLen > 0) && !result) {
+ span<uint_least8_t>::index_type recvIdx = 0;
+ while (recvIdx < recvBuf.size() && !result) {
const uint_least8_t command[] = {
- OwReceiveBlockCmd,
- static_cast<uint_least8_t>(std::min(recvLen, maxBlockSize))};
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ 0xE1,
+ static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>(
+ recvBuf.size() - recvIdx, maxBlockSize))};
+ result = writeMemory(commandReg, command);
if (!result) {
result = pollBusy();
}
if (!result) {
- result = readMemory(Scratchpad, recvBuf, command[1]);
+ result = readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1]));
}
- recvBuf += command[1];
- recvLen -= command[1];
+ recvIdx += command[1];
}
return result;
}
-error_code DS2465::writeBlock(const uint_least8_t * sendBuf, size_t sendLen) {
+error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
error_code result;
- while ((sendLen > 0) && !result) {
+ span<const uint_least8_t>::index_type sendIdx = 0;
+ while (sendIdx < sendBuf.size() && !result) {
const uint_least8_t command[] = {
- OwTransmitBlockCmd,
- static_cast<uint_least8_t>(std::min(sendLen, maxBlockSize))};
+ owTransmitBlockCmd, static_cast<uint_least8_t>(
+ std::min<span<const uint_least8_t>::index_type>(
+ sendBuf.size() - sendIdx, maxBlockSize))};
// prefill scratchpad with required data
- result = writeMemory(Scratchpad, sendBuf, command[1]);
+ result = writeMemory(scratchpad, sendBuf.subspan(sendIdx, command[1]));
// 1-Wire Transmit Block (Case A)
// S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
// [] indicates from slave
// PR indicates byte containing parameter
if (!result) {
- result = writeMemory(CommandReg, command,
- sizeof(command) / sizeof(command[0]));
+ result = writeMemory(commandReg, command);
}
if (!result) {
result = pollBusy();
}
- sendBuf += command[1];
- sendLen -= command[1];
+ sendIdx += command[1];
}
return result;
}
@@ -356,9 +312,8 @@
// [] indicates from slave
// PR indicates byte containing parameter
- const uint_least8_t command[] = {OwTransmitBlockCmd, 0xFF};
- error_code result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+ const uint_least8_t command[] = {owTransmitBlockCmd, 0xFF};
+ error_code result = writeMemory(commandReg, command);
if (!result) {
result = pollBusy();
}
@@ -381,21 +336,18 @@
return result;
}
- uint_least8_t buf = OwReadByteCmd;
- result = writeMemory(CommandReg, &buf, 1);
-
- if (!result) {
- result = pollBusy();
+ const uint_least8_t command = 0x96;
+ result = writeMemory(commandReg, make_span(&command, 1));
+ if (result) {
+ return result;
}
- if (!result) {
- result = readMemory(ReadDataReg, &buf, 1);
+ result = pollBusy();
+ if (result) {
+ return result;
}
- if (!result) {
- recvByte = buf;
- }
-
+ result = readMemory(0x62, make_span(&recvByte, 1));
return result;
}
@@ -413,14 +365,13 @@
return result;
}
- const uint_least8_t command[] = {OwWriteByteCmd, sendByte};
-
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
- if (!result) {
- result = pollBusy();
+ const uint_least8_t command[] = {0xA5, sendByte};
+ result = writeMemory(commandReg, command);
+ if (result) {
+ return result;
}
+ result = pollBusy();
return result;
}
@@ -439,25 +390,22 @@
}
const uint_least8_t command[] = {
- OwSingleBitCmd, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
- uint_least8_t status;
-
- result =
- writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
-
- if (!result) {
- result = pollBusy(&status);
+ 0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
+ result = writeMemory(commandReg, command);
+ if (result) {
+ return result;
}
+ uint_least8_t status;
+ result = pollBusy(&status);
if (!result) {
sendRecvBit = ((status & Status_SBR) == Status_SBR);
}
-
return result;
}
-error_code DS2465::writeMemory(uint_least8_t addr, const uint_least8_t * buf,
- size_t bufLen) const {
+error_code DS2465::writeMemory(uint_least8_t addr,
+ span<const uint_least8_t> buf) const {
// Write SRAM (Case A)
// S AD,0 [A] VSA [A] DD [A] P
// \-----/
@@ -466,27 +414,27 @@
// VSA valid SRAM memory address
// DD memory data to write
- error_code result = i2cMaster->start(i2cAddress_);
+ error_code result = master->start(address_);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->writeByte(addr);
+ result = master->writeByte(addr);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->writeBlock(buf, bufLen);
+ result = master->writeBlock(buf);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->stop();
+ result = master->stop();
return result;
}
-error_code DS2465::readMemory(uint_least8_t addr, uint_least8_t * buf,
- size_t bufLen) const {
+error_code DS2465::readMemory(uint_least8_t addr,
+ span<uint_least8_t> buf) const {
// Read (Case A)
// S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P
// \-----/
@@ -495,40 +443,42 @@
// MA memory address
// DD memory data read
- error_code result = i2cMaster->start(i2cAddress_);
+ error_code result = master->start(address_);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->writeByte(addr);
+ result = master->writeByte(addr);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = readMemory(buf, bufLen);
+ result = readMemory(buf);
return result;
}
-error_code DS2465::readMemory(uint_least8_t * buf, size_t bufLen) const {
- error_code result = i2cMaster->start(i2cAddress_ | 1);
+error_code DS2465::readMemory(span<uint_least8_t> buf) const {
+ error_code result = master->start(address_ | 1);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->readBlock(I2CMaster::Nack, buf, bufLen);
+ result = master->readBlock(I2CMaster::Nack, buf);
if (result) {
- i2cMaster->stop();
+ master->stop();
return result;
}
- result = i2cMaster->stop();
+ result = master->stop();
return result;
}
error_code DS2465::writeConfig(Config config) {
- uint_least8_t configBuf = ((config.readByte() ^ 0xF) << 4) | config.readByte();
- error_code result = writeMemory(ConfigReg, &configBuf, 1);
+ const uint_least8_t configReg = 0x67;
+ uint_least8_t configBuf =
+ ((config.readByte() ^ 0xF) << 4) | config.readByte();
+ error_code result = writeMemory(configReg, make_span(&configBuf, 1));
if (!result) {
- result = readMemory(ConfigReg, &configBuf, 1);
+ result = readMemory(configReg, make_span(&configBuf, 1));
}
if (!result) {
if (configBuf != config.readByte())
@@ -549,29 +499,29 @@
switch (param) {
case tRSTL_STD:
case tRSTL_OD:
- addr = tRSTL_Reg;
+ addr = 0x68;
break;
case tMSP_STD:
case tMSP_OD:
- addr = tMSP_Reg;
+ addr = 0x69;
break;
case tW0L_STD:
case tW0L_OD:
- addr = tW0L_Reg;
+ addr = 0x6A;
break;
case tREC0:
- addr = tREC0_Reg;
+ addr = 0x6B;
break;
case RWPU:
- addr = RWPU_Reg;
+ addr = 0x6C;
break;
case tW1L_OD:
- addr = tW1L_Reg;
+ addr = 0x6D;
break;
}
uint_least8_t data;
- error_code result = readMemory(addr, &data, 1);
+ error_code result = readMemory(addr, make_span(&data, 1));
if (result) {
return result;
}
@@ -584,7 +534,7 @@
}
if (newData != data) {
- result = writeMemory(addr, &newData, 1);
+ result = writeMemory(addr, make_span(&newData, 1));
}
return result;
}
@@ -595,7 +545,7 @@
int pollCount = 0;
uint_least8_t status;
do {
- error_code result = readMemory(&status, 1);
+ error_code result = readMemory(make_span(&status, 1));
if (result) {
return result;
}
@@ -617,8 +567,8 @@
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
- uint_least8_t buf = OwResetCmd;
- error_code result = writeMemory(CommandReg, &buf, 1);
+ uint_least8_t buf = 0xB4;
+ error_code result = writeMemory(commandReg, make_span(&buf, 1));
if (!result) {
result = pollBusy(&buf);
@@ -627,8 +577,7 @@
if (!result) {
if ((buf & Status_SD) == Status_SD) {
result = make_error_code(ShortDetectedError);
- }
- else if ((buf & Status_PPD) != Status_PPD) {
+ } else if ((buf & Status_PPD) != Status_PPD) {
result = make_error_code(NoSlaveError);
}
}
@@ -642,11 +591,11 @@
// [] indicates from slave
// SS status byte to read to verify state
- uint_least8_t buf = DeviceResetCmd;
- error_code result = writeMemory(CommandReg, &buf, 1);
+ uint_least8_t buf = 0xF0;
+ error_code result = writeMemory(commandReg, make_span(&buf, 1));
if (!result) {
- result = readMemory(&buf, 1);
+ result = readMemory(make_span(&buf, 1));
}
if (!result) {
@@ -662,42 +611,44 @@
return result;
}
-error_code DS2465::computeNextMasterSecret(const SlaveSecretData & data) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code
+DS2465::computeNextMasterSecret(AuthenticationData::const_span data) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeNextMasterSecret(false, 0, FullPage);
}
return result;
}
-error_code DS2465::computeNextMasterSecretWithSwap(const SlaveSecretData & data,
- int pageNum,
- PageRegion region) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code
+DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
+ int pageNum, PageRegion region) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeNextMasterSecret(true, pageNum, region);
}
return result;
}
-error_code DS2465::computeWriteMac(const WriteMacData & data) const {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code DS2465::computeWriteMac(WriteMacData::const_span data) const {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeWriteMac(false, false, 0, 0);
}
return result;
}
-error_code DS2465::computeWriteMac(const WriteMacData & data,
- Hash & mac) const {
+error_code DS2465::computeWriteMac(WriteMacData::const_span data,
+ Hash::span mac) const {
error_code result = computeWriteMac(data);
if (!result) {
- result = readMemory(mac.data(), mac.size());
+ result = readMemory(mac);
}
return result;
}
-error_code DS2465::computeAndTransmitWriteMac(const WriteMacData & data) const {
+error_code
+DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const {
error_code result = computeWriteMac(data);
if (!result) {
result = writeMacBlock();
@@ -705,28 +656,28 @@
return result;
}
-error_code DS2465::computeWriteMacWithSwap(const WriteMacData & data,
+error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
int pageNum, int segmentNum) const {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeWriteMac(false, true, pageNum, segmentNum);
}
return result;
}
-error_code DS2465::computeWriteMacWithSwap(const WriteMacData & data,
+error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
int pageNum, int segmentNum,
- Hash & mac) const {
+ Hash::span mac) const {
error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
if (!result) {
- result = readMemory(mac.data(), mac.size());
+ result = readMemory(mac);
}
return result;
}
-error_code DS2465::computeAndTransmitWriteMacWithSwap(const WriteMacData & data,
- int pageNum,
- int segmentNum) const {
+error_code
+DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
+ int pageNum, int segmentNum) const {
error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
if (!result) {
result = writeMacBlock();
@@ -734,40 +685,43 @@
return result;
}
-error_code DS2465::computeSlaveSecret(const SlaveSecretData & data) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeSlaveSecret(false, 0, FullPage);
}
return result;
}
-error_code DS2465::computeSlaveSecretWithSwap(const SlaveSecretData & data,
- int pageNum, PageRegion region) {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code
+DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
+ int pageNum, PageRegion region) {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeSlaveSecret(true, pageNum, region);
}
return result;
}
-error_code DS2465::computeAuthMac(const AuthMacData & data) const {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+error_code DS2465::computeAuthMac(AuthenticationData::const_span data) const {
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeAuthMac(false, 0, FullPage);
}
return result;
}
-error_code DS2465::computeAuthMac(const AuthMacData & data, Hash & mac) const {
+error_code DS2465::computeAuthMac(AuthenticationData::const_span data,
+ Hash::span mac) const {
error_code result = computeAuthMac(data);
if (!result) {
- result = readMemory(mac.data(), mac.size());
+ result = readMemory(mac);
}
return result;
}
-error_code DS2465::computeAndTransmitAuthMac(const AuthMacData & data) const {
+error_code
+DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const {
error_code result = computeAuthMac(data);
if (!result) {
result = writeMacBlock();
@@ -775,27 +729,28 @@
return result;
}
-error_code DS2465::computeAuthMacWithSwap(const AuthMacData & data, int pageNum,
+error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
+ int pageNum,
PageRegion region) const {
- error_code result = writeMemory(Scratchpad, data.data(), data.size());
+ error_code result = writeMemory(scratchpad, data);
if (!result) {
result = computeAuthMac(true, pageNum, region);
}
return result;
}
-error_code DS2465::computeAuthMacWithSwap(const AuthMacData & data, int pageNum,
- PageRegion region, Hash & mac) const {
+error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
+ int pageNum, PageRegion region,
+ Hash::span mac) const {
error_code result = computeAuthMacWithSwap(data, pageNum, region);
if (!result) {
- result = readMemory(mac.data(), mac.size());
+ result = readMemory(mac);
}
return result;
}
-error_code DS2465::computeAndTransmitAuthMacWithSwap(const AuthMacData & data,
- int pageNum,
- PageRegion region) const {
+error_code DS2465::computeAndTransmitAuthMacWithSwap(
+ AuthenticationData::const_span data, int pageNum, PageRegion region) const {
error_code result = computeAuthMacWithSwap(data, pageNum, region);
if (!result) {
result = writeMacBlock();
--- a/Devices/DS2465.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2465.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,6 +36,7 @@
#include <MaximInterface/Links/I2CMaster.hpp>
#include <MaximInterface/Links/OneWireMaster.hpp>
#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
#include <MaximInterface/Utilities/Export.h>
#include <MaximInterface/Utilities/Sha256.hpp>
@@ -46,7 +47,7 @@
public:
enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
- /// 1-Wire port adjustment parameters.
+ /// @brief 1-Wire port adjustment parameters.
/// @note See datasheet page 13.
enum PortParameter {
tRSTL_STD,
@@ -64,13 +65,13 @@
enum PageRegion { FullPage = 0x03, FirstHalf = 0x01, SecondHalf = 0x02 };
/// Holds the contents of a device memory segment.
- typedef array<uint_least8_t, 4> Segment;
+ typedef array_span<uint_least8_t, 4> Segment;
/// Holds the contents of a device memory page.
- typedef array<uint_least8_t, 32> Page;
+ typedef array_span<uint_least8_t, 32> Page;
static const int memoryPages = 2;
- static const int segmentsPerPage = Page::csize / Segment::csize;
+ static const int segmentsPerPage = Page::size / Segment::size;
/// Represents a DS2465 configuration.
class Config {
@@ -79,52 +80,80 @@
explicit Config(uint_least8_t readByte = optionAPU)
: readByte_(readByte & 0xF) {}
+ /// @name 1WS
+ /// @brief 1-Wire Speed
/// @{
- /// 1-Wire Speed
+
+ /// Get 1WS bit.
bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
- void set1WS(bool new1WS) {
+
+ /// Set 1WS bit.
+ Config & set1WS(bool new1WS) {
if (new1WS) {
readByte_ |= option1WS;
} else {
readByte_ &= ~option1WS;
}
+ return *this;
}
+
/// @}
+ /// @name SPU
+ /// @brief Strong Pullup
/// @{
- /// Strong Pullup
+
+ /// Get SPU bit.
bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
- void setSPU(bool newSPU) {
+
+ /// Set SPU bit.
+ Config & setSPU(bool newSPU) {
if (newSPU) {
readByte_ |= optionSPU;
} else {
readByte_ &= ~optionSPU;
}
+ return *this;
}
+
/// @}
+ /// @name PDN
+ /// @brief 1-Wire Power Down
/// @{
- /// 1-Wire Power Down
+
+ /// Get PDN bit.
bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
- void setPDN(bool newPDN) {
+
+ /// Set PDN bit.
+ Config & setPDN(bool newPDN) {
if (newPDN) {
readByte_ |= optionPDN;
} else {
readByte_ &= ~optionPDN;
}
+ return *this;
}
+
/// @}
+ /// @name APU
+ /// @brief Active Pullup
/// @{
- /// Active Pullup
+
+ /// Get APU bit.
bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
- void setAPU(bool newAPU) {
+
+ /// Set APU bit.
+ Config & setAPU(bool newAPU) {
if (newAPU) {
readByte_ |= optionAPU;
} else {
readByte_ &= ~optionAPU;
}
+ return *this;
}
+
/// @}
/// Byte representation that is read from the DS2465.
@@ -143,196 +172,213 @@
// affect the state of the 1-Wire bus. Read pointer, scratchpad, MAC output
// register, and command register on the DS2465 are considered mutable.
- DS2465(const Sleep & sleep, I2CMaster & i2cMaster,
- uint_least8_t i2cAddress = 0x30)
- : sleep(&sleep), i2cMaster(&i2cMaster), i2cAddress_(i2cAddress & 0xFE) {}
+ DS2465(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x30)
+ : sleep(&sleep), master(&master), address_(address & 0xFE) {}
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
- void setI2CMaster(I2CMaster & i2cMaster) { this->i2cMaster = &i2cMaster; }
- uint_least8_t i2cAddress() const { return i2cAddress_; }
- void setI2CAddress(uint_least8_t i2cAddress) {
- this->i2cAddress_ = (i2cAddress & 0xFE);
- }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
+ void setMaster(I2CMaster & master) { this->master = &master; }
+
+ uint_least8_t address() const { return address_; }
+
+ void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
/// Initialize hardware for use.
MaximInterface_EXPORT error_code initialize(Config config = Config());
- /// Write a new configuration to the DS2465.
+ /// @brief Write a new configuration to the DS2465.
/// @param[in] config New configuration to write.
MaximInterface_EXPORT error_code writeConfig(Config config);
- /// Write a new port configuration parameter to the DS2465.
+ /// @brief Write a new port configuration parameter to the DS2465.
/// @param[in] param Parameter to adjust.
- /// @param[in] val New parameter value to set. Consult datasheet for value
- /// mappings.
+ /// @param[in] val
+ /// New parameter value to set. Consult datasheet for value mappings.
MaximInterface_EXPORT error_code writePortParameter(PortParameter param,
int val);
// 1-Wire Master Commands
MaximInterface_EXPORT virtual error_code reset();
+
MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
- size_t recvLen);
+
+ MaximInterface_EXPORT virtual error_code
+ readBlock(span<uint_least8_t> recvBuf);
+
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+ writeBlock(span<const uint_least8_t> sendBuf);
+
MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
- /// @note The DS2465 only supports enabling strong pullup following a 1-Wire
- /// read or write operation.
+
+ /// @copydoc OneWireMaster::setLevel
+ /// @note
+ /// The DS2465 only supports enabling strong pullup following a 1-Wire read or
+ /// write operation.
MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
// DS2465 Coprocessor Commands
-
- /// Read data from an EEPROM memory page.
+
+ /// @brief Read data from an EEPROM memory page.
/// @param pageNum Page number to read from.
- MaximInterface_EXPORT error_code readPage(int pageNum, Page & data) const;
+ /// @param[out] data Data that was read.
+ MaximInterface_EXPORT error_code readPage(int pageNum, Page::span data) const;
- /// Write data to an EEPROM memory page.
+ /// @brief Write data to an EEPROM memory page.
/// @param pageNum Page number to copy to.
- MaximInterface_EXPORT error_code writePage(int pageNum, const Page & data);
+ /// @param data Data to write.
+ MaximInterface_EXPORT error_code writePage(int pageNum,
+ Page::const_span data);
- /// Write data to an EEPROM memory segment.
+ /// @brief Write data to an EEPROM memory segment.
/// @param pageNum Page number to copy to.
/// @param segmentNum Segment number to copy to.
+ /// @param data Data to write.
MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
- const Segment & data);
+ Segment::const_span data);
/// Write data to the secret EEPROM memory page.
MaximInterface_EXPORT error_code
- writeMasterSecret(const Sha256::Hash & masterSecret);
+ writeMasterSecret(Sha256::Hash::const_span masterSecret);
- /// Compute Next Master Secret.
+ /// @brief Compute Next Master Secret.
/// @param data Combined data fields for computation.
MaximInterface_EXPORT error_code
- computeNextMasterSecret(const Sha256::SlaveSecretData & data);
+ computeNextMasterSecret(Sha256::AuthenticationData::const_span data);
- /// Compute Next Master Secret with page swapping.
+ /// @brief Compute Next Master Secret with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param region Region of the page to swap in.
- MaximInterface_EXPORT error_code computeNextMasterSecretWithSwap(
- const Sha256::SlaveSecretData & data, int pageNum, PageRegion region);
+ MaximInterface_EXPORT error_code
+ computeNextMasterSecretWithSwap(Sha256::AuthenticationData::const_span data,
+ int pageNum, PageRegion region);
- /// Compute Write MAC.
+ /// @brief Compute Write MAC.
/// @param data Combined data fields for computation.
/// @param[out] mac Computed Write MAC.
- MaximInterface_EXPORT error_code
- computeWriteMac(const Sha256::WriteMacData & data, Sha256::Hash & mac) const;
+ MaximInterface_EXPORT error_code computeWriteMac(
+ Sha256::WriteMacData::const_span data, Sha256::Hash::span mac) const;
- /// Compute Write MAC.
+ /// @brief Compute Write MAC.
/// @param data Combined data fields for computation.
MaximInterface_EXPORT error_code
- computeAndTransmitWriteMac(const Sha256::WriteMacData & data) const;
+ computeAndTransmitWriteMac(Sha256::WriteMacData::const_span data) const;
- /// Compute Write MAC with page swapping.
+ /// @brief Compute Write MAC with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param segmentNum Segment number to swap in.
/// @param[out] mac Computed Write MAC.
MaximInterface_EXPORT error_code
- computeWriteMacWithSwap(const Sha256::WriteMacData & data, int pageNum,
- int segmentNum, Sha256::Hash & mac) const;
+ computeWriteMacWithSwap(Sha256::WriteMacData::const_span data, int pageNum,
+ int segmentNum, Sha256::Hash::span mac) const;
- /// Compute Write MAC with page swapping.
+ /// @brief Compute Write MAC with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param segmentNum Segment number to swap in.
MaximInterface_EXPORT error_code computeAndTransmitWriteMacWithSwap(
- const Sha256::WriteMacData & data, int pageNum, int segmentNum) const;
+ Sha256::WriteMacData::const_span data, int pageNum, int segmentNum) const;
- /// Compute Slave Secret (S-Secret).
+ /// @brief Compute Slave Secret (S-Secret).
/// @param data Combined data fields for computation.
MaximInterface_EXPORT error_code
- computeSlaveSecret(const Sha256::SlaveSecretData & data);
+ computeSlaveSecret(Sha256::AuthenticationData::const_span data);
- /// Compute Slave Secret (S-Secret) with page swapping.
+ /// @brief Compute Slave Secret (S-Secret) with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param region Region of the page to swap in.
- MaximInterface_EXPORT error_code computeSlaveSecretWithSwap(
- const Sha256::SlaveSecretData & data, int pageNum, PageRegion region);
+ MaximInterface_EXPORT error_code
+ computeSlaveSecretWithSwap(Sha256::AuthenticationData::const_span data,
+ int pageNum, PageRegion region);
- /// Compute Authentication MAC.
+ /// @brief Compute Authentication MAC.
/// @param data Combined data fields for computation.
/// @param[out] mac Computed Auth MAC.
MaximInterface_EXPORT error_code
- computeAuthMac(const Sha256::AuthMacData & data, Sha256::Hash & mac) const;
+ computeAuthMac(Sha256::AuthenticationData::const_span data,
+ Sha256::Hash::span mac) const;
- /// Compute Authentication MAC.
+ /// @brief Compute Authentication MAC.
/// @param data Combined data fields for computation.
MaximInterface_EXPORT error_code
- computeAndTransmitAuthMac(const Sha256::AuthMacData & data) const;
+ computeAndTransmitAuthMac(Sha256::AuthenticationData::const_span data) const;
- /// Compute Authentication MAC with page swapping.
+ /// @brief Compute Authentication MAC with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param region Region of the page to swap in.
/// @param[out] mac Computed Auth MAC.
- MaximInterface_EXPORT error_code
- computeAuthMacWithSwap(const Sha256::AuthMacData & data, int pageNum,
- PageRegion region, Sha256::Hash & mac) const;
+ MaximInterface_EXPORT error_code computeAuthMacWithSwap(
+ Sha256::AuthenticationData::const_span data, int pageNum,
+ PageRegion region, Sha256::Hash::span mac) const;
- /// Compute Authentication MAC with page swapping.
+ /// @brief Compute Authentication MAC with page swapping.
/// @param data Combined data fields for computation.
/// @param pageNum Page number to swap in.
/// @param region Region of the page to swap in.
- MaximInterface_EXPORT error_code computeAndTransmitAuthMacWithSwap(
- const Sha256::AuthMacData & data, int pageNum, PageRegion region) const;
+ MaximInterface_EXPORT error_code
+ computeAndTransmitAuthMacWithSwap(Sha256::AuthenticationData::const_span data,
+ int pageNum, PageRegion region) const;
MaximInterface_EXPORT static const error_category & errorCategory();
private:
const Sleep * sleep;
- I2CMaster * i2cMaster;
- uint_least8_t i2cAddress_;
+ I2CMaster * master;
+ uint_least8_t address_;
Config curConfig;
- /// Performs a soft reset on the DS2465.
+ /// @brief Performs a soft reset on the DS2465.
/// @note This is not a 1-Wire Reset.
error_code resetDevice();
- /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be cleared.
+ /// @brief
+ /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be
+ /// cleared.
/// @param[out] pStatus Optionally retrive the status byte when 1WB cleared.
/// @returns Success or TimeoutError if poll limit reached.
error_code pollBusy(uint_least8_t * pStatus = NULL) const;
- /// Ensure that the desired 1-Wire level is set in the configuration.
+ /// @brief Ensure that the desired 1-Wire level is set in the configuration.
/// @param level Desired 1-Wire level.
error_code configureLevel(Level level);
- /// Const since only for internal use.
- error_code writeMemory(uint_least8_t addr, const uint_least8_t * buf,
- size_t bufLen) const;
+ /// @note Const since only for internal use.
+ error_code writeMemory(uint_least8_t addr,
+ span<const uint_least8_t> buf) const;
- /// Read memory from the DS2465.
+ /// @brief Read memory from the DS2465.
/// @param addr Address to begin reading from.
/// @param[out] buf Buffer to hold read data.
- /// @param bufLen Length of buffer, buf, and number of bytes to read.
- error_code readMemory(uint_least8_t addr, uint_least8_t * buf,
- size_t bufLen) const;
+ error_code readMemory(uint_least8_t addr, span<uint_least8_t> buf) const;
- /// Read memory from the DS2465 at the current pointer.
+ /// @brief Read memory from the DS2465 at the current pointer.
/// @param[out] buf Buffer to hold read data.
- /// @param bufLen Length of buffer, buf, and number of bytes to read.
- error_code readMemory(uint_least8_t * buf, size_t bufLen) const;
+ error_code readMemory(span<uint_least8_t> buf) const;
/// Write the last computed MAC to the 1-Wire bus.
error_code writeMacBlock() const;
- error_code computeWriteMac(const Sha256::WriteMacData & data) const;
+ error_code computeWriteMac(Sha256::WriteMacData::const_span data) const;
- error_code computeWriteMacWithSwap(const Sha256::WriteMacData & data,
+ error_code computeWriteMacWithSwap(Sha256::WriteMacData::const_span data,
int pageNum, int segmentNum) const;
- error_code computeAuthMac(const Sha256::AuthMacData & data) const;
+ error_code computeAuthMac(Sha256::AuthenticationData::const_span data) const;
- error_code computeAuthMacWithSwap(const Sha256::AuthMacData & data,
+ error_code computeAuthMacWithSwap(Sha256::AuthenticationData::const_span data,
int pageNum, PageRegion region) const;
// Legacy implementations
--- a/Devices/DS2480B.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2480B.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -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:
--- a/Devices/DS2480B.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2480B.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -43,25 +43,28 @@
/// Serial to 1-Wire Line Driver
class DS2480B : public OneWireMaster {
public:
- enum ErrorValue {
- HardwareError = 1
- };
+ enum ErrorValue { HardwareError = 1 };
- DS2480B(const Sleep & sleep, Uart & uart) : sleep(&sleep), uart(&uart) {}
+ DS2480B(Sleep & sleep, Uart & uart) : sleep(&sleep), uart(&uart) {}
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
void setUart(Uart & uart) { this->uart = &uart; }
MaximInterface_EXPORT error_code initialize();
MaximInterface_EXPORT virtual error_code reset();
+
MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
MaximInterface_EXPORT static const error_category & errorCategory();
@@ -70,23 +73,10 @@
MaximInterface_EXPORT error_code sendCommand(uint_least8_t command);
private:
- /// Baud rates for DS2480B
- enum BaudRate {
- Baud9600bps = 0, ///< 9600 bps
- Baud19200bps = 2, ///< 19200 bps
- Baud57600bps = 4, ///< 57600 bps
- Baud115200bps = 6 ///< 115200 bps
- };
-
- error_code changeBaud(BaudRate newBaud);
- error_code setComBaud(BaudRate newBaud);
- error_code breakCom();
-
const Sleep * sleep;
Uart * uart;
Level level;
- BaudRate baud;
uint_least8_t mode;
uint_least8_t speed;
};
--- a/Devices/DS2482_DS2484.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2482_DS2484.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,26 +35,6 @@
namespace MaximInterface {
-enum Command {
- DeviceResetCmd = 0xF0,
- WriteDeviceConfigCmd = 0xD2,
- AdjustOwPortCmd = 0xC3, // DS2484 only
- ChannelSelectCmd = 0xC3, // DS2482-800 only
- SetReadPointerCmd = 0xE1,
- OwResetCmd = 0xB4,
- OwWriteByteCmd = 0xA5,
- OwReadByteCmd = 0x96,
- OwSingleBitCmd = 0x87,
- OwTripletCmd = 0x78
-};
-
-// Device register pointers.
-enum Register {
- ConfigReg = 0xC3,
- StatusReg = 0xF0,
- ReadDataReg = 0xE1
-};
-
// Device Status bits
enum StatusBit {
Status_1WB = 0x01,
@@ -68,13 +48,11 @@
};
error_code DS2482_DS2484::initialize(Config config) {
- // reset device
error_code result = resetDevice();
if (result) {
return result;
}
-
- // write the default configuration setup
+ // Write the default configuration setup.
result = writeConfig(config);
return result;
}
@@ -85,23 +63,24 @@
// [] indicates from slave
// SS status byte to read to verify state
- uint_least8_t buf;
- error_code result = sendCommand(DeviceResetCmd);
-
- if (!result) {
- result = readRegister(buf);
+ error_code result = sendCommand(0xF0);
+ if (result) {
+ return result;
}
- if (!result) {
- if ((buf & 0xF7) != 0x10) {
- result = make_error_code(HardwareError);
- }
+ uint_least8_t buf;
+ result = readRegister(buf);
+ if (result) {
+ return result;
}
- if (!result) {
- reset(); // do a command to get 1-Wire master reset out of holding state
+ if ((buf & 0xF7) != 0x10) {
+ return make_error_code(HardwareError);
}
+ // Do a command to get 1-Wire master reset out of holding state.
+ reset();
+
return result;
}
@@ -113,12 +92,11 @@
// [] indicates from slave
// SS indicates byte containing search direction bit value in msbit
- error_code result = sendCommand(OwTripletCmd, data.writeBit ? 0x80 : 0x00);
+ error_code result = sendCommand(0x78, data.writeBit ? 0x80 : 0x00);
if (!result) {
uint_least8_t status;
result = pollBusy(&status);
if (!result) {
- // check bit results in status byte
data.readBit = ((status & Status_SBR) == Status_SBR);
data.readBitComplement = ((status & Status_TSB) == Status_TSB);
data.writeBit = ((status & Status_DIR) == Status_DIR);
@@ -134,26 +112,28 @@
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
- error_code result = sendCommand(OwResetCmd);
- uint_least8_t buf;
-
- if (!result) {
- result = pollBusy(&buf);
+ error_code result = sendCommand(0xB4);
+ if (result) {
+ return result;
}
- if (!result) {
- if ((buf & Status_SD) == Status_SD) {
- result = make_error_code(ShortDetectedError);
- }
- else if ((buf & Status_PPD) != Status_PPD) {
- result = make_error_code(NoSlaveError);
- }
+ uint_least8_t buf;
+ result = pollBusy(&buf);
+ if (result) {
+ return result;
+ }
+
+ if ((buf & Status_SD) == Status_SD) {
+ result = make_error_code(ShortDetectedError);
+ } else if ((buf & Status_PPD) != Status_PPD) {
+ result = make_error_code(NoSlaveError);
}
return result;
}
-error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit,
+ Level afterLevel) {
// 1-Wire bit (Case B)
// S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
@@ -162,25 +142,25 @@
// BB indicates byte containing bit value in msbit
error_code result = configureLevel(afterLevel);
+ if (result) {
+ return result;
+ }
- if (!result) {
- result = sendCommand(OwSingleBitCmd, sendRecvBit ? 0x80 : 0x00);
+ result = sendCommand(0x87, sendRecvBit ? 0x80 : 0x00);
+ if (result) {
+ return result;
}
uint_least8_t status;
-
- if (!result) {
- result = pollBusy(&status);
- }
-
+ result = pollBusy(&status);
if (!result) {
sendRecvBit = ((status & Status_SBR) == Status_SBR);
}
-
return result;
}
-error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) {
+error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte,
+ Level afterLevel) {
// 1-Wire Write Byte (Case B)
// S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
@@ -193,16 +173,17 @@
return result;
}
- result = sendCommand(OwWriteByteCmd, sendByte);
- if (!result) {
- result = pollBusy();
+ result = sendCommand(0xA5, sendByte);
+ if (result) {
+ return result;
}
+ result = pollBusy();
return result;
}
error_code DS2482_DS2484::readByteSetLevel(uint_least8_t & recvByte,
- Level afterLevel) {
+ Level afterLevel) {
// 1-Wire Read Bytes (Case C)
// S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
// \--------/
@@ -217,22 +198,17 @@
return result;
}
- result = sendCommand(OwReadByteCmd);
-
- if (!result) {
- result = pollBusy();
+ result = sendCommand(0x96);
+ if (result) {
+ return result;
}
- uint_least8_t buf;
-
- if (!result) {
- result = readRegister(ReadDataReg, buf);
+ result = pollBusy();
+ if (result) {
+ return result;
}
- if (!result) {
- recvByte = buf;
- }
-
+ result = readRegister(0xE1, recvByte);
return result;
}
@@ -246,9 +222,7 @@
return error_code();
}
// Set the speed
- Config newConfig = curConfig;
- newConfig.set1WS(newSpeed == OverdriveSpeed);
- return writeConfig(newConfig);
+ return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
}
error_code DS2482_DS2484::setLevel(Level newLevel) {
@@ -260,10 +234,11 @@
}
error_code DS2482_DS2484::writeConfig(Config config) {
- uint_least8_t configBuf = ((config.readByte() ^ 0xF) << 4) | config.readByte();
- error_code result = sendCommand(WriteDeviceConfigCmd, configBuf);
+ uint_least8_t configBuf =
+ ((config.readByte() ^ 0xF) << 4) | config.readByte();
+ error_code result = sendCommand(0xD2, configBuf);
if (!result) {
- result = readRegister(ConfigReg, configBuf);
+ result = readRegister(0xC3, configBuf);
}
if (!result) {
if (configBuf != config.readByte()) {
@@ -276,8 +251,9 @@
return result;
}
-error_code DS2482_DS2484::readRegister(uint_least8_t reg, uint_least8_t & buf) const {
- error_code result = sendCommand(SetReadPointerCmd, reg);
+error_code DS2482_DS2484::readRegister(uint_least8_t reg,
+ uint_least8_t & buf) const {
+ error_code result = sendCommand(0xE1, reg);
if (!result) {
result = readRegister(buf);
}
@@ -285,7 +261,7 @@
}
error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const {
- return i2cMaster->readPacket(i2cAddress_, &buf, 1);
+ return master->readPacket(address_, make_span(&buf, 1));
}
error_code DS2482_DS2484::pollBusy(uint_least8_t * pStatus) {
@@ -319,18 +295,17 @@
return error_code();
}
// Set the level
- Config newConfig = curConfig;
- newConfig.setSPU(level == StrongLevel);
- return writeConfig(newConfig);
+ return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
}
error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
- return i2cMaster->writePacket(i2cAddress_, &cmd, 1);
+ return master->writePacket(address_, make_span(&cmd, 1));
}
-error_code DS2482_DS2484::sendCommand(uint_least8_t cmd, uint_least8_t param) const {
+error_code DS2482_DS2484::sendCommand(uint_least8_t cmd,
+ uint_least8_t param) const {
uint_least8_t buf[] = {cmd, param};
- return i2cMaster->writePacket(i2cAddress_, buf, sizeof(buf) / sizeof(buf[0]));
+ return master->writePacket(address_, buf);
}
const error_category & DS2482_DS2484::errorCategory() {
@@ -408,7 +383,7 @@
return make_error_code(ArgumentOutOfRangeError);
};
- error_code result = sendCommand(ChannelSelectCmd, ch);
+ error_code result = sendCommand(0xC3, ch);
if (!result) {
result = readRegister(ch);
if (!result) {
@@ -427,13 +402,13 @@
return make_error_code(ArgumentOutOfRangeError);
}
- error_code result = sendCommand(AdjustOwPortCmd, (param << 4) | val);
+ error_code result = sendCommand(0xC3, (param << 4) | val);
if (result) {
return result;
}
- uint_least8_t portConfig;
- for (int paramNum = param + 1; paramNum > 0; paramNum--) {
+ uint_least8_t portConfig = val + 1;
+ for (int reads = -1; reads < param; ++reads) {
result = readRegister(portConfig);
if (result) {
return result;
--- a/Devices/DS2482_DS2484.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS2482_DS2484.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -51,52 +51,80 @@
explicit Config(uint_least8_t readByte = optionAPU)
: readByte_(readByte & 0xF) {}
+ /// @name 1WS
+ /// @brief 1-Wire Speed
/// @{
- /// 1-Wire Speed
+
+ /// Get 1WS bit.
bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
- void set1WS(bool new1WS) {
+
+ /// Set 1WS bit.
+ Config & set1WS(bool new1WS) {
if (new1WS) {
readByte_ |= option1WS;
} else {
readByte_ &= ~option1WS;
}
+ return *this;
}
+
/// @}
+ /// @name SPU
+ /// @brief Strong Pullup
/// @{
- /// Strong Pullup
+
+ /// Get SPU bit.
bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
- void setSPU(bool newSPU) {
+
+ /// Set SPU bit.
+ Config & setSPU(bool newSPU) {
if (newSPU) {
readByte_ |= optionSPU;
} else {
readByte_ &= ~optionSPU;
}
+ return *this;
}
+
/// @}
+ /// @name PDN
+ /// @brief 1-Wire Power Down
/// @{
- /// 1-Wire Power Down
+
+ /// Get PDN bit.
bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
- void setPDN(bool newPDN) {
+
+ /// Set PDN bit.
+ Config & setPDN(bool newPDN) {
if (newPDN) {
readByte_ |= optionPDN;
} else {
readByte_ &= ~optionPDN;
}
+ return *this;
}
+
/// @}
+ /// @name APU
+ /// @brief Active Pullup
/// @{
- /// Active Pullup
+
+ /// Get APU bit.
bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
- void setAPU(bool newAPU) {
+
+ /// Set APU bit.
+ Config & setAPU(bool newAPU) {
if (newAPU) {
readByte_ |= optionAPU;
} else {
readByte_ &= ~optionAPU;
}
+ return *this;
}
+
/// @}
/// Byte representation that is read from the device.
@@ -111,37 +139,41 @@
uint_least8_t readByte_;
};
- void setI2CMaster(I2CMaster & i2cMaster) { this->i2cMaster = &i2cMaster; }
- uint_least8_t i2cAddress() const { return i2cAddress_; }
- void setI2CAddress(uint_least8_t i2cAddress) {
- this->i2cAddress_ = i2cAddress;
- }
+ void setMaster(I2CMaster & master) { this->master = &master; }
+
+ uint_least8_t address() const { return address_; }
+
+ void setAddress(uint_least8_t address) { address_ = address; }
/// Initialize hardware for use.
MaximInterface_EXPORT error_code initialize(Config config = Config());
- /// Write a new configuration to the device.
+ /// @brief Write a new configuration to the device.
/// @param[in] config New configuration to write.
MaximInterface_EXPORT error_code writeConfig(Config config);
- /// @note Perform a 1-Wire triplet using the device command.
MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
MaximInterface_EXPORT virtual error_code reset();
+
MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
MaximInterface_EXPORT static const error_category & errorCategory();
protected:
- DS2482_DS2484(I2CMaster & i2cMaster, uint_least8_t i2cAddress)
- : i2cMaster(&i2cMaster), i2cAddress_(i2cAddress) {}
+ DS2482_DS2484(I2CMaster & master, uint_least8_t address)
+ : master(&master), address_(address) {}
/// @note Allow marking const since not public.
error_code sendCommand(uint_least8_t cmd) const;
@@ -149,31 +181,32 @@
/// @note Allow marking const since not public.
error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const;
- /// Reads a register from the device.
+ /// @brief Reads a register from the device.
/// @param reg Register to read from.
/// @param[out] buf Buffer to hold read data.
error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const;
- /// Reads the current register from the device.
+ /// @brief Reads the current register from the device.
/// @param[out] buf Buffer to hold read data.
error_code readRegister(uint_least8_t & buf) const;
private:
- /// Performs a soft reset on the device.
+ /// @brief Performs a soft reset on the device.
/// @note This is not a 1-Wire Reset.
error_code resetDevice();
+ /// @brief
/// Polls the device status waiting for the 1-Wire Busy bit (1WB) to be cleared.
/// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared.
/// @returns Success or TimeoutError if poll limit reached.
error_code pollBusy(uint_least8_t * pStatus = NULL);
- /// Ensure that the desired 1-Wire level is set in the configuration.
+ /// @brief Ensure that the desired 1-Wire level is set in the configuration.
/// @param level Desired 1-Wire level.
error_code configureLevel(Level level);
- I2CMaster * i2cMaster;
- uint_least8_t i2cAddress_;
+ I2CMaster * master;
+ uint_least8_t address_;
Config curConfig;
};
@@ -193,7 +226,7 @@
DS2482_800(I2CMaster & i2c_bus, uint_least8_t adrs)
: DS2482_DS2484(i2c_bus, adrs) {}
- /// Select the active 1-Wire channel.
+ /// @brief Select the active 1-Wire channel.
/// @param channel Channel number to select from 0 to 7.
MaximInterface_EXPORT error_code selectChannel(int channel);
};
@@ -201,7 +234,7 @@
/// DS2484 I2C to 1-Wire Master
class DS2484 : public DS2482_DS2484 {
public:
- /// 1-Wire port adjustment parameters.
+ /// @brief 1-Wire port adjustment parameters.
/// @note See datasheet page 13.
enum PortParameter {
tRSTL = 0,
@@ -217,7 +250,7 @@
explicit DS2484(I2CMaster & i2c_bus, uint_least8_t adrs = 0x30)
: DS2482_DS2484(i2c_bus, adrs) {}
- /// Adjust 1-Wire port parameters.
+ /// @brief Adjust 1-Wire port parameters.
/// @param param Parameter to adjust.
/// @param val New parameter value to set. Consult datasheet for value mappings.
MaximInterface_EXPORT error_code adjustPort(PortParameter param, int val);
--- a/Devices/DS28C36_DS2476.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28C36_DS2476.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -1,731 +1,724 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <MaximInterface/Links/I2CMaster.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include <MaximInterface/Utilities/RomId.hpp>
-#include "DS28C36_DS2476.hpp"
-
-using std::copy;
-
-namespace MaximInterface {
-using namespace Ecc256;
-
-// DS28C36 commands.
-enum Command {
- WriteMemory = 0x96,
- ReadMemory = 0x69,
- WriteBuffer = 0x87,
- ReadBuffer = 0x5A,
- ReadPageProtection = 0xAA,
- SetPageProtection = 0xC3,
- DecrementCounter = 0xC9,
- ReadRng = 0xD2,
- EncryptedReadMemory = 0x4B,
- ComputeAndReadPathAuthentication = 0xA5,
- AuthenticatedSha2WriteMemory = 0x99,
- ComputeAndLockSha2Secret = 0x3C,
- GenerateEcc256KeyPair = 0xCB,
- ComputeMultiblockHash = 0x33,
- VerifyEcdsaSignature = 0x59,
- AuthenticateEcdsaPublicKey = 0xA8,
- AuthenticatedEcdsaWriteMemory = 0x89
-};
-
-static error_code convertResultByte(uint_least8_t resultByte) {
- error_code errorCode;
- if (resultByte != 0xAA) {
- errorCode.assign((resultByte == 0x00)
- ? static_cast<int>(DS28C36::AuthenticationError)
- : resultByte,
- DS28C36::errorCategory());
- }
- return errorCode;
-}
-
-error_code DS28C36::writeMemory(int pageNum, const Page & page) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 1 + Page::csize> buffer;
- buffer[0] = pageNum;
- copy(page.begin(), page.end(), buffer.begin() + 1);
- error_code result = writeCommand(WriteMemory, buffer.data(), buffer.size());
- if (!result) {
- sleep(writeMemoryTimeMs);
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::readMemory(int pageNum, Page & page) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- const uint_least8_t parameter = pageNum;
- error_code result = writeCommand(ReadMemory, ¶meter, 1);
- if (!result) {
- sleep(readMemoryTimeMs);
- array<uint_least8_t, 1 + Page::csize> response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- copy(response.begin() + 1, response.end(), page.begin());
- }
- }
- return result;
-}
-
-error_code DS28C36::writeBuffer(const uint_least8_t * data, size_t dataSize) {
- return writeCommand(WriteBuffer, data, dataSize);
-}
-
-error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) {
- error_code result = writeCommand(ReadBuffer);
- if (!result) {
- data.resize(80);
- size_t dataSize = data.size();
- result = readVariableLengthResponse(&data[0], dataSize);
- if (result) {
- data.clear();
- } else {
- data.resize(dataSize);
- }
- }
- return result;
-}
-
-error_code DS28C36::readPageProtection(int pageNum,
- PageProtection & protection) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- uint_least8_t buffer = pageNum;
- error_code result = writeCommand(ReadPageProtection, &buffer, 1);
- if (!result) {
- sleep(readMemoryTimeMs);
- result = readFixedLengthResponse(&buffer, 1);
- if (!result) {
- protection = buffer;
- }
- }
- return result;
-}
-
-error_code DS28C36::setPageProtection(int pageNum,
- const PageProtection & protection) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 2> buffer = {
- static_cast<uint_least8_t>(pageNum),
- static_cast<uint_least8_t>(protection.to_ulong())};
- error_code result =
- writeCommand(SetPageProtection, buffer.data(), buffer.size());
- if (!result) {
- sleep(writeMemoryTimeMs);
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::decrementCounter() {
- error_code result = writeCommand(DecrementCounter);
- if (!result) {
- sleep(writeMemoryTimeMs);
- uint_least8_t response;
- result = readFixedLengthResponse(&response, 1);
- if (!result) {
- result = convertResultByte(response);
- }
- }
- return result;
-}
-
-error_code DS28C36::readRng(uint_least8_t * data, size_t dataSize) {
- if ((dataSize < 1) || (dataSize > 64)) {
- return make_error_code(InvalidParameterError);
- }
-
- data[0] = static_cast<uint_least8_t>(dataSize - 1);
- error_code result = writeCommand(ReadRng, data, 1);
- if (!result) {
- sleep(sha256ComputationTimeMs);
- result = readFixedLengthResponse(data, dataSize);
- }
- return result;
-}
-
-error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
- EncryptedPage & page) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- const uint_least8_t parameter = (secretNum << 6) | pageNum;
- error_code result = writeCommand(EncryptedReadMemory, ¶meter, 1);
- if (!result) {
- sleep(readMemoryTimeMs + sha256ComputationTimeMs);
- typedef array<uint_least8_t, 1 + EncryptedPage::size> Response;
- Response response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- Response::const_iterator begin = response.begin() + 1;
- Response::const_iterator end = begin + page.challenge.size();
- copy(begin, end, page.challenge.begin());
- begin = end;
- end = begin + page.data.size();
- copy(begin, end, page.data.begin());
- }
- }
- return result;
-}
-
-error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
- AuthType authType) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- const uint_least8_t parameter = (authType << 5) | pageNum;
- return writeCommand(ComputeAndReadPathAuthentication, ¶meter, 1);
-}
-
-error_code
-DS28C36::computeAndReadEcdsaPageAuthentication(int pageNum, KeyNum keyNum,
- Signature & signature) {
- AuthType authType;
- switch (keyNum) {
- case KeyNumA:
- authType = EcdsaWithKeyA;
- break;
- case KeyNumB:
- authType = EcdsaWithKeyB;
- break;
- case KeyNumC:
- authType = EcdsaWithKeyC;
- break;
- default:
- return make_error_code(InvalidParameterError);
- }
- error_code result = computeAndReadPageAuthentication(pageNum, authType);
- if (!result) {
- sleep(sha256ComputationTimeMs);
- typedef array<uint_least8_t, 1 + Signature::size> Response;
- Response response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- Response::const_iterator begin = response.begin() + 1;
- Response::const_iterator end = begin + signature.s.size();
- copy(begin, end, signature.s.begin());
- begin = end;
- end = begin + signature.r.size();
- copy(begin, end, signature.r.begin());
- }
- }
- return result;
-}
-
-error_code DS28C36::computeAndReadHmacPageAuthentication(int pageNum,
- SecretNum secretNum,
- Sha256::Hash & hmac) {
- AuthType authType;
- switch (secretNum) {
- case SecretNumA:
- authType = HmacWithSecretA;
- break;
- case SecretNumB:
- authType = HmacWithSecretB;
- break;
- case SecretNumS:
- authType = HmacWithSecretS;
- break;
- default:
- return make_error_code(InvalidParameterError);
- }
- error_code result = computeAndReadPageAuthentication(pageNum, authType);
- if (!result) {
- sleep(generateEcdsaSignatureTimeMs);
- array<uint_least8_t, 1 + Sha256::Hash::csize> response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- copy(response.begin() + 1, response.end(), hmac.begin());
- }
- }
- return result;
-}
-
-error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
- SecretNum secretNum,
- const Page & page) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 1 + Page::csize> buffer;
- buffer[0] = (secretNum << 6) | pageNum;
- copy(page.begin(), page.end(), buffer.begin() + 1);
- error_code result =
- writeCommand(AuthenticatedSha2WriteMemory, buffer.data(), buffer.size());
- if (!result) {
- sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
- SecretNum dsecretNum,
- bool writeProtectEnable) {
- // User pages only
- if (pageNum < UserData0 || pageNum > UserData15) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 2> buffer = {
- static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) |
- pageNum),
- static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)};
- error_code result =
- writeCommand(ComputeAndLockSha2Secret, buffer.data(), buffer.size());
- if (!result) {
- sleep(sha256ComputationTimeMs +
- ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
- bool writeProtectEnable) {
- if (keyNum == KeyNumS) {
- return make_error_code(InvalidParameterError);
- }
-
- uint_least8_t buffer = keyNum;
- if (writeProtectEnable) {
- buffer |= 0x80;
- }
- error_code result = writeCommand(GenerateEcc256KeyPair, &buffer, 1);
- if (!result) {
- sleep(generateEccKeyPairTimeMs);
- result = readFixedLengthResponse(&buffer, 1);
- if (!result) {
- result = convertResultByte(buffer);
- }
- }
- return result;
-}
-
-error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
- const uint_least8_t * data,
- size_t dataSize) {
- const size_t maxDataSize = 64;
-
- if (dataSize < 1 || dataSize > maxDataSize) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 1 + maxDataSize> buffer;
- buffer[0] = 0;
- if (firstBlock) {
- buffer[0] |= 0x40;
- }
- if (lastBlock) {
- buffer[0] |= 0x80;
- }
- copy(data, data + dataSize, buffer.begin() + 1);
- error_code result =
- writeCommand(ComputeMultiblockHash, buffer.data(), dataSize + 1);
- if (!result) {
- sleep(sha256ComputationTimeMs);
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
- const Signature & signature,
- PioState pioa, PioState piob) {
- typedef array<uint_least8_t, 1 + Signature::size> Buffer;
- Buffer buffer;
- buffer[0] = keyNum | (hashType << 2);
- if (pioa != Unchanged) {
- buffer[0] |= 0x20;
- }
- if (pioa == Conducting) {
- buffer[0] |= 0x10;
- }
- if (piob != Unchanged) {
- buffer[0] |= 0x80;
- }
- if (piob == Conducting) {
- buffer[0] |= 0x40;
- }
- Buffer::iterator bufferIt =
- copy(signature.r.begin(), signature.r.end(), buffer.begin() + 1);
- copy(signature.s.begin(), signature.s.end(), bufferIt);
- error_code result =
- writeCommand(VerifyEcdsaSignature, buffer.data(), buffer.size());
- if (!result) {
- sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
- ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh,
- KeyNum keyNum, int csOffset,
- const Signature & signature) {
- if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
- (csOffset > 31)) {
- return make_error_code(InvalidParameterError);
- }
-
- typedef array<uint_least8_t, 1 + Signature::size> Buffer;
- Buffer buffer;
- buffer[0] = (csOffset << 3) | (keyNum << 2);
- if (ecdh) {
- buffer[0] |= 0x02;
- }
- if (authWrites) {
- buffer[0] |= 0x01;
- }
- Buffer::iterator bufferIt =
- copy(signature.r.begin(), signature.r.end(), buffer.begin() + 1);
- copy(signature.s.begin(), signature.s.end(), bufferIt);
- error_code result =
- writeCommand(AuthenticateEcdsaPublicKey, buffer.data(), buffer.size());
- if (!result) {
- sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
- const Page & page) {
- if (pageNum < 0 || pageNum >= memoryPages) {
- return make_error_code(InvalidParameterError);
- }
-
- array<uint_least8_t, 1 + Page::csize> buffer;
- buffer[0] = pageNum;
- copy(page.begin(), page.end(), buffer.begin() + 1);
- error_code result =
- writeCommand(AuthenticatedEcdsaWriteMemory, buffer.data(), buffer.size());
- if (!result) {
- sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
- sha256ComputationTimeMs);
- result = readFixedLengthResponse(buffer.data(), 1);
- if (!result) {
- result = convertResultByte(buffer[0]);
- }
- }
- return result;
-}
-
-error_code DS28C36::writeCommand(uint_least8_t command,
- const uint_least8_t * parameters,
- size_t parametersSize) {
- error_code result = master->start(address_);
- if (result) {
- master->stop();
- return result;
- }
- result = master->writeByte(command);
- if (result) {
- master->stop();
- return result;
- }
- if (parameters) {
- result = master->writeByte(static_cast<uint_least8_t>(parametersSize));
- if (result) {
- master->stop();
- return result;
- }
- result = master->writeBlock(parameters, parametersSize);
- if (result) {
- master->stop();
- return result;
- }
- }
- result = master->stop();
- return result;
-}
-
-error_code DS28C36::readVariableLengthResponse(uint_least8_t * response,
- size_t & responseSize) {
- error_code result = master->start(address_ | 1);
- if (result) {
- master->stop();
- return result;
- }
- uint_least8_t length;
- result = master->readByte(I2CMaster::Ack, length);
- if (result) {
- master->stop();
- return result;
- }
- if (length > responseSize) {
- master->stop();
- return make_error_code(InvalidResponseError);
- }
- if (length > 0) {
- result = master->readBlock(I2CMaster::Nack, response, length);
- if (result) {
- master->stop();
- return result;
- }
- }
- responseSize = length;
- result = master->stop();
- return result;
-}
-
-error_code DS28C36::readFixedLengthResponse(uint_least8_t * response,
- size_t responseSize) {
- const size_t requestedResponseSize = responseSize;
- error_code result = readVariableLengthResponse(response, responseSize);
- if (!result && responseSize != requestedResponseSize) {
- result = make_error_code(InvalidResponseError);
- }
- return result;
-}
-
-DS28C36::PageAuthenticationData
-DS28C36::createPageAuthenticationData(const RomId & romId, const Page & page,
- const Page & challenge, int pageNum,
- const ManId & manId) {
- PageAuthenticationData data;
- PageAuthenticationData::iterator dataIt = data.begin();
- dataIt = copy(romId.begin(), romId.end(), dataIt);
- dataIt = copy(page.begin(), page.end(), dataIt);
- dataIt = copy(challenge.begin(), challenge.end(), dataIt);
- *dataIt = static_cast<uint_least8_t>(pageNum);
- ++dataIt;
- copy(manId.begin(), manId.end(), dataIt);
- return data;
-}
-
-const error_category & DS28C36::errorCategory() {
- static class : public error_category {
- public:
- virtual const char * name() const { return "DS28C36"; }
-
- virtual std::string message(int condition) const {
- switch (condition) {
- case ProtectionError:
- return "Protection Error";
-
- case InvalidParameterError:
- return "Invalid Parameter Error";
-
- case InvalidSequenceError:
- return "Invalid Sequence Error";
-
- case InvalidEcdsaInputOrResultError:
- return "Invalid ECDSA Input or Result Error";
-
- case AuthenticationError:
- return "Authentication Error";
-
- case InvalidResponseError:
- return "Invalid Response Error";
-
- default:
- return defaultErrorMessage(condition);
- }
- }
- } instance;
- return instance;
-}
-
-error_code readRomIdAndManId(DS28C36 & ds28c36, RomId * romId, ManId * manId) {
- DS28C36::Page page;
- const error_code result = ds28c36.readMemory(DS28C36::RomOptions, page);
- if (!result) {
- DS28C36::Page::const_iterator pageIt = page.begin() + 22;
- if (manId) {
- copy(pageIt, pageIt + ManId::size(), manId->begin());
- }
- pageIt += ManId::size();
- if (romId) {
- copy(pageIt, pageIt + RomId::size(), romId->begin());
- }
- }
- return result;
-}
-
-error_code computeMultiblockHash(DS28C36 & ds28c36, const uint_least8_t * data,
- const size_t dataSize) {
- error_code result;
- size_t remainingSize = dataSize;
- while ((remainingSize > 0) && !result) {
- const size_t chunkSize = std::min<size_t>(remainingSize, 64);
- result = ds28c36.computeMultiblockHash(
- remainingSize == dataSize, remainingSize == chunkSize, data, chunkSize);
- data += chunkSize;
- remainingSize -= chunkSize;
- }
- return result;
-}
-
-error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
- const uint_least8_t * data, size_t dataSize,
- const Signature & signature,
- DS28C36::PioState pioa,
- DS28C36::PioState piob) {
- error_code result = computeMultiblockHash(ds28c36, data, dataSize);
- if (!result) {
- result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
- pioa, piob);
- }
- return result;
-}
-
-error_code verifyEcdsaSignature(DS28C36 & ds28c36, const PublicKey & publicKey,
- const uint_least8_t * data, size_t dataSize,
- const Signature & signature,
- DS28C36::PioState pioa,
- DS28C36::PioState piob) {
- error_code result = ds28c36.writeMemory(DS28C36::PublicKeySX, publicKey.x);
- if (!result) {
- result = ds28c36.writeMemory(DS28C36::PublicKeySY, publicKey.y);
- }
- if (!result) {
- result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, dataSize,
- signature, pioa, piob);
- }
- return result;
-}
-
-// DS2476 additional commands.
-enum DS2476_Command {
- GenerateEcdsaSignature = 0x1E,
- ComputeSha2UniqueSecret = 0x55,
- ComputeSha2Hmac = 0x2D
-};
-
-error_code DS2476::generateEcdsaSignature(KeyNum keyNum,
- Signature & signature) {
- if (keyNum == KeyNumS) {
- return make_error_code(InvalidParameterError);
- }
-
- const uint_least8_t parameter = keyNum;
- error_code result = writeCommand(GenerateEcdsaSignature, ¶meter, 1);
- if (!result) {
- sleep(generateEcdsaSignatureTimeMs);
- typedef array<uint_least8_t, 1 + Signature::size> Response;
- Response response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- Response::const_iterator begin = response.begin() + 1;
- Response::const_iterator end = begin + signature.s.size();
- copy(begin, end, signature.s.begin());
- begin = end;
- end = begin + signature.r.size();
- copy(begin, end, signature.r.begin());
- }
- }
- return result;
-}
-
-error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
- uint_least8_t buffer = msecretNum << 4;
- error_code result = writeCommand(ComputeSha2UniqueSecret, &buffer, 1);
- if (!result) {
- sleep(sha256ComputationTimeMs);
- result = readFixedLengthResponse(&buffer, 1);
- if (!result) {
- convertResultByte(buffer);
- }
- }
- return result;
-}
-
-error_code DS2476::computeSha2Hmac(Sha256::Hash & hmac) {
- error_code result = writeCommand(ComputeSha2Hmac);
- if (!result) {
- sleep(sha256ComputationTimeMs);
- array<uint_least8_t, 1 + Sha256::Hash::csize> response;
- result = readFixedLengthResponse(response.data(), response.size());
- if (!result) {
- result = convertResultByte(response[0]);
- copy(response.begin() + 1, response.end(), hmac.begin());
- }
- }
- return result;
-}
-
-error_code enableCoprocessor(DS2476 & ds2476) {
- DS2476::Page gpioControl;
- error_code result = ds2476.readMemory(DS2476::GpioControl, gpioControl);
- if (!result && gpioControl[0] != 0xAA) {
- gpioControl[0] = 0xAA;
- result = ds2476.writeMemory(DS2476::GpioControl, gpioControl);
- }
- return result;
-}
-
-} // namespace MaximInterface
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <algorithm>
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include "DS28C36_DS2476.hpp"
+
+namespace MaximInterface {
+
+using namespace Ecc256;
+using std::copy;
+
+static error_code convertResultByte(uint_least8_t resultByte) {
+ error_code errorCode;
+ if (resultByte != 0xAA) {
+ errorCode.assign((resultByte == 0x00)
+ ? static_cast<int>(DS28C36::AuthenticationError)
+ : resultByte,
+ DS28C36::errorCategory());
+ }
+ return errorCode;
+}
+
+const int DS28C36::publicKeyAxPage;
+const int DS28C36::publicKeyAyPage;
+const int DS28C36::publicKeyBxPage;
+const int DS28C36::publicKeyByPage;
+const int DS28C36::publicKeyCxPage;
+const int DS28C36::publicKeyCyPage;
+const int DS28C36::privateKeyAPage;
+const int DS28C36::privateKeyBPage;
+const int DS28C36::privateKeyCPage;
+const int DS28C36::secretAPage;
+const int DS28C36::secretBPage;
+const int DS28C36::decrementCounterPage;
+const int DS28C36::romOptionsPage;
+const int DS28C36::gpioControlPage;
+const int DS28C36::publicKeySxPage;
+const int DS28C36::publicKeySyPage;
+const int DS28C36::memoryPages;
+
+error_code DS28C36::writeMemory(int pageNum, Page::const_span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + Page::size];
+ buffer[0] = pageNum;
+ copy(page.begin(), page.end(), buffer + 1);
+ error_code result = writeCommand(0x96, buffer);
+ if (!result) {
+ sleep(writeMemoryTimeMs);
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::readMemory(int pageNum, Page::span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ const uint_least8_t parameter = pageNum;
+ error_code result = writeCommand(0x69, make_span(¶meter, 1));
+ if (!result) {
+ sleep(readMemoryTimeMs);
+ array<uint_least8_t, 1 + Page::size> response;
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ copy(response.begin() + 1, response.end(), page.begin());
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::writeBuffer(span<const uint_least8_t> data) {
+ return writeCommand(0x87, data);
+}
+
+error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) {
+ error_code result = writeCommand(0x5A);
+ if (!result) {
+ data.resize(80);
+ span<uint_least8_t> dataSpan(data);
+ result = readVariableLengthResponse(dataSpan);
+ if (result) {
+ data.clear();
+ } else {
+ data.resize(dataSpan.size());
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::readPageProtection(int pageNum,
+ PageProtection & protection) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer = pageNum;
+ error_code result = writeCommand(0xAA, make_span(&buffer, 1));
+ if (!result) {
+ sleep(readMemoryTimeMs);
+ result = readFixedLengthResponse(make_span(&buffer, 1));
+ if (!result) {
+ protection = buffer;
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::setPageProtection(int pageNum,
+ const PageProtection & protection) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum),
+ static_cast<uint_least8_t>(protection.to_ulong())};
+ error_code result = writeCommand(0xC3, buffer);
+ if (!result) {
+ sleep(writeMemoryTimeMs);
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::decrementCounter() {
+ error_code result = writeCommand(0xC9);
+ if (!result) {
+ sleep(writeMemoryTimeMs);
+ uint_least8_t response;
+ result = readFixedLengthResponse(make_span(&response, 1));
+ if (!result) {
+ result = convertResultByte(response);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::readRng(span<uint_least8_t> data) {
+ if ((data.size() < 1) || (data.size() > 64)) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ data[0] = static_cast<uint_least8_t>(data.size() - 1);
+ error_code result = writeCommand(0xD2, data.first(1));
+ if (!result) {
+ sleep(sha256ComputationTimeMs);
+ result = readFixedLengthResponse(data);
+ }
+ return result;
+}
+
+error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
+ EncryptionChallenge::span challenge,
+ Page::span data) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ const uint_least8_t parameter = (secretNum << 6) | pageNum;
+ error_code result = writeCommand(0x4B, make_span(¶meter, 1));
+ if (!result) {
+ sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+ uint_least8_t response[1 + EncryptionChallenge::size + Page::size];
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ const uint_least8_t * begin = response + 1;
+ const uint_least8_t * end = begin + challenge.size();
+ copy(begin, end, challenge.begin());
+ begin = end;
+ end = begin + data.size();
+ copy(begin, end, data.begin());
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
+ AuthType authType) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ const uint_least8_t parameter = (authType << 5) | pageNum;
+ return writeCommand(0xA5, make_span(¶meter, 1));
+}
+
+error_code
+DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum,
+ Signature::span signature) {
+ AuthType authType;
+ switch (keyNum) {
+ case KeyNumA:
+ authType = EcdsaWithKeyA;
+ break;
+ case KeyNumB:
+ authType = EcdsaWithKeyB;
+ break;
+ case KeyNumC:
+ authType = EcdsaWithKeyC;
+ break;
+ default:
+ return make_error_code(InvalidParameterError);
+ }
+ error_code result = computeAndReadPageAuthentication(pageNum, authType);
+ if (!result) {
+ sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs);
+ uint_least8_t response[1 + 2 * Scalar::size];
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ const uint_least8_t * begin = response + 1;
+ const uint_least8_t * end = begin + signature.s.size();
+ copy(begin, end, signature.s.begin());
+ begin = end;
+ end = begin + signature.r.size();
+ copy(begin, end, signature.r.begin());
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
+ SecretNum secretNum,
+ Sha256::Hash::span hmac) {
+ AuthType authType;
+ switch (secretNum) {
+ case SecretNumA:
+ authType = HmacWithSecretA;
+ break;
+ case SecretNumB:
+ authType = HmacWithSecretB;
+ break;
+ case SecretNumS:
+ authType = HmacWithSecretS;
+ break;
+ default:
+ return make_error_code(InvalidParameterError);
+ }
+ error_code result = computeAndReadPageAuthentication(pageNum, authType);
+ if (!result) {
+ sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+ array<uint_least8_t, 1 + Sha256::Hash::size> response;
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ copy(response.begin() + 1, response.end(), hmac.begin());
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
+ SecretNum secretNum,
+ Page::const_span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + Page::size];
+ buffer[0] = (secretNum << 6) | pageNum;
+ copy(page.begin(), page.end(), buffer + 1);
+ error_code result = writeCommand(0x99, buffer);
+ if (!result) {
+ sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+ SecretNum dsecretNum,
+ bool writeProtectEnable) {
+ // User pages only
+ if (pageNum < 0 || pageNum > 15) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[] = {
+ static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) |
+ pageNum),
+ static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)};
+ error_code result = writeCommand(0x3C, buffer);
+ if (!result) {
+ sleep(sha256ComputationTimeMs +
+ ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
+ bool writeProtectEnable) {
+ if (keyNum == KeyNumS) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer = keyNum;
+ if (writeProtectEnable) {
+ buffer |= 0x80;
+ }
+ error_code result = writeCommand(0xCB, make_span(&buffer, 1));
+ if (!result) {
+ sleep(generateEccKeyPairTimeMs);
+ result = readFixedLengthResponse(make_span(&buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
+ span<const uint_least8_t> data) {
+ const span<const uint_least8_t>::index_type maxDataSize = 64;
+
+ if (data.size() < 1 || data.size() > maxDataSize) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + maxDataSize];
+ buffer[0] = 0;
+ if (firstBlock) {
+ buffer[0] |= 0x40;
+ }
+ if (lastBlock) {
+ buffer[0] |= 0x80;
+ }
+ copy(data.begin(), data.end(), buffer + 1);
+ error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1));
+ if (!result) {
+ sleep(sha256ComputationTimeMs);
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
+ Signature::const_span signature,
+ PioState pioa, PioState piob) {
+ uint_least8_t buffer[1 + 2 * Scalar::size];
+ buffer[0] = keyNum | (hashType << 2);
+ if (pioa != Unchanged) {
+ buffer[0] |= 0x20;
+ }
+ if (pioa == Conducting) {
+ buffer[0] |= 0x10;
+ }
+ if (piob != Unchanged) {
+ buffer[0] |= 0x80;
+ }
+ if (piob == Conducting) {
+ buffer[0] |= 0x40;
+ }
+ uint_least8_t * bufferIt =
+ copy(signature.r.begin(), signature.r.end(), buffer + 1);
+ copy(signature.s.begin(), signature.s.end(), bufferIt);
+ error_code result = writeCommand(0x59, buffer);
+ if (!result) {
+ sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
+ ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code
+DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
+ int csOffset,
+ Signature::const_span signature) {
+ if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
+ (csOffset > 31)) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + 2 * Scalar::size];
+ buffer[0] = (csOffset << 3) | (keyNum << 2);
+ if (ecdh) {
+ buffer[0] |= 0x02;
+ }
+ if (authWrites) {
+ buffer[0] |= 0x01;
+ }
+ uint_least8_t * bufferIt =
+ copy(signature.r.begin(), signature.r.end(), buffer + 1);
+ copy(signature.s.begin(), signature.s.end(), bufferIt);
+ error_code result = writeCommand(0xA8, buffer);
+ if (!result) {
+ sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
+ Page::const_span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + Page::size];
+ buffer[0] = pageNum;
+ copy(page.begin(), page.end(), buffer + 1);
+ error_code result = writeCommand(0x89, buffer);
+ if (!result) {
+ sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
+ sha256ComputationTimeMs);
+ result = readFixedLengthResponse(make_span(buffer, 1));
+ if (!result) {
+ result = convertResultByte(buffer[0]);
+ }
+ }
+ return result;
+}
+
+error_code DS28C36::writeCommand(uint_least8_t command,
+ span<const uint_least8_t> parameters) {
+ error_code result = master->start(address_);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ result = master->writeByte(command);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ if (!parameters.empty()) {
+ result = master->writeByte(static_cast<uint_least8_t>(parameters.size()));
+ if (result) {
+ master->stop();
+ return result;
+ }
+ result = master->writeBlock(parameters);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ }
+ result = master->stop();
+ return result;
+}
+
+error_code DS28C36::readVariableLengthResponse(span<uint_least8_t> & response) {
+ error_code result = master->start(address_ | 1);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ uint_least8_t length;
+ result = master->readByte(I2CMaster::Ack, length);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ if (length > response.size()) {
+ master->stop();
+ return make_error_code(InvalidResponseError);
+ }
+ response = response.first(length);
+ if (!response.empty()) {
+ result = master->readBlock(I2CMaster::Nack, response);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ }
+ result = master->stop();
+ return result;
+}
+
+error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) {
+ const span<uint_least8_t>::index_type requestedResponseSize = response.size();
+ error_code result = readVariableLengthResponse(response);
+ if (!result && response.size() != requestedResponseSize) {
+ result = make_error_code(InvalidResponseError);
+ }
+ return result;
+}
+
+const error_category & DS28C36::errorCategory() {
+ static class : public error_category {
+ public:
+ virtual const char * name() const { return "DS28C36"; }
+
+ virtual std::string message(int condition) const {
+ switch (condition) {
+ case ProtectionError:
+ return "Protection Error";
+
+ case InvalidParameterError:
+ return "Invalid Parameter Error";
+
+ case InvalidSequenceError:
+ return "Invalid Sequence Error";
+
+ case InvalidEcdsaInputOrResultError:
+ return "Invalid ECDSA Input or Result Error";
+
+ case AuthenticationError:
+ return "Authentication Error";
+
+ case InvalidResponseError:
+ return "Invalid Response Error";
+
+ default:
+ return defaultErrorMessage(condition);
+ }
+ }
+ } instance;
+ return instance;
+}
+
+error_code DS2476::generateEcdsaSignature(KeyNum keyNum,
+ Signature::span signature) {
+ if (keyNum == KeyNumS) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ const uint_least8_t parameter = keyNum;
+ error_code result = writeCommand(0x1E, make_span(¶meter, 1));
+ if (!result) {
+ sleep(generateEcdsaSignatureTimeMs);
+ uint_least8_t response[1 + 2 * Scalar::size];
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ const uint_least8_t * begin = response + 1;
+ const uint_least8_t * end = begin + signature.s.size();
+ copy(begin, end, signature.s.begin());
+ begin = end;
+ end = begin + signature.r.size();
+ copy(begin, end, signature.r.begin());
+ }
+ }
+ return result;
+}
+
+error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
+ uint_least8_t buffer = msecretNum << 4;
+ error_code result = writeCommand(0x55, make_span(&buffer, 1));
+ if (!result) {
+ sleep(sha256ComputationTimeMs);
+ result = readFixedLengthResponse(make_span(&buffer, 1));
+ if (!result) {
+ convertResultByte(buffer);
+ }
+ }
+ return result;
+}
+
+error_code DS2476::computeSha2Hmac(Sha256::Hash::span hmac) {
+ error_code result = writeCommand(0x2D);
+ if (!result) {
+ sleep(sha256ComputationTimeMs);
+ array<uint_least8_t, 1 + Sha256::Hash::size> response;
+ result = readFixedLengthResponse(response);
+ if (!result) {
+ result = convertResultByte(response[0]);
+ copy(response.begin() + 1, response.end(), hmac.begin());
+ }
+ }
+ return result;
+}
+
+error_code computeMultiblockHash(DS28C36 & ds28c36,
+ span<const uint_least8_t> data) {
+ error_code result;
+ span<const uint_least8_t>::index_type dataIdx = 0;
+ while (dataIdx < data.size() && !result) {
+ const span<const uint_least8_t>::index_type remainingSize =
+ data.size() - dataIdx;
+ const span<const uint_least8_t>::index_type chunkSize =
+ std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
+ result =
+ ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
+ data.subspan(dataIdx, chunkSize));
+ dataIdx += chunkSize;
+ }
+ return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+ span<const uint_least8_t> data,
+ Signature::const_span signature,
+ DS28C36::PioState pioa,
+ DS28C36::PioState piob) {
+ error_code result = computeMultiblockHash(ds28c36, data);
+ if (!result) {
+ result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
+ pioa, piob);
+ }
+ return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36,
+ PublicKey::const_span publicKey,
+ span<const uint_least8_t> data,
+ Signature::const_span signature,
+ DS28C36::PioState pioa,
+ DS28C36::PioState piob) {
+ error_code result =
+ ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x);
+ if (!result) {
+ result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
+ }
+ if (!result) {
+ result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature,
+ pioa, piob);
+ }
+ return result;
+}
+
+error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId,
+ ManId::span manId) {
+ DS28C36::Page::array page;
+ error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page);
+ if (!result) {
+ const DS28C36::RomOptions romOptions(page);
+ copy(romOptions.romId(), romId);
+ copy(romOptions.manId(), manId);
+ }
+ return result;
+}
+
+error_code enableCoprocessor(DS2476 & ds2476) {
+ DS2476::Page::array page;
+ error_code result = ds2476.readMemory(DS2476::gpioControlPage, page);
+ if (!result) {
+ DS2476::GpioControl gpioControl(page);
+ if (!gpioControl.pioaConducting()) {
+ gpioControl.setPioaConducting(true);
+ result = ds2476.writeMemory(DS2476::gpioControlPage, page);
+ }
+ }
+ return result;
+}
+
+error_code enableRomId(DS2476 & ds2476) {
+ DS2476::Page::array page;
+ error_code result = ds2476.readMemory(DS2476::romOptionsPage, page);
+ if (!result) {
+ DS2476::RomOptions romOptions(page);
+ if (!romOptions.romBlockDisable()) {
+ romOptions.setRomBlockDisable(true);
+ result = ds2476.writeMemory(DS2476::romOptionsPage, page);
+ }
+ }
+ return result;
+}
+
+static void setAnonymous(RomId::span romId) {
+ std::fill(romId.begin(), romId.end(), 0xFF);
+}
+
+DS28C36::PageAuthenticationData &
+DS28C36::PageAuthenticationData::setAnonymousRomId() {
+ setAnonymous(romId());
+ return *this;
+}
+
+DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() {
+ setAnonymous(romId());
+ return *this;
+}
+
+} // namespace MaximInterface
--- a/Devices/DS28C36_DS2476.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28C36_DS2476.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -1,411 +1,923 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_DS28C36_DS2476
-#define MaximInterface_DS28C36_DS2476
-
-#include <stddef.h>
-#include <stdint.h>
-#include <vector>
-#include <MaximInterface/Links/I2CMaster.hpp>
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/array.hpp>
-#include <MaximInterface/Utilities/Ecc256.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/RomId.hpp>
-#include <MaximInterface/Utilities/ManId.hpp>
-#include <MaximInterface/Utilities/Sha256.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-#include <MaximInterface/Utilities/FlagSet.hpp>
-
-namespace MaximInterface {
-
-/// Interface to the DS28C36 authenticator.
-class DS28C36 {
-public:
- /// Device command results.
- enum ErrorValue {
- ProtectionError = 0x55,
- InvalidParameterError = 0x77,
- InvalidSequenceError = 0x33,
- InvalidEcdsaInputOrResultError = 0x22,
- AuthenticationError = 0x100,
- InvalidResponseError = 0x101 ///< Response does not match expected format.
- };
-
- /// Device memory pages.
- enum PageNum {
- UserData0 = 0,
- UserData1,
- UserData2,
- UserData3,
- UserData4,
- UserData5,
- UserData6,
- UserData7,
- UserData8,
- UserData9,
- UserData10,
- UserData11,
- UserData12,
- UserData13,
- UserData14,
- UserData15,
- PublicKeyAX,
- PublicKeyAY,
- PublicKeyBX,
- PublicKeyBY,
- PublicKeyCX,
- PublicKeyCY,
- PrivateKeyA,
- PrivateKeyB,
- PrivateKeyC,
- SecretA,
- SecretB,
- DecrementCounter,
- RomOptions,
- GpioControl,
- PublicKeySX,
- PublicKeySY
- };
-
- /// Available keys for ECDSA operations.
- enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 };
-
- /// Available secrets for HMAC operations.
- enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 };
-
- /// Data hash type when verifying an ECDSA signature.
- enum HashType {
- HashInBuffer = 0, ///< Hash is loaded in the buffer.
- DataInBuffer = 1, ///< Compute hash from data loaded in the buffer.
- THASH = 2 ///< Use THASH from Compute Multiblock Hash command.
- };
-
- /// Available PIO states when verifying an ECDSA signature.
- enum PioState { Unchanged, Conducting, HighImpedance };
-
- /// Holds a device memory page.
- typedef array<uint_least8_t, 32> Page;
-
- /// Holds page authentication input data.
- typedef array<uint_least8_t, 75> PageAuthenticationData;
-
- /// Page protection types.
- enum PageProtectionType {
- RP = 0x01, ///< Read protection.
- WP = 0x02, ///< Write protection.
- EM = 0x04, ///< EPROM emulation mode.
- APH = 0x08, ///< Authentication write protection HMAC.
- EPH = 0x10, ///< Encryption and authenticated write protection HMAC.
- AUTH = 0x20, ///< Public Key C is set to authority public key.
- ECH = 0x40, ///< Encrypted read and write using shared key from ECDH.
- ECW = 0x80 ///< Authentication write protection ECDSA.
- };
- typedef FlagSet<PageProtectionType, 8> PageProtection;
-
- /// Holds an encrypted device memory page.
- struct EncryptedPage {
- typedef array<uint_least8_t, 8> Challenge;
-
- /// Total size of all elements in bytes.
- static const size_t size = Challenge::csize + Page::csize;
-
- Challenge challenge;
- Page data;
- };
-
- /// Number of memory pages on the device.
- static const int memoryPages = 32;
-
- DS28C36(const Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x36)
- : sleep_(&sleep), master(&master), address_(address & 0xFE) {}
-
- void setSleep(const Sleep & sleep) { this->sleep_ = &sleep; }
- void setMaster(I2CMaster & master) { this->master = &master; }
- uint_least8_t address() const { return address_; }
- void setAddress(uint_least8_t address) { this->address_ = (address & 0xFE); }
-
- /// Write memory with no protection.
- /// @param pageNum Number of page to write.
- /// @param page Data to write.
- MaximInterface_EXPORT error_code writeMemory(int pageNum, const Page & page);
-
- /// Read memory with no protection.
- /// @param pageNum Number of page to read.
- /// @param[out] page Data that was read.
- MaximInterface_EXPORT error_code readMemory(int pageNum, Page & page);
-
- /// Write the temporary buffer.
- /// @param data Data to write.
- /// @param dataSize Size of data to write.
- MaximInterface_EXPORT error_code writeBuffer(const uint_least8_t * data,
- size_t dataSize);
-
- /// Read the temporary buffer.
- /// @param[out] data Data that was read.
- MaximInterface_EXPORT error_code
- readBuffer(std::vector<uint_least8_t> & data);
-
- /// Read the protection settings of a page.
- /// @param pageNum Number of page to read.
- /// @param[out] protection Protection that was read.
- MaximInterface_EXPORT error_code
- readPageProtection(int pageNum, PageProtection & protection);
-
- /// Set the protection settings of a page.
- /// @param pageNum Number of page to write.
- /// @param protection Protection to write.
- MaximInterface_EXPORT error_code
- setPageProtection(int pageNum, const PageProtection & protection);
-
- /// Decrement the decrement-only counter.
- MaximInterface_EXPORT error_code decrementCounter();
-
- /// Read a block of random data from the RNG.
- /// @param[out] data Buffer to hold random data from RNG.
- /// @param dataSize Number of bytes to read from 1 to 64 and length of data.
- MaximInterface_EXPORT error_code readRng(uint_least8_t * data,
- size_t dataSize);
-
- /// Read memory with encryption.
- /// @param pageNum Number of page to read from.
- /// @param secretNum Secret to use for encryption.
- /// @param[out] page Data that was read.
- MaximInterface_EXPORT error_code encryptedReadMemory(int pageNum,
- SecretNum secretNum,
- EncryptedPage & page);
-
- /// Compute and read page authentication with ECDSA.
- /// @param pageNum Number of page to authenticate.
- /// @param keyNum Private key to use for authentication.
- /// Key S cannot be used with this command.
- /// @param[out] signature Computed page signature.
- MaximInterface_EXPORT error_code computeAndReadEcdsaPageAuthentication(
- int pageNum, KeyNum keyNum, Ecc256::Signature & signature);
-
- /// Compute and read page authentication with HMAC.
- /// @param pageNum Number of page to authenticate.
- /// @param secretNum Secret to use for authentication.
- /// @param[out] hmac Computed page HMAC.
- MaximInterface_EXPORT error_code computeAndReadHmacPageAuthentication(
- int pageNum, SecretNum secretNum, Sha256::Hash & hmac);
-
- /// Write with SHA2 authentication.
- /// @param pageNum Number of page to write.
- /// @param secretNum Secret to use for authentication.
- /// @param page Data to write.
- MaximInterface_EXPORT error_code authenticatedSha2WriteMemory(
- int pageNum, SecretNum secretNum, const Page & page);
-
- /// Compute SHA2 secret and optionally lock.
- /// @param pageNum Number of page to use in computation.
- /// @param msecretNum Master secret to use in computation.
- /// @param dsecretNum Destination secret to receive the computation result.
- /// @param writeProtectEnable
- /// True to lock the destination secret against further writes.
- MaximInterface_EXPORT error_code
- computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
- SecretNum dsecretNum, bool writeProtectEnable);
-
- /// Generate a new ECDSA key pair.
- /// @param keyNum Key to generate. Key S cannot be used with this command.
- /// @param writeProtectEnable True to lock the key against further writes.
- MaximInterface_EXPORT error_code
- generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
-
- /// Compute a hash over multiple blocks.
- /// @param firstBlock True if this is the first block being hashed.
- /// @param lastBlock True if this is the last block being hashed.
- /// @param data Data block to hash.
- /// @param dataSize Size of data to hash.
- /// Should be 64 bytes unless this is the last block.
- MaximInterface_EXPORT error_code
- computeMultiblockHash(bool firstBlock, bool lastBlock,
- const uint_least8_t * data, size_t dataSize);
-
- /// Verify ECDSA signature.
- /// @param keyNum Public key to use for verification.
- /// @param hashType Source of the data hash input.
- /// @param signature Signature to verify.
- /// @param pioa New state of PIOA if verification successful.
- /// @param piob New state of PIOB if verification successful.
- MaximInterface_EXPORT error_code verifyEcdsaSignature(
- KeyNum keyNum, HashType hashType, const Ecc256::Signature & signature,
- PioState pioa = Unchanged, PioState piob = Unchanged);
-
- /// Authenticate a public key for authenticated writes or encrypted reads with ECDH.
- /// @param authWrites True to select authentication for writes.
- /// @param ecdh True to select ECDH key exchange.
- /// @param keyNum Private key to use for ECDH key exchange.
- /// Key A or B can be selected.
- /// @param csOffset Certificate customization field ending offset in buffer.
- /// @param signature Signature to use for authentication of public key S.
- MaximInterface_EXPORT error_code
- authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
- int csOffset, const Ecc256::Signature & signature);
-
- /// Write with ECDSA authentication.
- /// @param pageNum Number of page to write.
- /// @param page Data to write.
- MaximInterface_EXPORT error_code
- authenticatedEcdsaWriteMemory(int pageNum, const Page & page);
-
- /// Create data used by the Compute and Read Page Authentication command to
- /// generate a signature.
- MaximInterface_EXPORT static PageAuthenticationData
- createPageAuthenticationData(const RomId & romId, const Page & page,
- const Page & challenge, int pageNum,
- const ManId & manId);
-
- MaximInterface_EXPORT static const error_category & errorCategory();
-
-protected:
- // Timing constants.
- static const int generateEcdsaSignatureTimeMs = 50;
- static const int generateEccKeyPairTimeMs = 100;
- static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150;
- static const int sha256ComputationTimeMs = 3;
- static const int readMemoryTimeMs = /*1*/ 2;
- static const int writeMemoryTimeMs = 15;
-
- error_code writeCommand(uint_least8_t command,
- const uint_least8_t * parameters,
- size_t parametersSize);
-
- error_code writeCommand(uint_least8_t command) {
- return writeCommand(command, NULL, 0);
- }
-
- error_code readVariableLengthResponse(uint_least8_t * response,
- size_t & responseSize);
-
- error_code readFixedLengthResponse(uint_least8_t * response,
- size_t responseSize);
-
- void sleep(int ms) const { (*sleep_)(ms); }
-
-private:
- enum AuthType {
- HmacWithSecretA = 0,
- HmacWithSecretB = 1,
- HmacWithSecretS = 2,
- EcdsaWithKeyA = 3,
- EcdsaWithKeyB = 4,
- EcdsaWithKeyC = 5
- };
-
- const Sleep * sleep_;
- I2CMaster * master;
- uint_least8_t address_;
-
- error_code computeAndReadPageAuthentication(int pageNum, AuthType authType);
-};
-
-/// Read the device ROM ID and MAN ID using the Read Memory command on the
-/// ROM Options page.
-/// @param[out] romId
-/// Read ROM ID valid when operation is successful. May be set to NULL.
-/// @param[out] manId
-/// Read MAN ID valid when operation is successful. May be set to NULL.
-MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36,
- RomId * romId,
- ManId * manId);
-
-/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
-/// @param data Data to hash.
-/// @param dataSize Size of data to hash.
-MaximInterface_EXPORT error_code computeMultiblockHash(
- DS28C36 & ds28c36, const uint_least8_t * data, const size_t dataSize);
-
-/// Verify ECDSA signature.
-/// @param publicKey Public key to use for verification.
-/// @param data Data to verify.
-/// @param dataSize Size of data to verify.
-/// @param signature Signature to verify.
-/// @param pioa New state of PIOA if verification successful.
-/// @param piob New state of PIOB if verification successful.
-MaximInterface_EXPORT error_code verifyEcdsaSignature(
- DS28C36 & ds28c36, DS28C36::KeyNum publicKey, const uint_least8_t * data,
- size_t dataSize, const Ecc256::Signature & signature,
- DS28C36::PioState pioa = DS28C36::Unchanged,
- DS28C36::PioState piob = DS28C36::Unchanged);
-
-/// Verify ECDSA signature.
-/// @param publicKey
-/// Public key to use for verification which is loaded into Public Key S.
-/// @param data Data to verify.
-/// @param dataSize Size of data to verify.
-/// @param signature Signature to verify.
-/// @param pioa New state of PIOA if verification successful.
-/// @param piob New state of PIOB if verification successful.
-MaximInterface_EXPORT error_code
-verifyEcdsaSignature(DS28C36 & ds28c36, const Ecc256::PublicKey & publicKey,
- const uint_least8_t * data, size_t dataSize,
- const Ecc256::Signature & signature,
- DS28C36::PioState pioa = DS28C36::Unchanged,
- DS28C36::PioState piob = DS28C36::Unchanged);
-
-inline error_code make_error_code(DS28C36::ErrorValue e) {
- return error_code(e, DS28C36::errorCategory());
-}
-
-/// Interface to the DS2476 coprocessor.
-class DS2476 : public DS28C36 {
-public:
- DS2476(const Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76)
- : DS28C36(sleep, master, address) {}
-
- /// Generate ECDSA signature.
- /// @param keyNum Private key to use to create signature.
- /// Key S cannot be used with this command.
- /// @param[out] signature Computed signature.
- MaximInterface_EXPORT error_code
- generateEcdsaSignature(KeyNum keyNum, Ecc256::Signature & signature);
-
- /// Compute unique SHA2 secret.
- /// @param msecretNum Master secret to use in computation.
- MaximInterface_EXPORT error_code
- computeSha2UniqueSecret(SecretNum msecretNum);
-
- /// Compute SHA2 HMAC.
- /// @param[out] hmac Computed HMAC.
- MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash & hmac);
-};
-
-/// Enable coprocessor functionality on the DS2476 by writing to the
-/// ROM Options page.
-MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476);
-
-} // namespace MaximInterface
-
-#endif
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS28C36_DS2476
+#define MaximInterface_DS28C36_DS2476
+
+#include <stdint.h>
+#include <vector>
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
+#include <MaximInterface/Utilities/Ecc256.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include <MaximInterface/Utilities/ManId.hpp>
+#include <MaximInterface/Utilities/Sha256.hpp>
+#include <MaximInterface/Utilities/system_error.hpp>
+#include <MaximInterface/Utilities/FlagSet.hpp>
+
+namespace MaximInterface {
+
+/// Interface to the DS28C36 authenticator.
+class DS28C36 {
+public:
+ /// Device command results.
+ enum ErrorValue {
+ ProtectionError = 0x55,
+ InvalidParameterError = 0x77,
+ InvalidSequenceError = 0x33,
+ InvalidEcdsaInputOrResultError = 0x22,
+ AuthenticationError = 0x100,
+ InvalidResponseError = 0x101 ///< Response does not match expected format.
+ };
+
+ /// @name Device memory pages
+ /// @{
+
+ static const int publicKeyAxPage = 16;
+ static const int publicKeyAyPage = 17;
+ static const int publicKeyBxPage = 18;
+ static const int publicKeyByPage = 19;
+ static const int publicKeyCxPage = 20;
+ static const int publicKeyCyPage = 21;
+ static const int privateKeyAPage = 22;
+ static const int privateKeyBPage = 23;
+ static const int privateKeyCPage = 24;
+ static const int secretAPage = 25;
+ static const int secretBPage = 26;
+ static const int decrementCounterPage = 27;
+ static const int romOptionsPage = 28;
+ static const int gpioControlPage = 29;
+ static const int publicKeySxPage = 30;
+ static const int publicKeySyPage = 31;
+
+ /// @}
+
+ /// Number of memory pages on the device.
+ static const int memoryPages = 32;
+
+ /// Available keys for ECDSA operations.
+ enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 };
+
+ /// Available secrets for HMAC operations.
+ enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 };
+
+ /// Data hash type when verifying an ECDSA signature.
+ enum HashType {
+ HashInBuffer = 0, ///< Hash is loaded in the buffer.
+ DataInBuffer = 1, ///< Compute hash from data loaded in the buffer.
+ THASH = 2 ///< Use THASH from Compute Multiblock Hash command.
+ };
+
+ /// Available PIO states when verifying an ECDSA signature.
+ enum PioState { Unchanged, Conducting, HighImpedance };
+
+ /// Holds a device memory page.
+ typedef array_span<uint_least8_t, 32> Page;
+
+ // Format page authentication input data.
+ class PageAuthenticationData;
+
+ // Format authenticated write input data.
+ class WriteAuthenticationData;
+
+ // Format compute secret input data.
+ class ComputeSecretData;
+
+ // Format encryption or decryption HMAC input data.
+ class EncryptionHmacData;
+
+ // Access fields in the ROM Options page.
+ class RomOptions;
+
+ // Access fields in the GPIO Control page.
+ class GpioControl;
+
+ /// Page protection types.
+ enum PageProtectionType {
+ RP = 0x01, ///< Read protection.
+ WP = 0x02, ///< Write protection.
+ EM = 0x04, ///< EPROM emulation mode.
+ APH = 0x08, ///< Authentication write protection HMAC.
+ EPH = 0x10, ///< Encryption and authenticated write protection HMAC.
+ AUTH = 0x20, ///< Public Key C is set to authority public key.
+ ECH = 0x40, ///< Encrypted read and write using shared key from ECDH.
+ ECW = 0x80 ///< Authentication write protection ECDSA.
+ };
+ typedef FlagSet<PageProtectionType, 8> PageProtection;
+
+ /// Challenge for an encrypted device memory page.
+ typedef array_span<uint_least8_t, 8> EncryptionChallenge;
+
+ DS28C36(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x36)
+ : sleep_(&sleep), master(&master), address_(address & 0xFE) {}
+
+ void setSleep(Sleep & sleep) { sleep_ = &sleep; }
+
+ void setMaster(I2CMaster & master) { this->master = &master; }
+
+ uint_least8_t address() const { return address_; }
+
+ void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
+
+ /// @brief Write memory with no protection.
+ /// @param pageNum Number of page to write.
+ /// @param page Data to write.
+ MaximInterface_EXPORT error_code writeMemory(int pageNum,
+ Page::const_span page);
+
+ /// @brief Read memory with no protection.
+ /// @param pageNum Number of page to read.
+ /// @param[out] page Data that was read.
+ MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page);
+
+ /// @brief Write the temporary buffer.
+ /// @param data Data to write.
+ MaximInterface_EXPORT error_code writeBuffer(span<const uint_least8_t> data);
+
+ /// @brief Read the temporary buffer.
+ /// @param[out] data Data that was read.
+ MaximInterface_EXPORT error_code
+ readBuffer(std::vector<uint_least8_t> & data);
+
+ /// @brief Read the protection settings of a page.
+ /// @param pageNum Number of page to read.
+ /// @param[out] protection Protection that was read.
+ MaximInterface_EXPORT error_code
+ readPageProtection(int pageNum, PageProtection & protection);
+
+ /// @brief Set the protection settings of a page.
+ /// @param pageNum Number of page to write.
+ /// @param protection Protection to write.
+ MaximInterface_EXPORT error_code
+ setPageProtection(int pageNum, const PageProtection & protection);
+
+ /// Decrement the decrement-only counter.
+ MaximInterface_EXPORT error_code decrementCounter();
+
+ /// @brief Read a block of random data from the RNG.
+ /// @param[out] data Random data from RNG with length from 1 to 64.
+ MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
+
+ /// @brief Read memory with encryption.
+ /// @param pageNum Number of page to read from.
+ /// @param secretNum Secret to use for encryption.
+ /// @param[out] challenge Encryption challenge that was read.
+ /// @param[out] data Encrypted page data that was read.
+ MaximInterface_EXPORT error_code
+ encryptedReadMemory(int pageNum, SecretNum secretNum,
+ EncryptionChallenge::span challenge, Page::span data);
+
+ /// @brief Compute and read page authentication with ECDSA.
+ /// @param pageNum Number of page to authenticate.
+ /// @param keyNum
+ /// Private key to use for authentication.
+ /// Key S cannot be used with this command.
+ /// @param[out] signature Computed page signature.
+ MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
+ int pageNum, KeyNum keyNum, Ecc256::Signature::span signature);
+
+ /// @brief Compute and read page authentication with HMAC.
+ /// @param pageNum Number of page to authenticate.
+ /// @param secretNum Secret to use for authentication.
+ /// @param[out] hmac Computed page HMAC.
+ MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
+ int pageNum, SecretNum secretNum, Sha256::Hash::span hmac);
+
+ /// @brief Write with SHA2 authentication.
+ /// @param pageNum Number of page to write.
+ /// @param secretNum Secret to use for authentication.
+ /// @param page Data to write.
+ MaximInterface_EXPORT error_code authenticatedSha2WriteMemory(
+ int pageNum, SecretNum secretNum, Page::const_span page);
+
+ /// @brief Compute SHA2 secret and optionally lock.
+ /// @param pageNum Number of page to use in computation.
+ /// @param msecretNum Master secret to use in computation.
+ /// @param dsecretNum Destination secret to receive the computation result.
+ /// @param writeProtectEnable
+ /// True to lock the destination secret against further writes.
+ MaximInterface_EXPORT error_code
+ computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+ SecretNum dsecretNum, bool writeProtectEnable);
+
+ /// @brief Generate a new ECDSA key pair.
+ /// @param keyNum Key to generate. Key S cannot be used with this command.
+ /// @param writeProtectEnable True to lock the key against further writes.
+ MaximInterface_EXPORT error_code
+ generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
+
+ /// @brief Compute a hash over multiple blocks.
+ /// @param firstBlock True if this is the first block being hashed.
+ /// @param lastBlock True if this is the last block being hashed.
+ /// @param data
+ /// Data block to hash. Should be 64 bytes unless this is the last block.
+ MaximInterface_EXPORT error_code computeMultiblockHash(
+ bool firstBlock, bool lastBlock, span<const uint_least8_t> data);
+
+ /// @brief Verify ECDSA signature.
+ /// @param keyNum Public key to use for verification.
+ /// @param hashType Source of the data hash input.
+ /// @param signature Signature to verify.
+ /// @param pioa New state of PIOA if verification successful.
+ /// @param piob New state of PIOB if verification successful.
+ MaximInterface_EXPORT error_code verifyEcdsaSignature(
+ KeyNum keyNum, HashType hashType, Ecc256::Signature::const_span signature,
+ PioState pioa = Unchanged, PioState piob = Unchanged);
+
+ /// @brief
+ /// Authenticate a public key for authenticated writes or encrypted reads
+ /// with ECDH.
+ /// @param authWrites True to select authentication for writes.
+ /// @param ecdh True to select ECDH key exchange.
+ /// @param keyNum
+ /// Private key to use for ECDH key exchange. Key A or B can be selected.
+ /// @param csOffset Certificate customization field ending offset in buffer.
+ /// @param signature Signature to use for authentication of public key S.
+ MaximInterface_EXPORT error_code authenticateEcdsaPublicKey(
+ bool authWrites, bool ecdh, KeyNum keyNum, int csOffset,
+ Ecc256::Signature::const_span signature);
+
+ /// @brief Write with ECDSA authentication.
+ /// @param pageNum Number of page to write.
+ /// @param page Data to write.
+ MaximInterface_EXPORT error_code
+ authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page);
+
+ MaximInterface_EXPORT static const error_category & errorCategory();
+
+protected:
+ // Timing constants.
+ static const int generateEcdsaSignatureTimeMs = 50;
+ static const int generateEccKeyPairTimeMs = 100;
+ static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150;
+ static const int sha256ComputationTimeMs = 3;
+ static const int readMemoryTimeMs = /*1*/ 2;
+ static const int writeMemoryTimeMs = 15;
+
+ error_code writeCommand(uint_least8_t command,
+ span<const uint_least8_t> parameters);
+
+ error_code writeCommand(uint_least8_t command) {
+ return writeCommand(command, span<const uint_least8_t>());
+ }
+
+ error_code readVariableLengthResponse(span<uint_least8_t> & response);
+
+ error_code readFixedLengthResponse(span<uint_least8_t> response);
+
+ void sleep(int ms) const { sleep_->invoke(ms); }
+
+private:
+ enum AuthType {
+ HmacWithSecretA = 0,
+ HmacWithSecretB = 1,
+ HmacWithSecretS = 2,
+ EcdsaWithKeyA = 3,
+ EcdsaWithKeyB = 4,
+ EcdsaWithKeyC = 5
+ };
+
+ const Sleep * sleep_;
+ I2CMaster * master;
+ uint_least8_t address_;
+
+ error_code computeAndReadPageAuthentication(int pageNum, AuthType authType);
+};
+
+/// Interface to the DS2476 coprocessor.
+class DS2476 : public DS28C36 {
+public:
+ DS2476(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76)
+ : DS28C36(sleep, master, address) {}
+
+ /// @brief Generate ECDSA signature.
+ /// @param keyNum
+ /// Private key to use to create signature.
+ /// Key S cannot be used with this command.
+ /// @param[out] signature Computed signature.
+ MaximInterface_EXPORT error_code
+ generateEcdsaSignature(KeyNum keyNum, Ecc256::Signature::span signature);
+
+ /// @brief Compute unique SHA2 secret.
+ /// @param msecretNum Master secret to use in computation.
+ MaximInterface_EXPORT error_code
+ computeSha2UniqueSecret(SecretNum msecretNum);
+
+ /// @brief Compute SHA2 HMAC.
+ /// @param[out] hmac Computed HMAC.
+ MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash::span hmac);
+};
+
+inline error_code make_error_code(DS28C36::ErrorValue e) {
+ return error_code(e, DS28C36::errorCategory());
+}
+
+/// @brief
+/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param ds28c36 Device for computation.
+/// @param data Data to hash.
+MaximInterface_EXPORT error_code
+computeMultiblockHash(DS28C36 & ds28c36, span<const uint_least8_t> data);
+
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
+/// @param publicKey Public key to use for verification.
+/// @param data Data to verify.
+/// @param signature Signature to verify.
+/// @param pioa New state of PIOA if verification successful.
+/// @param piob New state of PIOB if verification successful.
+MaximInterface_EXPORT error_code verifyEcdsaSignature(
+ DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+ span<const uint_least8_t> data, Ecc256::Signature::const_span signature,
+ DS28C36::PioState pioa = DS28C36::Unchanged,
+ DS28C36::PioState piob = DS28C36::Unchanged);
+
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
+/// @param publicKey
+/// Public key to use for verification which is loaded into Public Key S.
+/// @param data Data to verify.
+/// @param signature Signature to verify.
+/// @param pioa New state of PIOA if verification successful.
+/// @param piob New state of PIOB if verification successful.
+MaximInterface_EXPORT error_code verifyEcdsaSignature(
+ DS28C36 & ds28c36, Ecc256::PublicKey::const_span publicKey,
+ span<const uint_least8_t> data, Ecc256::Signature::const_span signature,
+ DS28C36::PioState pioa = DS28C36::Unchanged,
+ DS28C36::PioState piob = DS28C36::Unchanged);
+
+/// @brief
+/// Read the device ROM ID and MAN ID using the Read Memory command on the
+/// ROM Options page.
+/// @param ds28c36 Device to read.
+/// @param[out] romId Read ROM ID valid when operation is successful.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36,
+ RomId::span romId,
+ ManId::span manId);
+
+/// @brief
+/// Enable coprocessor functionality on the DS2476 by writing to the
+/// GPIO Control page.
+MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476);
+
+/// @brief
+/// Disable blocking of the ROM ID on the DS2476 by writing to the
+/// ROM Options page.
+MaximInterface_EXPORT error_code enableRomId(DS2476 & ds2476);
+
+/// Format page authentication input data.
+class DS28C36::PageAuthenticationData {
+public:
+ typedef array_span<uint_least8_t,
+ RomId::size + 2 * Page::size + 1 + ManId::size>
+ Result;
+
+ PageAuthenticationData() : result_() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return result_; }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<PageAuthenticationData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ PageAuthenticationData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// Set ROM ID for use in anonymous mode.
+ MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+ /// @}
+
+ /// @name Page
+ /// @brief Data from a device memory page.
+ /// @{
+
+ /// Get mutable page.
+ Page::span page() {
+ return make_span(result_).subspan<pageIdx, Page::size>();
+ }
+
+ /// Get immutable page.
+ Page::const_span page() const {
+ return const_cast<PageAuthenticationData &>(*this).page();
+ }
+
+ /// Set page.
+ PageAuthenticationData & setPage(Page::const_span page) {
+ copy(page, this->page());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Challenge
+ /// @brief Random challenge used to prevent replay attacks.
+ /// @{
+
+ /// Get mutable Challenge.
+ Page::span challenge() {
+ return make_span(result_).subspan<challengeIdx, Page::size>();
+ }
+
+ /// Get immutable Challenge.
+ Page::const_span challenge() const {
+ return const_cast<PageAuthenticationData &>(*this).challenge();
+ }
+
+ /// Set Challenge.
+ PageAuthenticationData & setChallenge(Page::const_span challenge) {
+ copy(challenge, this->challenge());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Number of the page to use data from.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return result_[pageNumIdx]; }
+
+ /// Set page number.
+ PageAuthenticationData & setPageNum(int pageNum) {
+ result_[pageNumIdx] = pageNum;
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<PageAuthenticationData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ PageAuthenticationData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Result::span::index_type index;
+
+ static const index romIdIdx = 0;
+ static const index pageIdx = romIdIdx + RomId::size;
+ static const index challengeIdx = pageIdx + Page::size;
+ static const index pageNumIdx = challengeIdx + Page::size;
+ static const index manIdIdx = pageNumIdx + 1;
+
+ Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28C36::WriteAuthenticationData {
+public:
+ typedef PageAuthenticationData::Result Result;
+
+ WriteAuthenticationData() : data() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return data.result(); }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() { return data.romId(); }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const { return data.romId(); }
+
+ /// Set ROM ID.
+ WriteAuthenticationData & setRomId(RomId::const_span romId) {
+ data.setRomId(romId);
+ return *this;
+ }
+
+ /// Set ROM ID for use in anonymous mode.
+ WriteAuthenticationData & setAnonymousRomId() {
+ data.setAnonymousRomId();
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Old page
+ /// @brief Existing data contained in the page.
+ /// @{
+
+ /// Get mutable old page.
+ Page::span oldPage() { return data.page(); }
+
+ /// Get immutable old page.
+ Page::const_span oldPage() const { return data.page(); }
+
+ /// Set old page.
+ WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+ data.setPage(oldPage);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name New page
+ /// @brief New data to write to the page.
+ /// @{
+
+ /// Get mutable new page.
+ Page::span newPage() { return data.challenge(); }
+
+ /// Get immutable new page.
+ Page::const_span newPage() const { return data.challenge(); }
+
+ /// Set new page.
+ WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+ data.setChallenge(newPage);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Page number for write operation.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return data.pageNum(); }
+
+ /// Set page number.
+ WriteAuthenticationData & setPageNum(int pageNum) {
+ data.setPageNum(pageNum);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() { return data.manId(); }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const { return data.manId(); }
+
+ /// Set MAN ID.
+ WriteAuthenticationData & setManId(ManId::const_span manId) {
+ data.setManId(manId);
+ return *this;
+ }
+
+ /// @}
+
+private:
+ PageAuthenticationData data;
+};
+
+/// Format compute secret input data.
+class DS28C36::ComputeSecretData {
+public:
+ typedef PageAuthenticationData::Result Result;
+
+ ComputeSecretData() : data() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return data.result(); }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() { return data.romId(); }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const { return data.romId(); }
+
+ /// Set ROM ID.
+ ComputeSecretData & setRomId(RomId::const_span romId) {
+ data.setRomId(romId);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Binding Data
+ /// @brief Binding Data contained in the selected page.
+ /// @{
+
+ /// Get mutable Binding Data.
+ Page::span bindingData() { return data.page(); }
+
+ /// Get immutable Binding Data.
+ Page::const_span bindingData() const { return data.page(); }
+
+ /// Set Binding Data.
+ ComputeSecretData & setBindingData(Page::const_span bindingData) {
+ data.setPage(bindingData);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Partial Secret
+ /// @brief Partial Secret used for customization.
+ /// @{
+
+ /// Get mutable Partial Secret.
+ Page::span partialSecret() { return data.challenge(); }
+
+ /// Get immutable Partial Secret.
+ Page::const_span partialSecret() const { return data.challenge(); }
+
+ /// Set Partial Secret.
+ ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
+ data.setChallenge(partialSecret);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Page number for Binding Data.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return data.pageNum(); }
+
+ /// Set page number.
+ ComputeSecretData & setPageNum(int pageNum) {
+ data.setPageNum(pageNum);
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() { return data.manId(); }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const { return data.manId(); }
+
+ /// Set MAN ID.
+ ComputeSecretData & setManId(ManId::const_span manId) {
+ data.setManId(manId);
+ return *this;
+ }
+
+ /// @}
+
+private:
+ PageAuthenticationData data;
+};
+
+/// Format encryption or decryption HMAC input data.
+class DS28C36::EncryptionHmacData {
+public:
+ typedef array_span<uint_least8_t,
+ EncryptionChallenge::size + RomId::size + 1 + ManId::size>
+ Result;
+
+ EncryptionHmacData() : result_() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return result_; }
+
+ /// @name Encryption Challenge
+ /// @brief Random challenge used to prevent replay attacks.
+ /// @{
+
+ /// Get mutable Encryption Challenge.
+ EncryptionChallenge::span encryptionChallenge() {
+ return make_span(result_)
+ .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
+ }
+
+ /// Get immutable Encryption Challenge.
+ EncryptionChallenge::const_span encryptionChallenge() const {
+ return const_cast<EncryptionHmacData &>(*this).encryptionChallenge();
+ }
+
+ /// Set Encryption Challenge.
+ EncryptionHmacData &
+ setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+ copy(encryptionChallenge, this->encryptionChallenge());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<EncryptionHmacData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ EncryptionHmacData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// Set ROM ID for use in anonymous mode.
+ MaximInterface_EXPORT EncryptionHmacData & setAnonymousRomId();
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Number of the page to use data from.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return result_[pageNumIdx]; }
+
+ /// Set page number.
+ EncryptionHmacData & setPageNum(int pageNum) {
+ result_[pageNumIdx] = pageNum;
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<EncryptionHmacData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ EncryptionHmacData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Result::span::index_type index;
+
+ static const index encryptionChallengeIdx = 0;
+ static const index romIdIdx =
+ encryptionChallengeIdx + EncryptionChallenge::size;
+ static const index pageNumIdx = romIdIdx + RomId::size;
+ static const index manIdIdx = pageNumIdx + 1;
+
+ Result::array result_;
+};
+
+/// Access fields in the ROM Options page.
+class DS28C36::RomOptions {
+public:
+ explicit RomOptions(Page::span page) : page(page) {}
+
+ bool romBlockDisable() const {
+ return page[romBlockDisableIdx] == enabledValue;
+ }
+
+ RomOptions & setRomBlockDisable(bool romBlockDisable) {
+ page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0);
+ return *this;
+ }
+
+ bool anonymous() const { return page[anonymousIdx] == enabledValue; }
+
+ RomOptions & setAnonymous(bool anonymous) {
+ page[anonymousIdx] = (anonymous ? enabledValue : 0);
+ return *this;
+ }
+
+ ManId::const_span manId() const {
+ return page.subspan<22, ManId::size>();
+ }
+
+ RomId::const_span romId() const {
+ return page.subspan<24, RomId::size>();
+ }
+
+private:
+ static const Page::span::index_type romBlockDisableIdx = 0;
+ static const Page::span::index_type anonymousIdx = 1;
+ static const Page::span::value_type enabledValue = 0xAA;
+
+ Page::span page;
+};
+
+/// Access fields in the GPIO Control page.
+class DS28C36::GpioControl {
+public:
+ explicit GpioControl(Page::span page) : page(page) {}
+
+ bool pioaConducting() const {
+ return page[pioaConductingIdx] == pioConductingValue;
+ }
+
+ GpioControl & setPioaConducting(bool pioaConducting) {
+ page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55);
+ return *this;
+ }
+
+ bool piobConducting() const {
+ return page[piobConductingIdx] == pioConductingValue;
+ }
+
+ GpioControl & setPiobConducting(bool piobConducting) {
+ page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55);
+ return *this;
+ }
+
+ bool pioaLevel() const { return page[2] == pioLevelValue; }
+
+ bool piobLevel() const { return page[3] == pioLevelValue; }
+
+private:
+ static const Page::span::index_type pioaConductingIdx = 0;
+ static const Page::span::index_type piobConductingIdx = 1;
+ static const Page::span::value_type pioConductingValue = 0xAA;
+ static const Page::span::value_type pioLevelValue = 0x55;
+
+ Page::span page;
+};
+
+} // namespace MaximInterface
+
+#endif
--- a/Devices/DS28E15_22_25.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28E15_22_25.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -31,29 +31,28 @@
*******************************************************************************/
#include <algorithm>
-#include "DS28E15_22_25.hpp"
#include <MaximInterface/Utilities/crc.hpp>
#include <MaximInterface/Utilities/Error.hpp>
-
-using std::copy;
+#include "DS28E15_22_25.hpp"
namespace MaximInterface {
using namespace Sha256;
+using std::copy;
static const int shaComputationDelayMs = 3;
static const int eepromWriteDelayMs = 10;
static inline int secretEepromWriteDelayMs(bool lowPower) {
return lowPower ? 200 : 100;
}
+
static const int ds28e22_25_pagesPerBlock = 2;
static error_code
-writeDataWithCrc(OneWireMaster & master, const uint_least8_t * data,
- size_t dataLen,
+writeDataWithCrc(OneWireMaster & master, span<const uint_least8_t> data,
OneWireMaster::Level level = OneWireMaster::NormalLevel,
uint_fast16_t crcStart = 0) {
- error_code result = master.writeBlock(data, dataLen);
+ error_code result = master.writeBlock(data);
if (result) {
return result;
}
@@ -66,13 +65,20 @@
if (result) {
return result;
}
- if (calculateCrc16(response, sizeof(response) / sizeof(response[0]),
- calculateCrc16(data, dataLen, crcStart)) != 0xB001) {
+ if (calculateCrc16(response, calculateCrc16(data, crcStart)) != 0xB001) {
result = make_error_code(DS28E15_22_25::CrcError);
}
return result;
}
+const int DS28E15_22_25::segmentsPerPage;
+
+DS28E15_22_25::AuthenticationData &
+DS28E15_22_25::AuthenticationData::setAnonymousRomId() {
+ std::fill(romId().begin(), romId().end(), 0xFF);
+ return *this;
+}
+
error_code
DS28E15_22_25::writeCommandWithCrc(Command command, uint_least8_t parameter,
OneWireMaster::Level level) const {
@@ -80,26 +86,23 @@
if (!result) {
const uint_least8_t data[] = {static_cast<uint_least8_t>(command),
parameter};
- result =
- writeDataWithCrc(*master, data, sizeof(data) / sizeof(data[0]), level);
+ result = writeDataWithCrc(*master, data);
}
return result;
}
-static error_code readDataWithCrc(OneWireMaster & master, uint_least8_t * data,
- size_t dataLen) {
- error_code result = master.readBlock(data, dataLen);
+static error_code readDataWithCrc(OneWireMaster & master,
+ span<uint_least8_t> data) {
+ error_code result = master.readBlock(data);
if (result) {
return result;
}
uint_least8_t response[2];
- const size_t responseLen = sizeof(response) / sizeof(response[0]);
- result = master.readBlock(response, responseLen);
+ result = master.readBlock(response);
if (result) {
return result;
}
- if (calculateCrc16(response, responseLen, calculateCrc16(data, dataLen)) !=
- 0xB001) {
+ if (calculateCrc16(response, calculateCrc16(data)) != 0xB001) {
result = make_error_code(DS28E15_22_25::CrcError);
}
return result;
@@ -117,7 +120,7 @@
return result;
}
-static error_code releaseSequence(OneWireMaster & master, const Sleep & sleep,
+static error_code releaseSequence(OneWireMaster & master, Sleep & sleep,
int delayTimeMs) {
error_code result = master.writeBytePower(0xAA);
if (result) {
@@ -131,21 +134,11 @@
return readCsByte(master);
}
-DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection,
- bool writeProtection,
- bool eepromEmulation,
- bool authProtection,
- int blockNum) {
- setReadProtection(readProtection);
- setWriteProtection(writeProtection);
- setEepromEmulation(eepromEmulation);
- setAuthProtection(authProtection);
- setBlockNum(blockNum);
-}
-
-void DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) {
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) {
status &= ~blockNumMask;
status |= (blockNum & blockNumMask);
+ return *this;
}
bool DS28E15_22_25::BlockProtection::noProtection() const {
@@ -153,41 +146,78 @@
!authProtection();
}
-void DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) {
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) {
if (readProtection) {
status |= readProtectionMask;
} else {
status &= ~readProtectionMask;
}
+ return *this;
}
-void DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) {
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) {
if (writeProtection) {
status |= writeProtectionMask;
} else {
status &= ~writeProtectionMask;
}
+ return *this;
}
-void DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) {
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) {
if (eepromEmulation) {
status |= eepromEmulationMask;
} else {
status &= ~eepromEmulationMask;
}
+ return *this;
}
-void DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) {
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) {
if (authProtection) {
status |= authProtectionMask;
} else {
status &= ~authProtectionMask;
}
+ return *this;
+}
+
+DS28E15_22_25::ProtectionWriteMacData::ProtectionWriteMacData()
+ : result_(), oldProtection_(), newProtection_() {
+ setOldProtection(oldProtection_);
+ setNewProtection(newProtection_);
+}
+
+DS28E15_22_25::ProtectionWriteMacData &
+DS28E15_22_25::ProtectionWriteMacData::setOldProtection(
+ BlockProtection oldProtection) {
+ result_[oldProtectionIdx] = oldProtection.authProtection() ? 1 : 0;
+ result_[oldProtectionIdx + 1] = oldProtection.eepromEmulation() ? 1 : 0;
+ result_[oldProtectionIdx + 2] = oldProtection.writeProtection() ? 1 : 0;
+ result_[oldProtectionIdx + 3] = oldProtection.readProtection() ? 1 : 0;
+ oldProtection_ = oldProtection;
+ return *this;
+}
+
+DS28E15_22_25::ProtectionWriteMacData &
+DS28E15_22_25::ProtectionWriteMacData::setNewProtection(
+ BlockProtection newProtection) {
+ result_[blockNumIdx] = newProtection.blockNum();
+ result_[newProtectionIdx] = newProtection.authProtection() ? 1 : 0;
+ result_[newProtectionIdx + 1] = newProtection.eepromEmulation() ? 1 : 0;
+ result_[newProtectionIdx + 2] = newProtection.writeProtection() ? 1 : 0;
+ result_[newProtectionIdx + 3] = newProtection.readProtection() ? 1 : 0;
+ newProtection_ = newProtection;
+ return *this;
}
error_code
-DS28E15_22_25::writeAuthBlockProtection(const BlockProtection & newProtection,
- const Hash & mac) {
+DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection,
+ Hash::const_span mac) {
error_code result =
writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(),
OneWireMaster::StrongLevel);
@@ -195,13 +225,13 @@
return result;
}
- (*sleep)(shaComputationDelayMs);
+ sleep->invoke(shaComputationDelayMs);
result = master->setLevel(OneWireMaster::NormalLevel);
if (result) {
return result;
}
- result = writeDataWithCrc(*master, mac.data(), mac.size());
+ result = writeDataWithCrc(*master, mac);
if (result) {
return result;
}
@@ -215,8 +245,7 @@
return result;
}
-error_code
-DS28E15_22_25::writeBlockProtection(const BlockProtection & protection) {
+error_code DS28E15_22_25::writeBlockProtection(BlockProtection protection) {
error_code result =
writeCommandWithCrc(WriteBlockProtection, protection.statusByte());
if (result) {
@@ -244,33 +273,8 @@
return result;
}
-AuthMacData DS28E15_22_25::createAuthMacData(const Page & pageData, int pageNum,
- const Scratchpad & challenge,
- const RomId & romId,
- const ManId & manId) {
- AuthMacData authMacData;
- AuthMacData::iterator authMacDataIt = authMacData.begin();
- authMacDataIt = copy(pageData.begin(), pageData.end(), authMacDataIt);
- authMacDataIt = copy(challenge.begin(), challenge.end(), authMacDataIt);
- authMacDataIt = copy(romId.begin(), romId.end(), authMacDataIt);
- *authMacDataIt = manId[1];
- *(++authMacDataIt) = manId[0];
- *(++authMacDataIt) = pageNum;
- *(++authMacDataIt) = 0x00;
- return authMacData;
-}
-
-AuthMacData DS28E15_22_25::createAnonAuthMacData(const Page & pageData,
- int pageNum,
- const Scratchpad & challenge,
- const ManId & manId) {
- RomId romId;
- romId.fill(0xFF);
- return createAuthMacData(pageData, pageNum, challenge, romId, manId);
-}
-
error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon,
- Hash & mac) const {
+ Hash::span mac) const {
error_code result =
writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num,
OneWireMaster::StrongLevel);
@@ -278,7 +282,7 @@
return result;
}
- (*sleep)(shaComputationDelayMs * 2);
+ sleep->invoke(shaComputationDelayMs * 2);
result = master->setLevel(OneWireMaster::NormalLevel);
if (result) {
return result;
@@ -289,7 +293,7 @@
return result;
}
- result = readDataWithCrc(*master, mac.data(), mac.size());
+ result = readDataWithCrc(*master, mac);
return result;
}
@@ -307,7 +311,7 @@
return result;
}
-error_code DS28E15_22_25::doWriteScratchpad(const Scratchpad & data,
+error_code DS28E15_22_25::doWriteScratchpad(Scratchpad::const_span data,
Variant variant) {
const uint_least8_t parameter =
(variant == DS28E22 || variant == DS28E25) ? 0x20 : 0x00;
@@ -316,11 +320,11 @@
return result;
}
- result = writeDataWithCrc(*master, data.data(), data.size());
+ result = writeDataWithCrc(*master, data);
return result;
}
-error_code DS28E15_22_25::doReadScratchpad(Scratchpad & data,
+error_code DS28E15_22_25::doReadScratchpad(Scratchpad::span data,
Variant variant) const {
const uint_least8_t parameter =
(variant == DS28E22 || variant == DS28E25) ? 0x2F : 0x0F;
@@ -329,7 +333,7 @@
return result;
}
- result = readDataWithCrc(*master, data.data(), data.size());
+ result = readDataWithCrc(*master, data);
return result;
}
@@ -344,7 +348,7 @@
return result;
}
-error_code DS28E15_22_25::readPage(int page, Page & rdbuf) const {
+error_code DS28E15_22_25::readPage(int page, Page::span rdbuf) const {
error_code result = writeCommandWithCrc(ReadMemory, page);
if (result) {
return result;
@@ -354,31 +358,31 @@
return result;
}
-error_code DS28E15_22_25::continueReadPage(Page & rdbuf) const {
- return readDataWithCrc(*master, rdbuf.data(), rdbuf.size());
+error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const {
+ return readDataWithCrc(*master, rdbuf);
}
-error_code DS28E15_22_25::doWriteAuthSegment(const Segment & newData,
- const Hash & mac, Variant variant,
- bool continuing) {
+error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData,
+ Hash::const_span mac,
+ Variant variant, bool continuing) {
// CRC gets calculated with CS byte when continuing on DS28E22 and DS28E25.
const uint_fast16_t crcStart =
((variant == DS28E22 || variant == DS28E25) && continuing)
? calculateCrc16(0xAA)
: 0;
- error_code result = writeDataWithCrc(*master, newData.data(), newData.size(),
- OneWireMaster::StrongLevel, crcStart);
+ error_code result =
+ writeDataWithCrc(*master, newData, OneWireMaster::StrongLevel, crcStart);
if (result) {
return result;
}
- (*sleep)(shaComputationDelayMs);
+ sleep->invoke(shaComputationDelayMs);
result = master->setLevel(OneWireMaster::NormalLevel);
if (result) {
return result;
}
- result = writeDataWithCrc(*master, mac.data(), mac.size());
+ result = writeDataWithCrc(*master, mac);
if (result) {
return result;
}
@@ -393,8 +397,8 @@
}
error_code DS28E15_22_25::doWriteAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Hash & mac,
+ Segment::const_span newData,
+ Hash::const_span mac,
Variant variant) {
error_code result =
writeCommandWithCrc(AuthWriteMemory, (segmentNum << 5) | pageNum);
@@ -406,67 +410,13 @@
return result;
}
-error_code DS28E15_22_25::doContinueWriteAuthSegment(const Segment & newData,
- const Hash & mac,
- Variant variant) {
+error_code DS28E15_22_25::doContinueWriteAuthSegment(
+ Segment::const_span newData, Hash::const_span mac, Variant variant) {
return doWriteAuthSegment(newData, mac, variant, true);
}
-WriteMacData DS28E15_22_25::createSegmentWriteMacData(
- int pageNum, int segmentNum, const Segment & newData,
- const Segment & oldData, const RomId & romId, const ManId & manId) {
- WriteMacData MT;
-
- // insert ROM number
- copy(romId.begin(), romId.end(), MT.begin());
-
- MT[11] = segmentNum;
- MT[10] = pageNum;
- MT[9] = manId[0];
- MT[8] = manId[1];
-
- // insert old data
- copy(oldData.begin(), oldData.end(), MT.begin() + 12);
-
- // insert new data
- copy(newData.begin(), newData.end(), MT.begin() + 16);
-
- return MT;
-}
-
-WriteMacData DS28E15_22_25::createProtectionWriteMacData(
- const BlockProtection & newProtection,
- const BlockProtection & oldProtection, const RomId & romId,
- const ManId & manId) {
- WriteMacData MT;
-
- // insert ROM number
- copy(romId.begin(), romId.end(), MT.begin());
-
- // instert block and page
- MT[11] = 0;
- MT[10] = newProtection.blockNum();
-
- MT[9] = manId[0];
- MT[8] = manId[1];
-
- // old data
- MT[12] = oldProtection.authProtection() ? 0x01 : 0x00;
- MT[13] = oldProtection.eepromEmulation() ? 0x01 : 0x00;
- MT[14] = oldProtection.writeProtection() ? 0x01 : 0x00;
- MT[15] = oldProtection.readProtection() ? 0x01 : 0x00;
- // new data
- MT[16] = newProtection.authProtection() ? 0x01 : 0x00;
- MT[17] = newProtection.eepromEmulation() ? 0x01 : 0x00;
- MT[18] = newProtection.writeProtection() ? 0x01 : 0x00;
- MT[19] = newProtection.readProtection() ? 0x01 : 0x00;
-
- // compute the mac
- return MT;
-}
-
error_code DS28E15_22_25::readSegment(int page, int segment,
- Segment & data) const {
+ Segment::span data) const {
error_code result = writeCommandWithCrc(ReadMemory, (segment << 5) | page);
if (result) {
return result;
@@ -476,12 +426,12 @@
return result;
}
-error_code DS28E15_22_25::continueReadSegment(Segment & data) const {
- return master->readBlock(data.data(), data.size());
+error_code DS28E15_22_25::continueReadSegment(Segment::span data) const {
+ return master->readBlock(data);
}
error_code DS28E15_22_25::writeSegment(int page, int block,
- const Segment & data) {
+ Segment::const_span data) {
error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page);
if (result) {
return result;
@@ -491,8 +441,8 @@
return result;
}
-error_code DS28E15_22_25::continueWriteSegment(const Segment & data) {
- error_code result = writeDataWithCrc(*master, data.data(), data.size());
+error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) {
+ error_code result = writeDataWithCrc(*master, data);
if (result) {
return result;
}
@@ -501,55 +451,37 @@
return result;
}
-SlaveSecretData
-DS28E15_22_25::createSlaveSecretData(const Page & bindingPage,
- int bindingPageNum,
- const Scratchpad & partialSecret,
- const RomId & romId, const ManId & manId) {
- SlaveSecretData slaveSecretData;
- SlaveSecretData::iterator slaveSecretDataIt = slaveSecretData.begin();
- slaveSecretDataIt =
- copy(bindingPage.begin(), bindingPage.end(), slaveSecretDataIt);
- slaveSecretDataIt =
- copy(partialSecret.begin(), partialSecret.end(), slaveSecretDataIt);
- slaveSecretDataIt = copy(romId.begin(), romId.end(), slaveSecretDataIt);
- *slaveSecretDataIt = manId[1];
- *(++slaveSecretDataIt) = manId[0];
- *(++slaveSecretDataIt) = bindingPageNum;
- *(++slaveSecretDataIt) = 0x00;
- return slaveSecretData;
-}
-
-error_code DS28E15_22_25::doReadAllBlockProtection(BlockProtection * protection,
- const size_t protectionLen,
- Variant variant) const {
+error_code
+DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection,
+ Variant variant) const {
error_code result = writeCommandWithCrc(ReadStatus, 0);
if (!result) {
if (variant == DS28E22 || variant == DS28E25) {
// Need to read extra data on DS28E22 to get CRC16.
uint_least8_t buf[DS28E25::memoryPages];
- result = readDataWithCrc(*master, buf, DS28E25::memoryPages);
+ result = readDataWithCrc(*master, buf);
if (!result) {
const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages
: DS28E25::memoryPages) /
ds28e22_25_pagesPerBlock;
- for (size_t i = 0;
- i < std::min(protectionLen, static_cast<size_t>(blocks)); i++) {
+ for (span<BlockProtection>::index_type i = 0;
+ i < std::min<span<BlockProtection>::index_type>(protection.size(),
+ blocks);
+ ++i) {
protection[i].setStatusByte(
(buf[i * ds28e22_25_pagesPerBlock] & 0xF0) | // Upper nibble
((buf[i * ds28e22_25_pagesPerBlock] & 0x0F) /
ds28e22_25_pagesPerBlock)); // Lower nibble
}
}
- } else // DS28E15
- {
+ } else { // DS28E15
uint_least8_t buf[DS28E15::protectionBlocks];
- result = readDataWithCrc(*master, buf, DS28E15::protectionBlocks);
+ result = readDataWithCrc(*master, buf);
if (!result) {
- for (size_t i = 0;
- i < std::min(protectionLen,
- static_cast<size_t>(DS28E15::protectionBlocks));
- i++) {
+ for (span<BlockProtection>::index_type i = 0;
+ i < std::min<span<BlockProtection>::index_type>(
+ protection.size(), DS28E15::protectionBlocks);
+ ++i) {
protection[i].setStatusByte(buf[i]);
}
}
@@ -592,8 +524,8 @@
error_code DS28E15_22_25::readPersonality(Personality & personality) const {
error_code result = writeCommandWithCrc(ReadStatus, 0xE0);
if (!result) {
- array<uint_least8_t, 4> data;
- result = readDataWithCrc(*master, data.data(), data.size());
+ uint_least8_t data[4];
+ result = readDataWithCrc(*master, data);
if (!result) {
personality.PB1 = data[0];
personality.PB2 = data[1];
@@ -604,11 +536,14 @@
return result;
}
-error_code DS28EL15::writeScratchpad(const Scratchpad & data) {
+const int DS28EL15::memoryPages;
+const int DS28EL15::protectionBlocks;
+
+error_code DS28EL15::writeScratchpad(Scratchpad::const_span data) {
return doWriteScratchpad(data, DS28E15);
}
-error_code DS28EL15::readScratchpad(Scratchpad & data) const {
+error_code DS28EL15::readScratchpad(Scratchpad::span data) const {
return doReadScratchpad(data, DS28E15);
}
@@ -618,20 +553,19 @@
}
error_code DS28EL15::writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Hash & mac) {
+ Segment::const_span newData,
+ Hash::const_span mac) {
return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15);
}
-error_code DS28EL15::continueWriteAuthSegment(const Segment & newData,
- const Hash & mac) {
+error_code DS28EL15::continueWriteAuthSegment(Segment::const_span newData,
+ Hash::const_span mac) {
return doContinueWriteAuthSegment(newData, mac, DS28E15);
}
error_code DS28EL15::readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const {
- return doReadAllBlockProtection(protection.data(), protection.size(),
- DS28E15);
+ span<BlockProtection, protectionBlocks> protection) const {
+ return doReadAllBlockProtection(protection, DS28E15);
}
error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); }
@@ -640,11 +574,14 @@
return doComputeSecret(pageNum, lock, false);
}
-error_code DS28EL22::writeScratchpad(const Scratchpad & data) {
+const int DS28EL22::memoryPages;
+const int DS28EL22::protectionBlocks;
+
+error_code DS28EL22::writeScratchpad(Scratchpad::const_span data) {
return doWriteScratchpad(data, DS28E22);
}
-error_code DS28EL22::readScratchpad(Scratchpad & data) const {
+error_code DS28EL22::readScratchpad(Scratchpad::span data) const {
return doReadScratchpad(data, DS28E22);
}
@@ -654,20 +591,19 @@
}
error_code DS28EL22::writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Hash & mac) {
+ Segment::const_span newData,
+ Hash::const_span mac) {
return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22);
}
-error_code DS28EL22::continueWriteAuthSegment(const Segment & newData,
- const Hash & mac) {
+error_code DS28EL22::continueWriteAuthSegment(Segment::const_span newData,
+ Hash::const_span mac) {
return doContinueWriteAuthSegment(newData, mac, DS28E22);
}
error_code DS28EL22::readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const {
- return doReadAllBlockProtection(protection.data(), protection.size(),
- DS28E22);
+ span<BlockProtection, protectionBlocks> protection) const {
+ return doReadAllBlockProtection(protection, DS28E22);
}
error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); }
@@ -676,11 +612,14 @@
return doComputeSecret(pageNum, lock, false);
}
-error_code DS28EL25::writeScratchpad(const Scratchpad & data) {
+const int DS28EL25::memoryPages;
+const int DS28EL25::protectionBlocks;
+
+error_code DS28EL25::writeScratchpad(Scratchpad::const_span data) {
return doWriteScratchpad(data, DS28E25);
}
-error_code DS28EL25::readScratchpad(Scratchpad & data) const {
+error_code DS28EL25::readScratchpad(Scratchpad::span data) const {
return doReadScratchpad(data, DS28E25);
}
@@ -690,20 +629,19 @@
}
error_code DS28EL25::writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Hash & mac) {
+ Segment::const_span newData,
+ Hash::const_span mac) {
return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25);
}
-error_code DS28EL25::continueWriteAuthSegment(const Segment & newData,
- const Hash & mac) {
+error_code DS28EL25::continueWriteAuthSegment(Segment::const_span newData,
+ Hash::const_span mac) {
return doContinueWriteAuthSegment(newData, mac, DS28E25);
}
error_code DS28EL25::readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const {
- return doReadAllBlockProtection(protection.data(), protection.size(),
- DS28E25);
+ span<BlockProtection, protectionBlocks> protection) const {
+ return doReadAllBlockProtection(protection, DS28E25);
}
error_code DS28E25::loadSecret(bool lock) { return doLoadSecret(lock, false); }
--- a/Devices/DS28E15_22_25.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28E15_22_25.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -33,16 +33,18 @@
#ifndef MaximInterface_DS28E15_22_25
#define MaximInterface_DS28E15_22_25
+#include <stdint.h>
#include <MaximInterface/Links/OneWireMaster.hpp>
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/array.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
#include <MaximInterface/Utilities/Export.h>
#include <MaximInterface/Utilities/ManId.hpp>
#include <MaximInterface/Utilities/Sha256.hpp>
namespace MaximInterface {
+/// @brief
/// Interface to the DS28E15/22/25 series of authenticators
/// including low power variants.
class DS28E15_22_25 {
@@ -50,146 +52,43 @@
enum ErrorValue { CrcError = 1, OperationFailure };
/// Holds the contents of a device memory segment.
- typedef array<uint_least8_t, 4> Segment;
+ typedef array_span<uint_least8_t, 4> Segment;
/// Holds the contents of a device memory page.
- typedef array<uint_least8_t, 32> Page;
+ typedef array_span<uint_least8_t, 32> Page;
/// Number of segments per page.
- static const int segmentsPerPage = Page::csize / Segment::csize;
+ static const int segmentsPerPage = Page::size / Segment::size;
/// Holds the contents of the device scratchpad.
- typedef array<uint_least8_t, 32> Scratchpad;
+ typedef array_span<uint_least8_t, 32> Scratchpad;
- /// Container for the device personality.
+ /// Container for the device personality.
struct Personality {
uint_least8_t PB1;
uint_least8_t PB2;
- ManId manId;
-
+ ManId::array manId;
+
bool secretLocked() const { return PB2 & 0x01; }
};
- /// Represents the status of a memory protection block.
- class BlockProtection {
- private:
- static const unsigned int readProtectionMask = 0x80,
- writeProtectionMask = 0x40,
- eepromEmulationMask = 0x20,
- authProtectionMask = 0x10,
- blockNumMask = 0x0F;
- uint_least8_t status;
-
- public:
- explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
- MaximInterface_EXPORT BlockProtection(bool readProtection,
- bool writeProtection,
- bool eepromEmulation,
- bool authProtection,
- int blockNum);
-
- /// Get the byte representation used by the device.
- uint_least8_t statusByte() const { return status; }
- /// Set the byte representation used by the device.
- void setStatusByte(uint_least8_t status) { this->status = status; }
-
- /// Get the Block Number which is indexed from zero.
- int blockNum() const { return (status & blockNumMask); }
- /// Set the Block Number which is indexed from zero.
- MaximInterface_EXPORT void setBlockNum(int blockNum);
+ // Represents the status of a memory protection block.
+ class BlockProtection;
- /// Get the Read Protection status.
- /// @returns True if Read Protection is enabled.
- bool readProtection() const {
- return ((status & readProtectionMask) == readProtectionMask);
- }
- /// Set the Read Protection status.
- MaximInterface_EXPORT void setReadProtection(bool readProtection);
-
- /// Get the Write Protection status.
- /// @returns True if Write Protection is enabled.
- bool writeProtection() const {
- return ((status & writeProtectionMask) == writeProtectionMask);
- }
- /// Set the Write Protection status.
- MaximInterface_EXPORT void setWriteProtection(bool writeProtection);
+ // Format data to hash for an Authenticated Write to a memory segment.
+ class SegmentWriteMacData;
- /// Get the EEPROM Emulation Mode status.
- /// @returns True if EEPROM Emulation Mode is enabled.
- bool eepromEmulation() const {
- return ((status & eepromEmulationMask) == eepromEmulationMask);
- }
- /// Set the EEPROM Emulation Mode status.
- MaximInterface_EXPORT void setEepromEmulation(bool eepromEmulation);
-
- /// Get the Authentication Protection status.
- /// @returns True if Authentication Protection is enabled.
- bool authProtection() const {
- return ((status & authProtectionMask) == authProtectionMask);
- }
- /// Set the Authentication Protection status.
- MaximInterface_EXPORT void setAuthProtection(bool authProtection);
+ // Format data to hash for an Authenticated Write to a memory protection block.
+ class ProtectionWriteMacData;
- /// Check if no protection options are enabled.
- /// @returns True if no protection options are enabled.
- MaximInterface_EXPORT bool noProtection() const;
- };
-
- /// Format data to hash for an Authenticated Write to a memory segment.
- /// @param pageNum Page number for write operation.
- /// @param segmentNum Segment number within page for write operation.
- /// @param[in] newData New data to write to the segment.
- /// @param[in] oldData Existing data contained in the segment.
- /// @param[in] romId 1-Wire ROM ID of the device.
- /// @param[in] manId Manufacturer ID of the device.
- MaximInterface_EXPORT static Sha256::WriteMacData
- createSegmentWriteMacData(int pageNum, int segmentNum,
- const Segment & newData, const Segment & oldData,
- const RomId & romId, const ManId & manId);
-
- /// Format data to hash for an Authenticated Write to a memory protection block.
- /// @param[in] newProtection New protection status to write.
- /// @param[in] oldProtection Existing protection status in device.
- /// @param[in] romId 1-Wire ROM ID of the device.
- /// @param[in] manId Manufacturer ID of the device.
- MaximInterface_EXPORT static Sha256::WriteMacData
- createProtectionWriteMacData(const BlockProtection & newProtection,
- const BlockProtection & oldProtection,
- const RomId & romId, const ManId & manId);
+ // Format data to hash for device authentication or computing the next secret
+ // from the existing secret.
+ class AuthenticationData;
- /// Format data to hash to compute the next secret from the existing secret.
- /// @param[in] bindingPage Binding data from a device memory page.
- /// @param bindingPageNum Number of the page where the binding data is from.
- /// @param[in] partialSecret Partial secret data from the device scratchpad.
- /// @param[in] romId 1-Wire ROM ID of the device.
- /// @param[in] manId Manufacturer ID of the device.
- MaximInterface_EXPORT static Sha256::SlaveSecretData
- createSlaveSecretData(const Page & bindingPage, int bindingPageNum,
- const Scratchpad & partialSecret, const RomId & romId,
- const ManId & manId);
-
- /// Format data to hash for device authentication.
- /// @param[in] pageData Data from a device memory page.
- /// @param pageNum Number of the page to use data from.
- /// @param[in] challenge Random challenge to prevent replay attacks.
- /// @param[in] romId 1-Wire ROM ID of the device.
- /// @param[in] manId Manufacturer ID of the device.
- MaximInterface_EXPORT static Sha256::AuthMacData
- createAuthMacData(const Page & pageData, int pageNum,
- const Scratchpad & challenge, const RomId & romId,
- const ManId & manId);
-
- /// Format datat to hash for device authentication using anonymous mode.
- /// @param[in] pageData Data from a device memory page.
- /// @param pageNum Number of the page to use data from.
- /// @param[in] challenge Random challenge to prevent replay attacks.
- /// @param[in] manId Manufacturer ID of the device.
- MaximInterface_EXPORT static Sha256::AuthMacData
- createAnonAuthMacData(const Page & pageData, int pageNum,
- const Scratchpad & challenge, const ManId & manId);
-
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
@@ -197,74 +96,81 @@
// Const member functions should not affect the state of the memory,
// block protection, or secret on the device.
- /// Read memory segment using the Read Memory command on the device.
+ /// @brief Read memory segment using the Read Memory command on the device.
/// @param pageNum Page number for read operation.
/// @param segmentNum Segment number within page for read operation.
/// @param[out] data Buffer to read data from the segment into.
MaximInterface_EXPORT error_code readSegment(int pageNum, int segmentNum,
- Segment & data) const;
+ Segment::span data) const;
- /// Continue an in-progress readSegment operation.
+ /// @brief Continue an in-progress readSegment operation.
/// @note A CRC16 will encountered after reading the last segment of a page.
/// @param[out] data Buffer to read data from the segment into.
- MaximInterface_EXPORT error_code continueReadSegment(Segment & data) const;
+ MaximInterface_EXPORT error_code
+ continueReadSegment(Segment::span data) const;
- /// Write memory segment using the Write Memory command.
+ /// @brief Write memory segment using the Write Memory command.
/// @note 1-Wire ROM selection should have already occurred.
/// @param pageNum Page number for write operation.
/// @param segmentNum Segment number within page for write operation.
/// @param[in] data Data to write to the memory segment.
MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
- const Segment & data);
+ Segment::const_span data);
- /// Continue an in-progress Write Memory command.
+ /// @brief Continue an in-progress Write Memory command.
/// @param[in] data Data to write to the memory segment.
- MaximInterface_EXPORT error_code continueWriteSegment(const Segment & data);
+ MaximInterface_EXPORT error_code
+ continueWriteSegment(Segment::const_span data);
- /// Read memory page using the Read Memory command on the device.
+ /// @brief Read memory page using the Read Memory command on the device.
/// @param pageNum Page number for write operation.
/// @param[out] rdbuf Buffer to read data from the page into.
- MaximInterface_EXPORT error_code readPage(int pageNum, Page & rdbuf) const;
+ MaximInterface_EXPORT error_code readPage(int pageNum,
+ Page::span rdbuf) const;
- /// Continue an in-progress readPageOperation.
+ /// @brief Continue an in-progress readPageOperation.
/// @param[out] rdbuf Buffer to read data from the page into.
- MaximInterface_EXPORT error_code continueReadPage(Page & rdbuf) const;
+ MaximInterface_EXPORT error_code continueReadPage(Page::span rdbuf) const;
+ /// @brief
/// Perform a Compute Page MAC command on the device.
/// Read back the MAC and verify the CRC16.
/// @param pageNum Page number to use for the computation.
/// @param anon True to compute in anonymous mode where ROM ID is not used.
/// @param[out] mac The device computed MAC.
- MaximInterface_EXPORT error_code computeReadPageMac(int pageNum, bool anon,
- Sha256::Hash & mac) const;
+ MaximInterface_EXPORT error_code
+ computeReadPageMac(int pageNum, bool anon, Sha256::Hash::span mac) const;
+ /// @brief
/// Update the status of a memory protection block using the
/// Write Page Protection command.
- /// @param[in] Desired protection status for the block.
- /// It is not possible to disable existing protections.
- /// @param continuing True to continue a previous Write Page Protection command.
- /// False to begin a new command.
+ /// @param protection
+ /// Desired protection status for the block.
+ /// It is not possible to disable existing protections.
MaximInterface_EXPORT error_code
- writeBlockProtection(const BlockProtection & protection);
+ writeBlockProtection(BlockProtection protection);
+ /// @brief
/// Update the status of a memory protection block using the
/// Authenticated Write Page Protection command.
- /// @param[in] newProtection New protection status to write.
+ /// @param newProtection New protection status to write.
/// @param[in] mac Write MAC computed for this operation.
MaximInterface_EXPORT error_code writeAuthBlockProtection(
- const BlockProtection & newProtection, const Sha256::Hash & mac);
+ BlockProtection newProtection, Sha256::Hash::const_span mac);
- /// Perform Load and Lock Secret command on the device.
+ /// @brief Perform Load and Lock Secret command on the device.
/// @note The secret should already be stored in the scratchpad on the device.
- /// @param lock Prevent further changes to the secret on the device after loading.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after loading.
MaximInterface_EXPORT error_code loadSecret(bool lock);
- /// Perform a Compute and Lock Secret command on the device.
+ /// @brief Perform a Compute and Lock Secret command on the device.
/// @param pageNum Page number to use as the binding data.
- /// @param lock Prevent further changes to the secret on the device after computing.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after computing.
MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
- /// Read the personality bytes using the Read Status command.
+ /// @brief Read the personality bytes using the Read Status command.
/// @param[out] personality Receives personality read from device.
MaximInterface_EXPORT error_code
readPersonality(Personality & personality) const;
@@ -274,27 +180,28 @@
protected:
enum Variant { DS28E15, DS28E22, DS28E25 };
- DS28E15_22_25(const Sleep & sleep, OneWireMaster & master,
+ DS28E15_22_25(Sleep & sleep, OneWireMaster & master,
const SelectRom & selectRom)
: selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+ ~DS28E15_22_25() {}
- error_code doWriteScratchpad(const Scratchpad & data, Variant variant);
+ error_code doWriteScratchpad(Scratchpad::const_span data, Variant variant);
- error_code doReadScratchpad(Scratchpad & data, Variant variant) const;
+ error_code doReadScratchpad(Scratchpad::span data, Variant variant) const;
error_code doReadBlockProtection(int blockNum, BlockProtection & protection,
Variant variant) const;
error_code doWriteAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Sha256::Hash & mac, Variant variant);
+ Segment::const_span newData,
+ Sha256::Hash::const_span mac, Variant variant);
- error_code doContinueWriteAuthSegment(const Segment & newData,
- const Sha256::Hash & mac,
+ error_code doContinueWriteAuthSegment(Segment::const_span newData,
+ Sha256::Hash::const_span mac,
Variant variant);
- error_code doReadAllBlockProtection(BlockProtection * protection,
- size_t protectionLen,
+ error_code doReadAllBlockProtection(span<BlockProtection> protection,
Variant variant) const;
error_code doLoadSecret(bool lock, bool lowPower);
@@ -315,8 +222,8 @@
AuthWriteBlockProtection = 0xCC,
};
- error_code doWriteAuthSegment(const Segment & newData,
- const Sha256::Hash & mac, Variant variant,
+ error_code doWriteAuthSegment(Segment::const_span newData,
+ Sha256::Hash::const_span mac, Variant variant,
bool continuing);
error_code writeCommandWithCrc(
@@ -325,23 +232,13 @@
SelectRom selectRom;
OneWireMaster * master;
- const Sleep * sleep;
+ Sleep * sleep;
};
inline error_code make_error_code(DS28E15_22_25::ErrorValue e) {
return error_code(e, DS28E15_22_25::errorCategory());
}
-inline bool operator==(DS28E15_22_25::BlockProtection lhs,
- DS28E15_22_25::BlockProtection rhs) {
- return lhs.statusByte() == rhs.statusByte();
-}
-
-inline bool operator!=(DS28E15_22_25::BlockProtection lhs,
- DS28E15_22_25::BlockProtection rhs) {
- return !operator==(lhs, rhs);
-}
-
/// Interface to the DS28EL15 (low power) authenticator.
class DS28EL15 : public DS28E15_22_25 {
public:
@@ -349,18 +246,150 @@
static const int memoryPages = 2;
static const int protectionBlocks = 4;
- DS28EL15(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
+ DS28EL15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+ : DS28E15_22_25(sleep, master, selectRom) {}
+
+ /// @brief Perform Write Scratchpad operation on the device.
+ /// @param[in] data Data to write to the scratchpad.
+ MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
+
+ /// @brief Perform a Read Scratchpad operation on the device.
+ /// @param[out] data Buffer to read data from the scratchpad into.
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
+
+ /// @brief
+ /// Read the status of a memory protection block using the Read Status command.
+ /// @param blockNum Block number to to read status of.
+ /// @param[out] protection Receives protection status read from device.
+ MaximInterface_EXPORT error_code
+ readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+ /// @brief Write memory segment using the Authenticated Write Memory command.
+ /// @param pageNum Page number for write operation.
+ /// @param segmentNum Segment number within page for write operation.
+ /// @param[in] newData New data to write to the segment.
+ /// @param[in] mac Write MAC computed for this operation.
+ MaximInterface_EXPORT error_code
+ writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+ Sha256::Hash::const_span mac);
+
+ /// @brief Continue an in-progress Authenticated Write Memory command.
+ /// @param[in] newData New data to write to the segment.
+ /// @param[in] mac Write MAC computed for this operation.
+ MaximInterface_EXPORT error_code continueWriteAuthSegment(
+ Segment::const_span newData, Sha256::Hash::const_span mac);
+
+ /// @brief
+ /// Read the status of all memory protection blocks using the Read Status command.
+ /// @param[out] protection Receives protection statuses read from device.
+ MaximInterface_EXPORT error_code readAllBlockProtection(
+ span<BlockProtection, protectionBlocks> protection) const;
+};
+
+/// Interface to the DS28E15 authenticator.
+class DS28E15 : public DS28EL15 {
+public:
+ DS28E15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+ : DS28EL15(sleep, master, selectRom) {}
+
+ /// @brief Perform Load and Lock Secret command on the device.
+ /// @note The secret should already be stored in the scratchpad on the device.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after loading.
+ MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+ /// @brief Perform a Compute and Lock Secret command on the device.
+ /// @param pageNum Page number to use as the binding data.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after computing.
+ MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+/// Interface to the DS28EL22 (low power) authenticator.
+class DS28EL22 : public DS28E15_22_25 {
+public:
+ // DS28E15_22_25 traits
+ static const int memoryPages = 8;
+ static const int protectionBlocks = 4;
+
+ DS28EL22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
: DS28E15_22_25(sleep, master, selectRom) {}
- /// Perform Write Scratchpad operation on the device.
+ /// @brief Perform Write Scratchpad operation on the device.
/// @param[in] data Data to write to the scratchpad.
- MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+ MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
+
+ /// @brief Perform a Read Scratchpad operation on the device.
+ /// @param[out] data Buffer to read data from the scratchpad into.
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
+
+ /// @brief
+ /// Read the status of a memory protection block using the Read Status command.
+ /// @param blockNum Block number to to read status of.
+ /// @param[out] protection Receives protection status read from device.
+ MaximInterface_EXPORT error_code
+ readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+ /// @brief Write memory segment using the Authenticated Write Memory command.
+ /// @param pageNum Page number for write operation.
+ /// @param segmentNum Segment number within page for write operation.
+ /// @param[in] newData New data to write to the segment.
+ /// @param[in] mac Write MAC computed for this operation.
+ MaximInterface_EXPORT error_code
+ writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+ Sha256::Hash::const_span mac);
+
+ /// @brief Continue an in-progress Authenticated Write Memory command.
+ /// @param[in] newData New data to write to the segment.
+ /// @param[in] mac Write MAC computed for this operation.
+ MaximInterface_EXPORT error_code continueWriteAuthSegment(
+ Segment::const_span newData, Sha256::Hash::const_span mac);
+
+ /// @brief
+ /// Read the status of all memory protection blocks using the Read Status command.
+ /// @param[out] protection Receives protection statuses read from device.
+ MaximInterface_EXPORT error_code readAllBlockProtection(
+ span<BlockProtection, protectionBlocks> protection) const;
+};
- /// Perform a Read Scratchpad operation on the device.
+/// Interface to the DS28E22 authenticator.
+class DS28E22 : public DS28EL22 {
+public:
+ DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+ : DS28EL22(sleep, master, selectRom) {}
+
+ /// @brief Perform Load and Lock Secret command on the device.
+ /// @note The secret should already be stored in the scratchpad on the device.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after loading.
+ MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+ /// @brief Perform a Compute and Lock Secret command on the device.
+ /// @param pageNum Page number to use as the binding data.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after computing.
+ MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+/// Interface to the DS28EL25 (low power) authenticator.
+class DS28EL25 : public DS28E15_22_25 {
+public:
+ // DS28E15_22_25 traits
+ static const int memoryPages = 16;
+ static const int protectionBlocks = 8;
+
+ DS28EL25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+ : DS28E15_22_25(sleep, master, selectRom) {}
+
+ /// @brief Perform Write Scratchpad operation on the device.
+ /// @param[in] data Data to write to the scratchpad.
+ MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
+
+ /// @brief Perform a Read Scratchpad operation on the device.
/// @param[out] data Buffer to read data from the scratchpad into.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
+ MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
+ /// @brief
/// Read the status of a memory protection block using the Read Status command.
/// @param blockNum Block number to to read status of.
/// @param[out] protection Receives protection status read from device.
@@ -372,168 +401,485 @@
/// @param segmentNum Segment number within page for write operation.
/// @param[in] newData New data to write to the segment.
/// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Sha256::Hash & mac);
+ MaximInterface_EXPORT error_code
+ writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+ Sha256::Hash::const_span mac);
- /// Continue an in-progress Authenticated Write Memory command.
+ /// @brief Continue an in-progress Authenticated Write Memory command.
/// @param[in] newData New data to write to the segment.
/// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code
- continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
+ MaximInterface_EXPORT error_code continueWriteAuthSegment(
+ Segment::const_span newData, Sha256::Hash::const_span mac);
+ /// @brief
/// Read the status of all memory protection blocks using the Read Status command.
/// @param[out] protection Receives protection statuses read from device.
MaximInterface_EXPORT error_code readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const;
-};
-
-/// Interface to the DS28E15 authenticator.
-class DS28E15 : public DS28EL15 {
-public:
- DS28E15(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
- : DS28EL15(sleep, master, selectRom) {}
-
- /// Perform Load and Lock Secret command on the device.
- /// @note The secret should already be stored in the scratchpad on the device.
- /// @param lock Prevent further changes to the secret on the device after loading.
- MaximInterface_EXPORT error_code loadSecret(bool lock);
-
- /// Perform a Compute and Lock Secret command on the device.
- /// @param pageNum Page number to use as the binding data.
- /// @param lock Prevent further changes to the secret on the device after computing.
- MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
-};
-
-/// Interface to the DS28EL22 (low power) authenticator.
-class DS28EL22 : public DS28E15_22_25 {
-public:
- // DS28E15_22_25 traits
- static const int memoryPages = 8;
- static const int protectionBlocks = 4;
-
- DS28EL22(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
- : DS28E15_22_25(sleep, master, selectRom) {}
-
- /// Perform Write Scratchpad operation on the device.
- /// @param[in] data Data to write to the scratchpad.
- MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
-
- /// Perform a Read Scratchpad operation on the device.
- /// @param[out] data Buffer to read data from the scratchpad into.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
-
- /// Read the status of a memory protection block using the Read Status command.
- /// @param blockNum Block number to to read status of.
- /// @param[out] protection Receives protection status read from device.
- MaximInterface_EXPORT error_code
- readBlockProtection(int blockNum, BlockProtection & protection) const;
-
- /// Write memory segment using the Authenticated Write Memory command.
- /// @param pageNum Page number for write operation.
- /// @param segmentNum Segment number within page for write operation.
- /// @param[in] newData New data to write to the segment.
- /// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Sha256::Hash & mac);
-
- /// Continue an in-progress Authenticated Write Memory command.
- /// @param[in] newData New data to write to the segment.
- /// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code
- continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
-
- /// Read the status of all memory protection blocks using the Read Status command.
- /// @param[out] protection Receives protection statuses read from device.
- MaximInterface_EXPORT error_code readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const;
-};
-
-/// Interface to the DS28E22 authenticator.
-class DS28E22 : public DS28EL22 {
-public:
- DS28E22(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
- : DS28EL22(sleep, master, selectRom) {}
-
- /// Perform Load and Lock Secret command on the device.
- /// @note The secret should already be stored in the scratchpad on the device.
- /// @param lock Prevent further changes to the secret on the device after loading.
- MaximInterface_EXPORT error_code loadSecret(bool lock);
-
- /// Perform a Compute and Lock Secret command on the device.
- /// @param pageNum Page number to use as the binding data.
- /// @param lock Prevent further changes to the secret on the device after computing.
- MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
-};
-
-/// Interface to the DS28EL25 (low power) authenticator.
-class DS28EL25 : public DS28E15_22_25 {
-public:
- // DS28E15_22_25 traits
- static const int memoryPages = 16;
- static const int protectionBlocks = 8;
-
- DS28EL25(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
- : DS28E15_22_25(sleep, master, selectRom) {}
-
- /// Perform Write Scratchpad operation on the device.
- /// @param[in] data Data to write to the scratchpad.
- MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
-
- /// Perform a Read Scratchpad operation on the device.
- /// @param[out] data Buffer to read data from the scratchpad into.
- MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
-
- /// Read the status of a memory protection block using the Read Status command.
- /// @param blockNum Block number to to read status of.
- /// @param[out] protection Receives protection status read from device.
- MaximInterface_EXPORT error_code
- readBlockProtection(int blockNum, BlockProtection & protection) const;
-
- /// Write memory segment using the Authenticated Write Memory command.
- /// @param pageNum Page number for write operation.
- /// @param segmentNum Segment number within page for write operation.
- /// @param[in] newData New data to write to the segment.
- /// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
- const Segment & newData,
- const Sha256::Hash & mac);
-
- /// Continue an in-progress Authenticated Write Memory command.
- /// @param[in] newData New data to write to the segment.
- /// @param[in] mac Write MAC computed for this operation.
- MaximInterface_EXPORT error_code
- continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
-
- /// Read the status of all memory protection blocks using the Read Status command.
- /// @param[out] protection Receives protection statuses read from device.
- MaximInterface_EXPORT error_code readAllBlockProtection(
- array<BlockProtection, protectionBlocks> & protection) const;
+ span<BlockProtection, protectionBlocks> protection) const;
};
/// Interface to the DS28E25 authenticator.
class DS28E25 : public DS28EL25 {
public:
- DS28E25(const Sleep & sleep, OneWireMaster & master,
- const SelectRom & selectRom)
+ DS28E25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
: DS28EL25(sleep, master, selectRom) {}
- /// Perform Load and Lock Secret command on the device.
+ /// @brief Perform Load and Lock Secret command on the device.
/// @note The secret should already be stored in the scratchpad on the device.
/// @param lock Prevent further changes to the secret on the device after loading.
MaximInterface_EXPORT error_code loadSecret(bool lock);
- /// Perform a Compute and Lock Secret command on the device.
+ /// @brief Perform a Compute and Lock Secret command on the device.
/// @param pageNum Page number to use as the binding data.
- /// @param lock Prevent further changes to the secret on the device after computing.
+ /// @param lock
+ /// Prevent further changes to the secret on the device after computing.
MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
};
+/// Represents the status of a memory protection block.
+class DS28E15_22_25::BlockProtection {
+public:
+ explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
+
+ /// Get the byte representation used by the device.
+ uint_least8_t statusByte() const { return status; }
+
+ /// Set the byte representation used by the device.
+ BlockProtection & setStatusByte(uint_least8_t status) {
+ this->status = status;
+ return *this;
+ }
+
+ /// Get the Block Number which is indexed from zero.
+ int blockNum() const { return (status & blockNumMask); }
+
+ /// Set the Block Number which is indexed from zero.
+ MaximInterface_EXPORT BlockProtection & setBlockNum(int blockNum);
+
+ /// @brief Get the Read Protection status.
+ /// @returns True if Read Protection is enabled.
+ bool readProtection() const {
+ return ((status & readProtectionMask) == readProtectionMask);
+ }
+
+ /// Set the Read Protection status.
+ MaximInterface_EXPORT BlockProtection &
+ setReadProtection(bool readProtection);
+
+ /// @brief Get the Write Protection status.
+ /// @returns True if Write Protection is enabled.
+ bool writeProtection() const {
+ return ((status & writeProtectionMask) == writeProtectionMask);
+ }
+
+ /// Set the Write Protection status.
+ MaximInterface_EXPORT BlockProtection &
+ setWriteProtection(bool writeProtection);
+
+ /// @brief Get the EEPROM Emulation Mode status.
+ /// @returns True if EEPROM Emulation Mode is enabled.
+ bool eepromEmulation() const {
+ return ((status & eepromEmulationMask) == eepromEmulationMask);
+ }
+
+ /// Set the EEPROM Emulation Mode status.
+ MaximInterface_EXPORT BlockProtection &
+ setEepromEmulation(bool eepromEmulation);
+
+ /// @brief Get the Authentication Protection status.
+ /// @returns True if Authentication Protection is enabled.
+ bool authProtection() const {
+ return ((status & authProtectionMask) == authProtectionMask);
+ }
+
+ /// Set the Authentication Protection status.
+ MaximInterface_EXPORT BlockProtection &
+ setAuthProtection(bool authProtection);
+
+ /// @brief Check if no protection options are enabled.
+ /// @returns True if no protection options are enabled.
+ MaximInterface_EXPORT bool noProtection() const;
+
+private:
+ static const unsigned int readProtectionMask = 0x80,
+ writeProtectionMask = 0x40,
+ eepromEmulationMask = 0x20,
+ authProtectionMask = 0x10,
+ blockNumMask = 0x0F;
+ uint_least8_t status;
+};
+
+inline bool operator==(DS28E15_22_25::BlockProtection lhs,
+ DS28E15_22_25::BlockProtection rhs) {
+ return lhs.statusByte() == rhs.statusByte();
+}
+
+inline bool operator!=(DS28E15_22_25::BlockProtection lhs,
+ DS28E15_22_25::BlockProtection rhs) {
+ return !operator==(lhs, rhs);
+}
+
+/// Format data to hash for an Authenticated Write to a memory segment.
+class DS28E15_22_25::SegmentWriteMacData {
+public:
+ SegmentWriteMacData() : result_() {}
+
+ /// Formatted data result.
+ Sha256::WriteMacData::const_span result() const { return result_; }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<SegmentWriteMacData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ SegmentWriteMacData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<SegmentWriteMacData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ SegmentWriteMacData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Page number for write operation.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return result_[pageNumIdx]; }
+
+ /// Set page number.
+ SegmentWriteMacData & setPageNum(int pageNum) {
+ result_[pageNumIdx] = pageNum;
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Segment number
+ /// @brief Segment number within page for write operation.
+ /// @{
+
+ /// Get segment number.
+ int segmentNum() const { return result_[segmentNumIdx]; }
+
+ /// Set segment number.
+ SegmentWriteMacData & setSegmentNum(int segmentNum) {
+ result_[segmentNumIdx] = segmentNum;
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Old data
+ /// @brief Existing data contained in the segment.
+ /// @{
+
+ /// Get mutable old data.
+ Segment::span oldData() {
+ return make_span(result_).subspan<oldDataIdx, Segment::size>();
+ }
+
+ /// Get immutable old data.
+ Segment::const_span oldData() const {
+ return const_cast<SegmentWriteMacData &>(*this).oldData();
+ }
+
+ /// Set old data.
+ SegmentWriteMacData & setOldData(Segment::const_span oldData) {
+ copy(oldData, this->oldData());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name New data
+ /// @brief New data to write to the segment.
+ /// @{
+
+ /// Get mutable new data.
+ Segment::span newData() {
+ return make_span(result_).subspan<newDataIdx, Segment::size>();
+ }
+
+ /// Get immutable new data.
+ Segment::const_span newData() const {
+ return const_cast<SegmentWriteMacData &>(*this).newData();
+ }
+
+ /// Set new data.
+ SegmentWriteMacData & setNewData(Segment::const_span newData) {
+ copy(newData, this->newData());
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Sha256::WriteMacData::span::index_type index;
+
+ static const index romIdIdx = 0;
+ static const index manIdIdx = romIdIdx + RomId::size;
+ static const index pageNumIdx = manIdIdx + ManId::size;
+ static const index segmentNumIdx = pageNumIdx + 1;
+ static const index oldDataIdx = segmentNumIdx + 1;
+ static const index newDataIdx = oldDataIdx + Segment::size;
+
+ Sha256::WriteMacData::array result_;
+};
+
+/// Format data to hash for an Authenticated Write to a memory protection block.
+class DS28E15_22_25::ProtectionWriteMacData {
+public:
+ MaximInterface_EXPORT ProtectionWriteMacData();
+
+ /// Formatted data result.
+ Sha256::WriteMacData::const_span result() const { return result_; }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<ProtectionWriteMacData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ ProtectionWriteMacData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<ProtectionWriteMacData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ ProtectionWriteMacData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Old protection
+ /// @brief Existing protection status in device.
+ /// @{
+
+ /// Get old protection.
+ BlockProtection oldProtection() const { return oldProtection_; }
+
+ /// Set old protection.
+ MaximInterface_EXPORT ProtectionWriteMacData &
+ setOldProtection(BlockProtection oldProtection);
+
+ /// @}
+
+ /// @name New protection
+ /// @brief New protection status to write.
+ /// @{
+
+ /// Get new protection.
+ BlockProtection newProtection() const { return newProtection_; }
+
+ /// Set new protection.
+ MaximInterface_EXPORT ProtectionWriteMacData &
+ setNewProtection(BlockProtection newProtection);
+
+ /// @}
+
+private:
+ typedef Sha256::WriteMacData::span::index_type index;
+
+ static const index romIdIdx = 0;
+ static const index manIdIdx = romIdIdx + RomId::size;
+ static const index blockNumIdx = manIdIdx + ManId::size;
+ static const index oldProtectionIdx = blockNumIdx + 2;
+ static const index newProtectionIdx = oldProtectionIdx + 4;
+
+ Sha256::WriteMacData::array result_;
+ BlockProtection oldProtection_;
+ BlockProtection newProtection_;
+};
+
+/// @brief
+/// Format data to hash for device authentication or computing the next secret
+/// from the existing secret.
+class DS28E15_22_25::AuthenticationData {
+public:
+ AuthenticationData() : result_() {}
+
+ /// Formatted data result.
+ Sha256::AuthenticationData::const_span result() const { return result_; }
+
+ /// @name Page
+ /// @brief Data from a device memory page.
+ /// @{
+
+ /// Get mutable page.
+ Page::span page() {
+ return make_span(result_).subspan<pageIdx, Page::size>();
+ }
+
+ /// Get immutable page.
+ Page::const_span page() const {
+ return const_cast<AuthenticationData &>(*this).page();
+ }
+
+ /// Set page.
+ AuthenticationData & setPage(Page::const_span page) {
+ copy(page, this->page());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Scratchpad
+ /// @brief
+ /// Data from device scratchpad used as a random challenge in device
+ /// authentication and a partial secret in secret computation.
+ /// @{
+
+ /// Get mutable scratchpad.
+ Scratchpad::span scratchpad() {
+ return make_span(result_).subspan<scratchpadIdx, Scratchpad::size>();
+ }
+
+ /// Get immutable scratchpad.
+ Scratchpad::const_span scratchpad() const {
+ return const_cast<AuthenticationData &>(*this).scratchpad();
+ }
+
+ /// Set scratchpad.
+ AuthenticationData & setScratchpad(Scratchpad::const_span scratchpad) {
+ copy(scratchpad, this->scratchpad());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<AuthenticationData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ AuthenticationData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// Set ROM ID for use in anonymous mode.
+ MaximInterface_EXPORT AuthenticationData & setAnonymousRomId();
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<AuthenticationData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ AuthenticationData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Number of the page to use data from.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return result_[pageNumIdx]; }
+
+ /// Set page number.
+ AuthenticationData & setPageNum(int pageNum) {
+ result_[pageNumIdx] = pageNum;
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Sha256::AuthenticationData::span::index_type index;
+
+ static const index pageIdx = 0;
+ static const index scratchpadIdx = pageIdx + Page::size;
+ static const index romIdIdx = scratchpadIdx + Scratchpad::size;
+ static const index manIdIdx = romIdIdx + RomId::size;
+ static const index pageNumIdx = manIdIdx + ManId::size;
+
+ Sha256::AuthenticationData::array result_;
+};
+
} // namespace MaximInterface
#endif
--- a/Devices/DS28E17.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28E17.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -39,46 +39,43 @@
namespace MaximInterface {
error_code DS28E17::writeDataWithStop(uint_least8_t I2C_addr,
- const uint_least8_t * data,
- size_t data_len,
+ span<const uint_least8_t> data,
uint_least8_t * wr_status) {
- return sendPacket(WriteDataWithStopCmd, &I2C_addr, data, data_len, NULL, 0,
- wr_status);
+ return sendPacket(WriteDataWithStopCmd, &I2C_addr, data,
+ span<uint_least8_t>(), wr_status);
}
error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
- const uint_least8_t * data, size_t data_len,
+ span<const uint_least8_t> data,
uint_least8_t * wr_status) {
- return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, data_len, NULL, 0,
+ return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>(),
wr_status);
}
-error_code DS28E17::writeDataOnly(const uint_least8_t * data, size_t data_len,
+error_code DS28E17::writeDataOnly(span<const uint_least8_t> data,
uint_least8_t * wr_status) {
- return sendPacket(WriteDataOnlyCmd, NULL, data, data_len, NULL, 0, wr_status);
+ return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>(),
+ wr_status);
}
-error_code DS28E17::writeDataOnlyWithStop(const uint_least8_t * data,
- size_t data_len,
+error_code DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data,
uint_least8_t * wr_status) {
- return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, data_len, NULL, 0,
+ return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, span<uint_least8_t>(),
wr_status);
}
error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
- const uint_least8_t * write_data,
- size_t write_data_len,
- uint_least8_t * read_data,
- size_t read_data_len,
+ span<const uint_least8_t> write_data,
+ span<uint_least8_t> read_data,
uint_least8_t * wr_status) {
- return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data,
- write_data_len, read_data, read_data_len, wr_status);
+ return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data,
+ wr_status);
}
error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr,
- uint_least8_t * data, size_t data_len) {
- return sendPacket(ReadDataWithStopCmd, &I2C_addr, NULL, 0, data, data_len,
- NULL);
+ span<uint_least8_t> data) {
+ return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(),
+ data, NULL);
}
error_code DS28E17::writeConfigReg(I2CSpeed speed) {
@@ -87,8 +84,7 @@
// Send CMD and Data
const uint_least8_t send_block[] = {WriteConfigurationCmd,
static_cast<uint_least8_t>(speed)};
- result = master->writeBlock(send_block,
- sizeof(send_block) / sizeof(send_block[0]));
+ result = master->writeBlock(send_block);
}
return result;
}
@@ -141,18 +137,14 @@
}
error_code DS28E17::sendPacket(Command command, const uint_least8_t * I2C_addr,
- const uint_least8_t * write_data,
- size_t write_data_len, uint_least8_t * read_data,
- size_t read_data_len,
+ span<const uint_least8_t> write_data,
+ span<uint_least8_t> read_data,
uint_least8_t * wr_status) {
const int pollLimit = 10000;
- const size_t minDataLen = 1;
- const size_t maxDataLen = 255;
+ const span<const uint_least8_t>::index_type maxDataLen = 255;
- if ((write_data &&
- (write_data_len < minDataLen || write_data_len > maxDataLen)) ||
- (read_data &&
- (read_data_len < minDataLen || read_data_len > maxDataLen))) {
+ if ((!write_data.empty() && write_data.size() > maxDataLen) ||
+ (!read_data.empty() && read_data.size() > maxDataLen)) {
return make_error_code(OutOfRangeError);
}
@@ -172,21 +164,21 @@
return result;
}
}
- if (write_data) {
- crc16 = calculateCrc16(static_cast<uint_fast8_t>(write_data_len), crc16);
- result = master->writeByte(static_cast<uint_least8_t>(write_data_len));
+ if (!write_data.empty()) {
+ crc16 = calculateCrc16(static_cast<uint_fast8_t>(write_data.size()), crc16);
+ result = master->writeByte(static_cast<uint_least8_t>(write_data.size()));
if (result) {
return result;
}
- crc16 = calculateCrc16(write_data, write_data_len, crc16);
- result = master->writeBlock(write_data, write_data_len);
+ crc16 = calculateCrc16(write_data, crc16);
+ result = master->writeBlock(write_data);
if (result) {
return result;
}
}
- if (read_data) {
- crc16 = calculateCrc16(static_cast<uint_fast8_t>(read_data_len), crc16);
- result = master->writeByte(static_cast<uint_least8_t>(read_data_len));
+ if (!read_data.empty()) {
+ crc16 = calculateCrc16(static_cast<uint_fast8_t>(read_data.size()), crc16);
+ result = master->writeByte(static_cast<uint_least8_t>(read_data.size()));
if (result) {
return result;
}
@@ -194,8 +186,7 @@
crc16 ^= 0xFFFFU;
const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16),
static_cast<uint_least8_t>(crc16 >> 8)};
- result = master->writeBlock(crc16Bytes,
- sizeof(crc16Bytes) / sizeof(crc16Bytes[0]));
+ result = master->writeBlock(crc16Bytes);
if (result) {
return result;
}
@@ -225,7 +216,7 @@
if ((status & 0x8) == 0x8) {
return make_error_code(InvalidStartError);
}
- if (write_data) {
+ if (!write_data.empty()) {
result = master->readByte(status);
if (result) {
return result;
@@ -237,8 +228,8 @@
return make_error_code(WriteNackError);
}
}
- if (read_data) {
- result = master->readBlock(read_data, read_data_len);
+ if (!read_data.empty()) {
+ result = master->readBlock(read_data);
}
return result;
}
--- a/Devices/DS28E17.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS28E17.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,10 +36,11 @@
#include <stdint.h>
#include <MaximInterface/Links/SelectRom.hpp>
#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/span.hpp>
namespace MaximInterface {
-/// DS28E17 1-Wire®-to-I2C Master Bridge
+/// @brief DS28E17 1-Wire®-to-I2C Master Bridge
/// @details The DS28E17 is a 1-Wire slave to I2C master bridge
/// device that interfaces directly to I2C slaves at standard
/// (100kHz max) or fast (400kHz max). Data transfers serially by
@@ -69,110 +70,102 @@
: selectRom(selectRom), master(&master) {}
void setMaster(OneWireMaster & master) { this->master = &master; }
+
void setSelectRom(const SelectRom & selectRom) {
this->selectRom = selectRom;
}
- /// Write Data With Stop command.
+ /// @brief Write Data With Stop command.
/// @details Output on I2C: S, Address + Write, Write Data [1-255], P
/// @param[in] I2C_addr
/// I2C slave address. The least significant bit of the I2C
/// address is automatically cleared by the command.
- /// @param[in] data I2C data to write.
- /// @param[in] data_len Length of data. Valid from 1-255.
+ /// @param[in] data I2C data to write with length 1-255.
/// @param[out] wr_status
/// Indicates which write byte NACK’d. A value of 00h indicates all bytes
/// were acknowledged by the slave. A non-zero value indicates the byte number
/// that NACK’d. May be set to NULL.
MaximInterface_EXPORT error_code
- writeDataWithStop(uint_least8_t I2C_addr, const uint_least8_t * data,
- size_t data_len, uint_least8_t * wr_status = NULL);
+ writeDataWithStop(uint_least8_t I2C_addr, span<const uint_least8_t> data,
+ uint_least8_t * wr_status = NULL);
- /// Write Data No Stop command.
+ /// @brief Write Data No Stop command.
/// @details Output on I2C: S, Address + Write, Write Data [1-255]
/// @param[in] I2C_addr
/// I2C slave address. The least significant bit of the I2C address
/// is automatically cleared by the command.
- /// @param[in] data I2C data to write.
- /// @param[in] data_len Length of data. Valid from 1-255.
+ /// @param[in] data I2C data to write with length 1-255.
/// @param[out] wr_status
/// Indicates which write byte NACK’d. A value of 00h indicates all bytes
/// were acknowledged by the slave. A non-zero value indicates the byte number
/// that NACK’d. May be set to NULL.
MaximInterface_EXPORT error_code
- writeDataNoStop(uint_least8_t I2C_addr, const uint_least8_t * data,
- size_t data_len, uint_least8_t * wr_status = NULL);
+ writeDataNoStop(uint_least8_t I2C_addr, span<const uint_least8_t> data,
+ uint_least8_t * wr_status = NULL);
- /// Write Data Only command.
+ /// @brief Write Data Only command.
/// @details Output on I2C: Write Data [1-255]
- /// @param[in] data I2C data to write.
- /// @param[in] data_len Length of data. Valid from 1-255.
+ /// @param[in] data I2C data to write with length 1-255.
/// @param[out] wr_status
/// Indicates which write byte NACK’d. A value of 00h indicates all bytes
/// were acknowledged by the slave. A non-zero value indicates the byte number
/// that NACK’d. May be set to NULL.
MaximInterface_EXPORT error_code
- writeDataOnly(const uint_least8_t * data, size_t data_len,
+ writeDataOnly(span<const uint_least8_t> data,
uint_least8_t * wr_status = NULL);
- /// Write Data Only With Stop command.
+ /// @brief Write Data Only With Stop command.
/// @details Output on I2C: Write Data [1-255], P
- /// @param[in] data I2C data to write.
- /// @param[in] data_len Length of data. Valid from 1-255.
+ /// @param[in] data I2C data to write with length 1-255.
/// @param[out] wr_status
/// Indicates which write byte NACK’d. A value of 00h indicates all bytes
/// were acknowledged by the slave. A non-zero value indicates the byte number
/// that NACK’d. May be set to NULL.
MaximInterface_EXPORT error_code
- writeDataOnlyWithStop(const uint_least8_t * data, size_t data_len,
+ writeDataOnlyWithStop(span<const uint_least8_t> data,
uint_least8_t * wr_status = NULL);
- /// Write, Read Data With Stop command.
+ /// @brief Write, Read Data With Stop command.
/// @details Output on I2C:
/// S, Slave Address + Write, Write Data [1-255],
/// Sr, Address + Read, Read Data [1-255], P (NACK last read byte)
/// @param[in] I2C_addr
/// I2C slave address. The least significant bit of the I2C address
/// is automatically cleared and set by the command.
- /// @param[in] write_data I2C data to write.
- /// @param[in] write_data_len Length of write_data. Valid from 1-255.
- /// @param[out] read_data I2C data that was read.
- /// @param[in] read_data_len Length of read_data. Valid from 1-255.
+ /// @param[in] write_data I2C data to write with length 1-255.
+ /// @param[out] read_data I2C data that was read with length 1-255.
/// @param[out] wr_status
/// Indicates which write byte NACK’d. A value of 00h indicates all bytes
/// were acknowledged by the slave. A non-zero value indicates the byte number
/// that NACK’d. May be set to NULL.
MaximInterface_EXPORT error_code writeReadDataWithStop(
- uint_least8_t I2C_addr, const uint_least8_t * write_data,
- size_t write_data_len, uint_least8_t * read_data, size_t read_data_len,
- uint_least8_t * wr_status = NULL);
+ uint_least8_t I2C_addr, span<const uint_least8_t> write_data,
+ span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL);
- /// Read Data With Stop command.
+ /// @brief Read Data With Stop command.
/// @details Output on I2C:
/// S, Slave Address + Read, Read Data [1-255], P (NACK last read byte)
/// @param[in] I2C_addr
/// I2C slave address. The least significant bit of the I2C address
/// is automatically set by the command.
- /// @param[out] data I2C data that was read.
- /// @param[in] data_len Length of data. Valid from 1-255.
+ /// @param[out] data I2C data that was read with length 1-255.
MaximInterface_EXPORT error_code readDataWithStop(uint_least8_t I2C_addr,
- uint_least8_t * data,
- size_t data_len);
+ span<uint_least8_t> data);
/// Write to Configuration Register of DS28E17.
MaximInterface_EXPORT error_code writeConfigReg(I2CSpeed speed);
- /// Read the Configuration Register of DS28E17.
+ /// @brief Read the Configuration Register of DS28E17.
/// @param[out] speed Speed read from configuration register.
MaximInterface_EXPORT error_code readConfigReg(I2CSpeed & speed);
- /// The Enable Sleep Mode command puts the device into a low current mode.
+ /// @brief Put the device into a low current mode.
/// @details All 1-Wire communication is ignored until woken up. Immediately
/// after the command, the device monitors the WAKEUP input pin and exits
/// sleep mode on a rising edge.
MaximInterface_EXPORT error_code enableSleepMode();
- /// Read the Device Revision of DS28E17.
+ /// @brief Read the Device Revision of DS28E17.
/// @details The upper nibble is the major revision,
/// and the lower nibble is the minor revision.
/// @param[out] rev Device Revision.
@@ -195,8 +188,8 @@
};
error_code sendPacket(Command command, const uint_least8_t * I2C_addr,
- const uint_least8_t * write_data, size_t write_data_len,
- uint_least8_t * read_data, size_t read_data_len,
+ span<const uint_least8_t> write_data,
+ span<uint_least8_t> read_data,
uint_least8_t * wr_status);
SelectRom selectRom;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E38.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,302 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <stddef.h>
+#include <algorithm>
+#include <MaximInterface/Utilities/Algorithm.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS28E38.hpp"
+
+namespace MaximInterface {
+
+using std::copy;
+
+static const int readMemoryTimeMs = 30;
+static const int writeMemoryTimeMs = 65;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 200;
+static const int generateEcdsaSignatureTimeMs = 130;
+static const int trngOnDemandCheckTimeMs = 20;
+static const int trngGenerationTimeMs = 10;
+
+const int DS28E38::decrementCounterPage;
+const int DS28E38::publicKeyXPage;
+const int DS28E38::publicKeyYPage;
+const int DS28E38::privateKeyPage;
+const int DS28E38::memoryPages;
+
+error_code DS28E38::writeMemory(int pageNum, Page::const_span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t command[2 + Page::size];
+ command[0] = 0x96;
+ command[1] = pageNum;
+ copy(page.begin(), page.end(), command + 2);
+ return runCommand(command, writeMemoryTimeMs);
+}
+
+error_code DS28E38::readMemory(int pageNum, Page::span page) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + Page::size];
+ buffer[0] = 0x44;
+ buffer[1] = pageNum;
+ span<uint_least8_t> response(buffer);
+ const error_code result =
+ runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+ if (!result) {
+ copy(response.begin(), response.end(), page.begin());
+ }
+ return result;
+}
+
+error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) {
+ int delay = readMemoryTimeMs;
+ if (entropyHealthTest) {
+ delay += trngOnDemandCheckTimeMs;
+ }
+ uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
+ Status::RomVersion::csize + 2];
+ buffer[0] = 0xAA;
+ buffer[1] = entropyHealthTest ? 0x01 : 0x00;
+ span<uint_least8_t> response(buffer);
+ error_code result = runCommand(make_span(buffer, 2), delay, response);
+ if (!result) {
+ span<uint_least8_t>::const_iterator responseIt = response.begin();
+ for (Status::PageProtectionList::iterator it =
+ status.pageProtection.begin();
+ it != status.pageProtection.end(); ++it) {
+ *it = *responseIt;
+ ++responseIt;
+ }
+ span<uint_least8_t>::const_iterator responseItEnd =
+ responseIt + status.manId.size();
+ copy(responseIt, responseItEnd, status.manId.begin());
+ responseIt = responseItEnd;
+ responseItEnd = responseIt + status.romVersion.size();
+ copy(responseIt, responseItEnd, status.romVersion.begin());
+ responseIt = responseItEnd;
+ switch (*responseIt) {
+ case Status::TestNotPerformed:
+ case Status::EntropyHealthy:
+ case Status::EntropyNotHealthy:
+ status.entropyHealthTestStatus =
+ static_cast<Status::EntropyHealthTestStatus>(*responseIt);
+ break;
+
+ default:
+ result = make_error_code(InvalidResponseError);
+ break;
+ }
+ }
+ return result;
+}
+
+error_code DS28E38::setPageProtection(int pageNum,
+ const PageProtection & protection) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ int delay = writeStateTimeMs;
+ if (pageNum == decrementCounterPage) {
+ delay += writeMemoryTimeMs;
+ }
+ const uint_least8_t command[] = {
+ 0xC3, static_cast<uint_least8_t>(pageNum),
+ static_cast<uint_least8_t>(protection.to_ulong())};
+ return runCommand(command, delay);
+}
+
+error_code
+DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous,
+ Page::const_span challenge,
+ Ecc256::Signature::span signature) {
+ if (pageNum < 0 || pageNum >= memoryPages) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ const size_t commandSize = 2 + Page::size;
+ const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+ uint_least8_t buffer[MaximInterface_MAX(commandSize, responseSize)];
+ buffer[0] = 0xA5;
+ buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00);
+ copy(challenge.begin(), challenge.end(), buffer + 2);
+ span<uint_least8_t> response(buffer, responseSize);
+ const error_code result = runCommand(make_span(buffer, commandSize),
+ generateEcdsaSignatureTimeMs, response);
+ if (!result) {
+ span<uint_least8_t>::const_iterator begin = response.begin();
+ span<uint_least8_t>::const_iterator end = begin + signature.s.size();
+ copy(begin, end, signature.s.begin());
+ begin = end;
+ end = begin + signature.r.size();
+ copy(begin, end, signature.r.begin());
+ }
+ return result;
+}
+
+error_code DS28E38::decrementCounter() {
+ const uint_least8_t command = 0xC9;
+ return runCommand(make_span(&command, 1), writeMemoryTimeMs);
+}
+
+error_code DS28E38::disableDevice() {
+ const uint_least8_t command[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB,
+ 0x10, 0x62, 0x0A, 0x26};
+ return runCommand(command, writeStateTimeMs);
+}
+
+error_code DS28E38::generateEcc256KeyPair(bool privateKeyPuf,
+ bool writeProtectEnable) {
+ int delay = generateEccKeyPairTimeMs;
+ if (writeProtectEnable) {
+ delay += writeStateTimeMs;
+ }
+ uint_least8_t command[] = {0xCB, 0x00};
+ if (privateKeyPuf) {
+ command[1] |= 0x01;
+ }
+ if (writeProtectEnable) {
+ command[1] |= 0x80;
+ }
+ return runCommand(command, delay);
+}
+
+error_code DS28E38::readRng(span<uint_least8_t> data) {
+ const span<uint_least8_t>::index_type maxDataSize = 64;
+ if ((data.size() < 1) || (data.size() > maxDataSize)) {
+ return make_error_code(InvalidParameterError);
+ }
+
+ uint_least8_t buffer[1 + maxDataSize];
+ buffer[0] = 0xD2;
+ buffer[1] = data.size() - 1;
+ span<uint_least8_t> response(buffer, 1 + data.size());
+ const error_code result =
+ runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+ if (!result) {
+ copy(response.begin(), response.end(), data.begin());
+ }
+ return result;
+}
+
+error_code DS28E38::runCommand(span<const uint_least8_t> command, int delayTime,
+ span<uint_least8_t> & response) {
+ const span<const uint_least8_t>::index_type responseInputSize =
+ response.size();
+ error_code result = doRunCommand(command, delayTime, response);
+ if (result) {
+ return result;
+ }
+ if (response.empty()) {
+ return make_error_code(InvalidResponseError);
+ }
+ // Parse command result byte.
+ switch (response[0]) {
+ case 0xAA:
+ // Success response.
+ if (response.size() != responseInputSize) {
+ result = make_error_code(InvalidResponseError);
+ }
+ break;
+
+ case 0x00:
+ result = make_error_code(InvalidResponseError);
+ break;
+
+ default:
+ result.assign(response[0], errorCategory());
+ break;
+ }
+ response = response.subspan(1);
+ return result;
+}
+
+error_code DS28E38::runCommand(span<const uint_least8_t> command,
+ int delayTime) {
+ uint_least8_t buffer;
+ span<uint_least8_t> response(&buffer, 1);
+ return runCommand(command, delayTime, response);
+}
+
+const error_category & DS28E38::errorCategory() {
+ static class : public error_category {
+ public:
+ virtual const char * name() const { return "DS28E38"; }
+
+ virtual std::string message(int condition) const {
+ switch (condition) {
+ case InvalidOperationError:
+ return "Invalid Operation Error";
+
+ case InvalidParameterError:
+ return "Invalid Parameter Error";
+
+ case InvalidSequenceError:
+ return "Invalid Sequence Error";
+
+ case InternalError:
+ return "Internal Error";
+
+ case DeviceDisabledError:
+ return "Device Disabled Error";
+
+ case InvalidResponseError:
+ return "Invalid Response Error";
+ }
+ return defaultErrorMessage(condition);
+ }
+ } instance;
+ return instance;
+}
+
+error_code readManId(DS28E38 & ds28e38, ManId::span manId) {
+ DS28E38::Status status;
+ const error_code result = ds28e38.readStatus(false, status);
+ if (!result) {
+ copy(make_span(status.manId), manId);
+ }
+ return result;
+}
+
+DS28E38::PageAuthenticationData &
+DS28E38::PageAuthenticationData::setAnonymousRomId() {
+ std::fill(romId().begin(), romId().end(), 0xFF);
+ return *this;
+}
+
+} // namespace MaximInterface
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E38.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,316 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS28E38
+#define MaximInterface_DS28E38
+
+#include <stdint.h>
+#include <MaximInterface/Links/RunCommand.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
+#include <MaximInterface/Utilities/Ecc256.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/FlagSet.hpp>
+#include <MaximInterface/Utilities/ManId.hpp>
+#include <MaximInterface/Utilities/system_error.hpp>
+
+namespace MaximInterface {
+
+class DS28E38 {
+public:
+ /// Device command results.
+ enum ErrorValue {
+ InvalidOperationError = 0x55,
+ InvalidParameterError = 0x77,
+ InvalidSequenceError = 0x33,
+ InternalError = 0x22,
+ DeviceDisabledError = 0x88,
+ InvalidResponseError =
+ 0x100 ///< Command response does not match expected format.
+ };
+
+ /// @name Device memory pages
+ /// @{
+
+ static const int decrementCounterPage = 3;
+ static const int publicKeyXPage = 4;
+ static const int publicKeyYPage = 5;
+ static const int privateKeyPage = 6;
+
+ /// @}
+
+ static const int memoryPages = 7;
+
+ /// Holds a device memory page.
+ typedef array_span<uint_least8_t, 32> Page;
+
+ // Format page authentication input data.
+ class PageAuthenticationData;
+
+ /// Page protection types.
+ enum PageProtectionType {
+ RP = 0x01, ///< Read protection.
+ WP = 0x02, ///< Write protection.
+ EM = 0x04, ///< EPROM emulation mode.
+ DC = 0x08, ///< Decrement counter.
+ PF = 0x10 ///< PUF used as private key.
+ };
+ typedef FlagSet<PageProtectionType, 5> PageProtection;
+
+ struct Status {
+ enum EntropyHealthTestStatus {
+ TestNotPerformed = 0xFF,
+ EntropyHealthy = 0xAA,
+ EntropyNotHealthy = 0xDD
+ };
+
+ typedef array<PageProtection, memoryPages> PageProtectionList;
+ typedef array<uint_least8_t, 2> RomVersion;
+
+ PageProtectionList pageProtection;
+ ManId::array manId;
+ RomVersion romVersion;
+ EntropyHealthTestStatus entropyHealthTestStatus;
+ };
+
+ explicit DS28E38(const RunCommand & runCommand) : doRunCommand(runCommand) {}
+
+ void setRunCommand(const RunCommand & runCommand) {
+ doRunCommand = runCommand;
+ }
+
+ /// @brief Write memory with no protection.
+ /// @param pageNum Number of page to write.
+ /// @param page Data to write.
+ MaximInterface_EXPORT error_code writeMemory(int pageNum,
+ Page::const_span page);
+
+ /// @brief Read memory with no protection.
+ /// @param pageNum Number of page to read.
+ /// @param[out] page Data that was read.
+ MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page);
+
+ /// @brief
+ /// Reads the current status of the device and optionally performs an
+ /// entropy health test.
+ /// @param entropyHealthTest True to perform an entropy health test.
+ /// @param[out] status Status that was read.
+ MaximInterface_EXPORT error_code readStatus(bool entropyHealthTest,
+ Status & status);
+
+ /// @brief Set the protection settings of a page.
+ /// @param pageNum Number of page to write.
+ /// @param protection Protection to write.
+ MaximInterface_EXPORT error_code
+ setPageProtection(int pageNum, const PageProtection & protection);
+
+ /// @brief Compute and read page authentication with ECDSA.
+ /// @param pageNum Number of page to authenticate.
+ /// @param anonymous True to disable use of ROM ID in computation.
+ /// @param challenge Random challenge used to prevent replay attacks.
+ /// @param[out] signature Computed page signature.
+ MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
+ int pageNum, bool anonymous, Page::const_span challenge,
+ Ecc256::Signature::span signature);
+
+ /// Decrement the decrement-only counter.
+ MaximInterface_EXPORT error_code decrementCounter();
+
+ /// Permanently disable the device.
+ MaximInterface_EXPORT error_code disableDevice();
+
+ /// @brief Generate a new ECDSA public key from an existing private key.
+ /// @param privateKeyPuf True if PUF is used as the private key.
+ /// @param writeProtectEnable True to lock the key against further writes.
+ MaximInterface_EXPORT error_code
+ generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable);
+
+ /// @brief Read a block of random data from the RNG.
+ /// @param[out] data Random data from RNG with length from 1 to 64.
+ MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
+
+ MaximInterface_EXPORT static const error_category & errorCategory();
+
+protected:
+ MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
+ int delayTime,
+ span<uint_least8_t> & response);
+
+ MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
+ int delayTime);
+
+private:
+ RunCommand doRunCommand;
+};
+
+inline error_code make_error_code(DS28E38::ErrorValue e) {
+ return error_code(e, DS28E38::errorCategory());
+}
+
+/// @brief Read the device MAN ID using the Read Status command.
+/// @param ds28e38 Device to read.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterface_EXPORT error_code readManId(DS28E38 & ds28e38,
+ ManId::span manId);
+
+/// Format page authentication input data.
+class DS28E38::PageAuthenticationData {
+public:
+ typedef array_span<uint_least8_t,
+ RomId::size + 2 * Page::size + 1 + ManId::size>
+ Result;
+
+ PageAuthenticationData() : result_() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return result_; }
+
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<PageAuthenticationData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ PageAuthenticationData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// Set ROM ID for use in anonymous mode.
+ MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+ /// @}
+
+ /// @name Page
+ /// @brief Data from a device memory page.
+ /// @{
+
+ /// Get mutable page.
+ Page::span page() {
+ return make_span(result_).subspan<pageIdx, Page::size>();
+ }
+
+ /// Get immutable page.
+ Page::const_span page() const {
+ return const_cast<PageAuthenticationData &>(*this).page();
+ }
+
+ /// Set page.
+ PageAuthenticationData & setPage(Page::const_span page) {
+ copy(page, this->page());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Challenge
+ /// @brief Random challenge used to prevent replay attacks.
+ /// @{
+
+ /// Get mutable Challenge.
+ Page::span challenge() {
+ return make_span(result_).subspan<challengeIdx, Page::size>();
+ }
+
+ /// Get immutable Challenge.
+ Page::const_span challenge() const {
+ return const_cast<PageAuthenticationData &>(*this).challenge();
+ }
+
+ /// Set Challenge.
+ PageAuthenticationData & setChallenge(Page::const_span challenge) {
+ copy(challenge, this->challenge());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name Page number
+ /// @brief Number of the page to use data from.
+ /// @{
+
+ /// Get page number.
+ int pageNum() const { return result_[pageNumIdx]; }
+
+ /// Set page number.
+ PageAuthenticationData & setPageNum(int pageNum) {
+ result_[pageNumIdx] = pageNum;
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<PageAuthenticationData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ PageAuthenticationData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Result::span::index_type index;
+
+ static const index romIdIdx = 0;
+ static const index pageIdx = romIdIdx + RomId::size;
+ static const index challengeIdx = pageIdx + Page::size;
+ static const index pageNumIdx = challengeIdx + Page::size;
+ static const index manIdIdx = pageNumIdx + 1;
+
+ Result::array result_;
+};
+
+} // namespace MaximInterface
+
+#endif
--- a/Devices/DS9400.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS9400.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -59,7 +59,7 @@
const uint_least8_t packet[] = {'Q', data};
error_code result = uart->clearReadBuffer();
if (!result) {
- result = uart->writeBlock(packet, sizeof(packet) / sizeof(packet[0]));
+ result = uart->writeBlock(packet);
if (!result) {
result = uart->readByte(data);
if (!result && data != 0) {
@@ -83,7 +83,7 @@
error_code DS9400::configure(uint_least8_t config) {
const uint_least8_t packet[] = {'C', config};
- return uart->writeBlock(packet, sizeof(packet) / sizeof(packet[0]));
+ return uart->writeBlock(packet);
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Devices/DS9400.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS9400.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -48,9 +48,13 @@
MaximInterface_EXPORT error_code waitAwake();
MaximInterface_EXPORT error_code start();
+
MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+
MaximInterface_EXPORT virtual error_code stop();
+
MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+
MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
uint_least8_t & data);
@@ -63,4 +67,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Devices/DS9481P_300.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS9481P_300.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,7 +35,7 @@
namespace MaximInterface {
-DS9481P_300::DS9481P_300(const Sleep & sleep, SerialPort & serialPort)
+DS9481P_300::DS9481P_300(Sleep & sleep, SerialPort & serialPort)
: serialPort(&serialPort), currentBus(OneWire), ds2480b(sleep, serialPort),
oneWireMaster_(*this), ds9400(serialPort), i2cMaster_(*this) {}
@@ -135,20 +135,19 @@
}
error_code
-DS9481P_300::OneWireMasterImpl::writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen) {
+DS9481P_300::OneWireMasterImpl::writeBlock(span<const uint_least8_t> sendBuf) {
error_code result = parent->selectBus(OneWire);
if (!result) {
- result = OneWireMasterDecorator::writeBlock(sendBuf, sendLen);
+ result = OneWireMasterDecorator::writeBlock(sendBuf);
}
return result;
}
-error_code DS9481P_300::OneWireMasterImpl::readBlock(uint_least8_t * recvBuf,
- size_t recvLen) {
+error_code
+DS9481P_300::OneWireMasterImpl::readBlock(span<uint_least8_t> recvBuf) {
error_code result = parent->selectBus(OneWire);
if (!result) {
- result = OneWireMasterDecorator::readBlock(recvBuf, recvLen);
+ result = OneWireMasterDecorator::readBlock(recvBuf);
}
return result;
}
@@ -201,22 +200,20 @@
return result;
}
-error_code DS9481P_300::I2CMasterImpl::writeBlock(const uint_least8_t * data,
- size_t dataLen) {
+error_code
+DS9481P_300::I2CMasterImpl::writeBlock(span<const uint_least8_t> data) {
error_code result = parent->selectBus(I2C);
if (!result) {
- result = I2CMasterDecorator::writeBlock(data, dataLen);
+ result = I2CMasterDecorator::writeBlock(data);
}
return result;
}
error_code DS9481P_300::I2CMasterImpl::writePacketImpl(
- uint_least8_t address, const uint_least8_t * data, size_t dataLen,
- bool sendStop) {
+ uint_least8_t address, span<const uint_least8_t> data, bool sendStop) {
error_code result = parent->selectBus(I2C);
if (!result) {
- result = I2CMasterDecorator::writePacketImpl(address, data, dataLen,
- sendStop);
+ result = I2CMasterDecorator::writePacketImpl(address, data, sendStop);
}
return result;
}
@@ -231,23 +228,20 @@
}
error_code DS9481P_300::I2CMasterImpl::readBlock(AckStatus status,
- uint_least8_t * data,
- size_t dataLen) {
+ span<uint_least8_t> data) {
error_code result = parent->selectBus(I2C);
if (!result) {
- result = I2CMasterDecorator::readBlock(status, data, dataLen);
+ result = I2CMasterDecorator::readBlock(status, data);
}
return result;
}
error_code DS9481P_300::I2CMasterImpl::readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen,
+ span<uint_least8_t> data,
bool sendStop) {
error_code result = parent->selectBus(I2C);
if (!result) {
- result = I2CMasterDecorator::readPacketImpl(address, data, dataLen,
- sendStop);
+ result = I2CMasterDecorator::readPacketImpl(address, data, sendStop);
}
return result;
}
@@ -260,4 +254,4 @@
return configure('O');
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Devices/DS9481P_300.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Devices/DS9481P_300.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -46,10 +46,10 @@
/// DS9481P-300 USB to 1-Wire and I2C adapter.
class DS9481P_300 {
public:
- MaximInterface_EXPORT DS9481P_300(const Sleep & sleep,
- SerialPort & serialPort);
+ MaximInterface_EXPORT DS9481P_300(Sleep & sleep, SerialPort & serialPort);
- void setSleep(const Sleep & sleep) { ds2480b.setSleep(sleep); }
+ void setSleep(Sleep & sleep) { ds2480b.setSleep(sleep); }
+
void setSerialPort(SerialPort & serialPort) {
this->serialPort = &serialPort;
ds2480b.setUart(serialPort);
@@ -57,13 +57,16 @@
}
MaximInterface_EXPORT error_code connect(const std::string & portName);
+
MaximInterface_EXPORT error_code disconnect();
+
MaximInterface_EXPORT bool connected() const;
+
MaximInterface_EXPORT std::string portName() const;
/// Access the 1-Wire master when connected to an adapter.
OneWireMaster & oneWireMaster() { return oneWireMaster_; }
-
+
/// Access the I2C master when connected to an adapter.
I2CMaster & i2cMaster() { return i2cMaster_; }
@@ -73,18 +76,28 @@
explicit OneWireMasterImpl(DS9481P_300 & parent)
: OneWireMasterDecorator(parent.ds2480b), parent(&parent) {}
- virtual error_code reset();
- virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
- virtual error_code writeByteSetLevel(uint_least8_t sendByte,
- Level afterLevel);
- virtual error_code readByteSetLevel(uint_least8_t & recvByte,
- Level afterLevel);
- virtual error_code writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen);
- virtual error_code readBlock(uint_least8_t * recvBuf, size_t recvLen);
- virtual error_code setSpeed(Speed newSpeed);
- virtual error_code setLevel(Level newLevel);
- virtual error_code triplet(TripletData & data);
+ MaximInterface_EXPORT virtual error_code reset();
+
+ MaximInterface_EXPORT virtual error_code
+ touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+ MaximInterface_EXPORT virtual error_code
+ writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+ MaximInterface_EXPORT virtual error_code
+ readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+ MaximInterface_EXPORT virtual error_code
+ writeBlock(span<const uint_least8_t> sendBuf);
+
+ MaximInterface_EXPORT virtual error_code
+ readBlock(span<uint_least8_t> recvBuf);
+
+ MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
+ MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
+ MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
private:
DS9481P_300 * parent;
@@ -95,21 +108,28 @@
explicit I2CMasterImpl(DS9481P_300 & parent)
: I2CMasterDecorator(parent.ds9400), parent(&parent) {}
- virtual error_code start(uint_least8_t address);
- virtual error_code stop();
- virtual error_code writeByte(uint_least8_t data);
- virtual error_code writeBlock(const uint_least8_t * data, size_t dataLen);
- virtual error_code readByte(AckStatus status, uint_least8_t & data);
- virtual error_code readBlock(AckStatus status, uint_least8_t * data,
- size_t dataLen);
+ MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+
+ MaximInterface_EXPORT virtual error_code stop();
+
+ MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+
+ MaximInterface_EXPORT virtual error_code
+ writeBlock(span<const uint_least8_t> data);
+
+ MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
+ uint_least8_t & data);
+ MaximInterface_EXPORT virtual error_code
+ readBlock(AckStatus status, span<uint_least8_t> data);
protected:
- virtual error_code writePacketImpl(uint_least8_t address,
- const uint_least8_t * data,
- size_t dataLen, bool sendStop);
- virtual error_code readPacketImpl(uint_least8_t address,
- uint_least8_t * data, size_t dataLen,
- bool sendStop);
+ MaximInterface_EXPORT virtual error_code
+ writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
+ bool sendStop);
+
+ MaximInterface_EXPORT virtual error_code
+ readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
+ bool sendStop);
private:
DS9481P_300 * parent;
@@ -117,8 +137,7 @@
class DS2480BWithEscape : public DS2480B {
public:
- DS2480BWithEscape(const Sleep & sleep, Uart & uart)
- : DS2480B(sleep, uart) {}
+ DS2480BWithEscape(Sleep & sleep, Uart & uart) : DS2480B(sleep, uart) {}
error_code escape();
};
@@ -148,4 +167,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/I2CMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/I2CMaster.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,20 +35,21 @@
namespace MaximInterface {
-error_code I2CMaster::writeBlock(const uint_least8_t * data, size_t dataLen) {
+error_code I2CMaster::writeBlock(span<const uint_least8_t> data) {
error_code result;
- for (size_t i = 0; (i < dataLen) && !result; i++) {
+ for (span<const uint_least8_t>::index_type i = 0;
+ i < data.size() && !result; ++i) {
result = writeByte(data[i]);
}
return result;
}
error_code I2CMaster::writePacketImpl(uint_least8_t address,
- const uint_least8_t * data,
- size_t dataLen, bool sendStop) {
+ span<const uint_least8_t> data,
+ bool sendStop) {
error_code result = start(address & 0xFE);
if (!result) {
- result = writeBlock(data, dataLen);
+ result = writeBlock(data);
}
if (sendStop) {
error_code stopResult = stop();
@@ -59,21 +60,19 @@
return result;
}
-error_code I2CMaster::readBlock(AckStatus status, uint_least8_t * data,
- size_t dataLen) {
+error_code I2CMaster::readBlock(AckStatus status, span<uint_least8_t> data) {
error_code result;
- for (size_t i = 0; (i < dataLen) && !result; i++) {
- result = readByte(i == (dataLen - 1) ? status : Ack, data[i]);
+ for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) {
+ result = readByte(i == (data.size() - 1) ? status : Ack, data[i]);
}
return result;
}
error_code I2CMaster::readPacketImpl(uint_least8_t address,
- uint_least8_t * data, size_t dataLen,
- bool sendStop) {
+ span<uint_least8_t> data, bool sendStop) {
error_code result = start(address | 0x01);
if (!result) {
- result = readBlock(Nack, data, dataLen);
+ result = readBlock(Nack, data);
}
if (sendStop) {
error_code stopResult = stop();
@@ -102,4 +101,4 @@
return instance;
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/I2CMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/I2CMaster.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -33,9 +33,9 @@
#ifndef MaximInterface_I2CMaster
#define MaximInterface_I2CMaster
-#include <stddef.h>
#include <stdint.h>
#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/span.hpp>
#include <MaximInterface/Utilities/system_error.hpp>
namespace MaximInterface {
@@ -51,7 +51,7 @@
virtual ~I2CMaster() {}
- /// Send start condition and address on the bus.
+ /// @brief Send start condition and address on the bus.
/// @param address Address with R/W bit.
virtual error_code start(uint_least8_t address) = 0;
@@ -63,60 +63,63 @@
/// Write data block to the bus.
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * data, size_t dataLen);
+ writeBlock(span<const uint_least8_t> data);
+ /// @brief
/// Perform a complete write transaction on the bus with optional stop
/// condition.
/// @param address Address in 8-bit format.
+ /// @param data Data to write to the bus.
/// @param sendStop
/// True to send a stop condition or false to set up a repeated start.
- error_code writePacket(uint_least8_t address, const uint_least8_t * data,
- size_t dataLen, bool sendStop = true) {
- return writePacketImpl(address, data, dataLen, sendStop);
+ error_code writePacket(uint_least8_t address, span<const uint_least8_t> data,
+ bool sendStop = true) {
+ return writePacketImpl(address, data, sendStop);
}
- /// Read data byte from the bus.
+ /// @brief Read data byte from the bus.
/// @param status Determines whether an ACK or NACK is sent after reading.
/// @param[out] data Data read from the bus if successful.
virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0;
- /// Read data block from the bus.
+ /// @brief Read data block from the bus.
/// @param status Determines whether an ACK or NACK is sent after reading.
/// @param[out] data Data read from the bus if successful.
- /// @param dataLen Number of bytes to read and length of data.
MaximInterface_EXPORT virtual error_code
- readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+ readBlock(AckStatus status, span<uint_least8_t> data);
+ /// @brief
/// Perform a complete read transaction on the bus with optional stop
/// condition.
/// @param address Address in 8-bit format.
+ /// @param[out] data Data read from the bus if successful.
/// @param sendStop
/// True to send a stop condition or false to set up a repeated start.
- error_code readPacket(uint_least8_t address, uint_least8_t * data,
- size_t dataLen, bool sendStop = true) {
- return readPacketImpl(address, data, dataLen, sendStop);
+ error_code readPacket(uint_least8_t address, span<uint_least8_t> data,
+ bool sendStop = true) {
+ return readPacketImpl(address, data, sendStop);
}
MaximInterface_EXPORT static const error_category & errorCategory();
protected:
MaximInterface_EXPORT virtual error_code
- writePacketImpl(uint_least8_t address, const uint_least8_t * data,
- size_t dataLen, bool sendStop);
+ writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
+ bool sendStop);
- MaximInterface_EXPORT virtual error_code readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen,
- bool sendStop);
+ MaximInterface_EXPORT virtual error_code
+ readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
+ bool sendStop);
};
inline error_code make_error_code(I2CMaster::ErrorValue e) {
return error_code(e, I2CMaster::errorCategory());
}
+
inline error_condition make_error_condition(I2CMaster::ErrorValue e) {
return error_condition(e, I2CMaster::errorCategory());
}
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/I2CMasterDecorator.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/I2CMasterDecorator.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,40 +35,39 @@
namespace MaximInterface {
error_code I2CMasterDecorator::start(uint_least8_t address) {
- return i2c->start(address);
+ return master->start(address);
}
-error_code I2CMasterDecorator::stop() { return i2c->stop(); }
+error_code I2CMasterDecorator::stop() { return master->stop(); }
error_code I2CMasterDecorator::writeByte(uint_least8_t data) {
- return i2c->writeByte(data);
+ return master->writeByte(data);
}
-error_code I2CMasterDecorator::writeBlock(const uint_least8_t * data,
- size_t dataLen) {
- return i2c->writeBlock(data, dataLen);
+error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) {
+ return master->writeBlock(data);
}
error_code I2CMasterDecorator::writePacketImpl(uint_least8_t address,
- const uint_least8_t * data,
- size_t dataLen, bool sendStop) {
- return i2c->writePacket(address, data, dataLen, sendStop);
+ span<const uint_least8_t> data,
+ bool sendStop) {
+ return master->writePacket(address, data, sendStop);
}
error_code I2CMasterDecorator::readByte(AckStatus status,
uint_least8_t & data) {
- return i2c->readByte(status, data);
+ return master->readByte(status, data);
}
-error_code I2CMasterDecorator::readBlock(AckStatus status, uint_least8_t * data,
- size_t dataLen) {
- return i2c->readBlock(status, data, dataLen);
+error_code I2CMasterDecorator::readBlock(AckStatus status,
+ span<uint_least8_t> data) {
+ return master->readBlock(status, data);
}
error_code I2CMasterDecorator::readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen, bool sendStop) {
- return i2c->readPacket(address, data, dataLen, sendStop);
+ span<uint_least8_t> data,
+ bool sendStop) {
+ return master->readPacket(address, data, sendStop);
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/I2CMasterDecorator.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/I2CMasterDecorator.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -40,34 +40,39 @@
class I2CMasterDecorator : public I2CMaster {
protected:
- explicit I2CMasterDecorator(I2CMaster & i2c) : i2c(&i2c) {}
+ explicit I2CMasterDecorator(I2CMaster & master) : master(&master) {}
public:
- void setI2CMaster(I2CMaster & i2c) { this->i2c = &i2c; }
+ void setMaster(I2CMaster & master) { this->master = &master; }
MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+
MaximInterface_EXPORT virtual error_code stop();
+
MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * data, size_t dataLen);
+ writeBlock(span<const uint_least8_t> data);
+
MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
uint_least8_t & data);
+
MaximInterface_EXPORT virtual error_code
- readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+ readBlock(AckStatus status, span<uint_least8_t> data);
protected:
MaximInterface_EXPORT virtual error_code
- writePacketImpl(uint_least8_t address, const uint_least8_t * data,
- size_t dataLen, bool sendStop);
- MaximInterface_EXPORT virtual error_code readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen,
- bool sendStop);
+ writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
+ bool sendStop);
+
+ MaximInterface_EXPORT virtual error_code
+ readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
+ bool sendStop);
private:
- I2CMaster * i2c;
+ I2CMaster * master;
};
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/LoggingI2CMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/LoggingI2CMaster.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -41,14 +41,13 @@
static const char startString[] = "S ";
static const char stopString[] = "P";
-static string formatDataString(const uint_least8_t * data, size_t dataSize,
- bool read) {
+static string formatDataString(span<const uint_least8_t> data, bool read) {
string dataBuilder;
- for (size_t i = 0; i < dataSize; i++) {
+ for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
if (read) {
dataBuilder.append(1, '[');
}
- dataBuilder.append(byteArrayToHexString(data + i, 1));
+ dataBuilder.append(byteArrayToHexString(data.subspan(i, 1)));
if (read) {
dataBuilder.append(1, ']');
}
@@ -66,7 +65,7 @@
error_code LoggingI2CMaster::start(uint_least8_t address) {
messageBuilder.append(startString);
- messageBuilder.append(formatDataString(&address, 1, false));
+ messageBuilder.append(formatDataString(make_span(&address, 1), false));
return I2CMasterDecorator::start(address);
}
@@ -77,25 +76,24 @@
}
error_code LoggingI2CMaster::writeByte(uint_least8_t data) {
- messageBuilder.append(formatDataString(&data, 1, false));
+ messageBuilder.append(formatDataString(make_span(&data, 1), false));
return I2CMasterDecorator::writeByte(data);
}
-error_code LoggingI2CMaster::writeBlock(const uint_least8_t * data,
- size_t dataLen) {
- messageBuilder.append(formatDataString(data, dataLen, false));
- return I2CMasterDecorator::writeBlock(data, dataLen);
+error_code LoggingI2CMaster::writeBlock(span<const uint_least8_t> data) {
+ messageBuilder.append(formatDataString(data, false));
+ return I2CMasterDecorator::writeBlock(data);
}
error_code LoggingI2CMaster::writePacketImpl(uint_least8_t address,
- const uint_least8_t * data,
- size_t dataLen, bool sendStop) {
+ span<const uint_least8_t> data,
+ bool sendStop) {
messageBuilder.append(startString);
- messageBuilder.append(formatDataString(&address, 1, false));
+ messageBuilder.append(formatDataString(make_span(&address, 1), false));
error_code result =
- I2CMasterDecorator::writePacketImpl(address, data, dataLen, sendStop);
+ I2CMasterDecorator::writePacketImpl(address, data, sendStop);
if (!result) {
- messageBuilder.append(formatDataString(data, dataLen, false));
+ messageBuilder.append(formatDataString(data, false));
}
if (sendStop || result) {
messageBuilder.append(stopString);
@@ -107,29 +105,29 @@
error_code LoggingI2CMaster::readByte(AckStatus status, uint_least8_t & data) {
error_code result = I2CMasterDecorator::readByte(status, data);
if (!result) {
- messageBuilder.append(formatDataString(&data, 1, true));
+ messageBuilder.append(formatDataString(make_span(&data, 1), true));
}
return result;
}
-error_code LoggingI2CMaster::readBlock(AckStatus status, uint_least8_t * data,
- size_t dataLen) {
- error_code result = I2CMasterDecorator::readBlock(status, data, dataLen);
+error_code LoggingI2CMaster::readBlock(AckStatus status,
+ span<uint_least8_t> data) {
+ error_code result = I2CMasterDecorator::readBlock(status, data);
if (!result) {
- messageBuilder.append(formatDataString(data, dataLen, true));
+ messageBuilder.append(formatDataString(data, true));
}
return result;
}
error_code LoggingI2CMaster::readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen, bool sendStop) {
+ span<uint_least8_t> data,
+ bool sendStop) {
messageBuilder.append(startString);
- messageBuilder.append(formatDataString(&address, 1, false));
+ messageBuilder.append(formatDataString(make_span(&address, 1), false));
error_code result =
- I2CMasterDecorator::readPacketImpl(address, data, dataLen, sendStop);
+ I2CMasterDecorator::readPacketImpl(address, data, sendStop);
if (!result) {
- messageBuilder.append(formatDataString(data, dataLen, true));
+ messageBuilder.append(formatDataString(data, true));
}
if (sendStop || result) {
messageBuilder.append(stopString);
@@ -138,4 +136,4 @@
return result;
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/LoggingI2CMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/LoggingI2CMaster.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -51,23 +51,27 @@
}
MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+
MaximInterface_EXPORT virtual error_code stop();
+
MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * data, size_t dataLen);
+ writeBlock(span<const uint_least8_t> data);
+
MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
uint_least8_t & data);
MaximInterface_EXPORT virtual error_code
- readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+ readBlock(AckStatus status, span<uint_least8_t> data);
protected:
MaximInterface_EXPORT virtual error_code
- writePacketImpl(uint_least8_t address, const uint_least8_t * data,
- size_t dataLen, bool sendStop);
- MaximInterface_EXPORT virtual error_code readPacketImpl(uint_least8_t address,
- uint_least8_t * data,
- size_t dataLen,
- bool sendStop);
+ writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
+ bool sendStop);
+
+ MaximInterface_EXPORT virtual error_code
+ readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
+ bool sendStop);
private:
void tryWriteMessage();
@@ -78,4 +82,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/LoggingOneWireMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/LoggingOneWireMaster.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -39,14 +39,13 @@
static const char strongLevelString[] = "<SP_ON>";
-static string formatDataString(const uint_least8_t * data, size_t dataSize,
- bool read) {
+static string formatDataString(span<const uint_least8_t> data, bool read) {
string dataBuilder;
- for (size_t i = 0; i < dataSize; i++) {
+ for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
if (read) {
dataBuilder.append(1, '[');
}
- dataBuilder.append(byteArrayToHexString(data + i, 1));
+ dataBuilder.append(byteArrayToHexString(data.subspan(i, 1)));
if (read) {
dataBuilder.append(1, ']');
}
@@ -69,7 +68,7 @@
error_code LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
Level afterLevel) {
- tryWriteMessage(formatDataString(&sendByte, 1, false));
+ tryWriteMessage(formatDataString(make_span(&sendByte, 1), false));
if (afterLevel == StrongLevel) {
tryWriteMessage(strongLevelString);
}
@@ -81,7 +80,7 @@
error_code result =
OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel);
if (!result) {
- tryWriteMessage(formatDataString(&recvByte, 1, true));
+ tryWriteMessage(formatDataString(make_span(&recvByte, 1), true));
if (afterLevel == StrongLevel) {
tryWriteMessage(strongLevelString);
}
@@ -89,17 +88,15 @@
return result;
}
-error_code LoggingOneWireMaster::writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen) {
- tryWriteMessage(formatDataString(sendBuf, sendLen, false));
- return OneWireMasterDecorator::writeBlock(sendBuf, sendLen);
+error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+ tryWriteMessage(formatDataString(sendBuf, false));
+ return OneWireMasterDecorator::writeBlock(sendBuf);
}
-error_code LoggingOneWireMaster::readBlock(uint_least8_t * recvBuf,
- size_t recvLen) {
- error_code result = OneWireMasterDecorator::readBlock(recvBuf, recvLen);
+error_code LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+ error_code result = OneWireMasterDecorator::readBlock(recvBuf);
if (!result) {
- tryWriteMessage(formatDataString(recvBuf, recvLen, true));
+ tryWriteMessage(formatDataString(recvBuf, true));
}
return result;
}
@@ -144,4 +141,4 @@
return result;
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/LoggingOneWireMaster.hpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Links/LoggingOneWireMaster.hpp Wed Apr 03 12:33:10 2019 +0000 @@ -52,15 +52,21 @@ } MaximInterface_EXPORT virtual error_code reset(); + MaximInterface_EXPORT virtual error_code writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + MaximInterface_EXPORT virtual error_code readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + MaximInterface_EXPORT virtual error_code - writeBlock(const uint_least8_t * sendBuf, size_t sendLen); - MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf, - size_t recvLen); + writeBlock(span<const uint_least8_t> sendBuf); + + MaximInterface_EXPORT virtual error_code + readBlock(span<uint_least8_t> recvBuf); + MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); + MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); private: @@ -71,4 +77,4 @@ } // namespace MaximInterface -#endif \ No newline at end of file +#endif
--- a/Links/LoggingSleep.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/LoggingSleep.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,13 +35,13 @@
namespace MaximInterface {
-void LoggingSleep::operator()(int ms) const {
+void LoggingSleep::invoke(int ms) const {
if (writeMessage) {
std::ostringstream message;
message << "<DELAY" << ms << '>';
writeMessage(message.str());
}
- SleepDecorator::operator()(ms);
+ SleepDecorator::invoke(ms);
}
} // namespace MaximInterface
--- a/Links/LoggingSleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/LoggingSleep.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -41,7 +41,7 @@
class LoggingSleep : public SleepDecorator {
public:
- LoggingSleep(const Sleep & sleep,
+ LoggingSleep(Sleep & sleep,
const WriteMessage & writeMessage = WriteMessage())
: SleepDecorator(sleep), writeMessage(writeMessage) {}
@@ -49,7 +49,7 @@
this->writeMessage = writeMessage;
}
- MaximInterface_EXPORT virtual void operator()(int ms) const;
+ MaximInterface_EXPORT virtual void invoke(int ms) const;
private:
WriteMessage writeMessage;
@@ -57,4 +57,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/OneWireMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/OneWireMaster.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,14 +35,14 @@
namespace MaximInterface {
+static const int maxBitNum = 7;
+
error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
Level afterLevel) {
error_code result;
- for (int idx = 0; (idx < 8) && !result; idx++) {
- result = writeBit(((sendByte >> idx) & 1) == 1);
- }
- if (!result) {
- result = setLevel(afterLevel);
+ for (int bitNum = 0; (bitNum <= maxBitNum) && !result; ++bitNum) {
+ result = writeBitSetLevel(((sendByte >> bitNum) & 1) == 1,
+ (bitNum == maxBitNum) ? afterLevel : NormalLevel);
}
return result;
}
@@ -51,35 +51,34 @@
Level afterLevel) {
recvByte = 0;
error_code result;
- for (int idx = 0; idx < 8; idx++) {
+ for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) {
bool recvBit;
- result = readBit(recvBit);
+ result = readBitSetLevel(recvBit,
+ (bitNum == maxBitNum) ? afterLevel : NormalLevel);
if (result) {
break;
}
if (recvBit) {
- recvByte |= (1 << idx);
+ recvByte |= (1 << bitNum);
}
}
- if (!result) {
- result = setLevel(afterLevel);
- }
return result;
}
-error_code OneWireMaster::writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen) {
+error_code OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
error_code result;
- for (size_t idx = 0; (idx < sendLen) && !result; idx++) {
- result = writeByte(sendBuf[idx]);
+ for (span<const uint_least8_t>::index_type i = 0;
+ i < sendBuf.size() && !result; ++i) {
+ result = writeByte(sendBuf[i]);
}
return result;
}
-error_code OneWireMaster::readBlock(uint_least8_t * recvBuf, size_t recvLen) {
+error_code OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
error_code result;
- for (size_t idx = 0; (idx < recvLen) && !result; idx++) {
- result = readByte(recvBuf[idx]);
+ for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size() && !result;
+ ++i) {
+ result = readByte(recvBuf[i]);
}
return result;
}
--- a/Links/OneWireMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/OneWireMaster.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -33,9 +33,9 @@
#ifndef MaximInterface_OneWireMaster
#define MaximInterface_OneWireMaster
-#include <stddef.h>
#include <stdint.h>
#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/span.hpp>
#include <MaximInterface/Utilities/system_error.hpp>
namespace MaximInterface {
@@ -65,10 +65,13 @@
virtual ~OneWireMaster() {}
+ /// @brief
/// Reset all of the devices on the 1-Wire bus and check for a presence pulse.
- /// @returns NoSlaveError if reset was performed but no presence pulse was detected.
+ /// @returns
+ /// NoSlaveError if reset was performed but no presence pulse was detected.
virtual error_code reset() = 0;
+ /// @brief
/// Send and receive one bit of communication and set a new level on the
/// 1-Wire bus.
/// @param[in,out] sendRecvBit
@@ -76,29 +79,29 @@
/// @param afterLevel Level to set the 1-Wire bus to after communication.
virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0;
+ /// @brief
/// Send one byte of communication and set a new level on the 1-Wire bus.
/// @param sendByte Byte to send on the 1-Wire bus.
/// @param afterLevel Level to set the 1-Wire bus to after communication.
MaximInterface_EXPORT virtual error_code
writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+ /// @brief
/// Receive one byte of communication and set a new level on the 1-Wire bus.
/// @param recvByte Buffer to receive the data from the 1-Wire bus.
/// @param afterLevel Level to set the 1-Wire bus to after communication.
MaximInterface_EXPORT virtual error_code
readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
- /// Send a block of communication on the 1-Wire bus.
+ /// @brief Send a block of communication on the 1-Wire bus.
/// @param[in] sendBuf Buffer to send on the 1-Wire bus.
- /// @param sendLen Length of the buffer to send.
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+ writeBlock(span<const uint_least8_t> sendBuf);
- /// Receive a block of communication on the 1-Wire bus.
+ /// @brief Receive a block of communication on the 1-Wire bus.
/// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus.
- /// @param recvLen Length of the buffer to receive.
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
- size_t recvLen);
+ MaximInterface_EXPORT virtual error_code
+ readBlock(span<uint_least8_t> recvBuf);
/// Set the 1-Wire bus communication speed.
virtual error_code setSpeed(Speed newSpeed) = 0;
@@ -106,16 +109,17 @@
/// Set the 1-Wire bus level.
virtual error_code setLevel(Level newLevel) = 0;
- /// 1-Wire Triplet operation.
+ /// @brief 1-Wire Triplet operation.
/// @details Perform one bit of a 1-Wire search. This command
/// does two read bits and one write bit. The write bit is either
/// the default direction (all devices have same bit) or in case
/// of a discrepancy, the data.writeBit parameter is used.
- ///@param[in,out] data
+ /// @param[in,out] data
/// Input with desired writeBit in case both read bits are zero.
/// Output with all data fields set.
MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
+ /// @brief
/// Send one bit of communication and set a new level on the 1-Wire bus.
/// @param sendBit Bit to send on the 1-Wire bus.
/// @param afterLevel Level to set the 1-Wire bus to after communication.
@@ -123,6 +127,7 @@
return touchBitSetLevel(sendBit, afterLevel);
}
+ /// @brief
/// Receive one bit of communication and set a new level on the 1-Wire bus.
/// @param[out] recvBit Received data from the 1-Wire bus.
/// @param afterLevel Level to set the 1-Wire bus to after communication.
@@ -132,27 +137,39 @@
}
// Alternate forms of the read and write functions.
+
+ error_code touchBit(bool & sendRecvBit) {
+ return touchBitSetLevel(sendRecvBit, NormalLevel);
+ }
+
error_code writeBit(bool sendBit) {
return writeBitSetLevel(sendBit, NormalLevel);
}
+
error_code readBit(bool & recvBit) {
return readBitSetLevel(recvBit, NormalLevel);
}
+
error_code writeBitPower(bool sendBit) {
return writeBitSetLevel(sendBit, StrongLevel);
}
+
error_code readBitPower(bool & recvBit) {
return readBitSetLevel(recvBit, StrongLevel);
}
+
error_code writeByte(uint_least8_t sendByte) {
return writeByteSetLevel(sendByte, NormalLevel);
}
+
error_code readByte(uint_least8_t & recvByte) {
return readByteSetLevel(recvByte, NormalLevel);
}
+
error_code writeBytePower(uint_least8_t sendByte) {
return writeByteSetLevel(sendByte, StrongLevel);
}
+
error_code readBytePower(uint_least8_t & recvByte) {
return readByteSetLevel(recvByte, StrongLevel);
}
@@ -163,6 +180,7 @@
inline error_code make_error_code(OneWireMaster::ErrorValue e) {
return error_code(e, OneWireMaster::errorCategory());
}
+
inline error_condition make_error_condition(OneWireMaster::ErrorValue e) {
return error_condition(e, OneWireMaster::errorCategory());
}
--- a/Links/OneWireMasterDecorator.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/OneWireMasterDecorator.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -51,14 +51,13 @@
return master->readByteSetLevel(recvByte, afterLevel);
}
-error_code OneWireMasterDecorator::writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen) {
- return master->writeBlock(sendBuf, sendLen);
+error_code
+OneWireMasterDecorator::writeBlock(span<const uint_least8_t> sendBuf) {
+ return master->writeBlock(sendBuf);
}
-error_code OneWireMasterDecorator::readBlock(uint_least8_t * recvBuf,
- size_t recvLen) {
- return master->readBlock(recvBuf, recvLen);
+error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) {
+ return master->readBlock(recvBuf);
}
error_code OneWireMasterDecorator::setSpeed(Speed newSpeed) {
@@ -73,4 +72,4 @@
return master->triplet(data);
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/OneWireMasterDecorator.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/OneWireMasterDecorator.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -43,21 +43,29 @@
explicit OneWireMasterDecorator(OneWireMaster & master) : master(&master) {}
public:
- void setOneWireMaster(OneWireMaster & master) { this->master = &master; }
+ void setMaster(OneWireMaster & master) { this->master = &master; }
MaximInterface_EXPORT virtual error_code reset();
+
MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
- size_t recvLen);
+ writeBlock(span<const uint_least8_t> sendBuf);
+
+ MaximInterface_EXPORT virtual error_code
+ readBlock(span<uint_least8_t> recvBuf);
+
MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
private:
@@ -66,4 +74,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/RomCommands.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/RomCommands.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -30,7 +30,6 @@
* ownership rights.
*******************************************************************************/
-#include <algorithm>
#include "RomCommands.hpp"
namespace MaximInterface {
@@ -46,114 +45,106 @@
};
void skipCurrentFamily(SearchRomState & searchState) {
- // set the Last discrepancy to last family discrepancy
+ // Set the last discrepancy to last family discrepancy.
searchState.lastDiscrepancy = searchState.lastFamilyDiscrepancy;
-
- // clear the last family discrepancy
+ // Clear the last family discrepancy.
searchState.lastFamilyDiscrepancy = 0;
-
- // check for end of list
+ // Check for end of list.
if (searchState.lastDiscrepancy == 0) {
searchState.lastDevice = true;
}
}
-error_code verifyRom(OneWireMaster & master, const RomId & romId) {
+error_code verifyRom(OneWireMaster & master, RomId::const_span romId) {
SearchRomState searchState(romId);
error_code result = searchRom(master, searchState);
- if (!result) {
- // check if same device found
- if (romId != searchState.romId) {
- result = make_error_code(OneWireMaster::NoSlaveError);
- }
+ if (result) {
+ return result;
+ }
+ // Check if same device found.
+ if (romId != make_span(searchState.romId)) {
+ result = make_error_code(OneWireMaster::NoSlaveError);
}
return result;
}
-error_code readRom(OneWireMaster & master, RomId & romId) {
+error_code readRom(OneWireMaster & master, RomId::span romId) {
error_code result = master.reset();
- if (!result) {
- result = master.writeByte(ReadRomCmd);
- }
-
- // read the ROM
- RomId readId;
- if (!result) {
- result = master.readBlock(readId.data(), readId.size());
+ if (result) {
+ return result;
}
-
- // verify CRC8
- if (!result) {
- if (valid(readId)) {
- romId = readId;
- } else {
- result = make_error_code(OneWireMaster::NoSlaveError);
- }
+ result = master.writeByte(ReadRomCmd);
+ if (result) {
+ return result;
}
-
+ result = master.readBlock(romId);
+ if (result) {
+ return result;
+ }
+ if (!valid(romId)) {
+ result = make_error_code(OneWireMaster::NoSlaveError);
+ }
return result;
}
error_code skipRom(OneWireMaster & master) {
error_code result = master.reset();
- if (!result) {
- result = master.writeByte(SkipRomCmd);
+ if (result) {
+ return result;
}
+ result = master.writeByte(SkipRomCmd);
return result;
}
-error_code matchRom(OneWireMaster & master, const RomId & romId) {
- // use MatchROM
+error_code matchRom(OneWireMaster & master, RomId::const_span romId) {
error_code result = master.reset();
- if (!result) {
- uint_least8_t buf[1 + RomId::csize];
- buf[0] = MatchRomCmd;
- std::copy(romId.begin(), romId.end(), buf + 1);
- // send command and rom
- result = master.writeBlock(buf, sizeof(buf) / sizeof(buf[0]));
+ if (result) {
+ return result;
}
+ result = master.writeByte(MatchRomCmd);
+ if (result) {
+ return result;
+ }
+ result = master.writeBlock(romId);
return result;
}
error_code overdriveSkipRom(OneWireMaster & master) {
- error_code result = master.setSpeed(OneWireMaster::StandardSpeed);
-
- if (!result) {
- result = master.reset();
+ error_code result = master.reset();
+ if (result) {
+ return result;
}
-
- if (!result) {
- result = master.writeByte(OverdriveSkipRomCmd);
+ result = master.writeByte(OverdriveSkipRomCmd);
+ if (result) {
+ return result;
}
-
- if (!result) {
- result = master.setSpeed(OneWireMaster::OverdriveSpeed);
- }
-
+ result = master.setSpeed(OneWireMaster::OverdriveSpeed);
return result;
}
-error_code overdriveMatchRom(OneWireMaster & master, const RomId & romId) {
- // use overdrive MatchROM
- master.setSpeed(OneWireMaster::StandardSpeed);
-
+error_code overdriveMatchRom(OneWireMaster & master, RomId::const_span romId) {
error_code result = master.reset();
- if (!result) {
- result = master.writeByte(OverdriveMatchRomCmd);
- if (!result) {
- master.setSpeed(OneWireMaster::OverdriveSpeed);
- // send ROM
- result = master.writeBlock(romId.data(), romId.size());
- }
+ if (result) {
+ return result;
}
+ result = master.writeByte(OverdriveMatchRomCmd);
+ if (result) {
+ return result;
+ }
+ result = master.setSpeed(OneWireMaster::OverdriveSpeed);
+ if (result) {
+ return result;
+ }
+ result = master.writeBlock(romId);
return result;
}
error_code resumeRom(OneWireMaster & master) {
error_code result = master.reset();
- if (!result) {
- result = master.writeByte(ResumeRomCmd);
+ if (result) {
+ return result;
}
+ result = master.writeByte(ResumeRomCmd);
return result;
}
@@ -171,20 +162,20 @@
return result;
}
- SearchRomState newSearchState = searchState;
- for (int idBitNumber = 1; idBitNumber <= 64; idBitNumber++) {
+ SearchRomState newSearchState;
+ newSearchState.lastFamilyDiscrepancy = searchState.lastFamilyDiscrepancy;
+ for (int idBitNumber = 1; idBitNumber <= 64; ++idBitNumber) {
const int idByteNumber = (idBitNumber - 1) / 8;
const unsigned int idBitMask = 1 << ((idBitNumber - 1) % 8);
OneWireMaster::TripletData tripletData;
- if (idBitNumber == newSearchState.lastDiscrepancy) {
+ if (idBitNumber == searchState.lastDiscrepancy) {
tripletData.writeBit = 1;
- } else if (idBitNumber > newSearchState.lastDiscrepancy) {
+ } else if (idBitNumber > searchState.lastDiscrepancy) {
tripletData.writeBit = 0;
- } else // idBitNumber < searchState.lastDiscrepancy
- {
+ } else { // idBitNumber < searchState.lastDiscrepancy
tripletData.writeBit =
- (newSearchState.romId[idByteNumber] & idBitMask) == idBitMask;
+ (searchState.romId[idByteNumber] & idBitMask) == idBitMask;
}
result = master.triplet(tripletData);
@@ -197,19 +188,16 @@
if (tripletData.writeBit) {
newSearchState.romId[idByteNumber] |= idBitMask;
- } else {
- newSearchState.romId[idByteNumber] &= ~idBitMask;
- if (!tripletData.readBit && !tripletData.readBitComplement) {
- newSearchState.lastDiscrepancy = idBitNumber;
- if (idBitNumber <= 8) {
- newSearchState.lastFamilyDiscrepancy = idBitNumber;
- }
+ } else if (!tripletData.readBit && !tripletData.readBitComplement) {
+ newSearchState.lastDiscrepancy = idBitNumber;
+ if (idBitNumber <= 8) {
+ newSearchState.lastFamilyDiscrepancy = idBitNumber;
}
}
}
if (valid(newSearchState.romId)) {
- if (newSearchState.lastDiscrepancy == searchState.lastDiscrepancy) {
+ if (newSearchState.lastDiscrepancy == 0) {
newSearchState.lastDevice = true;
}
searchState = newSearchState;
--- a/Links/RomCommands.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/RomCommands.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -30,7 +30,8 @@
* ownership rights.
*******************************************************************************/
-/// @file ROM Commands for enumerating and selecting 1-Wire devices.
+/// @file
+/// @brief ROM Commands for enumerating and selecting 1-Wire devices.
#ifndef MaximInterface_RomCommands
#define MaximInterface_RomCommands
@@ -44,7 +45,7 @@
/// State used by Search ROM command.
struct SearchRomState {
- RomId romId;
+ RomId::array romId;
int_least8_t lastDiscrepancy;
int_least8_t lastFamilyDiscrepancy;
bool lastDevice;
@@ -53,61 +54,74 @@
: romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0),
lastDevice(false) {}
- explicit SearchRomState(const RomId & romId)
- : romId(romId), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
- lastDevice(false) {}
+ explicit SearchRomState(RomId::const_span romId)
+ : lastDiscrepancy(64), lastFamilyDiscrepancy(0), lastDevice(false) {
+ copy(romId, make_span(this->romId));
+ }
- explicit SearchRomState(RomId::value_type familyCode)
+ explicit SearchRomState(RomId::element familyCode)
: romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
lastDevice(false) {
setFamilyCode(romId, familyCode);
}
};
+/// @brief
/// Set the search state to skip the current device family on the next
/// Search ROM command.
MaximInterface_EXPORT void skipCurrentFamily(SearchRomState & searchState);
/// Verify that the device with the specified ROM ID is present.
MaximInterface_EXPORT error_code verifyRom(OneWireMaster & master,
- const RomId & romId);
+ RomId::const_span romId);
-/// Use Read ROM command to read ROM ID from device on bus.
-/// @note Only use this command with a single drop bus, data
-/// collisions will occur if more than 1 device on bus.
+/// @brief Use Read ROM command to read ROM ID from device on bus.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
+/// @param master 1-Wire master for operation.
/// @param[out] romId ROM ID read from device.
-MaximInterface_EXPORT error_code readRom(OneWireMaster & master, RomId & romId);
+MaximInterface_EXPORT error_code readRom(OneWireMaster & master,
+ RomId::span romId);
-/// Issue Skip ROM command on bus.
-/// @note Only use this command with a single drop bus, data
-/// collisions will occur if more than 1 device on bus.
+/// @brief Issue Skip ROM command on bus.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
MaximInterface_EXPORT error_code skipRom(OneWireMaster & master);
-/// Use the Match ROM command to select the device by its known ID.
-/// @note This command causes all devices supporting Overdrive
-/// mode to switch to Overdrive timing.
+/// @brief Use the Match ROM command to select the device by its known ID.
+/// @note
+/// This command causes all devices supporting Overdrive mode to switch to
+/// Overdrive timing.
+/// @param master 1-Wire master for operation.
/// @param[in] romId ROM ID of device to select.
MaximInterface_EXPORT error_code matchRom(OneWireMaster & master,
- const RomId & romId);
+ RomId::const_span romId);
-/// Issue Overdrive Skip ROM command on bus.
-/// @note This command causes all devices supporting Overdrive
-/// mode to switch to Overdrive timing.
-/// @note Only use this command with a single drop bus, data
-/// collisions will occur if more than 1 device on bus.
+/// @brief Issue Overdrive Skip ROM command on bus.
+/// @note
+/// This command causes all devices supporting Overdrive mode to switch to
+/// Overdrive timing.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
MaximInterface_EXPORT error_code overdriveSkipRom(OneWireMaster & master);
+/// @brief
/// Use the Overdrive Match ROM command to select the device by its known ID.
+/// @param master 1-Wire master for operation.
/// @param[in] romId ROM ID of device to select.
MaximInterface_EXPORT error_code overdriveMatchRom(OneWireMaster & master,
- const RomId & romId);
+ RomId::const_span romId);
-/// Perform a Resume ROM command on bus.
-/// @details Resumes communication with the last device selected
-/// though a Match ROM or Search ROM operation.
+/// @brief Perform a Resume ROM command on bus.
+/// @details
+/// Resumes communication with the last device selected through a Match ROM or
+/// Search ROM operation.
MaximInterface_EXPORT error_code resumeRom(OneWireMaster & master);
-/// Find device on the 1-Wire bus.
+/// @brief Find device on the 1-Wire bus.
/// @details
/// This command uses the Search ROM command to enumerate all 1-Wire devices in
/// sequence. Begin with a new search state and continue using the same search
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/RunCommand.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,210 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/crc.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "I2CMaster.hpp"
+#include "OneWireMaster.hpp"
+#include "Sleep.hpp"
+#include "RunCommand.hpp"
+
+namespace MaximInterface {
+
+const error_category & RunCommandWithOneWireMaster::errorCategory() {
+ static class : public error_category {
+ public:
+ virtual const char * name() const { return "RunCommandWithOneWireMaster"; }
+
+ virtual std::string message(int condition) const {
+ switch (condition) {
+ case CrcError:
+ return "CRC Error";
+
+ case InvalidResponseError:
+ return "Invalid Response Error";
+ }
+ return defaultErrorMessage(condition);
+ }
+ } instance;
+ return instance;
+}
+
+error_code RunCommandWithOneWireMaster::
+operator()(span<const uint_least8_t> command, int delayTime,
+ span<uint_least8_t> & response) const {
+ // Write command.
+ error_code result = selectRom(*master);
+ if (result) {
+ return result;
+ }
+ uint_least8_t xpcBuffer[2] = {0x66,
+ static_cast<uint_least8_t>(command.size())};
+ result = master->writeBlock(xpcBuffer);
+ if (result) {
+ return result;
+ }
+ result = master->writeBlock(command);
+ if (result) {
+ return result;
+ }
+ uint_fast16_t expectedCrc =
+ calculateCrc16(command, calculateCrc16(xpcBuffer)) ^ 0xFFFFU;
+ result = master->readBlock(xpcBuffer);
+ if (result) {
+ return result;
+ }
+ if (expectedCrc !=
+ ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
+ return make_error_code(CrcError);
+ }
+ result = master->writeBytePower(0xAA);
+ if (result) {
+ return result;
+ }
+
+ // Wait for device to process.
+ sleep->invoke(delayTime);
+
+ // Read response.
+ result = master->setLevel(OneWireMaster::NormalLevel);
+ if (result) {
+ return result;
+ }
+ result = master->readBlock(xpcBuffer);
+ if (result) {
+ return result;
+ }
+ if (xpcBuffer[1] > response.size()) {
+ return make_error_code(InvalidResponseError);
+ }
+ response = response.first(xpcBuffer[1]);
+ result = master->readBlock(response);
+ if (result) {
+ return result;
+ }
+ expectedCrc =
+ calculateCrc16(response, calculateCrc16(make_span(xpcBuffer + 1, 1))) ^
+ 0xFFFFU;
+ result = master->readBlock(xpcBuffer);
+ if (result) {
+ return result;
+ }
+ if (expectedCrc !=
+ ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
+ return make_error_code(CrcError);
+ }
+ return result;
+}
+
+const error_category & RunCommandWithI2CMaster::errorCategory() {
+ static class : public error_category {
+ public:
+ virtual const char * name() const { return "RunCommandWithI2CMaster"; }
+
+ virtual std::string message(int condition) const {
+ switch (condition) {
+ case InvalidResponseError:
+ return "Invalid Response Error";
+ }
+ return defaultErrorMessage(condition);
+ }
+ } instance;
+ return instance;
+}
+
+error_code RunCommandWithI2CMaster::
+operator()(span<const uint_least8_t> command, int delayTime,
+ span<uint_least8_t> & response) const {
+ // Write command.
+ error_code result = master->start(address_);
+ if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) {
+ result = master->start(0);
+ }
+ if (result) {
+ master->stop();
+ return result;
+ }
+ if (!command.empty()) {
+ result = master->writeByte(command[0]);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ command = command.subspan(1);
+ if (!command.empty()) {
+ result = master->writeByte(command.size());
+ if (result) {
+ master->stop();
+ return result;
+ }
+ result = master->writeBlock(command);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ }
+ }
+ result = master->stop();
+ if (result) {
+ return result;
+ }
+
+ // Wait for device to process.
+ sleep->invoke(delayTime);
+
+ // Read response.
+ result = master->start(address_ | 1);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ uint_least8_t length;
+ result = master->readByte(I2CMaster::Ack, length);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ if (length > response.size()) {
+ master->stop();
+ return make_error_code(InvalidResponseError);
+ }
+ response = response.first(length);
+ result = master->readBlock(I2CMaster::Nack, response);
+ if (result) {
+ master->stop();
+ return result;
+ }
+ result = master->stop();
+ return result;
+}
+
+} // namespace MaximInterface
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/RunCommand.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,120 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_RunCommand
+#define MaximInterface_RunCommand
+
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/Function.hpp>
+#include <MaximInterface/Utilities/span.hpp>
+#include <MaximInterface/Utilities/system_error.hpp>
+#include "SelectRom.hpp"
+
+namespace MaximInterface {
+
+class I2CMaster;
+class OneWireMaster;
+class Sleep;
+
+typedef Function<error_code(span<const uint_least8_t>, int,
+ span<uint_least8_t> &)>
+ RunCommand;
+
+class RunCommandWithOneWireMaster {
+public:
+ typedef RunCommand::result_type result_type;
+
+ enum ErrorValue { CrcError = 1, InvalidResponseError };
+ MaximInterface_EXPORT static const error_category & errorCategory();
+
+ RunCommandWithOneWireMaster(Sleep & sleep, OneWireMaster & master,
+ const SelectRom & selectRom)
+ : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
+ void setMaster(OneWireMaster & master) { this->master = &master; }
+
+ void setSelectRom(const SelectRom & selectRom) {
+ this->selectRom = selectRom;
+ }
+
+ MaximInterface_EXPORT error_code
+ operator()(span<const uint_least8_t> command, int delayTime,
+ span<uint_least8_t> & response) const;
+
+private:
+ SelectRom selectRom;
+ OneWireMaster * master;
+ const Sleep * sleep;
+};
+
+inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) {
+ return error_code(e, RunCommandWithOneWireMaster::errorCategory());
+}
+
+class RunCommandWithI2CMaster {
+public:
+ typedef RunCommand::result_type result_type;
+
+ enum ErrorValue { InvalidResponseError = 1 };
+ MaximInterface_EXPORT static const error_category & errorCategory();
+
+ RunCommandWithI2CMaster(Sleep & sleep, I2CMaster & master,
+ uint_least8_t address)
+ : sleep(&sleep), master(&master), address_(address & 0xFE) {}
+
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
+ void setMaster(I2CMaster & master) { this->master = &master; }
+
+ uint_least8_t address() const { return address_; }
+
+ void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
+
+ MaximInterface_EXPORT error_code
+ operator()(span<const uint_least8_t> command, int delayTime,
+ span<uint_least8_t> & response) const;
+
+private:
+ const Sleep * sleep;
+ I2CMaster * master;
+ uint_least8_t address_;
+};
+
+inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) {
+ return error_code(e, RunCommandWithI2CMaster::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- a/Links/SelectRom.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/SelectRom.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -40,11 +40,11 @@
error_code SelectMatchRomWithResume::operator()(OneWireMaster & master) const {
error_code result;
- if (romId_ == data->lastRom) {
+ if (romId_ == data->lastRomId) {
result = resumeRom(master);
} else {
result = matchRom(master, romId_);
- data->lastRom = romId_;
+ data->lastRomId = romId_;
}
return result;
}
--- a/Links/SelectRom.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/SelectRom.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -43,6 +43,7 @@
class OneWireMaster;
+/// Selects a 1-Wire device on the bus for communication.
typedef Function<error_code(OneWireMaster &)> SelectRom;
typedef Function<error_code(OneWireMaster &, const RomId & romId)> SelectRomExt;
@@ -52,41 +53,47 @@
typedef SelectRom::argument_type argument_type;
typedef SelectRom::result_type result_type;
- explicit SelectMatchRom(const RomId & romId = RomId()) : romId_(romId) {}
+ explicit SelectMatchRom(RomId::const_span romId) { setRomId(romId); }
- const RomId & romId() const { return romId_; }
- void setRomId(const RomId & romId) { romId_ = romId; }
+ RomId::const_span romId() const { return romId_; }
+
+ void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
private:
- RomId romId_;
+ RomId::array romId_;
};
-/// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM command.
+/// @brief
+/// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM
+/// command.
class SelectMatchRomWithResume {
public:
typedef SelectRom::argument_type argument_type;
typedef SelectRom::result_type result_type;
struct SharedData {
- RomId lastRom;
-
- SharedData() : lastRom() {}
+ SharedData() : lastRomId() {}
+ RomId::array lastRomId;
};
- explicit SelectMatchRomWithResume(SharedData & data,
- const RomId & romId = RomId())
- : romId_(romId), data(&data) {}
+ SelectMatchRomWithResume(SharedData & data, RomId::const_span romId)
+ : data(&data) {
+ setRomId(romId);
+ }
- const RomId & romId() const { return romId_; }
- void setRomId(const RomId & romId) { romId_ = romId; }
+ void setSharedData(SharedData & data) { this->data = &data; }
+
+ RomId::const_span romId() const { return romId_; }
+
+ void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
private:
- RomId romId_;
SharedData * data;
+ RomId::array romId_;
};
} // namespace MaximInterface
--- a/Links/SerialPort.hpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Links/SerialPort.hpp Wed Apr 03 12:33:10 2019 +0000 @@ -46,7 +46,7 @@ /// Disconnect from the current port. virtual error_code disconnect() = 0; - /// Check if currently connected to a port. + /// @brief Check if currently connected to a port. /// @returns True if connected. virtual bool connected() const = 0; @@ -56,4 +56,4 @@ } -#endif \ No newline at end of file +#endif
--- a/Links/Sleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/Sleep.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -38,10 +38,10 @@
class Sleep {
public:
virtual ~Sleep() {}
-
- virtual void operator()(int ms) const = 0;
+ virtual void invoke(int ms) const = 0;
+ void operator()(int ms) const { invoke(ms); }
};
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/SleepDecorator.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/SleepDecorator.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -34,6 +34,6 @@
namespace MaximInterface {
-void SleepDecorator::operator()(int ms) const { (*sleep)(ms); }
+void SleepDecorator::invoke(int ms) const { sleep->invoke(ms); }
-}
\ No newline at end of file
+}
--- a/Links/SleepDecorator.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/SleepDecorator.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -40,11 +40,11 @@
class SleepDecorator : public Sleep {
protected:
- explicit SleepDecorator(const Sleep & sleep) : sleep(&sleep) {}
+ explicit SleepDecorator(Sleep & sleep) : sleep(&sleep) {}
public:
- void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
- MaximInterface_EXPORT virtual void operator()(int ms) const;
+ void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+ MaximInterface_EXPORT virtual void invoke(int ms) const;
private:
const Sleep * sleep;
@@ -52,4 +52,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Links/Uart.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/Uart.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,17 +35,18 @@
namespace MaximInterface {
-error_code Uart::writeBlock(const uint_least8_t * data, size_t dataLen) {
+error_code Uart::writeBlock(span<const uint_least8_t> data) {
error_code result;
- for (size_t i = 0; i < dataLen && !result; i++) {
+ for (span<const uint_least8_t>::index_type i = 0;
+ i < data.size() && !result; ++i) {
result = writeByte(data[i]);
}
return result;
}
-error_code Uart::readBlock(uint_least8_t * data, size_t dataLen) {
+error_code Uart::readBlock(span<uint_least8_t> data) {
error_code result;
- for (size_t i = 0; i < dataLen && !result; i++) {
+ for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) {
result = readByte(data[i]);
}
return result;
@@ -72,4 +73,4 @@
return instance;
}
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Links/Uart.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Links/Uart.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -34,9 +34,8 @@
#define MaximInterface_Uart
#include <stdint.h>
-#include <stddef.h>
-
#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/span.hpp>
#include <MaximInterface/Utilities/system_error.hpp>
namespace MaximInterface {
@@ -65,19 +64,19 @@
/// Writes a block of data to the port.
MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * data, size_t dataLen);
+ writeBlock(span<const uint_least8_t> data);
+ /// @brief
/// Reads a byte of data from the port. Block until data is received or a
/// timeout is reached.
/// @param[out] data Data read from the port if successful.
virtual error_code readByte(uint_least8_t & data) = 0;
+ /// @brief
/// Read a block of data from the port. Block until data is received or a
/// timeout is reached.
/// @param[out] data Data read from the port if successful.
- /// @para dataLen Number of bytes to read and length of data.
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * data,
- size_t dataLen);
+ MaximInterface_EXPORT virtual error_code readBlock(span<uint_least8_t> data);
MaximInterface_EXPORT static const error_category & errorCategory();
};
@@ -85,10 +84,11 @@
inline error_code make_error_code(Uart::ErrorValue e) {
return error_code(e, Uart::errorCategory());
}
+
inline error_condition make_error_condition(Uart::ErrorValue e) {
return error_condition(e, Uart::errorCategory());
}
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Platforms/Qt/.mbedignore Tue Jul 24 08:33:31 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -* \ No newline at end of file
--- a/Platforms/Qt/SerialPort.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <QSerialPortInfo>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "SerialPort.hpp"
-#include "Sleep.hpp"
-
-using std::string;
-
-namespace MaximInterface {
-namespace Qt {
-
-static_assert(QSerialPort::NoError == 0, "Remapping required for error_code.");
-
-error_code SerialPort::connect(const string & portName) {
- port.setPort(QSerialPortInfo(QString::fromStdString(portName)));
- auto result = port.open(QSerialPort::ReadWrite)
- ? error_code()
- : make_error_code(port.error());
- if (result) {
- return result;
- }
- result = port.setDataTerminalReady(true) ? error_code()
- : make_error_code(port.error());
- if (result) {
- port.close();
- }
- return result;
-}
-
-error_code SerialPort::disconnect() {
- port.close();
- return error_code();
-}
-
-bool SerialPort::connected() const { return port.isOpen(); }
-
-string SerialPort::portName() const { return port.portName().toStdString(); }
-
-error_code SerialPort::setBaudRate(int_least32_t baudRate) {
- return port.setBaudRate(baudRate) ? error_code()
- : make_error_code(port.error());
-}
-
-error_code SerialPort::sendBreak() {
- auto result =
- port.setBreakEnabled(true) ? error_code() : make_error_code(port.error());
- if (!result) {
- sleep(1);
- result = port.setBreakEnabled(false) ? error_code()
- : make_error_code(port.error());
- }
- return result;
-}
-
-error_code SerialPort::clearReadBuffer() {
- port.readAll();
- return error_code();
-}
-
-error_code SerialPort::writeByte(uint_least8_t data) {
- auto result =
- port.putChar(data) ? error_code() : make_error_code(port.error());
- if (!result) {
- result = port.waitForBytesWritten(1000) ? error_code()
- : make_error_code(port.error());
- }
- return result;
-}
-
-error_code SerialPort::readByte(uint_least8_t & data) {
- if (port.atEnd()) {
- const auto result = port.waitForReadyRead(1000)
- ? error_code()
- : make_error_code(port.error());
- if (result) {
- return result;
- }
- }
- return port.getChar(reinterpret_cast<char *>(&data))
- ? error_code()
- : make_error_code(port.error());
-}
-
-const error_category & SerialPort::errorCategory() {
- static class : public error_category {
- public:
- virtual const char * name() const override { return "Qt SerialPort"; }
-
- virtual string message(int condition) const override {
- switch (condition) {
- case QSerialPort::DeviceNotFoundError:
- return "Device Not Found";
-
- case QSerialPort::PermissionError:
- return "Permission Error";
-
- case QSerialPort::OpenError:
- return "Open Error";
-
- case QSerialPort::NotOpenError:
- return "Not Open Error";
-
- case QSerialPort::WriteError:
- return "Write Error";
-
- case QSerialPort::ReadError:
- return "Read Error";
-
- case QSerialPort::ResourceError:
- return "Resource Error";
-
- case QSerialPort::UnsupportedOperationError:
- return "Unsupported Operation Error";
-
- case QSerialPort::TimeoutError:
- return "Timeout Error";
-
- default:
- return defaultErrorMessage(condition);
- }
- }
-
- // Make QSerialPort::TimeoutError equivalent to Uart::TimeoutError.
- virtual bool equivalent(int code,
- const error_condition & condition) const override {
- return (code == QSerialPort::TimeoutError)
- ? (condition == make_error_condition(Uart::TimeoutError))
- : error_category::equivalent(code, condition);
- }
- } instance;
- return instance;
-}
-
-} // namespace Qt
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/Qt/SerialPort.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <QSerialPort>
-#include <MaximInterface/Links/SerialPort.hpp>
-#include <MaximInterface/Utilities/Export.h>
-
-namespace MaximInterface {
-namespace Qt {
-
-class SerialPort : public MaximInterface::SerialPort {
-public:
- MaximInterface_EXPORT virtual error_code
- connect(const std::string & portName) override;
- MaximInterface_EXPORT virtual error_code disconnect() override;
- MaximInterface_EXPORT virtual bool connected() const override;
- MaximInterface_EXPORT virtual std::string portName() const override;
-
- MaximInterface_EXPORT virtual error_code
- setBaudRate(int_least32_t baudRate) override;
- MaximInterface_EXPORT virtual error_code sendBreak() override;
- MaximInterface_EXPORT virtual error_code clearReadBuffer() override;
- MaximInterface_EXPORT virtual error_code
- writeByte(uint_least8_t data) override;
- MaximInterface_EXPORT virtual error_code
- readByte(uint_least8_t & data) override;
-
- MaximInterface_EXPORT static const error_category & errorCategory();
-
-private:
- QSerialPort port;
-};
-
-inline error_code make_error_code(QSerialPort::SerialPortError e) {
- return error_code(e, SerialPort::errorCategory());
-}
-
-} // namespace Qt
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/Qt/Sleep.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <QThread>
-#include "SerialPort.hpp"
-#include "Sleep.hpp"
-
-namespace MaximInterface {
-namespace Qt {
-
-void sleep(const int ms) {
- QThread::msleep(ms);
-}
-
-Sleep & Sleep::instance() {
- static Sleep instance;
- return instance;
-}
-
-void Sleep::operator()(int ms) const { sleep(ms); }
-
-} // namespace Qt
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/Qt/Sleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_Qt_SerialPort
-#define MaximInterface_Qt_SerialPort
-
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/Uncopyable.hpp>
-
-namespace MaximInterface {
-namespace Qt {
-
-MaximInterface_EXPORT void sleep(int ms);
-
-class Sleep : public MaximInterface::Sleep, private Uncopyable {
-public:
- MaximInterface_EXPORT static Sleep & instance();
-
- MaximInterface_EXPORT virtual void operator()(int ms) const override;
-
-private:
- Sleep() = default;
-};
-
-} // namespace Qt
-} // namespace MaximInterface
-
-#endif
\ No newline at end of file
--- a/Platforms/dotnet/.mbedignore Tue Jul 24 08:33:31 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -* \ No newline at end of file
--- a/Platforms/dotnet/ChangeSizeType.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#pragma once
-
-#include <algorithm>
-#include <limits>
-#include <type_traits>
-
-namespace MaximInterface {
-
-/// Adapts functions taking a data pointer and data size where the size type is
-/// not size_t. The function will be called multiple times if necessary to
-/// process all data.
-template <typename NewSize, typename Func, typename Data>
-void changeSizeType(Func func, Data data, size_t dataSize) {
- using namespace std;
-
- // Check if NewSize can represent the maximum value of dataSize.
- if (numeric_limits<decltype(dataSize)>::max() >
- static_cast<make_unsigned_t<NewSize>>(numeric_limits<NewSize>::max())) {
- do {
- const auto chunkSize =
- min<decltype(dataSize)>(dataSize, numeric_limits<NewSize>::max());
- func(data, static_cast<NewSize>(chunkSize));
- data += chunkSize;
- dataSize -= chunkSize;
- } while (dataSize > 0);
- } else {
- func(data, static_cast<NewSize>(dataSize));
- }
-}
-
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/DelegateWrapper.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#pragma once
-
-#include <msclr/marshal_cppstd.h>
-#include <vcclr.h>
-
-namespace MaximInterface {
-namespace detail {
-
-template <typename DelegateT> class DelegateWrapperBase {
-public:
- using Delegate = DelegateT;
-
-protected:
- DelegateWrapperBase(Delegate ^ target) : target_(target) {}
- ~DelegateWrapperBase() = default;
-
-public:
- Delegate ^ target() const { return static_cast<Delegate ^>(target_); }
- void setTarget(Delegate ^ target) { target_ = target; }
- void swap(DelegateWrapperBase & other) { target_.swap(other.target_); }
- explicit operator bool() const { return target() != nullptr; }
-
-private:
- gcroot<Delegate ^> target_;
-};
-
-template <typename DelegateT>
-inline void swap(DelegateWrapperBase<DelegateT> & lhs,
- DelegateWrapperBase<DelegateT> & rhs) {
- lhs.swap(rhs);
-}
-
-template <typename R, typename... Args>
-class DelegateWrapperImpl
- : public DelegateWrapperBase<System::Func<Args..., R> > {
-protected:
- DelegateWrapperImpl(Delegate ^ target) : DelegateWrapperBase(target) {}
-
-public:
- R operator()(Args... args) { return target()(args...); }
-};
-
-template <typename... Args>
-class DelegateWrapperImpl<void, Args...>
- : public DelegateWrapperBase<System::Action<Args...> > {
-protected:
- DelegateWrapperImpl(Delegate ^ target) : DelegateWrapperBase(target) {}
-
-public:
- void operator()(Args... args) const { target()(args...); }
-};
-
-} // namespace detail
-
-/// @{
-/// Functor wrapper for .NET delegates.
-template <typename> class DelegateWrapper;
-
-template <typename R, typename... Args>
-class DelegateWrapper<R(Args...)>
- : public detail::DelegateWrapperImpl<R, Args...> {
-public:
- DelegateWrapper(Delegate ^ target = nullptr) : DelegateWrapperImpl(target) {}
-};
-
-template <typename R, typename... Args>
-class DelegateWrapper<R __clrcall(Args...)>
- : public detail::DelegateWrapperImpl<R, Args...> {
-public:
- DelegateWrapper(Delegate ^ target = nullptr) : DelegateWrapperImpl(target) {}
-};
-/// @}
-
-/// Wrapper for using a .NET delegate as a MaximInterface::WriteMessage.
-class WriteMessageDelegateWrapper
- : public DelegateWrapper<void(System::String ^)> {
-public:
- WriteMessageDelegateWrapper(Delegate ^ target = nullptr)
- : DelegateWrapper(target) {}
-
- void operator()(const std::string & arg) const {
- target()(msclr::interop::marshal_as<System::String ^>(arg));
- }
-};
-
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/MoveOnly.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_MoveOnly
-#define MaximInterface_MoveOnly
-
-namespace MaximInterface {
-
-class MoveOnly {
-protected:
- MoveOnly() = default;
- ~MoveOnly() = default;
-
- MoveOnly(const MoveOnly &) = delete;
- MoveOnly(MoveOnly &&) = default;
- const MoveOnly & operator=(const MoveOnly &) = delete;
- MoveOnly & operator=(MoveOnly &&) = default;
-};
-
-} // namespace MaximInterface
-
-#endif
\ No newline at end of file
--- a/Platforms/dotnet/OneWireLinkLayerMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <stdexcept>
-#include <msclr/auto_gcroot.h>
-#include <msclr/marshal_cppstd.h>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "ChangeSizeType.hpp"
-#include "OneWireLinkLayerMaster.hpp"
-
-using DalSemi::OneWire::Adapter::AdapterException;
-using System::IntPtr;
-using System::Runtime::InteropServices::Marshal;
-using System::String;
-using msclr::interop::marshal_as;
-using std::string;
-
-namespace MaximInterface {
-
-struct OneWireLinkLayerMaster::Data {
- msclr::auto_gcroot<DalSemi::OneWire::Adapter::PortAdapter ^> adapter;
- bool connected = false;
-};
-
-OneWireLinkLayerMaster::OneWireLinkLayerMaster(const string & adapterName)
- : data(std::make_unique<Data>()) {
- try {
- data->adapter = DalSemi::OneWire::AccessProvider::GetAdapter(
- marshal_as<String ^>(adapterName));
- } catch (AdapterException ^ e) {
- throw std::invalid_argument(marshal_as<string>(e->Message));
- }
-}
-
-OneWireLinkLayerMaster::~OneWireLinkLayerMaster() = default;
-
-OneWireLinkLayerMaster::OneWireLinkLayerMaster(
- OneWireLinkLayerMaster && rhs) noexcept = default;
-
-OneWireLinkLayerMaster & OneWireLinkLayerMaster::
-operator=(OneWireLinkLayerMaster && rhs) noexcept = default;
-
-error_code OneWireLinkLayerMaster::connect(const string & portName) {
- if (connected()) {
- return make_error_code(AlreadyConnectedError);
- }
-
- error_code result;
- try {
- auto adapterResult =
- data->adapter->OpenPort(marshal_as<String ^>(portName));
- if (adapterResult) {
- adapterResult = data->adapter->BeginExclusive(true);
- if (adapterResult) {
- data->connected = true;
- } else {
- data->adapter->FreePort();
- result = make_error_code(OpenPortError);
- }
- } else {
- result = make_error_code(OpenPortError);
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-void OneWireLinkLayerMaster::disconnect() {
- data->adapter->EndExclusive();
- data->adapter->FreePort();
- data->connected = false;
-}
-
-bool OneWireLinkLayerMaster::connected() const { return data->connected; }
-
-string OneWireLinkLayerMaster::adapterName() const {
- return marshal_as<string>(data->adapter->AdapterName);
-}
-
-string OneWireLinkLayerMaster::portName() const {
- return connected() ? marshal_as<string>(data->adapter->PortName) : "";
-}
-
-error_code OneWireLinkLayerMaster::reset() {
- using DalSemi::OneWire::Adapter::OWResetResult;
-
- error_code result;
- try {
- switch (data->adapter->Reset()) {
- case OWResetResult::RESET_SHORT:
- result = make_error_code(ShortDetectedError);
- break;
-
- case OWResetResult::RESET_NOPRESENCE:
- result = make_error_code(NoSlaveError);
- break;
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::touchBitSetLevel(bool & sendRecvBit,
- Level afterLevel) {
- error_code result;
- try {
- switch (afterLevel) {
- case StrongLevel: {
- auto adapterResult = data->adapter->StartPowerDelivery(
- DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BIT);
- if (!adapterResult) {
- result = make_error_code(PowerDeliveryError);
- }
- } break;
-
- case NormalLevel:
- break;
-
- default:
- result = make_error_code(InvalidLevelError);
- break;
- }
- if (!result) {
- if (sendRecvBit) {
- sendRecvBit = data->adapter->GetBit();
- } else {
- data->adapter->PutBit(0);
- }
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::writeByteSetLevel(uint_least8_t sendByte,
- Level afterLevel) {
- error_code result;
- try {
- switch (afterLevel) {
- case StrongLevel: {
- auto adapterResult = data->adapter->StartPowerDelivery(
- DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BYTE);
- if (!adapterResult) {
- result = make_error_code(PowerDeliveryError);
- }
- } break;
-
- case NormalLevel:
- break;
-
- default:
- result = make_error_code(InvalidLevelError);
- break;
- }
- if (!result) {
- data->adapter->PutByte(sendByte);
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::readByteSetLevel(uint_least8_t & recvByte,
- Level afterLevel) {
- error_code result;
- try {
- switch (afterLevel) {
- case StrongLevel: {
- auto adapterResult = data->adapter->StartPowerDelivery(
- DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BYTE);
- if (!adapterResult) {
- result = make_error_code(PowerDeliveryError);
- }
- } break;
-
- case NormalLevel:
- break;
-
- default:
- result = make_error_code(InvalidLevelError);
- break;
- }
- if (!result) {
- recvByte = data->adapter->GetByte();
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::writeBlock(const uint_least8_t * sendBuf,
- size_t sendLen) {
- error_code result;
- try {
- changeSizeType<int>(
- [this](const uint_least8_t * data, int dataSize) {
- auto dataManaged = gcnew array<uint_least8_t>(dataSize);
- Marshal::Copy(static_cast<IntPtr>(const_cast<uint_least8_t *>(data)),
- dataManaged, 0, dataSize);
- this->data->adapter->DataBlock(dataManaged, 0, dataSize);
- },
- sendBuf, sendLen);
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::readBlock(uint_least8_t * recvBuf,
- size_t recvLen) {
- error_code result;
- try {
- changeSizeType<int>(
- [this](uint_least8_t * data, int dataSize) {
- auto dataManaged = gcnew array<uint_least8_t>(dataSize);
- this->data->adapter->GetBlock(dataManaged, dataSize);
- Marshal::Copy(dataManaged, 0, static_cast<IntPtr>(data), dataSize);
- },
- recvBuf, recvLen);
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::setSpeed(Speed newSpeed) {
- using DalSemi::OneWire::Adapter::OWSpeed;
-
- error_code result;
- try {
- switch (newSpeed) {
- case OverdriveSpeed:
- data->adapter->Speed = OWSpeed::SPEED_OVERDRIVE;
- break;
-
- case StandardSpeed:
- data->adapter->Speed = OWSpeed::SPEED_REGULAR;
- break;
-
- default:
- result = make_error_code(InvalidSpeedError);
- break;
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-error_code OneWireLinkLayerMaster::setLevel(Level newLevel) {
- error_code result;
- try {
- switch (newLevel) {
- case StrongLevel: {
- auto setResult = data->adapter->StartPowerDelivery(
- DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_NOW);
- if (!setResult) {
- result = make_error_code(PowerDeliveryError);
- }
- } break;
-
- case NormalLevel:
- data->adapter->SetPowerNormal();
- break;
-
- default:
- result = make_error_code(InvalidLevelError);
- break;
- }
- } catch (AdapterException ^) {
- result = make_error_code(CommunicationError);
- }
- return result;
-}
-
-const error_category & OneWireLinkLayerMaster::errorCategory() {
- static class : public error_category {
- public:
- virtual const char * name() const { return "OneWireLinkLayerMaster"; }
-
- virtual string message(int condition) const {
- switch (condition) {
- case CommunicationError:
- return "Communication Error";
-
- case OpenPortError:
- return "Open Port Error";
-
- case PowerDeliveryError:
- return "Power Delivery Error";
-
- case AlreadyConnectedError:
- return "Already Connected Error";
-
- default:
- return defaultErrorMessage(condition);
- }
- }
- } instance;
- return instance;
-}
-
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/OneWireLinkLayerMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <MaximInterface/Links/OneWireMaster.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include "MoveOnly.hpp"
-
-namespace MaximInterface {
-
-/// 1-Wire interface using the OneWireLinkLayer DLL from the Compact.NET API.
-class OneWireLinkLayerMaster : public OneWireMaster, private MoveOnly {
-public:
- enum ErrorValue {
- CommunicationError = 1,
- OpenPortError,
- PowerDeliveryError,
- AlreadyConnectedError
- };
-
- /// @param adapterName Adapter type name recogized by OneWireLinkLayer.
- MaximInterface_EXPORT OneWireLinkLayerMaster(const std::string & adapterName);
- MaximInterface_EXPORT ~OneWireLinkLayerMaster();
-
- MaximInterface_EXPORT
- OneWireLinkLayerMaster(OneWireLinkLayerMaster &&) noexcept;
- MaximInterface_EXPORT OneWireLinkLayerMaster &
- operator=(OneWireLinkLayerMaster &&) noexcept;
-
- /// Connect to an adapter on the specified COM port.
- MaximInterface_EXPORT error_code connect(const std::string & portName);
-
- /// Disconnect from the adapter on the current COM port.
- MaximInterface_EXPORT void disconnect();
-
- /// Check if currently connected to an adapter.
- /// @returns True if connected.
- MaximInterface_EXPORT bool connected() const;
-
- /// Get the adapter type name.
- MaximInterface_EXPORT std::string adapterName() const;
-
- /// Get the currently connected COM port name.
- MaximInterface_EXPORT std::string portName() const;
-
- MaximInterface_EXPORT virtual error_code reset() override;
- MaximInterface_EXPORT virtual error_code
- touchBitSetLevel(bool & sendRecvBit, Level afterLevel) override;
- MaximInterface_EXPORT virtual error_code
- writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) override;
- MaximInterface_EXPORT virtual error_code
- readByteSetLevel(uint_least8_t & recvByte, Level afterLevel) override;
- MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * sendBuf, size_t sendLen) override;
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
- size_t recvLen) override;
- MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed) override;
- MaximInterface_EXPORT virtual error_code setLevel(Level newLevel) override;
-
- MaximInterface_EXPORT static const error_category & errorCategory();
-
-private:
- struct Data;
- std::unique_ptr<Data> data;
-};
-
-inline error_code make_error_code(OneWireLinkLayerMaster::ErrorValue e) {
- return error_code(e, OneWireLinkLayerMaster::errorCategory());
-}
-
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/SerialPort.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <msclr/auto_gcroot.h>
-#include <msclr/marshal_cppstd.h>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "ChangeSizeType.hpp"
-#include "Sleep.hpp"
-#include "SerialPort.hpp"
-
-using msclr::interop::marshal_as;
-using std::string;
-using namespace System;
-using System::Runtime::InteropServices::Marshal;
-
-namespace MaximInterface {
-namespace dotnet {
-
-template <typename Type, typename Input> static bool isType(Input in) {
- return dynamic_cast<Type>(in) != nullptr;
-}
-
-template <typename Func>
-static error_code executeTryCatchOperation(Func tryOperation) {
- return executeTryCatchOperation(tryOperation, [] {});
-}
-
-template <typename TryFunc, typename CatchFunc>
-static error_code executeTryCatchOperation(TryFunc tryOperation,
- CatchFunc catchOperation) {
- error_code result;
- try {
- tryOperation();
- } catch (Exception ^ e) {
- catchOperation();
- if (isType<ArgumentException ^>(e)) {
- result = make_error_code(SerialPort::ArgumentError);
- } else if (isType<InvalidOperationException ^>(e)) {
- result = make_error_code(SerialPort::InvalidOperationError);
- } else if (isType<System::IO::IOException ^>(e)) {
- result = make_error_code(SerialPort::IOError);
- } else if (isType<UnauthorizedAccessException ^>(e)) {
- result = make_error_code(SerialPort::UnauthorizedAccessError);
- } else if (isType<TimeoutException ^>(e)) {
- result = make_error_code(SerialPort::TimeoutError);
- } else {
- throw;
- }
- }
- return result;
-}
-
-template <typename Func>
-static error_code executeIfConnected(const SerialPort & serial,
- Func operation) {
- return serial.connected() ? operation()
- : make_error_code(SerialPort::NotConnectedError);
-}
-
-struct SerialPort::Data {
- msclr::auto_gcroot<System::IO::Ports::SerialPort ^> port;
-};
-
-SerialPort::SerialPort() : data(std::make_unique<Data>()) {}
-
-SerialPort::~SerialPort() = default;
-
-SerialPort::SerialPort(SerialPort &&) noexcept = default;
-
-SerialPort & SerialPort::operator=(SerialPort &&) noexcept = default;
-
-error_code SerialPort::connect(const string & portName) {
- data->port = gcnew System::IO::Ports::SerialPort;
- return executeTryCatchOperation(
- [this, &portName] {
- data->port->PortName = marshal_as<String ^>(portName);
- data->port->DtrEnable = true;
- data->port->ReadTimeout = 1000;
- data->port->WriteTimeout = 1000;
- data->port->Open();
- },
- [this] { data->port.reset(); });
-}
-
-error_code SerialPort::disconnect() {
- data->port.reset();
- return error_code();
-}
-
-bool SerialPort::connected() const { return data->port.get() != nullptr; }
-
-string SerialPort::portName() const {
- return connected() ? marshal_as<string>(data->port->PortName) : "";
-}
-
-error_code SerialPort::setBaudRate(int_least32_t baudRate) {
- return executeIfConnected(*this, [this, baudRate] {
- return executeTryCatchOperation(
- [this, baudRate] { data->port->BaudRate = baudRate; });
- });
-}
-
-error_code SerialPort::sendBreak() {
- return executeIfConnected(*this, [this] {
- return executeTryCatchOperation([this] {
- data->port->BreakState = true;
- sleep(1);
- data->port->BreakState = false;
- });
- });
-}
-
-error_code SerialPort::clearReadBuffer() {
- return executeIfConnected(*this, [this] {
- return executeTryCatchOperation([this] { data->port->ReadExisting(); });
- });
-}
-
-error_code SerialPort::writeByte(uint_least8_t data) {
- return writeBlock(&data, 1);
-}
-
-error_code SerialPort::writeBlock(const uint_least8_t * data, size_t dataLen) {
- return executeIfConnected(*this, [this, data, dataLen] {
- return executeTryCatchOperation([this, data, dataLen] {
- changeSizeType<int>(
- [this](const uint_least8_t * dataChunk, int dataChunkSize) {
- auto dataManaged = gcnew array<uint_least8_t>(dataChunkSize);
- Marshal::Copy(
- static_cast<IntPtr>(const_cast<uint_least8_t *>(dataChunk)),
- dataManaged, 0, dataChunkSize);
- this->data->port->Write(dataManaged, 0, dataChunkSize);
- },
- data, dataLen);
- });
- });
-}
-
-error_code SerialPort::readByte(uint_least8_t & data) {
- return executeIfConnected(*this, [this, &data] {
- return executeTryCatchOperation(
- [this, &data] { data = this->data->port->ReadByte(); });
- });
-}
-
-error_code SerialPort::readBlock(uint_least8_t * data, size_t dataLen) {
- return executeIfConnected(*this, [this, data, dataLen] {
- return executeTryCatchOperation([this, data, dataLen] {
- changeSizeType<int>(
- [this](uint_least8_t * dataChunk, int dataChunkSize) {
- auto dataManaged = gcnew array<uint_least8_t>(dataChunkSize);
- int bytesRead = 0;
- do {
- bytesRead += this->data->port->Read(dataManaged, bytesRead,
- dataChunkSize - bytesRead);
- } while (bytesRead < dataChunkSize);
- Marshal::Copy(dataManaged, 0, static_cast<IntPtr>(dataChunk),
- dataChunkSize);
- },
- data, dataLen);
- });
- });
-}
-
-const error_category & SerialPort::errorCategory() {
- static class : public error_category {
- public:
- virtual const char * name() const override { return "dotnet SerialPort"; }
-
- virtual string message(int condition) const override {
- switch (condition) {
- case NotConnectedError:
- return "Not Connected Error";
-
- case ArgumentError:
- return "Argument Error";
-
- case InvalidOperationError:
- return "Invalid Operation Error";
-
- case IOError:
- return "IO Error";
-
- case UnauthorizedAccessError:
- return "Unauthorized Access Error";
-
- default:
- return defaultErrorMessage(condition);
- }
- }
- } instance;
- return instance;
-}
-
-} // namespace dotnet
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/SerialPort.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <MaximInterface/Links/SerialPort.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include "MoveOnly.hpp"
-
-namespace MaximInterface {
-namespace dotnet {
-
-/// Serial port interface using .NET type System::IO::Ports::SerialPort.
-class SerialPort : public MaximInterface::SerialPort, private MoveOnly {
-public:
- enum ErrorValue {
- NotConnectedError = 1,
- ArgumentError,
- InvalidOperationError,
- IOError,
- UnauthorizedAccessError
- };
-
- MaximInterface_EXPORT SerialPort();
- MaximInterface_EXPORT ~SerialPort();
-
- MaximInterface_EXPORT SerialPort(SerialPort &&) noexcept;
- MaximInterface_EXPORT SerialPort & operator=(SerialPort &&) noexcept;
-
- MaximInterface_EXPORT virtual error_code
- connect(const std::string & portName) override;
- MaximInterface_EXPORT virtual error_code disconnect() override;
- MaximInterface_EXPORT virtual bool connected() const override;
- MaximInterface_EXPORT virtual std::string portName() const override;
-
- MaximInterface_EXPORT virtual error_code
- setBaudRate(int_least32_t baudRate) override;
- MaximInterface_EXPORT virtual error_code sendBreak() override;
- MaximInterface_EXPORT virtual error_code clearReadBuffer() override;
- MaximInterface_EXPORT virtual error_code
- writeByte(uint_least8_t data) override;
- MaximInterface_EXPORT virtual error_code
- writeBlock(const uint_least8_t * data, size_t dataLen) override;
- MaximInterface_EXPORT virtual error_code
- readByte(uint_least8_t & data) override;
- MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * data,
- size_t dataLen) override;
-
- MaximInterface_EXPORT static const error_category & errorCategory();
-
-private:
- struct Data;
- std::unique_ptr<Data> data;
-};
-
-inline error_code make_error_code(SerialPort::ErrorValue e) {
- return error_code(e, SerialPort::errorCategory());
-}
-
-} // namespace dotnet
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/Sleep.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include "Sleep.hpp"
-
-namespace MaximInterface {
-namespace dotnet {
-
-void sleep(const int ms) {
- constexpr int timeSlice_ms = 20;
- if (ms > timeSlice_ms / 2) {
- System::Threading::Thread::Sleep(ms);
- } else {
- auto watch = System::Diagnostics::Stopwatch::StartNew();
- while (watch->ElapsedMilliseconds < ms);
- watch->Stop();
- }
-}
-
-Sleep & Sleep::instance() {
- static Sleep instance;
- return instance;
-}
-
-void Sleep::operator()(int ms) const { sleep(ms); }
-
-} // namespace dotnet
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/dotnet/Sleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#pragma once
-
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/Uncopyable.hpp>
-
-namespace MaximInterface {
-namespace dotnet {
-
-MaximInterface_EXPORT void sleep(int ms);
-
-class Sleep : public MaximInterface::Sleep, private Uncopyable {
-public:
- MaximInterface_EXPORT static Sleep & instance();
-
- MaximInterface_EXPORT virtual void operator()(int ms) const override;
-
-private:
- Sleep() = default;
-};
-
-} // namespace dotnet
-} // namespace MaximInterface
\ No newline at end of file
--- a/Platforms/mbed/I2CMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/I2CMaster.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -50,10 +50,10 @@
}
error_code I2CMaster::writePacketImpl(uint_least8_t address,
- const uint_least8_t * data,
- size_t dataLen, bool sendStop) {
- return (i2c->write(address, reinterpret_cast<const char *>(data), dataLen,
- !sendStop) == 0)
+ span<const uint_least8_t> data,
+ bool sendStop) {
+ return (i2c->write(address, reinterpret_cast<const char *>(data.data()),
+ data.size(), !sendStop) == 0)
? error_code()
: make_error_code(NackError);
}
@@ -64,13 +64,12 @@
}
error_code I2CMaster::readPacketImpl(uint_least8_t address,
- uint_least8_t * data, size_t dataLen,
- bool sendStop) {
- return (i2c->read(address, reinterpret_cast<char *>(data), dataLen,
+ span<uint_least8_t> data, bool sendStop) {
+ return (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(),
!sendStop) == 0)
? error_code()
: make_error_code(NackError);
}
} // namespace mbed
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Platforms/mbed/I2CMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/I2CMaster.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -50,12 +50,13 @@
virtual error_code stop();
virtual error_code writeByte(uint_least8_t data);
virtual error_code readByte(AckStatus status, uint_least8_t & data);
-
+
protected:
- virtual error_code readPacketImpl(uint_least8_t address, uint_least8_t * data,
- size_t dataLen, bool sendStop);
+ virtual error_code readPacketImpl(uint_least8_t address,
+ span<uint_least8_t> data, bool sendStop);
+
virtual error_code writePacketImpl(uint_least8_t address,
- const uint_least8_t * data, size_t dataLen,
+ span<const uint_least8_t> data,
bool sendStop);
private:
--- a/Platforms/mbed/Sleep.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/Sleep.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -43,7 +43,7 @@
return instance;
}
-void Sleep::operator()(int ms) const { sleep(ms); }
+void Sleep::invoke(int ms) const { sleep(ms); }
} // namespace mbed
-} // namespace MaximInterface
\ No newline at end of file
+} // namespace MaximInterface
--- a/Platforms/mbed/Sleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/Sleep.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -44,8 +44,7 @@
class Sleep : public MaximInterface::Sleep, private Uncopyable {
public:
static Sleep & instance();
-
- virtual void operator()(int ms) const;
+ virtual void invoke(int ms) const;
private:
Sleep() {}
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Wed Apr 03 12:33:10 2019 +0000
@@ -31,17 +31,25 @@
**********************************************************************/
// ow_usdelay configuration
-#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz
-#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
-// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results
+//
+// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP
+// for best results
+//
+// Processor clock in MHz
+#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000)
+//
+// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
+#define OVERHEAD_TUNING 18
+//
+// ARM specifies 1-3 cycles for pipeline refill following a branch
+#define PIPELINE_REFILL_PROC_CYCLES 1
// ow_usdelay constants
-#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch
#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
-#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay
+#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP)
#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
-// OwTiming offsets
+// OneWireTiming offsets
#define tRSTL_OFFSET 0
#define tMSP_OFFSET 2
#define tW0L_OFFSET 4
@@ -65,7 +73,7 @@
ow_usdelay_return
bx R14
-// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask)
+// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask)
MACRO
$label write_ow_gpio_low
ldr R2, [R0]
@@ -73,7 +81,7 @@
str R2, [R0]
MEND
-// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask)
+// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask)
MACRO
$label write_ow_gpio_high
ldr R2, [R0]
@@ -81,7 +89,9 @@
str R2, [R0]
MEND
-// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing)
+// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg,
+// volatile uint32_t * outReg, unsigned int pinMask,
+// const OneWireTiming * timing)
EXPORT ow_bit
ow_bit
push {R4-R8, R14}
@@ -90,9 +100,9 @@
ldr R6, [R6] // Load timing struct
ldrh R4, [R6, #tSLOT_OFFSET]
ldrh R5, [R6, #tMSR_OFFSET]
- // R0: sendrecvbit
- // R1: inPortReg
- // R2: outPortReg
+ // R0: sendRecvBit
+ // R1: inReg
+ // R2: outReg
// R3: pinMask
// R4: tSLOT
// R5: tMSR
@@ -102,22 +112,22 @@
// R14: Scratch
// Reorganize registers for upcoming function calls
- mov R8, R1 // inPortReg to R8
- mov R7, R2 // outPortReg to R7
+ mov R8, R1 // inReg to R8
+ mov R7, R2 // outReg to R7
mov R1, R3 // pinMask to R1
- mov R3, R0 // sendrecvbit to R3
+ mov R3, R0 // sendRecvBit to R3
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tSLOT
// R5: tMSR
// R6: timing
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- // if (*sendrecvbit & 1)
+ // if (*sendRecvBit & 1)
ldrb R14, [R3]
tst R14, #1
beq write_zero
@@ -127,22 +137,22 @@
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
// R5: delay2
// R6: tW1L
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_low // Pull low
mov R0, R6 // tLOW
bl ow_usdelay // Delay for tLOW
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_high // Release pin
mov R0, R5 // delay2
bl ow_usdelay // Delay for sample time
- ldr R5, [R8] // Read *inPortReg
+ ldr R5, [R8] // Read *inReg
b recovery_delay
// else
write_zero
@@ -152,32 +162,32 @@
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
// R5: tMSR
// R6: delay2
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_low // Pull low
mov R0, R5 // tMSR
bl ow_usdelay // Delay for tMSR
- ldr R5, [R8] // Read *inPortReg
+ ldr R5, [R8] // Read *inReg
mov R0, R6 // delay2
bl ow_usdelay // Delay for release
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_high // Release pin
- // endif (*sendrecvbit & 1)
+ // endif (*sendRecvBit & 1)
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
- // R5: *inPortReg
+ // R5: *inReg
// R6: Scratch
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
recovery_delay
@@ -185,7 +195,7 @@
bl ow_usdelay // Delay for tREC
// Parse received bit
- // *sendrecvbit = ((*inPortReg & pinMask) == pinMask)
+ // *sendRecvBit = ((*inReg & pinMask) == pinMask)
and R5, R5, R1
cmp R5, R1
ite eq
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Tue Jul 24 08:33:31 2018 +0000 +++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Wed Apr 03 12:33:10 2019 +0000 @@ -31,17 +31,25 @@ **********************************************************************/ // ow_usdelay configuration -#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz -#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ -// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results +// +// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP +// for best results +// +// Processor clock in MHz +#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) +// +// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ +#define OVERHEAD_TUNING 18 +// +// ARM specifies 1-3 cycles for pipeline refill following a branch +#define PIPELINE_REFILL_PROC_CYCLES 1 // ow_usdelay constants -#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch #define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES) -#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay +#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) #define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP) -// OwTiming offsets +// OneWireTiming offsets #define tRSTL_OFFSET 0 #define tMSP_OFFSET 2 #define tW0L_OFFSET 4 @@ -67,21 +75,23 @@ ow_usdelay_return: bx R14 -// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask) +// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask) .macro write_ow_gpio_low ldr R2, [R0] bic R2, R2, R1 str R2, [R0] .endm -// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask) +// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask) .macro write_ow_gpio_high ldr R2, [R0] orr R2, R2, R1 str R2, [R0] .endm -// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing) +// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg, +// volatile uint32_t * outReg, unsigned int pinMask, +// const OneWireTiming * timing) .thumb_func .global ow_bit ow_bit: @@ -91,9 +101,9 @@ ldr R6, [R6] // Load timing struct ldrh R4, [R6, #tSLOT_OFFSET] ldrh R5, [R6, #tMSR_OFFSET] - // R0: sendrecvbit - // R1: inPortReg - // R2: outPortReg + // R0: sendRecvBit + // R1: inReg + // R2: outReg // R3: pinMask // R4: tSLOT // R5: tMSR @@ -103,22 +113,22 @@ // R14: Scratch // Reorganize registers for upcoming function calls - mov R8, R1 // inPortReg to R8 - mov R7, R2 // outPortReg to R7 + mov R8, R1 // inReg to R8 + mov R7, R2 // outReg to R7 mov R1, R3 // pinMask to R1 - mov R3, R0 // sendrecvbit to R3 + mov R3, R0 // sendRecvBit to R3 // R0: Scratch // R1: pinMask // R2: Scratch - // R3: sendrecvbit + // R3: sendRecvBit // R4: tSLOT // R5: tMSR // R6: timing - // R7: outPortReg - // R8: inPortReg + // R7: outReg + // R8: inReg // R14: Scratch - // if (*sendrecvbit & 1) + // if (*sendRecvBit & 1) ldrb R14, [R3] tst R14, #1 beq write_zero @@ -128,22 +138,22 @@ // R0: Scratch // R1: pinMask // R2: Scratch - // R3: sendrecvbit + // R3: sendRecvBit // R4: tREC // R5: delay2 // R6: tW1L - // R7: outPortReg - // R8: inPortReg + // R7: outReg + // R8: inReg // R14: Scratch - mov R0, R7 // outPortReg + mov R0, R7 // outReg write_ow_gpio_low // Pull low mov R0, R6 // tLOW bl ow_usdelay // Delay for tLOW - mov R0, R7 // outPortReg + mov R0, R7 // outReg write_ow_gpio_high // Release pin mov R0, R5 // delay2 bl ow_usdelay // Delay for sample time - ldr R5, [R8] // Read *inPortReg + ldr R5, [R8] // Read *inReg b recovery_delay // else write_zero: @@ -153,32 +163,32 @@ // R0: Scratch // R1: pinMask // R2: Scratch - // R3: sendrecvbit + // R3: sendRecvBit // R4: tREC // R5: tMSR // R6: delay2 - // R7: outPortReg - // R8: inPortReg + // R7: outReg + // R8: inReg // R14: Scratch - mov R0, R7 // outPortReg + mov R0, R7 // outReg write_ow_gpio_low // Pull low mov R0, R5 // tMSR bl ow_usdelay // Delay for tMSR - ldr R5, [R8] // Read *inPortReg + ldr R5, [R8] // Read *inReg mov R0, R6 // delay2 bl ow_usdelay // Delay for release - mov R0, R7 // outPortReg + mov R0, R7 // outReg write_ow_gpio_high // Release pin - // endif (*sendrecvbit & 1) + // endif (*sendRecvBit & 1) // R0: Scratch // R1: pinMask // R2: Scratch - // R3: sendrecvbit + // R3: sendRecvBit // R4: tREC - // R5: *inPortReg + // R5: *inReg // R6: Scratch - // R7: outPortReg - // R8: inPortReg + // R7: outReg + // R8: inReg // R14: Scratch recovery_delay: @@ -186,7 +196,7 @@ bl ow_usdelay // Delay for tREC // Parse received bit - // *sendrecvbit = ((*inPortReg & pinMask) == pinMask) + // *sendRecvBit = ((*inReg & pinMask) == pinMask) and R5, R5, R1 cmp R5, R1 ite eq
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Wed Apr 03 12:33:10 2019 +0000
@@ -31,17 +31,25 @@
**********************************************************************/
// ow_usdelay configuration
-#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz
-#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
-// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results
+//
+// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP
+// for best results
+//
+// Processor clock in MHz
+#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000)
+//
+// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
+#define OVERHEAD_TUNING 18
+//
+// ARM specifies 1-3 cycles for pipeline refill following a branch
+#define PIPELINE_REFILL_PROC_CYCLES 1
// ow_usdelay constants
-#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch
#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
-#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay
+#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP)
#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
-// OwTiming offsets
+// OneWireTiming offsets
#define tRSTL_OFFSET 0
#define tMSP_OFFSET 2
#define tW0L_OFFSET 4
@@ -66,21 +74,23 @@
ow_usdelay_return
bx R14
-// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask)
+// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask)
write_ow_gpio_low MACRO
ldr R2, [R0]
bic R2, R2, R1
str R2, [R0]
ENDM
-// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask)
+// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask)
write_ow_gpio_high MACRO
ldr R2, [R0]
orr R2, R2, R1
str R2, [R0]
ENDM
-// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing)
+// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg,
+// volatile uint32_t * outReg, unsigned int pinMask,
+// const OneWireTiming * timing)
EXPORT ow_bit
ow_bit
push {R4-R8, R14}
@@ -89,9 +99,9 @@
ldr R6, [R6] // Load timing struct
ldrh R4, [R6, #tSLOT_OFFSET]
ldrh R5, [R6, #tMSR_OFFSET]
- // R0: sendrecvbit
- // R1: inPortReg
- // R2: outPortReg
+ // R0: sendRecvBit
+ // R1: inReg
+ // R2: outReg
// R3: pinMask
// R4: tSLOT
// R5: tMSR
@@ -101,22 +111,22 @@
// R14: Scratch
// Reorganize registers for upcoming function calls
- mov R8, R1 // inPortReg to R8
- mov R7, R2 // outPortReg to R7
+ mov R8, R1 // inReg to R8
+ mov R7, R2 // outReg to R7
mov R1, R3 // pinMask to R1
- mov R3, R0 // sendrecvbit to R3
+ mov R3, R0 // sendRecvBit to R3
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tSLOT
// R5: tMSR
// R6: timing
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- // if (*sendrecvbit & 1)
+ // if (*sendRecvBit & 1)
ldrb R14, [R3]
tst R14, #1
beq write_zero
@@ -126,22 +136,22 @@
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
// R5: delay2
// R6: tW1L
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_low // Pull low
mov R0, R6 // tLOW
bl ow_usdelay // Delay for tLOW
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_high // Release pin
mov R0, R5 // delay2
bl ow_usdelay // Delay for sample time
- ldr R5, [R8] // Read *inPortReg
+ ldr R5, [R8] // Read *inReg
b recovery_delay
// else
write_zero
@@ -151,32 +161,32 @@
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
// R5: tMSR
// R6: delay2
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_low // Pull low
mov R0, R5 // tMSR
bl ow_usdelay // Delay for tMSR
- ldr R5, [R8] // Read *inPortReg
+ ldr R5, [R8] // Read *inReg
mov R0, R6 // delay2
bl ow_usdelay // Delay for release
- mov R0, R7 // outPortReg
+ mov R0, R7 // outReg
write_ow_gpio_high // Release pin
- // endif (*sendrecvbit & 1)
+ // endif (*sendRecvBit & 1)
// R0: Scratch
// R1: pinMask
// R2: Scratch
- // R3: sendrecvbit
+ // R3: sendRecvBit
// R4: tREC
- // R5: *inPortReg
+ // R5: *inReg
// R6: Scratch
- // R7: outPortReg
- // R8: inPortReg
+ // R7: outReg
+ // R8: inReg
// R14: Scratch
recovery_delay
@@ -184,7 +194,7 @@
bl ow_usdelay // Delay for tREC
// Parse received bit
- // *sendrecvbit = ((*inPortReg & pinMask) == pinMask)
+ // *sendRecvBit = ((*inReg & pinMask) == pinMask)
and R5, R5, R1
cmp R5, R1
ite eq
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Tue Jul 24 08:33:31 2018 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Wed Apr 03 12:33:10 2019 +0000
@@ -39,8 +39,7 @@
extern "C" {
#endif
-/// Timing parameters for the 1-Wire bus.
-/// @note All times are in terms of microseconds.
+/// Timing parameters for the 1-Wire bus in microseconds.
struct OneWireTiming {
uint16_t tRSTL; ///< Reset Low Time
uint16_t tMSP; ///< Presence-Detect Sample Time
@@ -53,16 +52,17 @@
/// Delay for the specified number of microseconds.
void ow_usdelay(unsigned int time_us);
-/// Send and receive one bit of communication and set a new level on the 1-Wire bus.
+/// @brief Send and receive one bit, and set a new level on the 1-Wire bus.
/// @note GPIO pin must be configured for open drain operation.
-/// @param[in,out] sendRecvBit Buffer containing the bit to send on 1-Wire bus in lsb.
-/// Read data from 1-Wire bus will be returned in lsb.
-/// @param inReg Input register for GPIO pin.
-/// @param outReg Output register for GPIO pin.
+/// @param[in,out] sendRecvBit
+/// Buffer containing the bit to send on 1-Wire bus in lsb.
+/// Read data from 1-Wire bus will be returned in lsb.
+/// @param[in] inReg Input register for GPIO pin.
+/// @param[in,out] outReg Output register for GPIO pin.
/// @param pinMask Pin mask for input and output registers.
/// @param[in] timing 1-Wire timing parameters to use.
-void ow_bit(uint8_t * sendRecvBit, volatile uint32_t * inReg,
- volatile uint32_t * outPortReg, unsigned int pinMask,
+void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg,
+ volatile uint32_t * outReg, unsigned int pinMask,
const OneWireTiming * timing);
#ifdef __cplusplus
--- a/Platforms/mbed/Uart.cpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Platforms/mbed/Uart.cpp Wed Apr 03 12:33:10 2019 +0000 @@ -103,4 +103,4 @@ } } // namespace mbed -} // namespace MaximInterface \ No newline at end of file +} // namespace MaximInterface
--- a/Platforms/mxc/.mbedignore Tue Jul 24 08:33:31 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -* \ No newline at end of file
--- a/Platforms/mxc/Error.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <MaximInterface/Links/I2CMaster.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include <mxc_errors.h>
-#include "Error.hpp"
-
-namespace MaximInterface {
-namespace mxc {
-
-const error_category & errorCategory() {
- static class : public error_category {
- public:
- virtual const char * name() const { return "mxc"; }
-
- virtual std::string message(int condition) const {
- return defaultErrorMessage(condition);
- }
-
- // Make E_COMM_ERR equivalent to I2CMaster::NackError.
- virtual bool equivalent(int code, const error_condition & condition) const {
- return (code == E_COMM_ERR)
- ? (condition == make_error_condition(I2CMaster::NackError))
- : error_category::equivalent(code, condition);
- }
- } instance;
- return instance;
-}
-
-} // namespace mxc
-} // namespace MaximInterface
--- a/Platforms/mxc/Error.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-/// @file Common functionality for mapping mxc return codes to
-/// MaximInterface::error_code.
-
-#ifndef MaximInterface_mxc_Error
-#define MaximInterface_mxc_Error
-
-#include <MaximInterface/Utilities/system_error.hpp>
-
-namespace MaximInterface {
-namespace mxc {
-
-const error_category & errorCategory();
-
-inline error_code makeErrorCode(int mxcResult) {
- return error_code(mxcResult, errorCategory());
-}
-
-} // namespace mxc
-} // namespace MaximInterface
-
-#endif
--- a/Platforms/mxc/I2CMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include <mxc_device.h>
-#include "Error.hpp"
-#include "I2CMaster.hpp"
-
-namespace MaximInterface {
-namespace mxc {
-
-static void verifyTransactionStarted(mxc_i2cm_regs_t & i2cm) {
- if (!(i2cm.trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
- i2cm.trans |= MXC_F_I2CM_TRANS_TX_START;
- }
-}
-
-error_code I2CMaster::initialize(const sys_cfg_i2cm_t & sysCfg,
- i2cm_speed_t speed) {
- return makeErrorCode(I2CM_Init(i2cm, &sysCfg, speed));
-}
-
-error_code I2CMaster::shutdown() { return makeErrorCode(I2CM_Shutdown(i2cm)); }
-
-error_code I2CMaster::writeByte(uint_least8_t data, bool start) {
- const uint16_t fifoData =
- static_cast<uint16_t>(data & 0xFF) |
- (start ? MXC_S_I2CM_TRANS_TAG_START : MXC_S_I2CM_TRANS_TAG_TXDATA_ACK);
- const error_code result =
- makeErrorCode(I2CM_WriteTxFifo(i2cm, i2cmFifo, fifoData));
- if (result) {
- I2CM_Recover(i2cm);
- } else {
- verifyTransactionStarted(*i2cm);
- }
- return result;
-}
-
-error_code I2CMaster::start(uint_least8_t address) {
- return writeByte(address, true);
-}
-
-error_code I2CMaster::stop() {
- error_code result = makeErrorCode(
- I2CM_WriteTxFifo(i2cm, i2cmFifo, MXC_S_I2CM_TRANS_TAG_STOP));
- if (!result) {
- result = makeErrorCode(I2CM_TxInProgress(i2cm));
- }
- return result;
-}
-
-error_code I2CMaster::writeByte(uint_least8_t data) {
- return writeByte(data, false);
-}
-
-error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) {
- uint16_t fifoData = (status == Nack) ? MXC_S_I2CM_TRANS_TAG_RXDATA_NACK
- : MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT;
- error_code result = makeErrorCode(I2CM_WriteTxFifo(i2cm, i2cmFifo, fifoData));
- if (!result) {
- verifyTransactionStarted(*i2cm);
- do {
- int timeout = 0x5000;
- while ((i2cm->bb & MXC_F_I2CM_BB_RX_FIFO_CNT) == 0) {
- if ((--timeout <= 0) || (i2cm->trans & MXC_F_I2CM_TRANS_TX_TIMEOUT)) {
- result = makeErrorCode(E_TIME_OUT);
- goto exit;
- }
- if (i2cm->trans &
- (MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED)) {
- result = make_error_code(NackError);
- goto exit;
- }
- }
- fifoData = i2cmFifo->rx;
- } while (fifoData & MXC_S_I2CM_RSTLS_TAG_EMPTY);
- data = fifoData & 0xFF;
- }
-
-exit:
- if (result) {
- I2CM_Recover(i2cm);
- }
- return result;
-}
-
-} // namespace mxc
-} // namespace MaximInterface
--- a/Platforms/mxc/I2CMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_mxc_I2CMaster
-#define MaximInterface_mxc_I2CMaster
-
-#include <MaximInterface/Links/I2CMaster.hpp>
-#include <i2cm.h>
-
-namespace MaximInterface {
-namespace mxc {
-
-class I2CMaster : public MaximInterface::I2CMaster {
-public:
- I2CMaster(mxc_i2cm_regs_t & i2cm, mxc_i2cm_fifo_regs_t & i2cmFifo)
- : i2cm(&i2cm), i2cmFifo(&i2cmFifo) {}
-
- void set_mxc_i2cm(mxc_i2cm_regs_t & i2cm, mxc_i2cm_fifo_regs_t & i2cmFifo) {
- this->i2cm = &i2cm;
- this->i2cmFifo = &i2cmFifo;
- }
-
- /// Initialize the hardware interface for use.
- error_code initialize(const sys_cfg_i2cm_t & sysCfg, i2cm_speed_t speed);
-
- /// Shutdown the hardware interface after use.
- error_code shutdown();
-
- virtual error_code start(uint_least8_t address);
- virtual error_code stop();
- virtual error_code writeByte(uint_least8_t data);
- virtual error_code readByte(AckStatus status, uint_least8_t & data);
-
-private:
- error_code writeByte(uint_least8_t data, bool start);
-
- mxc_i2cm_regs_t * i2cm;
- mxc_i2cm_fifo_regs_t * i2cmFifo;
-};
-
-} // namespace mxc
-} // namespace MaximInterface
-
-#endif
--- a/Platforms/mxc/OneWireMaster.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include "Error.hpp"
-#include "OneWireMaster.hpp"
-
-namespace MaximInterface {
-namespace mxc {
-
-error_code OneWireMaster::initialize(const owm_cfg_t & owmCfg,
- const sys_cfg_owm_t & sysCfgOwm) {
- extStrongPup = (owmCfg.ext_pu_mode != OWM_EXT_PU_UNUSED);
- return makeErrorCode(OWM_Init(owm, &owmCfg, &sysCfgOwm));
-}
-
-error_code OneWireMaster::shutdown() {
- return makeErrorCode(OWM_Shutdown(owm));
-}
-
-error_code OneWireMaster::reset() {
- return OWM_Reset(owm) ? error_code() : make_error_code(NoSlaveError);
-}
-
-error_code OneWireMaster::touchBitSetLevel(bool & sendRecvBit,
- Level afterLevel) {
- sendRecvBit = OWM_TouchBit(owm, sendRecvBit);
- return setLevel(afterLevel);
-}
-
-error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
- Level afterLevel) {
- error_code result = makeErrorCode(OWM_WriteByte(owm, sendByte));
- if (!result) {
- result = setLevel(afterLevel);
- }
- return result;
-}
-
-error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
- Level afterLevel) {
- recvByte = OWM_ReadByte(owm);
- return setLevel(afterLevel);
-}
-
-error_code OneWireMaster::setSpeed(Speed newSpeed) {
- error_code result;
- if (newSpeed == OverdriveSpeed) {
- OWM_SetOverdrive(owm, 1);
- } else if (newSpeed == StandardSpeed) {
- OWM_SetOverdrive(owm, 0);
- } else {
- result = make_error_code(InvalidSpeedError);
- }
- return result;
-}
-
-error_code OneWireMaster::setLevel(Level newLevel) {
- error_code result;
- if (extStrongPup) {
- if (newLevel == StrongLevel) {
- OWM_SetExtPullup(owm, 1);
- } else if (newLevel == NormalLevel) {
- OWM_SetExtPullup(owm, 0);
- } else {
- result = make_error_code(InvalidLevelError);
- }
- } else if (newLevel != NormalLevel) {
- result = make_error_code(InvalidLevelError);
- }
- return result;
-}
-
-} // namespace mxc
-} // namespace MaximInterface
--- a/Platforms/mxc/OneWireMaster.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_mxc_OneWireMaster
-#define MaximInterface_mxc_OneWireMaster
-
-#include <MaximInterface/Links/OneWireMaster.hpp>
-#include <owm.h>
-
-namespace MaximInterface {
-namespace mxc {
-
-/// MCU peripheral 1-Wire master (OWM)
-class OneWireMaster : public MaximInterface::OneWireMaster {
-public:
- explicit OneWireMaster(mxc_owm_regs_t & owm)
- : owm(&owm), extStrongPup(false) {}
-
- void set_mxc_owm(mxc_owm_regs_t & owm) { this->owm = &owm; }
-
- /// Initialize the hardware interface for use.
- error_code initialize(const owm_cfg_t & owmCfg,
- const sys_cfg_owm_t & sysCfgOwm);
-
- /// Shutdown the hardware interface after use.
- error_code shutdown();
-
- virtual error_code reset();
- virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
- virtual error_code writeByteSetLevel(uint_least8_t sendByte,
- Level afterLevel);
- virtual error_code readByteSetLevel(uint_least8_t & recvByte,
- Level afterLevel);
- virtual error_code setSpeed(Speed newSpeed);
- virtual error_code setLevel(Level newLevel);
-
-private:
- mxc_owm_regs_t * owm;
- bool extStrongPup;
-};
-
-} // namespace mxc
-} // namespace MaximInterface
-
-#endif /* MaximInterface_mxc_OneWireMaster */
--- a/Platforms/mxc/Sleep.cpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#include "Sleep.hpp"
-
-namespace MaximInterface {
-namespace mxc {
-
-void Sleep::operator()(int ms) const {
- if (ms > 0) {
- TMR_Delay(tmr, MSEC(static_cast<unsigned long>(ms)));
- }
-}
-
-} // namespace mxc
-} // namespace MaximInterface
--- a/Platforms/mxc/Sleep.hpp Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-
-#ifndef MaximInterface_mxc_Sleep
-#define MaximInterface_mxc_Sleep
-
-#include <MaximInterface/Links/Sleep.hpp>
-#include <tmr_utils.h>
-
-namespace MaximInterface {
-namespace mxc {
-
-class Sleep : public MaximInterface::Sleep {
-public:
- explicit Sleep(mxc_tmr_regs_t & tmr) : tmr(&tmr) {}
-
- void set_mxc_tmr(mxc_tmr_regs_t & tmr) { this->tmr = &tmr; }
-
- virtual void operator()(int ms) const;
-
-private:
- mxc_tmr_regs_t * tmr;
-};
-
-} // namespace mxc
-} // namespace MaximInterface
-
-#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utilities/Algorithm.hpp Wed Apr 03 12:33:10 2019 +0000 @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterface_Algorithm +#define MaximInterface_Algorithm + +/// Alternative to std::max when a constant expression is required. +#define MaximInterface_MAX(a, b) ((a) < (b) ? (b) : (a)) + +/// Alternative to std::min when a constant expression is required. +#define MaximInterface_MIN(a, b) ((b) < (a) ? (b) : (a)) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/ChangeSizeType.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,77 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_ChangeSizeType
+#define MaximInterface_ChangeSizeType
+
+#include <stdint.h>
+#include <algorithm>
+#include <limits>
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterface {
+
+/// @brief
+/// Adapts functions taking an array pointer and size where the size type is
+/// nonstandard.
+/// @tparam NewSize Nonstandard size type.
+/// @tparam Func Must be callable as func(Data *, NewSize).
+/// @tparam Data Array element type.
+/// @param func Callback for processing chunks of data.
+/// @param data Data to process with callback.
+template <typename NewSize, typename Func, typename Data>
+error_code changeSizeType(Func func, span<Data> data) {
+ using namespace std;
+ typedef typename span<Data>::index_type DataSize;
+
+ error_code result;
+ // Check if NewSize can represent the maximum value of DataSize.
+ if (static_cast<uintmax_t>(numeric_limits<DataSize>::max()) >
+ static_cast<uintmax_t>(numeric_limits<NewSize>::max())) {
+ DataSize dataIdx = 0;
+ do {
+ const span<Data> chunk =
+ data.subspan(dataIdx, min<DataSize>(data.size() - dataIdx,
+ numeric_limits<NewSize>::max()));
+ result = func(chunk.data(), static_cast<NewSize>(chunk.size()));
+ dataIdx += chunk.size();
+ } while (dataIdx < data.size() && !result);
+ } else {
+ result = func(data.data(), static_cast<NewSize>(data.size()));
+ }
+ return result;
+}
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- a/Utilities/Ecc256.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Ecc256.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -30,24 +30,32 @@
* ownership rights.
*******************************************************************************/
-#include <algorithm>
#include "Ecc256.hpp"
namespace MaximInterface {
namespace Ecc256 {
-CertificateData createCertificateData(const PublicKey & publicKey,
- const RomId & romId,
- const ManId & manId) {
- using std::copy;
+void copy(Point::const_span src, Point::span dst) {
+ copy(src.x, dst.x);
+ copy(src.y, dst.y);
+}
+
+void copy(KeyPair::const_span src, KeyPair::span dst) {
+ copy(src.privateKey, dst.privateKey);
+ copy(src.publicKey, dst.publicKey);
+}
- CertificateData data;
- CertificateData::iterator dataIt = data.begin();
- dataIt = copy(publicKey.x.begin(), publicKey.x.end(), dataIt);
- dataIt = copy(publicKey.y.begin(), publicKey.y.end(), dataIt);
- dataIt = copy(romId.begin(), romId.end(), dataIt);
- copy(manId.begin(), manId.end(), dataIt);
- return data;
+void copy(Signature::const_span src, Signature::span dst) {
+ copy(src.r, dst.r);
+ copy(src.s, dst.s);
+}
+
+PublicKey::span CertificateData::publicKey() {
+ const PublicKey::span span = {
+ make_span(result_).subspan<publicKeyIdx, Scalar::size>(),
+ make_span(result_)
+ .subspan<publicKeyIdx + Scalar::size, Scalar::size>()};
+ return span;
}
} // namespace Ecc256
--- a/Utilities/Ecc256.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Ecc256.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -34,7 +34,7 @@
#define MaximInterface_Ecc256
#include <stdint.h>
-#include "array.hpp"
+#include "array_span.hpp"
#include "Export.h"
#include "ManId.hpp"
#include "RomId.hpp"
@@ -42,41 +42,206 @@
namespace MaximInterface {
namespace Ecc256 {
-typedef array<uint_least8_t, 32> Scalar;
+typedef array_span<uint_least8_t, 32> Scalar;
+
struct Point {
- /// Total size of all elements in bytes.
- static const size_t size = 2 * Scalar::csize;
+ struct const_span {
+ Scalar::const_span x;
+ Scalar::const_span y;
+ };
+
+ struct span {
+ Scalar::span x;
+ Scalar::span y;
+
+ operator const_span() const {
+ const const_span sp = {x, y};
+ return sp;
+ }
+ };
+
+ struct array {
+ Scalar::array x;
+ Scalar::array y;
+
+ operator span() {
+ const span sp = {x, y};
+ return sp;
+ }
+
+ operator const_span() const {
+ const const_span sp = {x, y};
+ return sp;
+ }
+ };
- Scalar x;
- Scalar y;
+private:
+ Point(); // deleted
};
+MaximInterface_EXPORT void copy(Point::const_span src, Point::span dst);
+
typedef Scalar PrivateKey;
typedef Point PublicKey;
+
struct KeyPair {
- /// Total size of all elements in bytes.
- static const size_t size = PrivateKey::csize + PublicKey::size;
+ struct const_span {
+ PrivateKey::const_span privateKey;
+ PublicKey::const_span publicKey;
+ };
+
+ struct span {
+ PrivateKey::span privateKey;
+ PublicKey::span publicKey;
+
+ operator const_span() const {
+ const const_span sp = {privateKey, publicKey};
+ return sp;
+ }
+ };
+
+ struct array {
+ PrivateKey::array privateKey;
+ PublicKey::array publicKey;
+
+ operator span() {
+ const span sp = {privateKey, publicKey};
+ return sp;
+ }
+
+ operator const_span() const {
+ const const_span sp = {privateKey, publicKey};
+ return sp;
+ }
+ };
- PrivateKey privateKey;
- PublicKey publicKey;
+private:
+ KeyPair(); // deleted
};
+MaximInterface_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst);
+
struct Signature {
- /// Total size of all elements in bytes.
- static const size_t size = 2 * Scalar::csize;
+ struct const_span {
+ Scalar::const_span r;
+ Scalar::const_span s;
+ };
+
+ struct span {
+ Scalar::span r;
+ Scalar::span s;
+
+ operator const_span() const {
+ const const_span sp = {r, s};
+ return sp;
+ }
+ };
+
+ struct array {
+ Scalar::array r;
+ Scalar::array s;
+
+ operator span() {
+ const span sp = {r, s};
+ return sp;
+ }
+
+ operator const_span() const {
+ const const_span sp = {r, s};
+ return sp;
+ }
+ };
- Scalar r;
- Scalar s;
+private:
+ Signature(); // deleted
};
+MaximInterface_EXPORT void copy(Signature::const_span src, Signature::span dst);
+
/// Data used to create a device key certificate for ECC-256 authenticators.
-typedef array<uint_least8_t, 2 * Scalar::csize + RomId::csize + ManId::csize>
- CertificateData;
+class CertificateData {
+public:
+ typedef array_span<uint_least8_t, 2 * Scalar::size + RomId::size + ManId::size>
+ Result;
+
+ CertificateData() : result_() {}
+
+ /// Formatted data result.
+ Result::const_span result() const { return result_; }
+
+ /// @name Public Key
+ /// @brief Public key of the device.
+ /// @{
+
+ /// Get mutable Public Key.
+ MaximInterface_EXPORT PublicKey::span publicKey();
+
+ /// Get immutable Public Key.
+ PublicKey::const_span publicKey() const {
+ return const_cast<CertificateData &>(*this).publicKey();
+ }
+
+ /// Set Public Key.
+ CertificateData & setPublicKey(PublicKey::const_span publicKey) {
+ copy(publicKey, this->publicKey());
+ return *this;
+ }
+
+ /// @}
-/// Formats data for creating a device key certificate from the public key,
-/// ROM ID, and MAN ID.
-MaximInterface_EXPORT CertificateData createCertificateData(
- const PublicKey & publicKey, const RomId & romId, const ManId & manId);
+ /// @name ROM ID
+ /// @brief 1-Wire ROM ID of the device.
+ /// @{
+
+ /// Get mutable ROM ID.
+ RomId::span romId() {
+ return make_span(result_).subspan<romIdIdx, RomId::size>();
+ }
+
+ /// Get immutable ROM ID.
+ RomId::const_span romId() const {
+ return const_cast<CertificateData &>(*this).romId();
+ }
+
+ /// Set ROM ID.
+ CertificateData & setRomId(RomId::const_span romId) {
+ copy(romId, this->romId());
+ return *this;
+ }
+
+ /// @}
+
+ /// @name MAN ID
+ /// @brief Manufacturer ID of the device.
+ /// @{
+
+ /// Get mutable MAN ID.
+ ManId::span manId() {
+ return make_span(result_).subspan<manIdIdx, ManId::size>();
+ }
+
+ /// Get immutable MAN ID.
+ ManId::const_span manId() const {
+ return const_cast<CertificateData &>(*this).manId();
+ }
+
+ /// Set MAN ID.
+ CertificateData & setManId(ManId::const_span manId) {
+ copy(manId, this->manId());
+ return *this;
+ }
+
+ /// @}
+
+private:
+ typedef Result::span::index_type index;
+
+ static const index publicKeyIdx = 0;
+ static const index romIdIdx = publicKeyIdx + 2 * Scalar::size;
+ static const index manIdIdx = romIdIdx + RomId::size;
+
+ Result::array result_;
+};
} // namespace Ecc256
} // namespace MaximInterface
--- a/Utilities/Error.cpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Utilities/Error.cpp Wed Apr 03 12:33:10 2019 +0000 @@ -38,4 +38,4 @@ return (condition == 0) ? "Success" : "Unknown Error"; } -} // namespace MaximInterface \ No newline at end of file +} // namespace MaximInterface
--- a/Utilities/Error.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Error.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -37,10 +37,10 @@
namespace MaximInterface {
-/// Get the default error message associated with a condition. Typically used
-/// by an error_category when the condition is unknown.
+/// @brief Get the default error message associated with a condition.
+/// @details Typically used by an error_category when the condition is unknown.
MaximInterface_EXPORT const char * defaultErrorMessage(int condition);
}
-#endif
\ No newline at end of file
+#endif
--- a/Utilities/Export.h Tue Jul 24 08:33:31 2018 +0000 +++ b/Utilities/Export.h Wed Apr 03 12:33:10 2019 +0000 @@ -31,13 +31,9 @@ *******************************************************************************/ #ifndef MaximInterface_EXPORT - #ifdef _MSC_VER - #ifdef _DLL - #define MaximInterface_EXPORT __declspec(dllexport) - #else - #define MaximInterface_EXPORT __declspec(dllimport) - #endif /* _DLL */ - #else - #define MaximInterface_EXPORT - #endif /* _MSC_VER */ -#endif /* MaximInterface_EXPORT */ \ No newline at end of file + #if defined(_MSC_VER) && defined(MaximInterface_EXPORTING) + #define MaximInterface_EXPORT __declspec(dllexport) + #else + #define MaximInterface_EXPORT + #endif +#endif
--- a/Utilities/FlagSet.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/FlagSet.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -38,6 +38,7 @@
namespace MaximInterface {
+/// @brief
/// Provides functionality similar to std::bitset except using a bit flag,
/// typically of an enum type, as the indexer.
template <typename Flag, size_t flagBits> class FlagSet {
@@ -45,15 +46,20 @@
class reference {
public:
reference(FlagSet & flagSet, Flag flag) : flagSet(&flagSet), flag(flag) {}
+
reference & operator=(bool x) {
flagSet->set(flag, x);
return *this;
}
+
reference & operator=(const reference & x) {
return operator=(static_cast<bool>(x));
}
+
operator bool() const { return flagSet->test(flag); }
+
bool operator~() const { return reference(*this).flip(); }
+
reference & flip() {
*this = !*this;
return *this;
@@ -65,6 +71,7 @@
};
FlagSet() : bits() {}
+
FlagSet(unsigned long val) : bits(val) {}
template <typename CharT, typename Traits, typename Alloc>
@@ -76,38 +83,58 @@
: bits(str, pos, n) {}
bool operator==(const FlagSet & rhs) const { return bits == rhs.bits; }
+
bool operator!=(const FlagSet & rhs) const { return !operator==(rhs); }
- // Element access
+ /// @name Element access
+ /// @{
+
bool operator[](Flag flag) const { return test(flag); }
+
reference operator[](Flag flag) { return reference(*this, flag); }
+
bool test(Flag flag) const { return (bits.to_ulong() & flag) == flag; }
+
bool any() const { return bits.any(); }
+
bool none() const { return bits.none(); }
+
size_t count() const { return bits.count(); }
+
+ /// @}
- // Capacity
+ /// @name Capacity
+ /// @{
+
size_t size() const { return bits.size(); }
+
+ /// @}
- // Modifiers
+ /// @name Modifiers
+ /// @{
+
FlagSet & operator&=(const FlagSet & other) {
bits &= other.bits;
return *this;
}
+
FlagSet & operator|=(const FlagSet & other) {
bits |= other.bits;
return *this;
}
+
FlagSet & operator^=(const FlagSet & other) {
bits ^= other.bits;
return *this;
}
+
FlagSet operator~() const { return ~bits; }
FlagSet & set() {
bits.set();
return *this;
}
+
FlagSet & set(Flag flag, bool value = true) {
if (value) {
bits |= flag;
@@ -116,26 +143,37 @@
}
return *this;
}
+
FlagSet & reset() {
bits.reset();
return *this;
}
+
FlagSet & reset(Flag flag) { return set(flag, false); }
+
FlagSet & flip() {
bits.flip();
return *this;
}
+
FlagSet & flip(Flag flag) {
bits ^= flag;
return *this;
}
+
+ /// @}
- // Conversions
+ /// @name Conversions
+ /// @{
+
template <typename CharT, typename Traits, typename Allocator>
std::basic_string<CharT, Traits, Allocator> to_string() const {
return bits.template to_string<CharT, Traits, Allocator>();
}
+
unsigned long to_ulong() const { return bits.to_ulong(); }
+
+ /// @}
private:
std::bitset<flagBits> bits;
@@ -185,4 +223,4 @@
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Utilities/Function.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Function.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -34,6 +34,7 @@
#define MaximInterface_Function
#include <stddef.h>
+#include "SafeBool.hpp"
#include "type_traits.hpp"
// Include for std::swap.
@@ -70,7 +71,9 @@
private:
char data[TypeSize];
- long double aligner;
+ long double aligner1;
+ long int aligner2;
+ void * aligner3;
};
// Computes the internal target size for TypeStorage based on a desired total
@@ -80,7 +83,9 @@
template <typename Target, size_t totalSize> class TypeWrapperTotalSize {
private:
typedef TypeStorage<Target, 1> MinSizeStorage;
+
static const size_t otherDataSize = sizeof(Target *);
+
// Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value.
static const size_t internalTargetRawSize =
(totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value *
@@ -235,7 +240,7 @@
} // namespace detail
-// Function wrapper similar to std::function for 0-2 argument functions.
+// Function wrapper similar to std::function for 0-3 argument functions.
template <typename> class Function;
// Function implementation for zero argument functions.
@@ -267,10 +272,12 @@
void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
- operator bool() const { return callableWrapper.target() != NULL; }
+ operator SafeBool() const {
+ return makeSafeBool(callableWrapper.target() != NULL);
+ }
ResultType operator()() const {
- return callableWrapper.target() ? (*callableWrapper.target())()
+ return callableWrapper.target() ? callableWrapper.target()->invoke()
: ResultType();
}
@@ -278,7 +285,7 @@
class Callable {
public:
virtual ~Callable() {}
- virtual ResultType operator()() const = 0;
+ virtual ResultType invoke() const = 0;
virtual Callable * clone() const = 0;
virtual void clone(void * buffer) const = 0;
};
@@ -287,7 +294,7 @@
public:
CallableAdapter(F func) : func(func) {}
- virtual ResultType operator()() const { return func(); }
+ virtual ResultType invoke() const { return func(); }
virtual Callable * clone() const { return new CallableAdapter(*this); }
@@ -338,10 +345,12 @@
void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
- operator bool() const { return callableWrapper.target() != NULL; }
+ operator SafeBool() const {
+ return makeSafeBool(callableWrapper.target() != NULL);
+ }
ResultType operator()(ArgumentType arg) const {
- return callableWrapper.target() ? (*callableWrapper.target())(arg)
+ return callableWrapper.target() ? callableWrapper.target()->invoke(arg)
: ResultType();
}
@@ -349,7 +358,7 @@
class Callable {
public:
virtual ~Callable() {}
- virtual ResultType operator()(ArgumentType) const = 0;
+ virtual ResultType invoke(ArgumentType) const = 0;
virtual Callable * clone() const = 0;
virtual void clone(void * buffer) const = 0;
};
@@ -358,7 +367,7 @@
public:
CallableAdapter(F func) : func(func) {}
- virtual ResultType operator()(ArgumentType arg) const { return func(arg); }
+ virtual ResultType invoke(ArgumentType arg) const { return func(arg); }
virtual Callable * clone() const { return new CallableAdapter(*this); }
@@ -414,19 +423,21 @@
void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
- operator bool() const { return callableWrapper.target() != NULL; }
+ operator SafeBool() const {
+ return makeSafeBool(callableWrapper.target() != NULL);
+ }
ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const {
- return callableWrapper.target() ? (*callableWrapper.target())(arg1, arg2)
- : ResultType();
+ return callableWrapper.target()
+ ? callableWrapper.target()->invoke(arg1, arg2)
+ : ResultType();
}
private:
class Callable {
public:
virtual ~Callable() {}
- virtual ResultType operator()(FirstArgumentType,
- SecondArgumentType) const = 0;
+ virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0;
virtual Callable * clone() const = 0;
virtual void clone(void * buffer) const = 0;
};
@@ -435,8 +446,8 @@
public:
CallableAdapter(F func) : func(func) {}
- virtual ResultType operator()(FirstArgumentType arg1,
- SecondArgumentType arg2) const {
+ virtual ResultType invoke(FirstArgumentType arg1,
+ SecondArgumentType arg2) const {
return func(arg1, arg2);
}
@@ -461,6 +472,94 @@
lhs.swap(rhs);
}
+// Function implementation for three argument functions.
+template <typename FirstArgumentType, typename SecondArgumentType,
+ typename ThirdArgumentType, typename ResultType>
+class Function<ResultType(FirstArgumentType, SecondArgumentType,
+ ThirdArgumentType)> {
+public:
+ typedef ResultType result_type;
+
+ Function(ResultType (*func)(FirstArgumentType, SecondArgumentType,
+ ThirdArgumentType) = NULL)
+ : callableWrapper() {
+ if (func) {
+ callableWrapper = func;
+ }
+ }
+
+ template <typename F> Function(F func) : callableWrapper(func) {}
+
+ const Function & operator=(ResultType (*func)(FirstArgumentType,
+ SecondArgumentType,
+ ThirdArgumentType)) {
+ if (func) {
+ callableWrapper = func;
+ } else {
+ callableWrapper.clear();
+ }
+ return *this;
+ }
+
+ template <typename F> const Function & operator=(F func) {
+ callableWrapper = func;
+ return *this;
+ }
+
+ void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
+
+ operator SafeBool() const {
+ return makeSafeBool(callableWrapper.target() != NULL);
+ }
+
+ ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2,
+ ThirdArgumentType arg3) const {
+ return callableWrapper.target()
+ ? callableWrapper.target()->invoke(arg1, arg2, arg3)
+ : ResultType();
+ }
+
+private:
+ class Callable {
+ public:
+ virtual ~Callable() {}
+ virtual ResultType invoke(FirstArgumentType, SecondArgumentType,
+ ThirdArgumentType) const = 0;
+ virtual Callable * clone() const = 0;
+ virtual void clone(void * buffer) const = 0;
+ };
+
+ template <typename F> class CallableAdapter : public Callable {
+ public:
+ CallableAdapter(F func) : func(func) {}
+
+ virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2,
+ ThirdArgumentType arg3) const {
+ return func(arg1, arg2, arg3);
+ }
+
+ virtual Callable * clone() const { return new CallableAdapter(*this); }
+
+ virtual void clone(void * buffer) const {
+ new (buffer) CallableAdapter(*this);
+ }
+
+ private:
+ F func;
+ };
+
+ detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
+};
+
+template <typename FirstArgumentType, typename SecondArgumentType,
+ typename ThirdArgumentType, typename ResultType>
+inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType,
+ ThirdArgumentType)> & lhs,
+ Function<ResultType(FirstArgumentType, SecondArgumentType,
+ ThirdArgumentType)> & rhs) {
+ lhs.swap(rhs);
+}
+
} // namespace MaximInterface
#endif
--- a/Utilities/HexConversions.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/HexConversions.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -30,31 +30,55 @@
* ownership rights.
*******************************************************************************/
+#include <cctype>
#include <cstdio>
+#include <cstdlib>
#include "HexConversions.hpp"
+using std::string;
+using std::vector;
+
namespace MaximInterface {
-static const unsigned int charsPerByte = 2;
+static const int charsPerByte = 2;
-std::string byteArrayToHexString(const uint_least8_t * byteArray,
- size_t byteArraySize) {
- std::string hexString;
- char hexBuf[charsPerByte + 1];
- for (size_t i = 0; i < byteArraySize; i++) {
+string byteArrayToHexString(span<const uint_least8_t> byteArray) {
+ string hexString;
+ hexString.reserve(byteArray.size() * charsPerByte);
+ for (span<const uint_least8_t>::index_type i = 0; i < byteArray.size(); ++i) {
+ char hexBuf[charsPerByte + 1];
std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF);
hexString.append(hexBuf, charsPerByte);
}
return hexString;
}
-std::vector<uint_least8_t> hexStringToByteArray(const std::string & hexString) {
- std::vector<uint_least8_t> byteArray;
- byteArray.reserve(hexString.size() / charsPerByte + 1);
- for (std::string::size_type i = 0; i < hexString.size(); i += charsPerByte) {
- unsigned int byte;
- std::sscanf(hexString.substr(i, charsPerByte).c_str(), "%2x", &byte);
- byteArray.push_back(byte);
+optional<vector<uint_least8_t> >
+hexStringToByteArray(const string & hexString) {
+ optional<vector<uint_least8_t> > byteArray = vector<uint_least8_t>();
+ byteArray->reserve(hexString.size() / charsPerByte);
+ char hexBuf[charsPerByte + 1];
+ char * const hexBufEnd = hexBuf + charsPerByte;
+ *hexBufEnd = '\0';
+ char * hexBufIt = hexBuf;
+ for (string::const_iterator hexStringIt = hexString.begin(),
+ hexStringEnd = hexString.end();
+ hexStringIt != hexStringEnd; ++hexStringIt) {
+ if (!std::isspace(*hexStringIt)) {
+ *hexBufIt = *hexStringIt;
+ if (++hexBufIt == hexBufEnd) {
+ char * hexBufParseEnd;
+ byteArray->push_back(static_cast<uint_least8_t>(
+ std::strtoul(hexBuf, &hexBufParseEnd, 16)));
+ if (hexBufParseEnd != hexBufEnd) {
+ break;
+ }
+ hexBufIt = hexBuf;
+ }
+ }
+ }
+ if (hexBufIt != hexBuf) {
+ byteArray.reset();
}
return byteArray;
}
--- a/Utilities/HexConversions.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/HexConversions.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -37,16 +37,18 @@
#include <stdint.h>
#include <string>
#include <vector>
-#include <MaximInterface/Utilities/Export.h>
+#include "Export.h"
+#include "optional.hpp"
+#include "span.hpp"
namespace MaximInterface {
/// Convert a byte array to a hex string.
MaximInterface_EXPORT std::string
-byteArrayToHexString(const uint_least8_t * byteArray, size_t byteArraySize);
+byteArrayToHexString(span<const uint_least8_t> byteArray);
/// Convert a hex string to a byte array.
-MaximInterface_EXPORT std::vector<uint_least8_t>
+MaximInterface_EXPORT optional<std::vector<uint_least8_t> >
hexStringToByteArray(const std::string & hexString);
} // namespace MaximInterface
--- a/Utilities/ManId.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/ManId.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -33,12 +33,12 @@
#ifndef MaximInterface_ManId
#define MaximInterface_ManId
-#include "array.hpp"
+#include "array_span.hpp"
namespace MaximInterface {
/// Standard container for a manufacturer ID.
-typedef array<uint_least8_t, 2> ManId;
+typedef array_span<uint_least8_t, 2> ManId;
} // namespace MaximInterface
--- a/Utilities/RomId.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/RomId.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -33,36 +33,48 @@
#ifndef MaximInterface_RomId
#define MaximInterface_RomId
-#include "array.hpp"
+#include "array_span.hpp"
#include "crc.hpp"
namespace MaximInterface {
/// Standard container for a 1-Wire ROM ID.
-typedef array<uint_least8_t, 8> RomId;
+typedef array_span<uint_least8_t, 8> RomId;
+/// @name Family Code
/// @{
-/// Access the Family Code byte.
-inline RomId::value_type familyCode(const RomId & romId) {
- return romId.front();
+
+/// Get the Family Code byte.
+inline RomId::element familyCode(RomId::const_span romId) {
+ return romId[0];
}
-inline void setFamilyCode(RomId & romId, RomId::value_type familyCode) {
- romId.front() = familyCode;
+
+/// Set the Family Code byte.
+inline void setFamilyCode(RomId::span romId, RomId::element familyCode) {
+ romId[0] = familyCode;
}
+
/// @}
+/// @name CRC8
/// @{
-/// Access the CRC8 byte.
-inline RomId::value_type crc8(const RomId & romId) { return romId.back(); }
-inline void setCrc8(RomId & romId, RomId::value_type crc8) {
- romId.back() = crc8;
+
+/// Get the CRC8 byte.
+inline RomId::element crc8(RomId::const_span romId) {
+ return *romId.last<1>().data();
}
+
+/// Set the CRC8 byte.
+inline void setCrc8(RomId::span romId, RomId::element crc8) {
+ *romId.last<1>().data() = crc8;
+}
+
/// @}
-/// Check if the ROM ID is valid (Family Code and CRC8 are both valid).
+/// @brief Check if the ROM ID is valid (Family Code and CRC8 are both valid).
/// @returns True if the ROM ID is valid.
-inline bool valid(const RomId & romId) {
- return calculateCrc8(romId.data(), romId.size() - 1) == crc8(romId);
+inline bool valid(RomId::const_span romId) {
+ return calculateCrc8(romId.first(romId.size() - 1)) == crc8(romId);
}
} // namespace MaximInterface
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/SafeBool.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_SafeBool
+#define MaximInterface_SafeBool
+
+#include <stddef.h>
+
+namespace MaximInterface {
+namespace detail {
+
+// Implement SafeBool as a member function pointer since some compilers allow
+// function pointer to void pointer conversion.
+struct SafeBoolHelper {
+ void trueValue() const {}
+
+private:
+ SafeBoolHelper(); // deleted
+};
+
+} // namespace detail
+
+/// @brief Type definition for SafeBool.
+/// @details
+/// SafeBool is a boolean type that eliminates many error-prone implicit
+/// conversions allowed by the fundamental bool type.
+/// @note
+/// SafeBool can be used to add an explicit bool conversion operator to a type.
+typedef void (detail::SafeBoolHelper::*SafeBool)() const;
+
+/// Constructor for SafeBool.
+inline SafeBool makeSafeBool(bool value) {
+ return value ? &detail::SafeBoolHelper::trueValue : NULL;
+}
+
+} // namespace MaximInterface
+
+#endif
--- a/Utilities/Segment.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Segment.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -39,8 +39,9 @@
namespace MaximInterface {
+/// @brief
/// Advances a given iterator by a given number of elements with bounds checking.
-/// InputIt must meet the requirements of InputIterator.
+/// @tparam InputIt Must meet the requirements of InputIterator.
/// @param[in,out] it Iterator to advance.
/// @param bound
/// Past-the-end boundary iterator. If distance is positive, bound must be
@@ -97,16 +98,19 @@
return distance;
}
-/// Locates an iterator sub-range using segment number addressing. Useful for
-/// devices that divide the memory space into uniform chunks such as pages and
-/// segments. ForwardIt must meet the requirements of ForwardIterator.
+/// @brief Locates an iterator sub-range using segment number addressing.
+/// @details
+/// Useful for devices that divide the memory space into uniform chunks such as
+/// pages and segments.
+/// @tparam ForwardIt Must meet the requirements of ForwardIterator.
/// @param begin Beginning of the input data range.
/// @param end End of the input data range.
/// @param segmentSize Number of elements contained in a segment.
/// @param segmentNum Zero-indexed number of the desired segment.
-/// @returns Pair of iterators representing the sub-range of the segment within
+/// @returns
+/// Pair of iterators representing the sub-range of the segment within
/// the input range. If the segment does not exist within the input range, both
-/// iterators in the pair are set to the end interator of the input range.
+/// iterators in the pair are set to the end iterator of the input range.
template <typename ForwardIt, typename Index>
std::pair<ForwardIt, ForwardIt> createSegment(
ForwardIt begin, const ForwardIt end,
--- a/Utilities/Sha256.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/Sha256.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -34,26 +34,24 @@
#define MaximInterface_Sha256
#include <stdint.h>
-#include "array.hpp"
+#include "array_span.hpp"
namespace MaximInterface {
namespace Sha256 {
/// Container for a SHA-256 hash.
-typedef array<uint_least8_t, 32> Hash;
-
-// Data used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465.
+typedef array_span<uint_least8_t, 32> Hash;
-/// Data for Compute Write MAC operation.
-typedef array<uint_least8_t, 20> WriteMacData;
+/// @brief Data for Compute Write MAC operation.
+/// @details
+/// Used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465.
+typedef array_span<uint_least8_t, 20> WriteMacData;
-/// Data for the Compute Auth. MAC operation.
-typedef array<uint_least8_t, 76>AuthMacData;
-
-/// Data for the Compute Slave Secret operation.
-typedef array<uint_least8_t, 76> SlaveSecretData;
+/// @brief Data for the Compute Auth. MAC and Compute Slave Secret operations.
+/// @copydetails WriteMacData
+typedef array_span<uint_least8_t, 76> AuthenticationData;
} // namespace Sha256
} // namespace MaximInterface
-#endif
\ No newline at end of file
+#endif
--- a/Utilities/Uncopyable.hpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Utilities/Uncopyable.hpp Wed Apr 03 12:33:10 2019 +0000 @@ -47,4 +47,4 @@ } // namespace MaximInterface -#endif \ No newline at end of file +#endif
--- a/Utilities/WriteMessage.hpp Tue Jul 24 08:33:31 2018 +0000 +++ b/Utilities/WriteMessage.hpp Wed Apr 03 12:33:10 2019 +0000 @@ -43,4 +43,4 @@ } -#endif \ No newline at end of file +#endif
--- a/Utilities/array.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/array.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -55,58 +55,98 @@
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- // Element access
+ /// @name Element access
+ /// @{
+
reference operator[](size_type pos) {
return const_cast<reference>(
static_cast<const array &>(*this).operator[](pos));
}
- const_reference operator[](size_type pos) const { return _buffer[pos]; }
+
+ const_reference operator[](size_type pos) const { return data()[pos]; }
+
reference front() {
return const_cast<reference>(static_cast<const array &>(*this).front());
}
- const_reference front() const { return _buffer[0]; }
+
+ const_reference front() const { return operator[](0); }
+
reference back() {
return const_cast<reference>(static_cast<const array &>(*this).back());
}
- const_reference back() const { return _buffer[size() - 1]; }
+
+ const_reference back() const { return operator[](size() - 1); }
+
pointer data() {
return const_cast<pointer>(static_cast<const array &>(*this).data());
}
+
const_pointer data() const { return _buffer; }
+
+ /// @}
- // Iterators
+ /// @name Iterators
+ /// @{
+
iterator begin() {
return const_cast<iterator>(static_cast<const array &>(*this).cbegin());
}
+
const_iterator begin() const { return cbegin(); }
- const_iterator cbegin() const { return _buffer; }
+
+ const_iterator cbegin() const { return data(); }
+
iterator end() {
return const_cast<iterator>(static_cast<const array &>(*this).cend());
}
+
const_iterator end() const { return cend(); }
- const_iterator cend() const { return _buffer + size(); }
+
+ const_iterator cend() const { return cbegin() + size(); }
+
reverse_iterator rbegin() { return reverse_iterator(end()); }
+
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
+
const_reverse_iterator crbegin() const { return rbegin(); }
+
reverse_iterator rend() { return reverse_iterator(begin()); }
+
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
+
const_reverse_iterator crend() const { return rend(); }
+
+ /// @}
- // Capacity
+ /// @name Capacity
+ /// @{
+
static bool empty() { return size() == 0; }
+
static size_type size() { return N; }
+
static size_type max_size() { return size(); }
- static const size_type csize =
- N; ///< Alternative to size() when a constant expression is required.
+
+ /// Alternative to size() when a constant expression is required.
+ static const size_type csize = N;
+
+ /// @}
- // Operations
+ /// @name Operations
+ /// @{
+
void fill(const_reference value) { std::fill(begin(), end(), value); }
+
void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); }
+
+ /// @}
+ /// @private
+ /// @note Implementation detail set public to allow aggregate initialization.
T _buffer[N];
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/array_span.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,63 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_array_span
+#define MaximInterface_array_span
+
+#include "array.hpp"
+#include "span.hpp"
+#include "type_traits.hpp"
+
+namespace MaximInterface {
+
+/// @brief
+/// Defines a standard set of types for data fields that are represented as a
+/// fixed-size array of elements.
+/// @tparam T A const qualifier is not allowed.
+template <typename T, size_t N> struct array_span {
+ typedef typename remove_volatile<T>::type element;
+ static const size_t size = N;
+
+ typedef MaximInterface::array<element, N> array;
+ typedef MaximInterface::span<const T, N> const_span;
+ typedef MaximInterface::span<T, N> span;
+
+private:
+ array_span(); // deleted
+};
+
+// Specialization for "const T" is not defined.
+template <typename T, size_t N> struct array_span<const T, N>;
+
+}
+
+#endif
--- a/Utilities/crc.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/crc.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -48,9 +48,8 @@
return crc;
}
-uint_fast8_t calculateCrc8(const uint_least8_t * data, size_t dataLen,
- uint_fast8_t crc) {
- for (size_t i = 0; i < dataLen; i++) {
+uint_fast8_t calculateCrc8(span<const uint_least8_t> data, uint_fast8_t crc) {
+ for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
crc = calculateCrc8(data[i], crc);
}
return crc;
@@ -75,9 +74,9 @@
return crc;
}
-uint_fast16_t calculateCrc16(const uint_least8_t * data, size_t dataLen,
+uint_fast16_t calculateCrc16(span<const uint_least8_t> data,
uint_fast16_t crc) {
- for (size_t i = 0; i < dataLen; i++) {
+ for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
crc = calculateCrc16(data[i], crc);
}
return crc;
--- a/Utilities/crc.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/crc.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -36,41 +36,37 @@
#include <stddef.h>
#include <stdint.h>
#include <MaximInterface/Utilities/Export.h>
+#include "span.hpp"
namespace MaximInterface {
-/// Perform a CRC8 calculation.
+/// @brief Perform a CRC8 calculation.
/// @param data Data to pass though the CRC generator.
/// @param crc Beginning state of the CRC generator.
/// @returns The calculated CRC8.
MaximInterface_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t data,
uint_fast8_t crc = 0);
-/// Perform a CRC8 calculation with variable length data.
+/// @brief Perform a CRC8 calculation with variable length data.
/// @param[in] data Data array to pass through the CRC generator.
-/// @param dataLen Length of the data array to process.
/// @param crc Beginning state of the CRC generator.
/// @returns The calculated CRC8.
-MaximInterface_EXPORT uint_fast8_t calculateCrc8(const uint_least8_t * data,
- size_t dataLen,
+MaximInterface_EXPORT uint_fast8_t calculateCrc8(span<const uint_least8_t> data,
uint_fast8_t crc = 0);
-/// Perform a CRC16 calculation.
+/// @brief Perform a CRC16 calculation.
/// @param data Data to pass though the CRC generator.
/// @param crc Beginning state of the CRC generator.
/// @returns The calculated CRC16.
MaximInterface_EXPORT uint_fast16_t calculateCrc16(uint_fast8_t data,
uint_fast16_t crc = 0);
-/// Perform a CRC16 calculation with variable length data.
+/// @brief Perform a CRC16 calculation with variable length data.
/// @param[in] data Data array to pass through the CRC generator.
-/// @param data_offset Offset of the data array to begin processing.
-/// @param data_len Length of the data array to process.
/// @param crc Beginning state of the CRC generator.
/// @returns The calculated CRC16.
-MaximInterface_EXPORT uint_fast16_t calculateCrc16(const uint_least8_t * data,
- size_t dataLen,
- uint_fast16_t crc = 0);
+MaximInterface_EXPORT uint_fast16_t
+calculateCrc16(span<const uint_least8_t> data, uint_fast16_t crc = 0);
} // namespace MaximInterface
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/optional.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,318 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_optional
+#define MaximInterface_optional
+
+#include "SafeBool.hpp"
+
+// Include for std::swap.
+#include <algorithm>
+#include <utility>
+
+namespace MaximInterface {
+
+struct nullopt_t {
+ explicit nullopt_t(int) {}
+};
+
+static const nullopt_t nullopt(0);
+
+/// @brief Optional value container similar to std::optional.
+/// @details
+/// To prevent the need for aligned storage, this implementation imposes that
+/// types must be DefaultConstructible, CopyConstructible, and CopyAssignable.
+/// No exceptions are thrown when accessing a valueless optional.
+template <typename T> class optional {
+public:
+ typedef T value_type;
+
+ optional() : value_(), has_value_(false) {}
+
+ optional(nullopt_t) : value_(), has_value_(false) {}
+
+ optional(const T & value) : value_(value), has_value_(true) {}
+
+ template <typename U>
+ explicit optional(const optional<U> & other)
+ : value_(other.value_), has_value_(other.has_value_) {}
+
+ optional & operator=(nullopt_t) {
+ reset();
+ return *this;
+ }
+
+ optional & operator=(const T & value) {
+ value_ = value;
+ has_value_ = true;
+ return *this;
+ }
+
+ template <typename U> optional & operator=(const optional<U> & other) {
+ if (has_value_ || other.has_value_) {
+ value_ = other.value_;
+ has_value_ = other.has_value_;
+ }
+ return *this;
+ }
+
+ bool has_value() const { return has_value_; }
+
+ operator SafeBool() const { return makeSafeBool(has_value()); }
+
+ const T & value() const { return value_; }
+
+ T & value() {
+ return const_cast<T &>(static_cast<const optional &>(*this).value());
+ }
+
+ const T & operator*() const { return value(); }
+
+ T & operator*() {
+ return const_cast<T &>(static_cast<const optional &>(*this).operator*());
+ }
+
+ const T * operator->() const { return &value(); }
+
+ T * operator->() {
+ return const_cast<T *>(static_cast<const optional &>(*this).operator->());
+ }
+
+ const T & value_or(const T & default_value) const {
+ return has_value() ? value() : default_value;
+ }
+
+ void swap(optional & other) {
+ if (has_value_ || other.has_value_) {
+ using std::swap;
+ swap(value_, other.value_);
+ swap(has_value_, other.has_value_);
+ }
+ }
+
+ void reset() {
+ if (has_value_) {
+ has_value_ = false;
+ value_ = T();
+ }
+ }
+
+private:
+ T value_;
+ bool has_value_;
+};
+
+template <typename T> optional<T> make_optional(const T & value) {
+ return value;
+}
+
+template <typename T> void swap(optional<T> & lhs, optional<T> & rhs) {
+ lhs.swap(rhs);
+}
+
+template <typename T, typename U>
+bool operator==(const optional<T> & lhs, const optional<U> & rhs) {
+ if (lhs.has_value() != rhs.has_value()) {
+ return false;
+ }
+ if (!lhs.has_value()) {
+ return true;
+ }
+ return lhs.value() == rhs.value();
+}
+
+template <typename T, typename U>
+bool operator!=(const optional<T> & lhs, const optional<U> & rhs) {
+ if (lhs.has_value() != rhs.has_value()) {
+ return true;
+ }
+ if (!lhs.has_value()) {
+ return false;
+ }
+ return lhs.value() != rhs.value();
+}
+
+template <typename T, typename U>
+bool operator<(const optional<T> & lhs, const optional<U> & rhs) {
+ if (!rhs.has_value()) {
+ return false;
+ }
+ if (!lhs.has_value()) {
+ return true;
+ }
+ return lhs.value() < rhs.value();
+}
+
+template <typename T, typename U>
+bool operator<=(const optional<T> & lhs, const optional<U> & rhs) {
+ if (!lhs.has_value()) {
+ return true;
+ }
+ if (!rhs.has_value()) {
+ return false;
+ }
+ return lhs.value() <= rhs.value();
+}
+
+template <typename T, typename U>
+bool operator>(const optional<T> & lhs, const optional<U> & rhs) {
+ if (!lhs.has_value()) {
+ return false;
+ }
+ if (!rhs.has_value()) {
+ return true;
+ }
+ return lhs.value() > rhs.value();
+}
+
+template <typename T, typename U>
+bool operator>=(const optional<T> & lhs, const optional<U> & rhs) {
+ if (!rhs.has_value()) {
+ return true;
+ }
+ if (!lhs.has_value()) {
+ return false;
+ }
+ return lhs.value() >= rhs.value();
+}
+
+template <typename T> bool operator==(const optional<T> & opt, nullopt_t) {
+ return !opt.has_value();
+}
+
+template <typename T> bool operator==(nullopt_t, const optional<T> & opt) {
+ return operator==(opt, nullopt);
+}
+
+template <typename T> bool operator!=(const optional<T> & opt, nullopt_t) {
+ return !operator==(opt, nullopt);
+}
+
+template <typename T> bool operator!=(nullopt_t, const optional<T> & opt) {
+ return operator!=(opt, nullopt);
+}
+
+template <typename T> bool operator<(const optional<T> &, nullopt_t) {
+ return false;
+}
+
+template <typename T> bool operator<(nullopt_t, const optional<T> & opt) {
+ return opt.has_value();
+}
+
+template <typename T> bool operator<=(const optional<T> & opt, nullopt_t) {
+ return !operator>(opt, nullopt);
+}
+
+template <typename T> bool operator<=(nullopt_t, const optional<T> & opt) {
+ return !operator>(nullopt, opt);
+}
+
+template <typename T> bool operator>(const optional<T> & opt, nullopt_t) {
+ return operator<(nullopt, opt);
+}
+
+template <typename T> bool operator>(nullopt_t, const optional<T> & opt) {
+ return operator<(opt, nullopt);
+}
+
+template <typename T> bool operator>=(const optional<T> & opt, nullopt_t) {
+ return !operator<(opt, nullopt);
+}
+
+template <typename T> bool operator>=(nullopt_t, const optional<T> & opt) {
+ return !operator<(nullopt, opt);
+}
+
+template <typename T, typename U>
+bool operator==(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() == value : false;
+}
+
+template <typename T, typename U>
+bool operator==(const T & value, const optional<U> & opt) {
+ return operator==(opt, value);
+}
+
+template <typename T, typename U>
+bool operator!=(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() != value : true;
+}
+
+template <typename T, typename U>
+bool operator!=(const T & value, const optional<U> & opt) {
+ return operator!=(opt, value);
+}
+
+template <typename T, typename U>
+bool operator<(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() < value : true;
+}
+
+template <typename T, typename U>
+bool operator<(const T & value, const optional<U> & opt) {
+ return opt.has_value() ? value < opt.value() : false;
+}
+
+template <typename T, typename U>
+bool operator<=(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() <= value : true;
+}
+
+template <typename T, typename U>
+bool operator<=(const T & value, const optional<U> & opt) {
+ return opt.has_value() ? value <= opt.value() : false;
+}
+
+template <typename T, typename U>
+bool operator>(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() > value : false;
+}
+
+template <typename T, typename U>
+bool operator>(const T & value, const optional<U> & opt) {
+ return opt.has_value() ? value > opt.value() : true;
+}
+
+template <typename T, typename U>
+bool operator>=(const optional<T> & opt, const U & value) {
+ return opt.has_value() ? opt.value() >= value : false;
+}
+
+template <typename T, typename U>
+bool operator>=(const T & value, const optional<U> & opt) {
+ return opt.has_value() ? value >= opt.value() : true;
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/span.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -0,0 +1,366 @@
+/*******************************************************************************
+* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_span
+#define MaximInterface_span
+
+#include <stddef.h>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include "array.hpp"
+#include "type_traits.hpp"
+
+namespace MaximInterface {
+
+static const ptrdiff_t dynamic_extent = -1;
+
+struct with_container_t {
+ explicit with_container_t(int) {}
+};
+
+static const with_container_t with_container(0);
+
+namespace detail {
+
+template <template <typename, ptrdiff_t = MaximInterface::dynamic_extent>
+ class span,
+ typename T, ptrdiff_t Extent>
+class span_base {
+public:
+ typedef T element_type;
+ typedef typename remove_cv<element_type>::type value_type;
+ typedef ptrdiff_t index_type;
+ typedef ptrdiff_t difference_type;
+ typedef element_type * pointer;
+ typedef element_type & reference;
+ typedef element_type * iterator;
+ typedef const element_type * const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ static const index_type extent = Extent;
+
+protected:
+ span_base(pointer data) : data_(data) {}
+ ~span_base() {}
+
+public:
+ /// @name Iterators
+ /// @{
+
+ iterator begin() const {
+ return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin());
+ }
+
+ const_iterator cbegin() const { return data(); }
+
+ iterator end() const {
+ return const_cast<iterator>(static_cast<const span_base &>(*this).cend());
+ }
+
+ const_iterator cend() const { return cbegin() + size(); }
+
+ reverse_iterator rbegin() const { return reverse_iterator(end()); }
+
+ const_reverse_iterator crbegin() const {
+ return const_reverse_iterator(cend());
+ }
+
+ reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+ const_reverse_iterator crend() const {
+ return const_reverse_iterator(cbegin());
+ }
+
+ /// @}
+
+ /// @name Element access
+ /// @{
+
+ reference operator[](index_type idx) const { return data()[idx]; }
+
+ reference operator()(index_type idx) const { return operator[](idx); }
+
+ pointer data() const { return data_; }
+
+ /// @}
+
+ /// @name Subviews
+ /// @{
+
+ template <index_type Count> span<element_type, Count> first() const {
+ return subspan<0, Count>();
+ }
+
+ span<element_type> first(index_type Count) const { return subspan(0, Count); }
+
+ span<element_type> last(index_type Count) const {
+ return subspan(size() - Count, Count);
+ }
+
+ template <index_type Offset, index_type Count>
+ span<element_type, Count> subspan() const {
+ return span<element_type, Count>(data() + Offset, Count);
+ }
+
+ span<element_type> subspan(index_type Offset,
+ index_type Count = dynamic_extent) const {
+ return span<element_type>(
+ data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
+ }
+
+ /// @}
+
+private:
+ index_type size() const {
+ return static_cast<const span<T, Extent> &>(*this).size();
+ }
+
+ pointer data_;
+};
+
+} // namespace detail
+
+/// Generic memory span class similar to gsl::span or the proposed std::span.
+template <typename T, ptrdiff_t Extent = dynamic_extent>
+class span : public detail::span_base<MaximInterface::span, T, Extent> {
+ typedef detail::span_base<MaximInterface::span, T, Extent> span_base;
+
+public:
+ using span_base::extent;
+ using typename span_base::element_type;
+ using typename span_base::index_type;
+ using typename span_base::pointer;
+ using typename span_base::value_type;
+
+ span(pointer data, index_type) : span_base(data) {}
+
+ span(pointer begin, pointer) : span_base(begin) {}
+
+ span(element_type (&arr)[extent]) : span_base(arr) {}
+
+ span(array<value_type, extent> & arr) : span_base(arr.data()) {}
+
+ span(const array<value_type, extent> & arr) : span_base(arr.data()) {}
+
+ template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {}
+
+ template <typename Allocator>
+ explicit span(std::vector<value_type, Allocator> & vec)
+ : span_base(&vec.front()) {}
+
+ template <typename Allocator>
+ explicit span(const std::vector<value_type, Allocator> & vec)
+ : span_base(&vec.front()) {}
+
+ template <typename Container>
+ span(with_container_t, Container & cont) : span_base(cont.data()) {}
+
+ template <typename Container>
+ span(with_container_t, const Container & cont) : span_base(cont.data()) {}
+
+ /// @name Observers
+ /// @{
+
+ static index_type size() { return extent; }
+
+ static index_type size_bytes() { return size() * sizeof(element_type); }
+
+ static bool empty() { return size() == 0; }
+
+ /// @}
+
+ /// @name Subviews
+ /// @{
+
+ template <index_type Count> span<element_type, Count> last() const {
+ return this->template subspan<extent - Count, Count>();
+ }
+
+ /// @}
+};
+
+template <typename T>
+class span<T, dynamic_extent>
+ : public detail::span_base<MaximInterface::span, T, dynamic_extent> {
+ typedef detail::span_base<MaximInterface::span, T, dynamic_extent> span_base;
+
+public:
+ using typename span_base::element_type;
+ using typename span_base::index_type;
+ using typename span_base::pointer;
+ using typename span_base::value_type;
+
+ span() : span_base(NULL), size_(0) {}
+
+ span(pointer data, index_type size) : span_base(data), size_(size) {}
+
+ span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {}
+
+ template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {}
+
+ template <size_t N>
+ span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
+
+ template <size_t N>
+ span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
+
+ template <typename U, ptrdiff_t N>
+ span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
+
+ template <typename Allocator>
+ span(std::vector<value_type, Allocator> & vec)
+ : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
+
+ template <typename Allocator>
+ span(const std::vector<value_type, Allocator> & vec)
+ : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
+
+ template <typename Container>
+ span(with_container_t, Container & cont)
+ : span_base(cont.data()), size_(cont.size()) {}
+
+ template <typename Container>
+ span(with_container_t, const Container & cont)
+ : span_base(cont.data()), size_(cont.size()) {}
+
+ /// @name Observers
+ /// @{
+
+ index_type size() const { return size_; }
+
+ index_type size_bytes() const { return size() * sizeof(element_type); }
+
+ bool empty() const { return size() == 0; }
+
+ /// @}
+
+ /// @name Subviews
+ /// @{
+
+ template <index_type Count> span<element_type, Count> last() const {
+ return span<element_type, Count>(this->data() + (size() - Count), Count);
+ }
+
+ /// @}
+
+private:
+ index_type size_;
+};
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator==(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return lhs.size() == rhs.size() &&
+ std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator!=(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return !operator==(lhs, rhs);
+}
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator<(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
+ rhs.end());
+}
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator>(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return operator<(rhs, lhs);
+}
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator<=(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return !operator>(lhs, rhs);
+}
+
+template <typename T, ptrdiff_t Extent, typename U>
+bool operator>=(span<T, Extent> lhs, span<U, Extent> rhs) {
+ return !operator<(lhs, rhs);
+}
+
+template <typename T>
+span<T> make_span(T * data, typename span<T>::index_type size) {
+ return span<T>(data, size);
+}
+
+template <typename T> span<T> make_span(T * begin, T * end) {
+ return span<T>(begin, end);
+}
+
+template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) {
+ return span<T, N>(arr);
+}
+
+template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) {
+ return arr;
+}
+
+template <typename T, size_t N>
+span<const T, N> make_span(const array<T, N> & arr) {
+ return arr;
+}
+
+template <typename T, typename Allocator>
+span<T> make_span(std::vector<T, Allocator> & vec) {
+ return vec;
+}
+
+template <typename T, typename Allocator>
+span<const T> make_span(const std::vector<T, Allocator> & vec) {
+ return vec;
+}
+
+template <typename Container>
+span<typename Container::value_type> make_span(with_container_t,
+ Container & cont) {
+ return span<typename Container::value_type>(with_container, cont);
+}
+
+template <typename Container>
+span<const typename Container::value_type> make_span(with_container_t,
+ const Container & cont) {
+ return span<const typename Container::value_type>(with_container, cont);
+}
+
+/// Deep copy between static spans of the same size.
+template <typename T, ptrdiff_t Extent, typename U>
+typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src,
+ span<U, Extent> dst) {
+ std::copy(src.begin(), src.end(), dst.begin());
+}
+
+} // namespace MaximInterface
+
+#endif
--- a/Utilities/system_error.cpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/system_error.cpp Wed Apr 03 12:33:10 2019 +0000
@@ -35,6 +35,8 @@
namespace MaximInterface {
+using std::string;
+
error_condition error_category::default_error_condition(int code) const {
return error_condition(code, *this);
}
@@ -53,11 +55,42 @@
public:
virtual const char * name() const { return "system"; }
- virtual std::string message(int condition) const {
+ virtual string message(int condition) const {
return defaultErrorMessage(condition);
}
} instance;
return instance;
}
-} // namespace MaximInterface
\ No newline at end of file
+static string formatWhat(const error_code & ec) {
+ return string(ec.category().name()) + ' ' + ec.message();
+}
+
+template <typename T>
+static string formatWhat(const error_code & ec, const T & what_arg) {
+ return string(what_arg) + ": " + formatWhat(ec);
+}
+
+system_error::system_error(const error_code & ec)
+ : runtime_error(formatWhat(ec)), code_(ec) {}
+
+system_error::system_error(const error_code & ec, const string & what_arg)
+ : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
+
+system_error::system_error(const error_code & ec, const char * what_arg)
+ : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
+
+system_error::system_error(int ev, const error_category & ecat)
+ : runtime_error(formatWhat(error_code(ev, ecat))), code_(ev, ecat) {}
+
+system_error::system_error(int ev, const error_category & ecat,
+ const string & what_arg)
+ : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
+ code_(ev, ecat) {}
+
+system_error::system_error(int ev, const error_category & ecat,
+ const char * what_arg)
+ : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
+ code_(ev, ecat) {}
+
+} // namespace MaximInterface
--- a/Utilities/system_error.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/system_error.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -31,14 +31,17 @@
*******************************************************************************/
/// @file
-/// Error handling constructs similar std::error_code, std::error_condition, and
-/// std::error_category.
+/// @brief
+/// Error handling constructs similar to std::error_code, std::error_condition,
+/// and std::error_category.
#ifndef MaximInterface_system_error
#define MaximInterface_system_error
+#include <stdexcept>
#include <string>
-#include <MaximInterface/Utilities/Export.h>
+#include "Export.h"
+#include "SafeBool.hpp"
#include "Uncopyable.hpp"
namespace MaximInterface {
@@ -51,20 +54,27 @@
virtual ~error_category() {}
virtual const char * name() const = 0;
+
MaximInterface_EXPORT virtual error_condition
default_error_condition(int code) const;
+
MaximInterface_EXPORT virtual bool
equivalent(int code, const error_condition & condition) const;
+
MaximInterface_EXPORT virtual bool equivalent(const error_code & code,
int condition) const;
+
virtual std::string message(int condition) const = 0;
};
+
inline bool operator==(const error_category & lhs, const error_category & rhs) {
return &lhs == &rhs;
}
+
inline bool operator!=(const error_category & lhs, const error_category & rhs) {
return !operator==(lhs, rhs);
}
+
inline bool operator<(const error_category & lhs, const error_category & rhs) {
return &lhs < &rhs;
}
@@ -74,6 +84,7 @@
class error_condition {
public:
error_condition() : value_(0), category_(&system_category()) {}
+
error_condition(int value, const error_category & category)
: value_(value), category_(&category) {}
@@ -81,27 +92,35 @@
value_ = value;
category_ = &category;
}
+
void clear() {
value_ = 0;
category_ = &system_category();
}
+
int value() const { return value_; }
+
const error_category & category() const { return *category_; }
+
std::string message() const { return category().message(value()); }
- operator bool() const { return value() != 0; }
+
+ operator SafeBool() const { return makeSafeBool(value() != 0); }
private:
int value_;
const error_category * category_;
};
+
inline bool operator==(const error_condition & lhs,
const error_condition & rhs) {
return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category());
}
+
inline bool operator!=(const error_condition & lhs,
const error_condition & rhs) {
return !operator==(lhs, rhs);
}
+
inline bool operator<(const error_condition & lhs,
const error_condition & rhs) {
return (lhs.category() < rhs.category()) ||
@@ -111,6 +130,7 @@
class error_code {
public:
error_code() : value_(0), category_(&system_category()) {}
+
error_code(int value, const error_category & category)
: value_(value), category_(&category) {}
@@ -118,28 +138,37 @@
value_ = value;
category_ = &category;
}
+
void clear() {
value_ = 0;
category_ = &system_category();
}
+
int value() const { return value_; }
+
const error_category & category() const { return *category_; }
+
error_condition default_error_condition() const {
return category().default_error_condition(value());
}
+
std::string message() const { return category().message(value()); }
- operator bool() const { return value() != 0; }
+
+ operator SafeBool() const { return makeSafeBool(value() != 0); }
private:
int value_;
const error_category * category_;
};
+
inline bool operator==(const error_code & lhs, const error_code & rhs) {
return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category());
}
+
inline bool operator!=(const error_code & lhs, const error_code & rhs) {
return !operator==(lhs, rhs);
}
+
inline bool operator<(const error_code & lhs, const error_code & rhs) {
return (lhs.category() < rhs.category()) ||
((lhs.category() == rhs.category()) && (lhs.value() < rhs.value()));
@@ -156,16 +185,43 @@
return lhs.category().equivalent(lhs.value(), rhs) ||
rhs.category().equivalent(lhs, rhs.value());
}
+
inline bool operator!=(const error_code & lhs, const error_condition & rhs) {
return !operator==(lhs, rhs);
}
+
inline bool operator==(const error_condition & lhs, const error_code & rhs) {
return operator==(rhs, lhs);
}
+
inline bool operator!=(const error_condition & lhs, const error_code & rhs) {
return !operator==(lhs, rhs);
}
+class system_error : public std::runtime_error {
+public:
+ MaximInterface_EXPORT system_error(const error_code & ec);
+
+ MaximInterface_EXPORT system_error(const error_code & ec,
+ const std::string & what_arg);
+
+ MaximInterface_EXPORT system_error(const error_code & ec,
+ const char * what_arg);
+
+ MaximInterface_EXPORT system_error(int ev, const error_category & ecat);
+
+ MaximInterface_EXPORT system_error(int ev, const error_category & ecat,
+ const std::string & what_arg);
+
+ MaximInterface_EXPORT system_error(int ev, const error_category & ecat,
+ const char * what_arg);
+
+ const error_code & code() const { return code_; }
+
+private:
+ error_code code_;
+};
+
} // namespace MaximInterface
#endif
--- a/Utilities/type_traits.hpp Tue Jul 24 08:33:31 2018 +0000
+++ b/Utilities/type_traits.hpp Wed Apr 03 12:33:10 2019 +0000
@@ -39,7 +39,8 @@
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
- operator T() { return v; }
+ operator value_type() const { return value; }
+ value_type operator()() const { return value; }
};
typedef integral_constant<bool, true> true_type;
@@ -71,6 +72,16 @@
struct alignment_of
: integral_constant<size_t,
sizeof(detail::alignment_of_helper<T>) - sizeof(T)> {};
+
+template <typename T> struct remove_const { typedef T type; };
+template <typename T> struct remove_const<const T> { typedef T type; };
+
+template <typename T> struct remove_volatile { typedef T type; };
+template <typename T> struct remove_volatile<volatile T> { typedef T type; };
+
+template <typename T> struct remove_cv {
+ typedef typename remove_volatile<typename remove_const<T>::type>::type type;
+};
} // namespace MaximInterface
--- a/clr.cmake Tue Jul 24 08:33:31 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-#[[*****************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-******************************************************************************]]
-
-include_guard()
-
-macro(initializeClr)
- if(NOT MSVC)
- message(SEND_ERROR "MSVC must be used for CLR compilation.")
- endif()
- string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa /DNOMINMAX")
-endmacro(initializeClr)
-
-function(enableClr target dotnetFrameworkVersion)
- set(dotnetFrameworkDir
- "C:/Program Files (x86)/Reference Assemblies/Microsoft/Framework/.NETFramework/${dotnetFrameworkVersion}")
- set(ARGN "mscorlib.dll" ${ARGN})
- unset(dotnetReferences)
- foreach(reference ${ARGN})
- if(NOT IS_ABSOLUTE ${reference})
- set(reference "${dotnetFrameworkDir}/${reference}")
- endif()
- list(APPEND dotnetReferences ${reference})
- endforeach()
-
- if(CMAKE_GENERATOR MATCHES "Visual Studio")
- if(CMAKE_GENERATOR MATCHES "2005" OR CMAKE_GENERATOR MATCHES "2008")
- message(SEND_ERROR "Visual Studio 2010 or later is required to build CLR target \"${target}\".")
- endif()
-
- set_property(TARGET ${target} PROPERTY VS_GLOBAL_CLRSupport "true")
- set_property(TARGET ${target} PROPERTY
- VS_DOTNET_TARGET_FRAMEWORK_VERSION "${dotnetFrameworkVersion}")
- set_property(TARGET ${target} PROPERTY VS_DOTNET_REFERENCES ${dotnetReferences})
- else()
- unset(dotnetReferenceArgs)
- foreach(reference ${dotnetReferences})
- list(APPEND dotnetReferenceArgs "/FU${reference}")
- endforeach()
- set_property(TARGET ${target} APPEND PROPERTY COMPILE_OPTIONS
- "/AI${dotnetFrameworkDir}"
- "/clr"
- ${dotnetReferenceArgs}
- "/clr:nostdlib")
- endif()
-endfunction(enableClr)
\ No newline at end of file