работает слейв и мастер
This commit is contained in:
50
App/app_config.h
Normal file
50
App/app_config.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef APP_CONFIG_H
|
||||
#define APP_CONFIG_H
|
||||
|
||||
#include "app_types.h"
|
||||
|
||||
/*
|
||||
* Markdown note:
|
||||
* - APP_ROLE_DEFAULT chooses firmware behavior at reset.
|
||||
* - Role can be changed at runtime by App_SetRole().
|
||||
* - Replace pin/channel values after CubeMX pinout is fixed.
|
||||
*/
|
||||
|
||||
#define APP_ROLE_DEFAULT APP_ROLE_MASTER // APP_ROLE_MASTER //APP_ROLE_SLAVE
|
||||
|
||||
#define APP_ZIGBEE_ENDPOINT 10U
|
||||
#define APP_ZIGBEE_CLUSTER_INPUTS 0xFC10U
|
||||
#define APP_ZIGBEE_REPORT_PERIOD_MS 100U
|
||||
#define APP_ZIGBEE_CHANNEL 20U
|
||||
#define APP_ZIGBEE_PAN_ID 0x1234U
|
||||
#define APP_ZIGBEE_EXTENDED_PAN_ID 0x1122334455667788ULL
|
||||
#define APP_ZIGBEE_PERMIT_JOIN_SEC 0xFFU
|
||||
#define APP_ZIGBEE_PERMIT_REFRESH_MS 5000U
|
||||
#define APP_ZIGBEE_REJOIN_FAIL_COUNT 3U
|
||||
#define APP_ZIGBEE_REJOIN_RETRY_MS 15000U
|
||||
#define APP_ZIGBEE_JOIN_WATCHDOG_MS 20000U
|
||||
|
||||
#define APP_BUTTON_COUNT 3U
|
||||
#define APP_ADC_CHANNEL_COUNT 1U
|
||||
|
||||
#define APP_BUTTON_ACTIVE_LEVEL 0U
|
||||
#define APP_BUTTON_DEBOUNCE_MS 20U
|
||||
#define APP_BUTTON_GPIO_PORT GPIOB
|
||||
#define APP_BUTTON1_GPIO_PIN GPIO_PIN_0
|
||||
#define APP_BUTTON2_GPIO_PIN GPIO_PIN_1
|
||||
#define APP_BUTTON3_GPIO_PIN GPIO_PIN_2
|
||||
|
||||
#define APP_ROLE_DETECT_ENABLED 0U
|
||||
#define APP_ROLE_DETECT_GPIO_PORT GPIOA
|
||||
#define APP_ROLE_DETECT_GPIO_PIN GPIO_PIN_9
|
||||
#define APP_ROLE_DETECT_PULL GPIO_PULLDOWN
|
||||
#define APP_ROLE_DETECT_MASTER_LEVEL GPIO_PIN_RESET
|
||||
|
||||
#define APP_ROLE_LED_GPIO_PORT GPIOE
|
||||
#define APP_ROLE_LED_GPIO_PIN GPIO_PIN_4
|
||||
#define APP_ROLE_LED_ACTIVE_LEVEL GPIO_PIN_SET
|
||||
|
||||
#define APP_ANALOG_MIN_RAW 0U
|
||||
#define APP_ANALOG_MAX_RAW 4095U
|
||||
|
||||
#endif
|
||||
150
App/app_globals.c
Normal file
150
App/app_globals.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "app_config.h"
|
||||
#include "app_types.h"
|
||||
|
||||
AppContext_t g_app =
|
||||
{
|
||||
.role = APP_ROLE_DEFAULT,
|
||||
.zigbee_state = APP_ZB_DISCONNECTED,
|
||||
.slave_inputs =
|
||||
{
|
||||
.buttons =
|
||||
{
|
||||
{ .pressed = false, .changed = false, .last_change_ms = 0U },
|
||||
{ .pressed = false, .changed = false, .last_change_ms = 0U },
|
||||
{ .pressed = false, .changed = false, .last_change_ms = 0U }
|
||||
},
|
||||
.analog = { .raw = 0U, .filtered = 0U, .percent = 0U },
|
||||
.sequence = 0U
|
||||
},
|
||||
.master_node =
|
||||
{
|
||||
.online = false,
|
||||
.last_report = { .sequence = 0U, .button_mask = 0U, .analog_raw = 0U, .analog_percent = 0U },
|
||||
.last_seen_ms = 0U
|
||||
},
|
||||
.zigbee =
|
||||
{
|
||||
.pan_id = APP_ZIGBEE_PAN_ID,
|
||||
.channel = APP_ZIGBEE_CHANNEL,
|
||||
.endpoint = APP_ZIGBEE_ENDPOINT,
|
||||
.cluster_id = APP_ZIGBEE_CLUSTER_INPUTS
|
||||
},
|
||||
.uptime_ms = 0U,
|
||||
.last_report_ms = 0U
|
||||
};
|
||||
|
||||
volatile uint32_t watch_role = APP_ROLE_DEFAULT;
|
||||
volatile uint32_t watch_is_master = 0U;
|
||||
volatile uint32_t watch_is_slave = 1U;
|
||||
volatile uint32_t watch_role_pin_is_master = 0U;
|
||||
volatile uint32_t watch_zigbee_state = APP_ZB_DISCONNECTED;
|
||||
volatile uint32_t watch_master_online = 0U;
|
||||
volatile uint32_t watch_master_last_seen_ms = 0U;
|
||||
volatile uint32_t watch_master_last_sequence = 0U;
|
||||
volatile uint32_t watch_master_button_mask = 0U;
|
||||
volatile uint32_t watch_master_analog_raw = 0U;
|
||||
volatile uint32_t watch_master_analog_percent = 0U;
|
||||
volatile uint32_t watch_slave_sequence = 0U;
|
||||
volatile uint32_t watch_slave_button_mask = 0U;
|
||||
volatile uint32_t watch_slave_analog_raw = 0U;
|
||||
volatile uint32_t watch_slave_analog_percent = 0U;
|
||||
volatile uint32_t watch_report_tx_count = 0U;
|
||||
volatile uint32_t watch_report_rx_count = 0U;
|
||||
volatile uint32_t watch_report_tx_attempt_count = 0U;
|
||||
volatile uint32_t watch_report_tx_ok_count = 0U;
|
||||
volatile uint32_t watch_report_tx_busy_count = 0U;
|
||||
volatile uint32_t watch_report_tx_confirm_count = 0U;
|
||||
volatile uint32_t watch_report_tx_confirm_status = 0U;
|
||||
volatile uint32_t watch_report_rx_ind_count = 0U;
|
||||
volatile uint32_t watch_report_rx_decode_fail_count = 0U;
|
||||
volatile uint32_t watch_report_rx_last_cluster = 0U;
|
||||
volatile uint32_t watch_report_rx_last_length = 0U;
|
||||
volatile uint32_t watch_zigbee_ready = 0U;
|
||||
volatile uint32_t watch_rejoin_request_count = 0U;
|
||||
volatile uint32_t watch_rejoin_success_count = 0U;
|
||||
volatile uint32_t watch_rejoin_fail_count = 0U;
|
||||
volatile uint32_t watch_rejoin_active = 0U;
|
||||
volatile uint32_t watch_rejoin_last_status = 0U;
|
||||
volatile uint32_t watch_report_tx_fail_streak = 0U;
|
||||
volatile uint32_t watch_permit_join_count = 0U;
|
||||
volatile uint32_t watch_permit_join_status = 0U;
|
||||
volatile uint32_t watch_permit_join_duration = 0U;
|
||||
volatile uint32_t watch_join_watchdog_count = 0U;
|
||||
|
||||
static void App_DebugCopyReportToMasterWatch(const AppSlaveReport_t *report)
|
||||
{
|
||||
watch_master_last_sequence = report->sequence;
|
||||
watch_master_button_mask = report->button_mask;
|
||||
watch_master_analog_raw = report->analog_raw;
|
||||
watch_master_analog_percent = report->analog_percent;
|
||||
}
|
||||
|
||||
static void App_DebugCopyReportToSlaveWatch(const AppSlaveReport_t *report)
|
||||
{
|
||||
watch_slave_sequence = report->sequence;
|
||||
watch_slave_button_mask = report->button_mask;
|
||||
watch_slave_analog_raw = report->analog_raw;
|
||||
watch_slave_analog_percent = report->analog_percent;
|
||||
}
|
||||
|
||||
const char *App_RoleName(AppRole_t role)
|
||||
{
|
||||
return (role == APP_ROLE_MASTER) ? "master" : "slave";
|
||||
}
|
||||
|
||||
void App_SetRole(AppRole_t role)
|
||||
{
|
||||
g_app.role = role;
|
||||
g_app.zigbee_state = APP_ZB_DISCONNECTED;
|
||||
g_app.last_report_ms = 0U;
|
||||
}
|
||||
|
||||
AppSlaveReport_t App_MakeSlaveReport(const AppSlaveInputs_t *inputs)
|
||||
{
|
||||
AppSlaveReport_t report;
|
||||
uint8_t mask = 0U;
|
||||
|
||||
for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
|
||||
{
|
||||
if (inputs->buttons[i].pressed)
|
||||
{
|
||||
mask |= (uint8_t)(1U << i);
|
||||
}
|
||||
}
|
||||
|
||||
report.sequence = inputs->sequence;
|
||||
report.button_mask = mask;
|
||||
report.analog_raw = inputs->analog.raw;
|
||||
report.analog_percent = inputs->analog.percent;
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
void App_MasterAcceptReport(const AppSlaveReport_t *report, uint32_t now_ms)
|
||||
{
|
||||
g_app.master_node.online = true;
|
||||
g_app.master_node.last_report = *report;
|
||||
g_app.master_node.last_seen_ms = now_ms;
|
||||
|
||||
watch_report_rx_count++;
|
||||
App_DebugCopyReportToMasterWatch(report);
|
||||
App_DebugRefresh(watch_role_pin_is_master);
|
||||
}
|
||||
|
||||
void App_DebugRefresh(uint32_t role_pin_is_master)
|
||||
{
|
||||
watch_role = (uint32_t)g_app.role;
|
||||
watch_is_master = (g_app.role == APP_ROLE_MASTER) ? 1U : 0U;
|
||||
watch_is_slave = (g_app.role == APP_ROLE_SLAVE) ? 1U : 0U;
|
||||
watch_role_pin_is_master = role_pin_is_master;
|
||||
watch_zigbee_state = (uint32_t)g_app.zigbee_state;
|
||||
watch_master_online = g_app.master_node.online ? 1U : 0U;
|
||||
watch_master_last_seen_ms = g_app.master_node.last_seen_ms;
|
||||
App_DebugCopyReportToMasterWatch(&g_app.master_node.last_report);
|
||||
}
|
||||
|
||||
void App_DebugOnSlaveReportTx(const AppSlaveReport_t *report)
|
||||
{
|
||||
watch_report_tx_count++;
|
||||
App_DebugCopyReportToSlaveWatch(report);
|
||||
}
|
||||
123
App/app_types.h
Normal file
123
App/app_types.h
Normal file
@@ -0,0 +1,123 @@
|
||||
#ifndef APP_TYPES_H
|
||||
#define APP_TYPES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_ROLE_MASTER = 1,
|
||||
APP_ROLE_SLAVE = 0
|
||||
} AppRole_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_ZB_DISCONNECTED = 0,
|
||||
APP_ZB_JOINING,
|
||||
APP_ZB_CONNECTED,
|
||||
APP_ZB_ERROR
|
||||
} AppZigbeeState_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool pressed;
|
||||
bool changed;
|
||||
uint32_t last_change_ms;
|
||||
} AppButton_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t raw;
|
||||
uint16_t filtered;
|
||||
uint8_t percent;
|
||||
} AppAnalogChannel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AppButton_t buttons[3];
|
||||
AppAnalogChannel_t analog;
|
||||
uint32_t sequence;
|
||||
} AppSlaveInputs_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t sequence;
|
||||
uint8_t button_mask;
|
||||
uint16_t analog_raw;
|
||||
uint8_t analog_percent;
|
||||
} AppSlaveReport_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool online;
|
||||
AppSlaveReport_t last_report;
|
||||
uint32_t last_seen_ms;
|
||||
} AppMasterNode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pan_id;
|
||||
uint8_t channel;
|
||||
uint8_t endpoint;
|
||||
uint16_t cluster_id;
|
||||
} AppZigbeeConfig_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AppRole_t role;
|
||||
AppZigbeeState_t zigbee_state;
|
||||
AppSlaveInputs_t slave_inputs;
|
||||
AppMasterNode_t master_node;
|
||||
AppZigbeeConfig_t zigbee;
|
||||
uint32_t uptime_ms;
|
||||
uint32_t last_report_ms;
|
||||
} AppContext_t;
|
||||
|
||||
extern AppContext_t g_app;
|
||||
|
||||
extern volatile uint32_t watch_role;
|
||||
extern volatile uint32_t watch_is_master;
|
||||
extern volatile uint32_t watch_is_slave;
|
||||
extern volatile uint32_t watch_role_pin_is_master;
|
||||
extern volatile uint32_t watch_zigbee_state;
|
||||
extern volatile uint32_t watch_master_online;
|
||||
extern volatile uint32_t watch_master_last_seen_ms;
|
||||
extern volatile uint32_t watch_master_last_sequence;
|
||||
extern volatile uint32_t watch_master_button_mask;
|
||||
extern volatile uint32_t watch_master_analog_raw;
|
||||
extern volatile uint32_t watch_master_analog_percent;
|
||||
extern volatile uint32_t watch_slave_sequence;
|
||||
extern volatile uint32_t watch_slave_button_mask;
|
||||
extern volatile uint32_t watch_slave_analog_raw;
|
||||
extern volatile uint32_t watch_slave_analog_percent;
|
||||
extern volatile uint32_t watch_report_tx_count;
|
||||
extern volatile uint32_t watch_report_rx_count;
|
||||
extern volatile uint32_t watch_report_tx_attempt_count;
|
||||
extern volatile uint32_t watch_report_tx_ok_count;
|
||||
extern volatile uint32_t watch_report_tx_busy_count;
|
||||
extern volatile uint32_t watch_report_tx_confirm_count;
|
||||
extern volatile uint32_t watch_report_tx_confirm_status;
|
||||
extern volatile uint32_t watch_report_rx_ind_count;
|
||||
extern volatile uint32_t watch_report_rx_decode_fail_count;
|
||||
extern volatile uint32_t watch_report_rx_last_cluster;
|
||||
extern volatile uint32_t watch_report_rx_last_length;
|
||||
extern volatile uint32_t watch_zigbee_ready;
|
||||
extern volatile uint32_t watch_rejoin_request_count;
|
||||
extern volatile uint32_t watch_rejoin_success_count;
|
||||
extern volatile uint32_t watch_rejoin_fail_count;
|
||||
extern volatile uint32_t watch_rejoin_active;
|
||||
extern volatile uint32_t watch_rejoin_last_status;
|
||||
extern volatile uint32_t watch_report_tx_fail_streak;
|
||||
extern volatile uint32_t watch_permit_join_count;
|
||||
extern volatile uint32_t watch_permit_join_status;
|
||||
extern volatile uint32_t watch_permit_join_duration;
|
||||
extern volatile uint32_t watch_join_watchdog_count;
|
||||
|
||||
const char *App_RoleName(AppRole_t role);
|
||||
void App_SetRole(AppRole_t role);
|
||||
AppSlaveReport_t App_MakeSlaveReport(const AppSlaveInputs_t *inputs);
|
||||
void App_MasterAcceptReport(const AppSlaveReport_t *report, uint32_t now_ms);
|
||||
void App_DebugRefresh(uint32_t role_pin_is_master);
|
||||
void App_DebugOnSlaveReportTx(const AppSlaveReport_t *report);
|
||||
|
||||
#endif
|
||||
100
App/hardware.c
Normal file
100
App/hardware.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "hardware.h"
|
||||
#include "app_config.h"
|
||||
#include "main.h"
|
||||
#include "stm32wbxx_nucleo.h"
|
||||
|
||||
/*
|
||||
* Markdown note:
|
||||
* - This file is the only place that should know real GPIO/ADC pins.
|
||||
* - Replace the weak placeholder code with HAL_GPIO_ReadPin() and HAL_ADC calls
|
||||
* after STM32CubeWB/CubeMX generates the board initialization.
|
||||
*/
|
||||
|
||||
void Hardware_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio = {0};
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
|
||||
#if (APP_ROLE_DETECT_ENABLED != 0U)
|
||||
gpio.Pin = APP_ROLE_DETECT_GPIO_PIN;
|
||||
gpio.Mode = GPIO_MODE_INPUT;
|
||||
gpio.Pull = APP_ROLE_DETECT_PULL;
|
||||
gpio.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(APP_ROLE_DETECT_GPIO_PORT, &gpio);
|
||||
#endif
|
||||
|
||||
gpio.Pin = APP_BUTTON1_GPIO_PIN | APP_BUTTON2_GPIO_PIN | APP_BUTTON3_GPIO_PIN;
|
||||
gpio.Mode = GPIO_MODE_INPUT;
|
||||
gpio.Pull = (APP_BUTTON_ACTIVE_LEVEL == 0U) ? GPIO_PULLUP : GPIO_PULLDOWN;
|
||||
gpio.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(APP_BUTTON_GPIO_PORT, &gpio);
|
||||
|
||||
gpio.Pin = APP_ROLE_LED_GPIO_PIN;
|
||||
gpio.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
gpio.Pull = GPIO_NOPULL;
|
||||
gpio.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(APP_ROLE_LED_GPIO_PORT, &gpio);
|
||||
Hardware_SetRoleLed(false);
|
||||
}
|
||||
|
||||
void Hardware_Process(void)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t Hardware_GetTickMs(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
|
||||
bool Hardware_ReadRoleSwitchIsMaster(void)
|
||||
{
|
||||
#if (APP_ROLE_DETECT_ENABLED != 0U)
|
||||
return (HAL_GPIO_ReadPin(APP_ROLE_DETECT_GPIO_PORT, APP_ROLE_DETECT_GPIO_PIN) ==
|
||||
APP_ROLE_DETECT_MASTER_LEVEL);
|
||||
#else
|
||||
return (APP_ROLE_DEFAULT == APP_ROLE_MASTER);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Hardware_SetRoleLed(bool on)
|
||||
{
|
||||
const GPIO_PinState active = APP_ROLE_LED_ACTIVE_LEVEL;
|
||||
const GPIO_PinState inactive = (active == GPIO_PIN_SET) ? GPIO_PIN_RESET : GPIO_PIN_SET;
|
||||
|
||||
HAL_GPIO_WritePin(APP_ROLE_LED_GPIO_PORT,
|
||||
APP_ROLE_LED_GPIO_PIN,
|
||||
on ? active : inactive);
|
||||
}
|
||||
|
||||
bool Hardware_ReadButton(uint8_t index)
|
||||
{
|
||||
uint16_t pin;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0U:
|
||||
pin = APP_BUTTON1_GPIO_PIN;
|
||||
break;
|
||||
|
||||
case 1U:
|
||||
pin = APP_BUTTON2_GPIO_PIN;
|
||||
break;
|
||||
|
||||
case 2U:
|
||||
pin = APP_BUTTON3_GPIO_PIN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return (HAL_GPIO_ReadPin(APP_BUTTON_GPIO_PORT, pin) == APP_BUTTON_ACTIVE_LEVEL);
|
||||
}
|
||||
|
||||
uint16_t Hardware_ReadAnalogRaw(void)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
15
App/hardware.h
Normal file
15
App/hardware.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef HARDWARE_H
|
||||
#define HARDWARE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void Hardware_Init(void);
|
||||
void Hardware_Process(void);
|
||||
uint32_t Hardware_GetTickMs(void);
|
||||
bool Hardware_ReadRoleSwitchIsMaster(void);
|
||||
void Hardware_SetRoleLed(bool on);
|
||||
bool Hardware_ReadButton(uint8_t index);
|
||||
uint16_t Hardware_ReadAnalogRaw(void);
|
||||
|
||||
#endif
|
||||
84
App/slave_inputs.c
Normal file
84
App/slave_inputs.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "app_config.h"
|
||||
#include "app_types.h"
|
||||
#include "hardware.h"
|
||||
#include "slave_inputs.h"
|
||||
|
||||
static uint8_t Analog_ToPercent(uint16_t raw)
|
||||
{
|
||||
uint32_t clamped = raw;
|
||||
|
||||
if (clamped > APP_ANALOG_MAX_RAW)
|
||||
{
|
||||
clamped = APP_ANALOG_MAX_RAW;
|
||||
}
|
||||
|
||||
return (uint8_t)((clamped * 100U) / APP_ANALOG_MAX_RAW);
|
||||
}
|
||||
|
||||
void SlaveInputs_Init(void)
|
||||
{
|
||||
for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
|
||||
{
|
||||
g_app.slave_inputs.buttons[i].pressed = Hardware_ReadButton(i);
|
||||
g_app.slave_inputs.buttons[i].changed = false;
|
||||
g_app.slave_inputs.buttons[i].last_change_ms = Hardware_GetTickMs();
|
||||
}
|
||||
|
||||
g_app.slave_inputs.analog.raw = Hardware_ReadAnalogRaw();
|
||||
g_app.slave_inputs.analog.filtered = g_app.slave_inputs.analog.raw;
|
||||
g_app.slave_inputs.analog.percent = Analog_ToPercent(g_app.slave_inputs.analog.filtered);
|
||||
}
|
||||
|
||||
void SlaveInputs_Process(void)
|
||||
{
|
||||
const uint32_t now = Hardware_GetTickMs();
|
||||
|
||||
for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
|
||||
{
|
||||
const bool pressed = Hardware_ReadButton(i);
|
||||
AppButton_t *button = &g_app.slave_inputs.buttons[i];
|
||||
|
||||
if ((pressed != button->pressed) &&
|
||||
((now - button->last_change_ms) >= APP_BUTTON_DEBOUNCE_MS))
|
||||
{
|
||||
button->pressed = pressed;
|
||||
button->changed = true;
|
||||
button->last_change_ms = now;
|
||||
g_app.slave_inputs.sequence++;
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t raw = Hardware_ReadAnalogRaw();
|
||||
AppAnalogChannel_t *analog = &g_app.slave_inputs.analog;
|
||||
const uint16_t old_percent = analog->percent;
|
||||
|
||||
analog->raw = raw;
|
||||
analog->filtered = (uint16_t)(((uint32_t)analog->filtered * 7U + raw) / 8U);
|
||||
analog->percent = Analog_ToPercent(analog->filtered);
|
||||
|
||||
if (analog->percent != old_percent)
|
||||
{
|
||||
g_app.slave_inputs.sequence++;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveInputs_HasChanges(void)
|
||||
{
|
||||
for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
|
||||
{
|
||||
if (g_app.slave_inputs.buttons[i].changed)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SlaveInputs_ClearChanges(void)
|
||||
{
|
||||
for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
|
||||
{
|
||||
g_app.slave_inputs.buttons[i].changed = false;
|
||||
}
|
||||
}
|
||||
9
App/slave_inputs.h
Normal file
9
App/slave_inputs.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef SLAVE_INPUTS_H
|
||||
#define SLAVE_INPUTS_H
|
||||
|
||||
void SlaveInputs_Init(void);
|
||||
void SlaveInputs_Process(void);
|
||||
int SlaveInputs_HasChanges(void);
|
||||
void SlaveInputs_ClearChanges(void);
|
||||
|
||||
#endif
|
||||
89
App/zigbee_app.c
Normal file
89
App/zigbee_app.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "app_config.h"
|
||||
#include "app_types.h"
|
||||
#include "hardware.h"
|
||||
#include "slave_inputs.h"
|
||||
#include "zigbee_app.h"
|
||||
#include "zigbee_port.h"
|
||||
|
||||
static void ZigbeeApp_UpdateStatusLed(void)
|
||||
{
|
||||
const uint32_t phase = g_app.uptime_ms % 1000U;
|
||||
bool on = false;
|
||||
|
||||
switch (g_app.zigbee_state)
|
||||
{
|
||||
case APP_ZB_CONNECTED:
|
||||
if (g_app.role == APP_ROLE_MASTER)
|
||||
{
|
||||
on = (phase < 80U);
|
||||
}
|
||||
else
|
||||
{
|
||||
on = (phase < 80U) || ((phase >= 160U) && (phase < 240U));
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_ZB_JOINING:
|
||||
on = ((phase % 160U) < 80U);
|
||||
break;
|
||||
|
||||
case APP_ZB_ERROR:
|
||||
on = ((phase % 100U) < 50U);
|
||||
break;
|
||||
|
||||
case APP_ZB_DISCONNECTED:
|
||||
default:
|
||||
on = ((phase % 400U) < 80U);
|
||||
break;
|
||||
}
|
||||
|
||||
Hardware_SetRoleLed(on);
|
||||
}
|
||||
|
||||
static void ZigbeeApp_UpdateRoleFromSwitch(void)
|
||||
{
|
||||
const bool role_pin_is_master = Hardware_ReadRoleSwitchIsMaster();
|
||||
const AppRole_t requested_role = role_pin_is_master;
|
||||
// role_pin_is_master ? APP_ROLE_MASTER : APP_ROLE_SLAVE;
|
||||
|
||||
if (requested_role != g_app.role)
|
||||
{
|
||||
App_SetRole(requested_role);
|
||||
ZigbeePort_Init(&g_app.zigbee, g_app.role);
|
||||
}
|
||||
|
||||
App_DebugRefresh(role_pin_is_master ? 1U : 0U);
|
||||
}
|
||||
|
||||
void ZigbeeApp_Init(void)
|
||||
{
|
||||
ZigbeePort_Init(&g_app.zigbee, g_app.role);
|
||||
SlaveInputs_Init();
|
||||
|
||||
const bool role_pin_is_master = Hardware_ReadRoleSwitchIsMaster();
|
||||
App_DebugRefresh(role_pin_is_master ? 1U : 0U);
|
||||
ZigbeeApp_UpdateStatusLed();
|
||||
}
|
||||
|
||||
void ZigbeeApp_Process(void)
|
||||
{
|
||||
g_app.uptime_ms = Hardware_GetTickMs();
|
||||
|
||||
ZigbeeApp_UpdateRoleFromSwitch();
|
||||
ZigbeePort_Process();
|
||||
ZigbeeApp_UpdateStatusLed();
|
||||
|
||||
if (g_app.role == APP_ROLE_SLAVE)
|
||||
{
|
||||
SlaveInputs_Process();
|
||||
|
||||
if ((g_app.uptime_ms - g_app.last_report_ms) >= APP_ZIGBEE_REPORT_PERIOD_MS)
|
||||
{
|
||||
if (ZigbeePort_SendSlaveInputs(&g_app.slave_inputs) == ZIGBEE_PORT_OK)
|
||||
{
|
||||
g_app.last_report_ms = g_app.uptime_ms;
|
||||
SlaveInputs_ClearChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
App/zigbee_app.h
Normal file
7
App/zigbee_app.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef ZIGBEE_APP_H
|
||||
#define ZIGBEE_APP_H
|
||||
|
||||
void ZigbeeApp_Init(void);
|
||||
void ZigbeeApp_Process(void);
|
||||
|
||||
#endif
|
||||
34
App/zigbee_port.c
Normal file
34
App/zigbee_port.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "zigbee_port.h"
|
||||
#include "app_zigbee.h"
|
||||
|
||||
/*
|
||||
* Markdown note:
|
||||
* - Keep STM32_WPAN / Zigbee Cluster Library calls in this adapter.
|
||||
* - Master should create/open the network and receive reports.
|
||||
* - Slave should join the network and send AppSlaveInputs_t payload.
|
||||
*/
|
||||
|
||||
void ZigbeePort_Init(const AppZigbeeConfig_t *config, AppRole_t role)
|
||||
{
|
||||
(void)config;
|
||||
(void)role;
|
||||
}
|
||||
|
||||
void ZigbeePort_Process(void)
|
||||
{
|
||||
APP_ZIGBEE_Process();
|
||||
}
|
||||
|
||||
ZigbeePortStatus_t ZigbeePort_SendSlaveInputs(const AppSlaveInputs_t *inputs)
|
||||
{
|
||||
const AppSlaveReport_t report = App_MakeSlaveReport(inputs);
|
||||
|
||||
App_DebugOnSlaveReportTx(&report);
|
||||
|
||||
return APP_ZIGBEE_SendSlaveReport(&report) ? ZIGBEE_PORT_OK : ZIGBEE_PORT_BUSY;
|
||||
}
|
||||
|
||||
void ZigbeePort_OnSlaveReportReceived(const AppSlaveReport_t *report, uint32_t now_ms)
|
||||
{
|
||||
App_MasterAcceptReport(report, now_ms);
|
||||
}
|
||||
19
App/zigbee_port.h
Normal file
19
App/zigbee_port.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef ZIGBEE_PORT_H
|
||||
#define ZIGBEE_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "app_types.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ZIGBEE_PORT_OK = 0,
|
||||
ZIGBEE_PORT_BUSY,
|
||||
ZIGBEE_PORT_ERROR
|
||||
} ZigbeePortStatus_t;
|
||||
|
||||
void ZigbeePort_Init(const AppZigbeeConfig_t *config, AppRole_t role);
|
||||
void ZigbeePort_Process(void);
|
||||
ZigbeePortStatus_t ZigbeePort_SendSlaveInputs(const AppSlaveInputs_t *inputs);
|
||||
void ZigbeePort_OnSlaveReportReceived(const AppSlaveReport_t *report, uint32_t now_ms);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user