mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-27 01:58:09 -07:00
Merge remote-tracking branch 'UFW/dev' into cc1101_ext
This commit is contained in:
@@ -61,7 +61,7 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
|
||||
|
||||
// OTG power configuration
|
||||
bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V
|
||||
bq25896_regs.r0A.BOOST_LIM = BOOST_LIM_1400; // BOOST Current limit: 1.4A
|
||||
bq25896_regs.r0A.BOOST_LIM = BoostLim_1400; // BOOST Current limit: 1.4A
|
||||
furi_hal_i2c_write_reg_8(
|
||||
handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT);
|
||||
|
||||
@@ -74,6 +74,12 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
|
||||
BQ25896_I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) {
|
||||
bq25896_regs.r0A.BOOST_LIM = boost_lim;
|
||||
furi_hal_i2c_write_reg_8(
|
||||
handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
void bq25896_poweroff(FuriHalI2cBusHandle* handle) {
|
||||
bq25896_regs.r09.BATFET_DIS = 1;
|
||||
furi_hal_i2c_write_reg_8(
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
/** Initialize Driver */
|
||||
void bq25896_init(FuriHalI2cBusHandle* handle);
|
||||
|
||||
/** Set boost lim*/
|
||||
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim);
|
||||
|
||||
/** Send device into shipping mode */
|
||||
void bq25896_poweroff(FuriHalI2cBusHandle* handle);
|
||||
|
||||
|
||||
@@ -159,14 +159,16 @@ typedef struct {
|
||||
#define BOOSTV_128 (1 << 1)
|
||||
#define BOOSTV_64 (1 << 0)
|
||||
|
||||
#define BOOST_LIM_500 (0b000)
|
||||
#define BOOST_LIM_750 (0b001)
|
||||
#define BOOST_LIM_1200 (0b010)
|
||||
#define BOOST_LIM_1400 (0b011)
|
||||
#define BOOST_LIM_1650 (0b100)
|
||||
#define BOOST_LIM_1875 (0b101)
|
||||
#define BOOST_LIM_2150 (0b110)
|
||||
#define BOOST_LIM_RSVD (0b111)
|
||||
typedef enum {
|
||||
BoostLim_500 = 0b000,
|
||||
BoostLim_750 = 0b001,
|
||||
BoostLim_1200 = 0b010,
|
||||
BoostLim_1400 = 0b011,
|
||||
BoostLim_1650 = 0b100,
|
||||
BoostLim_1875 = 0b101,
|
||||
BoostLim_2150 = 0b110,
|
||||
BoostLim_Rsvd = 0b111,
|
||||
} BoostLim;
|
||||
|
||||
typedef struct {
|
||||
uint8_t BOOST_LIM : 3; // Boost Mode Current Limit
|
||||
|
||||
@@ -336,8 +336,8 @@ bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) {
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
if(index++ != target) continue;
|
||||
stream_seek(dict->stream, -(NFC_MF_CLASSIC_KEY_LEN + 1), StreamOffsetFromCurrent);
|
||||
if(!stream_delete(dict->stream, (NFC_MF_CLASSIC_KEY_LEN + 1))) break;
|
||||
stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent);
|
||||
if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break;
|
||||
dict->total_keys--;
|
||||
key_removed = true;
|
||||
}
|
||||
|
||||
+11
-4
@@ -809,6 +809,8 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
|
||||
emulator.auth_received_callback = nfc_worker_mf_ultralight_auth_received_callback;
|
||||
emulator.context = nfc_worker;
|
||||
|
||||
rfal_platform_spi_acquire();
|
||||
|
||||
while(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
|
||||
mf_ul_reset_emulation(&emulator, true);
|
||||
furi_hal_nfc_emulate_nfca(
|
||||
@@ -828,6 +830,8 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
|
||||
emulator.data_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
rfal_platform_spi_release();
|
||||
}
|
||||
|
||||
static bool nfc_worker_mf_get_b_key_from_sector_trailer(
|
||||
@@ -1103,7 +1107,9 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
|
||||
furi_hal_nfc_listen_start(nfc_data);
|
||||
while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044
|
||||
if(furi_hal_nfc_listen_rx(&tx_rx, 300)) {
|
||||
mf_classic_emulator(&emulator, &tx_rx, false);
|
||||
if(!mf_classic_emulator(&emulator, &tx_rx, false)) {
|
||||
furi_hal_nfc_listen_start(nfc_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(emulator.data_changed) {
|
||||
@@ -1378,8 +1384,6 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
||||
bool reader_no_data_notified = true;
|
||||
|
||||
while(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
|
||||
furi_hal_nfc_stop_cmd();
|
||||
furi_delay_ms(5);
|
||||
furi_hal_nfc_listen_start(nfc_data);
|
||||
if(furi_hal_nfc_listen_rx(&tx_rx, 300)) {
|
||||
if(reader_no_data_notified) {
|
||||
@@ -1390,7 +1394,9 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
||||
NfcProtocol protocol =
|
||||
reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8);
|
||||
if(protocol == NfcDeviceProtocolMifareClassic) {
|
||||
mf_classic_emulator(&emulator, &tx_rx, true);
|
||||
if(!mf_classic_emulator(&emulator, &tx_rx, true)) {
|
||||
furi_hal_nfc_listen_start(nfc_data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader_no_data_received_cnt++;
|
||||
@@ -1402,6 +1408,7 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
||||
FURI_LOG_D(TAG, "No data from reader");
|
||||
continue;
|
||||
}
|
||||
furi_delay_ms(1);
|
||||
}
|
||||
|
||||
rfal_platform_spi_release();
|
||||
|
||||
@@ -869,7 +869,7 @@ bool mf_classic_emulator(
|
||||
if(!furi_hal_nfc_tx_rx(tx_rx, 300)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Error in tx rx. Tx :%d bits, Rx: %d bits",
|
||||
"Error in tx rx. Tx: %d bits, Rx: %d bits",
|
||||
tx_rx->tx_bits,
|
||||
tx_rx->rx_bits);
|
||||
break;
|
||||
@@ -883,12 +883,17 @@ bool mf_classic_emulator(
|
||||
break;
|
||||
}
|
||||
|
||||
if(cmd == 0x50 && plain_data[1] == 0x00) {
|
||||
if(cmd == NFCA_CMD_HALT && plain_data[1] == 0x00) {
|
||||
FURI_LOG_T(TAG, "Halt received");
|
||||
furi_hal_nfc_listen_sleep();
|
||||
command_processed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cmd == NFCA_CMD_RATS && !is_encrypted) {
|
||||
// Mifare Classic doesn't support ATS, NACK it and start listening again
|
||||
FURI_LOG_T(TAG, "RATS received");
|
||||
break;
|
||||
}
|
||||
|
||||
if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD || cmd == MF_CLASSIC_AUTH_KEY_B_CMD) {
|
||||
uint8_t block = plain_data[1];
|
||||
uint64_t key = 0;
|
||||
@@ -903,8 +908,7 @@ bool mf_classic_emulator(
|
||||
access_key = MfClassicKeyA;
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Key not known");
|
||||
command_processed = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(mf_classic_is_key_found(
|
||||
@@ -914,8 +918,7 @@ bool mf_classic_emulator(
|
||||
access_key = MfClassicKeyB;
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Key not known");
|
||||
command_processed = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -943,16 +946,14 @@ bool mf_classic_emulator(
|
||||
tx_rx->tx_bits = sizeof(nt) * 8;
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||
}
|
||||
|
||||
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
||||
FURI_LOG_E(TAG, "Error in NT exchange");
|
||||
command_processed = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tx_rx->rx_bits != 64) {
|
||||
FURI_LOG_W(TAG, "Incorrect nr + ar length: %d", tx_rx->rx_bits);
|
||||
command_processed = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4);
|
||||
@@ -963,8 +964,7 @@ bool mf_classic_emulator(
|
||||
if(cardRr != prng_successor(nonce, 64)) {
|
||||
FURI_LOG_T(TAG, "Wrong AUTH! %08lX != %08lX", cardRr, prng_successor(nonce, 64));
|
||||
// Don't send NACK, as the tag doesn't send it
|
||||
command_processed = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ans = prng_successor(nonce, 96);
|
||||
@@ -1156,6 +1156,7 @@ bool mf_classic_emulator(
|
||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||
tx_rx->tx_bits = 4;
|
||||
furi_hal_nfc_tx_rx(tx_rx, 300);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1164,7 +1165,7 @@ bool mf_classic_emulator(
|
||||
void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto) {
|
||||
furi_assert(tx_rx);
|
||||
|
||||
uint8_t plain_data[4] = {0x50, 0x00, 0x00, 0x00};
|
||||
uint8_t plain_data[4] = {NFCA_CMD_HALT, 0x00, 0x00, 0x00};
|
||||
|
||||
nfca_append_crc16(plain_data, 2);
|
||||
if(crypto) {
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define NFCA_CMD_RATS (0xE0U)
|
||||
|
||||
#define NFCA_CRC_INIT (0x6363)
|
||||
|
||||
#define NFCA_F_SIG (13560000.0)
|
||||
@@ -22,7 +20,7 @@ typedef struct {
|
||||
|
||||
static uint8_t nfca_default_ats[] = {0x05, 0x78, 0x80, 0x80, 0x00};
|
||||
|
||||
static uint8_t nfca_sleep_req[] = {0x50, 0x00};
|
||||
static uint8_t nfca_halt_req[] = {NFCA_CMD_HALT, 0x00};
|
||||
|
||||
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) {
|
||||
uint16_t crc = NFCA_CRC_INIT;
|
||||
@@ -50,17 +48,17 @@ bool nfca_emulation_handler(
|
||||
uint16_t buff_rx_len,
|
||||
uint8_t* buff_tx,
|
||||
uint16_t* buff_tx_len) {
|
||||
bool sleep = false;
|
||||
bool halt = false;
|
||||
uint8_t rx_bytes = buff_rx_len / 8;
|
||||
|
||||
if(rx_bytes == sizeof(nfca_sleep_req) && !memcmp(buff_rx, nfca_sleep_req, rx_bytes)) {
|
||||
sleep = true;
|
||||
if(rx_bytes == sizeof(nfca_halt_req) && !memcmp(buff_rx, nfca_halt_req, rx_bytes)) {
|
||||
halt = true;
|
||||
} else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) {
|
||||
memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats));
|
||||
*buff_tx_len = sizeof(nfca_default_ats) * 8;
|
||||
}
|
||||
|
||||
return sleep;
|
||||
return halt;
|
||||
}
|
||||
|
||||
static void nfca_add_bit(DigitalSignal* signal, bool bit) {
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#include <lib/digital_signal/digital_signal.h>
|
||||
|
||||
#define NFCA_CMD_RATS (0xE0U)
|
||||
#define NFCA_CMD_HALT (0x50U)
|
||||
|
||||
typedef struct {
|
||||
DigitalSignal* one;
|
||||
DigitalSignal* zero;
|
||||
|
||||
@@ -110,7 +110,9 @@ void subghz_protocol_encoder_faac_slh_free(void* context) {
|
||||
}
|
||||
|
||||
static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* instance) {
|
||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||
if(instance->generic.seed != 0x0) {
|
||||
instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult();
|
||||
}
|
||||
uint32_t fix = instance->generic.serial << 4 | instance->generic.btn;
|
||||
uint32_t hop = 0;
|
||||
uint32_t decrypt = 0;
|
||||
@@ -499,21 +501,39 @@ void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* outp
|
||||
uint32_t code_fix = instance->generic.data >> 32;
|
||||
uint32_t code_hop = instance->generic.data & 0xFFFFFFFF;
|
||||
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%lX%08lX\r\n"
|
||||
"Fix:%08lX Cnt:%05lX\r\n"
|
||||
"Hop:%08lX Btn:%X\r\n"
|
||||
"Sn:%07lX Sd:%08lX",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
(uint32_t)(instance->generic.data >> 32),
|
||||
(uint32_t)instance->generic.data,
|
||||
code_fix,
|
||||
instance->generic.cnt,
|
||||
code_hop,
|
||||
instance->generic.btn,
|
||||
instance->generic.serial,
|
||||
instance->generic.seed);
|
||||
if(instance->generic.seed == 0x0) {
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%lX%08lX\r\n"
|
||||
"Fix:%08lX\r\n"
|
||||
"Hop:%08lX Btn:%X\r\n"
|
||||
"Sn:%07lX Sd:Unknown",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
(uint32_t)(instance->generic.data >> 32),
|
||||
(uint32_t)instance->generic.data,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->generic.btn,
|
||||
instance->generic.serial);
|
||||
} else {
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%lX%08lX\r\n"
|
||||
"Fix:%08lX Cnt:%05lX\r\n"
|
||||
"Hop:%08lX Btn:%X\r\n"
|
||||
"Sn:%07lX Sd:%08lX",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
(uint32_t)(instance->generic.data >> 32),
|
||||
(uint32_t)instance->generic.data,
|
||||
code_fix,
|
||||
instance->generic.cnt,
|
||||
code_hop,
|
||||
instance->generic.btn,
|
||||
instance->generic.serial,
|
||||
instance->generic.seed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,9 @@ static bool subghz_protocol_keeloq_gen_data(
|
||||
} else if(strcmp(instance->manufacture_name, "Beninca") == 0) {
|
||||
decrypt = btn << 28 | (0x000) << 16 | instance->generic.cnt;
|
||||
// Beninca / Allmatic -> no serial - simple XOR
|
||||
} else if(strcmp(instance->manufacture_name, "Centurion") == 0) {
|
||||
decrypt = btn << 28 | (0x1CE) << 16 | instance->generic.cnt;
|
||||
// Centurion -> no serial in hop, uses fixed value 0x1CE - normal learning
|
||||
}
|
||||
uint8_t kl_type_en = instance->keystore->kl_type;
|
||||
for
|
||||
@@ -302,7 +305,7 @@ static bool subghz_protocol_keeloq_gen_data(
|
||||
uint64_t yek = (uint64_t)fix << 32 | hop;
|
||||
instance->generic.data =
|
||||
subghz_protocol_blocks_reverse_key(yek, instance->generic.data_count_bit);
|
||||
} // What should happen if seed = 0 in bft programming mode
|
||||
} // What should happen if seed = 0 in bft programming mode -> collapse of the universe I think :)
|
||||
return true; // Always return true
|
||||
}
|
||||
|
||||
@@ -693,6 +696,33 @@ static inline bool subghz_protocol_keeloq_check_decrypt(
|
||||
if((decrypt >> 28 == btn) && (((((uint16_t)(decrypt >> 16)) & 0xFF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0xFF) == 0))) {
|
||||
instance->cnt = decrypt & 0x0000FFFF;
|
||||
/*FURI_LOG_I(
|
||||
"KL",
|
||||
"decrypt: 0x%08lX, btn: %d, end_serial: 0x%03lX, cnt: %ld",
|
||||
decrypt,
|
||||
btn,
|
||||
end_serial,
|
||||
instance->cnt);*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Centurion specific check
|
||||
static inline bool subghz_protocol_keeloq_check_decrypt_centurion(
|
||||
SubGhzBlockGeneric* instance,
|
||||
uint32_t decrypt,
|
||||
uint8_t btn) {
|
||||
furi_assert(instance);
|
||||
|
||||
if((decrypt >> 28 == btn) && (((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0x1CE))) {
|
||||
instance->cnt = decrypt & 0x0000FFFF;
|
||||
/*FURI_LOG_I(
|
||||
"KL",
|
||||
"decrypt: 0x%08lX, btn: %d, end_serial: 0x%03lX, cnt: %ld",
|
||||
decrypt,
|
||||
btn,
|
||||
end_serial,
|
||||
instance->cnt);*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -753,10 +783,19 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
|
||||
man =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
|
||||
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
keystore->mfname = *manufacture_name;
|
||||
return 1;
|
||||
if((strcmp(furi_string_get_cstr(manufacture_code->name), "Centurion") == 0)) {
|
||||
if(subghz_protocol_keeloq_check_decrypt_centurion(instance, decrypt, btn)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
keystore->mfname = *manufacture_name;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if(subghz_protocol_keeloq_check_decrypt(
|
||||
instance, decrypt, btn, end_serial)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
keystore->mfname = *manufacture_name;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_SECURE:
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
#include "princeton_for_testing.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include "../blocks/math.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
#define SUBGHZ_PT_SHORT 300
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
#define SUBGHZ_PT_COUNT_KEY_433 9
|
||||
#define SUBGHZ_PT_TIMEOUT_433 900
|
||||
#define SUBGHZ_PT_COUNT_KEY_868 9
|
||||
#define SUBGHZ_PT_TIMEOUT_868 14000
|
||||
|
||||
#define TAG "SubGhzProtocolPrinceton"
|
||||
|
||||
struct SubGhzEncoderPrinceton {
|
||||
uint32_t key;
|
||||
uint16_t te;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
size_t count_key;
|
||||
size_t count_key_package;
|
||||
uint32_t time_high;
|
||||
uint32_t time_low;
|
||||
uint32_t timeout;
|
||||
uint32_t time_stop;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PrincetonDecoderStepReset = 0,
|
||||
PrincetonDecoderStepSaveDuration,
|
||||
PrincetonDecoderStepCheckDuration,
|
||||
} PrincetonDecoderStep;
|
||||
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_for_testing_alloc() {
|
||||
SubGhzEncoderPrinceton* instance = malloc(sizeof(SubGhzEncoderPrinceton));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_for_testing_free(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_for_testing_stop(
|
||||
SubGhzEncoderPrinceton* instance,
|
||||
uint32_t time_stop) {
|
||||
instance->time_stop = time_stop;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_for_testing_set(
|
||||
SubGhzEncoderPrinceton* instance,
|
||||
uint32_t key,
|
||||
size_t repeat,
|
||||
uint32_t frequency) {
|
||||
furi_assert(instance);
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->key = key;
|
||||
instance->repeat = repeat + 1;
|
||||
instance->front = 48;
|
||||
instance->time_high = 0;
|
||||
instance->time_low = 0;
|
||||
if(frequency < 700000000) {
|
||||
instance->count_key_package = SUBGHZ_PT_COUNT_KEY_433;
|
||||
instance->timeout = SUBGHZ_PT_TIMEOUT_433;
|
||||
} else {
|
||||
instance->count_key_package = SUBGHZ_PT_COUNT_KEY_868;
|
||||
instance->timeout = SUBGHZ_PT_TIMEOUT_868;
|
||||
}
|
||||
|
||||
instance->count_key = instance->count_key_package + 3;
|
||||
|
||||
if((furi_get_tick() - instance->time_stop) < instance->timeout) {
|
||||
instance->time_stop = (instance->timeout - (furi_get_tick() - instance->time_stop)) * 1000;
|
||||
} else {
|
||||
instance->time_stop = 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t subghz_encoder_princeton_for_testing_get_repeat_left(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_for_testing_print_log(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
float duty_cycle =
|
||||
((float)instance->time_high / (instance->time_high + instance->time_low)) * 100;
|
||||
FURI_LOG_I(
|
||||
TAG "Encoder",
|
||||
"Radio tx_time=%luus ON=%luus, OFF=%luus, DutyCycle=%lu,%lu%%",
|
||||
instance->time_high + instance->time_low,
|
||||
instance->time_high,
|
||||
instance->time_low,
|
||||
(uint32_t)duty_cycle,
|
||||
(uint32_t)((duty_cycle - (uint32_t)duty_cycle) * 100UL));
|
||||
}
|
||||
|
||||
LevelDuration subghz_encoder_princeton_for_testing_yield(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
if(instance->repeat == 0) {
|
||||
subghz_encoder_princeton_for_testing_print_log(instance);
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
size_t bit = instance->front / 2;
|
||||
bool level = !(instance->front % 2);
|
||||
|
||||
LevelDuration ret;
|
||||
if(bit < 24) {
|
||||
uint8_t byte = bit / 8;
|
||||
uint8_t bit_in_byte = bit % 8;
|
||||
bool value = (((uint8_t*)&instance->key)[2 - byte] >> (7 - bit_in_byte)) & 1;
|
||||
if(value) {
|
||||
ret = level_duration_make(level, level ? instance->te * 3 : instance->te);
|
||||
if(level)
|
||||
instance->time_high += instance->te * 3;
|
||||
else
|
||||
instance->time_low += instance->te;
|
||||
} else {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 3);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 3;
|
||||
}
|
||||
} else {
|
||||
if(instance->time_stop) {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->time_stop);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else {
|
||||
instance->time_low += instance->time_stop;
|
||||
instance->time_stop = 0;
|
||||
instance->front = 47;
|
||||
}
|
||||
} else {
|
||||
if(--instance->count_key != 0) {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 30);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 30;
|
||||
} else {
|
||||
instance->count_key = instance->count_key_package + 2;
|
||||
instance->front = 48;
|
||||
ret = level_duration_make(level, level ? instance->te : instance->timeout * 1000);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->timeout * 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instance->front++;
|
||||
if(instance->front == 50) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct SubGhzDecoderPrinceton {
|
||||
const char* name;
|
||||
uint16_t te_long;
|
||||
uint16_t te_short;
|
||||
uint16_t te_delta;
|
||||
uint8_t code_count_bit;
|
||||
uint8_t code_last_count_bit;
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t btn;
|
||||
uint32_t te_last;
|
||||
uint32_t serial;
|
||||
uint32_t parser_step;
|
||||
uint16_t cnt;
|
||||
uint32_t te;
|
||||
|
||||
SubGhzDecoderPrincetonCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_for_testing_alloc(void) {
|
||||
SubGhzDecoderPrinceton* instance = malloc(sizeof(SubGhzDecoderPrinceton));
|
||||
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->name = "Princeton";
|
||||
instance->code_min_count_bit_for_found = 24;
|
||||
instance->te_short = 400;
|
||||
instance->te_long = 1200;
|
||||
instance->te_delta = 250;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_for_testing_free(SubGhzDecoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_for_testing_set_callback(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzDecoderPrincetonCallback callback,
|
||||
void* context) {
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_for_testing_reset(SubGhzDecoderPrinceton* instance) {
|
||||
instance->parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
|
||||
static void
|
||||
subghz_decoder_princeton_for_testing_add_bit(SubGhzDecoderPrinceton* instance, uint8_t bit) {
|
||||
instance->code_found = instance->code_found << 1 | bit;
|
||||
instance->code_count_bit++;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_for_testing_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->parser_step) {
|
||||
case PrincetonDecoderStepReset:
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, instance->te_short * 36) < instance->te_delta * 36)) {
|
||||
//Found Preambula
|
||||
instance->parser_step = PrincetonDecoderStepSaveDuration;
|
||||
instance->code_found = 0;
|
||||
instance->code_count_bit = 0;
|
||||
instance->te = 0;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepSaveDuration:
|
||||
//save duration
|
||||
if(level) {
|
||||
instance->te_last = duration;
|
||||
instance->te += duration;
|
||||
instance->parser_step = PrincetonDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= ((uint32_t)instance->te_short * 10 + instance->te_delta)) {
|
||||
instance->parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if(instance->code_count_bit == instance->code_min_count_bit_for_found) {
|
||||
instance->te /= (instance->code_count_bit * 4 + 1);
|
||||
|
||||
instance->code_last_found = instance->code_found;
|
||||
instance->code_last_count_bit = instance->code_count_bit;
|
||||
instance->serial = instance->code_found >> 4;
|
||||
instance->btn = (uint8_t)instance->code_found & 0x00000F;
|
||||
|
||||
if(instance->callback) instance->callback(instance, instance->context);
|
||||
}
|
||||
instance->code_found = 0;
|
||||
instance->code_count_bit = 0;
|
||||
instance->te = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->te += duration;
|
||||
|
||||
if((DURATION_DIFF(instance->te_last, instance->te_short) < instance->te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->te_long) < instance->te_delta * 3)) {
|
||||
subghz_decoder_princeton_for_testing_add_bit(instance, 0);
|
||||
instance->parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->te_last, instance->te_long) < instance->te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->te_short) < instance->te_delta)) {
|
||||
subghz_decoder_princeton_for_testing_add_bit(instance, 1);
|
||||
instance->parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/** SubGhzDecoderPrinceton anonymous type */
|
||||
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
||||
/** SubGhzEncoderPrinceton anonymous type */
|
||||
typedef struct SubGhzEncoderPrinceton SubGhzEncoderPrinceton;
|
||||
|
||||
typedef void (*SubGhzDecoderPrincetonCallback)(SubGhzDecoderPrinceton* parser, void* context);
|
||||
|
||||
/**
|
||||
* Allocate SubGhzEncoderPrinceton
|
||||
* @return pointer to SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_for_testing_alloc();
|
||||
|
||||
/**
|
||||
* Free SubGhzEncoderPrinceton instance
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_for_testing_free(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/**
|
||||
* Forced transmission stop.
|
||||
* @param instance Pointer to a SubGhzEncoderPrinceton instance
|
||||
* @param time_stop Transmission stop time, ms
|
||||
*/
|
||||
void subghz_encoder_princeton_for_testing_stop(
|
||||
SubGhzEncoderPrinceton* instance,
|
||||
uint32_t time_stop);
|
||||
|
||||
/**
|
||||
* Set new encoder params
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @param key - 24bit key
|
||||
* @param repeat - how many times to repeat
|
||||
* @param frequency - frequency
|
||||
*/
|
||||
void subghz_encoder_princeton_for_testing_set(
|
||||
SubGhzEncoderPrinceton* instance,
|
||||
uint32_t key,
|
||||
size_t repeat,
|
||||
uint32_t frequency);
|
||||
|
||||
/**
|
||||
* Get repeat count left
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return repeat count left
|
||||
*/
|
||||
size_t subghz_encoder_princeton_for_testing_get_repeat_left(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/**
|
||||
* Print encoder log
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_for_testing_print_log(void* context);
|
||||
|
||||
/**
|
||||
* Get level duration
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return level duration
|
||||
*/
|
||||
LevelDuration subghz_encoder_princeton_for_testing_yield(void* context);
|
||||
|
||||
/**
|
||||
* Allocate SubGhzDecoderPrinceton
|
||||
* @return SubGhzDecoderPrinceton*
|
||||
*/
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_for_testing_alloc();
|
||||
|
||||
/**
|
||||
* Free SubGhzDecoderPrinceton
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_decoder_princeton_for_testing_free(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
void subghz_decoder_princeton_for_testing_set_callback(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzDecoderPrincetonCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Reset internal state
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
*/
|
||||
void subghz_decoder_princeton_for_testing_reset(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/**
|
||||
* Parse accepted duration
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_decoder_princeton_for_testing_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration);
|
||||
@@ -8,6 +8,31 @@ extern "C" {
|
||||
|
||||
extern const SubGhzProtocolRegistry subghz_protocol_registry;
|
||||
|
||||
typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW;
|
||||
|
||||
bool subghz_protocol_secplus_v2_create_data(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
uint32_t serial,
|
||||
uint8_t btn,
|
||||
uint32_t cnt,
|
||||
SubGhzRadioPreset* preset);
|
||||
|
||||
bool subghz_protocol_keeloq_create_data(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
uint32_t serial,
|
||||
uint8_t btn,
|
||||
uint16_t cnt,
|
||||
const char* manufacture_name,
|
||||
SubGhzRadioPreset* preset);
|
||||
|
||||
void subghz_protocol_decoder_bin_raw_data_input_rssi(
|
||||
SubGhzProtocolDecoderBinRAW* instance,
|
||||
float rssi);
|
||||
|
||||
bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user