#include "periph28335.h" #include #include "set_crc.h" typedef struct { const char *project; const char *commands[PERIPH28335_COMMAND_COUNT]; } periph28335_project_t; static const periph28335_project_t projects[] = { { "По умолчанию", { "Test", "Def", "Save", "Load", "Calibr", "Calcul", "Secret", "Light", "Raw", "-", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "23470", { "Test", "Def", "Save", "Load", "Calibr", "Read", "Secret", "-", "-", "-", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "23550", { "Test", "Def", "Save", "Load", "Calibr", "Read", "Secret", "Send", "-", "-", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "23550.2", { "Test", "Def", "Save", "Load", "Calibr", "Calcul", "Secret", "Send", "Raw", "Beep", "", "", "", "", "Log", "Reset", "Nothing at all" } }, { "ICE 22220.1-3", { "Test", "Zero", "Save", "Def", "Calibr", "Read", "ExtLamp", "ExtLite", "-", "-", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "ICE 22220.4-5", { "Test", "Def", "Save", "Load", "Raw", "Read", "ExtLamp", "ExtLite", "No log", "-", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "Бальзам 161", { "Test", "Zero", "Save", "Def", "Calibr", "Clbr 400", "Stop", "Start", "Init", "Secret", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "Бальзам 162", { "Test", "Def", "Save", "Load", "Calibr", "Secret", "Stop", "Start", "Init", "Tune", "-", "-", "-", "-", "-", "Reset", "Nothing at all" } }, { "Бальзам 163", { "Test", "Def", "Save", "Load", "Calibr", "Calcul", "Stop", "Start", "Init", "Tune", "Secret", "-", "-", "-", "-", "Reset", "Nothing at all" } } }; static void put_be16(uint8_t *output, uint16_t value) { output[0] = (uint8_t)(value >> 8); output[1] = (uint8_t)value; } static uint16_t get_be16(const uint8_t *input) { return (uint16_t)(((uint16_t)input[0] << 8) | input[1]); } uint16_t periph28335_crc16_modbus(const uint8_t *data, size_t size) { return set_crc16_modbus(data, size); } size_t periph28335_append_crc(const uint8_t *payload, size_t payload_size, uint8_t *output, size_t output_size) { uint16_t crc; if ((output == NULL) || ((payload == NULL) && (payload_size != 0U)) || (payload_size > output_size) || (output_size - payload_size < 2U)) { return 0U; } if (payload_size != 0U) memcpy(output, payload, payload_size); crc = periph28335_crc16_modbus(payload, payload_size); output[payload_size] = (uint8_t)crc; output[payload_size + 1U] = (uint8_t)(crc >> 8); return payload_size + 2U; } size_t periph28335_build_read_registers( uint8_t controller, uint16_t start, uint16_t count, uint8_t *output, size_t output_size) { uint8_t payload[6]; if ((count == 0U) || (count > PERIPH28335_REGISTER_COUNT) || (start >= PERIPH28335_REGISTER_COUNT) || ((uint32_t)start + count > PERIPH28335_REGISTER_COUNT)) return 0U; payload[0] = controller; payload[1] = 3U; put_be16(&payload[2], start); put_be16(&payload[4], count); return periph28335_append_crc(payload, sizeof payload, output, output_size); } size_t periph28335_build_write_register( uint8_t controller, uint16_t address, uint16_t value, uint8_t *output, size_t output_size) { uint8_t payload[6]; if (address >= PERIPH28335_REGISTER_COUNT) return 0U; payload[0] = controller; payload[1] = 6U; put_be16(&payload[2], address); put_be16(&payload[4], value); return periph28335_append_crc(payload, sizeof payload, output, output_size); } size_t periph28335_build_command( uint8_t controller, uint8_t command_index, uint8_t *output, size_t output_size) { uint16_t value; if (command_index >= PERIPH28335_COMMAND_COUNT) return 0U; value = command_index < 16U ? (uint16_t)(1UL << command_index) : 0U; return periph28335_build_write_register( controller, PERIPH28335_REGISTER_COUNT - 1U, value, output, output_size); } size_t periph28335_expected_read_response_size(uint16_t count) { return (count >= 1U && count <= PERIPH28335_REGISTER_COUNT) ? (size_t)count * 2U + 5U : 0U; } int periph28335_decode_read_response( const uint8_t *data, size_t size, uint8_t controller, uint16_t count, uint16_t *output, size_t output_count) { size_t expected = periph28335_expected_read_response_size(count); uint16_t crc; size_t index; if ((data == NULL) || (output == NULL)) return PERIPH28335_ERROR_ARGUMENT; if (expected == 0U) return PERIPH28335_ERROR_RANGE; if (size != expected) return PERIPH28335_ERROR_LENGTH; if (output_count < count) return PERIPH28335_ERROR_CAPACITY; crc = periph28335_crc16_modbus(data, size - 2U); if ((data[size - 2U] != (uint8_t)crc) || (data[size - 1U] != (uint8_t)(crc >> 8))) { return PERIPH28335_ERROR_CRC; } if ((data[0] != controller) || (data[1] != 3U) || (data[2] != (uint8_t)(count * 2U))) { return PERIPH28335_ERROR_HEADER; } for (index = 0U; index < count; ++index) { output[index] = get_be16(&data[3U + index * 2U]); } return PERIPH28335_OK; } int periph28335_validate_write_response( const uint8_t *response, size_t response_size, const uint8_t *request, size_t request_size) { uint16_t crc; if ((response == NULL) || (request == NULL)) return PERIPH28335_ERROR_ARGUMENT; if ((response_size != PERIPH28335_REQUEST_SIZE) || (request_size != PERIPH28335_REQUEST_SIZE)) return PERIPH28335_ERROR_LENGTH; crc = periph28335_crc16_modbus(response, response_size - 2U); if ((response[response_size - 2U] != (uint8_t)crc) || (response[response_size - 1U] != (uint8_t)(crc >> 8))) { return PERIPH28335_ERROR_CRC; } return memcmp(response, request, PERIPH28335_REQUEST_SIZE) == 0 ? PERIPH28335_OK : PERIPH28335_ERROR_HEADER; } size_t periph28335_project_count(void) { return sizeof projects / sizeof projects[0]; } const char *periph28335_project_name(size_t project_index) { return project_index < periph28335_project_count() ? projects[project_index].project : NULL; } const char *periph28335_command_name(size_t project_index, size_t command_index) { return project_index < periph28335_project_count() && command_index < PERIPH28335_COMMAND_COUNT ? projects[project_index].commands[command_index] : NULL; }