aboutsummaryrefslogtreecommitdiff
path: root/control/application.c
blob: ce14bf2212702e639394b278149cc50538b6acc6 (plain)
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
#include <bcl.h>
#include <bc_eeprom.h>
#include <bc_spi.h>
#include <bc_dice.h>

#define SERVICE_INTERVAL_INTERVAL (60 * 60 * 1000)
#define BATTERY_UPDATE_INTERVAL (60 * 60 * 1000)

#define TEMPERATURE_TAG_PUB_NO_CHANGE_INTEVAL (15 * 60 * 1000)
#define TEMPERATURE_TAG_PUB_VALUE_CHANGE 0.2f
#define TEMPERATURE_UPDATE_SERVICE_INTERVAL (5 * 1000)
#define TEMPERATURE_UPDATE_NORMAL_INTERVAL (10 * 1000)

#define APPLICATION_TASK_ID 0

#define COLOR_BLACK true


typedef struct {
	uint8_t number;
	float value;
	bc_tick_t next_pub;
} event_param_t;

bc_led_t led;
bc_led_t led_lcd_red;
bc_led_t led_lcd_blue;

// Thermometer instance
bc_tmp112_t tmp112;
event_param_t temperature_event_param = { .next_pub = 0, .value = NAN };
float temperature_on_display = NAN;

void tmp112_event_handler(bc_tmp112_t *self, bc_tmp112_event_t event, void *event_param) {
	float value;
	event_param_t *param = (event_param_t *)event_param;

	if (event != BC_TMP112_EVENT_UPDATE)
		return;

	if (bc_tmp112_get_temperature_celsius(self, &value)) {
		if ((fabsf(value - param->value) >= TEMPERATURE_TAG_PUB_VALUE_CHANGE) || (param->next_pub < bc_scheduler_get_spin_tick())) {
			bc_radio_pub_temperature(BC_RADIO_PUB_CHANNEL_R1_I2C0_ADDRESS_ALTERNATE, &value);
			param->value = value;
			param->next_pub = bc_scheduler_get_spin_tick() + TEMPERATURE_TAG_PUB_NO_CHANGE_INTEVAL;
		}
	} else
		param->value = NAN;

	if ((fabsf(param->value - temperature_on_display) >= 0.1) || isnan(temperature_on_display))
		bc_scheduler_plan_now(APPLICATION_TASK_ID);
}

int brightness = 0;

void set_brightness() {
	bc_radio_pub_int("led/brightness/set", &brightness);
}

void lcd_button_left_event_handler(bc_button_t *self, bc_button_event_t event, void *event_param) {
	if (event != BC_BUTTON_EVENT_CLICK)
		return;
	bc_led_pulse(&led_lcd_blue, 30);
	brightness = 100;
	set_brightness();
}

void lcd_button_right_event_handler(bc_button_t *self, bc_button_event_t event, void *event_param) {
	if (event != BC_BUTTON_EVENT_CLICK)
		return;
	bc_led_pulse(&led_lcd_red, 30);
	brightness = 0;
	set_brightness();
}

void battery_event_handler(bc_module_battery_event_t event, void *event_param) {
	if (event != BC_MODULE_BATTERY_EVENT_UPDATE)
		return;
	float voltage;
	 if (bc_module_battery_get_voltage(&voltage))
		bc_radio_pub_battery(&voltage);
}

void switch_to_normal_mode_task(void *param) {
	bc_tmp112_set_update_interval(&tmp112, TEMPERATURE_UPDATE_NORMAL_INTERVAL);
	bc_scheduler_unregister(bc_scheduler_get_current_task_id());
}

void application_init(void) {
	// Initialize LED on core module
	bc_led_init(&led, BC_GPIO_LED, false, false);
	bc_led_set_mode(&led, BC_LED_MODE_OFF);

	// Initialize Radio
	bc_radio_init(BC_RADIO_MODE_NODE_SLEEPING);

	// Initialize battery
	bc_module_battery_init();
	bc_module_battery_set_event_handler(battery_event_handler, NULL);
	bc_module_battery_set_update_interval(BATTERY_UPDATE_INTERVAL);

	// Initialize thermometer sensor on core module
	bc_tmp112_init(&tmp112, BC_I2C_I2C0, 0x49);
	bc_tmp112_set_event_handler(&tmp112, tmp112_event_handler, &temperature_event_param);
	bc_tmp112_set_update_interval(&tmp112, TEMPERATURE_UPDATE_SERVICE_INTERVAL);

	// Initialize LCD
	bc_module_lcd_init();

	// Initialize LCD button left
	static bc_button_t lcd_left;
	bc_button_init_virtual(&lcd_left, BC_MODULE_LCD_BUTTON_LEFT, bc_module_lcd_get_button_driver(), false);
	bc_button_set_event_handler(&lcd_left, lcd_button_left_event_handler, NULL);

	// Initialize LCD button right
	static bc_button_t lcd_right;
	bc_button_init_virtual(&lcd_right, BC_MODULE_LCD_BUTTON_RIGHT, bc_module_lcd_get_button_driver(), false);
	bc_button_set_event_handler(&lcd_right, lcd_button_right_event_handler, NULL);

	// Initialize red and blue LED on LCD module
	bc_led_init_virtual(&led_lcd_red, BC_MODULE_LCD_LED_RED, bc_module_lcd_get_led_driver(), true);
	bc_led_init_virtual(&led_lcd_blue, BC_MODULE_LCD_LED_BLUE, bc_module_lcd_get_led_driver(), true);

	bc_radio_pairing_request("lcd-thermostat", VERSION);

	bc_scheduler_register(switch_to_normal_mode_task, NULL, SERVICE_INTERVAL_INTERVAL);

	bc_led_pulse(&led, 2000);
}

void application_task(void) {
	static char str_temperature[10];
	if (!bc_module_lcd_is_ready())
		return;

	bc_system_pll_enable();
	bc_module_lcd_clear();

	bc_module_lcd_set_font(&bc_font_ubuntu_33);
	snprintf(str_temperature, sizeof(str_temperature), "%.1f   ", temperature_event_param.value);
	int x = bc_module_lcd_draw_string(20, 20, str_temperature, COLOR_BLACK);
	temperature_on_display = temperature_event_param.value;

	bc_module_lcd_set_font(&bc_font_ubuntu_24);
	bc_module_lcd_draw_string(x - 20, 25, "\xb0" "C   ", COLOR_BLACK);

	bc_module_lcd_update();

	bc_system_pll_disable();
}