
#ifndef ETHERCAT_SLAVE_SOE_H
#define ETHERCAT_SLAVE_SOE_H

#include "../ethercat_types.h"
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef DYNAMIC_LOAD

BOOL     dx_soe_read(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                  uint8_t element_flags, uint16_t idn,
                  char** data, int* data_size, int timeout);
BOOL     dx_soe_write(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                   uint8_t element_flags, uint16_t idn,
                   const char* data, int data_size, int timeout);
BOOL     dx_soe_read_attributes(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                            uint16_t idn, uint32_t* attributes, int timeout);

BOOL     dx_soe_read_name(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                      uint16_t idn, char** name, int* name_length, int timeout);

BOOL     dx_soe_read_unit(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                      uint16_t idn, char** unit, int* unit_length, int timeout);

BOOL     dx_soe_read_idn_list(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                         uint16_t** idn_list, int* list_count, int timeout);

BOOL     dx_soe_read_min_max(uint16_t master_index, uint16_t slave, uint8_t drive_no,
                        uint16_t idn, char** min_value, int* min_size,
                        char** max_value, int* max_size, int timeout);

#endif

#define SOE_ELEM_NONE         ((uint8_t)0x00)
#define SOE_ELEM_DATA_STATUS  ((uint8_t)0x01)
#define SOE_ELEM_NAME         ((uint8_t)0x02)
#define SOE_ELEM_ATTRIBUTE    ((uint8_t)0x04)
#define SOE_ELEM_UNIT         ((uint8_t)0x08)
#define SOE_ELEM_MIN          ((uint8_t)0x10)
#define SOE_ELEM_MAX          ((uint8_t)0x20)
#define SOE_ELEM_VALUE        ((uint8_t)0x40)
#define SOE_ELEM_DEFAULT      ((uint8_t)0x80)

static inline uint16_t soe_idn_encode(int is_standard, uint8_t parameter_set, uint16_t data_block)
{
    uint16_t idn = 0;
    if (!is_standard) idn |= 0x8000;
    idn |= (uint16_t)(((uint16_t)(parameter_set & 0x07)) << 12);
    idn |= (uint16_t)(data_block & 0x0FFF);
    return idn;
}

static inline void soe_idn_decode(uint16_t idn,
                                         int* is_standard,
                                         uint8_t* parameter_set,
                                         uint16_t* data_block)
{
    if (is_standard)   *is_standard   = ((idn & 0x8000) == 0) ? 1 : 0;
    if (parameter_set) *parameter_set = (uint8_t)((idn >> 12) & 0x07);
    if (data_block)    *data_block    = (uint16_t)(idn & 0x0FFF);
}

#ifdef __cplusplus
}
#endif

#endif
