Skip to content

Commit ecf253a

Browse files
committed
Saved emulate 90% functional
Config settings now modify emulation - RFID / GPIO option working - Track selection option working (unconfirmed) - Interpacket and clock delay modification working Upcoming TODO - Reverse track setting + emulation code - Rework displayed card data (currently just displays Track 2) - Redo "Add Manually" process for new file format (currently just sets & saves Track 2)
1 parent d0faf35 commit ecf253a

7 files changed

+158
-46
lines changed

helpers/mag_helpers.c

+129-26
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "mag_helpers.h"
2+
#include "../mag_i.h"
23

34
#define GPIO_PIN_A &gpio_ext_pa6
45
#define GPIO_PIN_B &gpio_ext_pa7
@@ -7,48 +8,61 @@
78
#define ZERO_PREFIX 25 // n zeros prefix
89
#define ZERO_BETWEEN 53 // n zeros between tracks
910
#define ZERO_SUFFIX 25 // n zeros suffix
10-
#define US_CLOCK 240
11-
#define US_INTERPACKET 10
11+
//#define US_CLOCK 240
12+
//#define US_INTERPACKET 10
1213

1314
// bits per char on a given track
1415
const uint8_t bitlen[] = {7, 5, 5};
1516
// char offset by track
1617
const int sublen[] = {32, 48, 48};
1718
uint8_t bit_dir = 0;
1819

19-
void play_bit_rfid(uint8_t send_bit) {
20+
void play_bit_rfid(uint8_t send_bit, MagSetting* setting) {
2021
// internal TX over RFID coil
2122
bit_dir ^= 1;
2223
furi_hal_gpio_write(RFID_PIN, bit_dir);
23-
furi_delay_us(US_CLOCK);
24+
furi_delay_us(setting->us_clock);
2425

2526
if(send_bit) {
2627
bit_dir ^= 1;
2728
furi_hal_gpio_write(RFID_PIN, bit_dir);
2829
}
29-
furi_delay_us(US_CLOCK);
30+
furi_delay_us(setting->us_clock);
3031

31-
furi_delay_us(US_INTERPACKET);
32+
furi_delay_us(setting->us_interpacket);
3233
}
3334

34-
/*static void play_bit_gpio(uint8_t send_bit) {
35+
void play_bit_gpio(uint8_t send_bit, MagSetting* setting) {
3536
// external TX over motor driver wired to PIN_A and PIN_B
3637
bit_dir ^= 1;
3738
furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
3839
furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
39-
furi_delay_us(US_CLOCK);
40+
furi_delay_us(setting->us_clock);
4041

4142
if(send_bit) {
4243
bit_dir ^= 1;
4344
furi_hal_gpio_write(GPIO_PIN_A, bit_dir);
4445
furi_hal_gpio_write(GPIO_PIN_B, !bit_dir);
4546
}
46-
furi_delay_us(US_CLOCK);
47+
furi_delay_us(setting->us_clock);
4748

48-
furi_delay_us(US_INTERPACKET);
49-
}*/
49+
furi_delay_us(setting->us_interpacket);
50+
}
51+
52+
bool play_bit(uint8_t send_bit, MagSetting* setting) {
53+
// Initialize configured TX method
54+
if(setting->tx == MagTxStateRFID) {
55+
play_bit_rfid(send_bit, setting);
56+
} else if(setting->tx == MagTxStateGPIOA6A7) {
57+
play_bit_gpio(send_bit, setting);
58+
} else {
59+
return false;
60+
}
5061

51-
void rfid_tx_init() {
62+
return true;
63+
}
64+
65+
void tx_init_rfid() {
5266
// initialize RFID system for TX
5367
furi_hal_power_enable_otg();
5468

@@ -73,29 +87,54 @@ void rfid_tx_init() {
7387
furi_delay_ms(300);
7488
}
7589

76-
void rfid_tx_reset() {
90+
void tx_reset_rfid() {
7791
// reset RFID system
7892
furi_hal_gpio_write(RFID_PIN, 0);
7993

8094
furi_hal_rfid_pins_reset();
8195
furi_hal_power_disable_otg();
8296
}
8397

84-
/*
85-
static void gpio_tx_init() {
98+
void tx_init_gpio() {
8699
furi_hal_power_enable_otg();
87-
gpio_item_configure_all_pins(GpioModeOutputPushPull);
100+
// gpio_item_configure_all_pins(GpioModeOutputPushPull);
101+
furi_hal_gpio_init(GPIO_PIN_A, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
102+
furi_hal_gpio_init(GPIO_PIN_B, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
88103
}
89104

90-
static void gpio_tx_reset() {
91-
gpio_item_set_pin(PIN_A, 0);
92-
gpio_item_set_pin(PIN_B, 0);
93-
gpio_item_set_pin(ENABLE_PIN, 0);
105+
void tx_reset_gpio() {
106+
furi_hal_gpio_write(GPIO_PIN_A, 0);
107+
furi_hal_gpio_write(GPIO_PIN_B, 0);
94108

95-
gpio_item_configure_all_pins(GpioModeAnalog);
109+
//gpio_item_configure_all_pins(GpioModeAnalog);
96110
furi_hal_power_disable_otg();
97111
}
98-
*/
112+
113+
bool tx_init(MagSetting* setting) {
114+
// Initialize configured TX method
115+
if(setting->tx == MagTxStateRFID) {
116+
tx_init_rfid();
117+
} else if(setting->tx == MagTxStateGPIOA6A7) {
118+
tx_init_gpio();
119+
} else {
120+
return false;
121+
}
122+
123+
return true;
124+
}
125+
126+
bool tx_reset(MagSetting* setting) {
127+
// Reset configured TX method
128+
if(setting->tx == MagTxStateRFID) {
129+
tx_reset_rfid();
130+
} else if(setting->tx == MagTxStateGPIOA6A7) {
131+
tx_reset_gpio();
132+
} else {
133+
return false;
134+
}
135+
136+
return true;
137+
}
99138

100139
void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_index) {
101140
// convert individual track to bits
@@ -139,10 +178,11 @@ void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_ind
139178
//furi_assert(is_correct_length);
140179
}
141180

181+
/*
142182
void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index) {
143183
// Quick testing...
144184
145-
rfid_tx_init();
185+
tx_init_rfid();
146186
147187
size_t from;
148188
size_t to;
@@ -173,13 +213,13 @@ void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index) {
173213
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
174214
FURI_CRITICAL_EXIT();
175215
176-
rfid_tx_reset();
216+
tx_reset_rfid();
177217
}
178218
179219
void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2) {
180220
// Quick testing...
181221
182-
rfid_tx_init();
222+
tx_init_rfid();
183223
184224
const char* data1 = furi_string_get_cstr(track1);
185225
uint8_t bit_array1[(strlen(data1) * bitlen[0]) + 1];
@@ -197,7 +237,70 @@ void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2) {
197237
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) play_bit_rfid(0);
198238
FURI_CRITICAL_EXIT();
199239
200-
rfid_tx_reset();
240+
tx_reset_rfid();
241+
}*/
242+
243+
void mag_spoof(Mag* mag) {
244+
MagSetting* setting = mag->setting;
245+
246+
// precompute tracks (WIP; ignores reverse and 3rd track)
247+
// likely will be reworked to Samy's bitmap method anyway...
248+
const char* data1 = furi_string_get_cstr(mag->mag_dev->dev_data.track[0].str);
249+
const char* data2 = furi_string_get_cstr(mag->mag_dev->dev_data.track[0].str);
250+
uint8_t bit_array1[(strlen(data1) * bitlen[0]) + 1];
251+
uint8_t bit_array2[(strlen(data2) * bitlen[1]) + 1];
252+
track_to_bits(bit_array1, data1, 0);
253+
track_to_bits(bit_array2, data2, 1);
254+
255+
bool spoofed = false;
256+
do {
257+
// Initialize configured TX method
258+
if(!tx_init(setting)) break;
259+
260+
// Critical timing section (need to eliminate ifs? does this impact timing?)
261+
FURI_CRITICAL_ENTER();
262+
// Prefix of zeros
263+
for(uint8_t i = 0; i < ZERO_PREFIX; i++) {
264+
if(!play_bit(0, setting)) break;
265+
}
266+
267+
// Track 1
268+
if((setting->track == MagTrackStateAll) || (setting->track == MagTrackStateOne)) {
269+
for(uint8_t i = 0; bit_array1[i] != 2; i++) {
270+
if(!play_bit((bit_array1[i] & 1), setting)) break;
271+
}
272+
}
273+
274+
// Zeros between tracks
275+
if(setting->track == MagTrackStateAll) {
276+
for(uint8_t i = 0; i < ZERO_BETWEEN; i++) {
277+
if(!play_bit(0, setting)) break;
278+
}
279+
}
280+
281+
// Track 2 (TODO: Reverse track)
282+
if((setting->track == MagTrackStateAll) || (setting->track == MagTrackStateTwo)) {
283+
for(uint8_t i = 0; bit_array2[i] != 2; i++) {
284+
if(!play_bit((bit_array2[i] & 1), setting)) break;
285+
}
286+
}
287+
288+
// Suffix of zeros
289+
for(uint8_t i = 0; i < ZERO_SUFFIX; i++) {
290+
if(!play_bit(0, setting)) break;
291+
}
292+
FURI_CRITICAL_EXIT();
293+
294+
// Reset configured TX method
295+
if(!tx_reset(setting)) break;
296+
spoofed = true;
297+
} while(0);
298+
299+
UNUSED(spoofed);
300+
/*if(!spoofed) {
301+
// error handling?
302+
// cleanup?
303+
}*/
201304
}
202305

203306
//// @antirez's code from protoview for bitmapping. May want to refactor to use this...

helpers/mag_helpers.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
#include <stdio.h>
33
#include <string.h>
44

5-
void play_bit_rfid(uint8_t send_bit);
6-
// void play_bit_gpio(uint8_t send_bit);
7-
void rfid_tx_init();
8-
void rfid_tx_reset();
5+
void play_bit_rfid(uint8_t send_bit, MagSetting* setting);
6+
void play_bit_gpio(uint8_t send_bit, MagSetting* setting);
7+
bool play_bit(uint8_t send_bit, MagSetting* setting);
8+
void tx_init_rfid();
9+
void tx_init_gpio();
10+
void tx_reset_rfid();
11+
void tx_reset_gpio();
12+
bool tx_init(MagSetting* setting);
13+
bool tx_reset(MagSetting* setting);
914
void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_index);
10-
void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index);
11-
void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2);
15+
//void mag_spoof_single_track_rfid(FuriString* track_str, uint8_t track_index);
16+
//void mag_spoof_two_track_rfid(FuriString* track1, FuriString* track2);
17+
void mag_spoof(Mag* mag);
1218
void set_bit(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val);
1319
bool get_bit(uint8_t* b, uint32_t blen, uint32_t bitpos);

mag_i.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
#include "mag_device.h"
4-
#include "helpers/mag_helpers.h"
4+
//#include "helpers/mag_helpers.h"
55
#include "helpers/mag_text_input.h"
66
#include "helpers/mag_types.h"
77

scenes/mag_scene_emulate.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "../mag_i.h"
2+
#include "../helpers/mag_helpers.h"
23

34
void mag_scene_emulate_on_enter(void* context) {
45
Mag* mag = context;
@@ -39,17 +40,18 @@ bool mag_scene_emulate_on_event(void* context, SceneManagerEvent event) {
3940
} else if(event.event == GuiButtonTypeRight) {
4041
consumed = true;
4142

42-
FuriString* tmp_str;
43-
tmp_str = furi_string_alloc_set_str(
44-
furi_string_get_cstr(mag->mag_dev->dev_data.track[1].str));
43+
//FuriString* tmp_str;
44+
//tmp_str = furi_string_alloc_set_str(
45+
// furi_string_get_cstr(mag->mag_dev->dev_data.track[1].str));
4546

4647
// Assumes track 2 for temporary testing.
4748
// Will overhaul alongside file format and config system
4849
notification_message(mag->notifications, &sequence_blink_start_cyan);
49-
mag_spoof_single_track_rfid(tmp_str, 1);
50+
mag_spoof(mag);
51+
//mag_spoof_single_track_rfid(tmp_str, 1);
5052
notification_message(mag->notifications, &sequence_blink_stop);
5153

52-
furi_string_free(tmp_str);
54+
//furi_string_free(tmp_str);
5355
}
5456
}
5557

scenes/mag_scene_emulate_config.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void mag_scene_emulate_config_on_enter(void* context) {
193193
// Reverse
194194
item = variable_item_list_add(
195195
mag->variable_item_list,
196-
"Reverse:",
196+
"Reverse (WIP):",
197197
REVERSE_COUNT,
198198
mag_scene_emulate_config_set_reverse,
199199
mag);

scenes/mag_scene_emulate_test.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static void play_bit(uint8_t send_bit) {
4141
furi_delay_us(CLOCK_US);
4242
}
4343

44-
static void mag_spoof(FuriString* track_str, uint8_t track) {
44+
static void mag_spoof_test(FuriString* track_str, uint8_t track) {
4545
furi_hal_power_enable_otg();
4646

4747
size_t from;
@@ -186,7 +186,7 @@ bool mag_scene_emulate_test_on_event(void* context, SceneManagerEvent event) {
186186

187187
// blink led while spoofing
188188
notification_message(mag->notifications, &sequence_blink_start_cyan);
189-
mag_spoof(v, TEST_TRACK);
189+
mag_spoof_test(v, TEST_TRACK);
190190
// mag_spoof_single_track_rfid(v, TEST_TRACK);
191191
notification_message(mag->notifications, &sequence_blink_stop);
192192

scenes/mag_scene_start.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "../mag_i.h"
22

33
typedef enum {
4-
SubmenuIndexEmulateTest,
4+
//SubmenuIndexEmulateTest,
55
SubmenuIndexSaved,
66
SubmenuIndexAddManually,
77
} SubmenuIndex;
@@ -16,12 +16,12 @@ void mag_scene_start_on_enter(void* context) {
1616
Mag* mag = context;
1717
Submenu* submenu = mag->submenu;
1818

19-
submenu_add_item(
19+
/*submenu_add_item(
2020
submenu,
2121
"Emulate (Hardcoded)",
2222
SubmenuIndexEmulateTest,
2323
mag_scene_start_submenu_callback,
24-
mag);
24+
mag);*/
2525
submenu_add_item(submenu, "Saved", SubmenuIndexSaved, mag_scene_start_submenu_callback, mag);
2626
submenu_add_item(
2727
submenu, "Add Manually", SubmenuIndexAddManually, mag_scene_start_submenu_callback, mag);
@@ -40,10 +40,11 @@ bool mag_scene_start_on_event(void* context, SceneManagerEvent event) {
4040
bool consumed = false;
4141

4242
if(event.type == SceneManagerEventTypeCustom) {
43-
if(event.event == SubmenuIndexEmulateTest) {
43+
/*if(event.event == SubmenuIndexEmulateTest) {
4444
scene_manager_next_scene(mag->scene_manager, MagSceneEmulateTest);
4545
consumed = true;
46-
} else if(event.event == SubmenuIndexSaved) {
46+
} else */
47+
if(event.event == SubmenuIndexSaved) {
4748
furi_string_set(mag->file_path, MAG_APP_FOLDER);
4849
scene_manager_next_scene(mag->scene_manager, MagSceneFileSelect);
4950
consumed = true;

0 commit comments

Comments
 (0)