Skip to content

Commit df3c9f9

Browse files
Merge pull request #6 from jamisonderek/jamisonderek/rfid-ammo
2 parents f0181ef + bb8b73f commit df3c9f9

5 files changed

+271
-0
lines changed

infrared_controller.c

+16
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,19 @@ bool infrared_controller_receive(InfraredController* controller) {
187187

188188
return hit;
189189
}
190+
191+
void infrared_controller_pause(InfraredController* controller) {
192+
if(controller->worker_rx_active) {
193+
FURI_LOG_I(TAG, "Stopping RX worker");
194+
infrared_worker_rx_stop(controller->worker);
195+
controller->worker_rx_active = false;
196+
}
197+
}
198+
199+
void infrared_controller_resume(InfraredController* controller) {
200+
if(!controller->worker_rx_active) {
201+
FURI_LOG_I(TAG, "Starting RX worker");
202+
infrared_worker_rx_start(controller->worker);
203+
controller->worker_rx_active = true;
204+
}
205+
}

infrared_controller.h

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ void infrared_controller_free(InfraredController* controller);
1010
void infrared_controller_set_team(InfraredController* controller, LaserTagTeam team);
1111
void infrared_controller_send(InfraredController* controller);
1212
bool infrared_controller_receive(InfraredController* controller);
13+
void infrared_controller_pause(InfraredController* controller);
14+
void infrared_controller_resume(InfraredController* controller);
1315

1416
#define IR_COMMAND_RED_TEAM 0xA1
1517
#define IR_COMMAND_BLUE_TEAM 0xB2

laser_tag_app.c

+79
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "laser_tag_view.h"
33
#include "infrared_controller.h"
44
#include "game_state.h"
5+
#include "lfrfid_reader.h"
56
#include <furi.h>
67
#include <gui/gui.h>
78
#include <input/input.h>
@@ -20,6 +21,7 @@ struct LaserTagApp {
2021
GameState* game_state;
2122
LaserTagState state;
2223
bool need_redraw;
24+
LFRFIDReader* reader;
2325
};
2426

2527
const NotificationSequence sequence_vibro_1 = {&message_vibro_on, &message_vibro_off, NULL};
@@ -144,6 +146,55 @@ static void laser_tag_app_draw_callback(Canvas* canvas, void* context) {
144146
FURI_LOG_D(TAG, "Exiting draw callback");
145147
}
146148

149+
static bool matching_team(LaserTagApp* app, uint8_t data) {
150+
if(data == 0) {
151+
return true;
152+
} else if(game_state_get_team(app->game_state) == TeamRed) {
153+
return data == 0xA1;
154+
} else if(game_state_get_team(app->game_state) == TeamBlue) {
155+
return data == 0xB2;
156+
}
157+
return false;
158+
}
159+
160+
static void tag_callback(uint8_t* data, uint8_t length, void* context) {
161+
LaserTagApp* app = (LaserTagApp*)context;
162+
163+
if(length != 5) {
164+
FURI_LOG_W(TAG, "Tag is not for game. Length: %d", length);
165+
return;
166+
}
167+
168+
if(data[0] != 0x13 || data[1] != 0x37) {
169+
FURI_LOG_D(
170+
TAG,
171+
"Tag is not for game. Data: %02x %02x %02x %02x %02x",
172+
data[0],
173+
data[1],
174+
data[2],
175+
data[3],
176+
data[4]);
177+
return;
178+
}
179+
180+
if(matching_team(app, data[2])) {
181+
if(data[3] == 0xFD) {
182+
uint16_t max_delta_ammo = data[4];
183+
uint16_t ammo = game_state_get_ammo(app->game_state);
184+
uint16_t delta_ammo = INITIAL_AMMO - ammo;
185+
if(delta_ammo > max_delta_ammo) {
186+
delta_ammo = max_delta_ammo;
187+
}
188+
game_state_increase_ammo(app->game_state, delta_ammo);
189+
FURI_LOG_D(TAG, "Increased ammo by: %d", delta_ammo);
190+
} else {
191+
FURI_LOG_W(TAG, "Tag action unknown: %02x %02x", data[3], data[4]);
192+
}
193+
} else {
194+
FURI_LOG_I(TAG, "Tag not for team: %02x", data[2]);
195+
}
196+
}
197+
147198
LaserTagApp* laser_tag_app_alloc() {
148199
FURI_LOG_D(TAG, "Allocating Laser Tag App");
149200
LaserTagApp* app = malloc(sizeof(LaserTagApp));
@@ -186,6 +237,9 @@ LaserTagApp* laser_tag_app_alloc() {
186237
}
187238
FURI_LOG_I(TAG, "Timer allocated");
188239

240+
app->reader = lfrfid_reader_alloc();
241+
lfrfid_reader_set_tag_callback(app->reader, "EM4100", tag_callback, app);
242+
189243
furi_timer_start(app->timer, furi_kernel_get_tick_frequency());
190244
FURI_LOG_D(TAG, "Timer started");
191245

@@ -205,6 +259,10 @@ void laser_tag_app_free(LaserTagApp* app) {
205259
if(app->ir_controller) {
206260
infrared_controller_free(app->ir_controller);
207261
}
262+
if(app->reader) {
263+
lfrfid_reader_free(app->reader);
264+
app->reader = NULL;
265+
}
208266
free(app->game_state);
209267
furi_record_close(RECORD_GUI);
210268
furi_record_close(RECORD_NOTIFICATION);
@@ -356,6 +414,27 @@ int32_t laser_tag_app(void* p) {
356414
FURI_LOG_I(TAG, "OK key pressed, firing laser");
357415
laser_tag_app_fire(app);
358416
break;
417+
case InputKeyUp:
418+
FURI_LOG_I(TAG, "Up key pressed, scanning for ammo");
419+
notification_message(app->notifications, &sequence_short_beep);
420+
uint16_t ammo = game_state_get_ammo(app->game_state);
421+
infrared_controller_pause(app->ir_controller);
422+
lfrfid_reader_start(app->reader);
423+
for(int i = 0; i < 30; i++) {
424+
furi_delay_ms(100);
425+
if(ammo != game_state_get_ammo(app->game_state)) {
426+
break;
427+
}
428+
}
429+
lfrfid_reader_stop(app->reader);
430+
infrared_controller_resume(app->ir_controller);
431+
if(ammo != game_state_get_ammo(app->game_state)) {
432+
notification_message(app->notifications, &sequence_success);
433+
} else {
434+
notification_message(app->notifications, &sequence_error);
435+
}
436+
app->need_redraw = true;
437+
break;
359438
default:
360439
break;
361440
}

lfrfid_reader.c

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include "lfrfid_reader.h"
2+
#include <lfrfid/protocols/lfrfid_protocols.h>
3+
#include <toolbox/protocols/protocol_dict.h>
4+
#include <lib/lfrfid/lfrfid_worker.h>
5+
6+
#define TAG "LfRfid_Reader"
7+
8+
typedef enum {
9+
LFRFIDReaderEventTagRead = (1 << 0),
10+
LFRFIDReaderEventStopThread = (1 << 1),
11+
LFRFIDReaderEventAll = (LFRFIDReaderEventTagRead | LFRFIDReaderEventStopThread),
12+
} LFRFIDReaderEventType;
13+
14+
struct LFRFIDReader {
15+
char* requested_protocol;
16+
ProtocolId protocol;
17+
ProtocolDict* dict;
18+
LFRFIDWorker* worker;
19+
FuriThread* thread;
20+
LFRFIDReaderTagCallback callback;
21+
void* callback_context;
22+
};
23+
24+
static void lfrfid_cli_read_callback(LFRFIDWorkerReadResult result, ProtocolId proto, void* ctx) {
25+
furi_assert(ctx);
26+
LFRFIDReader* context = ctx;
27+
if(result == LFRFIDWorkerReadDone) {
28+
context->protocol = proto;
29+
furi_thread_flags_set(furi_thread_get_id(context->thread), LFRFIDReaderEventTagRead);
30+
}
31+
}
32+
33+
LFRFIDReader* lfrfid_reader_alloc() {
34+
LFRFIDReader* reader = malloc(sizeof(LFRFIDReader));
35+
reader->protocol = PROTOCOL_NO;
36+
reader->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
37+
reader->worker = lfrfid_worker_alloc(reader->dict);
38+
39+
return reader;
40+
}
41+
42+
void lfrfid_reader_set_tag_callback(
43+
LFRFIDReader* reader,
44+
char* requested_protocol,
45+
LFRFIDReaderTagCallback callback,
46+
void* context) {
47+
furi_assert(reader);
48+
furi_assert(requested_protocol);
49+
reader->requested_protocol = requested_protocol;
50+
reader->callback = callback;
51+
reader->callback_context = context;
52+
}
53+
54+
static int32_t lfrfid_reader_start_thread(void* ctx) {
55+
LFRFIDReader* reader = (LFRFIDReader*)ctx;
56+
furi_thread_flags_clear(LFRFIDReaderEventAll);
57+
lfrfid_worker_start_thread(reader->worker);
58+
lfrfid_worker_read_start(
59+
reader->worker, LFRFIDWorkerReadTypeASKOnly, lfrfid_cli_read_callback, reader);
60+
while(true) {
61+
uint32_t flags = furi_thread_flags_wait(LFRFIDReaderEventAll, FuriFlagWaitAny, 100);
62+
63+
if(flags != (unsigned)FuriFlagErrorTimeout) {
64+
if((flags & LFRFIDReaderEventTagRead) == LFRFIDReaderEventTagRead) {
65+
furi_thread_flags_clear(LFRFIDReaderEventTagRead);
66+
if(reader->protocol != PROTOCOL_NO) {
67+
const char* protocol_name =
68+
protocol_dict_get_name(reader->dict, reader->protocol);
69+
if(strcmp(protocol_name, reader->requested_protocol) == 0) {
70+
size_t size = protocol_dict_get_data_size(reader->dict, reader->protocol);
71+
uint8_t* data = malloc(size);
72+
protocol_dict_get_data(reader->dict, reader->protocol, data, size);
73+
if(reader->callback) {
74+
FURI_LOG_D(TAG, "Tag %s detected", protocol_name);
75+
reader->callback(data, size, reader->callback_context);
76+
} else {
77+
FURI_LOG_W(TAG, "No callback set for tag %s", protocol_name);
78+
}
79+
free(data);
80+
} else {
81+
FURI_LOG_W(TAG, "Unsupported tag %s, expected EM4100", protocol_name);
82+
}
83+
}
84+
reader->protocol = PROTOCOL_NO;
85+
lfrfid_worker_read_start(
86+
reader->worker, LFRFIDWorkerReadTypeASKOnly, lfrfid_cli_read_callback, reader);
87+
} else if((flags & LFRFIDReaderEventStopThread) == LFRFIDReaderEventStopThread) {
88+
break;
89+
}
90+
}
91+
}
92+
lfrfid_worker_stop(reader->worker);
93+
lfrfid_worker_stop_thread(reader->worker);
94+
FURI_LOG_D(TAG, "LfRfidReader thread exiting");
95+
return 0;
96+
}
97+
98+
void lfrfid_reader_start(LFRFIDReader* reader) {
99+
reader->thread =
100+
furi_thread_alloc_ex("lfrfid_reader", 2048, lfrfid_reader_start_thread, reader);
101+
furi_thread_start(reader->thread);
102+
}
103+
104+
void lfrfid_reader_stop(LFRFIDReader* reader) {
105+
if(reader->thread) {
106+
furi_thread_flags_set(furi_thread_get_id(reader->thread), LFRFIDReaderEventStopThread);
107+
furi_thread_join(reader->thread);
108+
reader->thread = NULL;
109+
}
110+
}
111+
112+
void lfrfid_reader_free(LFRFIDReader* reader) {
113+
lfrfid_reader_stop(reader);
114+
protocol_dict_free(reader->dict);
115+
lfrfid_worker_free(reader->worker);
116+
free(reader);
117+
}

lfrfid_reader.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
3+
/**
4+
* @file lfrfid_reader.h
5+
* @brief EM4100 tag reader, inspired by applications/main/lfrfid/lfrfid_cli.c
6+
* @details This file contains the declaration of the LFRFIDReader structure and its functions. You typically allocate a new LFRFIDReader, set the tag detection callback, start the reader. The tag detection callback is called each time a tag is detected. Once you are done, you stop the reader and free it.
7+
* @author CodeAllNight (MrDerekJamison)
8+
*/
9+
10+
#include <furi.h>
11+
12+
typedef struct LFRFIDReader LFRFIDReader;
13+
14+
/**
15+
* @brief Callback function for tag detection.
16+
* @param data Tag data.
17+
* @param length Tag data length.
18+
* @param context Callback context.
19+
*/
20+
typedef void (*LFRFIDReaderTagCallback)(uint8_t* data, uint8_t length, void* context);
21+
22+
/**
23+
* @brief Allocates a new LFRFIDReader.
24+
* @return LFRFIDReader* Pointer to the allocated LFRFIDReader.
25+
*/
26+
LFRFIDReader* lfrfid_reader_alloc();
27+
28+
/**
29+
* @brief Sets the tag detection callback.
30+
* @param reader LFRFIDReader to set the callback for.
31+
* @param requested_protocol Requested protocol, e.g. "EM4100".
32+
* @param callback Callback function.
33+
* @param context Callback context.
34+
*/
35+
void lfrfid_reader_set_tag_callback(
36+
LFRFIDReader* reader,
37+
char* requested_protocol,
38+
LFRFIDReaderTagCallback callback,
39+
void* context);
40+
41+
/**
42+
* @brief Starts the LFRFIDReader.
43+
* @param reader LFRFIDReader to start.
44+
*/
45+
void lfrfid_reader_start(LFRFIDReader* reader);
46+
47+
/**
48+
* @brief Stops the LFRFIDReader.
49+
* @param reader LFRFIDReader to stop.
50+
*/
51+
void lfrfid_reader_stop(LFRFIDReader* reader);
52+
53+
/**
54+
* @brief Frees the LFRFIDReader.
55+
* @param reader LFRFIDReader to free.
56+
*/
57+
void lfrfid_reader_free(LFRFIDReader* reader);

0 commit comments

Comments
 (0)