Files
templates/c/gas-logger/include/gas_logger.h

71 lines
3.0 KiB
C

/* Portable continuous recorder. All addresses/counts are 16-bit WORDS,
* including on C28x (CHAR_BIT=16). No heap, UART, HAL or global state. */
#ifndef GAS_LOGGER_H
#define GAS_LOGGER_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GL_MAGIC 0x474CU
#define GL_VERSION 1U
#define GL_HEADER_WORDS 5U /* time_ms:u32, sequence:u32, event:u16, values... */
#define GL_DATA_OFFSET 0x100U
#define GL_MAX_CHANNELS 64U
#define GL_COMMAND 18U
#define GL_RELEASE_LO 19U
#define GL_RELEASE_HI 20U
#define GL_START 1U
#define GL_SNAPSHOT 2U
#define GL_RELEASE 3U
typedef enum { GL_OK=0, GL_ADDRESS, GL_ARGUMENT, GL_BUSY, GL_EMPTY,
GL_STALE, GL_SOURCE_ERROR } gl_result;
typedef struct {
uint16_t gas, modbus, can;
} gl_channel;
typedef struct {
uint16_t base, channels, capacity;
uint32_t schema_id;
const gl_channel *map;
} gl_config;
/* enter returns the previous IRQ state; leave MUST restore it, not enable
* IRQs unconditionally. source executes under this lock: bounded RAM reads
* only, never I/O/waits. Cache remote CAN values before sampling. */
typedef struct {
void *user;
uint32_t (*enter)(void *user);
void (*leave)(void *user, uint32_t state);
int (*source)(void *user, uint16_t gas, uint16_t *value);
} gl_port;
typedef struct {
gl_config config;
gl_port port;
uint16_t *banks[2];
uint16_t active, count, next, recording, pinned, snap_count, snap_next;
uint32_t generation, release_generation, sequence, missed, source_errors;
} gas_logger;
/* Each distinct bank must have >=capacity*(channels+5) uint16_t elements.
* All callbacks and a nonoverlapping register map are required. */
gl_result gl_init(gas_logger *log, const gl_config *config, const gl_port *port,
uint16_t *bank0, uint16_t *bank1, uint32_t bank_words);
/* Called by the project timer/event hook. A failed source discards the whole
* sample. Sequence/time remain uint32, wrapping modulo 2^32. */
gl_result gl_capture(gas_logger *log, uint32_t time_ms, uint16_t event);
/* Snapshot swaps banks, pins the old one, and NEVER stops acquisition.
* Another snapshot while pinned returns BUSY and increments missed. */
gl_result gl_snapshot(gas_logger *log);
/* Atomic, all-or-nothing block read. Snapshot records are chronological;
* reads past snap_count are rejected, not zero-filled. */
gl_result gl_read(gas_logger *log, uint16_t address, uint16_t *out, uint16_t count);
/* No STOP/reset command. START is idempotent. RELEASE requires the generation
* staged in base+19/20. One controlling client per device. */
gl_result gl_write(gas_logger *log, uint16_t address, uint16_t value);
/* Register aliases for FC03/06 and ProtoCAN GAS. Transports keep their own
* framing/CRC; addresses are zero-based and words preserve their values. */
gl_result gl_modbus_read(gas_logger *log, uint16_t address, uint16_t *out, uint16_t count);
gl_result gl_modbus_write(gas_logger *log, uint16_t address, uint16_t value);
gl_result gl_can_read(gas_logger *log, uint16_t address, uint16_t *out, uint16_t count);
#ifdef __cplusplus
}
#endif
#endif