diff --git a/include/tfcppsimple/devices/TfIO16Bricklet.h b/include/tfcppsimple/devices/TfIO16Bricklet.h index b5e2603..4f5cdb4 100644 --- a/include/tfcppsimple/devices/TfIO16Bricklet.h +++ b/include/tfcppsimple/devices/TfIO16Bricklet.h @@ -9,10 +9,22 @@ #define TFIO16BRICKLET_H_ #include +#include namespace tfcppsimple { + + class TfIO16Bricklet: public TfBricklet { +private: + IO16 ioObj; + uint8_t dirMapA = 0xFF; // 1 .. Eingang, 0 .. Ausgang + uint8_t valueMapA = 0; + uint8_t outMapA = 0; + uint8_t dirMapB = 0xFF; // 1 .. Eingang, 0 .. Ausgang + uint8_t valueMapB = 0; + uint8_t outMapB = 0; + public: TfIO16Bricklet(TfConnection& connection, std::string uid, @@ -25,6 +37,19 @@ public: virtual ~TfIO16Bricklet(); virtual std::string getDeviceName(bool extended = true); + + virtual void doConfigureDevice(); + virtual void doReconfigureDevice(); + virtual void doConnectionLost(); + virtual void doShutdown(); + + void getPortConfiguration(char port, uint8_t& ret_direction_mask, uint8_t& ret_value_mask); + void setPortConfiguration(char port, uint8_t selection_mask, char direction, bool value); + void setPortConfiguration(char port, uint8_t direction_mask, uint8_t value_mask); + + uint8_t getPort(char port); + void setPort(char port, uint8_t value_mask); + void setPort(char port, uint8_t pin_mask, bool value); }; } /* namespace tfcppsimple */ diff --git a/src/devices/TfIO16Bricklet.cpp b/src/devices/TfIO16Bricklet.cpp index 05415f4..5068077 100644 --- a/src/devices/TfIO16Bricklet.cpp +++ b/src/devices/TfIO16Bricklet.cpp @@ -6,6 +6,7 @@ */ #include +#include namespace tfcppsimple { @@ -36,4 +37,168 @@ std::string TfIO16Bricklet::getDeviceName(bool extended) { return ss.str(); } +void TfIO16Bricklet::doConfigureDevice() { + io16_create(&ioObj, uid.c_str(), &connection.getTfIpConnection()); + int ret = io16_set_response_expected_all(&ioObj, true); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while configuring: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } else { + setPortConfiguration('a', dirMapA, valueMapA); + setPort('a', outMapA); + setPortConfiguration('b', dirMapB, valueMapB); + setPort('b', outMapB); + TfDevice::doConfigureDevice(); + } +} + +void TfIO16Bricklet::doReconfigureDevice() { + io16_destroy(&ioObj); + io16_create(&ioObj, uid.c_str(), &connection.getTfIpConnection()); + int ret = io16_set_response_expected_all(&ioObj, true); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while reconfiguring: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } else { + setPortConfiguration('a', dirMapA, valueMapA); + setPort('a', outMapA); + setPortConfiguration('b', dirMapB, valueMapB); + setPort('b', outMapB); + TfDevice::doReconfigureDevice(); + } +} + +void TfIO16Bricklet::doConnectionLost() { + TfDevice::doConnectionLost(); +} + +void TfIO16Bricklet::doShutdown() { + io16_destroy(&ioObj); + TfDevice::doShutdown(); +} + + +void TfIO16Bricklet::getPortConfiguration(char port, uint8_t& ret_direction_mask, uint8_t& ret_value_mask) { + if (port == 'a') { + ret_direction_mask = dirMapA; + ret_value_mask = valueMapA; + } else if (port == 'b') { + ret_direction_mask = dirMapB; + ret_value_mask = valueMapB; + } else { + std::ostringstream ss; + ss << "Unknown Port: " << port << "."; + throw TfError(ss.str(), TfErrorCode::E_INVALID_PARAMETER); + } +} + +void TfIO16Bricklet::setPortConfiguration(char port, uint8_t selection_mask, char direction, bool value) { + if (port == 'a') { + dirMapA = (dirMapA & ~selection_mask) | ((direction == 'i' ? 0xFF : 0x00) & selection_mask); + valueMapA = (dirMapA & ~selection_mask) | ((value ? 0xFF : 0x00) & selection_mask); + } else if (port == 'b') { + dirMapB = (dirMapB & ~selection_mask) | ((direction == 'i' ? 0xFF : 0x00) & selection_mask); + valueMapB = (valueMapB & ~selection_mask) | ((value ? 0xFF : 0x00) & selection_mask); + } else { + std::ostringstream ss; + ss << "Unknown Port: " << port << "."; + throw TfError(ss.str(), TfErrorCode::E_INVALID_PARAMETER); + } + int ret = io16_set_port_configuration(&ioObj, port, selection_mask, direction, value); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port configuration: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } +} + +void TfIO16Bricklet::setPortConfiguration(char port, uint8_t direction_mask, uint8_t value_mask) { + uint8_t dir; + uint8_t val; + if (port == 'a') { + dir = dirMapA = direction_mask; + val = valueMapA = value_mask; + } else if (port == 'b') { + dir = dirMapB = direction_mask; + val = valueMapB = value_mask; + } else { + std::ostringstream ss; + ss << "Unknown Port: " << port << "."; + throw TfError(ss.str(), TfErrorCode::E_INVALID_PARAMETER); + } + uint8_t mask = dir & val; + if (mask != 0) { + int ret = io16_set_port_configuration(&ioObj, port, mask, 'i', true); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port configuration: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } + } + mask = ~dir & val; + if (mask != 0) { + int ret = io16_set_port_configuration(&ioObj, port, mask, 'o', true); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port configuration: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } + } + mask = dir & ~val; + if (mask != 0) { + int ret = io16_set_port_configuration(&ioObj, port, mask, 'i', false); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port configuration: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } + } + mask = ~dir & ~val; + if (mask != 0) { + int ret = io16_set_port_configuration(&ioObj, port, mask, 'o', false); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port configuration: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } + } + +} + +uint8_t TfIO16Bricklet::getPort(char port) { + uint8_t retval; + int ret = io16_get_port(&ioObj, port, &retval); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while getting port: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } + return retval; +} + +void TfIO16Bricklet::setPort(char port, uint8_t value_mask) { + if (port == 'a') { + outMapA = value_mask; + } else if (port == 'b') { + outMapB = value_mask; + } else { + std::ostringstream ss; + ss << "Unknown Port: " << port << "."; + throw TfError(ss.str(), TfErrorCode::E_INVALID_PARAMETER); + } + int ret = io16_set_port(&ioObj, port, value_mask); + if (ret != E_OK) { + std::ostringstream ss; + ss << "Error while setting port: " << ret << "."; + throw TfError(ss.str(), (TfErrorCode)ret); + } +} + +void TfIO16Bricklet::setPort(char port, uint8_t pin_mask, bool value) { + throw TfError("Not implemented", TfErrorCode::E_UNKNOWN_ERROR_CODE); +} + + } /* namespace tfcppsimple */