From a311e31ba4734277b60b68ca378b6ea7b0db1667 Mon Sep 17 00:00:00 2001 From: prestonr Date: Wed, 23 Oct 2024 11:37:05 -0700 Subject: [PATCH] Add el2798 driver to jsd --- src/CMakeLists.txt | 1 + src/jsd.c | 9 +++++ src/jsd_el2798.c | 84 ++++++++++++++++++++++++++++++++++++++++++ src/jsd_el2798.h | 30 +++++++++++++++ src/jsd_el2798_pub.h | 56 ++++++++++++++++++++++++++++ src/jsd_el2798_types.h | 31 ++++++++++++++++ src/jsd_types.h | 4 ++ 7 files changed, 215 insertions(+) create mode 100644 src/jsd_el2798.c create mode 100644 src/jsd_el2798.h create mode 100644 src/jsd_el2798_pub.h create mode 100644 src/jsd_el2798_types.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 617e466..0b2216b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(jsd-lib STATIC jsd_el3208.c jsd_el2124.c jsd_el2809.c + jsd_el2798.c jsd_egd.c jsd_el3356.c jsd_jed0101.c diff --git a/src/jsd.c b/src/jsd.c index 3b0e9b4..b83514b 100644 --- a/src/jsd.c +++ b/src/jsd.c @@ -11,6 +11,7 @@ #include "jsd/jsd_el1008.h" #include "jsd/jsd_el2124.h" #include "jsd/jsd_el2809.h" +#include "jsd/jsd_el2798.h" #include "jsd/jsd_el3104.h" #include "jsd/jsd_el3162.h" #include "jsd/jsd_el3202.h" @@ -373,6 +374,8 @@ const char* jsd_driver_type_to_string(jsd_driver_type_t driver_type) { return "JSD_DRIVER_TYPE_EL2124"; case JSD_DRIVER_TYPE_EL2809: return "JSD_DRIVER_TYPE_EL2809"; + case JSD_DRIVER_TYPE_EL2798: + return "JSD_DRIVER_TYPE_EL2798"; case JSD_DRIVER_TYPE_EL3104: return "JSD_DRIVER_TYPE_EL3104"; case JSD_DRIVER_TYPE_EL3162: @@ -479,6 +482,9 @@ bool jsd_driver_is_compatible_with_product_code(jsd_driver_type_t driver_type, case JSD_DRIVER_TYPE_EL2809: is_compatible = jsd_el2809_product_code_is_compatible(product_code); break; + case JSD_DRIVER_TYPE_EL2798: + is_compatible = jsd_el2798_product_code_is_compatible(product_code); + break; case JSD_DRIVER_TYPE_EGD: is_compatible = jsd_egd_product_code_is_compatible(product_code); break; @@ -549,6 +555,9 @@ bool jsd_init_single_device(jsd_t* self, uint16_t slave_id) { case JSD_DRIVER_TYPE_EL2809: return jsd_el2809_init(self, slave_id); break; + case JSD_DRIVER_TYPE_EL2798: + return jsd_el2798_init(self, slave_id); + break; case JSD_DRIVER_TYPE_EL2124: return jsd_el2124_init(self, slave_id); break; diff --git a/src/jsd_el2798.c b/src/jsd_el2798.c new file mode 100644 index 0000000..6c801c6 --- /dev/null +++ b/src/jsd_el2798.c @@ -0,0 +1,84 @@ +#include "jsd/jsd_el2798.h" + +#include + +#include "jsd/jsd_sdo.h" + +/**************************************************** + * Public functions + ****************************************************/ + +/** + * @brief RxPDO struct used to set device command data in SOEM IOmap + */ +typedef struct __attribute__((__packed__)) { + uint8_t flags; +} jsd_el2798_rxpdo_t; + +const jsd_el2798_state_t* jsd_el2798_get_state(jsd_t* self, uint16_t slave_id) { + assert(self); + assert(jsd_el2798_product_code_is_compatible( + self->ecx_context.slavelist[slave_id].eep_id)); + + return &self->slave_states[slave_id].el2798; +} + +void jsd_el2798_process(jsd_t* self, uint16_t slave_id) { + assert(self); + assert(jsd_el2798_product_code_is_compatible( + self->ecx_context.slavelist[slave_id].eep_id)); + + jsd_el2798_rxpdo_t* rxpdo = + (jsd_el2798_rxpdo_t*)self->ecx_context.slavelist[slave_id].outputs; + + int ch; + for (ch = 0; ch < JSD_EL2798_NUM_CHANNELS; ch++) { + uint8_t output = self->slave_states[slave_id].el2798.output[ch]; + + if (output > 0) { + rxpdo->flags |= 0x01 << ch; + } else { + rxpdo->flags &= ~(0x01 << ch); + } + } +} + +void jsd_el2798_write_single_channel(jsd_t* self, uint16_t slave_id, + uint8_t channel, uint8_t output) { + assert(self); + assert(jsd_el2798_product_code_is_compatible( + self->ecx_context.slavelist[slave_id].eep_id)); + + self->slave_states[slave_id].el2798.output[channel] = output; +} + +void jsd_el2798_write_all_channels(jsd_t* self, uint16_t slave_id, + uint8_t output[JSD_EL2798_NUM_CHANNELS]) { + int ch; + for (ch = 0; ch < JSD_EL2798_NUM_CHANNELS; ch++) { + jsd_el2798_write_single_channel(self, slave_id, ch, output[ch]); + } +} + +/**************************************************** + * Private functions + ****************************************************/ + +bool jsd_el2798_init(jsd_t* self, uint16_t slave_id) { + assert(self); + assert(jsd_el2798_product_code_is_compatible( + self->ecx_context.slavelist[slave_id].eep_id)); + assert(self->ecx_context.slavelist[slave_id].eep_man == + JSD_BECKHOFF_VENDOR_ID); + + jsd_slave_config_t* config = &self->slave_configs[slave_id]; + + // no PO2SO callback for 2798 devices, so set the success flag now + config->PO2SO_success = true; + + return true; +} + +bool jsd_el2798_product_code_is_compatible(uint32_t product_code) { + return product_code == JSD_EL2798_PRODUCT_CODE; +} diff --git a/src/jsd_el2798.h b/src/jsd_el2798.h new file mode 100644 index 0000000..2a536c0 --- /dev/null +++ b/src/jsd_el2798.h @@ -0,0 +1,30 @@ +#ifndef JSD_EL2798_H +#define JSD_EL2798_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jsd/jsd_el2798_pub.h" + +/** @brief Initializes el2798 + * + * @param self pointer JSD context + * @param slave_id index of device on EtherCAT bus + * @return true on success, false on failure + */ +bool jsd_el2798_init(jsd_t* self, uint16_t slave_id); + +/** + * @brief Checks whether a product code is compatible with EL2798. + * + * @param product_code The product code to be checked + * @return True if the product code is compatible, false otherwise. + */ +bool jsd_el2798_product_code_is_compatible(uint32_t product_code); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/jsd_el2798_pub.h b/src/jsd_el2798_pub.h new file mode 100644 index 0000000..6660e58 --- /dev/null +++ b/src/jsd_el2798_pub.h @@ -0,0 +1,56 @@ +#ifndef JSD_EL2798_PUB_H +#define JSD_EL2798_PUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jsd/jsd_el2798_types.h" +#include "jsd/jsd_pub.h" + +/** + * @brief Read the EL2798 State + * + * Note: this device does not actually provide PDO feedback on state, + * This function reads back the cmd sent to the EL2798 device + * + * @param self pointer to JSD context + * @param slave_id id of EL2798 device + * @return Pointer to EL2798 device state + */ +const jsd_el2798_state_t* jsd_el2798_get_state(jsd_t* self, uint16_t slave_id); + +/** + * @brief process loop required for proper device function + * + * @param self pointer to JSD context + * @param slave_id id of EL2798 device + */ +void jsd_el2798_process(jsd_t* self, uint16_t slave_id); + +/** + * @brief Sets a specified channel level + * + * @param self pointer to JSD context + * @param slave_id id of EL2798 device + * @param channel specified device channel to command + * @param output command level (0 or 1) + */ +void jsd_el2798_write_single_channel(jsd_t* self, uint16_t slave_id, + uint8_t channel, uint8_t output); + +/** + * @brief Sets all channel levels + * + * @param self pointer to JSD context + * @param slave_id id of EL2798 device + * @param output command level (0 or 1) + */ +void jsd_el2798_write_all_channels(jsd_t* self, uint16_t slave_id, + uint8_t output[JSD_EL2798_NUM_CHANNELS]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/jsd_el2798_types.h b/src/jsd_el2798_types.h new file mode 100644 index 0000000..b17b1e1 --- /dev/null +++ b/src/jsd_el2798_types.h @@ -0,0 +1,31 @@ +#ifndef JSD_EL2798_TYPES_H +#define JSD_EL2798_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jsd/jsd_common_device_types.h" + +#define JSD_EL2798_PRODUCT_CODE (uint32_t)0x0AEE3052 + +#define JSD_EL2798_NUM_CHANNELS 8 + +/** + * @brief EL2798 State Data + */ +typedef struct { + uint8_t output[JSD_EL2798_NUM_CHANNELS]; ///< digital output level (0 or 1) +} jsd_el2798_state_t; + +/** + * @brief EL2798 device configuration + */ +typedef struct { +} jsd_el2798_config_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/jsd_types.h b/src/jsd_types.h index 0b94d6f..fa25c8a 100644 --- a/src/jsd_types.h +++ b/src/jsd_types.h @@ -14,6 +14,7 @@ extern "C" { #include "jsd/jsd_el1008_types.h" #include "jsd/jsd_el2124_types.h" #include "jsd/jsd_el2809_types.h" +#include "jsd/jsd_el2798_types.h" #include "jsd/jsd_el3104_types.h" #include "jsd/jsd_el3162_types.h" #include "jsd/jsd_el3202_types.h" @@ -35,6 +36,7 @@ typedef enum { JSD_DRIVER_TYPE_EL1008, JSD_DRIVER_TYPE_EL2124, JSD_DRIVER_TYPE_EL2809, + JSD_DRIVER_TYPE_EL2798, JSD_DRIVER_TYPE_EL3104, JSD_DRIVER_TYPE_EL3162, JSD_DRIVER_TYPE_EL3202, @@ -60,6 +62,7 @@ typedef struct { jsd_el3208_config_t el3208; jsd_el2124_config_t el2124; jsd_el2809_config_t el2809; + jsd_el2798_config_t el2798; jsd_egd_config_t egd; jsd_el3356_config_t el3356; jsd_jed0101_config_t jed0101; @@ -85,6 +88,7 @@ typedef struct { jsd_el3208_state_t el3208; jsd_el2124_state_t el2124; jsd_el2809_state_t el2809; + jsd_el2798_state_t el2798; jsd_egd_private_state_t egd; jsd_el3356_state_t el3356; jsd_jed0101_state_t jed0101;