#pragma once #include #ifdef __cplusplus extern "C" { #endif // The macro to get offset for parameter in the appropriate structure #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) #define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1)) // Discrete offset macro #define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1)) #define STR(fieldname) ((const char*)( fieldname )) // Options can be used as bit masks or parameter limits #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val } // BigEndian 32bit swap // just swap the two 16 bit registers since the two bytes in each // register are already swapped (BigEndian) as per modbus standard. # define __beswap_32(x) \ (__extension__ \ ({ uint32_t __bsx = (x); \ ((((__bsx) >> 16) & 0xffff) | (((__bsx) & 0xffff) << 16)); })) // The function to get pointer to parameter storage (instance) according to parameter description table static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor) { assert(param_descriptor != NULL); void* instance_ptr = NULL; if (param_descriptor->param_offset != 0) { switch(param_descriptor->mb_param_type) { case MB_PARAM_HOLDING: instance_ptr = ((void*)&holding_reg_params + param_descriptor->param_offset - 1); break; case MB_PARAM_INPUT: instance_ptr = ((void*)&input_reg_params + param_descriptor->param_offset - 1); break; case MB_PARAM_COIL: instance_ptr = ((void*)&coil_reg_params + param_descriptor->param_offset - 1); break; case MB_PARAM_DISCRETE: instance_ptr = ((void*)&discrete_reg_params + param_descriptor->param_offset - 1); break; default: instance_ptr = NULL; break; } } else { ESP_LOGE("MB_UTILS", "Wrong parameter offset for CID #%d", param_descriptor->cid); assert(instance_ptr != NULL); } return instance_ptr; } #ifdef __cplusplus } #endif