Skip to content

Commit d6be277

Browse files
[Thred Tutorial] Add IPC module.
1 parent 759fba5 commit d6be277

File tree

7 files changed

+596
-0
lines changed

7 files changed

+596
-0
lines changed
393 KB
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../../
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
PACKAGE_NAME = screen
10+
11+
STACK_SIZE = 4096
12+
EXTERN_LIBS += $(TOCK_USERLAND_BASE_DIR)/u8g2
13+
14+
# Include userland master makefile. Contains rules and flags for actually
15+
# building the application.
16+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
#include <stdbool.h>
2+
#include <stdint.h>
3+
#include <stdio.h>
4+
#include <string.h>
5+
6+
#include <libtock/interface/button.h>
7+
#include <libtock/kernel/ipc.h>
8+
#include <libtock/services/alarm.h>
9+
#include <libtock-sync/services/alarm.h>
10+
11+
#include <u8g2.h>
12+
#include <u8g2-tock.h>
13+
14+
// Global reference to the u8g2 context.
15+
u8g2_t u8g2;
16+
17+
// Helper method to update and format u8g2 screen.
18+
static void update_screen(void);
19+
20+
uint8_t global_temperature_setpoint = 0;
21+
uint8_t local_temperature_setpoint = 22;
22+
int measured_temperature = 0;
23+
24+
uint8_t prior_global_temperature_setpoint = 255;
25+
uint8_t prior_local_temperature_setpoint = 255;
26+
int prior_measured_temperature = 0;
27+
28+
bool network_up = false;
29+
30+
bool callback_event = false;
31+
32+
libtock_alarm_t read_temperature_timer;
33+
libtock_alarm_t network_timer;
34+
35+
// Helper method to initialize the screen.
36+
static int init_controller_ipc(void);
37+
size_t sensor_svc_num = 0;
38+
size_t openthread_svc_num = 0;
39+
40+
// We use this variable as a buffer that is naturally aligned to the int
41+
// alignment, and has an alignment >= its size.
42+
uint8_t temperature_buffer[64] __attribute__((aligned(64)));
43+
uint8_t openthread_buffer[64] __attribute__((aligned(64)));
44+
45+
46+
static void button_callback(returncode_t ret,
47+
int btn_num,
48+
bool pressed) {
49+
if (ret != RETURNCODE_SUCCESS) return;
50+
51+
if (pressed) {
52+
if (btn_num == 0 && local_temperature_setpoint < 35) {
53+
local_temperature_setpoint++;
54+
} else if (btn_num == 1 && local_temperature_setpoint > 0) {
55+
local_temperature_setpoint--;
56+
} else if (btn_num == 2) {
57+
local_temperature_setpoint = 22;
58+
}
59+
}
60+
61+
// Indicate that we have received a callback.
62+
callback_event = true;
63+
}
64+
65+
static void read_temperature_timer_callback(__attribute__ ((unused)) uint32_t now,
66+
__attribute__ ((unused)) uint32_t scheduled,
67+
__attribute__ ((unused)) void* opaque) {
68+
// Request a new temperature reading from the sensor:
69+
ipc_notify_service(sensor_svc_num);
70+
}
71+
72+
static void update_network_timer_callback(__attribute__ ((unused)) uint32_t now,
73+
__attribute__ ((unused)) uint32_t scheduled,
74+
__attribute__ ((unused)) void* opaque) {
75+
openthread_buffer[0] = local_temperature_setpoint;
76+
ipc_notify_service(openthread_svc_num);
77+
libtock_alarm_in_ms(500, update_network_timer_callback, NULL, &network_timer);
78+
79+
}
80+
81+
static void sensor_callback(__attribute__ ((unused)) int pid,
82+
__attribute__ ((unused)) int len,
83+
__attribute__ ((unused)) int arg2,
84+
__attribute__ ((unused)) void* ud) {
85+
// update measured temperature
86+
measured_temperature = *((int*) &temperature_buffer[0]);
87+
88+
// Indicate that we have received a callback.
89+
callback_event = true;
90+
91+
// Request a new temperature reading in 250ms:
92+
libtock_alarm_in_ms(250, read_temperature_timer_callback, NULL, &read_temperature_timer);
93+
}
94+
95+
static void openthread_callback(__attribute__ ((unused)) int pid,
96+
__attribute__ ((unused)) int len,
97+
__attribute__ ((unused)) int arg2,
98+
__attribute__ ((unused)) void* ud) {
99+
network_up = true;
100+
101+
// update setpoint temperature
102+
global_temperature_setpoint = *((int*) &openthread_buffer[0]);
103+
104+
// Indicate that we have received a callback.
105+
callback_event = true;
106+
107+
}
108+
109+
110+
int main(void) {
111+
// Init u8g2
112+
u8g2_tock_init(&u8g2);
113+
u8g2_SetFont(&u8g2, u8g2_font_profont12_tr);
114+
u8g2_SetFontPosTop(&u8g2);
115+
116+
init_controller_ipc();
117+
118+
// Enable buttons
119+
for (int i = 0; i < 4; i++){
120+
libtock_button_notify_on_press(i, button_callback);
121+
}
122+
123+
ipc_notify_service(sensor_svc_num);
124+
libtock_alarm_in_ms(500, update_network_timer_callback, NULL, &network_timer);
125+
126+
for(;;) {
127+
callback_event = false;
128+
yield_for(&callback_event);
129+
130+
if (measured_temperature != prior_measured_temperature
131+
|| global_temperature_setpoint != prior_global_temperature_setpoint
132+
|| local_temperature_setpoint != prior_local_temperature_setpoint)
133+
{
134+
prior_measured_temperature = measured_temperature;
135+
prior_global_temperature_setpoint = global_temperature_setpoint;
136+
prior_local_temperature_setpoint = local_temperature_setpoint;
137+
update_screen();
138+
}
139+
140+
}
141+
}
142+
143+
static void update_screen(void) {
144+
char temperature_set_point_str[35];
145+
char temperature_global_set_point_str[35];
146+
char temperature_current_measure_str[35];
147+
148+
// Format the buffers to be written.
149+
sprintf(temperature_set_point_str,
150+
"Set Point: %d",
151+
local_temperature_setpoint);
152+
153+
if(network_up) {
154+
sprintf(temperature_global_set_point_str,
155+
"Global Set Point: %d",
156+
global_temperature_setpoint);
157+
} else {
158+
sprintf(temperature_global_set_point_str,
159+
"Global Set Point: N/A");
160+
}
161+
162+
uint8_t whole_temp = measured_temperature / 100;
163+
uint8_t decimal_temp = measured_temperature % 100;
164+
165+
sprintf(temperature_current_measure_str,
166+
"Measured Temp: %d.%d",
167+
whole_temp,
168+
decimal_temp );
169+
170+
// Use u8g2 library to draw each string.
171+
u8g2_ClearBuffer(&u8g2);
172+
u8g2_SetDrawColor(&u8g2, 1);
173+
u8g2_DrawStr(&u8g2, 0, 0, temperature_set_point_str);
174+
u8g2_DrawStr(&u8g2, 0, 25, temperature_global_set_point_str);
175+
u8g2_DrawStr(&u8g2, 0, 50, temperature_current_measure_str);
176+
u8g2_SendBuffer(&u8g2);
177+
}
178+
179+
static int init_controller_ipc(void) {
180+
int err = -1;
181+
int discover_retry_count = 0;
182+
int err_sensor = -1;
183+
int err_openthread = -1;
184+
185+
while (err_sensor < 0 && err_openthread < 0 && discover_retry_count < 100) {
186+
err_sensor = ipc_discover("org.tockos.thread-tutorial.sensor", &sensor_svc_num);
187+
err_openthread = ipc_discover("org.tockos.thread-tutorial.openthread", &openthread_svc_num);
188+
discover_retry_count++;
189+
if (err < 0) {
190+
libtocksync_alarm_delay_ms(10);
191+
}
192+
}
193+
194+
if (err_sensor < 0) {
195+
printf("No sensor service\r\n");
196+
return -1;
197+
}
198+
199+
if (err_openthread < 0) {
200+
printf("No openthread service\r\n");
201+
return -1;
202+
}
203+
204+
printf("[controller] Discovered sensor service: %d\r\n", sensor_svc_num);
205+
printf("[controller] Discovered openthread service: %d\r\n", openthread_svc_num);
206+
207+
ipc_register_client_callback(sensor_svc_num, sensor_callback, NULL);
208+
ipc_register_client_callback(openthread_svc_num, openthread_callback, NULL);
209+
210+
ipc_share(sensor_svc_num, &temperature_buffer, sizeof(temperature_buffer));
211+
ipc_share(openthread_svc_num, &openthread_buffer, sizeof(openthread_buffer));
212+
213+
return err;
214+
}
215+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../../
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
PACKAGE_NAME = org.tockos.thread-tutorial.sensor
10+
11+
# Include userland master makefile. Contains rules and flags for actually
12+
# building the application.
13+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include <stdio.h>
2+
3+
#include <libtock-sync/sensors/temperature.h>
4+
#include <libtock-sync/services/alarm.h>
5+
#include <libtock/kernel/ipc.h>
6+
#include <libtock/tock.h>
7+
8+
static int current_temperature = 0;
9+
10+
static void sensor_ipc_callback(int pid, int len, int buf,
11+
__attribute__((unused)) void* ud) {
12+
// A client has requested us to provide them the current temperature value.
13+
// We must make sure that it provides us with a buffer sufficiently large to
14+
// store a single integer:
15+
if (len < ((int) sizeof(current_temperature))) {
16+
// We do not inform the caller and simply return. We do print a log message:
17+
puts("[thread-sensor] ERROR: sensor IPC invoked with too small buffer.\r\n");
18+
}
19+
20+
// The buffer is large enough, copy the current temperature into it:
21+
memcpy((void*) buf, &current_temperature, sizeof(current_temperature));
22+
23+
// Let the client know:
24+
ipc_notify_client(pid);
25+
}
26+
27+
28+
int main(void) {
29+
// Measure the temperature once before registering ourselves as an IPC
30+
// service. This ensures that we always return a correct (but potentially
31+
// stale) temperature value.
32+
libtocksync_temperature_read(&current_temperature);
33+
34+
// Register this application as an IPC service under its name:
35+
ipc_register_service_callback("org.tockos.thread-tutorial.sensor",
36+
sensor_ipc_callback,
37+
NULL);
38+
39+
// We measure the temperature in the main loop and
40+
//print this value to the console.
41+
while (1) {
42+
// Measure temperature -- returned in the form 2200 => 22C
43+
libtocksync_temperature_read(&current_temperature);
44+
45+
// Delay 1000 ms (1 second).
46+
libtocksync_alarm_delay_ms(1000);
47+
}
48+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../..
5+
6+
# Which files to compile.
7+
C_SRCS := $(wildcard *.c)
8+
9+
# Specify this app depends on the MTD OpenThread library.
10+
include $(TOCK_USERLAND_BASE_DIR)/libopenthread/libopenthread-mtd.mk
11+
12+
# set stack size to 8000 to support openthread app
13+
STACK_SIZE:=8000
14+
APP_HEAP_SIZE:=5000
15+
16+
PACKAGE_NAME = org.tockos.thread-tutorial.openthread
17+
18+
# Include userland master makefile. Contains rules and flags for actually
19+
# building the application.
20+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk

0 commit comments

Comments
 (0)