-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_pointer_view.c
211 lines (145 loc) · 6.27 KB
/
test_pointer_view.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
/***
* Noptel LRF rangefinder sampler for the Flipper Zero
* Version: 2.0
*
* Test pointer view
***/
/*** Includes ***/
#include <furi_hal_infrared.h>
#include <storage/storage.h>
#include "common.h"
#include "noptel_lrf_sampler_icons.h" /* Generated from images in assets */
/*** Routines ***/
/** IR capture callback */
static void ir_capture_callback(void *ctx, bool lvl, uint32_t duration) {
UNUSED(lvl);
UNUSED(duration);
TestPointerModel *testpointer_model = (TestPointerModel *)ctx;
testpointer_model->ir_received = true;
}
/** IR capture timeout callback */
static void ir_timeout_callback(void *ctx) {
TestPointerModel *testpointer_model = (TestPointerModel *)ctx;
testpointer_model->ir_received = false;
}
/** Test pointer view update timer callback **/
static void test_pointer_view_timer_callback(void *ctx) {
App *app = (App *)ctx;
TestPointerModel *testpointer_model = view_get_model(app->testpointer_view);
/* Did the IR receiver change state? */
if(testpointer_model->ir_received != testpointer_model->ir_received_prev) {
/* Trigger a test pointer view redraw */
with_view_model(app->testpointer_view, TestPointerModel *_model,
{UNUSED(_model);}, true);
testpointer_model->ir_received_prev = testpointer_model->ir_received;
}
/* If an IR signal was received and beeping is enabled, start a beep */
if(testpointer_model->ir_received && app->config.beep)
start_beep(&app->speaker_control, test_pointer_view_update_every + 50);
}
/** Pointer control timer callback **/
static void pointer_control_timer_callback(void *ctx) {
App *app = (App *)ctx;
TestPointerModel *testpointer_model = view_get_model(app->testpointer_view);
/* Jiggle the pointer */
testpointer_model->pointer_is_on = !testpointer_model->pointer_is_on;
send_lrf_command(app->lrf_serial_comm_app, testpointer_model->pointer_is_on?
pointer_on : pointer_off);
FURI_LOG_T(TAG, "Pointer %s", testpointer_model->pointer_is_on? "ON" : "OFF");
}
/** Test pointer view enter callback **/
void testpointer_view_enter_callback(void *ctx) {
App *app = (App *)ctx;
TestPointerModel *testpointer_model = view_get_model(app->testpointer_view);
uint32_t period_view_update =
furi_ms_to_ticks(test_pointer_view_update_every);
uint32_t period_jiggle_pointer = furi_ms_to_ticks(test_pointer_jiggle_every);
/* Make sure the IR receiver isn't busy */
testpointer_model->ir_busy = furi_hal_infrared_is_busy();
if(testpointer_model->ir_busy) {
FURI_LOG_I(TAG, "IR busy");
return;
}
testpointer_model->ir_received_prev = false;
testpointer_model->ir_received = false;
/* Reflect the current state of the pointer */
testpointer_model->pointer_is_on = app->pointer_is_on;
/* Start the UART at the correct baudrate */
start_uart(app->lrf_serial_comm_app, app->config.baudrate);
/* Set up the callback to catch an IR sensor level change */
furi_hal_infrared_async_rx_set_capture_isr_callback(ir_capture_callback,
testpointer_model);
/* Set up the callback to catch an IR sensor timeout */
furi_hal_infrared_async_rx_set_timeout_isr_callback(ir_timeout_callback,
testpointer_model);
/* Start the IR receiver and set the timeout */
furi_hal_infrared_async_rx_start();
furi_hal_infrared_async_rx_set_timeout(test_pointer_view_update_every * 1000);
/* Setup and start the view update timer */
app->test_pointer_view_timer =
furi_timer_alloc(test_pointer_view_timer_callback,
FuriTimerTypePeriodic, ctx);
furi_timer_start(app->test_pointer_view_timer, period_view_update);
/* Setup and start the pointer control timer */
app->test_pointer_control_timer =
furi_timer_alloc(pointer_control_timer_callback,
FuriTimerTypePeriodic, ctx);
furi_timer_start(app->test_pointer_control_timer, period_jiggle_pointer);
/* Set the backlight on all the time */
set_backlight(&app->backlight_control, BL_ON);
with_view_model(app->testpointer_view, TestPointerModel *_model,
{UNUSED(_model);}, false);
}
/** Test pointer view exit callback **/
void testpointer_view_exit_callback(void *ctx) {
App *app = (App *)ctx;
TestPointerModel *testpointer_model = view_get_model(app->testpointer_view);
/* If the IR sensor is busy, we have nothing to do */
if(testpointer_model->ir_busy)
return;
/* Set the backlight back to automatic */
set_backlight(&app->backlight_control, BL_AUTO);
/* Stop and free the pointer control timer */
furi_timer_stop(app->test_pointer_control_timer);
furi_timer_free(app->test_pointer_control_timer);
/* Restore the pointer as we found it */
if(testpointer_model->pointer_is_on != app->pointer_is_on)
send_lrf_command(app->lrf_serial_comm_app, app->pointer_is_on?
pointer_on : pointer_off);
/* Stop the UART */
stop_uart(app->lrf_serial_comm_app);
/* Unset the IR sensor timeout callback */
furi_hal_infrared_async_rx_set_timeout_isr_callback(NULL, NULL);
/* Unset the IR sensor level change callback */
furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL);
/* Stop the IR receiver */
furi_hal_infrared_async_rx_stop();
/* Stop and free the view update timer */
furi_timer_stop(app->test_pointer_view_timer);
furi_timer_free(app->test_pointer_view_timer);
}
/** Draw callback for the test pointer view **/
void testpointer_view_draw_callback(Canvas *canvas, void *model) {
TestPointerModel *testpointer_model = (TestPointerModel *)model;
canvas_set_font(canvas, FontPrimary);
/* Draw the icon to prompt the user to line up the LRF's IR pointer and the
Flipper's IR port */
canvas_draw_icon(canvas, 9, 0, &I_align_pointer_and_flipper);
/* If any IR signal was received, display the laser radiation icon */
if(testpointer_model->ir_received) {
canvas_draw_icon(canvas, 0, 22, &I_laser_radiation);
FURI_LOG_T(TAG, "IR signal received");
}
else
FURI_LOG_T(TAG, "No IR signal received");
/* Draw a dividing line between the icons and the bottom line */
canvas_draw_line(canvas, 0, 48, 128, 48);
/* If the IR sensor is busy, tell the user and stop */
if(testpointer_model->ir_busy) {
canvas_draw_str(canvas, 32, 61, "IR port busy!");
return;
}
/* Prompt the user to line up the LRF's IR pointer and the Flipper's IR port
at the bottom */
canvas_draw_str(canvas, 4, 61, "Aim IR pointer at IR port");
}