diff --git a/CMakeLists.txt b/CMakeLists.txt index 342d71c..7066e69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ find_package(YamlCpp REQUIRED 0.6.3) include(FetchContent) FetchContent_Declare(jsd GIT_REPOSITORY https://github.com/nasa-jpl/jsd.git - GIT_TAG v3.0.1 + GIT_TAG prestonr-add-el5042 ) FetchContent_MakeAvailable(jsd) diff --git a/doc/fastcat_device_config_parameters.md b/doc/fastcat_device_config_parameters.md index f6747a6..5a4fd8a 100644 --- a/doc/fastcat_device_config_parameters.md +++ b/doc/fastcat_device_config_parameters.md @@ -15,6 +15,9 @@ For every `JSD Device` there is an `Offline Device` to emulate the behavior of t | El3602 | Beckhoff | 2-channel +/-10v Diff. Analog Input | | El2124 | Beckhoff | 4-channel 5v Digital Output | | El2809 | Beckhoff | 16-channel 24v Digital Output | +| El5042 | Beckhoff | 2-channel Encoder | +| El2828 | Beckhoff | 8-channel 24v 2A Digital Output | +| El2798 | Beckhoff | 8-channel 30v AC/48v DC 2A Solid State Relay Output | | El4102 | Beckhoff | 2-channel 0-10v Analog Output | | Ild1900 | Micro-Epsilon | Distance Laser Sensor | | AtiFts | ATI | Force-Torque Sensor | @@ -425,6 +428,73 @@ The permitted range values are: name: el2809_1 ``` +## El5042 (2-channel BiSS-C Encoder Interface) + +| Parameter | Description | +| ----------------- | ------------------------------------------------------------ | +| `invert_feedback_direction` | Negates the position value (0 for don't invert and 1 for invert) | +| `disable_status_bits` | Tell the slave whether or not to send status bits (0 for don't disable and 1 for disable) | +| `invert_checksum` | Inverts the checksum bits (CRC) received by the encoder (0 for don't inver and 1 for invert) | +| `checksum_polynomial` | Polynomial used for calculating checksum. This is a 32 bit polynomial. | +| `supply_voltage` | Set the encoder supply voltage, either 50 for 5V or 90 for 9V | +| `clock_frequency` | Clock frequency for the BiSS-C protocol (250 kHz to 10 MHz as specified below) | +| `gray_code` | Option to either use dual code or gray code for accurate data (0 for dual code and 1 for gray code) | +| `multiturn_bits` | Set the number of multiturn bits (how many complete rotations) | +| `singleturn_bits` | Set the number of singleturn bits (resolution of a single rotation) | +| `offset_bits` | If there are addition null bits at the end of the packet, we shift by offset bits to get data | +| `ssi_mode` | Opt for SSI mode over BiSS-C (0 for BiSS-C and 1 for SSI) | + +Clock frequency correspondances + +* 10MHz: 10 MHz +* 5MHz: 5 MHz +* 3_33MHz: 3.3 MHz +* 2_5MHz: 2.5 MHz +* 2MHz: 2 MHz +* 1MHz: 1 MHz +* 500KHz: 500 kHz +* 250KHz: 250 kHz + +#### Example + +```yaml +- device_class: El5042 + name: el5042_1 + invert_feedback_direction: [0, 0] + disable_status_bits: [0, 0] + invert_checksum: [1, 1] + checksum_polynomial: [67, 67] + supply_voltage: [50, 50] + clock_frequency: [5MHz, 5MHz] + gray_code: [0, 0] + multiturn_bits: [0, 0] + singleturn_bits: [19, 19] + offset_bits: [0, 0] + ssi_mode: [0, 0] +``` + +## El2828 (8-channel 24v 2A Digital Output) + +**The El2828 device has no configuration parameters** + +#### Example + +``` yaml +- device_class: El2828 + name: el2828_1 +``` + +## El2798 (8-channel 30v AC/48v DC 2A Solid State Relay Output) + +**The El2798 device has no configuration parameters** + +#### Example + +``` yaml +- device_class: El2798 + name: el2798_1 +``` + ## El4102 (2-channel 0-10v Analog Output) **The El4102 device has no configuration parameters.** diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ae5d41..30e203c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,12 +76,15 @@ add_library(fastcat STATIC jsd/el3602.cc jsd/el2124.cc jsd/el2809.cc + jsd/el2828.cc + jsd/el2798.cc jsd/el4102.cc jsd/el3162.cc jsd/el1008.cc jsd/el3104.cc jsd/el3202.cc jsd/el3318.cc + jsd/el5042.cc jsd/gold_actuator.cc jsd/ild1900.cc jsd/jed0101.cc @@ -92,6 +95,8 @@ add_library(fastcat STATIC jsd/egd_offline.cc jsd/el2124_offline.cc jsd/el2809_offline.cc + jsd/el2828_offline.cc + jsd/el2798_offline.cc jsd/el4102_offline.cc jsd/el3208_offline.cc jsd/el3602_offline.cc @@ -100,6 +105,7 @@ add_library(fastcat STATIC jsd/el3104_offline.cc jsd/el3202_offline.cc jsd/el3318_offline.cc + jsd/el5042_offline.cc jsd/ild1900_offline.cc jsd/gold_actuator_offline.cc jsd/jed0101_offline.cc diff --git a/src/fcgen/fastcat_types.yaml b/src/fcgen/fastcat_types.yaml index a4d20a0..539c7b0 100644 --- a/src/fcgen/fastcat_types.yaml +++ b/src/fcgen/fastcat_types.yaml @@ -348,6 +348,44 @@ states: type: uint8_t - name: level_ch16 type: uint8_t + + - name: el2828 + fields: + - name: level_ch1 + type: uint8_t + - name: level_ch2 + type: uint8_t + - name: level_ch3 + type: uint8_t + - name: level_ch4 + type: uint8_t + - name: level_ch5 + type: uint8_t + - name: level_ch6 + type: uint8_t + - name: level_ch7 + type: uint8_t + - name: level_ch8 + type: uint8_t + + - name: el2798 + fields: + - name: level_ch1 + type: uint8_t + - name: level_ch2 + type: uint8_t + - name: level_ch3 + type: uint8_t + - name: level_ch4 + type: uint8_t + - name: level_ch5 + type: uint8_t + - name: level_ch6 + type: uint8_t + - name: level_ch7 + type: uint8_t + - name: level_ch8 + type: uint8_t - name: el4102 fields: @@ -486,6 +524,25 @@ states: - name: adc_value_ch8 type: int16_t + - name: el5042 + fields: + - name: position_ch1 + type: int64_t + - name: warning_ch1 + type: int8_t + - name: error_ch1 + type: int8_t + - name: ready_ch1 + type: int8_t + - name: position_ch2 + type: int64_t + - name: warning_ch2 + type: int8_t + - name: error_ch2 + type: int8_t + - name: ready_ch2 + type: int8_t + - name: ild1900 fields: - name: distance_m @@ -759,6 +816,58 @@ commands: - name: channel_ch16 type: uint8_t + - name: el2828_write_channel + fields: + - name: channel + type: uint8_t + - name: level + type: uint8_t + + - name: el2798_write_channel + fields: + - name: channel + type: uint8_t + - name: level + type: uint8_t + + - name: el2828_write_all_channels + fields: + - name: channel_ch1 + type: uint8_t + - name: channel_ch2 + type: uint8_t + - name: channel_ch3 + type: uint8_t + - name: channel_ch4 + type: uint8_t + - name: channel_ch5 + type: uint8_t + - name: channel_ch6 + type: uint8_t + - name: channel_ch7 + type: uint8_t + - name: channel_ch8 + type: uint8_t + + - name: el2798_write_all_channels + fields: + - name: channel_ch1 + type: uint8_t + - name: channel_ch2 + type: uint8_t + - name: channel_ch3 + type: uint8_t + - name: channel_ch4 + type: uint8_t + - name: channel_ch5 + type: uint8_t + - name: channel_ch6 + type: uint8_t + - name: channel_ch7 + type: uint8_t + - name: channel_ch8 + type: uint8_t + - name: el4102_write_channel fields: - name: channel diff --git a/src/jsd/el2798.cc b/src/jsd/el2798.cc new file mode 100644 index 0000000..3fb479f --- /dev/null +++ b/src/jsd/el2798.cc @@ -0,0 +1,101 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el2798.h" + +// Include c then c++ libraries +#include + +#include +#include + +// Include external then project includes +#include "fastcat/yaml_parser.h" + +fastcat::El2798::El2798() +{ + MSG_DEBUG("Constructed El2798"); + + state_ = std::make_shared(); + state_->type = EL2798_STATE; +} + +bool fastcat::El2798::ConfigFromYaml(const YAML::Node& node) +{ + bool retval = ConfigFromYamlCommon(node); + jsd_set_slave_config((jsd_t*)context_, slave_id_, jsd_slave_config_); + return retval; +} + +bool fastcat::El2798::ConfigFromYamlCommon(const YAML::Node& node) +{ + if (!ParseVal(node, "name", name_)) { + return false; + } + state_->name = name_; + + jsd_slave_config_.configuration_active = true; + jsd_slave_config_.driver_type = JSD_DRIVER_TYPE_EL2798; + snprintf(jsd_slave_config_.name, JSD_NAME_LEN, "%s", name_.c_str()); + + return true; +} + +bool fastcat::El2798::Read() +{ + const jsd_el2798_state_t* jsd_state = + jsd_el2798_get_state((jsd_t*)context_, slave_id_); + + state_->el2798_state.level_ch1 = jsd_state->output[0]; + state_->el2798_state.level_ch2 = jsd_state->output[1]; + state_->el2798_state.level_ch3 = jsd_state->output[2]; + state_->el2798_state.level_ch4 = jsd_state->output[3]; + state_->el2798_state.level_ch5 = jsd_state->output[4]; + state_->el2798_state.level_ch6 = jsd_state->output[5]; + state_->el2798_state.level_ch7 = jsd_state->output[6]; + state_->el2798_state.level_ch8 = jsd_state->output[7]; + + return true; +} + +fastcat::FaultType fastcat::El2798::Process() +{ + jsd_el2798_process((jsd_t*)context_, slave_id_); + return NO_FAULT; +} + +bool fastcat::El2798::Write(DeviceCmd& cmd) +{ + // If device supports async SDO requests + AsyncSdoRetVal sdoResult = WriteAsyncSdoRequest(cmd); + if (sdoResult != SDO_RET_VAL_NOT_APPLICABLE) { + return (sdoResult == SDO_RET_VAL_SUCCESS); + } + + if (cmd.type == EL2798_WRITE_CHANNEL_CMD) { + uint8_t ch = cmd.el2798_write_channel_cmd.channel; + if (ch < 1 || ch > JSD_EL2798_NUM_CHANNELS) { + ERROR("Channel must be in range (1,%u)", JSD_EL2798_NUM_CHANNELS); + return false; + } + + jsd_el2798_write_single_channel((jsd_t*)context_, slave_id_, ch - 1, + cmd.el2798_write_channel_cmd.level); + + } else if (cmd.type == EL2798_WRITE_ALL_CHANNELS_CMD) { + uint8_t output_array[JSD_EL2798_NUM_CHANNELS] = { + cmd.el2798_write_all_channels_cmd.channel_ch1, + cmd.el2798_write_all_channels_cmd.channel_ch2, + cmd.el2798_write_all_channels_cmd.channel_ch3, + cmd.el2798_write_all_channels_cmd.channel_ch4, + cmd.el2798_write_all_channels_cmd.channel_ch5, + cmd.el2798_write_all_channels_cmd.channel_ch6, + cmd.el2798_write_all_channels_cmd.channel_ch7, + cmd.el2798_write_all_channels_cmd.channel_ch8}; + + jsd_el2798_write_all_channels((jsd_t*)context_, slave_id_, output_array); + + } else { + ERROR("Bad EL2798 Command"); + return false; + } + return true; +} diff --git a/src/jsd/el2798.h b/src/jsd/el2798.h new file mode 100644 index 0000000..fcea6fa --- /dev/null +++ b/src/jsd/el2798.h @@ -0,0 +1,32 @@ +#ifndef FASTCAT_EL2798_H_ +#define FASTCAT_EL2798_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/jsd_device_base.h" +#include "jsd/jsd_el2798_pub.h" + +namespace fastcat +{ +class El2798 : public JsdDeviceBase +{ + public: + El2798(); + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; + FaultType Process() override; + bool Write(DeviceCmd& cmd) override; + + protected: + bool ConfigFromYamlCommon(const YAML::Node& node); + + private: + jsd_slave_config_t jsd_slave_config_ = {0}; +}; + +} // namespace fastcat + +#endif diff --git a/src/jsd/el2798_offline.cc b/src/jsd/el2798_offline.cc new file mode 100644 index 0000000..b5b9a8a --- /dev/null +++ b/src/jsd/el2798_offline.cc @@ -0,0 +1,100 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el2798_offline.h" + +// Include c then c++ libraries +#include + +#include +#include + +// Include external then project includes +#include "fastcat/yaml_parser.h" + +bool fastcat::El2798Offline::ConfigFromYaml(const YAML::Node& node) +{ + return ConfigFromYamlCommon(node); +} + +bool fastcat::El2798Offline::Read() { return true; } + +fastcat::FaultType fastcat::El2798Offline::Process() +{ + return DeviceBase::Process(); +} + +bool fastcat::El2798Offline::Write(DeviceCmd& cmd) +{ + // If device supports async SDO requests + AsyncSdoRetVal sdoResult = WriteAsyncSdoRequest(cmd); + if (sdoResult != SDO_RET_VAL_NOT_APPLICABLE) { + return (sdoResult == SDO_RET_VAL_SUCCESS); + } + + if (cmd.type == EL2798_WRITE_CHANNEL_CMD) { + uint8_t ch = cmd.el2798_write_channel_cmd.channel; + if (ch < 1 || ch > JSD_EL2798_NUM_CHANNELS) { + ERROR("Channel must be in range (1,%u)", JSD_EL2798_NUM_CHANNELS); + return false; + } + switch (cmd.el2798_write_channel_cmd.channel) { + case 1: + state_->el2798_state.level_ch1 = cmd.el2798_write_channel_cmd.level; + break; + case 2: + state_->el2798_state.level_ch2 = cmd.el2798_write_channel_cmd.level; + break; + case 3: + state_->el2798_state.level_ch3 = cmd.el2798_write_channel_cmd.level; + break; + case 4: + state_->el2798_state.level_ch4 = cmd.el2798_write_channel_cmd.level; + break; + case 5: + state_->el2798_state.level_ch5 = cmd.el2798_write_channel_cmd.level; + break; + case 6: + state_->el2798_state.level_ch6 = cmd.el2798_write_channel_cmd.level; + break; + case 7: + state_->el2798_state.level_ch7 = cmd.el2798_write_channel_cmd.level; + break; + case 8: + state_->el2798_state.level_ch8 = cmd.el2798_write_channel_cmd.level; + break; + default: + ERROR("Bad Channel value"); + break; + } + return true; + + } else if (cmd.type == EL2798_WRITE_ALL_CHANNELS_CMD) { + state_->el2798_state.level_ch1 = + cmd.el2798_write_all_channels_cmd.channel_ch1; + + state_->el2798_state.level_ch2 = + cmd.el2798_write_all_channels_cmd.channel_ch2; + + state_->el2798_state.level_ch3 = + cmd.el2798_write_all_channels_cmd.channel_ch3; + + state_->el2798_state.level_ch4 = + cmd.el2798_write_all_channels_cmd.channel_ch4; + + state_->el2798_state.level_ch5 = + cmd.el2798_write_all_channels_cmd.channel_ch5; + + state_->el2798_state.level_ch6 = + cmd.el2798_write_all_channels_cmd.channel_ch6; + + state_->el2798_state.level_ch7 = + cmd.el2798_write_all_channels_cmd.channel_ch7; + + state_->el2798_state.level_ch8 = + cmd.el2798_write_all_channels_cmd.channel_ch8; + + } else { + ERROR("Bad EL2798 Command"); + return false; + } + return true; +} diff --git a/src/jsd/el2798_offline.h b/src/jsd/el2798_offline.h new file mode 100644 index 0000000..f1c3b74 --- /dev/null +++ b/src/jsd/el2798_offline.h @@ -0,0 +1,24 @@ +#ifndef FASTCAT_EL2798_OFFLINE_H_ +#define FASTCAT_EL2798_OFFLINE_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/el2798.h" + +namespace fastcat +{ +class El2798Offline : public El2798 +{ + public: + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; + FaultType Process() override; + bool Write(DeviceCmd& cmd) override; +}; + +} // namespace fastcat + +#endif diff --git a/src/jsd/el2828.cc b/src/jsd/el2828.cc new file mode 100644 index 0000000..9ea07aa --- /dev/null +++ b/src/jsd/el2828.cc @@ -0,0 +1,101 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el2828.h" + +// Include c then c++ libraries +#include + +#include +#include + +// Include external then project includes +#include "fastcat/yaml_parser.h" + +fastcat::El2828::El2828() +{ + MSG_DEBUG("Constructed El2828"); + + state_ = std::make_shared(); + state_->type = EL2828_STATE; +} + +bool fastcat::El2828::ConfigFromYaml(const YAML::Node& node) +{ + bool retval = ConfigFromYamlCommon(node); + jsd_set_slave_config((jsd_t*)context_, slave_id_, jsd_slave_config_); + return retval; +} + +bool fastcat::El2828::ConfigFromYamlCommon(const YAML::Node& node) +{ + if (!ParseVal(node, "name", name_)) { + return false; + } + state_->name = name_; + + jsd_slave_config_.configuration_active = true; + jsd_slave_config_.driver_type = JSD_DRIVER_TYPE_EL2828; + snprintf(jsd_slave_config_.name, JSD_NAME_LEN, "%s", name_.c_str()); + + return true; +} + +bool fastcat::El2828::Read() +{ + const jsd_el2828_state_t* jsd_state = + jsd_el2828_get_state((jsd_t*)context_, slave_id_); + + state_->el2828_state.level_ch1 = jsd_state->output[0]; + state_->el2828_state.level_ch2 = jsd_state->output[1]; + state_->el2828_state.level_ch3 = jsd_state->output[2]; + state_->el2828_state.level_ch4 = jsd_state->output[3]; + state_->el2828_state.level_ch5 = jsd_state->output[4]; + state_->el2828_state.level_ch6 = jsd_state->output[5]; + state_->el2828_state.level_ch7 = jsd_state->output[6]; + state_->el2828_state.level_ch8 = jsd_state->output[7]; + + return true; +} + +fastcat::FaultType fastcat::El2828::Process() +{ + jsd_el2828_process((jsd_t*)context_, slave_id_); + return NO_FAULT; +} + +bool fastcat::El2828::Write(DeviceCmd& cmd) +{ + // If device supports async SDO requests + AsyncSdoRetVal sdoResult = WriteAsyncSdoRequest(cmd); + if (sdoResult != SDO_RET_VAL_NOT_APPLICABLE) { + return (sdoResult == SDO_RET_VAL_SUCCESS); + } + + if (cmd.type == EL2828_WRITE_CHANNEL_CMD) { + uint8_t ch = cmd.el2828_write_channel_cmd.channel; + if (ch < 1 || ch > JSD_EL2828_NUM_CHANNELS) { + ERROR("Channel must be in range (1,%u)", JSD_EL2828_NUM_CHANNELS); + return false; + } + + jsd_el2828_write_single_channel((jsd_t*)context_, slave_id_, ch - 1, + cmd.el2828_write_channel_cmd.level); + + } else if (cmd.type == EL2828_WRITE_ALL_CHANNELS_CMD) { + uint8_t output_array[JSD_EL2828_NUM_CHANNELS] = { + cmd.el2828_write_all_channels_cmd.channel_ch1, + cmd.el2828_write_all_channels_cmd.channel_ch2, + cmd.el2828_write_all_channels_cmd.channel_ch3, + cmd.el2828_write_all_channels_cmd.channel_ch4, + cmd.el2828_write_all_channels_cmd.channel_ch5, + cmd.el2828_write_all_channels_cmd.channel_ch6, + cmd.el2828_write_all_channels_cmd.channel_ch7, + cmd.el2828_write_all_channels_cmd.channel_ch8}; + + jsd_el2828_write_all_channels((jsd_t*)context_, slave_id_, output_array); + + } else { + ERROR("Bad EL2828 Command"); + return false; + } + return true; +} diff --git a/src/jsd/el2828.h b/src/jsd/el2828.h new file mode 100644 index 0000000..4119d6e --- /dev/null +++ b/src/jsd/el2828.h @@ -0,0 +1,32 @@ +#ifndef FASTCAT_EL2828_H_ +#define FASTCAT_EL2828_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/jsd_device_base.h" +#include "jsd/jsd_el2828_pub.h" + +namespace fastcat +{ +class El2828 : public JsdDeviceBase +{ + public: + El2828(); + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; + FaultType Process() override; + bool Write(DeviceCmd& cmd) override; + + protected: + bool ConfigFromYamlCommon(const YAML::Node& node); + + private: + jsd_slave_config_t jsd_slave_config_ = {0}; +}; + +} // namespace fastcat + +#endif diff --git a/src/jsd/el2828_offline.cc b/src/jsd/el2828_offline.cc new file mode 100644 index 0000000..a76a1fc --- /dev/null +++ b/src/jsd/el2828_offline.cc @@ -0,0 +1,100 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el2828_offline.h" + +// Include c then c++ libraries +#include + +#include +#include + +// Include external then project includes +#include "fastcat/yaml_parser.h" + +bool fastcat::El2828Offline::ConfigFromYaml(const YAML::Node& node) +{ + return ConfigFromYamlCommon(node); +} + +bool fastcat::El2828Offline::Read() { return true; } + +fastcat::FaultType fastcat::El2828Offline::Process() +{ + return DeviceBase::Process(); +} + +bool fastcat::El2828Offline::Write(DeviceCmd& cmd) +{ + // If device supports async SDO requests + AsyncSdoRetVal sdoResult = WriteAsyncSdoRequest(cmd); + if (sdoResult != SDO_RET_VAL_NOT_APPLICABLE) { + return (sdoResult == SDO_RET_VAL_SUCCESS); + } + + if (cmd.type == EL2828_WRITE_CHANNEL_CMD) { + uint8_t ch = cmd.el2828_write_channel_cmd.channel; + if (ch < 1 || ch > JSD_EL2828_NUM_CHANNELS) { + ERROR("Channel must be in range (1,%u)", JSD_EL2828_NUM_CHANNELS); + return false; + } + switch (cmd.el2828_write_channel_cmd.channel) { + case 1: + state_->el2828_state.level_ch1 = cmd.el2828_write_channel_cmd.level; + break; + case 2: + state_->el2828_state.level_ch2 = cmd.el2828_write_channel_cmd.level; + break; + case 3: + state_->el2828_state.level_ch3 = cmd.el2828_write_channel_cmd.level; + break; + case 4: + state_->el2828_state.level_ch4 = cmd.el2828_write_channel_cmd.level; + break; + case 5: + state_->el2828_state.level_ch5 = cmd.el2828_write_channel_cmd.level; + break; + case 6: + state_->el2828_state.level_ch6 = cmd.el2828_write_channel_cmd.level; + break; + case 7: + state_->el2828_state.level_ch7 = cmd.el2828_write_channel_cmd.level; + break; + case 8: + state_->el2828_state.level_ch8 = cmd.el2828_write_channel_cmd.level; + break; + default: + ERROR("Bad Channel value"); + break; + } + return true; + + } else if (cmd.type == EL2828_WRITE_ALL_CHANNELS_CMD) { + state_->el2828_state.level_ch1 = + cmd.el2828_write_all_channels_cmd.channel_ch1; + + state_->el2828_state.level_ch2 = + cmd.el2828_write_all_channels_cmd.channel_ch2; + + state_->el2828_state.level_ch3 = + cmd.el2828_write_all_channels_cmd.channel_ch3; + + state_->el2828_state.level_ch4 = + cmd.el2828_write_all_channels_cmd.channel_ch4; + + state_->el2828_state.level_ch5 = + cmd.el2828_write_all_channels_cmd.channel_ch5; + + state_->el2828_state.level_ch6 = + cmd.el2828_write_all_channels_cmd.channel_ch6; + + state_->el2828_state.level_ch7 = + cmd.el2828_write_all_channels_cmd.channel_ch7; + + state_->el2828_state.level_ch8 = + cmd.el2828_write_all_channels_cmd.channel_ch8; + + } else { + ERROR("Bad EL2828 Command"); + return false; + } + return true; +} diff --git a/src/jsd/el2828_offline.h b/src/jsd/el2828_offline.h new file mode 100644 index 0000000..9d19c15 --- /dev/null +++ b/src/jsd/el2828_offline.h @@ -0,0 +1,24 @@ +#ifndef FASTCAT_EL2828_OFFLINE_H_ +#define FASTCAT_EL2828_OFFLINE_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/el2828.h" + +namespace fastcat +{ +class El2828Offline : public El2828 +{ + public: + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; + FaultType Process() override; + bool Write(DeviceCmd& cmd) override; +}; + +} // namespace fastcat + +#endif diff --git a/src/jsd/el5042.cc b/src/jsd/el5042.cc new file mode 100644 index 0000000..1656cea --- /dev/null +++ b/src/jsd/el5042.cc @@ -0,0 +1,198 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el5042.h" + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/yaml_parser.h" + +fastcat::El5042::El5042() +{ + MSG_DEBUG("Constructed El5042"); + + state_ = std::make_shared(); + state_->type = EL5042_STATE; +} + +bool fastcat::El5042::ConfigFromYaml(const YAML::Node& node) +{ + bool retval = ConfigFromYamlCommon(node); + jsd_set_slave_config((jsd_t*)context_, slave_id_, jsd_slave_config_); + return retval; +} + +bool fastcat::El5042::ConfigFromYamlCommon(const YAML::Node& node) +{ + if (!ParseVal(node, "name", name_)) { + return false; + } + state_->name = name_; + + jsd_slave_config_.configuration_active = true; + jsd_slave_config_.driver_type = JSD_DRIVER_TYPE_EL5042; + snprintf(jsd_slave_config_.name, JSD_NAME_LEN, "%s", name_.c_str()); + + YAML::Node invert_feedback_direction_node; + if (!ParseList(node, "invert_feedback_direction", invert_feedback_direction_node)) { + return false; + } + + YAML::Node disable_status_bits_node; + if (!ParseList(node, "disable_status_bits", disable_status_bits_node)) { + return false; + } + + YAML::Node invert_checksum_node; + if (!ParseList(node, "invert_checksum", invert_checksum_node)) { + return false; + } + + YAML::Node checksum_polynomial_node; + if (!ParseList(node, "checksum_polynomial", checksum_polynomial_node)) { + return false; + } + + YAML::Node supply_voltage_node; + if (!ParseList(node, "supply_voltage", supply_voltage_node)) { + return false; + } + + // Parse clock frequency array + YAML::Node clock_frequency_node; + if (!ParseList(node, "clock_frequency", clock_frequency_node)) { + return false; + } + for (auto cf = clock_frequency_node.begin(); cf != clock_frequency_node.end(); ++cf) { + clock_frequency_strings_.push_back((*cf).as()); + } + + YAML::Node gray_code_node; + if (!ParseList(node, "gray_code", gray_code_node)) { + return false; + } + + YAML::Node multiturn_bits_node; + if (!ParseList(node, "multiturn_bits", multiturn_bits_node)) { + return false; + } + + YAML::Node singleturn_bits_node; + if (!ParseList(node, "singleturn_bits", singleturn_bits_node)) { + return false; + } + + YAML::Node offset_bits_node; + if (!ParseList(node, "offset_bits", offset_bits_node)) { + return false; + } + + YAML::Node ssi_mode_node; + if (!ParseList(node, "ssi_mode", ssi_mode_node)) { + return false; + } + + // Check the right number of entries in each array + if (invert_feedback_direction_node.size() != JSD_EL5042_NUM_CHANNELS || + disable_status_bits_node.size() != JSD_EL5042_NUM_CHANNELS || + invert_checksum_node.size() != JSD_EL5042_NUM_CHANNELS || + checksum_polynomial_node.size() != JSD_EL5042_NUM_CHANNELS || + supply_voltage_node.size() != JSD_EL5042_NUM_CHANNELS || + clock_frequency_node.size() != JSD_EL5042_NUM_CHANNELS || + gray_code_node.size() != JSD_EL5042_NUM_CHANNELS || + multiturn_bits_node.size() != JSD_EL5042_NUM_CHANNELS || + singleturn_bits_node.size() != JSD_EL5042_NUM_CHANNELS || + offset_bits_node.size() != JSD_EL5042_NUM_CHANNELS || + ssi_mode_node.size() != JSD_EL5042_NUM_CHANNELS) { + return false; + } + + int ii; + for (ii = 0; ii < JSD_EL5042_NUM_CHANNELS; ii++) { + jsd_slave_config_.el5042.invert_feedback_direction[ii] = + invert_feedback_direction_node[ii].as(); + + jsd_slave_config_.el5042.disable_status_bits[ii] = + disable_status_bits_node[ii].as(); + + jsd_slave_config_.el5042.invert_checksum[ii] = + invert_checksum_node[ii].as(); + + jsd_slave_config_.el5042.checksum_polynomial[ii] = + checksum_polynomial_node[ii].as(); + + jsd_slave_config_.el5042.supply_voltage[ii] = + supply_voltage_node[ii].as(); + + + jsd_slave_config_.el5042.gray_code[ii] = + gray_code_node[ii].as(); + + jsd_slave_config_.el5042.multiturn_bits[ii] = + multiturn_bits_node[ii].as(); + + jsd_slave_config_.el5042.singleturn_bits[ii] = + singleturn_bits_node[ii].as(); + + jsd_slave_config_.el5042.offset_bits[ii] = + offset_bits_node[ii].as(); + + jsd_slave_config_.el5042.ssi_mode[ii] = + ssi_mode_node[ii].as(); + + if (!ClockFrequencyFromString(clock_frequency_strings_[ii], + jsd_slave_config_.el5042.clock_frequency[ii])) { + return false; + } + } + + return true; +} + +bool fastcat::El5042::Read() +{ + jsd_el5042_read((jsd_t*)context_, slave_id_); + + const jsd_el5042_state_t* jsd_state = + jsd_el5042_get_state((jsd_t*)context_, slave_id_); + + state_->el5042_state.position_ch1 = jsd_state->position[0]; + state_->el5042_state.warning_ch1 = jsd_state->warning[0]; + state_->el5042_state.error_ch1 = jsd_state->error[0]; + state_->el5042_state.ready_ch1 = jsd_state->ready[0]; + state_->el5042_state.position_ch2 = jsd_state->position[1]; + state_->el5042_state.warning_ch2 = jsd_state->warning[1]; + state_->el5042_state.error_ch2 = jsd_state->error[1]; + state_->el5042_state.ready_ch2 = jsd_state->ready[1]; + + return true; +} + +bool fastcat::El5042::ClockFrequencyFromString(std::string clock_frequency_string, + jsd_el5042_clock_t& clock_frequency) +{ + MSG_DEBUG("Parsing clock frequency string: %s", clock_frequency_string.c_str()); + + if (clock_frequency_string.compare("10MHz") == 0) { + clock_frequency = JSD_EL5042_10MHz; + } else if (clock_frequency_string.compare("5MHz") == 0) { + clock_frequency = JSD_EL5042_5MHz; + } else if (clock_frequency_string.compare("3_33MHz") == 0) { + clock_frequency = JSD_EL5042_3_33MHz; + } else if (clock_frequency_string.compare("2_5MHz") == 0) { + clock_frequency = JSD_EL5042_2_5MHz; + } else if (clock_frequency_string.compare("2MHz") == 0) { + clock_frequency = JSD_EL5042_2MHz; + } else if (clock_frequency_string.compare("1MHz") == 0) { + clock_frequency = JSD_EL5042_1MHz; + } else if (clock_frequency_string.compare("500KHz") == 0) { + clock_frequency = JSD_EL5042_500KHz; + } else if (clock_frequency_string.compare("250KHz") == 0) { + clock_frequency = JSD_EL5042_250KHz; + } else { + ERROR("%s is not a valid clock frequency type for EL5042 devices.", + clock_frequency_string.c_str()); + return false; + } + + return true; +} diff --git a/src/jsd/el5042.h b/src/jsd/el5042.h new file mode 100644 index 0000000..ff35af4 --- /dev/null +++ b/src/jsd/el5042.h @@ -0,0 +1,35 @@ +#ifndef FASTCAT_EL5042_H_ +#define FASTCAT_EL5042_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/jsd_device_base.h" +#include "jsd/jsd_el5042_pub.h" + +namespace fastcat +{ +class El5042 : public JsdDeviceBase +{ + public: + El5042(); + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; + + protected: + bool ConfigFromYamlCommon(const YAML::Node& node); + + bool ClockFrequencyFromString(std::string clock_frequency_string, + jsd_el5042_clock_t& clock_frequency); + + std::vector clock_frequency_strings_; + + private: + jsd_slave_config_t jsd_slave_config_{0}; +}; + +} // namespace fastcat + +#endif diff --git a/src/jsd/el5042_offline.cc b/src/jsd/el5042_offline.cc new file mode 100644 index 0000000..41d389f --- /dev/null +++ b/src/jsd/el5042_offline.cc @@ -0,0 +1,13 @@ +// Include related header (for cc files) +#include "fastcat/jsd/el5042_offline.h" + +// Include c then c++ libraries + +// Include external then project includes + +bool fastcat::El5042Offline::ConfigFromYaml(const YAML::Node& node) +{ + return ConfigFromYamlCommon(node); +} + +bool fastcat::El5042Offline::Read() { return true; } diff --git a/src/jsd/el5042_offline.h b/src/jsd/el5042_offline.h new file mode 100644 index 0000000..1d6e9c3 --- /dev/null +++ b/src/jsd/el5042_offline.h @@ -0,0 +1,22 @@ +#ifndef FASTCAT_EL5042_OFFLINE_H_ +#define FASTCAT_EL5042_OFFLINE_H_ + +// Include related header (for cc files) + +// Include c then c++ libraries + +// Include external then project includes +#include "fastcat/jsd/el5042.h" + +namespace fastcat +{ +class El5042Offline : public El5042 +{ + public: + bool ConfigFromYaml(const YAML::Node& node) override; + bool Read() override; +}; + +} // namespace fastcat + +#endif \ No newline at end of file diff --git a/src/manager.cc b/src/manager.cc index dd3ab94..c391613 100644 --- a/src/manager.cc +++ b/src/manager.cc @@ -37,6 +37,10 @@ #include "fastcat/jsd/el2124_offline.h" #include "fastcat/jsd/el2809.h" #include "fastcat/jsd/el2809_offline.h" +#include "fastcat/jsd/el2828.h" +#include "fastcat/jsd/el2828_offline.h" +#include "fastcat/jsd/el2798.h" +#include "fastcat/jsd/el2798_offline.h" #include "fastcat/jsd/el3104.h" #include "fastcat/jsd/el3104_offline.h" #include "fastcat/jsd/el3162.h" @@ -51,6 +55,8 @@ #include "fastcat/jsd/el3602_offline.h" #include "fastcat/jsd/el4102.h" #include "fastcat/jsd/el4102_offline.h" +#include "fastcat/jsd/el5042.h" +#include "fastcat/jsd/el5042_offline.h" #include "fastcat/jsd/gold_actuator.h" #include "fastcat/jsd/gold_actuator_offline.h" #include "fastcat/jsd/ild1900.h" @@ -462,6 +468,12 @@ bool fastcat::Manager::ConfigJSDBusFromYaml(const YAML::Node& node, } else if (0 == device_class.compare("El2809")) { device = std::make_shared(); + } else if (0 == device_class.compare("El2828")) { + device = std::make_shared(); + + } else if (0 == device_class.compare("El2798")) { + device = std::make_shared(); + } else if (0 == device_class.compare("El4102")) { device = std::make_shared(); @@ -479,6 +491,9 @@ bool fastcat::Manager::ConfigJSDBusFromYaml(const YAML::Node& node, } else if (0 == device_class.compare("El3318")) { device = std::make_shared(); + + } else if (0 == device_class.compare("El5042")) { + device = std::make_shared(); } else if (0 == device_class.compare("Ild1900")) { device = std::make_shared(); @@ -539,7 +554,7 @@ bool fastcat::Manager::ConfigJSDBusFromYaml(const YAML::Node& node, jsd_device_list_.push_back(jsdDevice); } - return jsd_init(jsd, ifname.c_str(), enable_ar); + return jsd_init(jsd, ifname.c_str(), enable_ar, 1e6 / target_loop_rate_hz_); } bool fastcat::Manager::ConfigFastcatBusFromYaml(const YAML::Node& node, @@ -692,6 +707,12 @@ bool fastcat::Manager::ConfigOfflineBusFromYaml(const YAML::Node& node, } else if (0 == device_class.compare("El2809")) { device = std::make_shared(); + } else if (0 == device_class.compare("El2828")) { + device = std::make_shared(); + + } else if (0 == device_class.compare("El2798")) { + device = std::make_shared(); + } else if (0 == device_class.compare("El3208")) { device = std::make_shared(); @@ -715,8 +736,11 @@ bool fastcat::Manager::ConfigOfflineBusFromYaml(const YAML::Node& node, } else if (0 == device_class.compare("El1008")) { device = std::make_shared(); + + } else if (0 == device_class.compare("El5042")) { + device = std::make_shared(); - }else if (0 == device_class.compare("Ild1900")) { + } else if (0 == device_class.compare("Ild1900")) { device = std::make_shared(); } else if (0 == device_class.compare("GoldActuator")) {