This commit is contained in:
Willy-JL
2024-02-15 22:48:18 +00:00
31 changed files with 495 additions and 276 deletions

View File

@@ -45,6 +45,7 @@ libs = env.BuildModules(
"xtreme",
"heatshrink",
"bit_lib",
"datetime",
],
)

22
lib/datetime/SConscript Normal file
View File

@@ -0,0 +1,22 @@
Import("env")
env.Append(
LINT_SOURCES=[
Dir("."),
],
CPPPATH=[
"#/lib/datetime",
],
SDK_HEADERS=[
File("datetime.h"),
],
)
libenv = env.Clone(FW_LIB_NAME="datetime")
libenv.ApplyLibFlags()
sources = libenv.GlobRecursive("*.c*")
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Return("lib")

104
lib/datetime/datetime.c Normal file
View File

@@ -0,0 +1,104 @@
#include "datetime.h"
#define TAG "DateTime"
#define SECONDS_PER_MINUTE 60
#define SECONDS_PER_HOUR (SECONDS_PER_MINUTE * 60)
#define SECONDS_PER_DAY (SECONDS_PER_HOUR * 24)
#define MONTHS_COUNT 12
#define EPOCH_START_YEAR 1970
static const uint8_t datetime_days_per_month[2][MONTHS_COUNT] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
static const uint16_t datetime_days_per_year[] = {365, 366};
bool datetime_validate_datetime(DateTime* datetime) {
bool invalid = false;
invalid |= (datetime->second > 59);
invalid |= (datetime->minute > 59);
invalid |= (datetime->hour > 23);
invalid |= (datetime->year < 2000);
invalid |= (datetime->year > 2099);
invalid |= (datetime->month == 0);
invalid |= (datetime->month > 12);
invalid |= (datetime->day == 0);
invalid |= (datetime->day > 31);
invalid |= (datetime->weekday == 0);
invalid |= (datetime->weekday > 7);
return !invalid;
}
uint32_t datetime_datetime_to_timestamp(DateTime* datetime) {
uint32_t timestamp = 0;
uint8_t years = 0;
uint8_t leap_years = 0;
for(uint16_t y = EPOCH_START_YEAR; y < datetime->year; y++) {
if(datetime_is_leap_year(y)) {
leap_years++;
} else {
years++;
}
}
timestamp += ((years * datetime_days_per_year[0]) + (leap_years * datetime_days_per_year[1])) *
SECONDS_PER_DAY;
bool leap_year = datetime_is_leap_year(datetime->year);
for(uint8_t m = 1; m < datetime->month; m++) {
timestamp += datetime_get_days_per_month(leap_year, m) * SECONDS_PER_DAY;
}
timestamp += (datetime->day - 1) * SECONDS_PER_DAY;
timestamp += datetime->hour * SECONDS_PER_HOUR;
timestamp += datetime->minute * SECONDS_PER_MINUTE;
timestamp += datetime->second;
return timestamp;
}
void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime) {
uint32_t days = timestamp / SECONDS_PER_DAY;
uint32_t seconds_in_day = timestamp % SECONDS_PER_DAY;
datetime->year = EPOCH_START_YEAR;
while(days >= datetime_get_days_per_year(datetime->year)) {
days -= datetime_get_days_per_year(datetime->year);
(datetime->year)++;
}
datetime->month = 1;
while(days >=
datetime_get_days_per_month(datetime_is_leap_year(datetime->year), datetime->month)) {
days -=
datetime_get_days_per_month(datetime_is_leap_year(datetime->year), datetime->month);
(datetime->month)++;
}
datetime->day = days + 1;
datetime->hour = seconds_in_day / SECONDS_PER_HOUR;
datetime->minute = (seconds_in_day % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
datetime->second = seconds_in_day % SECONDS_PER_MINUTE;
}
uint16_t datetime_get_days_per_year(uint16_t year) {
return datetime_days_per_year[datetime_is_leap_year(year) ? 1 : 0];
}
bool datetime_is_leap_year(uint16_t year) {
return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0);
}
uint8_t datetime_get_days_per_month(bool leap_year, uint8_t month) {
return datetime_days_per_month[leap_year ? 1 : 0][month - 1];
}

75
lib/datetime/datetime.h Normal file
View File

@@ -0,0 +1,75 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// Time
uint8_t hour; /**< Hour in 24H format: 0-23 */
uint8_t minute; /**< Minute: 0-59 */
uint8_t second; /**< Second: 0-59 */
// Date
uint8_t day; /**< Current day: 1-31 */
uint8_t month; /**< Current month: 1-12 */
uint16_t year; /**< Current year: 2000-2099 */
uint8_t weekday; /**< Current weekday: 1-7 */
} DateTime;
/** Validate Date Time
*
* @param datetime The datetime to validate
*
* @return { description_of_the_return_value }
*/
bool datetime_validate_datetime(DateTime* datetime);
/** Convert DateTime to UNIX timestamp
*
* @warning Mind timezone when perform conversion
*
* @param datetime The datetime (UTC)
*
* @return UNIX Timestamp in seconds from UNIX epoch start
*/
uint32_t datetime_datetime_to_timestamp(DateTime* datetime);
/** Convert UNIX timestamp to DateTime
*
* @warning Mind timezone when perform conversion
*
* @param[in] timestamp UNIX Timestamp in seconds from UNIX epoch start
* @param[out] datetime The datetime (UTC)
*/
void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime);
/** Gets the number of days in the year according to the Gregorian calendar.
*
* @param year Input year.
*
* @return number of days in `year`.
*/
uint16_t datetime_get_days_per_year(uint16_t year);
/** Check if a year a leap year in the Gregorian calendar.
*
* @param year Input year.
*
* @return true if `year` is a leap year.
*/
bool datetime_is_leap_year(uint16_t year);
/** Get the number of days in the month.
*
* @param leap_year true to calculate based on leap years
* @param month month to check, where 1 = January
* @return the number of days in the month
*/
uint8_t datetime_get_days_per_month(bool leap_year, uint8_t month);
#ifdef __cplusplus
}
#endif

View File

@@ -20,7 +20,8 @@
const ProtocolBase* lfrfid_protocols[] = {
[LFRFIDProtocolEM4100] = &protocol_em4100,
[LFRFIDProtocolEM4100_32] = &protocol_em4100_32,
[LFRFIDProtocolEM410032] = &protocol_em4100_32,
[LFRFIDProtocolEM410016] = &protocol_em4100_16,
[LFRFIDProtocolH10301] = &protocol_h10301,
[LFRFIDProtocolIdteck] = &protocol_idteck,
[LFRFIDProtocolIndala26] = &protocol_indala26,

View File

@@ -9,7 +9,8 @@ typedef enum {
typedef enum {
LFRFIDProtocolEM4100,
LFRFIDProtocolEM4100_32,
LFRFIDProtocolEM410032,
LFRFIDProtocolEM410016,
LFRFIDProtocolH10301,
LFRFIDProtocolIdteck,
LFRFIDProtocolIndala26,

View File

@@ -45,6 +45,8 @@ uint16_t protocol_em4100_get_time_divisor(ProtocolEM4100* proto) {
return 1;
case 32:
return 2;
case 16:
return 4;
default:
return 1;
}
@@ -56,6 +58,8 @@ uint32_t protocol_em4100_get_t5577_bitrate(ProtocolEM4100* proto) {
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;
}
@@ -87,6 +91,12 @@ ProtocolEM4100* protocol_em4100_alloc(void) {
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;
@@ -373,3 +383,27 @@ const ProtocolBase protocol_em4100_32 = {
.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,
};

View File

@@ -4,3 +4,5 @@
extern const ProtocolBase protocol_em4100;
extern const ProtocolBase protocol_em4100_32;
extern const ProtocolBase protocol_em4100_16;

View File

@@ -139,4 +139,4 @@ void t5577_write_with_mask(LFRFIDT5577* data, uint8_t page, bool with_pass, uint
t5577_write_reset();
FURI_CRITICAL_EXIT();
t5577_stop();
}
}