Files
templates/c/can-sensor/can_sensor.h

128 lines
5.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file can_sensor.h
* @brief Портируемый транспорт SETTINGS для привязки DS18B20 к локации.
*
* Один Extended CAN-кадр содержит полную операцию. Поля локации находятся в
* Body идентификатора SETCAN, а восьмибайтовый ROM — в payload:
*
* @code
* Priority=1, DeviceType=0x7, DeviceID=0xF, MsgType=0xE (SETTINGS)
* Body[15:8] = номер сборки, Body[7:0] = позиция
* @endcode
*
* Запрос ПМ использует Route=0 (0x17FEZZYY), ответ прибора — Route=1
* (0x1FFEZZYY). DLC=0 означает GET, DLC=8 с ненулевым ROM — SET/REPLACE,
* DLC=8 с нулевым ROM — CLEAR. Успешный ответ возвращает текущий ROM с DLC=8,
* ошибка — однобайтовый код с DLC=1.
*/
#ifndef CAN_SENSOR_H
#define CAN_SENSOR_H
#include <stdint.h>
/** Длина ROM 1-Wire и максимального payload classic CAN. */
#define CAN_SENSOR_ID_SIZE 8U
#define CAN_SENSOR_MAX_DATA 8U
/** Назначенный проекту тип сообщения SETCAN SETTINGS. */
#define CAN_SENSOR_MSGTYPE_SETTINGS 0xEU
/** Маска полей SETCAN от Priority до MsgType; Body под маской не находится. */
#define CAN_SENSOR_HEADER_MASK 0x1FFF0000UL
#define CAN_SENSOR_BODY_MASK 0x0000FFFFUL
/** Базовые ID SETTINGS для выбранных DeviceType=0x7 и DeviceID=0xF. */
#define CAN_SENSOR_DEFAULT_TX_ID 0x1FFE0000UL
#define CAN_SENSOR_DEFAULT_RX_ID 0x17FE0000UL
/** Число попыток помещения кадра в почтовый ящик. */
#define CAN_SENSOR_DEFAULT_RETRIES 3U
/** Операции, полученные из направления, DLC и payload кадра. */
#define CAN_SENSOR_OPERATION_GET 0U
#define CAN_SENSOR_OPERATION_WRITE 1U
#define CAN_SENSOR_OPERATION_CLEAR 2U
#define CAN_SENSOR_OPERATION_RESPONSE 3U
#define CAN_SENSOR_OPERATION_ERROR 4U
#define CAN_SENSOR_OPERATION_INVALID 5U
/** Коды результата SETTINGS, передаваемые ответом с DLC=1. */
#define CAN_SENSOR_RESULT_OK 0x00U
#define CAN_SENSOR_RESULT_INVALID_DLC 0x01U
#define CAN_SENSOR_RESULT_INVALID_ROM_CRC 0x02U
#define CAN_SENSOR_RESULT_NOT_FOUND 0x03U
#define CAN_SENSOR_RESULT_ALREADY_ASSIGNED 0x04U
#define CAN_SENSOR_RESULT_EEPROM_ERROR 0x05U
#define CAN_SENSOR_RESULT_INVALID_LOCATION 0x06U
#define CAN_SENSOR_RESULT_BUSY 0x07U
/** Кадр CAN в форме, не зависящей от периферийного контроллера. */
typedef struct {
uint32_t id; /**< Расширенный идентификатор, 29 бит. */
uint8_t extended; /**< Для SETTINGS всегда 1. */
uint8_t length; /**< DLC, 0..8. */
uint8_t data[CAN_SENSOR_MAX_DATA]; /**< Payload. */
} CanSensor_Frame;
/** Разобранная команда или ответ SETTINGS. */
typedef struct {
uint8_t operation; /**< CAN_SENSOR_OPERATION_*. */
uint8_t request; /**< 1 — запрос Route=0, 0 — ответ Route=1. */
uint8_t assembly_serial; /**< Body[15:8], номер сборки Z. */
uint8_t position; /**< Body[7:0], позиция Y. */
uint8_t result; /**< Код ошибки для ERROR/INVALID. */
uint8_t id[CAN_SENSOR_ID_SIZE]; /**< ROM для WRITE/RESPONSE, нули для CLEAR. */
} CanSensor_Message;
/** Доступ переносимой части к CAN-контроллеру. */
typedef struct {
uint8_t (*send)(void *context, const CanSensor_Frame *frame);
uint8_t (*receive)(void *context, CanSensor_Frame *frame);
void *context;
} CanSensor_Io;
/** Базовые идентификаторы SETTINGS и режим транспорта. */
typedef struct {
uint32_t tx_id; /**< База ответа 0x1FFE0000, Body должен быть нулевым. */
uint32_t rx_id; /**< База запроса 0x17FE0000, Body должен быть нулевым. */
uint8_t extended; /**< 1 — Extended CAN ID. */
uint8_t retries; /**< Число попыток передачи. */
} CanSensor_Config;
/** Состояние транспорта и диагностические счётчики. */
typedef struct {
CanSensor_Io io;
CanSensor_Config config;
uint32_t sent_messages;
uint32_t send_errors;
uint32_t received_messages;
uint32_t dropped_frames;
} CanSensor;
void CanSensor_ConfigDefault(CanSensor_Config *config);
uint8_t CanSensor_Init(CanSensor *link, const CanSensor_Io *io,
const CanSensor_Config *config);
/** Собирает SETTINGS-кадр на базе tx_id или rx_id. */
uint8_t CanSensor_BuildFrame(const CanSensor_Config *config, CanSensor_Frame *frame,
uint8_t response, uint8_t position,
uint8_t assembly_serial, const uint8_t *data,
uint8_t length);
/** Передаёт успешный ответ с текущим ROM (DLC=8). */
uint8_t CanSensor_SendId(CanSensor *link, uint8_t position,
uint8_t assembly_serial, const uint8_t *id);
/** Передаёт ошибку SETTINGS (DLC=1). */
uint8_t CanSensor_SendError(CanSensor *link, uint8_t position,
uint8_t assembly_serial, uint8_t result);
uint8_t CanSensor_HandleFrame(CanSensor *link, const CanSensor_Frame *frame,
CanSensor_Message *out);
uint8_t CanSensor_Poll(CanSensor *link, CanSensor_Message *out);
#endif /* CAN_SENSOR_H */