Merge remote-tracking branch 'origin/dev' into release-candidate

This commit is contained in:
Aleksandr Kutuzov 2023-06-01 21:50:05 +09:00
commit 2d8f262dd4
67 changed files with 235 additions and 264 deletions

View File

@ -27,6 +27,12 @@ static const uint32_t nfc_test_file_version = 1;
#define NFC_TEST_DATA_MAX_LEN 18 #define NFC_TEST_DATA_MAX_LEN 18
#define NFC_TETS_TIMINGS_MAX_LEN 1350 #define NFC_TETS_TIMINGS_MAX_LEN 1350
// Maximum allowed time for buffer preparation to fit 500us nt message timeout
#define NFC_TEST_4_BYTE_BUILD_BUFFER_TIM_MAX (150)
#define NFC_TEST_16_BYTE_BUILD_BUFFER_TIM_MAX (640)
#define NFC_TEST_4_BYTE_BUILD_SIGNAL_TIM_MAX (110)
#define NFC_TEST_16_BYTE_BUILD_SIGNAL_TIM_MAX (440)
typedef struct { typedef struct {
Storage* storage; Storage* storage;
NfcaSignal* signal; NfcaSignal* signal;
@ -89,13 +95,13 @@ static bool nfc_test_read_signal_from_file(const char* file_name) {
static bool nfc_test_digital_signal_test_encode( static bool nfc_test_digital_signal_test_encode(
const char* file_name, const char* file_name,
uint32_t encode_max_time, uint32_t build_signal_max_time_us,
uint32_t build_buffer_max_time_us,
uint32_t timing_tolerance, uint32_t timing_tolerance,
uint32_t timings_sum_tolerance) { uint32_t timings_sum_tolerance) {
furi_assert(nfc_test); furi_assert(nfc_test);
bool success = false; bool success = false;
uint32_t time = 0;
uint32_t dut_timings_sum = 0; uint32_t dut_timings_sum = 0;
uint32_t ref_timings_sum = 0; uint32_t ref_timings_sum = 0;
uint8_t parity[10] = {}; uint8_t parity[10] = {};
@ -109,17 +115,37 @@ static bool nfc_test_digital_signal_test_encode(
// Encode signal // Encode signal
FURI_CRITICAL_ENTER(); FURI_CRITICAL_ENTER();
time = DWT->CYCCNT; uint32_t time_start = DWT->CYCCNT;
nfca_signal_encode( nfca_signal_encode(
nfc_test->signal, nfc_test->test_data, nfc_test->test_data_len * 8, parity); nfc_test->signal, nfc_test->test_data, nfc_test->test_data_len * 8, parity);
uint32_t time_signal =
(DWT->CYCCNT - time_start) / furi_hal_cortex_instructions_per_microsecond();
time_start = DWT->CYCCNT;
digital_signal_prepare_arr(nfc_test->signal->tx_signal); digital_signal_prepare_arr(nfc_test->signal->tx_signal);
time = (DWT->CYCCNT - time) / furi_hal_cortex_instructions_per_microsecond();
uint32_t time_buffer =
(DWT->CYCCNT - time_start) / furi_hal_cortex_instructions_per_microsecond();
FURI_CRITICAL_EXIT(); FURI_CRITICAL_EXIT();
// Check timings // Check timings
if(time > encode_max_time) { if(time_signal > build_signal_max_time_us) {
FURI_LOG_E( FURI_LOG_E(
TAG, "Encoding time: %ld us while accepted value: %ld us", time, encode_max_time); TAG,
"Build signal time: %ld us while accepted value: %ld us",
time_signal,
build_signal_max_time_us);
break;
}
if(time_buffer > build_buffer_max_time_us) {
FURI_LOG_E(
TAG,
"Build buffer time: %ld us while accepted value: %ld us",
time_buffer,
build_buffer_max_time_us);
break; break;
} }
@ -156,7 +182,16 @@ static bool nfc_test_digital_signal_test_encode(
break; break;
} }
FURI_LOG_I(TAG, "Encoding time: %ld us. Acceptable time: %ld us", time, encode_max_time); FURI_LOG_I(
TAG,
"Build signal time: %ld us. Acceptable time: %ld us",
time_signal,
build_signal_max_time_us);
FURI_LOG_I(
TAG,
"Build buffer time: %ld us. Acceptable time: %ld us",
time_buffer,
build_buffer_max_time_us);
FURI_LOG_I( FURI_LOG_I(
TAG, TAG,
"Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]", "Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]",
@ -171,11 +206,19 @@ static bool nfc_test_digital_signal_test_encode(
MU_TEST(nfc_digital_signal_test) { MU_TEST(nfc_digital_signal_test) {
mu_assert( mu_assert(
nfc_test_digital_signal_test_encode( nfc_test_digital_signal_test_encode(
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_SHORT_FILE, 500, 1, 37), NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_SHORT_FILE,
NFC_TEST_4_BYTE_BUILD_SIGNAL_TIM_MAX,
NFC_TEST_4_BYTE_BUILD_BUFFER_TIM_MAX,
1,
37),
"NFC short digital signal test failed\r\n"); "NFC short digital signal test failed\r\n");
mu_assert( mu_assert(
nfc_test_digital_signal_test_encode( nfc_test_digital_signal_test_encode(
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_LONG_FILE, 2000, 1, 37), NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_LONG_FILE,
NFC_TEST_16_BYTE_BUILD_SIGNAL_TIM_MAX,
NFC_TEST_16_BYTE_BUILD_BUFFER_TIM_MAX,
1,
37),
"NFC long digital signal test failed\r\n"); "NFC long digital signal test failed\r\n");
} }

View File

@ -5,7 +5,6 @@
#define TAG "Magic" #define TAG "Magic"
#define MAGIC_CMD_WUPA (0x40) #define MAGIC_CMD_WUPA (0x40)
#define MAGIC_CMD_WIPE (0x41)
#define MAGIC_CMD_ACCESS (0x43) #define MAGIC_CMD_ACCESS (0x43)
#define MAGIC_MIFARE_READ_CMD (0x30) #define MAGIC_MIFARE_READ_CMD (0x30)
@ -144,32 +143,3 @@ bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
return write_success; return write_success;
} }
bool magic_gen1_wipe() {
bool wipe_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_CMD_WIPE;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(2000));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
wipe_success = true;
} while(false);
return wipe_success;
}

View File

@ -9,5 +9,3 @@ bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data);
bool magic_gen1_data_access_cmd(); bool magic_gen1_data_access_cmd();
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data); bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data);
bool magic_gen1_wipe();

View File

@ -1,175 +0,0 @@
#include "classic_gen1.h"
#include <furi_hal_nfc.h>
#define TAG "Magic"
#define MAGIC_CMD_WUPA (0x40)
#define MAGIC_CMD_WIPE (0x41)
#define MAGIC_CMD_ACCESS (0x43)
#define MAGIC_MIFARE_READ_CMD (0x30)
#define MAGIC_MIFARE_WRITE_CMD (0xA0)
#define MAGIC_ACK (0x0A)
#define MAGIC_BUFFER_SIZE (32)
bool magic_gen1_wupa() {
bool magic_activated = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
// Start communication
tx_data[0] = MAGIC_CMD_WUPA;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
7,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
magic_activated = true;
} while(false);
return magic_activated;
}
bool magic_gen1_data_access_cmd() {
bool write_cmd_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_CMD_ACCESS;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
write_cmd_success = true;
} while(false);
return write_cmd_success;
}
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) {
furi_assert(data);
bool read_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_MIFARE_READ_CMD;
tx_data[1] = block_num;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
2 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnOk) break;
if(rx_len != 16 * 8) break;
memcpy(data->value, rx_data, sizeof(data->value));
read_success = true;
} while(false);
return read_success;
}
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
furi_assert(data);
bool write_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_MIFARE_WRITE_CMD;
tx_data[1] = block_num;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
2 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
memcpy(tx_data, data->value, sizeof(data->value));
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
16 * 8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(20));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
write_success = true;
} while(false);
return write_success;
}
bool magic_gen1_wipe() {
bool wipe_success = false;
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
uint16_t rx_len = 0;
FuriHalNfcReturn ret = 0;
do {
tx_data[0] = MAGIC_CMD_WIPE;
ret = furi_hal_nfc_ll_txrx_bits(
tx_data,
8,
rx_data,
sizeof(rx_data),
&rx_len,
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
furi_hal_nfc_ll_ms2fc(2000));
if(ret != FuriHalNfcReturnIncompleteByte) break;
if(rx_len != 4) break;
if(rx_data[0] != MAGIC_ACK) break;
wipe_success = true;
} while(false);
return wipe_success;
}

View File

@ -92,51 +92,49 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
do { do {
if(furi_hal_nfc_detect(&nfc_data, 200)) { if(magic_dev->type == MagicTypeClassicGen1) {
if(nfc_data.cuid != magic_dev->cuid) break; if(furi_hal_nfc_detect(&nfc_data, 200)) {
if(!card_found_notified) { magic_deactivate();
nfc_magic_worker->callback( magic_activate();
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
card_found_notified = true;
}
furi_hal_nfc_sleep();
magic_activate();
if(magic_dev->type == MagicTypeClassicGen1) {
if(dev_protocol != NfcDeviceProtocolMifareClassic) break;
MfClassicData* mfc_data = &dev_data->mf_classic_data;
if(mfc_data->type != MfClassicType1k) break;
if(!magic_gen1_wupa()) { if(!magic_gen1_wupa()) {
FURI_LOG_E(TAG, "Not Magic card"); FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
nfc_magic_worker->callback( nfc_magic_worker->callback(
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
done = true; done = true;
break; break;
} }
magic_deactivate();
}
magic_activate();
if(magic_gen1_wupa()) {
if(!magic_gen1_data_access_cmd()) { if(!magic_gen1_data_access_cmd()) {
FURI_LOG_E(TAG, "Not Magic card"); FURI_LOG_E(
TAG, "No card response to data access command (not a magic card)");
nfc_magic_worker->callback( nfc_magic_worker->callback(
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
done = true; done = true;
break; break;
} }
MfClassicData* mfc_data = &dev_data->mf_classic_data;
for(size_t i = 0; i < 64; i++) { for(size_t i = 0; i < 64; i++) {
FURI_LOG_D(TAG, "Writing block %d", i); FURI_LOG_D(TAG, "Writing block %d", i);
if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { if(!magic_gen1_write_blk(i, &mfc_data->block[i])) {
FURI_LOG_E(TAG, "Failed to write %d block", i); FURI_LOG_E(TAG, "Failed to write %d block", i);
done = true;
nfc_magic_worker->callback( nfc_magic_worker->callback(
NfcMagicWorkerEventFail, nfc_magic_worker->context); NfcMagicWorkerEventFail, nfc_magic_worker->context);
done = true;
break; break;
} }
} }
done = true;
nfc_magic_worker->callback( nfc_magic_worker->callback(
NfcMagicWorkerEventSuccess, nfc_magic_worker->context); NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
done = true;
break; break;
} else if(magic_dev->type == MagicTypeGen4) { }
} else if(magic_dev->type == MagicTypeGen4) {
if(furi_hal_nfc_detect(&nfc_data, 200)) {
uint8_t gen4_config[28]; uint8_t gen4_config[28];
uint32_t password = magic_dev->password; uint32_t password = magic_dev->password;
@ -196,6 +194,7 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
gen4_config[25] = dev_data->nfc_data.atqa[1]; gen4_config[25] = dev_data->nfc_data.atqa[1];
gen4_config[26] = dev_data->nfc_data.sak; gen4_config[26] = dev_data->nfc_data.sak;
furi_hal_nfc_sleep();
furi_hal_nfc_activate_nfca(200, &cuid); furi_hal_nfc_activate_nfca(200, &cuid);
if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) { if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) {
nfc_magic_worker->callback( nfc_magic_worker->callback(
@ -394,6 +393,11 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
MfClassicBlock block; MfClassicBlock block;
memset(&block, 0, sizeof(MfClassicBlock)); memset(&block, 0, sizeof(MfClassicBlock));
MfClassicBlock empty_block;
memset(&empty_block, 0, sizeof(MfClassicBlock));
MfClassicBlock trailer_block;
memset(&trailer_block, 0xff, sizeof(MfClassicBlock));
block.value[0] = 0x01; block.value[0] = 0x01;
block.value[1] = 0x02; block.value[1] = 0x02;
block.value[2] = 0x03; block.value[2] = 0x03;
@ -402,6 +406,10 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
block.value[5] = 0x08; block.value[5] = 0x08;
block.value[6] = 0x04; block.value[6] = 0x04;
trailer_block.value[7] = 0x07;
trailer_block.value[8] = 0x80;
trailer_block.value[9] = 0x69;
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
do { do {
magic_deactivate(); magic_deactivate();
@ -415,10 +423,26 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
card_found_notified = true; card_found_notified = true;
} }
if(!magic_gen1_wipe()) break;
if(!magic_gen1_data_access_cmd()) break; if(!magic_gen1_data_access_cmd()) break;
if(!magic_gen1_write_blk(0, &block)) break; if(!magic_gen1_write_blk(0, &block)) break;
for(size_t i = 1; i < 64; i++) {
FURI_LOG_D(TAG, "Wiping block %d", i);
bool success = false;
if((i | 0x03) == i) {
success = magic_gen1_write_blk(i, &trailer_block);
} else {
success = magic_gen1_write_blk(i, &empty_block);
}
if(!success) {
FURI_LOG_E(TAG, "Failed to write %d block", i);
nfc_magic_worker->callback(
NfcMagicWorkerEventFail, nfc_magic_worker->context);
break;
}
}
card_wiped = true; card_wiped = true;
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
} else if(magic_dev->type == MagicTypeGen4) { } else if(magic_dev->type == MagicTypeGen4) {

View File

@ -10,4 +10,5 @@ typedef enum {
1, /** File parsing error, or wrong file structure, or missing required parameters. more accurate data can be obtained through the debug port */ 1, /** File parsing error, or wrong file structure, or missing required parameters. more accurate data can be obtained through the debug port */
SubGhzErrorTypeOnlyRX = SubGhzErrorTypeOnlyRX =
2, /** Transmission on this frequency is blocked by regional settings */ 2, /** Transmission on this frequency is blocked by regional settings */
SubGhzErrorTypeParserOthers = 3, /** Error in protocol parameters description */
} SubGhzErrorType; } SubGhzErrorType;

View File

@ -40,15 +40,26 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) {
bool result = false; bool result = false;
if((state == SubGhzRpcStateLoaded)) { if((state == SubGhzRpcStateLoaded)) {
result = subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx)); switch(
state = SubGhzRpcStateTx; subghz_txrx_tx_start(subghz->txrx, subghz_txrx_get_fff_data(subghz->txrx))) {
if(result) subghz_blink_start(subghz); case SubGhzTxRxStartTxStateErrorOnlyRx:
} rpc_system_app_set_error_code(subghz->rpc_ctx, SubGhzErrorTypeOnlyRX);
if(!result) { rpc_system_app_set_error_text(
rpc_system_app_set_error_code(subghz->rpc_ctx, SubGhzErrorTypeOnlyRX); subghz->rpc_ctx,
rpc_system_app_set_error_text( "Transmission on this frequency is restricted in your region");
subghz->rpc_ctx, break;
"Transmission on this frequency is restricted in your region"); case SubGhzTxRxStartTxStateErrorParserOthers:
rpc_system_app_set_error_code(subghz->rpc_ctx, SubGhzErrorTypeParserOthers);
rpc_system_app_set_error_text(
subghz->rpc_ctx, "Error in protocol parameters description");
break;
default: //if(SubGhzTxRxStartTxStateOk)
result = true;
subghz_blink_start(subghz);
state = SubGhzRpcStateTx;
break;
}
} }
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result);
} else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) {
@ -56,9 +67,9 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
if(state == SubGhzRpcStateTx) { if(state == SubGhzRpcStateTx) {
subghz_txrx_stop(subghz->txrx); subghz_txrx_stop(subghz->txrx);
subghz_blink_stop(subghz); subghz_blink_stop(subghz);
state = SubGhzRpcStateIdle;
result = true; result = true;
} }
state = SubGhzRpcStateIdle;
rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result); rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result);
} else if(event.event == SubGhzCustomEventSceneRpcLoad) { } else if(event.event == SubGhzCustomEventSceneRpcLoad) {
bool result = false; bool result = false;
@ -95,7 +106,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) {
void subghz_scene_rpc_on_exit(void* context) { void subghz_scene_rpc_on_exit(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc); SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc);
if(state != SubGhzRpcStateIdle) { if(state == SubGhzRpcStateTx) {
subghz_txrx_stop(subghz->txrx); subghz_txrx_stop(subghz->txrx);
subghz_blink_stop(subghz); subghz_blink_stop(subghz);
} }

View File

@ -176,16 +176,19 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) {
furi_hal_power_suppress_charge_enter(); furi_hal_power_suppress_charge_enter();
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter); if(furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter)) {
while(!(furi_hal_subghz_is_async_tx_complete() || cli_cmd_interrupt_received(cli))) {
printf(".");
fflush(stdout);
furi_delay_ms(333);
}
furi_hal_subghz_stop_async_tx();
while(!(furi_hal_subghz_is_async_tx_complete() || cli_cmd_interrupt_received(cli))) { } else {
printf("."); printf("Transmission on this frequency is restricted in your region\r\n");
fflush(stdout);
furi_delay_ms(333);
} }
furi_hal_subghz_stop_async_tx();
furi_hal_subghz_sleep();
furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit(); furi_hal_power_suppress_charge_exit();
flipper_format_free(flipper_format); flipper_format_free(flipper_format);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,50 @@
Filetype: Flipper Animation
Version: 1
Width: 128
Height: 64
Passive frames: 16
Active frames: 60
Frames order: 0 1 2 1 0 3 4 5 6 3 7 1 8 1 7 9 0 10 11 12 13 14 15 16 14 12 17 18 19 20 21 22 22 23 22 24 25 26 27 26 25 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 19 18 14 45 14 45 14 45 14 45 14 16 14 14 11 46 47 1
Active cycles: 1
Frame rate: 2
Duration: 3600
Active cooldown: 7
Bubble slots: 1
Slot: 0
X: 83
Y: 42
Text: Sup
AlignH: Left
AlignV: Top
StartFrame: 38
EndFrame: 40
Slot: 0
X: 66
Y: 35
Text: What just
AlignH: Left
AlignV: Center
StartFrame: 62
EndFrame: 65
Slot: 0
X: 66
Y: 35
Text: happened?
AlignH: Left
AlignV: Center
StartFrame: 66
EndFrame: 68
Slot: 0
X: 87
Y: 38
Text: Idk
AlignH: Left
AlignV: Top
StartFrame: 70
EndFrame: 70

View File

@ -90,6 +90,13 @@ Min butthurt: 0
Max butthurt: 5 Max butthurt: 5
Min level: 1 Min level: 1
Max level: 3 Max level: 3
Weight: 3
Name: L1_Kaiju_128x64
Min butthurt: 0
Max butthurt: 10
Min level: 1
Max level: 3
Weight: 4 Weight: 4
Name: L2_Wake_up_128x64 Name: L2_Wake_up_128x64

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,28.1,, Version,+,28.2,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@ -80,6 +80,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,,
Header,+,lib/digital_signal/digital_signal.h,,
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
Header,+,lib/flipper_application/flipper_application.h,, Header,+,lib/flipper_application/flipper_application.h,,
@ -617,6 +618,24 @@ Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, u
Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*" Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*"
Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*" Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*"
Function,-,difftime,double,"time_t, time_t" Function,-,difftime,double,"time_t, time_t"
Function,-,digital_sequence_add,void,"DigitalSequence*, uint8_t"
Function,-,digital_sequence_alloc,DigitalSequence*,"uint32_t, const GpioPin*"
Function,-,digital_sequence_clear,void,DigitalSequence*
Function,-,digital_sequence_free,void,DigitalSequence*
Function,-,digital_sequence_send,_Bool,DigitalSequence*
Function,-,digital_sequence_set_sendtime,void,"DigitalSequence*, uint32_t"
Function,-,digital_sequence_set_signal,void,"DigitalSequence*, uint8_t, DigitalSignal*"
Function,-,digital_sequence_timebase_correction,void,"DigitalSequence*, float"
Function,-,digital_signal_add,void,"DigitalSignal*, uint32_t"
Function,-,digital_signal_add_pulse,void,"DigitalSignal*, uint32_t, _Bool"
Function,-,digital_signal_alloc,DigitalSignal*,uint32_t
Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*"
Function,-,digital_signal_free,void,DigitalSignal*
Function,-,digital_signal_get_edge,uint32_t,"DigitalSignal*, uint32_t"
Function,-,digital_signal_get_edges_cnt,uint32_t,DigitalSignal*
Function,-,digital_signal_get_start_level,_Bool,DigitalSignal*
Function,-,digital_signal_prepare_arr,void,DigitalSignal*
Function,-,digital_signal_send,void,"DigitalSignal*, const GpioPin*"
Function,-,diprintf,int,"int, const char*, ..." Function,-,diprintf,int,"int, const char*, ..."
Function,+,dir_walk_alloc,DirWalk*,Storage* Function,+,dir_walk_alloc,DirWalk*,Storage*
Function,+,dir_walk_close,void,DirWalk* Function,+,dir_walk_close,void,DirWalk*

1 entry status name type params
2 Version + 28.1 28.2
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
80 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h
81 Header + firmware/targets/furi_hal_include/furi_hal_version.h
82 Header + firmware/targets/furi_hal_include/furi_hal_vibro.h
83 Header + lib/digital_signal/digital_signal.h
84 Header + lib/flipper_application/api_hashtable/api_hashtable.h
85 Header + lib/flipper_application/api_hashtable/compilesort.hpp
86 Header + lib/flipper_application/flipper_application.h
618 Function + dialog_message_show DialogMessageButton DialogsApp*, const DialogMessage*
619 Function + dialog_message_show_storage_error void DialogsApp*, const char*
620 Function - difftime double time_t, time_t
621 Function - digital_sequence_add void DigitalSequence*, uint8_t
622 Function - digital_sequence_alloc DigitalSequence* uint32_t, const GpioPin*
623 Function - digital_sequence_clear void DigitalSequence*
624 Function - digital_sequence_free void DigitalSequence*
625 Function - digital_sequence_send _Bool DigitalSequence*
626 Function - digital_sequence_set_sendtime void DigitalSequence*, uint32_t
627 Function - digital_sequence_set_signal void DigitalSequence*, uint8_t, DigitalSignal*
628 Function - digital_sequence_timebase_correction void DigitalSequence*, float
629 Function - digital_signal_add void DigitalSignal*, uint32_t
630 Function - digital_signal_add_pulse void DigitalSignal*, uint32_t, _Bool
631 Function - digital_signal_alloc DigitalSignal* uint32_t
632 Function - digital_signal_append _Bool DigitalSignal*, DigitalSignal*
633 Function - digital_signal_free void DigitalSignal*
634 Function - digital_signal_get_edge uint32_t DigitalSignal*, uint32_t
635 Function - digital_signal_get_edges_cnt uint32_t DigitalSignal*
636 Function - digital_signal_get_start_level _Bool DigitalSignal*
637 Function - digital_signal_prepare_arr void DigitalSignal*
638 Function - digital_signal_send void DigitalSignal*, const GpioPin*
639 Function - diprintf int int, const char*, ...
640 Function + dir_walk_alloc DirWalk* Storage*
641 Function + dir_walk_close void DirWalk*

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,28.1,, Version,+,28.2,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@ -86,6 +86,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,,
Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,,
Header,+,lib/digital_signal/digital_signal.h,,
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
Header,+,lib/flipper_application/flipper_application.h,, Header,+,lib/flipper_application/flipper_application.h,,

1 entry status name type params
2 Version + 28.1 28.2
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
86 Header + firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h
87 Header + firmware/targets/furi_hal_include/furi_hal_version.h
88 Header + firmware/targets/furi_hal_include/furi_hal_vibro.h
89 Header + lib/digital_signal/digital_signal.h
90 Header + lib/flipper_application/api_hashtable/api_hashtable.h
91 Header + lib/flipper_application/api_hashtable/compilesort.hpp
92 Header + lib/flipper_application/flipper_application.h

View File

@ -28,6 +28,7 @@
"flipperformat", "flipperformat",
"toolbox", "toolbox",
"nfc", "nfc",
"digital_signal",
"pulse_reader", "pulse_reader",
"microtar", "microtar",
"usb_stm32", "usb_stm32",

View File

@ -27,6 +27,7 @@
- `nfc` - NFC library, used by NFC application - `nfc` - NFC library, used by NFC application
- `one_wire` - OneWire library, used by iButton application - `one_wire` - OneWire library, used by iButton application
- `print` - Tiny printf implementation - `print` - Tiny printf implementation
- `digital_signal` - Digital Signal library used by NFC for software implemented protocols
- `pulse_reader` - Pulse Reader library used by NFC for software implemented protocols - `pulse_reader` - Pulse Reader library used by NFC for software implemented protocols
- `qrcode` - QR-Code library - `qrcode` - QR-Code library
- `stm32wb_cmsis` - STM32WB series CMSIS headers, extends CMSIS Core - `stm32wb_cmsis` - STM32WB series CMSIS headers, extends CMSIS Core

View File

@ -15,7 +15,6 @@ env.Append(
Dir("u8g2"), Dir("u8g2"),
Dir("update_util"), Dir("update_util"),
Dir("print"), Dir("print"),
Dir("pulse_reader"),
], ],
) )
@ -95,6 +94,7 @@ libs = env.BuildModules(
"mbedtls", "mbedtls",
"subghz", "subghz",
"nfc", "nfc",
"digital_signal",
"pulse_reader", "pulse_reader",
"appframe", "appframe",
"misc", "misc",

View File

@ -0,0 +1,20 @@
Import("env")
env.Append(
CPPPATH=[
"#/lib/digital_signal",
],
SDK_HEADERS=[
File("digital_signal.h"),
],
)
libenv = env.Clone(FW_LIB_NAME="digital_signal")
libenv.ApplyLibFlags()
libenv.Append(CCFLAGS=["-O3", "-funroll-loops", "-Ofast"])
sources = libenv.GlobRecursive("*.c*")
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Return("lib")

View File

@ -212,8 +212,7 @@ void digital_signal_prepare_arr(DigitalSignal* signal) {
internals->reload_reg_entries = 0; internals->reload_reg_entries = 0;
for(size_t pos = 0; pos < signal->edge_cnt; pos++) { for(size_t pos = 0; pos < signal->edge_cnt; pos++) {
uint32_t edge_scaled = (internals->factor * signal->edge_timings[pos]) / (1024 * 1024); uint32_t pulse_duration = signal->edge_timings[pos] + internals->reload_reg_remainder;
uint32_t pulse_duration = edge_scaled + internals->reload_reg_remainder;
if(pulse_duration < 10 || pulse_duration > 10000000) { if(pulse_duration < 10 || pulse_duration > 10000000) {
FURI_LOG_D( FURI_LOG_D(
TAG, TAG,

View File

@ -4,7 +4,6 @@ Import("env")
env.Append( env.Append(
CPPPATH=[ CPPPATH=[
"#/lib/digital_signal",
"#/lib/fnv1a_hash", "#/lib/fnv1a_hash",
"#/lib/heatshrink", "#/lib/heatshrink",
"#/lib/micro-ecc", "#/lib/micro-ecc",
@ -26,7 +25,6 @@ libenv.ApplyLibFlags()
sources = [] sources = []
libs_recurse = [ libs_recurse = [
"digital_signal",
"micro-ecc", "micro-ecc",
"u8g2", "u8g2",
"update_util", "update_util",

View File

@ -49,11 +49,11 @@ class DolphinBubbleAnimation:
def load(self, animation_directory: str): def load(self, animation_directory: str):
if not os.path.isdir(animation_directory): if not os.path.isdir(animation_directory):
raise Exception(f"Animation folder doesn't exists: { animation_directory }") raise Exception(f"Animation folder doesn't exist: { animation_directory }")
meta_filename = os.path.join(animation_directory, "meta.txt") meta_filename = os.path.join(animation_directory, "meta.txt")
if not os.path.isfile(meta_filename): if not os.path.isfile(meta_filename):
raise Exception(f"Animation meta file doesn't exists: { meta_filename }") raise Exception(f"Animation meta file doesn't exist: { meta_filename }")
self.logger.info(f"Loading meta from {meta_filename}") self.logger.info(f"Loading meta from {meta_filename}")
file = FlipperFormatFile() file = FlipperFormatFile()