-
-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathzcl_app.c
executable file
·353 lines (302 loc) · 14.2 KB
/
zcl_app.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#include "AF.h"
#include "OSAL.h"
#include "OSAL_Clock.h"
#include "OSAL_PwrMgr.h"
#include "ZComDef.h"
#include "ZDApp.h"
#include "ZDNwkMgr.h"
#include "ZDObject.h"
#include "math.h"
#include "nwk_util.h"
#include "zcl.h"
#include "zcl_app.h"
#include "zcl_diagnostic.h"
#include "zcl_general.h"
#include "zcl_lighting.h"
#include "zcl_ms.h"
#include "bdb.h"
#include "bdb_interface.h"
#include "gp_interface.h"
#include "Debug.h"
#include "OnBoard.h"
/* HAL */
#include "bme280.h"
#include "ds18b20.h"
#include "hal_adc.h"
#include "hal_drivers.h"
#include "hal_i2c.h"
#include "hal_key.h"
#include "hal_led.h"
#include "battery.h"
#include "commissioning.h"
#include "factory_reset.h"
#include "utils.h"
#include "version.h"
/*********************************************************************
* MACROS
*/
#define HAL_KEY_CODE_RELEASE_KEY HAL_KEY_CODE_NOKEY
// use led4 as output pin, osal will shitch it low when go to PM
#define POWER_ON_SENSORS() \
do { \
HAL_TURN_ON_LED4(); \
st(T3CTL |= BV(4);); \
IO_PUD_PORT(OCM_CLK_PORT, IO_PUP); \
IO_PUD_PORT(OCM_DATA_PORT, IO_PUP); \
IO_PUD_PORT(DS18B20_PORT, IO_PUP); \
} while (0)
#define POWER_OFF_SENSORS() \
do { \
HAL_TURN_OFF_LED4(); \
st(T3CTL &= ~BV(4); T3CTL |= BV(2);); \
IO_PUD_PORT(OCM_CLK_PORT, IO_PDN); \
IO_PUD_PORT(OCM_DATA_PORT, IO_PDN); \
IO_PUD_PORT(DS18B20_PORT, IO_PDN); \
} while (0)
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
extern bool requestNewTrustCenterLinkKey;
byte zclApp_TaskID;
/*********************************************************************
* GLOBAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
static uint8 currentSensorsReadingPhase = 0;
afAddrType_t inderect_DstAddr = {.addrMode = (afAddrMode_t)AddrNotPresent, .endPoint = 0, .addr.shortAddr = 0};
struct bme280_data bme_results;
struct bme280_dev bme_dev = {.dev_id = BME280_I2C_ADDR_PRIM,
.intf = BME280_I2C_INTF,
.read = I2C_ReadMultByte,
.write = I2C_WriteMultByte,
.delay_ms = user_delay_ms};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void zclApp_HandleKeys(byte shift, byte keys);
static void zclApp_Report(void);
static void zclApp_ReadSensors(void);
static void zclApp_InitBME280(struct bme280_dev *dev);
static void zclApp_ReadBME280(struct bme280_dev *dev);
static void zclApp_ReadDS18B20(void);
static void zclApp_ReadLumosity(void);
static void zclApp_ReadSoilHumidity(void);
static void zclApp_InitPWM(void);
/*********************************************************************
* ZCL General Profile Callback table
*/
static zclGeneral_AppCallbacks_t zclApp_CmdCallbacks = {
NULL, // Basic Cluster Reset command
NULL, // Identify Trigger Effect command
NULL, // On/Off cluster commands
NULL, // On/Off cluster enhanced command Off with Effect
NULL, // On/Off cluster enhanced command On with Recall Global Scene
NULL, // On/Off cluster enhanced command On with Timed Off
NULL, // RSSI Location command
NULL // RSSI Location Response command
};
void zclApp_Init(byte task_id) {
IO_IMODE_PORT_PIN(SOIL_MOISTURE_PORT, SOIL_MOISTURE_PIN, IO_TRI); // tri state p0.4 (soil humidity pin)
IO_IMODE_PORT_PIN(LUMOISITY_PORT, LUMOISITY_PIN, IO_TRI); // tri state p0.7 (lumosity pin)
IO_PUD_PORT(OCM_CLK_PORT, IO_PUP);
IO_PUD_PORT(OCM_DATA_PORT, IO_PUP)
IO_PUD_PORT(DS18B20_PORT, IO_PUP);
POWER_OFF_SENSORS();
HalI2CInit();
zclApp_InitPWM();
// this is important to allow connects throught routers
// to make this work, coordinator should be compiled with this flag #define TP2_LEGACY_ZC
requestNewTrustCenterLinkKey = FALSE;
zclApp_TaskID = task_id;
zclGeneral_RegisterCmdCallbacks(1, &zclApp_CmdCallbacks);
zcl_registerAttrList(zclApp_FirstEP.EndPoint, zclApp_AttrsFirstEPCount, zclApp_AttrsFirstEP);
bdb_RegisterSimpleDescriptor(&zclApp_FirstEP);
zcl_registerAttrList(zclApp_SecondEP.EndPoint, zclApp_AttrsSecondEPCount, zclApp_AttrsSecondEP);
bdb_RegisterSimpleDescriptor(&zclApp_SecondEP);
zcl_registerForMsg(zclApp_TaskID);
// Register for all key events - This app will handle all key events
RegisterForKeys(zclApp_TaskID);
LREP("Started build %s \r\n", zclApp_DateCodeNT);
osal_start_reload_timer(zclApp_TaskID, APP_REPORT_EVT, APP_REPORT_DELAY);
}
uint16 zclApp_event_loop(uint8 task_id, uint16 events) {
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if (events & SYS_EVENT_MSG) {
while ((MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(zclApp_TaskID))) {
switch (MSGpkt->hdr.event) {
case KEY_CHANGE:
zclApp_HandleKeys(((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys);
break;
case ZCL_INCOMING_MSG:
if (((zclIncomingMsg_t *)MSGpkt)->attrCmd) {
osal_mem_free(((zclIncomingMsg_t *)MSGpkt)->attrCmd);
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate((uint8 *)MSGpkt);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if (events & APP_REPORT_EVT) {
LREPMaster("APP_REPORT_EVT\r\n");
zclApp_Report();
return (events ^ APP_REPORT_EVT);
}
if (events & APP_READ_SENSORS_EVT) {
LREPMaster("APP_READ_SENSORS_EVT\r\n");
zclApp_ReadSensors();
return (events ^ APP_READ_SENSORS_EVT);
}
// Discard unknown events
return 0;
}
static void zclApp_HandleKeys(byte portAndAction, byte keyCode) {
LREP("zclApp_HandleKeys portAndAction=0x%X keyCode=0x%X\r\n", portAndAction, keyCode);
zclFactoryResetter_HandleKeys(portAndAction, keyCode);
zclCommissioning_HandleKeys(portAndAction, keyCode);
if (portAndAction & HAL_KEY_PRESS) {
LREPMaster("Key press\r\n");
osal_start_timerEx(zclApp_TaskID, APP_REPORT_EVT, 200);
}
}
static void zclApp_InitPWM(void) {
PERCFG &= ~(0x20); // Select Timer 3 Alternative 1 location
P2SEL |= 0x20;
P2DIR |= 0xC0; // Give priority to Timer 1 channel2-3
P1SEL |= BV(4); // Set P1_4 to peripheral, Timer 1,channel 2
P1DIR |= BV(4);
T3CTL &= ~BV(4); // Stop timer 3 (if it was running)
T3CTL |= BV(2); // Clear timer 3
T3CTL &= ~0x08; // Disable Timer 3 overflow interrupts
T3CTL |= 0x03; // Timer 3 mode = 3 - Up/Down
T3CCTL1 &= ~0x40; // Disable channel 0 interrupts
T3CCTL1 |= BV(2); // Ch0 mode = compare
T3CCTL1 |= BV(4); // Ch0 output compare mode = toggle on compare
T3CTL &= ~(BV(7) | BV(6) | BV(5)); // Clear Prescaler divider value
T3CC0 = 4; // Set ticks
}
static void zclApp_ReadSensors(void) {
LREP("currentSensorsReadingPhase %d\r\n", currentSensorsReadingPhase);
/**
* FYI: split reading sensors into phases, so single call wouldn't block processor
* for extensive ammount of time
* */
HalLedSet(HAL_LED_1, HAL_LED_MODE_BLINK);
switch (currentSensorsReadingPhase++) {
case 0:
POWER_ON_SENSORS();
zclApp_ReadLumosity();
break;
case 1:
zclBattery_Report();
zclApp_ReadSoilHumidity();
break;
case 2:
zclApp_InitBME280(&bme_dev);
break;
case 3:
zclApp_ReadDS18B20();
break;
default:
POWER_OFF_SENSORS();
currentSensorsReadingPhase = 0;
break;
}
if (currentSensorsReadingPhase != 0) {
osal_start_timerEx(zclApp_TaskID, APP_READ_SENSORS_EVT, 10);
}
}
static void zclApp_ReadSoilHumidity(void) {
zclApp_SoilHumiditySensor_MeasuredValueRawAdc = adcReadSampled(SOIL_MOISTURE_PIN, HAL_ADC_RESOLUTION_14, HAL_ADC_REF_AVDD, 5);
// FYI: https://docs.google.com/spreadsheets/d/1qrFdMTo0ZrqtlGUoafeB3hplhU3GzDnVWuUK4M9OgNo/edit?usp=sharing
uint16 soilHumidityMinRangeAir = (uint16)AIR_COMPENSATION_FORMULA(zclBattery_RawAdc);
uint16 soilHumidityMaxRangeWater = (uint16)WATER_COMPENSATION_FORMULA(zclBattery_RawAdc);
LREP("soilHumidityMinRangeAir=%d soilHumidityMaxRangeWater=%d\r\n", soilHumidityMinRangeAir, soilHumidityMaxRangeWater);
zclApp_SoilHumiditySensor_MeasuredValue =
(uint16)mapRange(soilHumidityMinRangeAir, soilHumidityMaxRangeWater, 0.0, 10000.0, zclApp_SoilHumiditySensor_MeasuredValueRawAdc);
LREP("ReadSoilHumidity raw=%d mapped=%d\r\n", zclApp_SoilHumiditySensor_MeasuredValueRawAdc, zclApp_SoilHumiditySensor_MeasuredValue);
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, SOIL_HUMIDITY, ATTRID_MS_RELATIVE_HUMIDITY_MEASURED_VALUE);
}
static void zclApp_ReadDS18B20(void) {
int16 temp = readTemperature();
if (temp != 1) {
zclApp_DS18B20_MeasuredValue = temp;
LREP("ReadDS18B20 t=%d\r\n", zclApp_DS18B20_MeasuredValue);
bdb_RepChangedAttrValue(zclApp_SecondEP.EndPoint, TEMP, ATTRID_MS_TEMPERATURE_MEASURED_VALUE);
} else {
LREPMaster("ReadDS18B20 error\r\n");
}
}
static void zclApp_ReadLumosity(void) {
zclApp_IlluminanceSensor_MeasuredValueRawAdc = adcReadSampled(LUMOISITY_PIN, HAL_ADC_RESOLUTION_14, HAL_ADC_REF_AVDD, 5);
zclApp_IlluminanceSensor_MeasuredValue = zclApp_IlluminanceSensor_MeasuredValueRawAdc;
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, ILLUMINANCE, ATTRID_MS_ILLUMINANCE_MEASURED_VALUE);
LREP("IlluminanceSensor_MeasuredValue value=%d\r\n", zclApp_IlluminanceSensor_MeasuredValue);
}
static void _delay_us(uint16 microSecs) {
while (microSecs--) {
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
}
}
void user_delay_ms(uint32_t period) { _delay_us(1000 * period); }
static void zclApp_InitBME280(struct bme280_dev *dev) {
int8_t rslt = bme280_init(dev);
if (rslt == BME280_OK) {
uint8_t settings_sel;
dev->settings.osr_h = BME280_OVERSAMPLING_1X;
dev->settings.osr_p = BME280_OVERSAMPLING_16X;
dev->settings.osr_t = BME280_OVERSAMPLING_2X;
dev->settings.filter = BME280_FILTER_COEFF_16;
dev->settings.standby_time = BME280_STANDBY_TIME_62_5_MS;
settings_sel = BME280_OSR_PRESS_SEL;
settings_sel |= BME280_OSR_TEMP_SEL;
settings_sel |= BME280_OSR_HUM_SEL;
settings_sel |= BME280_STANDBY_SEL;
settings_sel |= BME280_FILTER_SEL;
rslt = bme280_set_sensor_settings(settings_sel, dev);
rslt = bme280_set_sensor_mode(BME280_NORMAL_MODE, dev);
uint32_t req_delay = bme280_cal_meas_delay(&dev->settings);
dev->delay_ms(req_delay);
zclApp_ReadBME280(dev);
} else {
LREP("ReadBME280 init error %d\r\n", rslt);
}
}
static void zclApp_ReadBME280(struct bme280_dev *dev) {
int8_t rslt = bme280_get_sensor_data(BME280_ALL, &bme_results, dev);
if (rslt == BME280_OK) {
zclApp_Temperature_Sensor_MeasuredValue = (int16)bme_results.temperature;
zclApp_PressureSensor_ScaledValue = (int16)(pow(10.0, (double)zclApp_PressureSensor_Scale) * (double)bme_results.pressure);
zclApp_PressureSensor_MeasuredValue = bme_results.pressure / 100;
LREP("ReadBME280 t=%ld, p=%ld h=%ld\r\n", bme_results.temperature, bme_results.pressure, bme_results.humidity);
zclApp_HumiditySensor_MeasuredValue = (uint16)(bme_results.humidity * 100 / 1024);
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, TEMP, ATTRID_MS_TEMPERATURE_MEASURED_VALUE);
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, PRESSURE, ATTRID_MS_PRESSURE_MEASUREMENT_MEASURED_VALUE);
bdb_RepChangedAttrValue(zclApp_FirstEP.EndPoint, HUMIDITY, ATTRID_MS_RELATIVE_HUMIDITY_MEASURED_VALUE);
} else {
LREP("ReadBME280 read error %d\r\n", rslt);
}
}
static void zclApp_Report(void) { osal_start_timerEx(zclApp_TaskID, APP_READ_SENSORS_EVT, 10); }
/****************************************************************************
****************************************************************************/