Move PM35 protocol into shared C core
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "pcan_crc.h"
|
||||
#include "balsam_can.h"
|
||||
#include "periph28335.h"
|
||||
#include "pcan_frame.h"
|
||||
#include "pcan_id.h"
|
||||
#include "gui_frame.h"
|
||||
@@ -88,6 +89,79 @@ size_t pcan_abi_balsam_register_name(uint8_t device, uint16_t address,
|
||||
return balsam_can_register_name(device, address, output, output_size);
|
||||
}
|
||||
|
||||
uint16_t pcan_abi_periph28335_crc16(const uint8_t *data, size_t size)
|
||||
{
|
||||
return periph28335_crc16_modbus(data, size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_append_crc(
|
||||
const uint8_t *payload, size_t payload_size,
|
||||
uint8_t *output, size_t output_size)
|
||||
{
|
||||
return periph28335_append_crc(payload, payload_size, output, output_size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_build_read(
|
||||
uint8_t controller, uint16_t start, uint16_t count,
|
||||
uint8_t *output, size_t output_size)
|
||||
{
|
||||
return periph28335_build_read_registers(
|
||||
controller, start, count, output, output_size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_build_write(
|
||||
uint8_t controller, uint16_t address, uint16_t value,
|
||||
uint8_t *output, size_t output_size)
|
||||
{
|
||||
return periph28335_build_write_register(
|
||||
controller, address, value, output, output_size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_build_command(
|
||||
uint8_t controller, uint8_t command_index,
|
||||
uint8_t *output, size_t output_size)
|
||||
{
|
||||
return periph28335_build_command(
|
||||
controller, command_index, output, output_size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_expected_read_size(uint16_t count)
|
||||
{
|
||||
return periph28335_expected_read_response_size(count);
|
||||
}
|
||||
|
||||
int pcan_abi_periph28335_decode_read(
|
||||
const uint8_t *data, size_t size, uint8_t controller, uint16_t count,
|
||||
uint16_t *output, size_t output_count)
|
||||
{
|
||||
return periph28335_decode_read_response(
|
||||
data, size, controller, count, output, output_count);
|
||||
}
|
||||
|
||||
int pcan_abi_periph28335_validate_write(
|
||||
const uint8_t *response, size_t response_size,
|
||||
const uint8_t *request, size_t request_size)
|
||||
{
|
||||
return periph28335_validate_write_response(
|
||||
response, response_size, request, request_size);
|
||||
}
|
||||
|
||||
size_t pcan_abi_periph28335_project_count(void)
|
||||
{
|
||||
return periph28335_project_count();
|
||||
}
|
||||
|
||||
const char *pcan_abi_periph28335_project_name(size_t project_index)
|
||||
{
|
||||
return periph28335_project_name(project_index);
|
||||
}
|
||||
|
||||
const char *pcan_abi_periph28335_command_name(
|
||||
size_t project_index, size_t command_index)
|
||||
{
|
||||
return periph28335_command_name(project_index, command_index);
|
||||
}
|
||||
|
||||
size_t pcan_abi_frame_encode(uint8_t sequence, uint8_t flags,
|
||||
uint32_t can_id, const uint8_t *data, uint8_t dlc,
|
||||
uint8_t *output, size_t output_size)
|
||||
|
||||
171
c/set-protocol/src/periph28335.c
Normal file
171
c/set-protocol/src/periph28335.c
Normal file
@@ -0,0 +1,171 @@
|
||||
#include "periph28335.h"
|
||||
|
||||
#include <string.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)
|
||||
{
|
||||
uint16_t crc = 0xFFFFU;
|
||||
size_t index;
|
||||
uint8_t bit;
|
||||
if ((data == NULL) && (size != 0U)) return 0U;
|
||||
for (index = 0U; index < size; ++index) {
|
||||
crc ^= data[index];
|
||||
for (bit = 0U; bit < 8U; ++bit) {
|
||||
crc = (crc & 1U) != 0U
|
||||
? (uint16_t)((crc >> 1) ^ 0xA001U)
|
||||
: (uint16_t)(crc >> 1);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user