Skip to content

Commit

Permalink
lfrfid/em4100: added support for different bit rates (#3410)
Browse files Browse the repository at this point in the history
* lfrfid/em4100: added support for different bit rates
* Format Sources

Co-authored-by: Radek Pilar <radek.pilar@apollogames.com>
Co-authored-by: あく <alleteam@gmail.com>
  • Loading branch information
3 people authored Feb 15, 2024
1 parent 26ac455 commit 8780437
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 17 deletions.
2 changes: 2 additions & 0 deletions lib/lfrfid/protocols/lfrfid_protocols.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

const ProtocolBase* lfrfid_protocols[] = {
[LFRFIDProtocolEM4100] = &protocol_em4100,
[LFRFIDProtocolEM410032] = &protocol_em4100_32,
[LFRFIDProtocolEM410016] = &protocol_em4100_16,
[LFRFIDProtocolH10301] = &protocol_h10301,
[LFRFIDProtocolIdteck] = &protocol_idteck,
[LFRFIDProtocolIndala26] = &protocol_indala26,
Expand Down
2 changes: 2 additions & 0 deletions lib/lfrfid/protocols/lfrfid_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ typedef enum {

typedef enum {
LFRFIDProtocolEM4100,
LFRFIDProtocolEM410032,
LFRFIDProtocolEM410016,
LFRFIDProtocolH10301,
LFRFIDProtocolIdteck,
LFRFIDProtocolIndala26,
Expand Down
140 changes: 124 additions & 16 deletions lib/lfrfid/protocols/protocol_em4100.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,9 @@ typedef uint64_t EM4100DecodedData;
#define EM4100_DECODED_DATA_SIZE (5)
#define EM4100_ENCODED_DATA_SIZE (sizeof(EM4100DecodedData))

#define EM4100_CLOCK_PER_BIT (64)

#define EM_READ_SHORT_TIME (256)
#define EM_READ_LONG_TIME (512)
#define EM_READ_JITTER_TIME (100)

#define EM_READ_SHORT_TIME_LOW (EM_READ_SHORT_TIME - EM_READ_JITTER_TIME)
#define EM_READ_SHORT_TIME_HIGH (EM_READ_SHORT_TIME + EM_READ_JITTER_TIME)
#define EM_READ_LONG_TIME_LOW (EM_READ_LONG_TIME - EM_READ_JITTER_TIME)
#define EM_READ_LONG_TIME_HIGH (EM_READ_LONG_TIME + EM_READ_JITTER_TIME)
#define EM_READ_SHORT_TIME_BASE (256)
#define EM_READ_LONG_TIME_BASE (512)
#define EM_READ_JITTER_TIME_BASE (100)

typedef struct {
uint8_t data[EM4100_DECODED_DATA_SIZE];
Expand All @@ -43,10 +36,70 @@ typedef struct {
bool encoded_polarity;

ManchesterState decoder_manchester_state;
uint8_t clock_per_bit;
} ProtocolEM4100;

uint16_t protocol_em4100_get_time_divisor(ProtocolEM4100* proto) {
switch(proto->clock_per_bit) {
case 64:
return 1;
case 32:
return 2;
case 16:
return 4;
default:
return 1;
}
}

uint32_t protocol_em4100_get_t5577_bitrate(ProtocolEM4100* proto) {
switch(proto->clock_per_bit) {
case 64:
return LFRFID_T5577_BITRATE_RF_64;
case 32:
return LFRFID_T5577_BITRATE_RF_32;
case 16:
return LFRFID_T5577_BITRATE_RF_16;
default:
return LFRFID_T5577_BITRATE_RF_64;
}
}

uint16_t protocol_em4100_get_short_time_low(ProtocolEM4100* proto) {
return EM_READ_SHORT_TIME_BASE / protocol_em4100_get_time_divisor(proto) -
EM_READ_JITTER_TIME_BASE / protocol_em4100_get_time_divisor(proto);
}

uint16_t protocol_em4100_get_short_time_high(ProtocolEM4100* proto) {
return EM_READ_SHORT_TIME_BASE / protocol_em4100_get_time_divisor(proto) +
EM_READ_JITTER_TIME_BASE / protocol_em4100_get_time_divisor(proto);
}

uint16_t protocol_em4100_get_long_time_low(ProtocolEM4100* proto) {
return EM_READ_LONG_TIME_BASE / protocol_em4100_get_time_divisor(proto) -
EM_READ_JITTER_TIME_BASE / protocol_em4100_get_time_divisor(proto);
}

uint16_t protocol_em4100_get_long_time_high(ProtocolEM4100* proto) {
return EM_READ_LONG_TIME_BASE / protocol_em4100_get_time_divisor(proto) +
EM_READ_JITTER_TIME_BASE / protocol_em4100_get_time_divisor(proto);
}

ProtocolEM4100* protocol_em4100_alloc(void) {
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
proto->clock_per_bit = 64;
return (void*)proto;
};

ProtocolEM4100* protocol_em4100_16_alloc(void) {
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
proto->clock_per_bit = 16;
return (void*)proto;
};

ProtocolEM4100* protocol_em4100_32_alloc(void) {
ProtocolEM4100* proto = malloc(sizeof(ProtocolEM4100));
proto->clock_per_bit = 32;
return (void*)proto;
};

Expand Down Expand Up @@ -145,13 +198,16 @@ bool protocol_em4100_decoder_feed(ProtocolEM4100* proto, bool level, uint32_t du

ManchesterEvent event = ManchesterEventReset;

if(duration > EM_READ_SHORT_TIME_LOW && duration < EM_READ_SHORT_TIME_HIGH) {
if(duration > protocol_em4100_get_short_time_low(proto) &&
duration < protocol_em4100_get_short_time_high(proto)) {
if(!level) {
event = ManchesterEventShortHigh;
} else {
event = ManchesterEventShortLow;
}
} else if(duration > EM_READ_LONG_TIME_LOW && duration < EM_READ_LONG_TIME_HIGH) {
} else if(
duration > protocol_em4100_get_long_time_low(proto) &&
duration < protocol_em4100_get_long_time_high(proto)) {
if(!level) {
event = ManchesterEventLongHigh;
} else {
Expand Down Expand Up @@ -227,7 +283,7 @@ bool protocol_em4100_encoder_start(ProtocolEM4100* proto) {

LevelDuration protocol_em4100_encoder_yield(ProtocolEM4100* proto) {
bool level = (proto->encoded_data >> (63 - proto->encoded_data_index)) & 1;
uint32_t duration = EM4100_CLOCK_PER_BIT / 2;
uint32_t duration = proto->clock_per_bit / 2;

if(proto->encoded_polarity) {
proto->encoded_polarity = false;
Expand Down Expand Up @@ -260,7 +316,7 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) {

if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] =
(LFRFID_T5577_MODULATION_MANCHESTER | LFRFID_T5577_BITRATE_RF_64 |
(LFRFID_T5577_MODULATION_MANCHESTER | protocol_em4100_get_t5577_bitrate(protocol) |
(2 << LFRFID_T5577_MAXBLOCK_SHIFT));
request->t5577.block[1] = protocol->encoded_data;
request->t5577.block[2] = protocol->encoded_data >> 32;
Expand All @@ -273,7 +329,11 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) {
void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) {
uint8_t* data = protocol->data;
furi_string_printf(
result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
result,
"FC: %03u, Card: %05u (RF/%u)",
data[2],
(uint16_t)((data[3] << 8) | (data[4])),
protocol->clock_per_bit);
};

const ProtocolBase protocol_em4100 = {
Expand All @@ -298,4 +358,52 @@ const ProtocolBase protocol_em4100 = {
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
};
};

const ProtocolBase protocol_em4100_32 = {
.name = "EM4100/32",
.manufacturer = "EM-Micro",
.data_size = EM4100_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_em4100_32_alloc,
.free = (ProtocolFree)protocol_em4100_free,
.get_data = (ProtocolGetData)protocol_em4100_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_em4100_encoder_start,
.yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
};

const ProtocolBase protocol_em4100_16 = {
.name = "EM4100/16",
.manufacturer = "EM-Micro",
.data_size = EM4100_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_em4100_16_alloc,
.free = (ProtocolFree)protocol_em4100_free,
.get_data = (ProtocolGetData)protocol_em4100_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_em4100_encoder_start,
.yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
};
6 changes: 5 additions & 1 deletion lib/lfrfid/protocols/protocol_em4100.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#pragma once
#include <toolbox/protocols/protocol.h>

extern const ProtocolBase protocol_em4100;
extern const ProtocolBase protocol_em4100;

extern const ProtocolBase protocol_em4100_32;

extern const ProtocolBase protocol_em4100_16;

0 comments on commit 8780437

Please sign in to comment.