diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c1618665..45a977468 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -152,7 +152,7 @@ jobs: with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' - body-includes: 'to flash the' + body-includes: 'Install with web updater' - name: 'Create or update comment' if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request}} @@ -161,7 +161,7 @@ jobs: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | - [Install with web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}) + [Install with web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}). edit-mode: replace compact: diff --git a/applications/nfc/helpers/nfc_debug_pcap.c b/applications/nfc/helpers/nfc_debug_pcap.c index c54dbedd6..85e020b6c 100644 --- a/applications/nfc/helpers/nfc_debug_pcap.c +++ b/applications/nfc/helpers/nfc_debug_pcap.c @@ -1,6 +1,7 @@ #include "nfc_debug_pcap.h" #include +#include #define TAG "NfcDebugPcap" @@ -14,9 +15,20 @@ #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA -File* nfc_debug_pcap_open(Storage* storage) { +#define NFC_DEBUG_PCAP_FILENAME "/ext/nfc/debug.pcap" +#define NFC_DEBUG_PCAP_BUFFER_SIZE 64 + +struct NfcDebugPcapWorker { + bool alive; + Storage* storage; + File* file; + StreamBufferHandle_t stream; + FuriThread* thread; +}; + +static File* nfc_debug_pcap_open(Storage* storage) { File* file = storage_file_alloc(storage); - if(!storage_file_open(file, "/ext/nfc/debug.pcap", FSAM_WRITE, FSOM_OPEN_APPEND)) { + if(!storage_file_open(file, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) { storage_file_free(file); return NULL; } @@ -41,10 +53,8 @@ File* nfc_debug_pcap_open(Storage* storage) { return file; } -void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16_t len) { - File* file = nfc_debug_pcap_open(storage); - if(!file) return; - +static void + nfc_debug_pcap_write(NfcDebugPcapWorker* instance, uint8_t event, uint8_t* data, uint16_t len) { FuriHalRtcDateTime datetime; furi_hal_rtc_get_datetime(&datetime); @@ -67,33 +77,90 @@ void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16 .event = event, .len = len << 8 | len >> 8, }; - if(storage_file_write(file, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr)) { - FURI_LOG_E(TAG, "Failed to write pcap packet header"); - } else if(storage_file_write(file, data, len) != len) { - FURI_LOG_E(TAG, "Failed to write pcap packet data"); - } - storage_file_free(file); + xStreamBufferSend(instance->stream, &pkt_hdr, sizeof(pkt_hdr), osWaitForever); + xStreamBufferSend(instance->stream, data, len, osWaitForever); } -void nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { +static void + nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { + NfcDebugPcapWorker* instance = context; uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC; - nfc_debug_pcap_write(context, event, data, bits / 8); + nfc_debug_pcap_write(instance, event, data, bits / 8); } -void nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { +static void + nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { + NfcDebugPcapWorker* instance = context; uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD; - nfc_debug_pcap_write(context, event, data, bits / 8); + nfc_debug_pcap_write(instance, event, data, bits / 8); } -void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc) { - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(is_picc) { - tx_rx->sniff_tx = nfc_debug_pcap_write_rx; - tx_rx->sniff_rx = nfc_debug_pcap_write_tx; - } else { - tx_rx->sniff_tx = nfc_debug_pcap_write_tx; - tx_rx->sniff_rx = nfc_debug_pcap_write_rx; +int32_t nfc_debug_pcap_thread(void* context) { + NfcDebugPcapWorker* instance = context; + uint8_t buffer[NFC_DEBUG_PCAP_BUFFER_SIZE]; + + while(instance->alive) { + size_t ret = + xStreamBufferReceive(instance->stream, buffer, NFC_DEBUG_PCAP_BUFFER_SIZE, 50); + if(storage_file_write(instance->file, buffer, ret) != ret) { + FURI_LOG_E(TAG, "Failed to write pcap data"); } - tx_rx->sniff_context = storage; } + + return 0; +} + +NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage) { + NfcDebugPcapWorker* instance = malloc(sizeof(NfcDebugPcapWorker)); + + instance->alive = true; + + instance->storage = storage; + + instance->file = nfc_debug_pcap_open(storage); + + instance->stream = xStreamBufferCreate(4096, 1); + + instance->thread = furi_thread_alloc(); + furi_thread_set_name(instance->thread, "PcapWorker"); + furi_thread_set_stack_size(instance->thread, 1024); + furi_thread_set_callback(instance->thread, nfc_debug_pcap_thread); + furi_thread_set_context(instance->thread, instance); + furi_thread_start(instance->thread); + + return instance; +} + +void nfc_debug_pcap_free(NfcDebugPcapWorker* instance) { + furi_assert(instance); + + instance->alive = false; + + furi_thread_join(instance->thread); + furi_thread_free(instance->thread); + + vStreamBufferDelete(instance->stream); + + if(instance->file) storage_file_free(instance->file); + + instance->storage = NULL; + + free(instance); +} + +void nfc_debug_pcap_prepare_tx_rx( + NfcDebugPcapWorker* instance, + FuriHalNfcTxRxContext* tx_rx, + bool is_picc) { + if(!instance || !instance->file) return; + + if(is_picc) { + tx_rx->sniff_tx = nfc_debug_pcap_write_rx; + tx_rx->sniff_rx = nfc_debug_pcap_write_tx; + } else { + tx_rx->sniff_tx = nfc_debug_pcap_write_tx; + tx_rx->sniff_rx = nfc_debug_pcap_write_rx; + } + + tx_rx->sniff_context = instance; } diff --git a/applications/nfc/helpers/nfc_debug_pcap.h b/applications/nfc/helpers/nfc_debug_pcap.h index 69ba86ebb..6d2a449ae 100644 --- a/applications/nfc/helpers/nfc_debug_pcap.h +++ b/applications/nfc/helpers/nfc_debug_pcap.h @@ -3,10 +3,19 @@ #include #include +typedef struct NfcDebugPcapWorker NfcDebugPcapWorker; + +NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage); + +void nfc_debug_pcap_free(NfcDebugPcapWorker* instance); + /** Prepare tx/rx context for debug pcap logging, if enabled. * + * @param instance NfcDebugPcapWorker* instance, can be NULL * @param tx_rx TX/RX context to log - * @param storage Storage to log to * @param is_picc if true, record Flipper as PICC, else PCD. */ -void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc); +void nfc_debug_pcap_prepare_tx_rx( + NfcDebugPcapWorker* instance, + FuriHalNfcTxRxContext* tx_rx, + bool is_picc); diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 907f5a4cb..8c8512f32 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -1,17 +1,6 @@ #include "nfc_worker_i.h" #include -#include -#include -#include -#include -#include -#include -#include - -#include "helpers/nfc_mf_classic_dict.h" -#include "helpers/nfc_debug_pcap.h" - #define TAG "NfcWorker" /***************************** NFC Worker API *******************************/ @@ -36,13 +25,22 @@ NfcWorker* nfc_worker_alloc() { } nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + nfc_worker->debug_pcap_worker = nfc_debug_pcap_alloc(nfc_worker->storage); + } + return nfc_worker; } void nfc_worker_free(NfcWorker* nfc_worker) { furi_assert(nfc_worker); + furi_thread_free(nfc_worker->thread); + furi_record_close("storage"); + + if(nfc_worker->debug_pcap_worker) nfc_debug_pcap_free(nfc_worker->debug_pcap_worker); + free(nfc_worker); } @@ -154,7 +152,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { void nfc_worker_emulate(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; @@ -177,7 +175,7 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) { void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); EmvApplication emv_app = {}; NfcDeviceData* result = nfc_worker->dev_data; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; @@ -209,7 +207,7 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { void nfc_worker_read_emv(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); EmvApplication emv_app = {}; NfcDeviceData* result = nfc_worker->dev_data; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; @@ -258,7 +256,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData params = { .uid = {0xCF, 0x72, 0xd4, 0x40}, .uid_len = 4, @@ -283,7 +281,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); MfUltralightReader reader = {}; MfUltralightData data = {}; NfcDeviceData* result = nfc_worker->dev_data; @@ -348,7 +346,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker->callback); FuriHalNfcTxRxContext tx_rx_ctx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx_ctx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx_ctx, false); MfClassicAuthContext auth_ctx = {}; MfClassicReader reader = {}; uint64_t curr_key = 0; @@ -491,6 +489,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; MfClassicEmulator emulator = { .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), @@ -519,7 +518,7 @@ void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); NfcDeviceData* result = nfc_worker->dev_data; nfc_device_data_clear(result); MifareDesfireData* data = &result->mf_df_data; diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h index a6f937f7d..18c495a46 100755 --- a/applications/nfc/nfc_worker_i.h +++ b/applications/nfc/nfc_worker_i.h @@ -1,11 +1,22 @@ #pragma once -#include "nfc_i.h" #include "nfc_worker.h" +#include "nfc_i.h" #include #include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers/nfc_mf_classic_dict.h" +#include "helpers/nfc_debug_pcap.h" + struct NfcWorker { FuriThread* thread; Storage* storage; @@ -17,6 +28,8 @@ struct NfcWorker { void* context; NfcWorkerState state; + + NfcDebugPcapWorker* debug_pcap_worker; }; void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); diff --git a/applications/storage/storage_external_api.c b/applications/storage/storage_external_api.c index 7f600af23..77bb6550b 100644 --- a/applications/storage/storage_external_api.c +++ b/applications/storage/storage_external_api.c @@ -134,6 +134,10 @@ bool storage_file_close(File* file) { } uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { + if(bytes_to_read == 0) { + return 0; + } + S_FILE_API_PROLOGUE; S_API_PROLOGUE; @@ -150,6 +154,10 @@ uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { } uint16_t storage_file_write(File* file, const void* buff, uint16_t bytes_to_write) { + if(bytes_to_write == 0) { + return 0; + } + S_FILE_API_PROLOGUE; S_API_PROLOGUE; diff --git a/assets/resources/badusb/demo_macos.txt b/assets/resources/badusb/demo_macos.txt index 5070edad5..6da305905 100644 --- a/assets/resources/badusb/demo_macos.txt +++ b/assets/resources/badusb/demo_macos.txt @@ -13,7 +13,7 @@ DELAY 500 ENTER DELAY 750 -REM Copy-Paste previuos string +REM Copy-Paste previous string UP CTRL c @@ -77,7 +77,7 @@ ENTER STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script format ENTER -STRING More information about script synax can be found here: +STRING More information about script syntax can be found here: ENTER STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript ENTER diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 070a33f68..6ffb6e3a0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -392,6 +392,10 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + if(tx_rx->sniff_tx) { + tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); + } + // Manually wait for interrupt furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE); @@ -428,6 +432,10 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ tx_rx->rx_bits = len * 8; memcpy(tx_rx->rx_data, rx, len); + if(tx_rx->sniff_rx) { + tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); + } + ret = true; } else { FURI_LOG_E(TAG, "Timeout error"); diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h b/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h new file mode 100644 index 000000000..5ea17b6dd --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h @@ -0,0 +1,314 @@ +#pragma once + +#include + +static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = { + // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration + + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* FIFO and internals */ + {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32 + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + // Modem Configuration + {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync + {CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud + {CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + {CC1101_AGCCTRL0, + 0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary + {CC1101_AGCCTRL1, + 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + {CC1101_AGCCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // + + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { + // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration + + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* FIFO and internals */ + {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + // Modem Configuration + {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync + {CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud + {CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + // {CC1101_AGCTRL0,0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary + // {CC1101_AGCTRL1,0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + // {CC1101_AGCCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + //MAGN_TARGET for RX filter BW =< 100 kHz is 0x3. For higher RX filter BW's MAGN_TARGET is 0x7. + {CC1101_AGCCTRL0, + 0x91}, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary + {CC1101_AGCCTRL1, + 0x0}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // + + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs[][2] = { + + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + {CC1101_PKTCTRL1, 0x04}, + + // // Modem Configuration + {CC1101_MDMCFG0, 0x00}, + {CC1101_MDMCFG1, 0x02}, + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) + {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud + {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz + {CC1101_DEVIATN, 0x04}, //Deviation 2.380371 kHz + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + {CC1101_AGCCTRL0, + 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary + {CC1101_AGCCTRL1, + 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer + {CC1101_FREND1, 0x56}, + + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs[][2] = { + + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + {CC1101_PKTCTRL1, 0x04}, + + // // Modem Configuration + {CC1101_MDMCFG0, 0x00}, + {CC1101_MDMCFG1, 0x02}, + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) + {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud + {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz + {CC1101_DEVIATN, 0x47}, //Deviation 47.60742 kHz + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + {CC1101_AGCCTRL0, + 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary + {CC1101_AGCCTRL1, + 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer + {CC1101_FREND1, 0x56}, + + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = { + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x06}, + + {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION + {CC1101_SYNC1, 0x46}, + {CC1101_SYNC0, 0x4C}, + {CC1101_ADDR, 0x00}, + {CC1101_PKTLEN, 0x00}, + {CC1101_CHANNR, 0x00}, + + {CC1101_PKTCTRL0, 0x05}, + + {CC1101_FSCTRL0, 0x23}, + {CC1101_FSCTRL1, 0x06}, + + {CC1101_MDMCFG0, 0xF8}, + {CC1101_MDMCFG1, 0x22}, + {CC1101_MDMCFG2, 0x72}, + {CC1101_MDMCFG3, 0xF8}, + {CC1101_MDMCFG4, 0x5B}, + {CC1101_DEVIATN, 0x47}, + + {CC1101_MCSM0, 0x18}, + {CC1101_FOCCFG, 0x16}, + + {CC1101_AGCCTRL0, 0xB2}, + {CC1101_AGCCTRL1, 0x00}, + {CC1101_AGCCTRL2, 0xC7}, + + {CC1101_FREND0, 0x10}, + {CC1101_FREND1, 0x56}, + + {CC1101_BSCFG, 0x1C}, + {CC1101_FSTEST, 0x59}, + + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_gfsk_9_99kb_async_regs[][2] = { + + {CC1101_IOCFG0, 0x06}, //GDO0 Output Pin Configuration + {CC1101_FIFOTHR, 0x47}, //RX FIFO and TX FIFO Thresholds + + //1 : CRC calculation in TX and CRC check in RX enabled, + //1 : Variable packet length mode. Packet length configured by the first byte after sync word + {CC1101_PKTCTRL0, 0x05}, + + {CC1101_FSCTRL1, 0x06}, //Frequency Synthesizer Control + + {CC1101_SYNC1, 0x46}, + {CC1101_SYNC0, 0x4C}, + {CC1101_ADDR, 0x00}, + {CC1101_PKTLEN, 0x00}, + + {CC1101_MDMCFG4, 0xC8}, //Modem Configuration 9.99 + {CC1101_MDMCFG3, 0x93}, //Modem Configuration + {CC1101_MDMCFG2, 0x12}, // 2: 16/16 sync word bits detected + + {CC1101_DEVIATN, 0x34}, //Deviation = 19.042969 + {CC1101_MCSM0, 0x18}, //Main Radio Control State Machine Configuration + {CC1101_FOCCFG, 0x16}, //Frequency Offset Compensation Configuration + + {CC1101_AGCCTRL2, 0x43}, //AGC Control + {CC1101_AGCCTRL1, 0x40}, + {CC1101_AGCCTRL0, 0x91}, + + {CC1101_WORCTRL, 0xFB}, //Wake On Radio Control + /* End */ + {0, 0}, +}; + +static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { + 0x00, + 0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + +static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = { + 0x00, + 0x37, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + +static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { + 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + +static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = { + 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + +static const uint8_t furi_hal_subghz_preset_gfsk_async_patable[8] = { + 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00};