Добавить общий API старого CAN terminal
This commit is contained in:
182
c/set-protocol/src/balsam_can.c
Normal file
182
c/set-protocol/src/balsam_can.c
Normal file
@@ -0,0 +1,182 @@
|
||||
#include "balsam_can.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static uint16_t get_be16(const uint8_t *data)
|
||||
{
|
||||
return (uint16_t)(((uint16_t)data[0] << 8) | data[1]);
|
||||
}
|
||||
|
||||
static size_t copy_name(const char *name, char *output, size_t output_size)
|
||||
{
|
||||
size_t length = strlen(name);
|
||||
if ((output != NULL) && (output_size != 0U)) {
|
||||
size_t copied = length < output_size - 1U ? length : output_size - 1U;
|
||||
memcpy(output, name, copied);
|
||||
output[copied] = '\0';
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static size_t indexed_name(const char *prefix, unsigned index,
|
||||
char *output, size_t output_size)
|
||||
{
|
||||
int length;
|
||||
if ((output == NULL) || (output_size == 0U)) {
|
||||
char scratch[64];
|
||||
length = snprintf(scratch, sizeof scratch, "%s %u", prefix, index);
|
||||
} else {
|
||||
length = snprintf(output, output_size, "%s %u", prefix, index);
|
||||
}
|
||||
return length > 0 ? (size_t)length : 0U;
|
||||
}
|
||||
|
||||
int balsam_can_is_id(uint32_t can_id)
|
||||
{
|
||||
uint32_t relative = (can_id & 0x1FFFFFFFUL) - BALSAM_CAN_BASE_ID;
|
||||
return relative < BALSAM_CAN_NODE_COUNT
|
||||
|| (relative >= BALSAM_CAN_DATA_OFFSET
|
||||
&& relative < BALSAM_CAN_DATA_OFFSET + BALSAM_CAN_NODE_COUNT);
|
||||
}
|
||||
|
||||
int balsam_can_decode(uint32_t can_id, const uint8_t *data, size_t size,
|
||||
balsam_can_frame_t *output)
|
||||
{
|
||||
uint32_t relative;
|
||||
uint16_t header;
|
||||
if ((data == NULL) || (output == NULL)) return -1;
|
||||
can_id &= 0x1FFFFFFFUL;
|
||||
if (!balsam_can_is_id(can_id)) return 0;
|
||||
if (size != BALSAM_CAN_DLC) return -2;
|
||||
|
||||
relative = can_id - BALSAM_CAN_BASE_ID;
|
||||
output->direction = relative >= BALSAM_CAN_DATA_OFFSET
|
||||
? BALSAM_CAN_FROM_NODE : BALSAM_CAN_TO_NODE;
|
||||
output->device = (uint8_t)((relative & 0x0FU) + 1U);
|
||||
header = get_be16(data);
|
||||
output->present_mask = (uint8_t)((header >> 13) & 0x07U);
|
||||
output->start_address = (uint16_t)(header & 0x1FFFU);
|
||||
output->values[0] = get_be16(&data[2]);
|
||||
output->values[1] = get_be16(&data[4]);
|
||||
output->values[2] = get_be16(&data[6]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *balsam_can_device_name(uint8_t device)
|
||||
{
|
||||
static const char *const names[BALSAM_CAN_NODE_COUNT] = {
|
||||
"Трансформатор 1", "Трансформатор 2", "Силовой блок 1",
|
||||
"Силовой блок 2", "УМП 1", "УМП 2", "Двигатель", "ВЭП",
|
||||
"Задатчик", "Узел 10", "Узел 11", "Узел 12", "Терминал"
|
||||
};
|
||||
return (device >= 1U && device <= BALSAM_CAN_NODE_COUNT)
|
||||
? names[device - 1U] : "Неизвестный узел";
|
||||
}
|
||||
|
||||
size_t balsam_can_register_name(uint8_t device, uint16_t address,
|
||||
char *output, size_t output_size)
|
||||
{
|
||||
if ((device == 1U || device == 2U) && address < 20U)
|
||||
return indexed_name("Диагностика T°", address + 1U, output, output_size);
|
||||
if ((device == 1U || device == 2U) && address >= 0x18U && address <= 0x2BU)
|
||||
return indexed_name("Показания T°", address - 0x17U, output, output_size);
|
||||
if ((device == 1U || device == 2U) && address >= 0x30U && address <= 0x43U)
|
||||
return indexed_name("Аварийная уставка T°", address - 0x2FU, output, output_size);
|
||||
if ((device == 1U || device == 2U) && address >= 0x48U && address <= 0x5BU)
|
||||
return indexed_name("Предупредительная уставка T°", address - 0x47U, output, output_size);
|
||||
|
||||
if ((device == 3U || device == 4U) && address < 16U)
|
||||
return indexed_name("Диагностика T°", address + 1U, output, output_size);
|
||||
if ((device == 3U || device == 4U) && address >= 0x18U && address <= 0x27U)
|
||||
return indexed_name("Показания T°", address - 0x17U, output, output_size);
|
||||
if ((device == 3U || device == 4U) && address == 0x28U)
|
||||
return copy_name("Действующее Uвх1", output, output_size);
|
||||
if ((device == 3U || device == 4U) && address == 0x29U)
|
||||
return copy_name("Амплитудное Uвх1", output, output_size);
|
||||
if ((device == 3U || device == 4U) && address == 0x2AU)
|
||||
return copy_name("Действующее Uвх2", output, output_size);
|
||||
if ((device == 3U || device == 4U) && address == 0x2BU)
|
||||
return copy_name("Амплитудное Uвх2", output, output_size);
|
||||
|
||||
if ((device == 5U || device == 6U) && address == 0U)
|
||||
return copy_name("Диагностика Utr a", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 1U)
|
||||
return copy_name("Диагностика Utr c", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 2U)
|
||||
return copy_name("Диагностика Itr a", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 3U)
|
||||
return copy_name("Диагностика Itr c", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x18U)
|
||||
return copy_name("Действующее Utr", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x19U)
|
||||
return copy_name("Амплитудное Utr", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x1AU)
|
||||
return copy_name("Действующее Itr", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x1BU)
|
||||
return copy_name("Амплитудное Itr", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x1CU)
|
||||
return copy_name("Ток СИФУ, задание (mA*10)", output, output_size);
|
||||
if ((device == 5U || device == 6U) && address == 0x1DU)
|
||||
return copy_name("Ток СИФУ, обратная связь (mA*10)", output, output_size);
|
||||
|
||||
if (device == 7U && address < 8U)
|
||||
return indexed_name("Диагностика T°", address + 1U, output, output_size);
|
||||
if (device == 7U && address >= 0x18U && address <= 0x1FU)
|
||||
return indexed_name("Показания T°", address - 0x17U, output, output_size);
|
||||
|
||||
if (device == 8U) {
|
||||
static const char *const vep_names[] = {
|
||||
"Диагностика 380В Ф1", "Диагностика 380В Ф2",
|
||||
"Диагностика 31В Ф1", "Диагностика 31В Ф2",
|
||||
"Диагностика 31В UC1", "Диагностика 31В UC2",
|
||||
"Диагностика 24В ПУ", "Диагностика 27В ФА",
|
||||
"Диагностика 24В ПК", "Диагностика 15В ДР",
|
||||
"Диагностика +24В ДТ", "Диагностика -24В ДТ",
|
||||
"Диагностика 24В ПМУ", "Диагностика T° 1", "Диагностика T° 2"
|
||||
};
|
||||
static const char *const vep_values[] = {
|
||||
"Показания 380В Ф1", "Показания 380В Ф2", "Показания 31В Ф1",
|
||||
"Показания 31В Ф2", "Показания 31В UC1", "Показания 31В UC2",
|
||||
"Показания 24В ПУ", "Показания 27В ФА", "Показания 24В ПК",
|
||||
"Показания 15В ДР", "Показания +24В ДТ", "Показания -24В ДТ",
|
||||
"Показания 24В ПМУ", "Показания T° 1", "Показания T° 2"
|
||||
};
|
||||
if (address < sizeof vep_names / sizeof vep_names[0])
|
||||
return copy_name(vep_names[address], output, output_size);
|
||||
if (address >= 0x18U && address < 0x18U + sizeof vep_values / sizeof vep_values[0])
|
||||
return copy_name(vep_values[address - 0x18U], output, output_size);
|
||||
if (address == 0x10U)
|
||||
return copy_name("Дискретные датчики (14 бит)", output, output_size);
|
||||
}
|
||||
|
||||
if (device == 9U && address == 0U)
|
||||
return copy_name("Обороты ГЭД, об/мин", output, output_size);
|
||||
if (device == 9U && address == 1U)
|
||||
return copy_name("Обороты ГВ, об/мин", output, output_size);
|
||||
if (device == 9U && address == 2U)
|
||||
return copy_name("Лампы (8 бит)", output, output_size);
|
||||
if (device == 9U && address == 3U)
|
||||
return copy_name("Диоды (16 бит)", output, output_size);
|
||||
if (device == 9U && address == 0x10U)
|
||||
return copy_name("Кнопки (12 бит)", output, output_size);
|
||||
|
||||
if (address == 0x16U)
|
||||
return copy_name("Дискретные входы / кнопки", output, output_size);
|
||||
if (address == 0x17U)
|
||||
return copy_name("Состояние джамперов", output, output_size);
|
||||
if (address == 0x60U)
|
||||
return copy_name("Период быстрого CAN-цикла", output, output_size);
|
||||
if (address == 0x61U)
|
||||
return copy_name("Период медленного CAN-цикла", output, output_size);
|
||||
if (address == 0x62U)
|
||||
return copy_name("Яркость индикации", output, output_size);
|
||||
if (address == 0x63U)
|
||||
return copy_name("Период опроса OWEN", output, output_size);
|
||||
if (address == 0x7EU)
|
||||
return copy_name("Последний режим", output, output_size);
|
||||
if (address == 0x7FU)
|
||||
return copy_name("Команды", output, output_size);
|
||||
|
||||
return copy_name("", output, output_size);
|
||||
}
|
||||
Reference in New Issue
Block a user