162 lines
6.4 KiB
C
162 lines
6.4 KiB
C
#include "periph28335.h"
|
|
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|