LCM — CH32V003 Light Control Module
Light Control Module, I2C slave
Loading...
Searching...
No Matches
lcm_module.h
Go to the documentation of this file.
1/********************************** (C) COPYRIGHT *******************************
2 * File Name : lcm_module.h
3 * Description : Заголовок I2C-ведомого модуля освещения (LCM).
4 *
5 * Light Control Module (LCM) — устройство управления
6 * освещением помещения. Подключается к Room Controller (RC)
7 * по шине I2C в режиме slave.
8 *
9 * Возможности:
10 * — 8 каналов реле (НО, активный высокий уровень);
11 * — 4 группы (зоны) освещения с настраиваемым составом;
12 * — энергонезависимое хранение I2C-адреса и масок групп;
13 * — регистр кода ошибки (чтение по I2C).
14 *
15 * Распиновка I2C (CH32V003, без remapping):
16 * SDA — PC1, SCL — PC2, 100 kHz, 7-битная адресация.
17 *
18 * Протокол прикладного уровня:
19 * Любая команда сразу же готовит ответ — код ошибки
20 * (0x00 — нет ошибки), доступный для чтения в той же
21 * транзакции через RepSTART:
22 * • Однобайтовая команда:
23 * START → Addr+W → cmd →
24 * [RepSTART → Addr+R → код ошибки] → STOP
25 * • Двухбайтовая команда:
26 * START → Addr+W → cmd → param →
27 * [RepSTART → Addr+R → код ошибки] → STOP
28 * • Явное чтение ошибки/ID:
29 * START → Addr+W → cmd(0x1C/0x1D) →
30 * RepSTART → Addr+R → [байт ответа] → STOP
31 * Чтение результата (RepSTART) необязательно — мастер
32 * может завершить транзакцию STOP-ом сразу после
33 * записи, если результат не нужен.
34 *
35 * Нераспознанные команды не меняют реле, но фиксируют
36 * LCM_ERR_UNKNOWN_CMD (возвращается тем же ответом).
37 *********************************************************************************/
38
39#ifndef __LCM_MODULE_H
40#define __LCM_MODULE_H
41
42#include <stdint.h>
43#include "user_data.h"
44
45/*
46 * ---------------------------------------------------------------------------
47 * Параметры шины I2C
48 * ---------------------------------------------------------------------------
49 * Заводской 7-битный адрес — 0x7F. После пуско-наладки RC задаёт новый адрес
50 * командой LCM_SET_ADDR; значение сохраняется в NVM и применяется после reboot.
51 *
52 * На проводе при записи мастером передаётся (addr << 1) | 0, при чтении — | 1.
53 * Пример для 0x7F: запись 0xFE, чтение 0xFF.
54 * ---------------------------------------------------------------------------
55 */
56
57#define LCM_I2C_ADDR_FACTORY 0x7FU /* заводской адрес (7 бит) */
58#define LCM_I2C_SPEED_HZ 100000U /* Standard-mode I2C */
59
60/*
61 * ---------------------------------------------------------------------------
62 * ID модуля контроллера освещения (LCM)
63 * ---------------------------------------------------------------------------
64 */
65#define LCM_ID 0x01U /* ID модуля контроллера освещения (LCM) */
66#define LCM_RELAY_COUNT 8U
67#define LCM_GROUP_COUNT 4U
68
69
70/*
71 * ---------------------------------------------------------------------------
72 * Размещение конфигурации LCM в user_data (6 байт из 26 доступных)
73 * ---------------------------------------------------------------------------
74 * Байты хранятся в RAM-кэше user_data; запись во flash — UserData_Commit()
75 * из LCM_Module_Poll() (нельзя вызывать Commit из прерывания I2C).
76 *
77 * [0] magic — 0x4C ('L'); при несовпадении — заводские значения
78 * [1] i2c_addr — текущий 7-битный адрес slave
79 * [2] group0 — битовая маска реле группы 0 (LSB = реле 0)
80 * [3] group1 — маска группы 1
81 * [4] group2 — маска группы 2
82 * [5] group3 — маска группы 3
83 * ---------------------------------------------------------------------------
84 */
85
86#define LCM_NVM_OFF_MAGIC 0U
87#define LCM_NVM_OFF_I2C_ADDR 1U
88#define LCM_NVM_OFF_GROUP_BASE 2U // 3 байта
89#define LCM_NVM_SIZE 6U // 6 байт
90#define LCM_NVM_MAGIC 0x4CU /* ASCII 'L' — признак валидной NVM */
91
92/*
93 * ---------------------------------------------------------------------------
94 * Однобайтовые команды записи (0x00 … 0x1A) и чтения (0x1C, 0x1D)
95 * ---------------------------------------------------------------------------
96 * Команды 0x00–0x07: включить реле N (N = код команды).
97 * Команды 0x08–0x0F: выключить реле (N = код − 0x08).
98 * Команды 0x12–0x15 / 0x16–0x19: вкл/выкл реле, входящих в группу 0…3;
99 * реле вне группы не изменяются.
100 * ---------------------------------------------------------------------------
101 */
102
103/* Включение отдельных реле (реле 0 … реле 7) */
104#define LCM_LAMP_0_ON 0x00U
105#define LCM_LAMP_1_ON 0x01U
106#define LCM_LAMP_2_ON 0x02U
107#define LCM_LAMP_3_ON 0x03U
108#define LCM_LAMP_4_ON 0x04U
109#define LCM_LAMP_5_ON 0x05U
110#define LCM_LAMP_6_ON 0x06U
111#define LCM_LAMP_7_ON 0x07U
112
113/* Выключение отдельных реле */
114#define LCM_LAMP_0_OFF 0x08U
115#define LCM_LAMP_1_OFF 0x09U
116#define LCM_LAMP_2_OFF 0x0AU
117#define LCM_LAMP_3_OFF 0x0BU
118#define LCM_LAMP_4_OFF 0x0CU
119#define LCM_LAMP_5_OFF 0x0DU
120#define LCM_LAMP_6_OFF 0x0EU
121#define LCM_LAMP_7_OFF 0x0FU
122
123#define LCM_LAMP_ALL_ON 0x10U /* все 8 реле вкл */
124#define LCM_LAMP_ALL_OFF 0x11U /* все 8 реле выкл */
125
126/* Включение реле, входящих в одну группу (остальные без изменений) */
127#define LCM_GROUP_0_ON 0x12U
128#define LCM_GROUP_1_ON 0x13U
129#define LCM_GROUP_2_ON 0x14U
130#define LCM_GROUP_3_ON 0x15U
131
132/* Выключение реле одной группы */
133#define LCM_GROUP_0_OFF 0x16U
134#define LCM_GROUP_1_OFF 0x17U
135#define LCM_GROUP_2_OFF 0x18U
136#define LCM_GROUP_3_OFF 0x19U
137
138#define LCM_RESET 0x1AU /* сброс: адрес 0x7F, группы 0, reboot */
139
140/* Явное чтение регистров (ответ — 1 байт после RepSTART + Addr+R).
141 Обычно избыточны: код ошибки уже доступен после ЛЮБОЙ команды —
142 см. описание протокола выше. GET_ID — единственный способ узнать ID. */
143#define LCM_GET_ERROR 0x1CU /* код последней ошибки */
144#define LCM_GET_ID 0x1DU /* ID модуля */
145
146/*
147 * ---------------------------------------------------------------------------
148 * Двухбайтовые команды (0x20 … 0x28): cmd + параметр (маска)
149 * ---------------------------------------------------------------------------
150 * В масках реле LSB соответствует реле 0; в масках групп LSB — группе 0.
151 * GROUP_n_SET сохраняет маску в RAM и NVM (commit в фоне).
152 * SET_ADDR сохраняет новый адрес и инициирует перезагрузку MCU.
153 * ---------------------------------------------------------------------------
154 */
155
156#define LCM_LAMP_ON 0x20U /* param: маска включаемых реле */
157#define LCM_LAMP_OFF 0x21U /* param: маска выключаемых реле */
158#define LCM_GROUP_ON 0x22U /* param: маска включаемых групп */
159#define LCM_GROUP_OFF 0x23U /* param: маска выключаемых групп */
160
161#define LCM_GROUP_0_SET 0x24U /* param: состав группы 0 → NVM */
162#define LCM_GROUP_1_SET 0x25U
163#define LCM_GROUP_2_SET 0x26U
164#define LCM_GROUP_3_SET 0x27U
165
166#define LCM_SET_ADDR 0x28U /* param: новый 7-битный I2C-адрес */
167
168/*
169 * ---------------------------------------------------------------------------
170 * Коды ошибок (ответ на LCM_GET_ERROR)
171 * ---------------------------------------------------------------------------
172 */
173
174#define LCM_ERR_NONE 0x00U /* ошибок нет */
175#define LCM_ERR_UNKNOWN_CMD 0x01U /* неизвестная команда (резерв) */
176#define LCM_ERR_BAD_PARAM 0x02U /* некорректный параметр (напр. addr > 0x7F) */
177
178/* Ошибки I2C (slave) — устанавливаются в I2C1_ER_IRQHandler() */
179#define LCM_ERR_I2C_BERR 0x03U /* Bus error: нарушение протокола */
180#define LCM_ERR_I2C_OVR 0x04U /* Overrun: не успели обработать DATAR */
181#define LCM_ERR_I2C_ARLO 0x05U /* Arbitration lost */
182
183/* Ошибки user_data */
184#define LCM_ERR_USER_DATA_COMMIT 0x06U /* сбой записи user_data в flash */
185#define LCM_ERR_USER_DATA_PARAM 0x07U /* NULL-указатель или некорректный параметр */
186#define LCM_ERR_USER_DATA_RANGE 0x08U /* offset/len выходят за USER_DATA_CAPACITY */
187#define LCM_ERR_USER_DATA_FLASH 0x09U /* ошибка программирования/стирания flash */
188#define LCM_ERR_USER_DATA_BUSY 0x0AU /* flash занят (редко, при вложенных вызовах) */
189
190/* Ошибки GPIO */
191#define LCM_ERR_GPIO_INIT 0x0BU /* сбой инициализации GPIO */
192#define LCM_ERR_GPIO_SET 0x0CU /* сбой установки GPIO */
193#define LCM_ERR_GPIO_GET 0x0DU /* сбой чтения уровня GPIO (readback) */
194#define LCM_ERR_GPIO_CLEAR 0x0EU /* сбой очистки GPIO */
195#define LCM_ERR_GPIO_SET_ALL 0x0FU /* сбой установки всех GPIO */
196#define LCM_ERR_GPIO_CLEAR_ALL 0x10U /* сбой очистки всех GPIO */
197
198/*********************************************************************
199 * @fn LCM_Module_ExecuteSingleByte / LCM_Module_ExecuteTwoByte
200 *
201 * @brief Диспетчер команд протокола LCM (вызывается из lcm_i2c.c).
202 *
203 * @details Не предназначены для вызова из прикладного кода main — только
204 * из FSM приёма I2C (lcm_i2c.c) при получении соответствующих байт.
205 */
206void LCM_Module_ExecuteSingleByte(uint8_t cmd);
207void LCM_Module_ExecuteTwoByte(uint8_t cmd, uint8_t param);
208
209/*********************************************************************
210 * @fn LCM_Module_SetError
211 *
212 * @brief Зафиксировать код ошибки в регистре LCM_GET_ERROR.
213 *
214 * @details Публичная обёртка для использования из lcm_i2c.c (обработчик
215 * ошибок шины I2C1_ER_IRQHandler).
216 */
217void LCM_Module_SetError(uint8_t err);
218
219/*********************************************************************
220 * @fn LCM_Module_ReportUserDataStatus
221 *
222 * @brief Зафиксировать ошибку API user_data в регистре LCM_GET_ERROR.
223 *
224 * @details Вызывать из main() при сбое UserData_Init() и т.п.
225 * USER_DATA_OK не изменяет текущий код ошибки.
226 */
228
229/*********************************************************************
230 * @fn LCM_Module_GetI2cAddr / GetRelayState / GetGroupMasks
231 *
232 * @brief Диагностический доступ к состоянию LCM (для event_log / отладки).
233 */
234uint8_t LCM_Module_GetI2cAddr(void);
235uint8_t LCM_Module_GetRelayState(void);
236const uint8_t *LCM_Module_GetGroupMasks(void);
237
238/*********************************************************************
239 * @fn LCM_Module_Init
240 *
241 * @brief Полная инициализация модуля LCM.
242 *
243 * @details Загружает конфигурацию из NVM, настраивает GPIO реле (все выкл),
244 * запускает I2C1 slave с адресом из NVM. Вызывать после UserData_Init().
245 */
246void LCM_Module_Init(void);
247
248/*********************************************************************
249 * @fn LCM_Module_Poll
250 *
251 * @brief Фоновая обработка отложенных операций.
252 *
253 * @details Вызывать в бесконечном цикле main(). Выполняет:
254 * — сброс к заводским настройкам (после LCM_RESET);
255 * — запись NVM во flash (после GROUP_SET / SET_ADDR);
256 * — программную перезагрузку MCU (после SET_ADDR / RESET).
257 * Операции с flash занимают миллисекунды — только здесь, не в ISR.
258 */
259void LCM_Module_Poll(void);
260
261#endif /* __LCM_MODULE_H */
void LCM_Module_Poll(void)
Definition lcm_module.c:521
void LCM_Module_ExecuteSingleByte(uint8_t cmd)
Definition lcm_module.c:302
void LCM_Module_ReportUserDataStatus(UserData_Status st)
Definition lcm_module.c:452
void LCM_Module_SetError(uint8_t err)
Definition lcm_module.c:64
uint8_t LCM_Module_GetI2cAddr(void)
Definition lcm_module.c:459
uint8_t LCM_Module_GetRelayState(void)
Definition lcm_module.c:464
const uint8_t * LCM_Module_GetGroupMasks(void)
Definition lcm_module.c:469
void LCM_Module_ExecuteTwoByte(uint8_t cmd, uint8_t param)
Definition lcm_module.c:389
void LCM_Module_Init(void)
Definition lcm_module.c:483
UserData_Status
Definition user_data.h:44