Skip to content

Commit

Permalink
Up button scans EM4100 health tag.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamisonderek committed Sep 2, 2024
1 parent f0181ef commit bb8b73f
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 0 deletions.
16 changes: 16 additions & 0 deletions infrared_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,19 @@ bool infrared_controller_receive(InfraredController* controller) {

return hit;
}

void infrared_controller_pause(InfraredController* controller) {
if(controller->worker_rx_active) {
FURI_LOG_I(TAG, "Stopping RX worker");
infrared_worker_rx_stop(controller->worker);
controller->worker_rx_active = false;
}
}

void infrared_controller_resume(InfraredController* controller) {
if(!controller->worker_rx_active) {
FURI_LOG_I(TAG, "Starting RX worker");
infrared_worker_rx_start(controller->worker);
controller->worker_rx_active = true;
}
}
2 changes: 2 additions & 0 deletions infrared_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ void infrared_controller_free(InfraredController* controller);
void infrared_controller_set_team(InfraredController* controller, LaserTagTeam team);
void infrared_controller_send(InfraredController* controller);
bool infrared_controller_receive(InfraredController* controller);
void infrared_controller_pause(InfraredController* controller);
void infrared_controller_resume(InfraredController* controller);

#define IR_COMMAND_RED_TEAM 0xA1
#define IR_COMMAND_BLUE_TEAM 0xB2
79 changes: 79 additions & 0 deletions laser_tag_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "laser_tag_view.h"
#include "infrared_controller.h"
#include "game_state.h"
#include "lfrfid_reader.h"
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
Expand All @@ -20,6 +21,7 @@ struct LaserTagApp {
GameState* game_state;
LaserTagState state;
bool need_redraw;
LFRFIDReader* reader;
};

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

static bool matching_team(LaserTagApp* app, uint8_t data) {
if(data == 0) {
return true;
} else if(game_state_get_team(app->game_state) == TeamRed) {
return data == 0xA1;
} else if(game_state_get_team(app->game_state) == TeamBlue) {
return data == 0xB2;
}
return false;
}

static void tag_callback(uint8_t* data, uint8_t length, void* context) {
LaserTagApp* app = (LaserTagApp*)context;

if(length != 5) {
FURI_LOG_W(TAG, "Tag is not for game. Length: %d", length);
return;
}

if(data[0] != 0x13 || data[1] != 0x37) {
FURI_LOG_D(
TAG,
"Tag is not for game. Data: %02x %02x %02x %02x %02x",
data[0],
data[1],
data[2],
data[3],
data[4]);
return;
}

if(matching_team(app, data[2])) {
if(data[3] == 0xFD) {
uint16_t max_delta_ammo = data[4];
uint16_t ammo = game_state_get_ammo(app->game_state);
uint16_t delta_ammo = INITIAL_AMMO - ammo;
if(delta_ammo > max_delta_ammo) {
delta_ammo = max_delta_ammo;
}
game_state_increase_ammo(app->game_state, delta_ammo);
FURI_LOG_D(TAG, "Increased ammo by: %d", delta_ammo);
} else {
FURI_LOG_W(TAG, "Tag action unknown: %02x %02x", data[3], data[4]);
}
} else {
FURI_LOG_I(TAG, "Tag not for team: %02x", data[2]);
}
}

LaserTagApp* laser_tag_app_alloc() {
FURI_LOG_D(TAG, "Allocating Laser Tag App");
LaserTagApp* app = malloc(sizeof(LaserTagApp));
Expand Down Expand Up @@ -186,6 +237,9 @@ LaserTagApp* laser_tag_app_alloc() {
}
FURI_LOG_I(TAG, "Timer allocated");

app->reader = lfrfid_reader_alloc();
lfrfid_reader_set_tag_callback(app->reader, "EM4100", tag_callback, app);

furi_timer_start(app->timer, furi_kernel_get_tick_frequency());
FURI_LOG_D(TAG, "Timer started");

Expand All @@ -205,6 +259,10 @@ void laser_tag_app_free(LaserTagApp* app) {
if(app->ir_controller) {
infrared_controller_free(app->ir_controller);
}
if(app->reader) {
lfrfid_reader_free(app->reader);
app->reader = NULL;
}
free(app->game_state);
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION);
Expand Down Expand Up @@ -356,6 +414,27 @@ int32_t laser_tag_app(void* p) {
FURI_LOG_I(TAG, "OK key pressed, firing laser");
laser_tag_app_fire(app);
break;
case InputKeyUp:
FURI_LOG_I(TAG, "Up key pressed, scanning for ammo");
notification_message(app->notifications, &sequence_short_beep);
uint16_t ammo = game_state_get_ammo(app->game_state);
infrared_controller_pause(app->ir_controller);
lfrfid_reader_start(app->reader);
for(int i = 0; i < 30; i++) {
furi_delay_ms(100);
if(ammo != game_state_get_ammo(app->game_state)) {
break;
}
}
lfrfid_reader_stop(app->reader);
infrared_controller_resume(app->ir_controller);
if(ammo != game_state_get_ammo(app->game_state)) {
notification_message(app->notifications, &sequence_success);
} else {
notification_message(app->notifications, &sequence_error);
}
app->need_redraw = true;
break;
default:
break;
}
Expand Down
117 changes: 117 additions & 0 deletions lfrfid_reader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "lfrfid_reader.h"
#include <lfrfid/protocols/lfrfid_protocols.h>
#include <toolbox/protocols/protocol_dict.h>
#include <lib/lfrfid/lfrfid_worker.h>

#define TAG "LfRfid_Reader"

typedef enum {
LFRFIDReaderEventTagRead = (1 << 0),
LFRFIDReaderEventStopThread = (1 << 1),
LFRFIDReaderEventAll = (LFRFIDReaderEventTagRead | LFRFIDReaderEventStopThread),
} LFRFIDReaderEventType;

struct LFRFIDReader {
char* requested_protocol;
ProtocolId protocol;
ProtocolDict* dict;
LFRFIDWorker* worker;
FuriThread* thread;
LFRFIDReaderTagCallback callback;
void* callback_context;
};

static void lfrfid_cli_read_callback(LFRFIDWorkerReadResult result, ProtocolId proto, void* ctx) {
furi_assert(ctx);
LFRFIDReader* context = ctx;
if(result == LFRFIDWorkerReadDone) {
context->protocol = proto;
furi_thread_flags_set(furi_thread_get_id(context->thread), LFRFIDReaderEventTagRead);
}
}

LFRFIDReader* lfrfid_reader_alloc() {
LFRFIDReader* reader = malloc(sizeof(LFRFIDReader));
reader->protocol = PROTOCOL_NO;
reader->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
reader->worker = lfrfid_worker_alloc(reader->dict);

return reader;
}

void lfrfid_reader_set_tag_callback(
LFRFIDReader* reader,
char* requested_protocol,
LFRFIDReaderTagCallback callback,
void* context) {
furi_assert(reader);
furi_assert(requested_protocol);
reader->requested_protocol = requested_protocol;
reader->callback = callback;
reader->callback_context = context;
}

static int32_t lfrfid_reader_start_thread(void* ctx) {
LFRFIDReader* reader = (LFRFIDReader*)ctx;
furi_thread_flags_clear(LFRFIDReaderEventAll);
lfrfid_worker_start_thread(reader->worker);
lfrfid_worker_read_start(
reader->worker, LFRFIDWorkerReadTypeASKOnly, lfrfid_cli_read_callback, reader);
while(true) {
uint32_t flags = furi_thread_flags_wait(LFRFIDReaderEventAll, FuriFlagWaitAny, 100);

if(flags != (unsigned)FuriFlagErrorTimeout) {
if((flags & LFRFIDReaderEventTagRead) == LFRFIDReaderEventTagRead) {
furi_thread_flags_clear(LFRFIDReaderEventTagRead);
if(reader->protocol != PROTOCOL_NO) {
const char* protocol_name =
protocol_dict_get_name(reader->dict, reader->protocol);
if(strcmp(protocol_name, reader->requested_protocol) == 0) {
size_t size = protocol_dict_get_data_size(reader->dict, reader->protocol);
uint8_t* data = malloc(size);
protocol_dict_get_data(reader->dict, reader->protocol, data, size);
if(reader->callback) {
FURI_LOG_D(TAG, "Tag %s detected", protocol_name);
reader->callback(data, size, reader->callback_context);
} else {
FURI_LOG_W(TAG, "No callback set for tag %s", protocol_name);
}
free(data);
} else {
FURI_LOG_W(TAG, "Unsupported tag %s, expected EM4100", protocol_name);
}
}
reader->protocol = PROTOCOL_NO;
lfrfid_worker_read_start(
reader->worker, LFRFIDWorkerReadTypeASKOnly, lfrfid_cli_read_callback, reader);
} else if((flags & LFRFIDReaderEventStopThread) == LFRFIDReaderEventStopThread) {
break;
}
}
}
lfrfid_worker_stop(reader->worker);
lfrfid_worker_stop_thread(reader->worker);
FURI_LOG_D(TAG, "LfRfidReader thread exiting");
return 0;
}

void lfrfid_reader_start(LFRFIDReader* reader) {
reader->thread =
furi_thread_alloc_ex("lfrfid_reader", 2048, lfrfid_reader_start_thread, reader);
furi_thread_start(reader->thread);
}

void lfrfid_reader_stop(LFRFIDReader* reader) {
if(reader->thread) {
furi_thread_flags_set(furi_thread_get_id(reader->thread), LFRFIDReaderEventStopThread);
furi_thread_join(reader->thread);
reader->thread = NULL;
}
}

void lfrfid_reader_free(LFRFIDReader* reader) {
lfrfid_reader_stop(reader);
protocol_dict_free(reader->dict);
lfrfid_worker_free(reader->worker);
free(reader);
}
57 changes: 57 additions & 0 deletions lfrfid_reader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

/**
* @file lfrfid_reader.h
* @brief EM4100 tag reader, inspired by applications/main/lfrfid/lfrfid_cli.c
* @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.
* @author CodeAllNight (MrDerekJamison)
*/

#include <furi.h>

typedef struct LFRFIDReader LFRFIDReader;

/**
* @brief Callback function for tag detection.
* @param data Tag data.
* @param length Tag data length.
* @param context Callback context.
*/
typedef void (*LFRFIDReaderTagCallback)(uint8_t* data, uint8_t length, void* context);

/**
* @brief Allocates a new LFRFIDReader.
* @return LFRFIDReader* Pointer to the allocated LFRFIDReader.
*/
LFRFIDReader* lfrfid_reader_alloc();

/**
* @brief Sets the tag detection callback.
* @param reader LFRFIDReader to set the callback for.
* @param requested_protocol Requested protocol, e.g. "EM4100".
* @param callback Callback function.
* @param context Callback context.
*/
void lfrfid_reader_set_tag_callback(
LFRFIDReader* reader,
char* requested_protocol,
LFRFIDReaderTagCallback callback,
void* context);

/**
* @brief Starts the LFRFIDReader.
* @param reader LFRFIDReader to start.
*/
void lfrfid_reader_start(LFRFIDReader* reader);

/**
* @brief Stops the LFRFIDReader.
* @param reader LFRFIDReader to stop.
*/
void lfrfid_reader_stop(LFRFIDReader* reader);

/**
* @brief Frees the LFRFIDReader.
* @param reader LFRFIDReader to free.
*/
void lfrfid_reader_free(LFRFIDReader* reader);

0 comments on commit bb8b73f

Please sign in to comment.