From e3d473bf429bd254b53550ebcbbb0d389b49240c Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Wed, 8 Feb 2023 07:41:22 +0300 Subject: [PATCH 01/34] [FL-2435] SD over SPI improvements (#2204) * get rid of BSP layer * sector_cache: init in any case * new sd-spi driver: init * Delete stm32_adafruit_sd.c.old * Delete spi_sd_hal.c.old * Storage: faster api lock primitive * Threads: priority control * Flags: correct error code * Spi: dma mode * SD-card: use DMA for big blocks of SPI data * Fix wrong SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE value * do not memset cache if it is NULL * remove top-level timeouts * sd hal: disable debug * Furi HAL: DMA * Furi HAL RFID: use furi_hal_dma * Furi HAL DMA: tests * Furi HAL DMA: docs * rollback "Furi HAL RFID: use furi_hal_dma" * 4 channels taken from DMA manager for core HAL. * Furi HAL DMA: live fast, die young * RPC tests: increase message buffer * SPI HAL: use second DMA instance * sd hal: new CID getter * SPI hal: use non-DMA version if kernel is not running * IR hal: generalize DMA definition * storage: add CID data to sd info * RFID hal: generalize DMA definition * SUBGHZ hal: generalize DMA definition. Core hal moved to DMA2. * Storage: small optimizations, removal of extra mutex * Storage: redundant macro * SD hal: more timeouts * SPI hal: DMA init * Target: make furi_hal_spi_dma_init symbol private * Update F18 api symbols Co-authored-by: Aleksandr Kutuzov --- applications/debug/unit_tests/rpc/rpc_test.c | 2 +- applications/services/storage/storage_cli.c | 21 +- .../services/storage/storage_external_api.c | 9 +- applications/services/storage/storage_glue.c | 18 +- applications/services/storage/storage_glue.h | 3 - .../services/storage/storage_message.h | 3 +- .../services/storage/storage_processing.c | 39 +- .../services/storage/storage_sd_api.h | 10 + .../services/storage/storages/storage_ext.c | 33 +- .../scenes/storage_settings_scene_sd_info.c | 21 +- firmware/targets/f18/api_symbols.csv | 6 +- firmware/targets/f18/furi_hal/furi_hal.c | 1 + firmware/targets/f7/api_symbols.csv | 6 +- firmware/targets/f7/fatfs/sd_spi_io.c | 877 +++++++++++++ firmware/targets/f7/fatfs/sd_spi_io.h | 157 +++ firmware/targets/f7/fatfs/sector_cache.c | 5 - firmware/targets/f7/fatfs/spi_sd_hal.c | 98 -- firmware/targets/f7/fatfs/stm32_adafruit_sd.c | 1113 ----------------- firmware/targets/f7/fatfs/stm32_adafruit_sd.h | 245 ---- firmware/targets/f7/fatfs/user_diskio.c | 36 +- firmware/targets/f7/fatfs/user_diskio.h | 2 +- firmware/targets/f7/furi_hal/furi_hal.c | 1 + .../targets/f7/furi_hal/furi_hal_infrared.c | 121 +- firmware/targets/f7/furi_hal/furi_hal_rfid.c | 46 +- firmware/targets/f7/furi_hal/furi_hal_spi.c | 231 +++- .../targets/f7/furi_hal/furi_hal_subghz.c | 49 +- firmware/targets/f7/src/update.c | 4 +- .../targets/furi_hal_include/furi_hal_spi.h | 20 + furi/core/event_flag.c | 2 +- furi/core/thread.c | 9 + furi/core/thread.h | 12 + 31 files changed, 1539 insertions(+), 1661 deletions(-) create mode 100644 firmware/targets/f7/fatfs/sd_spi_io.c create mode 100644 firmware/targets/f7/fatfs/sd_spi_io.h delete mode 100644 firmware/targets/f7/fatfs/spi_sd_hal.c delete mode 100644 firmware/targets/f7/fatfs/stm32_adafruit_sd.c delete mode 100644 firmware/targets/f7/fatfs/stm32_adafruit_sd.h diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index 5b52df2fa..76acf6be9 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -89,7 +89,7 @@ static void test_rpc_setup(void) { } furi_check(rpc_session[0].session); - rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1); + rpc_session[0].output_stream = furi_stream_buffer_alloc(4096, 1); rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback); rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary(); rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary(); diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index eeaa7fce8..ff2055697 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -61,28 +60,26 @@ static void storage_cli_info(Cli* cli, FuriString* path) { } } else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) { SDInfo sd_info; - SD_CID sd_cid; FS_Error error = storage_sd_info(api, &sd_info); - BSP_SD_GetCIDRegister(&sd_cid); if(error != FSE_OK) { storage_cli_print_error(error); } else { printf( "Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n" - "%02x%2.2s %5.5s %i.%i\r\nSN:%04lx %02i/%i\r\n", + "%02x%s %s v%i.%i\r\nSN:%04lx %02i/%i\r\n", sd_info.label, sd_api_get_fs_type_text(sd_info.fs_type), sd_info.kb_total, sd_info.kb_free, - sd_cid.ManufacturerID, - sd_cid.OEM_AppliID, - sd_cid.ProdName, - sd_cid.ProdRev >> 4, - sd_cid.ProdRev & 0xf, - sd_cid.ProdSN, - sd_cid.ManufactMonth, - sd_cid.ManufactYear + 2000); + sd_info.manufacturer_id, + sd_info.oem_id, + sd_info.product_name, + sd_info.product_revision_major, + sd_info.product_revision_minor, + sd_info.product_serial_number, + sd_info.manufacturing_month, + sd_info.manufacturing_year); } } else { storage_cli_print_usage(); diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 6929a9cbd..c5dfd533e 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -12,9 +12,7 @@ #define TAG "StorageAPI" -#define S_API_PROLOGUE \ - FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0); \ - furi_check(semaphore != NULL); +#define S_API_PROLOGUE FuriApiLock lock = api_lock_alloc_locked(); #define S_FILE_API_PROLOGUE \ Storage* storage = file->storage; \ @@ -24,13 +22,12 @@ furi_check( \ furi_message_queue_put(storage->message_queue, &message, FuriWaitForever) == \ FuriStatusOk); \ - furi_semaphore_acquire(semaphore, FuriWaitForever); \ - furi_semaphore_free(semaphore); + api_lock_wait_unlock_and_free(lock) #define S_API_MESSAGE(_command) \ SAReturn return_data; \ StorageMessage message = { \ - .semaphore = semaphore, \ + .lock = lock, \ .command = _command, \ .data = &data, \ .return_data = &return_data, \ diff --git a/applications/services/storage/storage_glue.c b/applications/services/storage/storage_glue.c index 22f2e3dfa..cccf4046a 100644 --- a/applications/services/storage/storage_glue.c +++ b/applications/services/storage/storage_glue.c @@ -31,29 +31,13 @@ void storage_file_clear(StorageFile* obj) { /****************** storage data ******************/ void storage_data_init(StorageData* storage) { - storage->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - furi_check(storage->mutex != NULL); storage->data = NULL; storage->status = StorageStatusNotReady; StorageFileList_init(storage->files); } -bool storage_data_lock(StorageData* storage) { - return (furi_mutex_acquire(storage->mutex, FuriWaitForever) == FuriStatusOk); -} - -bool storage_data_unlock(StorageData* storage) { - return (furi_mutex_release(storage->mutex) == FuriStatusOk); -} - StorageStatus storage_data_status(StorageData* storage) { - StorageStatus status; - - storage_data_lock(storage); - status = storage->status; - storage_data_unlock(storage); - - return status; + return storage->status; } const char* storage_data_status_text(StorageData* storage) { diff --git a/applications/services/storage/storage_glue.h b/applications/services/storage/storage_glue.h index 6fdc70099..501c26abc 100644 --- a/applications/services/storage/storage_glue.h +++ b/applications/services/storage/storage_glue.h @@ -38,8 +38,6 @@ void storage_file_set(StorageFile* obj, const StorageFile* src); void storage_file_clear(StorageFile* obj); void storage_data_init(StorageData* storage); -bool storage_data_lock(StorageData* storage); -bool storage_data_unlock(StorageData* storage); StorageStatus storage_data_status(StorageData* storage); const char* storage_data_status_text(StorageData* storage); void storage_data_timestamp(StorageData* storage); @@ -57,7 +55,6 @@ struct StorageData { const FS_Api* fs_api; StorageApi api; void* data; - FuriMutex* mutex; StorageStatus status; StorageFileList_t files; uint32_t timestamp; diff --git a/applications/services/storage/storage_message.h b/applications/services/storage/storage_message.h index 987268017..3edb1018e 100644 --- a/applications/services/storage/storage_message.h +++ b/applications/services/storage/storage_message.h @@ -1,5 +1,6 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -130,7 +131,7 @@ typedef enum { } StorageCommand; typedef struct { - FuriSemaphore* semaphore; + FuriApiLock lock; StorageCommand command; SAData* data; SAReturn* return_data; diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index 795a5d11c..b1ea5d29b 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -2,15 +2,7 @@ #include #include -#define FS_CALL(_storage, _fn) \ - storage_data_lock(_storage); \ - ret = _storage->fs_api->_fn; \ - storage_data_unlock(_storage); - -#define ST_CALL(_storage, _fn) \ - storage_data_lock(_storage); \ - ret = _storage->api._fn; \ - storage_data_unlock(_storage); +#define FS_CALL(_storage, _fn) ret = _storage->fs_api->_fn; static StorageData* storage_get_storage_by_type(Storage* app, StorageType type) { furi_check(type == ST_EXT || type == ST_INT); @@ -44,16 +36,11 @@ static const char* remove_vfs(const char* path) { static StorageType storage_get_type_by_path(Storage* app, const char* path) { StorageType type = ST_ERROR; - if(strlen(path) >= strlen(STORAGE_EXT_PATH_PREFIX) && - memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) { + if(memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) { type = ST_EXT; - } else if( - strlen(path) >= strlen(STORAGE_INT_PATH_PREFIX) && - memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) { + } else if(memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) { type = ST_INT; - } else if( - strlen(path) >= strlen(STORAGE_ANY_PATH_PREFIX) && - memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) { + } else if(memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) { type = ST_ANY; } @@ -68,21 +55,15 @@ static StorageType storage_get_type_by_path(Storage* app, const char* path) { } static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) { - if(memcmp( - furi_string_get_cstr(path), STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == - 0) { + if(furi_string_search(path, STORAGE_ANY_PATH_PREFIX) == 0) { switch(real_storage) { case ST_EXT: - furi_string_set_char(path, 0, STORAGE_EXT_PATH_PREFIX[0]); - furi_string_set_char(path, 1, STORAGE_EXT_PATH_PREFIX[1]); - furi_string_set_char(path, 2, STORAGE_EXT_PATH_PREFIX[2]); - furi_string_set_char(path, 3, STORAGE_EXT_PATH_PREFIX[3]); + furi_string_replace_at( + path, 0, strlen(STORAGE_EXT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX); break; case ST_INT: - furi_string_set_char(path, 0, STORAGE_INT_PATH_PREFIX[0]); - furi_string_set_char(path, 1, STORAGE_INT_PATH_PREFIX[1]); - furi_string_set_char(path, 2, STORAGE_INT_PATH_PREFIX[2]); - furi_string_set_char(path, 3, STORAGE_INT_PATH_PREFIX[3]); + furi_string_replace_at( + path, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_INT_PATH_PREFIX); break; default: break; @@ -604,7 +585,7 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) { break; } - furi_semaphore_release(message->semaphore); + api_lock_unlock(message->lock); } void storage_process_message(Storage* app, StorageMessage* message) { diff --git a/applications/services/storage/storage_sd_api.h b/applications/services/storage/storage_sd_api.h index f83360955..880640394 100644 --- a/applications/services/storage/storage_sd_api.h +++ b/applications/services/storage/storage_sd_api.h @@ -23,6 +23,16 @@ typedef struct { uint16_t cluster_size; uint16_t sector_size; char label[SD_LABEL_LENGTH]; + + uint8_t manufacturer_id; + char oem_id[3]; + char product_name[6]; + uint8_t product_revision_major; + uint8_t product_revision_minor; + uint32_t product_serial_number; + uint8_t manufacturing_month; + uint16_t manufacturing_year; + FS_Error error; } SDInfo; diff --git a/applications/services/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c index 0c81a0006..530c88f85 100644 --- a/applications/services/storage/storages/storage_ext.c +++ b/applications/services/storage/storages/storage_ext.c @@ -26,12 +26,10 @@ static FS_Error storage_ext_parse_error(SDError error); static bool sd_mount_card(StorageData* storage, bool notify) { bool result = false; - uint8_t counter = BSP_SD_MaxMountRetryCount(); + uint8_t counter = sd_max_mount_retry_count(); uint8_t bsp_result; SDData* sd_data = storage->data; - storage_data_lock(storage); - while(result == false && counter > 0 && hal_sd_detect()) { if(notify) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); @@ -41,9 +39,9 @@ static bool sd_mount_card(StorageData* storage, bool notify) { if((counter % 2) == 0) { // power reset sd card - bsp_result = BSP_SD_Init(true); + bsp_result = sd_init(true); } else { - bsp_result = BSP_SD_Init(false); + bsp_result = sd_init(false); } if(bsp_result) { @@ -91,7 +89,6 @@ static bool sd_mount_card(StorageData* storage, bool notify) { } storage_data_timestamp(storage); - storage_data_unlock(storage); return result; } @@ -100,14 +97,12 @@ FS_Error sd_unmount_card(StorageData* storage) { SDData* sd_data = storage->data; SDError error; - storage_data_lock(storage); storage->status = StorageStatusNotReady; error = FR_DISK_ERR; // TODO do i need to close the files? - f_mount(0, sd_data->path, 0); - storage_data_unlock(storage); + return storage_ext_parse_error(error); } @@ -120,8 +115,6 @@ FS_Error sd_format_card(StorageData* storage) { SDData* sd_data = storage->data; SDError error; - storage_data_lock(storage); - work_area = malloc(_MAX_SS); error = f_mkfs(sd_data->path, FM_ANY, 0, work_area, _MAX_SS); free(work_area); @@ -138,8 +131,6 @@ FS_Error sd_format_card(StorageData* storage) { storage->status = StorageStatusOK; } while(false); - storage_data_unlock(storage); - return storage_ext_parse_error(error); #endif } @@ -156,14 +147,12 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) { memset(sd_info, 0, sizeof(SDInfo)); // get fs info - storage_data_lock(storage); error = f_getlabel(sd_data->path, sd_info->label, NULL); if(error == FR_OK) { #ifndef FURI_RAM_EXEC error = f_getfree(sd_data->path, &free_clusters, &fs); #endif } - storage_data_unlock(storage); if(error == FR_OK) { // calculate size @@ -210,6 +199,20 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) { #endif } + SD_CID cid; + SdSpiStatus status = sd_get_cid(&cid); + + if(status == SdSpiStatusOK) { + sd_info->manufacturer_id = cid.ManufacturerID; + memcpy(sd_info->oem_id, cid.OEM_AppliID, sizeof(cid.OEM_AppliID)); + memcpy(sd_info->product_name, cid.ProdName, sizeof(cid.ProdName)); + sd_info->product_revision_major = cid.ProdRev >> 4; + sd_info->product_revision_minor = cid.ProdRev & 0x0F; + sd_info->product_serial_number = cid.ProdSN; + sd_info->manufacturing_year = 2000 + cid.ManufactYear; + sd_info->manufacturing_month = cid.ManufactMonth; + } + return storage_ext_parse_error(error); } diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c index a7991bc19..81c786d0c 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c @@ -1,5 +1,4 @@ #include "../storage_settings.h" -#include static void storage_settings_scene_sd_info_dialog_callback(DialogExResult result, void* context) { StorageSettings* app = context; @@ -12,9 +11,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) { DialogEx* dialog_ex = app->dialog_ex; SDInfo sd_info; - SD_CID sd_cid; FS_Error sd_status = storage_sd_info(app->fs_api, &sd_info); - BSP_SD_GetCIDRegister(&sd_cid); scene_manager_set_scene_state(app->scene_manager, StorageSettingsSDInfo, sd_status); @@ -31,19 +28,19 @@ void storage_settings_scene_sd_info_on_enter(void* context) { furi_string_printf( app->text_string, "Label: %s\nType: %s\n%lu KiB total\n%lu KiB free\n" - "%02X%2.2s %5.5s %i.%i\nSN:%04lX %02i/%i", + "%02X%s %s v%i.%i\nSN:%04lX %02i/%i", sd_info.label, sd_api_get_fs_type_text(sd_info.fs_type), sd_info.kb_total, sd_info.kb_free, - sd_cid.ManufacturerID, - sd_cid.OEM_AppliID, - sd_cid.ProdName, - sd_cid.ProdRev >> 4, - sd_cid.ProdRev & 0xf, - sd_cid.ProdSN, - sd_cid.ManufactMonth, - sd_cid.ManufactYear + 2000); + sd_info.manufacturer_id, + sd_info.oem_id, + sd_info.product_name, + sd_info.product_revision_major, + sd_info.product_revision_minor, + sd_info.product_serial_number, + sd_info.manufacturing_month, + sd_info.manufacturing_year); dialog_ex_set_text( dialog_ex, furi_string_get_cstr(app->text_string), 4, 1, AlignLeft, AlignTop); } diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index e4a7dfdd5..ff6dbc239 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.1,, +Version,+,12.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1062,10 +1062,12 @@ Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, +Function,-,furi_hal_spi_dma_init,void, Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* Function,+,furi_hal_switch,void,void* Function,+,furi_hal_uart_deinit,void,FuriHalUartId @@ -1231,6 +1233,7 @@ Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t" Function,+,furi_thread_free,void,FuriThread* Function,+,furi_thread_get_current,FuriThread*, Function,+,furi_thread_get_current_id,FuriThreadId, +Function,+,furi_thread_get_current_priority,FuriThreadPriority, Function,+,furi_thread_get_heap_size,size_t,FuriThread* Function,+,furi_thread_get_id,FuriThreadId,FuriThread* Function,+,furi_thread_get_name,const char*,FuriThreadId @@ -1244,6 +1247,7 @@ Function,+,furi_thread_mark_as_service,void,FuriThread* Function,+,furi_thread_resume,void,FuriThreadId Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" Function,+,furi_thread_set_context,void,"FuriThread*, void*" +Function,+,furi_thread_set_current_priority,void,FuriThreadPriority Function,+,furi_thread_set_name,void,"FuriThread*, const char*" Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority" Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t" diff --git a/firmware/targets/f18/furi_hal/furi_hal.c b/firmware/targets/f18/furi_hal/furi_hal.c index ad35a0074..0a68fdb69 100644 --- a/firmware/targets/f18/furi_hal/furi_hal.c +++ b/firmware/targets/f18/furi_hal/furi_hal.c @@ -51,6 +51,7 @@ void furi_hal_init() { furi_hal_version_init(); furi_hal_spi_config_init(); + furi_hal_spi_dma_init(); furi_hal_speaker_init(); FURI_LOG_I(TAG, "Speaker OK"); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index c1a979859..a1f34f106 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.1,, +Version,+,12.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1325,10 +1325,12 @@ Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, +Function,-,furi_hal_spi_dma_init,void, Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* Function,-,furi_hal_subghz_dump_state,void, Function,+,furi_hal_subghz_flush_rx,void, @@ -1524,6 +1526,7 @@ Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t" Function,+,furi_thread_free,void,FuriThread* Function,+,furi_thread_get_current,FuriThread*, Function,+,furi_thread_get_current_id,FuriThreadId, +Function,+,furi_thread_get_current_priority,FuriThreadPriority, Function,+,furi_thread_get_heap_size,size_t,FuriThread* Function,+,furi_thread_get_id,FuriThreadId,FuriThread* Function,+,furi_thread_get_name,const char*,FuriThreadId @@ -1537,6 +1540,7 @@ Function,+,furi_thread_mark_as_service,void,FuriThread* Function,+,furi_thread_resume,void,FuriThreadId Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" Function,+,furi_thread_set_context,void,"FuriThread*, void*" +Function,+,furi_thread_set_current_priority,void,FuriThreadPriority Function,+,furi_thread_set_name,void,"FuriThread*, const char*" Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority" Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t" diff --git a/firmware/targets/f7/fatfs/sd_spi_io.c b/firmware/targets/f7/fatfs/sd_spi_io.c new file mode 100644 index 000000000..93b837e85 --- /dev/null +++ b/firmware/targets/f7/fatfs/sd_spi_io.c @@ -0,0 +1,877 @@ +#include "sd_spi_io.h" +#include "sector_cache.h" +#include +#include +#include + +// #define SD_SPI_DEBUG 1 +#define TAG "SdSpi" + +#ifdef SD_SPI_DEBUG +#define sd_spi_debug(...) FURI_LOG_I(TAG, __VA_ARGS__) +#else +#define sd_spi_debug(...) +#endif + +#define SD_CMD_LENGTH 6 +#define SD_DUMMY_BYTE 0xFF +#define SD_ANSWER_RETRY_COUNT 8 +#define SD_IDLE_RETRY_COUNT 100 +#define SD_BLOCK_SIZE 512 + +#define FLAG_SET(x, y) (((x) & (y)) == (y)) + +static bool sd_high_capacity = false; + +typedef enum { + SdSpiDataResponceOK = 0x05, + SdSpiDataResponceCRCError = 0x0B, + SdSpiDataResponceWriteError = 0x0D, + SdSpiDataResponceOtherError = 0xFF, +} SdSpiDataResponce; + +typedef struct { + uint8_t r1; + uint8_t r2; + uint8_t r3; + uint8_t r4; + uint8_t r5; +} SdSpiCmdAnswer; + +typedef enum { + SdSpiCmdAnswerTypeR1, + SdSpiCmdAnswerTypeR1B, + SdSpiCmdAnswerTypeR2, + SdSpiCmdAnswerTypeR3, + SdSpiCmdAnswerTypeR4R5, + SdSpiCmdAnswerTypeR7, +} SdSpiCmdAnswerType; + +/* + SdSpiCmd and SdSpiToken use non-standard enum value names convention, + because it is more convenient to look for documentation on a specific command. + For example, to find out what the SD_CMD23_SET_BLOCK_COUNT command does, you need to look for + SET_BLOCK_COUNT or CMD23 in the "Part 1 Physical Layer Simplified Specification". + + Do not use that naming convention in other places. +*/ + +typedef enum { + SD_CMD0_GO_IDLE_STATE = 0, + SD_CMD1_SEND_OP_COND = 1, + SD_CMD8_SEND_IF_COND = 8, + SD_CMD9_SEND_CSD = 9, + SD_CMD10_SEND_CID = 10, + SD_CMD12_STOP_TRANSMISSION = 12, + SD_CMD13_SEND_STATUS = 13, + SD_CMD16_SET_BLOCKLEN = 16, + SD_CMD17_READ_SINGLE_BLOCK = 17, + SD_CMD18_READ_MULT_BLOCK = 18, + SD_CMD23_SET_BLOCK_COUNT = 23, + SD_CMD24_WRITE_SINGLE_BLOCK = 24, + SD_CMD25_WRITE_MULT_BLOCK = 25, + SD_CMD27_PROG_CSD = 27, + SD_CMD28_SET_WRITE_PROT = 28, + SD_CMD29_CLR_WRITE_PROT = 29, + SD_CMD30_SEND_WRITE_PROT = 30, + SD_CMD32_SD_ERASE_GRP_START = 32, + SD_CMD33_SD_ERASE_GRP_END = 33, + SD_CMD34_UNTAG_SECTOR = 34, + SD_CMD35_ERASE_GRP_START = 35, + SD_CMD36_ERASE_GRP_END = 36, + SD_CMD37_UNTAG_ERASE_GROUP = 37, + SD_CMD38_ERASE = 38, + SD_CMD41_SD_APP_OP_COND = 41, + SD_CMD55_APP_CMD = 55, + SD_CMD58_READ_OCR = 58, +} SdSpiCmd; + +/** Data tokens */ +typedef enum { + SD_TOKEN_START_DATA_SINGLE_BLOCK_READ = 0xFE, + SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ = 0xFE, + SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE = 0xFE, + SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE = 0xFC, + SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE = 0xFD, +} SdSpiToken; + +/** R1 answer value */ +typedef enum { + SdSpi_R1_NO_ERROR = 0x00, + SdSpi_R1_IN_IDLE_STATE = 0x01, + SdSpi_R1_ERASE_RESET = 0x02, + SdSpi_R1_ILLEGAL_COMMAND = 0x04, + SdSpi_R1_COM_CRC_ERROR = 0x08, + SdSpi_R1_ERASE_SEQUENCE_ERROR = 0x10, + SdSpi_R1_ADDRESS_ERROR = 0x20, + SdSpi_R1_PARAMETER_ERROR = 0x40, +} SdSpiR1; + +/** R2 answer value */ +typedef enum { + /* R2 answer value */ + SdSpi_R2_NO_ERROR = 0x00, + SdSpi_R2_CARD_LOCKED = 0x01, + SdSpi_R2_LOCKUNLOCK_ERROR = 0x02, + SdSpi_R2_ERROR = 0x04, + SdSpi_R2_CC_ERROR = 0x08, + SdSpi_R2_CARD_ECC_FAILED = 0x10, + SdSpi_R2_WP_VIOLATION = 0x20, + SdSpi_R2_ERASE_PARAM = 0x40, + SdSpi_R2_OUTOFRANGE = 0x80, +} SdSpiR2; + +static inline void sd_spi_select_card() { + furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false); + furi_delay_us(10); // Entry guard time for some SD cards +} + +static inline void sd_spi_deselect_card() { + furi_delay_us(10); // Exit guard time for some SD cards + furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true); +} + +static void sd_spi_bus_to_ground() { + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->miso, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->mosi, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->sck, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + + sd_spi_select_card(); + furi_hal_gpio_write(furi_hal_sd_spi_handle->miso, false); + furi_hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); + furi_hal_gpio_write(furi_hal_sd_spi_handle->sck, false); +} + +static void sd_spi_bus_rise_up() { + sd_spi_deselect_card(); + + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->miso, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->mosi, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->sck, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); +} + +static inline uint8_t sd_spi_read_byte(void) { + uint8_t responce; + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, &responce, 1, SD_TIMEOUT_MS)); + return responce; +} + +static inline void sd_spi_write_byte(uint8_t data) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, NULL, 1, SD_TIMEOUT_MS)); +} + +static inline uint8_t sd_spi_write_and_read_byte(uint8_t data) { + uint8_t responce; + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, &responce, 1, SD_TIMEOUT_MS)); + return responce; +} + +static inline void sd_spi_write_bytes(uint8_t* data, uint32_t size) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS)); +} + +static inline void sd_spi_read_bytes(uint8_t* data, uint32_t size) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS)); +} + +static inline void sd_spi_write_bytes_dma(uint8_t* data, uint32_t size) { + uint32_t timeout_mul = (size / 512) + 1; + furi_check(furi_hal_spi_bus_trx_dma( + furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS * timeout_mul)); +} + +static inline void sd_spi_read_bytes_dma(uint8_t* data, uint32_t size) { + uint32_t timeout_mul = (size / 512) + 1; + furi_check(furi_hal_spi_bus_trx_dma( + furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS * timeout_mul)); +} + +static uint8_t sd_spi_wait_for_data_and_read(void) { + uint8_t retry_count = SD_ANSWER_RETRY_COUNT; + uint8_t responce; + + // Wait until we get a valid data + do { + responce = sd_spi_read_byte(); + retry_count--; + + } while((responce == SD_DUMMY_BYTE) && retry_count); + + return responce; +} + +static SdSpiStatus sd_spi_wait_for_data(uint8_t data, uint32_t timeout_ms) { + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_ms * 1000); + uint8_t byte; + + do { + byte = sd_spi_read_byte(); + if(furi_hal_cortex_timer_is_expired(timer)) { + return SdSpiStatusTimeout; + } + } while((byte != data)); + + return SdSpiStatusOK; +} + +static inline void sd_spi_deselect_card_and_purge() { + sd_spi_deselect_card(); + sd_spi_read_byte(); +} + +static inline void sd_spi_purge_crc() { + sd_spi_read_byte(); + sd_spi_read_byte(); +} + +static SdSpiCmdAnswer + sd_spi_send_cmd(SdSpiCmd cmd, uint32_t arg, uint8_t crc, SdSpiCmdAnswerType answer_type) { + uint8_t frame[SD_CMD_LENGTH]; + SdSpiCmdAnswer cmd_answer = { + .r1 = SD_DUMMY_BYTE, + .r2 = SD_DUMMY_BYTE, + .r3 = SD_DUMMY_BYTE, + .r4 = SD_DUMMY_BYTE, + .r5 = SD_DUMMY_BYTE, + }; + + // R1 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 1 Bytes answer + NEC(0) = 15bytes + // R1b identical to R1 + Busy information + // R2 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 2 Bytes answer + NEC(0) = 16bytes + + frame[0] = ((uint8_t)cmd | 0x40); + frame[1] = (uint8_t)(arg >> 24); + frame[2] = (uint8_t)(arg >> 16); + frame[3] = (uint8_t)(arg >> 8); + frame[4] = (uint8_t)(arg); + frame[5] = (crc | 0x01); + + sd_spi_select_card(); + sd_spi_write_bytes(frame, sizeof(frame)); + + switch(answer_type) { + case SdSpiCmdAnswerTypeR1: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + break; + case SdSpiCmdAnswerTypeR1B: + // TODO: can be wrong, at least for SD_CMD12_STOP_TRANSMISSION you need to purge one byte before reading R1 + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + + // In general this shenenigans seems suspicious, please double check SD specs if you are using SdSpiCmdAnswerTypeR1B + // reassert card + sd_spi_deselect_card(); + furi_delay_us(1000); + sd_spi_deselect_card(); + + // and wait for it to be ready + while(sd_spi_read_byte() != 0xFF) { + }; + + break; + case SdSpiCmdAnswerTypeR2: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + cmd_answer.r2 = sd_spi_read_byte(); + break; + case SdSpiCmdAnswerTypeR3: + case SdSpiCmdAnswerTypeR7: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + cmd_answer.r2 = sd_spi_read_byte(); + cmd_answer.r3 = sd_spi_read_byte(); + cmd_answer.r4 = sd_spi_read_byte(); + cmd_answer.r5 = sd_spi_read_byte(); + break; + default: + break; + } + return cmd_answer; +} + +static SdSpiDataResponce sd_spi_get_data_response(uint32_t timeout_ms) { + SdSpiDataResponce responce = sd_spi_read_byte(); + // read busy response byte + sd_spi_read_byte(); + + switch(responce & 0x1F) { + case SdSpiDataResponceOK: + // TODO: check timings + sd_spi_deselect_card(); + sd_spi_select_card(); + + // wait for 0xFF + if(sd_spi_wait_for_data(0xFF, timeout_ms) == SdSpiStatusOK) { + return SdSpiDataResponceOK; + } else { + return SdSpiDataResponceOtherError; + } + case SdSpiDataResponceCRCError: + return SdSpiDataResponceCRCError; + case SdSpiDataResponceWriteError: + return SdSpiDataResponceWriteError; + default: + return SdSpiDataResponceOtherError; + } +} + +static SdSpiStatus sd_spi_init_spi_mode_v1(void) { + SdSpiCmdAnswer response; + uint8_t retry_count = 0; + + sd_spi_debug("Init SD card in SPI mode v1"); + + do { + retry_count++; + + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + + sd_spi_debug("Init SD card in SPI mode v1 done"); + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_init_spi_mode_v2(void) { + SdSpiCmdAnswer response; + uint8_t retry_count = 0; + + sd_spi_debug("Init SD card in SPI mode v2"); + + do { + retry_count++; + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + // ACMD41 (APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = + sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0x40000000, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("ACMD41 failed"); + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + + if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) { + sd_spi_debug("ACMD41 is illegal command"); + retry_count = 0; + do { + retry_count++; + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_IN_IDLE_STATE) { + sd_spi_debug("CMD55 failed"); + return SdSpiStatusError; + } + // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("ACMD41 failed"); + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + } + + sd_spi_debug("Init SD card in SPI mode v2 done"); + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_init_spi_mode(void) { + SdSpiCmdAnswer response; + uint8_t retry_count; + + // CMD0 (GO_IDLE_STATE) to put SD in SPI mode and + // wait for In Idle State Response (R1 Format) equal to 0x01 + retry_count = 0; + do { + retry_count++; + response = sd_spi_send_cmd(SD_CMD0_GO_IDLE_STATE, 0, 0x95, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("CMD0 failed"); + return SdSpiStatusError; + } + } while(response.r1 != SdSpi_R1_IN_IDLE_STATE); + + // CMD8 (SEND_IF_COND) to check the power supply status + // and wait until response (R7 Format) equal to 0xAA and + response = sd_spi_send_cmd(SD_CMD8_SEND_IF_COND, 0x1AA, 0x87, SdSpiCmdAnswerTypeR7); + sd_spi_deselect_card_and_purge(); + + if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) { + if(sd_spi_init_spi_mode_v1() != SdSpiStatusOK) { + sd_spi_debug("Init mode v1 failed"); + return SdSpiStatusError; + } + sd_high_capacity = 0; + } else if(response.r1 == SdSpi_R1_IN_IDLE_STATE) { + if(sd_spi_init_spi_mode_v2() != SdSpiStatusOK) { + sd_spi_debug("Init mode v2 failed"); + return SdSpiStatusError; + } + + // CMD58 (READ_OCR) to initialize SDHC or SDXC cards: R3 response + response = sd_spi_send_cmd(SD_CMD58_READ_OCR, 0, 0xFF, SdSpiCmdAnswerTypeR3); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_debug("CMD58 failed"); + return SdSpiStatusError; + } + sd_high_capacity = (response.r2 & 0x40) >> 6; + } else { + return SdSpiStatusError; + } + + sd_spi_debug("SD card is %s", sd_high_capacity ? "SDHC or SDXC" : "SDSC"); + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_get_csd(SD_CSD* csd) { + uint16_t counter = 0; + uint8_t csd_data[16]; + SdSpiStatus ret = SdSpiStatusError; + SdSpiCmdAnswer response; + + // CMD9 (SEND_CSD): R1 format (0x00 is no errors) + response = sd_spi_send_cmd(SD_CMD9_SEND_CSD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + + if(response.r1 == SdSpi_R1_NO_ERROR) { + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + // read CSD data + for(counter = 0; counter < 16; counter++) { + csd_data[counter] = sd_spi_read_byte(); + } + + sd_spi_purge_crc(); + + /************************************************************************* + CSD header decoding + *************************************************************************/ + + csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; + csd->Reserved1 = csd_data[0] & 0x3F; + csd->TAAC = csd_data[1]; + csd->NSAC = csd_data[2]; + csd->MaxBusClkFrec = csd_data[3]; + csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); + csd->RdBlockLen = csd_data[5] & 0x0F; + csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; + csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; + csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; + csd->DSRImpl = (csd_data[6] & 0x10) >> 4; + + /************************************************************************* + CSD v1/v2 decoding + *************************************************************************/ + + if(sd_high_capacity == 0) { + csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); + csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | + ((csd_data[8] & 0xC0) >> 6); + csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; + csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); + csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; + csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; + csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | + ((csd_data[10] & 0x80) >> 7); + } else { + csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | + ((csd_data[7] & 0xC0) >> 6); + csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | + csd_data[9]; + csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); + } + + csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; + csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); + csd->WrProtectGrSize = (csd_data[11] & 0x7F); + csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; + csd->Reserved2 = (csd_data[12] & 0x60) >> 5; + csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; + csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); + csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; + csd->Reserved3 = (csd_data[13] & 0x1F); + csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; + csd->CopyFlag = (csd_data[14] & 0x40) >> 6; + csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; + csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; + csd->FileFormat = (csd_data[14] & 0x0C) >> 2; + csd->Reserved4 = (csd_data[14] & 0x03); + csd->crc = (csd_data[15] & 0xFE) >> 1; + csd->Reserved5 = (csd_data[15] & 0x01); + + ret = SdSpiStatusOK; + } + } + + sd_spi_deselect_card_and_purge(); + + return ret; +} + +static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) { + uint16_t counter = 0; + uint8_t cid_data[16]; + SdSpiStatus ret = SdSpiStatusError; + SdSpiCmdAnswer response; + + // CMD10 (SEND_CID): R1 format (0x00 is no errors) + response = sd_spi_send_cmd(SD_CMD10_SEND_CID, 0, 0xFF, SdSpiCmdAnswerTypeR1); + + if(response.r1 == SdSpi_R1_NO_ERROR) { + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + // read CID data + for(counter = 0; counter < 16; counter++) { + cid_data[counter] = sd_spi_read_byte(); + } + + sd_spi_purge_crc(); + + Cid->ManufacturerID = cid_data[0]; + memcpy(Cid->OEM_AppliID, cid_data + 1, 2); + memcpy(Cid->ProdName, cid_data + 3, 5); + Cid->ProdRev = cid_data[8]; + Cid->ProdSN = cid_data[9] << 24; + Cid->ProdSN |= cid_data[10] << 16; + Cid->ProdSN |= cid_data[11] << 8; + Cid->ProdSN |= cid_data[12]; + Cid->Reserved1 = (cid_data[13] & 0xF0) >> 4; + Cid->ManufactYear = (cid_data[13] & 0x0F) << 4; + Cid->CID_CRC = (cid_data[15] & 0xFE) >> 1; + Cid->Reserved2 = 1; + + ret = SdSpiStatusOK; + } + } + + sd_spi_deselect_card_and_purge(); + + return ret; +} + +static inline bool sd_cache_get(uint32_t address, uint32_t* data) { + uint8_t* cached_data = sector_cache_get(address); + if(cached_data) { + memcpy(data, cached_data, SD_BLOCK_SIZE); + return true; + } + return false; +} + +static inline void sd_cache_put(uint32_t address, uint32_t* data) { + sector_cache_put(address, (uint8_t*)data); +} + +static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) { + sector_cache_invalidate_range(start_sector, end_sector); +} + +static SdSpiStatus + sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + uint32_t block_address = address; + uint32_t offset = 0; + + // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors) + SdSpiCmdAnswer response = + sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + return SdSpiStatusError; + } + + if(!sd_high_capacity) { + block_address = address * SD_BLOCK_SIZE; + } + + while(blocks--) { + // CMD17 (READ_SINGLE_BLOCK): R1 response (0x00: no errors) + response = + sd_spi_send_cmd(SD_CMD17_READ_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1); + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + // Wait for the data start token + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, timeout_ms) == + SdSpiStatusOK) { + // Read the data block + sd_spi_read_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE); + sd_spi_purge_crc(); + + // increase offset + offset += SD_BLOCK_SIZE; + + // increase block address + if(sd_high_capacity) { + block_address += 1; + } else { + block_address += SD_BLOCK_SIZE; + } + } else { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + sd_spi_deselect_card_and_purge(); + } + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_cmd_write_blocks( + uint32_t* data, + uint32_t address, + uint32_t blocks, + uint32_t timeout_ms) { + uint32_t block_address = address; + uint32_t offset = 0; + + // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors) + SdSpiCmdAnswer response = + sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + return SdSpiStatusError; + } + + if(!sd_high_capacity) { + block_address = address * SD_BLOCK_SIZE; + } + + while(blocks--) { + // CMD24 (WRITE_SINGLE_BLOCK): R1 response (0x00: no errors) + response = sd_spi_send_cmd( + SD_CMD24_WRITE_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1); + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + // Send dummy byte for NWR timing : one byte between CMD_WRITE and TOKEN + // TODO: check bytes count + sd_spi_write_byte(SD_DUMMY_BYTE); + sd_spi_write_byte(SD_DUMMY_BYTE); + + // Send the data start token + sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE); + sd_spi_write_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE); + sd_spi_purge_crc(); + + // Read data response + SdSpiDataResponce data_responce = sd_spi_get_data_response(timeout_ms); + sd_spi_deselect_card_and_purge(); + + if(data_responce != SdSpiDataResponceOK) { + return SdSpiStatusError; + } + + // increase offset + offset += SD_BLOCK_SIZE; + + // increase block address + if(sd_high_capacity) { + block_address += 1; + } else { + block_address += SD_BLOCK_SIZE; + } + } + + return SdSpiStatusOK; +} + +uint8_t sd_max_mount_retry_count() { + return 10; +} + +SdSpiStatus sd_init(bool power_reset) { + // Slow speed init + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); + furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; + + // We reset card in spi_lock context, so it is safe to disturb spi bus + if(power_reset) { + sd_spi_debug("Power reset"); + + // disable power and set low on all bus pins + furi_hal_power_disable_external_3_3v(); + sd_spi_bus_to_ground(); + hal_sd_detect_set_low(); + furi_delay_ms(250); + + // reinit bus and enable power + sd_spi_bus_rise_up(); + hal_sd_detect_init(); + furi_hal_power_enable_external_3_3v(); + furi_delay_ms(100); + } + + SdSpiStatus status = SdSpiStatusError; + + // Send 80 dummy clocks with CS high + sd_spi_deselect_card(); + for(uint8_t i = 0; i < 80; i++) { + sd_spi_write_byte(SD_DUMMY_BYTE); + } + + for(uint8_t i = 0; i < 128; i++) { + status = sd_spi_init_spi_mode(); + if(status == SdSpiStatusOK) { + // SD initialized and init to SPI mode properly + sd_spi_debug("SD init OK after %d retries", i); + break; + } + } + + furi_hal_sd_spi_handle = NULL; + furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); + + // Init sector cache + sector_cache_init(); + + return status; +} + +SdSpiStatus sd_get_card_state(void) { + SdSpiCmdAnswer response; + + // Send CMD13 (SEND_STATUS) to get SD status + response = sd_spi_send_cmd(SD_CMD13_SEND_STATUS, 0, 0xFF, SdSpiCmdAnswerTypeR2); + sd_spi_deselect_card_and_purge(); + + // Return status OK if response is valid + if((response.r1 == SdSpi_R1_NO_ERROR) && (response.r2 == SdSpi_R2_NO_ERROR)) { + return SdSpiStatusOK; + } + + return SdSpiStatusError; +} + +SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) { + SdSpiStatus status; + + status = sd_spi_get_csd(&(card_info->Csd)); + + if(status != SdSpiStatusOK) { + return status; + } + + status = sd_spi_get_cid(&(card_info->Cid)); + + if(status != SdSpiStatusOK) { + return status; + } + + if(sd_high_capacity == 1) { + card_info->LogBlockSize = 512; + card_info->CardBlockSize = 512; + card_info->CardCapacity = ((uint64_t)card_info->Csd.version.v2.DeviceSize + 1UL) * 1024UL * + (uint64_t)card_info->LogBlockSize; + card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize); + } else { + card_info->CardCapacity = (card_info->Csd.version.v1.DeviceSize + 1); + card_info->CardCapacity *= (1UL << (card_info->Csd.version.v1.DeviceSizeMul + 2)); + card_info->LogBlockSize = 512; + card_info->CardBlockSize = 1UL << (card_info->Csd.RdBlockLen); + card_info->CardCapacity *= card_info->CardBlockSize; + card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize); + } + + return status; +} + +SdSpiStatus + sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + SdSpiStatus status = SdSpiStatusError; + + bool single_sector_read = (blocks == 1); + + if(single_sector_read) { + if(sd_cache_get(address, data)) { + return SdSpiStatusOK; + } + + status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms); + + if(status == SdSpiStatusOK) { + sd_cache_put(address, data); + } + } else { + status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms); + } + + return status; +} + +SdSpiStatus + sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + sd_cache_invalidate_range(address, address + blocks); + SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms); + return status; +} + +SdSpiStatus sd_get_cid(SD_CID* cid) { + SdSpiStatus status; + + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); + furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; + + memset(cid, 0, sizeof(SD_CID)); + status = sd_spi_get_cid(cid); + + furi_hal_sd_spi_handle = NULL; + furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); + + return status; +} \ No newline at end of file diff --git a/firmware/targets/f7/fatfs/sd_spi_io.h b/firmware/targets/f7/fatfs/sd_spi_io.h new file mode 100644 index 000000000..8850eceb7 --- /dev/null +++ b/firmware/targets/f7/fatfs/sd_spi_io.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include + +#define __IO volatile + +#define SD_TIMEOUT_MS (1000) + +typedef enum { + SdSpiStatusOK, + SdSpiStatusError, + SdSpiStatusTimeout, +} SdSpiStatus; + +/** + * @brief Card Specific Data: CSD Register + */ +typedef struct { + /* Header part */ + uint8_t CSDStruct : 2; /* CSD structure */ + uint8_t Reserved1 : 6; /* Reserved */ + uint8_t TAAC : 8; /* Data read access-time 1 */ + uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */ + uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */ + uint16_t CardComdClasses : 12; /* Card command classes */ + uint8_t RdBlockLen : 4; /* Max. read data block length */ + uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */ + uint8_t WrBlockMisalign : 1; /* Write block misalignment */ + uint8_t RdBlockMisalign : 1; /* Read block misalignment */ + uint8_t DSRImpl : 1; /* DSR implemented */ + + /* v1 or v2 struct */ + union csd_version { + struct { + uint8_t Reserved1 : 2; /* Reserved */ + uint16_t DeviceSize : 12; /* Device Size */ + uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */ + uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */ + uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */ + uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */ + uint8_t DeviceSizeMul : 3; /* Device size multiplier */ + } v1; + struct { + uint8_t Reserved1 : 6; /* Reserved */ + uint32_t DeviceSize : 22; /* Device Size */ + uint8_t Reserved2 : 1; /* Reserved */ + } v2; + } version; + + uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */ + uint8_t EraseSectorSize : 7; /* Erase group size multiplier */ + uint8_t WrProtectGrSize : 7; /* Write protect group size */ + uint8_t WrProtectGrEnable : 1; /* Write protect group enable */ + uint8_t Reserved2 : 2; /* Reserved */ + uint8_t WrSpeedFact : 3; /* Write speed factor */ + uint8_t MaxWrBlockLen : 4; /* Max. write data block length */ + uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */ + uint8_t Reserved3 : 5; /* Reserved */ + uint8_t FileFormatGrouop : 1; /* File format group */ + uint8_t CopyFlag : 1; /* Copy flag (OTP) */ + uint8_t PermWrProtect : 1; /* Permanent write protection */ + uint8_t TempWrProtect : 1; /* Temporary write protection */ + uint8_t FileFormat : 2; /* File Format */ + uint8_t Reserved4 : 2; /* Reserved */ + uint8_t crc : 7; /* Reserved */ + uint8_t Reserved5 : 1; /* always 1*/ + +} SD_CSD; + +/** + * @brief Card Identification Data: CID Register + */ +typedef struct { + uint8_t ManufacturerID; /* ManufacturerID */ + char OEM_AppliID[2]; /* OEM/Application ID */ + char ProdName[5]; /* Product Name */ + uint8_t ProdRev; /* Product Revision */ + uint32_t ProdSN; /* Product Serial Number */ + uint8_t Reserved1; /* Reserved1 */ + uint8_t ManufactYear; /* Manufacturing Year */ + uint8_t ManufactMonth; /* Manufacturing Month */ + uint8_t CID_CRC; /* CID CRC */ + uint8_t Reserved2; /* always 1 */ +} SD_CID; + +/** + * @brief SD Card information structure + */ +typedef struct { + SD_CSD Csd; + SD_CID Cid; + uint64_t CardCapacity; /*!< Card Capacity */ + uint32_t CardBlockSize; /*!< Card Block Size */ + uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ + uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ +} SD_CardInfo; + +/** + * @brief SD card max mount retry count + * + * @return uint8_t + */ +uint8_t sd_max_mount_retry_count(); + +/** + * @brief Init sd card + * + * @param power_reset reset card power + * @return SdSpiStatus + */ +SdSpiStatus sd_init(bool power_reset); + +/** + * @brief Get card state + * + * @return SdSpiStatus + */ +SdSpiStatus sd_get_card_state(void); + +/** + * @brief Get card info + * + * @param card_info + * @return SdSpiStatus + */ +SdSpiStatus sd_get_card_info(SD_CardInfo* card_info); + +/** + * @brief Read blocks + * + * @param data + * @param address + * @param blocks + * @param timeout_ms + * @return SdSpiStatus + */ +SdSpiStatus sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms); + +/** + * @brief Write blocks + * + * @param data + * @param address + * @param blocks + * @param timeout_ms + * @return SdSpiStatus + */ +SdSpiStatus + sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms); + +/** + * @brief Get card CSD register + * + * @param Cid + * @return SdSpiStatus + */ +SdSpiStatus sd_get_cid(SD_CID* cid); \ No newline at end of file diff --git a/firmware/targets/f7/fatfs/sector_cache.c b/firmware/targets/f7/fatfs/sector_cache.c index d23c1d5ad..efb520ec8 100644 --- a/firmware/targets/f7/fatfs/sector_cache.c +++ b/firmware/targets/f7/fatfs/sector_cache.c @@ -8,7 +8,6 @@ #define SECTOR_SIZE 512 #define N_SECTORS 8 -#define TAG "SDCache" typedef struct { uint32_t itr; @@ -20,15 +19,11 @@ static SectorCache* cache = NULL; void sector_cache_init() { if(cache == NULL) { - // TODO: tuneup allocation order, to place cache in mem pool (MEM2) cache = memmgr_alloc_from_pool(sizeof(SectorCache)); } if(cache != NULL) { - FURI_LOG_I(TAG, "Init"); memset(cache, 0, sizeof(SectorCache)); - } else { - FURI_LOG_E(TAG, "Init failed"); } } diff --git a/firmware/targets/f7/fatfs/spi_sd_hal.c b/firmware/targets/f7/fatfs/spi_sd_hal.c deleted file mode 100644 index bfe046b58..000000000 --- a/firmware/targets/f7/fatfs/spi_sd_hal.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include - -#define SD_DUMMY_BYTE 0xFF - -const uint32_t SpiTimeout = 1000; -uint8_t SD_IO_WriteByte(uint8_t Data); - -/****************************************************************************** - BUS OPERATIONS - *******************************************************************************/ - -/** - * @brief SPI Write byte(s) to device - * @param DataIn: Pointer to data buffer to write - * @param DataOut: Pointer to data buffer for read data - * @param DataLength: number of bytes to write - * @retval None - */ -static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { - furi_check(furi_hal_spi_bus_trx( - furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); -} - -/** - * @brief SPI Write a byte to device - * @param Value: value to be written - * @retval None - */ -__attribute__((unused)) static void SPIx_Write(uint8_t Value) { - furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout)); -} - -/****************************************************************************** - LINK OPERATIONS - *******************************************************************************/ - -/********************************* LINK SD ************************************/ -/** - * @brief Initialize the SD Card and put it into StandBy State (Ready for - * data transfer). - * @retval None - */ -void SD_IO_Init(void) { - uint8_t counter = 0; - - /* SD chip select high */ - furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true); - furi_delay_us(10); - - /* Send dummy byte 0xFF, 10 times with CS high */ - /* Rise CS and MOSI for 80 clocks cycles */ - for(counter = 0; counter <= 200; counter++) { - /* Send dummy byte 0xFF */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - } -} - -/** - * @brief Set SD interface Chip Select state - * @param val: 0 (low) or 1 (high) state - * @retval None - */ -void SD_IO_CSState(uint8_t val) { - /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */ - if(val == 1) { - furi_delay_us(10); // Exit guard time for some SD cards - furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true); - } else { - furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false); - furi_delay_us(10); // Entry guard time for some SD cards - } -} - -/** - * @brief Write byte(s) on the SD - * @param DataIn: Pointer to data buffer to write - * @param DataOut: Pointer to data buffer for read data - * @param DataLength: number of bytes to write - * @retval None - */ -void SD_IO_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { - /* Send the byte */ - SPIx_WriteReadData(DataIn, DataOut, DataLength); -} - -/** - * @brief Write a byte on the SD. - * @param Data: byte to send. - * @retval Data written - */ -uint8_t SD_IO_WriteByte(uint8_t Data) { - uint8_t tmp; - - /* Send the byte */ - SPIx_WriteReadData(&Data, &tmp, 1); - return tmp; -} diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c deleted file mode 100644 index 998adee29..000000000 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c +++ /dev/null @@ -1,1113 +0,0 @@ -/** - ****************************************************************************** - * @file stm32_adafruit_sd.c - * @author MCD Application Team - * @version V3.0.0 - * @date 23-December-2016 - * @brief This file provides a set of functions needed to manage the SD card - * mounted on the Adafruit 1.8" TFT LCD shield (reference ID 802), - * that is used with the STM32 Nucleo board through SPI interface. - * It implements a high level communication layer for read and write - * from/to this memory. The needed STM32XXxx hardware resources (SPI and - * GPIO) are defined in stm32XXxx_nucleo.h file, and the initialization is - * performed in SD_IO_Init() function declared in stm32XXxx_nucleo.c - * file. - * You can easily tailor this driver to any other development board, - * by just adapting the defines for hardware resources and - * SD_IO_Init() function. - * - * +-------------------------------------------------------+ - * | Pin assignment | - * +-------------------------+---------------+-------------+ - * | STM32XXxx SPI Pins | SD | Pin | - * +-------------------------+---------------+-------------+ - * | SD_SPI_CS_PIN | ChipSelect | 1 | - * | SD_SPI_MOSI_PIN / MOSI | DataIn | 2 | - * | | GND | 3 (0 V) | - * | | VDD | 4 (3.3 V)| - * | SD_SPI_SCK_PIN / SCLK | Clock | 5 | - * | | GND | 6 (0 V) | - * | SD_SPI_MISO_PIN / MISO | DataOut | 7 | - * +-------------------------+---------------+-------------+ - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* File Info : ----------------------------------------------------------------- - User NOTES -1. How to use this driver: --------------------------- - - This driver does not need a specific component driver for the micro SD device - to be included with. - -2. Driver description: ---------------------- - + Initialization steps: - o Initialize the micro SD card using the BSP_SD_Init() function. - o Checking the SD card presence is not managed because SD detection pin is - not physically mapped on the Adafruit shield. - o The function BSP_SD_GetCardInfo() is used to get the micro SD card information - which is stored in the structure "SD_CardInfo". - - + Micro SD card operations - o The micro SD card can be accessed with read/write block(s) operations once - it is ready for access. The access can be performed in polling - mode by calling the functions BSP_SD_ReadBlocks()/BSP_SD_WriteBlocks() - - o The SD erase block(s) is performed using the function BSP_SD_Erase() with - specifying the number of blocks to erase. - o The SD runtime status is returned when calling the function BSP_SD_GetStatus(). - -------------------------------------------------------------------------------*/ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32_adafruit_sd.h" -#include "stdlib.h" -#include "string.h" -#include "stdio.h" -#include -#include "sector_cache.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup STM32_ADAFRUIT - * @{ - */ - -/** @defgroup STM32_ADAFRUIT_SD - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ - -/** @defgroup STM32_ADAFRUIT_SD_Private_Types_Definitions - * @{ - */ -typedef struct { - uint8_t r1; - uint8_t r2; - uint8_t r3; - uint8_t r4; - uint8_t r5; -} SD_CmdAnswer_typedef; - -/** - * @} - */ - -/* Private define ------------------------------------------------------------*/ - -/** @defgroup STM32_ADAFRUIT_SD_Private_Defines - * @{ - */ -#define SD_DUMMY_BYTE 0xFF - -#define SD_MAX_FRAME_LENGTH 17 /* Lenght = 16 + 1 */ -#define SD_CMD_LENGTH 6 - -#define SD_MAX_TRY 100 /* Number of try */ - -#define SD_CSD_STRUCT_V1 0x2 /* CSD struct version V1 */ -#define SD_CSD_STRUCT_V2 0x1 /* CSD struct version V2 */ - -/** - * @brief SD ansewer format - */ -typedef enum { - SD_ANSWER_R1_EXPECTED, - SD_ANSWER_R1B_EXPECTED, - SD_ANSWER_R2_EXPECTED, - SD_ANSWER_R3_EXPECTED, - SD_ANSWER_R4R5_EXPECTED, - SD_ANSWER_R7_EXPECTED, -} SD_Answer_type; - -/** - * @brief Start Data tokens: - * Tokens (necessary because at nop/idle (and CS active) only 0xff is - * on the data/command line) - */ -#define SD_TOKEN_START_DATA_SINGLE_BLOCK_READ \ - 0xFE /* Data token start byte, Start Single Block Read */ -#define SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ \ - 0xFE /* Data token start byte, Start Multiple Block Read */ -#define SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE \ - 0xFE /* Data token start byte, Start Single Block Write */ -#define SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE \ - 0xFD /* Data token start byte, Start Multiple Block Write */ -#define SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE \ - 0xFD /* Data toke stop byte, Stop Multiple Block Write */ - -/** - * @brief Commands: CMDxx = CMD-number | 0x40 - */ -#define SD_CMD_GO_IDLE_STATE 0 /* CMD0 = 0x40 */ -#define SD_CMD_SEND_OP_COND 1 /* CMD1 = 0x41 */ -#define SD_CMD_SEND_IF_COND 8 /* CMD8 = 0x48 */ -#define SD_CMD_SEND_CSD 9 /* CMD9 = 0x49 */ -#define SD_CMD_SEND_CID 10 /* CMD10 = 0x4A */ -#define SD_CMD_STOP_TRANSMISSION 12 /* CMD12 = 0x4C */ -#define SD_CMD_SEND_STATUS 13 /* CMD13 = 0x4D */ -#define SD_CMD_SET_BLOCKLEN 16 /* CMD16 = 0x50 */ -#define SD_CMD_READ_SINGLE_BLOCK 17 /* CMD17 = 0x51 */ -#define SD_CMD_READ_MULT_BLOCK 18 /* CMD18 = 0x52 */ -#define SD_CMD_SET_BLOCK_COUNT 23 /* CMD23 = 0x57 */ -#define SD_CMD_WRITE_SINGLE_BLOCK 24 /* CMD24 = 0x58 */ -#define SD_CMD_WRITE_MULT_BLOCK 25 /* CMD25 = 0x59 */ -#define SD_CMD_PROG_CSD 27 /* CMD27 = 0x5B */ -#define SD_CMD_SET_WRITE_PROT 28 /* CMD28 = 0x5C */ -#define SD_CMD_CLR_WRITE_PROT 29 /* CMD29 = 0x5D */ -#define SD_CMD_SEND_WRITE_PROT 30 /* CMD30 = 0x5E */ -#define SD_CMD_SD_ERASE_GRP_START 32 /* CMD32 = 0x60 */ -#define SD_CMD_SD_ERASE_GRP_END 33 /* CMD33 = 0x61 */ -#define SD_CMD_UNTAG_SECTOR 34 /* CMD34 = 0x62 */ -#define SD_CMD_ERASE_GRP_START 35 /* CMD35 = 0x63 */ -#define SD_CMD_ERASE_GRP_END 36 /* CMD36 = 0x64 */ -#define SD_CMD_UNTAG_ERASE_GROUP 37 /* CMD37 = 0x65 */ -#define SD_CMD_ERASE 38 /* CMD38 = 0x66 */ -#define SD_CMD_SD_APP_OP_COND 41 /* CMD41 = 0x69 */ -#define SD_CMD_APP_CMD 55 /* CMD55 = 0x77 */ -#define SD_CMD_READ_OCR 58 /* CMD55 = 0x79 */ - -/** - * @brief SD reponses and error flags - */ -typedef enum { - /* R1 answer value */ - SD_R1_NO_ERROR = (0x00), - SD_R1_IN_IDLE_STATE = (0x01), - SD_R1_ERASE_RESET = (0x02), - SD_R1_ILLEGAL_COMMAND = (0x04), - SD_R1_COM_CRC_ERROR = (0x08), - SD_R1_ERASE_SEQUENCE_ERROR = (0x10), - SD_R1_ADDRESS_ERROR = (0x20), - SD_R1_PARAMETER_ERROR = (0x40), - - /* R2 answer value */ - SD_R2_NO_ERROR = 0x00, - SD_R2_CARD_LOCKED = 0x01, - SD_R2_LOCKUNLOCK_ERROR = 0x02, - SD_R2_ERROR = 0x04, - SD_R2_CC_ERROR = 0x08, - SD_R2_CARD_ECC_FAILED = 0x10, - SD_R2_WP_VIOLATION = 0x20, - SD_R2_ERASE_PARAM = 0x40, - SD_R2_OUTOFRANGE = 0x80, - - /** - * @brief Data response error - */ - SD_DATA_OK = (0x05), - SD_DATA_CRC_ERROR = (0x0B), - SD_DATA_WRITE_ERROR = (0x0D), - SD_DATA_OTHER_ERROR = (0xFF) -} SD_Error; - -/** - * @} - */ - -/* Private macro -------------------------------------------------------------*/ - -/** @defgroup STM32_ADAFRUIT_SD_Private_Macros - * @{ - */ - -/** - * @} - */ - -/* Private variables ---------------------------------------------------------*/ - -/** @defgroup STM32_ADAFRUIT_SD_Private_Variables - * @{ - */ -__IO uint8_t SdStatus = SD_NOT_PRESENT; - -/* flag_SDHC : - 0 : Standard capacity - 1 : High capacity -*/ -uint16_t flag_SDHC = 0; - -/** - * @} - */ - -/* Private function prototypes -----------------------------------------------*/ -static uint8_t SD_GetCIDRegister(SD_CID* Cid); -static uint8_t SD_GetCSDRegister(SD_CSD* Csd); -static uint8_t SD_GetDataResponse(void); -static uint8_t SD_GoIdleState(void); -static SD_CmdAnswer_typedef SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Answer); -static uint8_t SD_WaitData(uint8_t data); -static uint8_t SD_ReadData(void); -/** @defgroup STM32_ADAFRUIT_SD_Private_Function_Prototypes - * @{ - */ -/** - * @} - */ - -/* Private functions ---------------------------------------------------------*/ - -void SD_SPI_Bus_To_Down_State() { - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->miso, - GpioModeOutputPushPull, - GpioPullNo, - GpioSpeedVeryHigh, - GpioAltFnUnused); - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->mosi, - GpioModeOutputPushPull, - GpioPullNo, - GpioSpeedVeryHigh, - GpioAltFnUnused); - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->sck, - GpioModeOutputPushPull, - GpioPullNo, - GpioSpeedVeryHigh, - GpioAltFnUnused); - - furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false); - furi_hal_gpio_write(furi_hal_sd_spi_handle->miso, false); - furi_hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); - furi_hal_gpio_write(furi_hal_sd_spi_handle->sck, false); -} - -void SD_SPI_Bus_To_Normal_State() { - furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true); - - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->miso, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn5SPI2); - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->mosi, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn5SPI2); - furi_hal_gpio_init_ex( - furi_hal_sd_spi_handle->sck, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn5SPI2); -} - -/** @defgroup STM32_ADAFRUIT_SD_Private_Functions - * @{ - */ - -uint8_t BSP_SD_MaxMountRetryCount() { - return 10; -} - -/** - * @brief Initializes the SD/SD communication. - * @param None - * @retval The SD Response: - * - MSD_ERROR: Sequence failed - * - MSD_OK: Sequence succeed - */ -uint8_t BSP_SD_Init(bool reset_card) { - /* Slow speed init */ - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); - furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; - - /* We must reset card in spi_lock context */ - if(reset_card) { - /* disable power and set low on all bus pins */ - furi_hal_power_disable_external_3_3v(); - SD_SPI_Bus_To_Down_State(); - hal_sd_detect_set_low(); - furi_delay_ms(250); - - /* reinit bus and enable power */ - SD_SPI_Bus_To_Normal_State(); - hal_sd_detect_init(); - furi_hal_power_enable_external_3_3v(); - furi_delay_ms(100); - } - - /* Configure IO functionalities for SD pin */ - SD_IO_Init(); - - /* SD detection pin is not physically mapped on the Adafruit shield */ - SdStatus = SD_PRESENT; - uint8_t res = BSP_SD_ERROR; - - for(uint8_t i = 0; i < 128; i++) { - res = SD_GoIdleState(); - if(res == BSP_SD_OK) break; - } - - furi_hal_sd_spi_handle = NULL; - furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); - - sector_cache_init(); - - /* SD initialized and set to SPI mode properly */ - return res; -} - -/** - * @brief Returns information about specific card. - * @param pCardInfo: Pointer to a SD_CardInfo structure that contains all SD - * card information. - * @retval The SD Response: - * - MSD_ERROR: Sequence failed - * - MSD_OK: Sequence succeed - */ -uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo) { - uint8_t status; - - status = SD_GetCSDRegister(&(pCardInfo->Csd)); - status |= SD_GetCIDRegister(&(pCardInfo->Cid)); - if(flag_SDHC == 1) { - pCardInfo->LogBlockSize = 512; - pCardInfo->CardBlockSize = 512; - pCardInfo->CardCapacity = ((uint64_t)pCardInfo->Csd.version.v2.DeviceSize + 1UL) * 1024UL * - (uint64_t)pCardInfo->LogBlockSize; - pCardInfo->LogBlockNbr = (pCardInfo->CardCapacity) / (pCardInfo->LogBlockSize); - } else { - pCardInfo->CardCapacity = (pCardInfo->Csd.version.v1.DeviceSize + 1); - pCardInfo->CardCapacity *= (1UL << (pCardInfo->Csd.version.v1.DeviceSizeMul + 2)); - pCardInfo->LogBlockSize = 512; - pCardInfo->CardBlockSize = 1UL << (pCardInfo->Csd.RdBlockLen); - pCardInfo->CardCapacity *= pCardInfo->CardBlockSize; - pCardInfo->LogBlockNbr = (pCardInfo->CardCapacity) / (pCardInfo->LogBlockSize); - } - - return status; -} - -/** - * @brief Reads block(s) from a specified address in the SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read. The address is counted - * in blocks of 512bytes - * @param NumOfBlocks: Number of SD blocks to read - * @param Timeout: This parameter is used for compatibility with BSP implementation - * @retval SD status - */ -uint8_t - BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { - UNUSED(Timeout); // FIXME! - uint32_t offset = 0; - uint32_t addr; - uint8_t retr = BSP_SD_ERROR; - SD_CmdAnswer_typedef response; - uint16_t BlockSize = 512; - uint8_t* cached_data; - - bool single_sector_read = (NumOfBlocks == 1); - if(single_sector_read && (cached_data = sector_cache_get(ReadAddr))) { - memcpy(pData, cached_data, BlockSize); - return BSP_SD_OK; - } - - /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and - Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 != SD_R1_NO_ERROR) { - goto error; - } - - /* Initialize the address */ - addr = (ReadAddr * ((flag_SDHC == 1) ? 1 : BlockSize)); - - /* Data transfer */ - while(NumOfBlocks--) { - /* Send CMD17 (SD_CMD_READ_SINGLE_BLOCK) to read one block */ - /* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, addr, 0xFF, SD_ANSWER_R1_EXPECTED); - if(response.r1 != SD_R1_NO_ERROR) { - goto error; - } - - /* Now look for the data token to signify the start of the data */ - if(SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) { - /* Read the SD block data : read NumByteToRead data */ - SD_IO_WriteReadData(NULL, (uint8_t*)pData + offset, BlockSize); - - /* Set next read address*/ - offset += BlockSize; - addr = ((flag_SDHC == 1) ? (addr + 1) : (addr + BlockSize)); - - /* get CRC bytes (not really needed by us, but required by SD) */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); - } else { - goto error; - } - - /* End the command data read cycle */ - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - } - - if(single_sector_read) { - sector_cache_put(ReadAddr, (uint8_t*)pData); - } - - retr = BSP_SD_OK; - -error: - /* Send dummy byte: 8 Clock pulses of delay */ - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Return the reponse */ - return retr; -} - -/** - * @brief Writes block(s) to a specified address in the SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written. The address is counted - * in blocks of 512bytes - * @param NumOfBlocks: Number of SD blocks to write - * @param Timeout: This parameter is used for compatibility with BSP implementation - * @retval SD status - */ -uint8_t BSP_SD_WriteBlocks( - uint32_t* pData, - uint32_t WriteAddr, - uint32_t NumOfBlocks, - uint32_t Timeout) { - UNUSED(Timeout); // FIXME! - uint32_t offset = 0; - uint32_t addr; - uint8_t retr = BSP_SD_ERROR; - SD_CmdAnswer_typedef response; - uint16_t BlockSize = 512; - sector_cache_invalidate_range(WriteAddr, WriteAddr + NumOfBlocks); - - /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and - Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 != SD_R1_NO_ERROR) { - goto error; - } - - /* Initialize the address */ - addr = (WriteAddr * ((flag_SDHC == 1) ? 1 : BlockSize)); - - /* Data transfer */ - while(NumOfBlocks--) { - /* Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write blocks and - Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, addr, 0xFF, SD_ANSWER_R1_EXPECTED); - if(response.r1 != SD_R1_NO_ERROR) { - goto error; - } - - /* Send dummy byte for NWR timing : one byte between CMDWRITE and TOKEN */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Send the data token to signify the start of the data */ - SD_IO_WriteByte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE); - - /* Write the block data to SD */ - SD_IO_WriteReadData((uint8_t*)pData + offset, NULL, BlockSize); - - /* Set next write address */ - offset += BlockSize; - addr = ((flag_SDHC == 1) ? (addr + 1) : (addr + BlockSize)); - - /* Put CRC bytes (not really needed by us, but required by SD) */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Read data response */ - if(SD_GetDataResponse() != SD_DATA_OK) { - /* Set response value to failure */ - goto error; - } - - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - } - retr = BSP_SD_OK; - -error: - - /* Send dummy byte: 8 Clock pulses of delay */ - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Return the reponse */ - return retr; -} - -/** - * @brief Erases the specified memory area of the given SD card. - * @param StartAddr: Start address in Blocks (Size of a block is 512bytes) - * @param EndAddr: End address in Blocks (Size of a block is 512bytes) - * @retval SD status - */ -uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr) { - uint8_t retr = BSP_SD_ERROR; - SD_CmdAnswer_typedef response; - uint16_t BlockSize = 512; - - /* Send CMD32 (Erase group start) and check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ - response = SD_SendCmd( - SD_CMD_SD_ERASE_GRP_START, - (StartAddr) * (flag_SDHC == 1 ? 1 : BlockSize), - 0xFF, - SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 == SD_R1_NO_ERROR) { - /* Send CMD33 (Erase group end) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ - response = SD_SendCmd( - SD_CMD_SD_ERASE_GRP_END, - (EndAddr * 512) * (flag_SDHC == 1 ? 1 : BlockSize), - 0xFF, - SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 == SD_R1_NO_ERROR) { - /* Send CMD38 (Erase) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_ERASE, 0, 0xFF, SD_ANSWER_R1B_EXPECTED); - if(response.r1 == SD_R1_NO_ERROR) { - retr = BSP_SD_OK; - } - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - } - } - - /* Return the reponse */ - return retr; -} - -/** - * @brief Returns the SD status. - * @param None - * @retval The SD status. - */ -uint8_t BSP_SD_GetCardState(void) { - SD_CmdAnswer_typedef retr; - - /* Send CMD13 (SD_SEND_STATUS) to get SD status */ - retr = SD_SendCmd(SD_CMD_SEND_STATUS, 0, 0xFF, SD_ANSWER_R2_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Find SD status according to card state */ - if((retr.r1 == SD_R1_NO_ERROR) && (retr.r2 == SD_R2_NO_ERROR)) { - return BSP_SD_OK; - } - - return BSP_SD_ERROR; -} - -/** - * @brief Reads the SD card SCD register. - * Reading the contents of the CSD register in SPI mode is a simple - * read-block transaction. - * @param Csd: pointer on an SCD register structure - * @retval SD status - */ -uint8_t SD_GetCSDRegister(SD_CSD* Csd) { - uint16_t counter = 0; - uint8_t CSD_Tab[16]; - uint8_t retr = BSP_SD_ERROR; - SD_CmdAnswer_typedef response; - - /* Send CMD9 (CSD register) or CMD10(CSD register) and Wait for response in the R1 format (0x00 is no errors) */ - response = SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); - if(response.r1 == SD_R1_NO_ERROR) { - if(SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) { - for(counter = 0; counter < 16; counter++) { - /* Store CSD register value on CSD_Tab */ - CSD_Tab[counter] = SD_IO_WriteByte(SD_DUMMY_BYTE); - } - - /* Get CRC bytes (not really needed by us, but required by SD) */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /************************************************************************* - CSD header decoding - *************************************************************************/ - - /* Byte 0 */ - Csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; - Csd->Reserved1 = CSD_Tab[0] & 0x3F; - - /* Byte 1 */ - Csd->TAAC = CSD_Tab[1]; - - /* Byte 2 */ - Csd->NSAC = CSD_Tab[2]; - - /* Byte 3 */ - Csd->MaxBusClkFrec = CSD_Tab[3]; - - /* Byte 4/5 */ - Csd->CardComdClasses = (CSD_Tab[4] << 4) | ((CSD_Tab[5] & 0xF0) >> 4); - Csd->RdBlockLen = CSD_Tab[5] & 0x0F; - - /* Byte 6 */ - Csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; - Csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; - Csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; - Csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4; - - /************************************************************************* - CSD v1/v2 decoding - *************************************************************************/ - - if(flag_SDHC == 0) { - Csd->version.v1.Reserved1 = ((CSD_Tab[6] & 0x0C) >> 2); - - Csd->version.v1.DeviceSize = ((CSD_Tab[6] & 0x03) << 10) | (CSD_Tab[7] << 2) | - ((CSD_Tab[8] & 0xC0) >> 6); - Csd->version.v1.MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; - Csd->version.v1.MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); - Csd->version.v1.MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; - Csd->version.v1.MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; - Csd->version.v1.DeviceSizeMul = ((CSD_Tab[9] & 0x03) << 1) | - ((CSD_Tab[10] & 0x80) >> 7); - } else { - Csd->version.v2.Reserved1 = ((CSD_Tab[6] & 0x0F) << 2) | - ((CSD_Tab[7] & 0xC0) >> 6); - Csd->version.v2.DeviceSize = ((CSD_Tab[7] & 0x3F) << 16) | (CSD_Tab[8] << 8) | - CSD_Tab[9]; - Csd->version.v2.Reserved2 = ((CSD_Tab[10] & 0x80) >> 8); - } - - Csd->EraseSingleBlockEnable = (CSD_Tab[10] & 0x40) >> 6; - Csd->EraseSectorSize = ((CSD_Tab[10] & 0x3F) << 1) | ((CSD_Tab[11] & 0x80) >> 7); - Csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F); - Csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; - Csd->Reserved2 = (CSD_Tab[12] & 0x60) >> 5; - Csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; - Csd->MaxWrBlockLen = ((CSD_Tab[12] & 0x03) << 2) | ((CSD_Tab[13] & 0xC0) >> 6); - Csd->WriteBlockPartial = (CSD_Tab[13] & 0x20) >> 5; - Csd->Reserved3 = (CSD_Tab[13] & 0x1F); - Csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; - Csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6; - Csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; - Csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; - Csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2; - Csd->Reserved4 = (CSD_Tab[14] & 0x03); - Csd->crc = (CSD_Tab[15] & 0xFE) >> 1; - Csd->Reserved5 = (CSD_Tab[15] & 0x01); - - retr = BSP_SD_OK; - } - } - - /* Send dummy byte: 8 Clock pulses of delay */ - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Return the reponse */ - return retr; -} - -/** - * @brief Reads the SD card CID register. - * Reading the contents of the CID register in SPI mode is a simple - * read-block transaction. - * @param Cid: pointer on an CID register structure - * @retval SD status - */ -uint8_t SD_GetCIDRegister(SD_CID* Cid) { - uint32_t counter = 0; - uint8_t retr = BSP_SD_ERROR; - uint8_t CID_Tab[16]; - SD_CmdAnswer_typedef response; - - /* Send CMD10 (CID register) and Wait for response in the R1 format (0x00 is no errors) */ - response = SD_SendCmd(SD_CMD_SEND_CID, 0, 0xFF, SD_ANSWER_R1_EXPECTED); - if(response.r1 == SD_R1_NO_ERROR) { - if(SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) { - /* Store CID register value on CID_Tab */ - for(counter = 0; counter < 16; counter++) { - CID_Tab[counter] = SD_IO_WriteByte(SD_DUMMY_BYTE); - } - - /* Get CRC bytes (not really needed by us, but required by SD) */ - SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Byte 0 */ - Cid->ManufacturerID = CID_Tab[0]; - - /* Byte 1 */ - memcpy(Cid->OEM_AppliID, CID_Tab + 1, 2); - - /* Byte 3 */ - memcpy(Cid->ProdName, CID_Tab + 3, 5); - - /* Byte 8 */ - Cid->ProdRev = CID_Tab[8]; - - /* Byte 9 */ - Cid->ProdSN = CID_Tab[9] << 24; - - /* Byte 10 */ - Cid->ProdSN |= CID_Tab[10] << 16; - - /* Byte 11 */ - Cid->ProdSN |= CID_Tab[11] << 8; - - /* Byte 12 */ - Cid->ProdSN |= CID_Tab[12]; - - /* Byte 13 */ - Cid->Reserved1 = (CID_Tab[13] & 0xF0) >> 4; - Cid->ManufactYear = (CID_Tab[13] & 0x0F) << 4; - - /* Byte 14 */ - Cid->ManufactYear |= (CID_Tab[14] & 0xF0) >> 4; - Cid->ManufactMonth = (CID_Tab[14] & 0x0F); - - /* Byte 15 */ - Cid->CID_CRC = (CID_Tab[15] & 0xFE) >> 1; - Cid->Reserved2 = 1; - - retr = BSP_SD_OK; - } - } - - /* Send dummy byte: 8 Clock pulses of delay */ - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Return the reponse */ - return retr; -} - -uint8_t BSP_SD_GetCIDRegister(SD_CID* Cid) { - uint8_t retr = BSP_SD_ERROR; - - /* Slow speed init */ - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); - furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; - - memset(Cid, 0, sizeof(SD_CID)); - retr = SD_GetCIDRegister(Cid); - - furi_hal_sd_spi_handle = NULL; - furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); - return retr; -} - -/** - * @brief Sends 5 bytes command to the SD card and get response - * @param Cmd: The user expected command to send to SD card. - * @param Arg: The command argument. - * @param Crc: The CRC. - * @param Answer: SD_ANSWER_NOT_EXPECTED or SD_ANSWER_EXPECTED - * @retval SD status - */ -SD_CmdAnswer_typedef SD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Answer) { - uint8_t frame[SD_CMD_LENGTH], frameout[SD_CMD_LENGTH]; - SD_CmdAnswer_typedef retr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - /* R1 Lenght = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 1 Bytes answer + NEC(0) = 15bytes */ - /* R1b identical to R1 + Busy information */ - /* R2 Lenght = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 2 Bytes answer + NEC(0) = 16bytes */ - - /* Prepare Frame to send */ - frame[0] = (Cmd | 0x40); /* Construct byte 1 */ - frame[1] = (uint8_t)(Arg >> 24); /* Construct byte 2 */ - frame[2] = (uint8_t)(Arg >> 16); /* Construct byte 3 */ - frame[3] = (uint8_t)(Arg >> 8); /* Construct byte 4 */ - frame[4] = (uint8_t)(Arg); /* Construct byte 5 */ - frame[5] = (Crc | 0x01); /* Construct byte 6 */ - - /* Send the command */ - SD_IO_CSState(0); - SD_IO_WriteReadData(frame, frameout, SD_CMD_LENGTH); /* Send the Cmd bytes */ - - switch(Answer) { - case SD_ANSWER_R1_EXPECTED: - retr.r1 = SD_ReadData(); - break; - case SD_ANSWER_R1B_EXPECTED: - retr.r1 = SD_ReadData(); - retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); - /* Set CS High */ - SD_IO_CSState(1); - furi_delay_us(1000); - /* Set CS Low */ - SD_IO_CSState(0); - - /* Wait IO line return 0xFF */ - while(SD_IO_WriteByte(SD_DUMMY_BYTE) != 0xFF) - ; - break; - case SD_ANSWER_R2_EXPECTED: - retr.r1 = SD_ReadData(); - retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); - break; - case SD_ANSWER_R3_EXPECTED: - case SD_ANSWER_R7_EXPECTED: - retr.r1 = SD_ReadData(); - retr.r2 = SD_IO_WriteByte(SD_DUMMY_BYTE); - retr.r3 = SD_IO_WriteByte(SD_DUMMY_BYTE); - retr.r4 = SD_IO_WriteByte(SD_DUMMY_BYTE); - retr.r5 = SD_IO_WriteByte(SD_DUMMY_BYTE); - break; - default: - break; - } - return retr; -} - -/** - * @brief Gets the SD card data response and check the busy flag. - * @param None - * @retval The SD status: Read data response xxx01 - * - status 010: Data accecpted - * - status 101: Data rejected due to a crc error - * - status 110: Data rejected due to a Write error. - * - status 111: Data rejected due to other error. - */ -uint8_t SD_GetDataResponse(void) { - uint8_t dataresponse; - uint8_t rvalue = SD_DATA_OTHER_ERROR; - - dataresponse = SD_IO_WriteByte(SD_DUMMY_BYTE); - SD_IO_WriteByte(SD_DUMMY_BYTE); /* read the busy response byte*/ - - /* Mask unused bits */ - switch(dataresponse & 0x1F) { - case SD_DATA_OK: - rvalue = SD_DATA_OK; - - /* Set CS High */ - SD_IO_CSState(1); - /* Set CS Low */ - SD_IO_CSState(0); - - /* Wait IO line return 0xFF */ - while(SD_IO_WriteByte(SD_DUMMY_BYTE) != 0xFF) - ; - break; - case SD_DATA_CRC_ERROR: - rvalue = SD_DATA_CRC_ERROR; - break; - case SD_DATA_WRITE_ERROR: - rvalue = SD_DATA_WRITE_ERROR; - break; - default: - break; - } - - /* Return response */ - return rvalue; -} - -/** - * @brief Put the SD in Idle state. - * @param None - * @retval SD status - */ -uint8_t SD_GoIdleState(void) { - SD_CmdAnswer_typedef response; - __IO uint8_t counter; - /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and - wait for In Idle State Response (R1 Format) equal to 0x01 */ - counter = 0; - do { - counter++; - response = SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(counter >= SD_MAX_TRY) { - return BSP_SD_ERROR; - } - } while(response.r1 != SD_R1_IN_IDLE_STATE); - - /* Send CMD8 (SD_CMD_SEND_IF_COND) to check the power supply status - and wait until response (R7 Format) equal to 0xAA and */ - response = SD_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, 0x87, SD_ANSWER_R7_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { - /* initialise card V1 */ - counter = 0; - do { - counter++; - /* initialise card V1 */ - /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_APP_CMD, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ - response = //-V519 - SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(counter >= SD_MAX_TRY) { - return BSP_SD_ERROR; - } - } while(response.r1 == SD_R1_IN_IDLE_STATE); - flag_SDHC = 0; - } else if(response.r1 == SD_R1_IN_IDLE_STATE) { - /* initialise card V2 */ - counter = 0; - do { - counter++; - /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - - /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ - response = //-V519 - SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(counter >= SD_MAX_TRY) { - return BSP_SD_ERROR; - } - } while(response.r1 == SD_R1_IN_IDLE_STATE); - - if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { - counter = 0; - do { - counter++; - /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 != SD_R1_IN_IDLE_STATE) { - return BSP_SD_ERROR; - } - /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ - response = - SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(counter >= SD_MAX_TRY) { - return BSP_SD_ERROR; - } - } while(response.r1 == SD_R1_IN_IDLE_STATE); - } - - /* Send CMD58 (SD_CMD_READ_OCR) to initialize SDHC or SDXC cards: R3 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_READ_OCR, 0x00000000, 0xFF, SD_ANSWER_R3_EXPECTED); - SD_IO_CSState(1); - SD_IO_WriteByte(SD_DUMMY_BYTE); - if(response.r1 != SD_R1_NO_ERROR) { - return BSP_SD_ERROR; - } - flag_SDHC = (response.r2 & 0x40) >> 6; - } else { - return BSP_SD_ERROR; - } - - return BSP_SD_OK; -} - -/** - * @brief Waits a data until a value different from SD_DUMMY_BITE - * @param None - * @retval the value read - */ -uint8_t SD_ReadData(void) { - uint8_t timeout = 0x08; - uint8_t readvalue; - - /* Check if response is got or a timeout is happen */ - do { - readvalue = SD_IO_WriteByte(SD_DUMMY_BYTE); - timeout--; - - } while((readvalue == SD_DUMMY_BYTE) && timeout); - - /* Right response got */ - return readvalue; -} - -/** - * @brief Waits a data from the SD card - * @param data : Expected data from the SD card - * @retval BSP_SD_OK or BSP_SD_TIMEOUT - */ -uint8_t SD_WaitData(uint8_t data) { - uint16_t timeout = 0xFFFF; - uint8_t readvalue; - - /* Check if response is got or a timeout is happen */ - - do { - readvalue = SD_IO_WriteByte(SD_DUMMY_BYTE); - timeout--; - } while((readvalue != data) && timeout); - - if(timeout == 0) { - /* After time out */ - return BSP_SD_TIMEOUT; - } - - /* Right response got */ - return BSP_SD_OK; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.h b/firmware/targets/f7/fatfs/stm32_adafruit_sd.h deleted file mode 100644 index a133c5922..000000000 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.h +++ /dev/null @@ -1,245 +0,0 @@ -/** - ****************************************************************************** - * @file stm32_adafruit_sd.h - * @author MCD Application Team - * @version V3.0.0 - * @date 23-December-2016 - * @brief This file contains the common defines and functions prototypes for - * the stm32_adafruit_sd.c driver. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32_ADAFRUIT_SD_H -#define __STM32_ADAFRUIT_SD_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include -#include - -/** @addtogroup BSP - * @{ - */ -#define __IO volatile - -/** @addtogroup STM32_ADAFRUIT - * @{ - */ - -/** @defgroup STM32_ADAFRUIT_SD - * @{ - */ - -/** @defgroup STM32_ADAFRUIT_SD_Exported_Types - * @{ - */ - -/** - * @brief SD status structure definition - */ -enum { BSP_SD_OK = 0x00, MSD_OK = 0x00, BSP_SD_ERROR = 0x01, BSP_SD_TIMEOUT }; - -typedef struct { - uint8_t Reserved1 : 2; /* Reserved */ - uint16_t DeviceSize : 12; /* Device Size */ - uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */ - uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */ - uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */ - uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */ - uint8_t DeviceSizeMul : 3; /* Device size multiplier */ -} struct_v1; - -typedef struct { - uint8_t Reserved1 : 6; /* Reserved */ - uint32_t DeviceSize : 22; /* Device Size */ - uint8_t Reserved2 : 1; /* Reserved */ -} struct_v2; - -/** - * @brief Card Specific Data: CSD Register - */ -typedef struct { - /* Header part */ - uint8_t CSDStruct : 2; /* CSD structure */ - uint8_t Reserved1 : 6; /* Reserved */ - uint8_t TAAC : 8; /* Data read access-time 1 */ - uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */ - uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */ - uint16_t CardComdClasses : 12; /* Card command classes */ - uint8_t RdBlockLen : 4; /* Max. read data block length */ - uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */ - uint8_t WrBlockMisalign : 1; /* Write block misalignment */ - uint8_t RdBlockMisalign : 1; /* Read block misalignment */ - uint8_t DSRImpl : 1; /* DSR implemented */ - - /* v1 or v2 struct */ - union csd_version { - struct_v1 v1; - struct_v2 v2; - } version; - - uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */ - uint8_t EraseSectorSize : 7; /* Erase group size multiplier */ - uint8_t WrProtectGrSize : 7; /* Write protect group size */ - uint8_t WrProtectGrEnable : 1; /* Write protect group enable */ - uint8_t Reserved2 : 2; /* Reserved */ - uint8_t WrSpeedFact : 3; /* Write speed factor */ - uint8_t MaxWrBlockLen : 4; /* Max. write data block length */ - uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */ - uint8_t Reserved3 : 5; /* Reserved */ - uint8_t FileFormatGrouop : 1; /* File format group */ - uint8_t CopyFlag : 1; /* Copy flag (OTP) */ - uint8_t PermWrProtect : 1; /* Permanent write protection */ - uint8_t TempWrProtect : 1; /* Temporary write protection */ - uint8_t FileFormat : 2; /* File Format */ - uint8_t Reserved4 : 2; /* Reserved */ - uint8_t crc : 7; /* Reserved */ - uint8_t Reserved5 : 1; /* always 1*/ - -} SD_CSD; - -/** - * @brief Card Identification Data: CID Register - */ -typedef struct { - uint8_t ManufacturerID; /* ManufacturerID */ - char OEM_AppliID[2]; /* OEM/Application ID */ - char ProdName[5]; /* Product Name */ - uint8_t ProdRev; /* Product Revision */ - uint32_t ProdSN; /* Product Serial Number */ - uint8_t Reserved1; /* Reserved1 */ - uint8_t ManufactYear; /* Manufacturing Year */ - uint8_t ManufactMonth; /* Manufacturing Month */ - uint8_t CID_CRC; /* CID CRC */ - uint8_t Reserved2; /* always 1 */ -} SD_CID; - -/** - * @brief SD Card information - */ -typedef struct { - SD_CSD Csd; - SD_CID Cid; - uint64_t CardCapacity; /*!< Card Capacity */ - uint32_t CardBlockSize; /*!< Card Block Size */ - uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ - uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ -} SD_CardInfo; - -/** - * @} - */ - -/** @defgroup STM32_ADAFRUIT_SPI_SD_Exported_Constants - * @{ - */ - -/** - * @brief Block Size - */ -#define SD_BLOCK_SIZE 0x200 - -/** - * @brief SD detection on its memory slot - */ -#define SD_PRESENT ((uint8_t)0x01) -#define SD_NOT_PRESENT ((uint8_t)0x00) - -#define SD_DATATIMEOUT ((uint32_t)100000000) - -/** - * @brief SD Card information structure - */ -#define BSP_SD_CardInfo SD_CardInfo - -/** - * @} - */ - -/** @defgroup STM32_ADAFRUIT_SD_Exported_Macro - * @{ - */ - -/** - * @} - */ - -/** @defgroup STM32_ADAFRUIT_SD_Exported_Functions - * @{ - */ -uint8_t BSP_SD_MaxMountRetryCount(); -uint8_t BSP_SD_Init(bool reset_card); -uint8_t - BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); -uint8_t - BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); -uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr); -uint8_t BSP_SD_GetCardState(void); -uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo); -uint8_t BSP_SD_GetCIDRegister(SD_CID* Cid); - -/* Link functions for SD Card peripheral*/ -void SD_SPI_Slow_Init(void); -void SD_SPI_Fast_Init(void); -void SD_IO_Init(void); -void SD_IO_CSState(uint8_t state); -void SD_IO_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength); -uint8_t SD_IO_WriteByte(uint8_t Data); - -/* Link function for HAL delay */ -void HAL_Delay(__IO uint32_t Delay); - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32_ADAFRUIT_SD_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/fatfs/user_diskio.c b/firmware/targets/f7/fatfs/user_diskio.c index b504fcd51..16ac78e4d 100644 --- a/firmware/targets/f7/fatfs/user_diskio.c +++ b/firmware/targets/f7/fatfs/user_diskio.c @@ -46,7 +46,7 @@ static volatile DSTATUS Stat = STA_NOINIT; static DSTATUS User_CheckStatus(BYTE lun) { UNUSED(lun); Stat = STA_NOINIT; - if(BSP_SD_GetCardState() == MSD_OK) { + if(sd_get_card_state() == SdSpiStatusOK) { Stat &= ~STA_NOINIT; } @@ -128,11 +128,18 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; - if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { + if(sd_read_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000); + /* wait until the read operation is finished */ - while(BSP_SD_GetCardState() != MSD_OK) { - } res = RES_OK; + while(sd_get_card_state() != SdSpiStatusOK) { + if(furi_hal_cortex_timer_is_expired(timer)) { + res = RES_ERROR; + break; + } + } } furi_hal_sd_spi_handle = NULL; @@ -160,11 +167,18 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; - if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { + if(sd_write_blocks((uint32_t*)buff, (uint32_t)(sector), count, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000); + /* wait until the Write operation is finished */ - while(BSP_SD_GetCardState() != MSD_OK) { - } res = RES_OK; + while(sd_get_card_state() != SdSpiStatusOK) { + if(furi_hal_cortex_timer_is_expired(timer)) { + res = RES_ERROR; + break; + } + } } furi_hal_sd_spi_handle = NULL; @@ -187,7 +201,7 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { /* USER CODE BEGIN IOCTL */ UNUSED(pdrv); DRESULT res = RES_ERROR; - BSP_SD_CardInfo CardInfo; + SD_CardInfo CardInfo; if(Stat & STA_NOINIT) return RES_NOTRDY; @@ -202,21 +216,21 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { /* Get number of sectors on the disk (DWORD) */ case GET_SECTOR_COUNT: - BSP_SD_GetCardInfo(&CardInfo); + sd_get_card_info(&CardInfo); *(DWORD*)buff = CardInfo.LogBlockNbr; res = RES_OK; break; /* Get R/W sector size (WORD) */ case GET_SECTOR_SIZE: - BSP_SD_GetCardInfo(&CardInfo); + sd_get_card_info(&CardInfo); *(WORD*)buff = CardInfo.LogBlockSize; res = RES_OK; break; /* Get erase block size in unit of sector (DWORD) */ case GET_BLOCK_SIZE: - BSP_SD_GetCardInfo(&CardInfo); + sd_get_card_info(&CardInfo); *(DWORD*)buff = CardInfo.LogBlockSize; res = RES_OK; break; diff --git a/firmware/targets/f7/fatfs/user_diskio.h b/firmware/targets/f7/fatfs/user_diskio.h index 177723be1..12e0f27dc 100644 --- a/firmware/targets/f7/fatfs/user_diskio.h +++ b/firmware/targets/f7/fatfs/user_diskio.h @@ -30,7 +30,7 @@ extern "C" { /* USER CODE BEGIN 0 */ /* Includes ------------------------------------------------------------------*/ -#include "stm32_adafruit_sd.h" +#include "sd_spi_io.h" #include "fatfs/ff_gen_drv.h" /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ diff --git a/firmware/targets/f7/furi_hal/furi_hal.c b/firmware/targets/f7/furi_hal/furi_hal.c index 7f2f5759f..afe46c4ed 100644 --- a/firmware/targets/f7/furi_hal/furi_hal.c +++ b/firmware/targets/f7/furi_hal/furi_hal.c @@ -53,6 +53,7 @@ void furi_hal_init() { furi_hal_region_init(); furi_hal_spi_config_init(); + furi_hal_spi_dma_init(); furi_hal_ibutton_init(); FURI_LOG_I(TAG, "iButton OK"); diff --git a/firmware/targets/f7/furi_hal/furi_hal_infrared.c b/firmware/targets/f7/furi_hal/furi_hal_infrared.c index dea1112ab..c1d24f803 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_infrared.c +++ b/firmware/targets/f7/furi_hal/furi_hal_infrared.c @@ -28,6 +28,15 @@ const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GPIO_PIN_7}; #define INFRARED_TX_CCMR_LOW \ (TIM_CCMR2_OC3PE | LL_TIM_OCMODE_FORCED_INACTIVE) /* Space time - force low */ +/* DMA Channels definition */ +#define IR_DMA DMA2 +#define IR_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1 +#define IR_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2 +#define IR_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1 +#define IR_DMA_CH2_IRQ FuriHalInterruptIdDma2Ch2 +#define IR_DMA_CH1_DEF IR_DMA, IR_DMA_CH1_CHANNEL +#define IR_DMA_CH2_DEF IR_DMA, IR_DMA_CH2_CHANNEL + typedef struct { FuriHalInfraredRxCaptureCallback capture_callback; void* capture_context; @@ -213,15 +222,15 @@ void furi_hal_infrared_async_rx_set_timeout_isr_callback( } static void furi_hal_infrared_tx_dma_terminate(void) { - LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_2); - LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF); + LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF); + LL_DMA_DisableIT_TC(IR_DMA_CH2_DEF); furi_assert(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress); - LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF); + LL_DMA_DisableChannel(IR_DMA_CH2_DEF); + LL_DMA_DisableChannel(IR_DMA_CH1_DEF); LL_TIM_DisableCounter(TIM1); FuriStatus status = furi_semaphore_release(infrared_tim_tx.stop_semaphore); furi_check(status == FuriStatusOk); @@ -230,7 +239,7 @@ static void furi_hal_infrared_tx_dma_terminate(void) { static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) { uint8_t buf_num = 0; - uint32_t buffer_adr = LL_DMA_GetMemoryAddress(DMA1, LL_DMA_CHANNEL_2); + uint32_t buffer_adr = LL_DMA_GetMemoryAddress(IR_DMA_CH2_DEF); if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[0].data) { buf_num = 0; } else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) { @@ -242,12 +251,13 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) { } static void furi_hal_infrared_tx_dma_polarity_isr() { - if(LL_DMA_IsActiveFlag_TE1(DMA1)) { - LL_DMA_ClearFlag_TE1(DMA1); +#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 + if(LL_DMA_IsActiveFlag_TE1(IR_DMA)) { + LL_DMA_ClearFlag_TE1(IR_DMA); furi_crash(NULL); } - if(LL_DMA_IsActiveFlag_TC1(DMA1) && LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_1)) { - LL_DMA_ClearFlag_TC1(DMA1); + if(LL_DMA_IsActiveFlag_TC1(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH1_DEF)) { + LL_DMA_ClearFlag_TC1(IR_DMA); furi_check( (furi_hal_infrared_state == InfraredStateAsyncTx) || @@ -257,25 +267,29 @@ static void furi_hal_infrared_tx_dma_polarity_isr() { uint8_t next_buf_num = furi_hal_infrared_get_current_dma_tx_buffer(); furi_hal_infrared_tx_dma_set_polarity(next_buf_num, 0); } +#else +#error Update this code. Would you kindly? +#endif } static void furi_hal_infrared_tx_dma_isr() { - if(LL_DMA_IsActiveFlag_TE2(DMA1)) { - LL_DMA_ClearFlag_TE2(DMA1); +#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2 + if(LL_DMA_IsActiveFlag_TE2(IR_DMA)) { + LL_DMA_ClearFlag_TE2(IR_DMA); furi_crash(NULL); } - if(LL_DMA_IsActiveFlag_HT2(DMA1) && LL_DMA_IsEnabledIT_HT(DMA1, LL_DMA_CHANNEL_2)) { - LL_DMA_ClearFlag_HT2(DMA1); + if(LL_DMA_IsActiveFlag_HT2(IR_DMA) && LL_DMA_IsEnabledIT_HT(IR_DMA_CH2_DEF)) { + LL_DMA_ClearFlag_HT2(IR_DMA); uint8_t buf_num = furi_hal_infrared_get_current_dma_tx_buffer(); uint8_t next_buf_num = !buf_num; if(infrared_tim_tx.buffer[buf_num].last_packet_end) { - LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF); } else if( !infrared_tim_tx.buffer[buf_num].packet_end || (furi_hal_infrared_state == InfraredStateAsyncTx)) { furi_hal_infrared_tx_fill_buffer(next_buf_num, 0); if(infrared_tim_tx.buffer[next_buf_num].last_packet_end) { - LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF); } } else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) { /* fallthrough */ @@ -283,8 +297,8 @@ static void furi_hal_infrared_tx_dma_isr() { furi_crash(NULL); } } - if(LL_DMA_IsActiveFlag_TC2(DMA1) && LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_2)) { - LL_DMA_ClearFlag_TC2(DMA1); + if(LL_DMA_IsActiveFlag_TC2(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH2_DEF)) { + LL_DMA_ClearFlag_TC2(IR_DMA); furi_check( (furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress) || (furi_hal_infrared_state == InfraredStateAsyncTxStopReq) || @@ -310,6 +324,9 @@ static void furi_hal_infrared_tx_dma_isr() { infrared_tim_tx.signal_sent_callback(infrared_tim_tx.signal_sent_context); } } +#else +#error Update this code. Would you kindly? +#endif } static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) { @@ -369,16 +386,19 @@ static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) { dma_config.NbData = 0; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP; dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); + LL_DMA_Init(IR_DMA_CH1_DEF, &dma_config); - LL_DMA_ClearFlag_TE1(DMA1); - LL_DMA_ClearFlag_TC1(DMA1); +#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 + LL_DMA_ClearFlag_TE1(IR_DMA); + LL_DMA_ClearFlag_TC1(IR_DMA); +#else +#error Update this code. Would you kindly? +#endif - LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_EnableIT_TE(IR_DMA_CH1_DEF); + LL_DMA_EnableIT_TC(IR_DMA_CH1_DEF); - furi_hal_interrupt_set_isr_ex( - FuriHalInterruptIdDma1Ch1, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL); + furi_hal_interrupt_set_isr_ex(IR_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL); } static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) { @@ -394,18 +414,21 @@ static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) { dma_config.NbData = 0; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP; dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config); + LL_DMA_Init(IR_DMA_CH2_DEF, &dma_config); - LL_DMA_ClearFlag_TC2(DMA1); - LL_DMA_ClearFlag_HT2(DMA1); - LL_DMA_ClearFlag_TE2(DMA1); +#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2 + LL_DMA_ClearFlag_TC2(IR_DMA); + LL_DMA_ClearFlag_HT2(IR_DMA); + LL_DMA_ClearFlag_TE2(IR_DMA); +#else +#error Update this code. Would you kindly? +#endif - LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2); - LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_2); - LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_EnableIT_TC(IR_DMA_CH2_DEF); + LL_DMA_EnableIT_HT(IR_DMA_CH2_DEF); + LL_DMA_EnableIT_TE(IR_DMA_CH2_DEF); - furi_hal_interrupt_set_isr_ex( - FuriHalInterruptIdDma1Ch2, 5, furi_hal_infrared_tx_dma_isr, NULL); + furi_hal_interrupt_set_isr_ex(IR_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL); } static void furi_hal_infrared_tx_fill_buffer_last(uint8_t buf_num) { @@ -507,14 +530,14 @@ static void furi_hal_infrared_tx_dma_set_polarity(uint8_t buf_num, uint8_t polar furi_assert(buffer->polarity != NULL); FURI_CRITICAL_ENTER(); - bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1); + bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH1_DEF); if(channel_enabled) { - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableChannel(IR_DMA_CH1_DEF); } - LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)buffer->polarity); - LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, buffer->size + polarity_shift); + LL_DMA_SetMemoryAddress(IR_DMA_CH1_DEF, (uint32_t)buffer->polarity); + LL_DMA_SetDataLength(IR_DMA_CH1_DEF, buffer->size + polarity_shift); if(channel_enabled) { - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_EnableChannel(IR_DMA_CH1_DEF); } FURI_CRITICAL_EXIT(); } @@ -527,14 +550,14 @@ static void furi_hal_infrared_tx_dma_set_buffer(uint8_t buf_num) { /* non-circular mode requires disabled channel before setup */ FURI_CRITICAL_ENTER(); - bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_2); + bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH2_DEF); if(channel_enabled) { - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DisableChannel(IR_DMA_CH2_DEF); } - LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)buffer->data); - LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, buffer->size); + LL_DMA_SetMemoryAddress(IR_DMA_CH2_DEF, (uint32_t)buffer->data); + LL_DMA_SetDataLength(IR_DMA_CH2_DEF, buffer->size); if(channel_enabled) { - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_EnableChannel(IR_DMA_CH2_DEF); } FURI_CRITICAL_EXIT(); } @@ -545,8 +568,8 @@ static void furi_hal_infrared_async_tx_free_resources(void) { (furi_hal_infrared_state == InfraredStateAsyncTxStopped)); furi_hal_gpio_init(&gpio_infrared_tx, GpioModeOutputOpenDrain, GpioPullDown, GpioSpeedLow); - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch2, NULL, NULL); + furi_hal_interrupt_set_isr(IR_DMA_CH1_IRQ, NULL, NULL); + furi_hal_interrupt_set_isr(IR_DMA_CH2_IRQ, NULL, NULL); LL_TIM_DeInit(TIM1); furi_semaphore_free(infrared_tim_tx.stop_semaphore); @@ -597,8 +620,8 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { furi_hal_infrared_state = InfraredStateAsyncTx; LL_TIM_ClearFlag_UPDATE(TIM1); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_EnableChannel(IR_DMA_CH1_DEF); + LL_DMA_EnableChannel(IR_DMA_CH2_DEF); furi_delay_us(5); LL_TIM_GenerateEvent_UPDATE(TIM1); /* DMA -> TIMx_RCR */ furi_delay_us(5); diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/firmware/targets/f7/furi_hal/furi_hal_rfid.c index 0ade85e0a..b0238f79f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.c @@ -21,6 +21,14 @@ #define RFID_CAPTURE_IND_CH LL_TIM_CHANNEL_CH3 #define RFID_CAPTURE_DIR_CH LL_TIM_CHANNEL_CH4 +/* DMA Channels definition */ +#define RFID_DMA DMA2 +#define RFID_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1 +#define RFID_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2 +#define RFID_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1 +#define RFID_DMA_CH1_DEF RFID_DMA, RFID_DMA_CH1_CHANNEL +#define RFID_DMA_CH2_DEF RFID_DMA, RFID_DMA_CH2_CHANNEL + typedef struct { FuriHalRfidEmulateCallback callback; FuriHalRfidDMACallback dma_callback; @@ -302,15 +310,19 @@ void furi_hal_rfid_tim_read_capture_stop() { } static void furi_hal_rfid_dma_isr() { - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); +#if RFID_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 + if(LL_DMA_IsActiveFlag_HT1(RFID_DMA)) { + LL_DMA_ClearFlag_HT1(RFID_DMA); furi_hal_rfid->dma_callback(true, furi_hal_rfid->context); } - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); + if(LL_DMA_IsActiveFlag_TC1(RFID_DMA)) { + LL_DMA_ClearFlag_TC1(RFID_DMA); furi_hal_rfid->dma_callback(false, furi_hal_rfid->context); } +#else +#error Update this code. Would you kindly? +#endif } void furi_hal_rfid_tim_emulate_dma_start( @@ -347,8 +359,8 @@ void furi_hal_rfid_tim_emulate_dma_start( dma_config.NbData = length; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_MODE_NORMAL; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_Init(RFID_DMA_CH1_DEF, &dma_config); + LL_DMA_EnableChannel(RFID_DMA_CH1_DEF); // configure DMA "mem -> CCR3" channel #if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3 @@ -366,13 +378,13 @@ void furi_hal_rfid_tim_emulate_dma_start( dma_config.NbData = length; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_MODE_NORMAL; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_Init(RFID_DMA_CH2_DEF, &dma_config); + LL_DMA_EnableChannel(RFID_DMA_CH2_DEF); // attach interrupt to one of DMA channels - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, furi_hal_rfid_dma_isr, NULL); - LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1); + furi_hal_interrupt_set_isr(RFID_DMA_CH1_IRQ, furi_hal_rfid_dma_isr, NULL); + LL_DMA_EnableIT_TC(RFID_DMA_CH1_DEF); + LL_DMA_EnableIT_HT(RFID_DMA_CH1_DEF); // start LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); @@ -385,14 +397,14 @@ void furi_hal_rfid_tim_emulate_dma_stop() { LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER); LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); - LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_1); + furi_hal_interrupt_set_isr(RFID_DMA_CH1_IRQ, NULL, NULL); + LL_DMA_DisableIT_TC(RFID_DMA_CH1_DEF); + LL_DMA_DisableIT_HT(RFID_DMA_CH1_DEF); FURI_CRITICAL_ENTER(); - LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DeInit(RFID_DMA_CH1_DEF); + LL_DMA_DeInit(RFID_DMA_CH2_DEF); LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); FURI_CRITICAL_EXIT(); @@ -471,4 +483,4 @@ void COMP_IRQHandler() { (LL_COMP_ReadOutputLevel(COMP1) == LL_COMP_OUTPUT_LEVEL_LOW), furi_hal_rfid_comp_callback_context); } -} +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index 2f9d87080..8dba8327f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -1,14 +1,33 @@ +#include #include #include #include +#include -#include -#include - +#include #include #include #include +#define TAG "FuriHalSpi" + +#define SPI_DMA DMA2 +#define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_3 +#define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_4 +#define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch3 +#define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch4 +#define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL +#define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL + +// For simplicity, I assume that only one SPI DMA transaction can occur at a time. +static FuriSemaphore* spi_dma_lock = NULL; +static FuriSemaphore* spi_dma_completed = NULL; + +void furi_hal_spi_dma_init() { + spi_dma_lock = furi_semaphore_alloc(1, 1); + spi_dma_completed = furi_semaphore_alloc(1, 1); +} + void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { furi_assert(bus); bus->callback(bus, FuriHalSpiBusEventInit); @@ -149,3 +168,209 @@ bool furi_hal_spi_bus_trx( return ret; } + +static void spi_dma_isr() { +#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 + if(LL_DMA_IsActiveFlag_TC3(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) { + LL_DMA_ClearFlag_TC3(SPI_DMA); + furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); + } +#else +#error Update this code. Would you kindly? +#endif + +#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 + if(LL_DMA_IsActiveFlag_TC4(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) { + LL_DMA_ClearFlag_TC4(SPI_DMA); + furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); + } +#else +#error Update this code. Would you kindly? +#endif +} + +bool furi_hal_spi_bus_trx_dma( + FuriHalSpiBusHandle* handle, + uint8_t* tx_buffer, + uint8_t* rx_buffer, + size_t size, + uint32_t timeout_ms) { + furi_assert(handle); + furi_assert(handle->bus->current_handle == handle); + furi_assert(size > 0); + + // If scheduler is not running, use blocking mode + if(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + return furi_hal_spi_bus_trx(handle, tx_buffer, rx_buffer, size, timeout_ms); + } + + // Lock DMA + furi_check(furi_semaphore_acquire(spi_dma_lock, FuriWaitForever) == FuriStatusOk); + + const uint32_t dma_dummy_u32 = 0xFFFFFFFF; + + bool ret = true; + SPI_TypeDef* spi = handle->bus->spi; + uint32_t dma_rx_req; + uint32_t dma_tx_req; + + if(spi == SPI1) { + dma_rx_req = LL_DMAMUX_REQ_SPI1_RX; + dma_tx_req = LL_DMAMUX_REQ_SPI1_TX; + } else if(spi == SPI2) { + dma_rx_req = LL_DMAMUX_REQ_SPI2_RX; + dma_tx_req = LL_DMAMUX_REQ_SPI2_TX; + } else { + furi_crash(NULL); + } + + if(rx_buffer == NULL) { + // Only TX mode, do not use RX channel + + LL_DMA_InitTypeDef dma_config = {0}; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_tx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); + +#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 + LL_DMA_ClearFlag_TC4(SPI_DMA); +#else +#error Update this code. Would you kindly? +#endif + + furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, spi_dma_isr, NULL); + + bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi); + if(!dma_tx_was_enabled) { + LL_SPI_EnableDMAReq_TX(spi); + } + + // acquire semaphore before enabling DMA + furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk); + + LL_DMA_EnableIT_TC(SPI_DMA_TX_DEF); + LL_DMA_EnableChannel(SPI_DMA_TX_DEF); + + // and wait for it to be released (DMA transfer complete) + if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) { + ret = false; + FURI_LOG_E(TAG, "DMA timeout\r\n"); + } + // release semaphore, because we are using it as a flag + furi_semaphore_release(spi_dma_completed); + + LL_DMA_DisableIT_TC(SPI_DMA_TX_DEF); + LL_DMA_DisableChannel(SPI_DMA_TX_DEF); + if(!dma_tx_was_enabled) { + LL_SPI_DisableDMAReq_TX(spi); + } + furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, NULL, NULL); + + LL_DMA_DeInit(SPI_DMA_TX_DEF); + } else { + // TRX or RX mode, use both channels + uint32_t tx_mem_increase_mode; + + if(tx_buffer == NULL) { + // RX mode, use dummy data instead of TX buffer + tx_buffer = (uint8_t*)&dma_dummy_u32; + tx_mem_increase_mode = LL_DMA_PERIPH_NOINCREMENT; + } else { + tx_mem_increase_mode = LL_DMA_MEMORY_INCREMENT; + } + + LL_DMA_InitTypeDef dma_config = {0}; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = tx_mem_increase_mode; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_tx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); + + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)rx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_rx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config); + +#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 + LL_DMA_ClearFlag_TC3(SPI_DMA); +#else +#error Update this code. Would you kindly? +#endif + + furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, spi_dma_isr, NULL); + + bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi); + bool dma_rx_was_enabled = LL_SPI_IsEnabledDMAReq_RX(spi); + + if(!dma_tx_was_enabled) { + LL_SPI_EnableDMAReq_TX(spi); + } + + if(!dma_rx_was_enabled) { + LL_SPI_EnableDMAReq_RX(spi); + } + + // acquire semaphore before enabling DMA + furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk); + + LL_DMA_EnableIT_TC(SPI_DMA_RX_DEF); + LL_DMA_EnableChannel(SPI_DMA_RX_DEF); + LL_DMA_EnableChannel(SPI_DMA_TX_DEF); + + // and wait for it to be released (DMA transfer complete) + if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) { + ret = false; + FURI_LOG_E(TAG, "DMA timeout\r\n"); + } + // release semaphore, because we are using it as a flag + furi_semaphore_release(spi_dma_completed); + + LL_DMA_DisableIT_TC(SPI_DMA_RX_DEF); + + LL_DMA_DisableChannel(SPI_DMA_TX_DEF); + LL_DMA_DisableChannel(SPI_DMA_RX_DEF); + + if(!dma_tx_was_enabled) { + LL_SPI_DisableDMAReq_TX(spi); + } + + if(!dma_rx_was_enabled) { + LL_SPI_DisableDMAReq_RX(spi); + } + + furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, NULL, NULL); + + LL_DMA_DeInit(SPI_DMA_TX_DEF); + LL_DMA_DeInit(SPI_DMA_RX_DEF); + } + + furi_hal_spi_bus_end_txrx(handle, timeout_ms); + + furi_check(furi_semaphore_release(spi_dma_lock) == FuriStatusOk); + + return ret; +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 9bde15c33..a6d275308 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -18,6 +18,14 @@ static uint32_t furi_hal_subghz_debug_gpio_buff[2]; +/* DMA Channels definition */ +#define SUBGHZ_DMA DMA2 +#define SUBGHZ_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1 +#define SUBGHZ_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2 +#define SUBGHZ_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1 +#define SUBGHZ_DMA_CH1_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH1_CHANNEL +#define SUBGHZ_DMA_CH2_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH2_CHANNEL + typedef struct { volatile SubGhzState state; volatile SubGhzRegulation regulation; @@ -525,8 +533,8 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { *buffer = 0; buffer++; samples--; - LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableIT_HT(SUBGHZ_DMA_CH1_DEF); + LL_DMA_DisableIT_TC(SUBGHZ_DMA_CH1_DEF); LL_TIM_EnableIT_UPDATE(TIM2); break; } else { @@ -567,17 +575,22 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { static void furi_hal_subghz_async_tx_dma_isr() { furi_assert(furi_hal_subghz.state == SubGhzStateAsyncTx); - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); + +#if SUBGHZ_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 + if(LL_DMA_IsActiveFlag_HT1(SUBGHZ_DMA)) { + LL_DMA_ClearFlag_HT1(SUBGHZ_DMA); furi_hal_subghz_async_tx_refill( furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); + if(LL_DMA_IsActiveFlag_TC1(SUBGHZ_DMA)) { + LL_DMA_ClearFlag_TC1(SUBGHZ_DMA); furi_hal_subghz_async_tx_refill( furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } +#else +#error Update this code. Would you kindly? +#endif } static void furi_hal_subghz_async_tx_timer_isr() { @@ -586,7 +599,7 @@ static void furi_hal_subghz_async_tx_timer_isr() { if(LL_TIM_GetAutoReload(TIM2) == 0) { if(furi_hal_subghz.state == SubGhzStateAsyncTx) { furi_hal_subghz.state = SubGhzStateAsyncTxLast; - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableChannel(SUBGHZ_DMA_CH1_DEF); } else if(furi_hal_subghz.state == SubGhzStateAsyncTxLast) { furi_hal_subghz.state = SubGhzStateAsyncTxEnd; //forcibly pulls the pin to the ground so that there is no carrier @@ -634,11 +647,11 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* dma_config.NbData = API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_MODE_NORMAL; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, furi_hal_subghz_async_tx_dma_isr, NULL); - LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_Init(SUBGHZ_DMA_CH1_DEF, &dma_config); + furi_hal_interrupt_set_isr(SUBGHZ_DMA_CH1_IRQ, furi_hal_subghz_async_tx_dma_isr, NULL); + LL_DMA_EnableIT_TC(SUBGHZ_DMA_CH1_DEF); + LL_DMA_EnableIT_HT(SUBGHZ_DMA_CH1_DEF); + LL_DMA_EnableChannel(SUBGHZ_DMA_CH1_DEF); // Configure TIM2 LL_TIM_InitTypeDef TIM_InitStruct = {0}; @@ -696,9 +709,9 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* dma_config.NbData = 2; dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH; - LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config); - LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_Init(SUBGHZ_DMA_CH2_DEF, &dma_config); + LL_DMA_SetDataLength(SUBGHZ_DMA_CH2_DEF, 2); + LL_DMA_EnableChannel(SUBGHZ_DMA_CH2_DEF); } return true; @@ -726,16 +739,16 @@ void furi_hal_subghz_stop_async_tx() { furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); // Deinitialize DMA - LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DeInit(SUBGHZ_DMA_CH1_DEF); - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); + furi_hal_interrupt_set_isr(SUBGHZ_DMA_CH1_IRQ, NULL, NULL); // Deinitialize GPIO furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); // Stop debug if(furi_hal_subghz_stop_debug()) { - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_DisableChannel(SUBGHZ_DMA_CH2_DEF); } FURI_CRITICAL_EXIT(); diff --git a/firmware/targets/f7/src/update.c b/firmware/targets/f7/src/update.c index b223a5dc3..d8d26eb7c 100644 --- a/firmware/targets/f7/src/update.c +++ b/firmware/targets/f7/src/update.c @@ -23,8 +23,8 @@ static FATFS* pfs = NULL; } static bool flipper_update_mount_sd() { - for(int i = 0; i < BSP_SD_MaxMountRetryCount(); ++i) { - if(BSP_SD_Init((i % 2) == 0) != MSD_OK) { + for(int i = 0; i < sd_max_mount_retry_count(); ++i) { + if(sd_init((i % 2) == 0) != SdSpiStatusOK) { /* Next attempt will be without card reset, let it settle */ furi_delay_ms(1000); continue; diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/firmware/targets/furi_hal_include/furi_hal_spi.h index ab00ef0d7..79e809317 100644 --- a/firmware/targets/furi_hal_include/furi_hal_spi.h +++ b/firmware/targets/furi_hal_include/furi_hal_spi.h @@ -16,6 +16,9 @@ void furi_hal_spi_config_deinit_early(); /** Initialize SPI HAL */ void furi_hal_spi_config_init(); +/** Initialize SPI DMA HAL */ +void furi_hal_spi_dma_init(); + /** Initialize SPI Bus * * @param handle pointer to FuriHalSpiBus instance @@ -103,6 +106,23 @@ bool furi_hal_spi_bus_trx( size_t size, uint32_t timeout); +/** SPI Transmit and Receive with DMA + * + * @param handle pointer to FuriHalSpiBusHandle instance + * @param tx_buffer pointer to tx buffer + * @param rx_buffer pointer to rx buffer + * @param size transaction size (buffer size) + * @param timeout_ms operation timeout in ms + * + * @return true on success + */ +bool furi_hal_spi_bus_trx_dma( + FuriHalSpiBusHandle* handle, + uint8_t* tx_buffer, + uint8_t* rx_buffer, + size_t size, + uint32_t timeout_ms); + #ifdef __cplusplus } #endif diff --git a/furi/core/event_flag.c b/furi/core/event_flag.c index 87de65f2d..9406a581f 100644 --- a/furi/core/event_flag.c +++ b/furi/core/event_flag.c @@ -32,7 +32,7 @@ uint32_t furi_event_flag_set(FuriEventFlag* instance, uint32_t flags) { if(FURI_IS_IRQ_MODE()) { yield = pdFALSE; if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) { - rflags = (uint32_t)FuriStatusErrorResource; + rflags = (uint32_t)FuriFlagErrorResource; } else { rflags = flags; portYIELD_FROM_ISR(yield); diff --git a/furi/core/thread.c b/furi/core/thread.c index ef9560b4a..9a112d9a8 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -195,6 +195,15 @@ void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority) { thread->priority = priority; } +void furi_thread_set_current_priority(FuriThreadPriority priority) { + UBaseType_t new_priority = priority ? priority : FuriThreadPriorityNormal; + vTaskPrioritySet(NULL, new_priority); +} + +FuriThreadPriority furi_thread_get_current_priority() { + return (FuriThreadPriority)uxTaskPriorityGet(NULL); +} + void furi_thread_set_state_callback(FuriThread* thread, FuriThreadStateCallback callback) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); diff --git a/furi/core/thread.h b/furi/core/thread.h index 1542d5bf0..2675f7cee 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -122,6 +122,18 @@ void furi_thread_set_context(FuriThread* thread, void* context); */ void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority); +/** Set current thread priority + * + * @param priority FuriThreadPriority value + */ +void furi_thread_set_current_priority(FuriThreadPriority priority); + +/** Get current thread priority + * + * @return FuriThreadPriority value + */ +FuriThreadPriority furi_thread_get_current_priority(); + /** Set FuriThread state change callback * * @param thread FuriThread instance From 7a3a1aaf0db35501b6ee5891ad039605285f2fea Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Wed, 8 Feb 2023 08:40:44 +0300 Subject: [PATCH 02/34] [FL-3057] Allow use of any suitable pin for 1-Wire devices (#2350) * Add 1-wire thermometer example app stub * Working 1-wire thermometer app * Refactor app to use threads * Clean up code, add comments * Add CRC checking * Increase update period * Fix error in fbt * Revert the old update period * Use settable pin in onewire_host * Use settable pin for onewire_slave * Clear EXTI flag after callback, make private methods static in onewire_slave * Do not hardcode GPIO pin number * Remove iButton hal from furi_hal_rfid * Remove most of furi_hal_ibutton * Add some of furi_hal_ibutton back * Slightly neater code * Fix formatting * Fix PVS-studio warnings * Update CODEOWNERS * Add furi_hal_gpio_get_ext_pin_number * Create README.md * FuriHal: move furi_hal_gpio_get_ext_pin_number to resources --------- Co-authored-by: Aleksandr Kutuzov --- .github/CODEOWNERS | 2 + .../examples/example_thermo/README.md | 44 +++ .../examples/example_thermo/application.fam | 10 + .../examples/example_thermo/example_thermo.c | 356 ++++++++++++++++++ .../example_thermo/example_thermo_10px.png | Bin 0 -> 7293 bytes applications/main/ibutton/ibutton_cli.c | 2 +- firmware/targets/f18/api_symbols.csv | 3 +- .../targets/f18/furi_hal/furi_hal_resources.c | 24 ++ .../targets/f18/furi_hal/furi_hal_resources.h | 7 + firmware/targets/f7/api_symbols.csv | 20 +- firmware/targets/f7/furi_hal/furi_hal_gpio.c | 33 +- .../targets/f7/furi_hal/furi_hal_ibutton.c | 43 +-- .../targets/f7/furi_hal/furi_hal_ibutton.h | 66 +--- .../targets/f7/furi_hal/furi_hal_resources.c | 23 ++ .../targets/f7/furi_hal/furi_hal_resources.h | 7 + firmware/targets/f7/furi_hal/furi_hal_rfid.c | 10 +- lib/one_wire/ibutton/ibutton_worker.c | 4 +- lib/one_wire/ibutton/ibutton_worker_modes.c | 13 +- lib/one_wire/one_wire_host.c | 48 ++- lib/one_wire/one_wire_host.h | 6 +- lib/one_wire/one_wire_slave.c | 51 +-- lib/one_wire/one_wire_slave.h | 4 +- 22 files changed, 592 insertions(+), 184 deletions(-) create mode 100644 applications/examples/example_thermo/README.md create mode 100644 applications/examples/example_thermo/application.fam create mode 100644 applications/examples/example_thermo/example_thermo.c create mode 100644 applications/examples/example_thermo/example_thermo_10px.png diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index aa4ada1a8..69f8289f9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -42,6 +42,8 @@ /applications/debug/unit_tests/ @skotopes @DrZlo13 @hedger @nminaylov @gornekich @Astrrra @gsurkov @Skorpionm +/applications/examples/example_thermo/ @skotopes @DrZlo13 @hedger @gsurkov + # Assets /assets/resources/infrared/ @skotopes @DrZlo13 @hedger @gsurkov diff --git a/applications/examples/example_thermo/README.md b/applications/examples/example_thermo/README.md new file mode 100644 index 000000000..fa00264dc --- /dev/null +++ b/applications/examples/example_thermo/README.md @@ -0,0 +1,44 @@ +# 1-Wire Thermometer +This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer. +It also covers basic GUI, input handling, threads and localisation. + +## Electrical connections +Before launching the application, connect the sensor to Flipper's external GPIO according to the table below: +| DS18B20 | Flipper | +| :-----: | :-----: | +| VDD | 9 | +| GND | 18 | +| DQ | 17 | + +*NOTE 1*: GND is also available on pins 8 and 11. + +*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9. + +## Launching the application +In order to launch this demo, follow the steps below: +1. Make sure your Flipper has an SD card installed. +2. Connect your Flipper to the computer via a USB cable. +3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice. + +## Changing the data pin +It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below: + +```c +/* Possible GPIO pin choices: + - gpio_ext_pc0 + - gpio_ext_pc1 + - gpio_ext_pc3 + - gpio_ext_pb2 + - gpio_ext_pb3 + - gpio_ext_pa4 + - gpio_ext_pa6 + - gpio_ext_pa7 + - ibutton_gpio +*/ + +#define THERMO_GPIO_PIN (ibutton_gpio) +``` +Do not forget about the external pull-up resistor as these pins do not have one built-in. + +With the changes been made, recompile and launch the application again. +The on-screen text should reflect it by asking to connect the thermometer to another pin. diff --git a/applications/examples/example_thermo/application.fam b/applications/examples/example_thermo/application.fam new file mode 100644 index 000000000..b4a05c7f9 --- /dev/null +++ b/applications/examples/example_thermo/application.fam @@ -0,0 +1,10 @@ +App( + appid="example_thermo", + name="Example: Thermometer", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_thermo_main", + requires=["gui"], + stack_size=1 * 1024, + fap_icon="example_thermo_10px.png", + fap_category="Examples", +) diff --git a/applications/examples/example_thermo/example_thermo.c b/applications/examples/example_thermo/example_thermo.c new file mode 100644 index 000000000..b3bc7cd99 --- /dev/null +++ b/applications/examples/example_thermo/example_thermo.c @@ -0,0 +1,356 @@ +/* + * This file contains an example application that reads and displays + * the temperature from a DS18B20 1-wire thermometer. + * + * It also covers basic GUI, input handling, threads and localisation. + * + * References: + * [1] DS18B20 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf + */ + +#include +#include + +#include +#include + +#include + +#include +#include + +#define UPDATE_PERIOD_MS 1000UL +#define TEXT_STORE_SIZE 64U + +#define DS18B20_CMD_CONVERT 0x44U +#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU + +#define DS18B20_CFG_RESOLUTION_POS 5U +#define DS18B20_CFG_RESOLUTION_MASK 0x03U +#define DS18B20_DECIMAL_PART_MASK 0x0fU + +#define DS18B20_SIGN_MASK 0xf0U + +/* Possible GPIO pin choices: + - gpio_ext_pc0 + - gpio_ext_pc1 + - gpio_ext_pc3 + - gpio_ext_pb2 + - gpio_ext_pb3 + - gpio_ext_pa4 + - gpio_ext_pa6 + - gpio_ext_pa7 + - ibutton_gpio +*/ + +#define THERMO_GPIO_PIN (ibutton_gpio) + +/* Flags which the reader thread responds to */ +typedef enum { + ReaderThreadFlagExit = 1, +} ReaderThreadFlag; + +typedef union { + struct { + uint8_t temp_lsb; /* Least significant byte of the temperature */ + uint8_t temp_msb; /* Most significant byte of the temperature */ + uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */ + uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */ + uint8_t config; /* Configuration register */ + uint8_t reserved[3]; /* Not used */ + uint8_t crc; /* CRC checksum for error detection */ + } fields; + uint8_t bytes[9]; +} DS18B20Scratchpad; + +/* Application context structure */ +typedef struct { + Gui* gui; + ViewPort* view_port; + FuriThread* reader_thread; + FuriMessageQueue* event_queue; + OneWireHost* onewire; + float temp_celsius; + bool has_device; +} ExampleThermoContext; + +/*************** 1-Wire Communication and Processing *****************/ + +/* Commands the thermometer to begin measuring the temperature. */ +static void example_thermo_request_temperature(ExampleThermoContext* context) { + OneWireHost* onewire = context->onewire; + + /* All 1-wire transactions must happen in a critical section, i.e + not interrupted by other threads. */ + FURI_CRITICAL_ENTER(); + + bool success = false; + do { + /* Each communication with a 1-wire device starts by a reset. + The functon will return true if a device responded with a presence pulse. */ + if(!onewire_host_reset(onewire)) break; + /* After the reset, a ROM operation must follow. + If there is only one device connected, the "Skip ROM" command is most appropriate + (it can also be used to address all of the connected devices in some cases).*/ + onewire_host_skip(onewire); + /* After the ROM operation, a device-specific command is issued. + In this case, it's a request to start measuring the temperature. */ + onewire_host_write(onewire, DS18B20_CMD_CONVERT); + + success = true; + } while(false); + + context->has_device = success; + + FURI_CRITICAL_EXIT(); +} + +/* Reads the measured temperature from the thermometer. */ +static void example_thermo_read_temperature(ExampleThermoContext* context) { + /* If there was no device detected, don't try to read the temperature */ + if(!context->has_device) { + return; + } + + OneWireHost* onewire = context->onewire; + + /* All 1-wire transactions must happen in a critical section, i.e + not interrupted by other threads. */ + FURI_CRITICAL_ENTER(); + + bool success = false; + + do { + DS18B20Scratchpad buf; + + /* Attempt reading the temperature 10 times before giving up */ + size_t attempts_left = 10; + do { + /* Each communication with a 1-wire device starts by a reset. + The functon will return true if a device responded with a presence pulse. */ + if(!onewire_host_reset(onewire)) continue; + + /* After the reset, a ROM operation must follow. + If there is only one device connected, the "Skip ROM" command is most appropriate + (it can also be used to address all of the connected devices in some cases).*/ + onewire_host_skip(onewire); + + /* After the ROM operation, a device-specific command is issued. + This time, it will be the "Read Scratchpad" command which will + prepare the device's internal buffer memory for reading. */ + onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD); + + /* The actual reading happens here. A total of 9 bytes is read. */ + onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes)); + + /* Calculate the checksum and compare it with one provided by the device. */ + const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT); + + /* Checksums match, exit the loop */ + if(crc == buf.fields.crc) break; + + } while(--attempts_left); + + if(attempts_left == 0) break; + + /* Get the measurement resolution from the configuration register. (See [1] page 9) */ + const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) & + DS18B20_CFG_RESOLUTION_MASK; + + /* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */ + const uint8_t decimal_mask = + (DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) & + DS18B20_DECIMAL_PART_MASK; + + /* Get the integer and decimal part of the temperature (See [1] page 6) */ + const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U); + const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask; + + /* Calculate the sign of the temperature (See [1] page 6) */ + const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0; + + /* Combine the integer and decimal part together */ + const float temp_celsius_abs = integer_part + decimal_part / 16.f; + + /* Set the appropriate sign */ + context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs; + + success = true; + } while(false); + + context->has_device = success; + + FURI_CRITICAL_EXIT(); +} + +/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */ +static int32_t example_thermo_reader_thread_callback(void* ctx) { + ExampleThermoContext* context = ctx; + + for(;;) { + /* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */ + example_thermo_request_temperature(context); + + /* Wait for the measurement to finish. At the same time wait for an exit signal. */ + const uint32_t flags = + furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS); + + /* If an exit signal was received, return from this thread. */ + if(flags != (unsigned)FuriFlagErrorTimeout) break; + + /* The measurement is now ready, read it from the termometer. */ + example_thermo_read_temperature(context); + } + + return 0; +} + +/*************** GUI, Input and Main Loop *****************/ + +/* Draw the GUI of the application. The screen is completely redrawn during each call. */ +static void example_thermo_draw_callback(Canvas* canvas, void* ctx) { + ExampleThermoContext* context = ctx; + char text_store[TEXT_STORE_SIZE]; + const size_t middle_x = canvas_width(canvas) / 2U; + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo"); + canvas_draw_line(canvas, 0, 16, 128, 16); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer"); + + snprintf( + text_store, + TEXT_STORE_SIZE, + "to GPIO pin %ld", + furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN)); + canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store); + + canvas_set_font(canvas, FontKeyboard); + + if(context->has_device) { + float temp; + char temp_units; + + /* The applicaton is locale-aware. + Change Settings->System->Units to check it out. */ + switch(locale_get_measurement_unit()) { + case LocaleMeasurementUnitsMetric: + temp = context->temp_celsius; + temp_units = 'C'; + break; + case LocaleMeasurementUnitsImperial: + temp = locale_celsius_to_fahrenheit(context->temp_celsius); + temp_units = 'F'; + break; + default: + furi_crash("Illegal measurement units"); + } + /* If a reading is available, display it */ + snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units); + } else { + /* Or show a message that no data is available */ + strncpy(text_store, "-- No data --", TEXT_STORE_SIZE); + } + + canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store); +} + +/* This function is called from the GUI thread. All it does is put the event + into the application's queue so it can be processed later. */ +static void example_thermo_input_callback(InputEvent* event, void* ctx) { + ExampleThermoContext* context = ctx; + furi_message_queue_put(context->event_queue, event, FuriWaitForever); +} + +/* Starts the reader thread and handles the input */ +static void example_thermo_run(ExampleThermoContext* context) { + /* Configure the hardware in host mode */ + onewire_host_start(context->onewire); + + /* Start the reader thread. It will talk to the thermometer in the background. */ + furi_thread_start(context->reader_thread); + + /* An endless loop which handles the input*/ + for(bool is_running = true; is_running;) { + InputEvent event; + /* Wait for an input event. Input events come from the GUI thread via a callback. */ + const FuriStatus status = + furi_message_queue_get(context->event_queue, &event, FuriWaitForever); + + /* This application is only interested in short button presses. */ + if((status != FuriStatusOk) || (event.type != InputTypeShort)) { + continue; + } + + /* When the user presses the "Back" button, break the loop and exit the application. */ + if(event.key == InputKeyBack) { + is_running = false; + } + } + + /* Signal the reader thread to cease operation and exit */ + furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit); + + /* Wait for the reader thread to finish */ + furi_thread_join(context->reader_thread); + + /* Reset the hardware */ + onewire_host_stop(context->onewire); +} + +/******************** Initialisation & startup *****************************/ + +/* Allocate the memory and initialise the variables */ +static ExampleThermoContext* example_thermo_context_alloc() { + ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext)); + + context->view_port = view_port_alloc(); + view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context); + view_port_input_callback_set(context->view_port, example_thermo_input_callback, context); + + context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); + + context->reader_thread = furi_thread_alloc(); + furi_thread_set_stack_size(context->reader_thread, 1024U); + furi_thread_set_context(context->reader_thread, context); + furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback); + + context->gui = furi_record_open(RECORD_GUI); + gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen); + + context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN); + + return context; +} + +/* Release the unused resources and deallocate memory */ +static void example_thermo_context_free(ExampleThermoContext* context) { + view_port_enabled_set(context->view_port, false); + gui_remove_view_port(context->gui, context->view_port); + + onewire_host_free(context->onewire); + furi_thread_free(context->reader_thread); + furi_message_queue_free(context->event_queue); + view_port_free(context->view_port); + + furi_record_close(RECORD_GUI); +} + +/* The application's entry point. Execution starts from here. */ +int32_t example_thermo_main(void* p) { + UNUSED(p); + + /* Allocate all of the necessary structures */ + ExampleThermoContext* context = example_thermo_context_alloc(); + + /* Start the applicaton's main loop. It won't return until the application was requested to exit. */ + example_thermo_run(context); + + /* Release all unneeded resources */ + example_thermo_context_free(context); + + return 0; +} diff --git a/applications/examples/example_thermo/example_thermo_10px.png b/applications/examples/example_thermo/example_thermo_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..3d527f306c2d325fc72380856f14860f51b3742c GIT binary patch literal 7293 zcmeHMcTkhr*A7x6NLK_ALQoVWh4chN3sne3kSb^z5F`mCp^7v?QHrvl6hTCBL5hNu zr78#tyMiuNk+Rqj6ahuC!}o%&>(2L^`DSOn-+!B#G&lf!DOee-p$;^GBJ^qYwG zu0k1IO#B$Gb(B+3AoDV=`A*lv!-15DO|QA$l_Ms@Xll-MW5R=b!OPJNaUtyR1q|np zl$|khVskbfHgkL54QYnI8?OL|f0;``)KARM?tEzZLbc#alyTGpbR5O!!}Ma7!G%KS zbqHQ$%Fu^juNm>qURXbR?WQr2IF^REyJ^!tD^}wYia+t?SMu57Kz!QS<}1sc@*093 zcMCB1vi(7)XS*l2jk*~m$o5D$+e$u+NdV_wNl_6kS?82-Ve|SczSSX8_bS_t!$R*H zo#?^Y8Ps#t=}+?x+_{^Pa-Vgt`4(d8wyc%WK~wd79(ty&X=Lw=I!?2vyLY2@^394n zH?nU$e3A8GQIg@W=YDX$$1OWc@I26tqFp>!zfPfwVTiStEV%N_IJL}5>_Vi6^Op9i zkerg<@toGXCI?412JfAw+ti8FOHr)sZbh1doT`l;Fy;7Z<%!y=B6``43vGMMTjT4* zGK6iP67E;_7rs)uy5Op^*?v==WR8|%?>2`d>Y{ktTCFw4${RQ8^;(_WZ-~d{L2mmorjXS3$w~=No55t?cc(^BS00WNY+frmo;lgK~<;{)UNr;`q$n-fyu3 z{sE;f4U?W~6a8k%Fl@jmf5)Q^>GzbMPF6B?$3jgm9o0Dae4yc(kHk4#vns74U1FU^ zM5fn3sC!KFwWQoJCjokQr1sePBh}``;4+~i)>mp{X_7^U4FzOkm^$2s6Dv;d&)z(& zwc~vImJ7G+$}MFSWX2i^GpdGnb&&lB zmU7H8L<;4bOzuqR7pezkl4c4gNyQD_r@gl-D;42>(vhtSu0Jf1eQdnPl@u{9f zLQCWGSgGlB^mETpTD_R{e0@CS^?KD!D)YY`lgZqbbgQ@R_f}K1BgWAf+%Rst84S+w zc6oK7(Clo3?2?I@lpShl_ISBeL9a&@+c#07DpE5~Rc*AeO|}2biK?7*1BSR|XLeki z_CtHZ`r?3#vpUKUk;xm#ksA7Gl5y;?*0Q-Rto3{>m+QoLXDJedTbD})Kk(}RlFgfOL}r|8GL)3T^cq^bl8wwcwp}nx0CxLJG+u7rjg)I<;k(_ zpCpodaa77hDN{rA{R8$*?wQp(JK1rVJ4}+=+9xQVv^>4-R{0$4b)EJEj)U{-nqryg z>XOB}T8^zq6Q^w$>E}k6TjX2#Ug+HMo45SJnCWS-={-4uZj;Z%tMQ3|C!DJJ47SYl z30FqKlZ$S_G3A`e_$n_QPD*~x8&Fjkm}9hmMuh(Us%hxqXQEx*pQ3#7Uh8idXNyT>!wdzf!94d2>*le-8)<2dA-KX~{cdO9a2vx7ahP#xHn&n33 zqY1<&ZU3YB1}$1}lc&^5SLa+AQ@?uz6meUe4gg zqtq=$R9GUju}J|~%h?uTCY0*kIfcC#ba>mEEpYW07wwu4A-)(XJh0g|`G?{IFm8bd zekqn4(IoT1?t}CK{A@PflOP1|G`%j}IVU~y(jP9qSg^B5e33&xlO?|B7jbC%!T}C; z?)AsQW-}Dt;qg@KUULNWWV~a%=S_)d4~QDoawH+Rd@ZrBg(&B)*E5_hUeV)v#X0Cw zv=_!_=Ji^eJ+SH;;KWdi6E(v)bCuTr6cbJ%CGELgEw*m zOB0=bilQcqw`!r;ruxCjzuh0a#1HsQy*Q}N4grC^Z{4-1bK);N8;|Fwhck!lcPQ1xII?EOIU2PA;+dFNpzugYovG_`D`i}mj+=maZ{g>cLn&g1AnBHz5;_c5zYNFdcCZ+wN zp6D-Z>iZ~CreY!Wxpm{lQz3h`WrymNWv43J zj~`31)D2x4o;3<>IzD?&bn&JodN`!kaCqI-{IEL7#y1lxi@iGPqle>!hc>Of`=vg@ zziX~rP%w0MfUdEn>$YB^azkfcy5{dQ@-`=58f9&mc|P!Eyib0*sxS^tJTY)ksJExk zq*I~(MMiFs!zO6QP0cjY!Z7^Ir6*~Ze=~l&m3iLceOu+hh4Z@0zA91Ejj80|0fAJ} zSopwEjevnX&1emq%J&T+MfW3HB3wpnwpe=2-!p$5o#bY<@Y*cUzsG4Va9X~ovE5Zn zQ_v<}Z!EK|-my$6I9k_v3#V@C%+DC{l3Hw+z^dF#!g+aYD`-l!ex~GkZOR_VUGCh>Ti@`k^A=Z*N-f9d z9NApWTs~~z4a+pEPWG%&x}m#8ueq=90VOZ5hj&S4N1m5G_%kw=zM%l+DXy#Qc17pR zi7CYkVi}b|w=ZT!Z!xWM^++{0Hx->feU%se7JNX|Kj^aaeI*3z_h&At0iSDoi_~I% zRq_8^gN+uWo*lc>>OjsMY8kQVp-76{O1R}PlJ8kc_21{#)DEU6`~K3O2}3>_XReEW zdMp*~AeMvLRC%4tR{z*)k_B$9n1x*_F}(~cP25{{uV;KmJ-()P&SzqF+VhWYKPOr2 zE&pQgk}iDIthQ7xM_GN;nPJgs?NZZ#oClxuNju^x{`NQ&T0?l&P>K>WqM=Jv+jKMo)yj(+Hab6*|#!2eGpLjhvq|zy@c$)*tjy zxPiQpq@{-fm6T3rBA8@XA}@GI4?EPj zErz!J$`yS<{-o4T?j4F-k{lf=s_XA3^_OPQwWy!Kn#(6&WOZFUStetdChk&b8v11- zX1>X*3`u;rHBr&zUGn3oj@Yx_=RCsl<`|vqv!FJ=iCw%;W$X4&X1s~?O4bm0$eDQ5 zSfP8c^{FiKJ+tfQnO&y2W`&^Uf?oX7*f_6qyq*^owI})|Ar$Y6+}OjE{WaFZFO249 zU(USz16{Ec4JxnaUmMB7Z3cm4z1YCD%bjXRV(>U{8k0w7!NWO0z_knn+G!jfL}MIa z2_bZrADc^t&NW?!LfA|))D25TQiCWgf3|fbpXD5B@4|>Yz#uZA#zt#*hLZpS4ogUb zgmVJ90#Y~`y2?ue+AC%R6tW5t9w0;Asg4i|kI#Z&;21a(W)aQ~ML~_$LU!_*zNFpe zmft9V9vSK{6b6wHh_J9Qco-Va|Ed z`R34nd_&*@++Gp8Spr@NpTV*SWpRbtKT=rPP#wQBtc2vp<^-(<1&H^z$(W4qxS$Yz z;3|g6K(GQ?9Dq~+_-F7pypZktmso%EZDnLNoF5$lru)wSH}s#euYv&-l}a+_F+x@* zwJ|3{SNtV0c?>p_wAw^6XapjjhJoRIfmC4VEHsRO!eU`49F2fOV(Azbo%REj4Obwf zaT%-?Du5i$26$LZ100cwVZazTA|8feFz_%M4TXj=eDOFI3x&ZTnZ7?zIPlp(Rnh`~ z^lF8Q2~Zgja5N$Yg@Iu)3?vLg#Q4I97z_%ACE(~N7K@1?5Ll~JD|sN9I@*w-C^+&j zi(?>7=*#1C$WS{rHzfS80T(uhU%P?q)ujZ1tS$-?jqx=E0WFlpT=f&+`Z~n$r*ZvQ z!0z#_T>rGQ|3fLD(ReH#V}OS-Ff=R-gJYs$GymMobkHG&{*S~W8BL)5u z_}}XKf0JwNUpGb;7dYsJ0rx?cL&P=UE-B$?=VAdomzS3>4i}68EfKn{l{qL$e6uys z0S8%o2!KBUl~%qYpxnHTfKgItL$#2cl-VSwBf)ExO#w`rHs+=-Qui3|BVr#Wi?+LM n{LmKn@Uh4d70Hbn>L3*8aiyH^d~eG#00r4t*qdKA+aLcw^(CDL literal 0 HcmV?d00001 diff --git a/applications/main/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c index fab1ccf05..9ddb079dc 100644 --- a/applications/main/ibutton/ibutton_cli.c +++ b/applications/main/ibutton/ibutton_cli.c @@ -271,7 +271,7 @@ void onewire_cli_print_usage() { static void onewire_cli_search(Cli* cli) { UNUSED(cli); - OneWireHost* onewire = onewire_host_alloc(); + OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio); uint8_t address[8]; bool done = false; diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index ff6dbc239..025b605fc 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.2,, +Version,+,13.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -910,6 +910,7 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* +Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/firmware/targets/f18/furi_hal/furi_hal_resources.c index dafeefdd0..41cc80bfb 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.c @@ -199,3 +199,27 @@ void furi_hal_resources_init() { NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(EXTI15_10_IRQn); } + +int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { + // TODO: describe second ROW + if(gpio == &gpio_ext_pa7) + return 2; + else if(gpio == &gpio_ext_pa6) + return 3; + else if(gpio == &gpio_ext_pa4) + return 4; + else if(gpio == &gpio_ext_pb3) + return 5; + else if(gpio == &gpio_ext_pb2) + return 6; + else if(gpio == &gpio_ext_pc3) + return 7; + else if(gpio == &gpio_ext_pc1) + return 15; + else if(gpio == &gpio_ext_pc0) + return 16; + else if(gpio == &ibutton_gpio) + return 17; + else + return -1; +} diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.h b/firmware/targets/f18/furi_hal/furi_hal_resources.h index ef2cdae7f..a24afbf94 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.h @@ -111,6 +111,13 @@ void furi_hal_resources_deinit_early(); void furi_hal_resources_init(); +/** + * Get a corresponding external connector pin number for a gpio + * @param gpio GpioPin + * @return pin number or -1 if gpio is not on the external connector + */ +int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a1f34f106..35985aebb 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.2,, +Version,+,13.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1094,6 +1094,7 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* +Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" @@ -1129,20 +1130,13 @@ Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uin Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t" Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t" Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t" -Function,+,furi_hal_ibutton_add_interrupt,void,"GpioExtiCallback, void*" Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t Function,+,furi_hal_ibutton_emulate_start,void,"uint32_t, FuriHalIbuttonEmulateCallback, void*" Function,+,furi_hal_ibutton_emulate_stop,void, Function,-,furi_hal_ibutton_init,void, -Function,+,furi_hal_ibutton_pin_get_level,_Bool, -Function,+,furi_hal_ibutton_pin_high,void, -Function,+,furi_hal_ibutton_pin_low,void, -Function,+,furi_hal_ibutton_remove_interrupt,void, -Function,+,furi_hal_ibutton_start_drive,void, -Function,+,furi_hal_ibutton_start_drive_in_isr,void, -Function,+,furi_hal_ibutton_start_interrupt,void, -Function,+,furi_hal_ibutton_start_interrupt_in_isr,void, -Function,+,furi_hal_ibutton_stop,void, +Function,+,furi_hal_ibutton_pin_configure,void, +Function,+,furi_hal_ibutton_pin_reset,void, +Function,+,furi_hal_ibutton_pin_write,void,const _Bool Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*" Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*" Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t @@ -2040,7 +2034,7 @@ Function,+,onewire_device_detach,void,OneWireDevice* Function,+,onewire_device_free,void,OneWireDevice* Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice* Function,+,onewire_device_send_id,void,OneWireDevice* -Function,+,onewire_host_alloc,OneWireHost*, +Function,+,onewire_host_alloc,OneWireHost*,const GpioPin* Function,+,onewire_host_free,void,OneWireHost* Function,+,onewire_host_read,uint8_t,OneWireHost* Function,+,onewire_host_read_bit,_Bool,OneWireHost* @@ -2054,7 +2048,7 @@ Function,+,onewire_host_stop,void,OneWireHost* Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t" Function,+,onewire_host_write,void,"OneWireHost*, uint8_t" Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool" -Function,+,onewire_slave_alloc,OneWireSlave*, +Function,+,onewire_slave_alloc,OneWireSlave*,const GpioPin* Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*" Function,+,onewire_slave_detach,void,OneWireSlave* Function,+,onewire_slave_free,void,OneWireSlave* diff --git a/firmware/targets/f7/furi_hal/furi_hal_gpio.c b/firmware/targets/f7/furi_hal/furi_hal_gpio.c index a148a3af2..e8318afcf 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_gpio.c +++ b/firmware/targets/f7/furi_hal/furi_hal_gpio.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #define GET_SYSCFG_EXTI_PORT(gpio) \ @@ -224,85 +225,85 @@ static void furi_hal_gpio_int_call(uint16_t pin_num) { /* Interrupt handlers */ void EXTI0_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0); furi_hal_gpio_int_call(0); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0); } } void EXTI1_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_1)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1); furi_hal_gpio_int_call(1); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1); } } void EXTI2_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_2)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2); furi_hal_gpio_int_call(2); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2); } } void EXTI3_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_3)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3); furi_hal_gpio_int_call(3); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3); } } void EXTI4_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4); furi_hal_gpio_int_call(4); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4); } } void EXTI9_5_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5); furi_hal_gpio_int_call(5); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6); furi_hal_gpio_int_call(6); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_7)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7); furi_hal_gpio_int_call(7); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_8)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8); furi_hal_gpio_int_call(8); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9); furi_hal_gpio_int_call(9); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9); } } void EXTI15_10_IRQHandler(void) { if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_10)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10); furi_hal_gpio_int_call(10); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_11)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11); furi_hal_gpio_int_call(11); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_12)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12); furi_hal_gpio_int_call(12); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13); furi_hal_gpio_int_call(13); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_14)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14); furi_hal_gpio_int_call(14); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14); } if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15)) { - LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15); furi_hal_gpio_int_call(15); + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15); } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_ibutton.c b/firmware/targets/f7/furi_hal/furi_hal_ibutton.c index 0375893e7..c05cd69a8 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_ibutton.c +++ b/firmware/targets/f7/furi_hal/furi_hal_ibutton.c @@ -89,47 +89,16 @@ void furi_hal_ibutton_emulate_stop() { } } -void furi_hal_ibutton_start_drive() { - furi_hal_ibutton_pin_high(); +void furi_hal_ibutton_pin_configure() { + furi_hal_gpio_write(&ibutton_gpio, true); furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); } -void furi_hal_ibutton_start_drive_in_isr() { - furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin); -} - -void furi_hal_ibutton_start_interrupt() { - furi_hal_ibutton_pin_high(); - furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); -} - -void furi_hal_ibutton_start_interrupt_in_isr() { - furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); - LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin); -} - -void furi_hal_ibutton_stop() { - furi_hal_ibutton_pin_high(); +void furi_hal_ibutton_pin_reset() { + furi_hal_gpio_write(&ibutton_gpio, true); furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } -void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context) { - furi_hal_gpio_add_int_callback(&ibutton_gpio, cb, context); -} - -void furi_hal_ibutton_remove_interrupt() { - furi_hal_gpio_remove_int_callback(&ibutton_gpio); -} - -void furi_hal_ibutton_pin_low() { - furi_hal_gpio_write(&ibutton_gpio, false); -} - -void furi_hal_ibutton_pin_high() { - furi_hal_gpio_write(&ibutton_gpio, true); -} - -bool furi_hal_ibutton_pin_get_level() { - return furi_hal_gpio_read(&ibutton_gpio); +void furi_hal_ibutton_pin_write(const bool state) { + furi_hal_gpio_write(&ibutton_gpio, state); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_ibutton.h b/firmware/targets/f7/furi_hal/furi_hal_ibutton.h index fb57d628b..b723fe176 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_ibutton.h +++ b/firmware/targets/f7/furi_hal/furi_hal_ibutton.h @@ -7,7 +7,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { @@ -18,70 +17,43 @@ typedef void (*FuriHalIbuttonEmulateCallback)(void* context); /** Initialize */ void furi_hal_ibutton_init(); +/** + * Start emulation timer + * @param period timer period + * @param callback timer callback + * @param context callback context + */ void furi_hal_ibutton_emulate_start( uint32_t period, FuriHalIbuttonEmulateCallback callback, void* context); +/** + * Update emulation timer period + * @param period new timer period + */ void furi_hal_ibutton_emulate_set_next(uint32_t period); +/** + * Stop emulation timer + */ void furi_hal_ibutton_emulate_stop(); /** - * Sets the pin to normal mode (open collector), and sets it to float + * Set the pin to normal mode (open collector), and sets it to float */ -void furi_hal_ibutton_start_drive(); - -/** - * Sets the pin to normal mode (open collector), and clears pin EXTI interrupt. - * Used in EXTI interrupt context. - */ -void furi_hal_ibutton_start_drive_in_isr(); - -/** - * Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and sets it to float - */ -void furi_hal_ibutton_start_interrupt(); - -/** - * Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and clears pin EXTI interrupt. - * Used in EXTI interrupt context. - */ -void furi_hal_ibutton_start_interrupt_in_isr(); +void furi_hal_ibutton_pin_configure(); /** * Sets the pin to analog mode, and sets it to float */ -void furi_hal_ibutton_stop(); +void furi_hal_ibutton_pin_reset(); /** - * Attach interrupt callback to iButton pin - * @param cb callback - * @param context context + * iButton write pin + * @param state true / false */ -void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context); - -/** - * Remove interrupt callback from iButton pin - */ -void furi_hal_ibutton_remove_interrupt(); - -/** - * Sets the pin to low - */ -void furi_hal_ibutton_pin_low(); - -/** - * Sets the pin to high (float in iButton pin modes) - */ -void furi_hal_ibutton_pin_high(); - -/** - * Get pin level - * @return true if level is high - * @return false if level is low - */ -bool furi_hal_ibutton_pin_get_level(); +void furi_hal_ibutton_pin_write(const bool state); #ifdef __cplusplus } diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 03cc6e714..c0eb9ee67 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -191,3 +191,26 @@ void furi_hal_resources_init() { NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(EXTI15_10_IRQn); } + +int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { + if(gpio == &gpio_ext_pa7) + return 2; + else if(gpio == &gpio_ext_pa6) + return 3; + else if(gpio == &gpio_ext_pa4) + return 4; + else if(gpio == &gpio_ext_pb3) + return 5; + else if(gpio == &gpio_ext_pb2) + return 6; + else if(gpio == &gpio_ext_pc3) + return 7; + else if(gpio == &gpio_ext_pc1) + return 15; + else if(gpio == &gpio_ext_pc0) + return 16; + else if(gpio == &ibutton_gpio) + return 17; + else + return -1; +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index 51ea7bcc1..04b99a84e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -216,6 +216,13 @@ void furi_hal_resources_deinit_early(); void furi_hal_resources_init(); +/** + * Get a corresponding external connector pin number for a gpio + * @param gpio GpioPin + * @return pin number or -1 if gpio is not on the external connector + */ +int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/firmware/targets/f7/furi_hal/furi_hal_rfid.c index b0238f79f..145e49df2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.c @@ -77,7 +77,7 @@ void furi_hal_rfid_init() { void furi_hal_rfid_pins_reset() { // ibutton bus disable - furi_hal_ibutton_stop(); + furi_hal_ibutton_pin_reset(); // pulldown rfid antenna furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -94,8 +94,8 @@ void furi_hal_rfid_pins_reset() { void furi_hal_rfid_pins_emulate() { // ibutton low - furi_hal_ibutton_start_drive(); - furi_hal_ibutton_pin_low(); + furi_hal_ibutton_pin_configure(); + furi_hal_ibutton_pin_write(false); // pull pin to timer out furi_hal_gpio_init_ex( @@ -115,8 +115,8 @@ void furi_hal_rfid_pins_emulate() { void furi_hal_rfid_pins_read() { // ibutton low - furi_hal_ibutton_start_drive(); - furi_hal_ibutton_pin_low(); + furi_hal_ibutton_pin_configure(); + furi_hal_ibutton_pin_write(false); // dont pull rfid antenna furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); diff --git a/lib/one_wire/ibutton/ibutton_worker.c b/lib/one_wire/ibutton/ibutton_worker.c index 9d5ea3897..1fe39b5e5 100644 --- a/lib/one_wire/ibutton/ibutton_worker.c +++ b/lib/one_wire/ibutton/ibutton_worker.c @@ -25,8 +25,8 @@ iButtonWorker* ibutton_worker_alloc() { iButtonWorker* worker = malloc(sizeof(iButtonWorker)); worker->key_p = NULL; worker->key_data = malloc(ibutton_key_get_max_size()); - worker->host = onewire_host_alloc(); - worker->slave = onewire_slave_alloc(); + worker->host = onewire_host_alloc(&ibutton_gpio); + worker->slave = onewire_slave_alloc(&ibutton_gpio); worker->writer = ibutton_writer_alloc(worker->host); worker->device = onewire_device_alloc(0, 0, 0, 0, 0, 0, 0, 0); worker->messages = furi_message_queue_alloc(1, sizeof(iButtonMessage)); diff --git a/lib/one_wire/ibutton/ibutton_worker_modes.c b/lib/one_wire/ibutton/ibutton_worker_modes.c index b284940e7..da6b10766 100644 --- a/lib/one_wire/ibutton/ibutton_worker_modes.c +++ b/lib/one_wire/ibutton/ibutton_worker_modes.c @@ -234,16 +234,13 @@ void ibutton_worker_emulate_timer_cb(void* context) { furi_assert(context); iButtonWorker* worker = context; - LevelDuration level = + const LevelDuration level_duration = protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode); - furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level)); + const bool level = level_duration_get_level(level_duration); - if(level_duration_get_level(level)) { - furi_hal_ibutton_pin_high(); - } else { - furi_hal_ibutton_pin_low(); - } + furi_hal_ibutton_emulate_set_next(level); + furi_hal_ibutton_pin_write(level); } void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { @@ -266,7 +263,7 @@ void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { protocol_dict_set_data(worker->protocols, worker->protocol_to_encode, key_id, key_size); protocol_dict_encoder_start(worker->protocols, worker->protocol_to_encode); - furi_hal_ibutton_start_drive(); + furi_hal_ibutton_pin_configure(); furi_hal_ibutton_emulate_start(0, ibutton_worker_emulate_timer_cb, worker); } diff --git a/lib/one_wire/one_wire_host.c b/lib/one_wire/one_wire_host.c index 654b9e45d..f3d3d3c4d 100644 --- a/lib/one_wire/one_wire_host.c +++ b/lib/one_wire/one_wire_host.c @@ -1,18 +1,19 @@ #include -#include + #include "one_wire_host.h" #include "one_wire_host_timing.h" struct OneWireHost { - // global search state - unsigned char saved_rom[8]; + const GpioPin* gpio_pin; + unsigned char saved_rom[8]; /** < global search state */ uint8_t last_discrepancy; uint8_t last_family_discrepancy; bool last_device_flag; }; -OneWireHost* onewire_host_alloc() { +OneWireHost* onewire_host_alloc(const GpioPin* gpio_pin) { OneWireHost* host = malloc(sizeof(OneWireHost)); + host->gpio_pin = gpio_pin; onewire_host_reset_search(host); return host; } @@ -23,49 +24,47 @@ void onewire_host_free(OneWireHost* host) { } bool onewire_host_reset(OneWireHost* host) { - UNUSED(host); uint8_t r; uint8_t retries = 125; // wait until the gpio is high - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(host->gpio_pin, true); do { if(--retries == 0) return 0; furi_delay_us(2); - } while(!furi_hal_ibutton_pin_get_level()); + } while(!furi_hal_gpio_read(host->gpio_pin)); // pre delay furi_delay_us(OWH_RESET_DELAY_PRE); // drive low - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(host->gpio_pin, false); furi_delay_us(OWH_RESET_DRIVE); // release - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(host->gpio_pin, true); furi_delay_us(OWH_RESET_RELEASE); // read and post delay - r = !furi_hal_ibutton_pin_get_level(); + r = !furi_hal_gpio_read(host->gpio_pin); furi_delay_us(OWH_RESET_DELAY_POST); return r; } bool onewire_host_read_bit(OneWireHost* host) { - UNUSED(host); bool result; // drive low - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(host->gpio_pin, false); furi_delay_us(OWH_READ_DRIVE); // release - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(host->gpio_pin, true); furi_delay_us(OWH_READ_RELEASE); // read and post delay - result = furi_hal_ibutton_pin_get_level(); + result = furi_hal_gpio_read(host->gpio_pin); furi_delay_us(OWH_READ_DELAY_POST); return result; @@ -90,22 +89,21 @@ void onewire_host_read_bytes(OneWireHost* host, uint8_t* buffer, uint16_t count) } void onewire_host_write_bit(OneWireHost* host, bool value) { - UNUSED(host); if(value) { // drive low - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(host->gpio_pin, false); furi_delay_us(OWH_WRITE_1_DRIVE); // release - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(host->gpio_pin, true); furi_delay_us(OWH_WRITE_1_RELEASE); } else { // drive low - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(host->gpio_pin, false); furi_delay_us(OWH_WRITE_0_DRIVE); // release - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(host->gpio_pin, true); furi_delay_us(OWH_WRITE_0_RELEASE); } } @@ -123,13 +121,13 @@ void onewire_host_skip(OneWireHost* host) { } void onewire_host_start(OneWireHost* host) { - UNUSED(host); - furi_hal_ibutton_start_drive(); + furi_hal_gpio_write(host->gpio_pin, true); + furi_hal_gpio_init(host->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); } void onewire_host_stop(OneWireHost* host) { - UNUSED(host); - furi_hal_ibutton_stop(); + furi_hal_gpio_write(host->gpio_pin, true); + furi_hal_gpio_init(host->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } void onewire_host_reset_search(OneWireHost* host) { @@ -150,7 +148,7 @@ void onewire_host_target_search(OneWireHost* host, uint8_t family_code) { host->last_device_flag = false; } -uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSearchMode mode) { +uint8_t onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearchMode mode) { uint8_t id_bit_number; uint8_t last_zero, rom_byte_number, search_result; uint8_t id_bit, cmp_id_bit; @@ -259,7 +257,7 @@ uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSear host->last_family_discrepancy = 0; search_result = false; } else { - for(int i = 0; i < 8; i++) newAddr[i] = host->saved_rom[i]; + for(int i = 0; i < 8; i++) new_addr[i] = host->saved_rom[i]; } return search_result; diff --git a/lib/one_wire/one_wire_host.h b/lib/one_wire/one_wire_host.h index 5b55ee8dd..9c01abc11 100644 --- a/lib/one_wire/one_wire_host.h +++ b/lib/one_wire/one_wire_host.h @@ -22,10 +22,10 @@ typedef struct OneWireHost OneWireHost; /** * Allocate onewire host bus - * @param gpio + * @param pin * @return OneWireHost* */ -OneWireHost* onewire_host_alloc(); +OneWireHost* onewire_host_alloc(const GpioPin* gpio_pin); /** * Deallocate onewire host bus @@ -114,7 +114,7 @@ void onewire_host_target_search(OneWireHost* host, uint8_t family_code); * @param mode * @return uint8_t */ -uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSearchMode mode); +uint8_t onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearchMode mode); #ifdef __cplusplus } diff --git a/lib/one_wire/one_wire_slave.c b/lib/one_wire/one_wire_slave.c index ad9c34b19..4b54c4f99 100644 --- a/lib/one_wire/one_wire_slave.c +++ b/lib/one_wire/one_wire_slave.c @@ -27,6 +27,7 @@ typedef enum { } OneWireSlaveError; struct OneWireSlave { + const GpioPin* gpio_pin; OneWireSlaveError error; OneWireDevice* device; OneWireSlaveResultCallback result_cb; @@ -35,15 +36,15 @@ struct OneWireSlave { /*********************** PRIVATE ***********************/ -uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) { - UNUSED(bus); +static uint32_t + onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) { uint32_t start = DWT->CYCCNT; uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond(); uint32_t time_captured; do { //-V1044 time_captured = DWT->CYCCNT; - if(furi_hal_ibutton_pin_get_level() != pin_value) { + if(furi_hal_gpio_read(bus->gpio_pin) != pin_value) { uint32_t remaining_time = time_ticks - (time_captured - start); remaining_time /= furi_hal_cortex_instructions_per_microsecond(); return remaining_time; @@ -53,14 +54,14 @@ uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, cons return 0; } -bool onewire_slave_show_presence(OneWireSlave* bus) { +static bool onewire_slave_show_presence(OneWireSlave* bus) { // wait while master delay presence check onewire_slave_wait_while_gpio_is(bus, OWS_PRESENCE_TIMEOUT, true); // show presence - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(bus->gpio_pin, false); furi_delay_us(OWS_PRESENCE_MIN); - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(bus->gpio_pin, true); // somebody also can show presence const uint32_t wait_low_time = OWS_PRESENCE_MAX - OWS_PRESENCE_MIN; @@ -74,7 +75,7 @@ bool onewire_slave_show_presence(OneWireSlave* bus) { return true; } -bool onewire_slave_receive_bit(OneWireSlave* bus) { +static bool onewire_slave_receive_bit(OneWireSlave* bus) { // wait while bus is low uint32_t time = OWS_SLOT_MAX; time = onewire_slave_wait_while_gpio_is(bus, time, false); @@ -98,7 +99,7 @@ bool onewire_slave_receive_bit(OneWireSlave* bus) { return (time > 0); } -bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { +static bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { const bool write_zero = !value; // wait while bus is low @@ -119,7 +120,7 @@ bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { // choose write time if(write_zero) { - furi_hal_ibutton_pin_low(); + furi_hal_gpio_write(bus->gpio_pin, false); time = OWS_WRITE_ZERO; } else { time = OWS_READ_MAX; @@ -127,12 +128,12 @@ bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { // hold line for ZERO or ONE time furi_delay_us(time); - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(bus->gpio_pin, true); return true; } -void onewire_slave_cmd_search_rom(OneWireSlave* bus) { +static void onewire_slave_cmd_search_rom(OneWireSlave* bus) { const uint8_t key_bytes = 8; uint8_t* key = onewire_device_get_id_p(bus->device); @@ -151,7 +152,7 @@ void onewire_slave_cmd_search_rom(OneWireSlave* bus) { } } -bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { +static bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { uint8_t cmd; onewire_slave_receive(bus, &cmd, 1); @@ -178,14 +179,14 @@ bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { } } -bool onewire_slave_bus_start(OneWireSlave* bus) { +static bool onewire_slave_bus_start(OneWireSlave* bus) { bool result = true; if(bus->device == NULL) { result = false; } else { FURI_CRITICAL_ENTER(); - furi_hal_ibutton_start_drive_in_isr(); + furi_hal_gpio_init(bus->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); bus->error = NO_ERROR; if(onewire_slave_show_presence(bus)) { @@ -197,7 +198,7 @@ bool onewire_slave_bus_start(OneWireSlave* bus) { result = false; } - furi_hal_ibutton_start_interrupt_in_isr(); + furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); FURI_CRITICAL_EXIT(); } @@ -207,7 +208,7 @@ bool onewire_slave_bus_start(OneWireSlave* bus) { static void exti_cb(void* context) { OneWireSlave* bus = context; - volatile bool input_state = furi_hal_ibutton_pin_get_level(); + volatile bool input_state = furi_hal_gpio_read(bus->gpio_pin); static uint32_t pulse_start = 0; if(input_state) { @@ -234,8 +235,9 @@ static void exti_cb(void* context) { /*********************** PUBLIC ***********************/ -OneWireSlave* onewire_slave_alloc() { +OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin) { OneWireSlave* bus = malloc(sizeof(OneWireSlave)); + bus->gpio_pin = gpio_pin; bus->error = NO_ERROR; bus->device = NULL; bus->result_cb = NULL; @@ -249,14 +251,15 @@ void onewire_slave_free(OneWireSlave* bus) { } void onewire_slave_start(OneWireSlave* bus) { - furi_hal_ibutton_add_interrupt(exti_cb, bus); - furi_hal_ibutton_start_interrupt(); + furi_hal_gpio_add_int_callback(bus->gpio_pin, exti_cb, bus); + furi_hal_gpio_write(bus->gpio_pin, true); + furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); } void onewire_slave_stop(OneWireSlave* bus) { - UNUSED(bus); - furi_hal_ibutton_stop(); - furi_hal_ibutton_remove_interrupt(); + furi_hal_gpio_write(bus->gpio_pin, true); + furi_hal_gpio_init(bus->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_remove_int_callback(bus->gpio_pin); } void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device) { @@ -282,7 +285,7 @@ void onewire_slave_set_result_callback( bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length) { uint8_t bytes_sent = 0; - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(bus->gpio_pin, true); // bytes loop for(; bytes_sent < data_length; ++bytes_sent) { @@ -304,7 +307,7 @@ bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length) { uint8_t bytes_received = 0; - furi_hal_ibutton_pin_high(); + furi_hal_gpio_write(bus->gpio_pin, true); for(; bytes_received < data_length; ++bytes_received) { uint8_t value = 0; diff --git a/lib/one_wire/one_wire_slave.h b/lib/one_wire/one_wire_slave.h index 82e9f5523..2e5db3a1c 100644 --- a/lib/one_wire/one_wire_slave.h +++ b/lib/one_wire/one_wire_slave.h @@ -19,10 +19,10 @@ typedef void (*OneWireSlaveResultCallback)(void* context); /** * Allocate onewire slave - * @param pin + * @param gpio_pin * @return OneWireSlave* */ -OneWireSlave* onewire_slave_alloc(); +OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin); /** * Free onewire slave From 111c7557b3c3c5a371f3fddf1a63592b7ad04b6c Mon Sep 17 00:00:00 2001 From: Liam Hays Date: Wed, 8 Feb 2023 01:08:50 -0700 Subject: [PATCH 03/34] Fix minor UI inconsistencies and bugs (#2361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Changed blue LED to cyan in NFC Magic and Picopass apps. * Fix capitalization of ATQA and UID in NFC Add Manually wizard. * Fix reselection of "Saved" menu item in NFC and RFID apps. * Fix double back press after deleting a file in the SubGhz browser. * Make NFC app behave like other apps: return to the file browser after deleting a file. * Rename NfcSceneSetAtqua to NfcSceneSetAtqa. * Save selected menu items in NFC Magic and Picopass apps in a way that always works. * Restore previous selection in Universal Remotes menu. * Other way to do universal remote menu saving, and NFC Extra Actions saves last selection. Co-authored-by: あく --- .../main/infrared/scenes/infrared_scene_universal.c | 4 +++- .../main/lfrfid/scenes/lfrfid_scene_start.c | 9 ++++++++- applications/main/nfc/scenes/nfc_scene_config.h | 2 +- .../main/nfc/scenes/nfc_scene_delete_success.c | 2 +- .../main/nfc/scenes/nfc_scene_extra_actions.c | 2 ++ applications/main/nfc/scenes/nfc_scene_set_atqa.c | 2 +- applications/main/nfc/scenes/nfc_scene_set_sak.c | 2 +- applications/main/nfc/scenes/nfc_scene_set_uid.c | 2 +- applications/main/nfc/scenes/nfc_scene_start.c | 13 ++++++++++++- .../subghz/scenes/subghz_scene_delete_success.c | 5 ++++- applications/plugins/nfc_magic/nfc_magic.c | 6 +++--- .../nfc_magic/scenes/nfc_magic_scene_start.c | 10 +++++++++- applications/plugins/picopass/picopass.c | 6 +++--- .../plugins/picopass/scenes/picopass_scene_start.c | 7 ++++++- 14 files changed, 55 insertions(+), 17 deletions(-) diff --git a/applications/main/infrared/scenes/infrared_scene_universal.c b/applications/main/infrared/scenes/infrared_scene_universal.c index 914360d78..5043c9bd7 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal.c +++ b/applications/main/infrared/scenes/infrared_scene_universal.c @@ -33,7 +33,8 @@ void infrared_scene_universal_on_enter(void* context) { SubmenuIndexUniversalAC, infrared_scene_universal_submenu_callback, context); - submenu_set_selected_item(submenu, 0); + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneUniversal)); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); } @@ -54,6 +55,7 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(scene_manager, InfraredSceneUniversalAudio); consumed = true; } + scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event); } return consumed; diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_start.c b/applications/main/lfrfid/scenes/lfrfid_scene_start.c index 8e1c92dbb..2d83ba53b 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_start.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_start.c @@ -47,21 +47,28 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexRead) { + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexRead); scene_manager_next_scene(app->scene_manager, LfRfidSceneRead); DOLPHIN_DEED(DolphinDeedRfidRead); consumed = true; } else if(event.event == SubmenuIndexSaved) { + // Like in the other apps, explicitly save the scene state + // in each branch in case the user cancels loading a file. + scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexSaved); furi_string_set(app->file_path, LFRFID_APP_FOLDER); scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey); consumed = true; } else if(event.event == SubmenuIndexAddManually) { + scene_manager_set_scene_state( + app->scene_manager, LfRfidSceneStart, SubmenuIndexAddManually); scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType); consumed = true; } else if(event.event == SubmenuIndexExtraActions) { + scene_manager_set_scene_state( + app->scene_manager, LfRfidSceneStart, SubmenuIndexExtraActions); scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions); consumed = true; } - scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event); } return consumed; diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index ce51d000d..f81fe178e 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -4,7 +4,7 @@ ADD_SCENE(nfc, saved_menu, SavedMenu) ADD_SCENE(nfc, extra_actions, ExtraActions) ADD_SCENE(nfc, set_type, SetType) ADD_SCENE(nfc, set_sak, SetSak) -ADD_SCENE(nfc, set_atqa, SetAtqua) +ADD_SCENE(nfc, set_atqa, SetAtqa) ADD_SCENE(nfc, set_uid, SetUid) ADD_SCENE(nfc, generate_info, GenerateInfo) ADD_SCENE(nfc, read_card_success, ReadCardSuccess) diff --git a/applications/main/nfc/scenes/nfc_scene_delete_success.c b/applications/main/nfc/scenes/nfc_scene_delete_success.c index 1664a9e5b..795363527 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -30,7 +30,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { nfc->scene_manager, NfcSceneMfClassicKeys); } else { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneStart); + nfc->scene_manager, NfcSceneFileSelect); } } } diff --git a/applications/main/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index 717e8efc4..66aaf5a26 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -34,6 +34,8 @@ void nfc_scene_extra_actions_on_enter(void* context) { SubmenuIndexMfUltralightUnlock, nfc_scene_extra_actions_submenu_callback, nfc); + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } diff --git a/applications/main/nfc/scenes/nfc_scene_set_atqa.c b/applications/main/nfc/scenes/nfc_scene_set_atqa.c index f2100aa19..d079b3804 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_atqa.c +++ b/applications/main/nfc/scenes/nfc_scene_set_atqa.c @@ -11,7 +11,7 @@ void nfc_scene_set_atqa_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter atqa in hex"); + byte_input_set_header_text(byte_input, "Enter ATQA in hex"); byte_input_set_result_callback( byte_input, nfc_scene_set_atqa_byte_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_set_sak.c b/applications/main/nfc/scenes/nfc_scene_set_sak.c index 3c88f3504..60a1e1494 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_sak.c +++ b/applications/main/nfc/scenes/nfc_scene_set_sak.c @@ -28,7 +28,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqa); consumed = true; } } diff --git a/applications/main/nfc/scenes/nfc_scene_set_uid.c b/applications/main/nfc/scenes/nfc_scene_set_uid.c index 5f0f52f6e..54606b68e 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_set_uid.c @@ -11,7 +11,7 @@ void nfc_scene_set_uid_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter uid in hex"); + byte_input_set_header_text(byte_input, "Enter UID in hex"); nfc->dev_edit_data = nfc->dev->dev_data.nfc_data; byte_input_set_result_callback( byte_input, diff --git a/applications/main/nfc/scenes/nfc_scene_start.c b/applications/main/nfc/scenes/nfc_scene_start.c index 2a116fe09..a01f871ab 100644 --- a/applications/main/nfc/scenes/nfc_scene_start.c +++ b/applications/main/nfc/scenes/nfc_scene_start.c @@ -48,11 +48,14 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexRead) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead); nfc->dev->dev_data.read_mode = NfcReadModeAuto; scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); DOLPHIN_DEED(DolphinDeedNfcRead); consumed = true; } else if(event.event == SubmenuIndexDetectReader) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader); bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK; if(sd_exist) { nfc_device_data_clear(&nfc->dev->dev_data); @@ -63,19 +66,27 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { } consumed = true; } else if(event.event == SubmenuIndexSaved) { + // Save the scene state explicitly in each branch, so that + // if the user cancels loading a file, the Saved menu item + // is properly reselected. + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved); scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect); consumed = true; } else if(event.event == SubmenuIndexExtraAction) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction); scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions); consumed = true; } else if(event.event == SubmenuIndexAddManually) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually); scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType); consumed = true; } else if(event.event == SubmenuIndexDebug) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug); scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug); consumed = true; } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event); } return consumed; } diff --git a/applications/main/subghz/scenes/subghz_scene_delete_success.c b/applications/main/subghz/scenes/subghz_scene_delete_success.c index 4f98b6a39..8a2546243 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_success.c +++ b/applications/main/subghz/scenes/subghz_scene_delete_success.c @@ -31,7 +31,10 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); } else if(scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneSaved)) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); + // Commented so that the user doesn't have to press + // back twice to get to the main SubGhz menu after + // deleting a file. + //scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); } else { scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); diff --git a/applications/plugins/nfc_magic/nfc_magic.c b/applications/plugins/nfc_magic/nfc_magic.c index e4e0ffde0..1805f35ed 100644 --- a/applications/plugins/nfc_magic/nfc_magic.c +++ b/applications/plugins/nfc_magic/nfc_magic.c @@ -136,9 +136,9 @@ void nfc_magic_free(NfcMagic* nfc_magic) { free(nfc_magic); } -static const NotificationSequence nfc_magic_sequence_blink_start_blue = { +static const NotificationSequence nfc_magic_sequence_blink_start_cyan = { &message_blink_start_10, - &message_blink_set_color_blue, + &message_blink_set_color_cyan, &message_do_not_reset, NULL, }; @@ -149,7 +149,7 @@ static const NotificationSequence nfc_magic_sequence_blink_stop = { }; void nfc_magic_blink_start(NfcMagic* nfc_magic) { - notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_blue); + notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_cyan); } void nfc_magic_blink_stop(NfcMagic* nfc_magic) { diff --git a/applications/plugins/nfc_magic/scenes/nfc_magic_scene_start.c b/applications/plugins/nfc_magic/scenes/nfc_magic_scene_start.c index f2984443f..a70eb8acc 100644 --- a/applications/plugins/nfc_magic/scenes/nfc_magic_scene_start.c +++ b/applications/plugins/nfc_magic/scenes/nfc_magic_scene_start.c @@ -40,16 +40,24 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexCheck) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); consumed = true; } else if(event.event == SubmenuIndexWriteGen1A) { + // Explicitly save state in each branch so that the + // correct option is reselected if the user cancels + // loading a file. + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); consumed = true; } else if(event.event == SubmenuIndexWipe) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); consumed = true; } - scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart, event.event); } return consumed; diff --git a/applications/plugins/picopass/picopass.c b/applications/plugins/picopass/picopass.c index e9f48b676..217f963d3 100644 --- a/applications/plugins/picopass/picopass.c +++ b/applications/plugins/picopass/picopass.c @@ -137,9 +137,9 @@ void picopass_text_store_clear(Picopass* picopass) { memset(picopass->text_store, 0, sizeof(picopass->text_store)); } -static const NotificationSequence picopass_sequence_blink_start_blue = { +static const NotificationSequence picopass_sequence_blink_start_cyan = { &message_blink_start_10, - &message_blink_set_color_blue, + &message_blink_set_color_cyan, &message_do_not_reset, NULL, }; @@ -150,7 +150,7 @@ static const NotificationSequence picopass_sequence_blink_stop = { }; void picopass_blink_start(Picopass* picopass) { - notification_message(picopass->notifications, &picopass_sequence_blink_start_blue); + notification_message(picopass->notifications, &picopass_sequence_blink_start_cyan); } void picopass_blink_stop(Picopass* picopass) { diff --git a/applications/plugins/picopass/scenes/picopass_scene_start.c b/applications/plugins/picopass/scenes/picopass_scene_start.c index 6d1aeedcd..d33a1d264 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_start.c +++ b/applications/plugins/picopass/scenes/picopass_scene_start.c @@ -32,13 +32,18 @@ bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexRead) { + scene_manager_set_scene_state( + picopass->scene_manager, PicopassSceneStart, SubmenuIndexRead); scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCard); consumed = true; } else if(event.event == SubmenuIndexSaved) { + // Explicitly save state so that the correct item is + // reselected if the user cancels loading a file. + scene_manager_set_scene_state( + picopass->scene_manager, PicopassSceneStart, SubmenuIndexSaved); scene_manager_next_scene(picopass->scene_manager, PicopassSceneFileSelect); consumed = true; } - scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneStart, event.event); } return consumed; From 23ecc186c24062002aeac5e73235b3a6c0021f77 Mon Sep 17 00:00:00 2001 From: LTVA1 <87536432+LTVA1@users.noreply.github.com> Date: Wed, 8 Feb 2023 12:26:17 +0300 Subject: [PATCH 04/34] Custom font set function (#2261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * custom font set function * update API symbols * add example of custom font usage * delete u8g2 dependency in example custom font * rename to canvas_set_custom_u8g2_font * now change the name in ALL places Co-authored-by: あく Co-authored-by: hedger --- .../debug/example_custom_font/application.fam | 9 ++ .../example_custom_font/example_custom_font.c | 98 +++++++++++++++++++ applications/services/gui/canvas.c | 6 ++ applications/services/gui/canvas.h | 7 ++ firmware/targets/f18/api_symbols.csv | 5 +- firmware/targets/f7/api_symbols.csv | 1 + 6 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 applications/debug/example_custom_font/application.fam create mode 100644 applications/debug/example_custom_font/example_custom_font.c diff --git a/applications/debug/example_custom_font/application.fam b/applications/debug/example_custom_font/application.fam new file mode 100644 index 000000000..02285b8a0 --- /dev/null +++ b/applications/debug/example_custom_font/application.fam @@ -0,0 +1,9 @@ +App( + appid="example_custom_font", + name="Example: custom font", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_custom_font_main", + requires=["gui"], + stack_size=1 * 1024, + fap_category="Debug", +) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c new file mode 100644 index 000000000..15eeb5f02 --- /dev/null +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -0,0 +1,98 @@ +#include +#include + +#include +#include + +//This arrays contains the font itself. You can use any u8g2 font you want + +/* +Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1 +Copyright: +Glyphs: 95/203 +BBX Build Mode: 0 +*/ +const uint8_t u8g2_font_tom_thumb_4x6_tr[725] = + "_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310" + "\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1" + "&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244" + "\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60" + "\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227" + "\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227" + "\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32" + "d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3" + "\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0" + "E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12" + "I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227" + "\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310" + "Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$" + "W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U" + "V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^" + "\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7" + "\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35" + "\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T" + "\1l\7\227\310\310\326\0m\7\223\310fb, 1); + u8g2_SetFont(&canvas->fb, font); +} + void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { furi_assert(canvas); if(!str) return; diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index 0b0c7e658..b2a065ca7 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -146,6 +146,13 @@ void canvas_invert_color(Canvas* canvas); */ void canvas_set_font(Canvas* canvas, Font font); +/** Set custom drawing font + * + * @param canvas Canvas instance + * @param font Pointer to u8g2 const uint8_t* font array + */ +void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font); + /** Draw string at position of baseline defined by x, y. * * @param canvas Canvas instance diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 025b605fc..d29d696fc 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.0,, +Version,+,13.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -546,6 +546,7 @@ Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" Function,+,canvas_set_color,void,"Canvas*, Color" +Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" @@ -910,7 +911,6 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* -Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" @@ -1017,6 +1017,7 @@ Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t Function,+,furi_hal_region_is_provisioned,_Bool, Function,+,furi_hal_region_set,void,FuriHalRegion* Function,-,furi_hal_resources_deinit_early,void, +Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,-,furi_hal_resources_init,void, Function,-,furi_hal_resources_init_early,void, Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime* diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 35985aebb..6456555d8 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -632,6 +632,7 @@ Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" Function,+,canvas_set_color,void,"Canvas*, Color" Function,+,canvas_set_font,void,"Canvas*, Font" +Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" Function,+,canvas_width,uint8_t,Canvas* From 00076deece707d61aed1f9cc01151b430b4f3a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Such=C3=A1nek?= Date: Wed, 8 Feb 2023 10:35:38 +0100 Subject: [PATCH 05/34] SCons: do not include backup files in build (#2221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SCons: do not include backup files in build * fbt: now GlobRecursive by default excludes backup files * fbt: added backup file exclusion to plain libs Signed-off-by: Michal Suchanek Co-authored-by: hedger Co-authored-by: hedger Co-authored-by: あく --- assets/SConscript | 4 +++- firmware.scons | 3 ++- lib/misc.scons | 8 +++++++- scripts/fbt/util.py | 4 ++++ scripts/fbt_tools/fbt_assets.py | 4 +--- scripts/fbt_tools/sconsrecursiveglob.py | 8 ++++++-- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/assets/SConscript b/assets/SConscript index ef5d83c79..21437aa30 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -78,7 +78,9 @@ if assetsenv["IS_BASE_FIRMWARE"]: resources = assetsenv.Command( "#/assets/resources/Manifest", assetsenv.GlobRecursive( - "*", assetsenv.Dir("resources").srcnode(), exclude="Manifest" + "*", + assetsenv.Dir("resources").srcnode(), + exclude=["Manifest"], ), action=Action( '${PYTHON3} "${ASSETS_COMPILER}" manifest "${TARGET.dir.posix}" --timestamp=${GIT_UNIX_TIMESTAMP}', diff --git a/firmware.scons b/firmware.scons index 92f2d1a91..a094765af 100644 --- a/firmware.scons +++ b/firmware.scons @@ -2,6 +2,7 @@ Import("ENV", "fw_build_meta") from SCons.Errors import UserError from SCons.Node import FS + import itertools from fbt_extra.util import ( @@ -171,7 +172,7 @@ sources = [apps_c] # Gather sources only from app folders in current configuration sources.extend( itertools.chain.from_iterable( - fwenv.GlobRecursive(source_type, appdir.relpath, exclude="lib") + fwenv.GlobRecursive(source_type, appdir.relpath, exclude=["lib"]) for appdir, source_type in fwenv["APPBUILD"].get_builtin_app_folders() ) ) diff --git a/lib/misc.scons b/lib/misc.scons index cd2377ceb..49b6b61d9 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -1,5 +1,7 @@ Import("env") +from fbt.util import GLOB_FILE_EXCLUSION + env.Append( CPPPATH=[ "#/lib/digital_signal", @@ -39,7 +41,11 @@ libs_plain = [ ] for lib in libs_plain: - sources += Glob(lib + "/*.c*", source=True) + sources += Glob( + lib + "/*.c*", + exclude=GLOB_FILE_EXCLUSION, + source=True, + ) lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) libenv.Install("${LIB_DIST_DIR}", lib) diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index ee7562058..7bdaea031 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -8,6 +8,10 @@ import os WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)") +# Used by default when globbing for files with GlobRecursive +# Excludes all files ending with ~, usually created by editors as backup files +GLOB_FILE_EXCLUSION = ["*~"] + def tempfile_arg_esc_func(arg): arg = quote_spaces(arg) diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index e17487358..d2a58f3fb 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -27,9 +27,7 @@ def proto_emitter(target, source, env): def dolphin_emitter(target, source, env): res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"]) source = [res_root_dir] - source.extend( - env.GlobRecursive("*.*", res_root_dir.srcnode()), - ) + source.extend(env.GlobRecursive("*.*", res_root_dir.srcnode())) target_base_dir = target[0] env.Replace(_DOLPHIN_OUT_DIR=target[0]) diff --git a/scripts/fbt_tools/sconsrecursiveglob.py b/scripts/fbt_tools/sconsrecursiveglob.py index 32ff55ea1..fbcee965b 100644 --- a/scripts/fbt_tools/sconsrecursiveglob.py +++ b/scripts/fbt_tools/sconsrecursiveglob.py @@ -1,7 +1,11 @@ import SCons +from SCons.Script import Flatten +from fbt.util import GLOB_FILE_EXCLUSION -def GlobRecursive(env, pattern, node=".", exclude=None): +def GlobRecursive(env, pattern, node=".", exclude=[]): + exclude = list(set(Flatten(exclude) + GLOB_FILE_EXCLUSION)) + # print(f"Starting glob for {pattern} from {node} (exclude: {exclude})") results = [] if isinstance(node, str): node = env.Dir(node) @@ -13,7 +17,7 @@ def GlobRecursive(env, pattern, node=".", exclude=None): source=True, exclude=exclude, ) - # print(f"Glob for {pattern} from {node}: {results}") + # print(f"Glob result for {pattern} from {node}: {results}") return results From 20f98050f2030e3a8f1509421cc43729617919b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Wed, 8 Feb 2023 19:38:09 +0900 Subject: [PATCH 06/34] Github: disable f18 build (#2375) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 080e7c2c2..a6c9219c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: pull_request: env: - TARGETS: f7 f18 + TARGETS: f7 DEFAULT_TARGET: f7 FBT_TOOLCHAIN_PATH: /runner/_work From cee9b640b30502f65ab1081134a891a1e6841343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Wed, 8 Feb 2023 20:45:33 +0900 Subject: [PATCH 07/34] Update Missing SD Card icon from PR 2373 (#2376) --- assets/icons/SDCard/SDQuestion_35x43.png | Bin 1950 -> 2042 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/icons/SDCard/SDQuestion_35x43.png b/assets/icons/SDCard/SDQuestion_35x43.png index 9b9c9a58e3257f926677533f8cc99ffb19dd74f5..257ab1d852460ad83dffa5989e765902fcb09578 100644 GIT binary patch delta 523 zcmbQo|BHWugar#T0}w3HVF!|o#X;^)4C~IxyaaMs(j9#r85lP9bN@+X1@hSfd_r9R z|NjqUh90_HH&Ic7@%uz8ezSl|hu0(V4SA9t0%7SFZhTNGdi(6U zqtX3c^NQF~FPUjxUAjEGb!OR09>>O*+iqu6ZhUtYncXoe)wdUX*U5dow13$b cea!*}8+O&+FAqd3fX-m>boFyt=akR{04GeM8vp%dtcP1$Xn~K~5UtcSa z%;J*#qDngjo1&C7tKif^yUBA|b~EXNDDla)tXmZHfpYpVNgxwl-{k*nGF%YtPKoJu zlNYnuaYJ>0`G45tb)bBg)Z*l#%z~24{5+VUK`w3}W`z~d*xb~TL_3Aaf$YNd+7>6) z0X=Zo)5S3)qV?@GZ@$9{JgkPN{;vPCYk}`2GmG;QF`|a6IRxAKa|IY)wstHrWSDT* z#4q^7^nZ)qe+@L{O>(>JubebcTr>xA;mo&QS_`}msD%H&0j`ym{bIX}= zOW&%!e!SiJ%|z?^88d$Te0N6PAoTmLgw@r0!CkAW-_AH!8nnmtgxFKVBQwS7oqSd? aS1_D$pUltxg^3;L9|liXKbLh*2~7Y$MyGH9 From 99253a0e28f45476d631ac8db8c8717d13e0bac8 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 8 Feb 2023 17:20:42 +0400 Subject: [PATCH 08/34] [FL-3093, FL-3087] SubGhz: Fix Raw write, add short duration filter setting (#2300) * SubGhz: Fix recording RAW files, sometimes could not start at a high level * SubGhz: subghz_worker, add short duration filter setting * SubGhz: capture raw timings in cli. Furi: clear pending interrupts on ISR set/reset * SubGhz: fix start duration in furi_hal_subghz_start_async_rx * [FL-3093] SubGhz: hopping issue in some regions * [FL-3087] SubGhz: fix delete-ok issue * SubGhz: remove copypasta from rx_raw cli command Co-authored-by: Aleksandr Kutuzov --- .../scenes/subghz_scene_delete_success.c | 5 -- .../scenes/subghz_scene_receiver_info.c | 15 ++++ applications/main/subghz/subghz_cli.c | 83 ++++++++++++++++++- firmware/targets/f7/api_symbols.csv | 3 +- .../targets/f7/furi_hal/furi_hal_interrupt.c | 17 ++++ .../targets/f7/furi_hal/furi_hal_subghz.c | 11 ++- lib/subghz/protocols/raw.c | 1 + lib/subghz/subghz_worker.c | 36 ++++---- lib/subghz/subghz_worker.h | 8 ++ 9 files changed, 150 insertions(+), 29 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_delete_success.c b/applications/main/subghz/scenes/subghz_scene_delete_success.c index 8a2546243..4d9f33e37 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_success.c +++ b/applications/main/subghz/scenes/subghz_scene_delete_success.c @@ -28,13 +28,8 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event if(event.event == SubGhzCustomEventSceneDeleteSuccess) { if(scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneReadRAW)) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); } else if(scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneSaved)) { - // Commented so that the user doesn't have to press - // back twice to get to the main SubGhz menu after - // deleting a file. - //scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); } else { scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index c0f901578..4733b0e1d 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -129,6 +129,21 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) subghz_history_get_raw_data( subghz->txrx->history, subghz->txrx->idx_menu_chosen))) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) { + subghz_begin( + subghz, + subghz_setting_get_preset_data_by_name( + subghz->setting, + furi_string_get_cstr(subghz->txrx->preset->name))); + subghz_rx(subghz, subghz->txrx->preset->frequency); + } + if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { + subghz->txrx->hopper_state = SubGhzHopperStateRunnig; + } + subghz->state_notifications = SubGhzNotificationStateRx; } else { subghz->state_notifications = SubGhzNotificationStateTx; } diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 536cb535e..9271443a8 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -309,6 +309,81 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { free(instance); } +void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { + UNUSED(context); + uint32_t frequency = 433920000; + + if(furi_string_size(args)) { + int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency); + if(ret != 1) { + printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); + cli_print_usage("subghz rx", "", furi_string_get_cstr(args)); + return; + } + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + printf( + "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n", + frequency); + return; + } + } + + // Allocate context and buffers + SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx)); + instance->stream = + furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); + furi_check(instance->stream); + + // Configure radio + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async); + frequency = furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + + furi_hal_power_suppress_charge_enter(); + + // Prepare and start RX + furi_hal_subghz_start_async_rx(subghz_cli_command_rx_capture_callback, instance); + + // Wait for packets to arrive + printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); + LevelDuration level_duration; + size_t counter = 0; + while(!cli_cmd_interrupt_received(cli)) { + int ret = furi_stream_buffer_receive( + instance->stream, &level_duration, sizeof(LevelDuration), 10); + if(ret == 0) { + continue; + } + if(ret != sizeof(LevelDuration)) { + puts("stream corrupt"); + break; + } + if(level_duration_is_reset(level_duration)) { + puts(". "); + } else { + bool level = level_duration_get_level(level_duration); + uint32_t duration = level_duration_get_duration(level_duration); + printf("%c%lu ", level ? '+' : '-', duration); + } + furi_thread_stdout_flush(); + counter++; + if(counter > 255) { + puts("\r\n"); + counter = 0; + } + } + + // Shutdown radio + furi_hal_subghz_stop_async_rx(); + furi_hal_subghz_sleep(); + + furi_hal_power_suppress_charge_exit(); + + // Cleanup + furi_stream_buffer_free(instance->stream); + free(instance); +} void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { UNUSED(context); FuriString* file_name; @@ -431,7 +506,8 @@ static void subghz_cli_command_print_usage() { printf("\tchat \t - Chat with other Flippers\r\n"); printf( "\ttx <3 byte Key: in hex> \t - Transmitting key\r\n"); - printf("\trx \t - Reception key\r\n"); + printf("\trx \t - Receive\r\n"); + printf("\trx_raw \t - Receive RAW\r\n"); printf("\tdecode_raw \t - Testing\r\n"); if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { @@ -733,6 +809,11 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { break; } + if(furi_string_cmp_str(cmd, "rx_raw") == 0) { + subghz_cli_command_rx_raw(cli, args, context); + break; + } + if(furi_string_cmp_str(cmd, "decode_raw") == 0) { subghz_cli_command_decode_raw(cli, args, context); break; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 6456555d8..65ab375ef 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.0,, +Version,+,13.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2675,6 +2675,7 @@ Function,+,subghz_worker_free,void,SubGhzWorker* Function,+,subghz_worker_is_running,_Bool,SubGhzWorker* Function,+,subghz_worker_rx_callback,void,"_Bool, uint32_t, void*" Function,+,subghz_worker_set_context,void,"SubGhzWorker*, void*" +Function,+,subghz_worker_set_filter,void,"SubGhzWorker*, uint16_t" Function,+,subghz_worker_set_overrun_callback,void,"SubGhzWorker*, SubGhzWorkerOverrunCallback" Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPairCallback" Function,+,subghz_worker_start,void,SubGhzWorker* diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c index 1b1132d0c..b5639d230 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c @@ -74,6 +74,21 @@ __attribute__((always_inline)) static inline void NVIC_EnableIRQ(furi_hal_interrupt_irqn[index]); } +__attribute__((always_inline)) static inline void + furi_hal_interrupt_clear_pending(FuriHalInterruptId index) { + NVIC_ClearPendingIRQ(furi_hal_interrupt_irqn[index]); +} + +__attribute__((always_inline)) static inline void + furi_hal_interrupt_get_pending(FuriHalInterruptId index) { + NVIC_GetPendingIRQ(furi_hal_interrupt_irqn[index]); +} + +__attribute__((always_inline)) static inline void + furi_hal_interrupt_set_pending(FuriHalInterruptId index) { + NVIC_SetPendingIRQ(furi_hal_interrupt_irqn[index]); +} + __attribute__((always_inline)) static inline void furi_hal_interrupt_disable(FuriHalInterruptId index) { NVIC_DisableIRQ(furi_hal_interrupt_irqn[index]); @@ -123,6 +138,7 @@ void furi_hal_interrupt_set_isr_ex( // Pre ISR clear furi_assert(furi_hal_interrupt_isr[index].isr != NULL); furi_hal_interrupt_disable(index); + furi_hal_interrupt_clear_pending(index); } furi_hal_interrupt_isr[index].isr = isr; @@ -131,6 +147,7 @@ void furi_hal_interrupt_set_isr_ex( if(isr) { // Post ISR set + furi_hal_interrupt_clear_pending(index); furi_hal_interrupt_enable(index, priority); } else { // Post ISR clear diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index a6d275308..596464613 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -438,7 +438,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 0x7FFFFFFE; - TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter LL_TIM_Init(TIM2, &TIM_InitStruct); // Timer: advanced @@ -455,13 +455,15 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI); LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING); - LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1); // Timer: channel 2 direct LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI); LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING); - LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8); + LL_TIM_IC_SetFilter( + TIM2, + LL_TIM_CHANNEL_CH2, + LL_TIM_IC_FILTER_FDIV32_N8); // Capture filter: 1/(64000000/64/4/32*8) = 16us // ISR setup furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL); @@ -481,6 +483,9 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // Switch to RX furi_hal_subghz_rx(); + + //Clear the variable after the end of the session + furi_hal_subghz_capture_delta_duration = 0; } void furi_hal_subghz_stop_async_rx() { diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index b639c93b9..ac3492e78 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -159,6 +159,7 @@ bool subghz_protocol_raw_save_to_file_init( instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t)); instance->file_is_open = RAWFileIsOpenWrite; instance->sample_write = 0; + instance->last_level = false; instance->pause = false; init = true; } while(0); diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 35e399885..50b5aba51 100644 --- a/lib/subghz/subghz_worker.c +++ b/lib/subghz/subghz_worker.c @@ -12,7 +12,6 @@ struct SubGhzWorker { volatile bool overrun; LevelDuration filter_level_duration; - bool filter_running; uint16_t filter_duration; SubGhzWorkerOverrunCallback overrun_callback; @@ -59,24 +58,19 @@ static int32_t subghz_worker_thread_callback(void* context) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); - if(instance->filter_running) { - if((duration < instance->filter_duration) || - (instance->filter_level_duration.level == level)) { - instance->filter_level_duration.duration += duration; + if((duration < instance->filter_duration) || + (instance->filter_level_duration.level == level)) { + instance->filter_level_duration.duration += duration; - } else if(instance->filter_level_duration.level != level) { - if(instance->pair_callback) - instance->pair_callback( - instance->context, - instance->filter_level_duration.level, - instance->filter_level_duration.duration); - - instance->filter_level_duration.duration = duration; - instance->filter_level_duration.level = level; - } - } else { + } else if(instance->filter_level_duration.level != level) { if(instance->pair_callback) - instance->pair_callback(instance->context, level, duration); + instance->pair_callback( + instance->context, + instance->filter_level_duration.level, + instance->filter_level_duration.duration); + + instance->filter_level_duration.duration = duration; + instance->filter_level_duration.level = level; } } } @@ -94,8 +88,7 @@ SubGhzWorker* subghz_worker_alloc() { instance->stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 4096, sizeof(LevelDuration)); - //setting filter - instance->filter_running = true; + //setting default filter in us instance->filter_duration = 30; return instance; @@ -149,3 +142,8 @@ bool subghz_worker_is_running(SubGhzWorker* instance) { furi_assert(instance); return instance->running; } + +void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout) { + furi_assert(instance); + instance->filter_duration = timeout; +} \ No newline at end of file diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index f85b1fdc7..657278f50 100644 --- a/lib/subghz/subghz_worker.h +++ b/lib/subghz/subghz_worker.h @@ -67,6 +67,14 @@ void subghz_worker_stop(SubGhzWorker* instance); */ bool subghz_worker_is_running(SubGhzWorker* instance); +/** + * Short duration filter setting. + * glues short durations into 1. The default setting is 30 us, if set to 0 the filter will be disabled + * @param instance Pointer to a SubGhzWorker instance + * @param timeout time in us + */ +void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout); + #ifdef __cplusplus } #endif From b1f581239bbc83af1720e7180e6bf4a7c319288e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:01:00 +0300 Subject: [PATCH 09/34] BadUSB: Keyboard Layouts (#2256) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * BadUSB: Keyboard Layouts * Apply requested changes pt1 * Add layout file check when we loading config Co-authored-by: Nikolay Minaylov Co-authored-by: あく --- applications/main/bad_usb/bad_usb_app.c | 72 +++++++++++++- applications/main/bad_usb/bad_usb_app_i.h | 11 ++- applications/main/bad_usb/bad_usb_script.c | 51 ++++++++-- applications/main/bad_usb/bad_usb_script.h | 2 + .../main/bad_usb/bad_usb_settings_filename.h | 3 + .../bad_usb/scenes/bad_usb_scene_config.c | 53 ++++++++++ .../bad_usb/scenes/bad_usb_scene_config.h | 2 + .../scenes/bad_usb_scene_config_layout.c | 50 ++++++++++ .../scenes/bad_usb_scene_file_select.c | 14 ++- .../main/bad_usb/scenes/bad_usb_scene_work.c | 27 ++++-- .../main/bad_usb/views/bad_usb_view.c | 91 ++++++++++++------ .../main/bad_usb/views/bad_usb_view.h | 6 +- assets/icons/Archive/keyboard_10px.png | Bin 0 -> 147 bytes .../resources/badusb/assets/layouts/ba-BA.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/cz_CS.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/da-DA.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/de-CH.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/de-DE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/dvorak.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/en-UK.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/en-US.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/es-ES.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-BE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-CH.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-FR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/hr-HR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/hu-HU.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/it-IT.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/nb-NO.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/nl-NL.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/pt-BR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/pt-PT.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/si-SI.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/sk-SK.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/sv-SE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/tr-TR.kl | Bin 0 -> 256 bytes 36 files changed, 323 insertions(+), 59 deletions(-) create mode 100644 applications/main/bad_usb/bad_usb_settings_filename.h create mode 100644 applications/main/bad_usb/scenes/bad_usb_scene_config.c create mode 100644 applications/main/bad_usb/scenes/bad_usb_scene_config_layout.c create mode 100644 assets/icons/Archive/keyboard_10px.png create mode 100644 assets/resources/badusb/assets/layouts/ba-BA.kl create mode 100644 assets/resources/badusb/assets/layouts/cz_CS.kl create mode 100644 assets/resources/badusb/assets/layouts/da-DA.kl create mode 100644 assets/resources/badusb/assets/layouts/de-CH.kl create mode 100644 assets/resources/badusb/assets/layouts/de-DE.kl create mode 100644 assets/resources/badusb/assets/layouts/dvorak.kl create mode 100644 assets/resources/badusb/assets/layouts/en-UK.kl create mode 100644 assets/resources/badusb/assets/layouts/en-US.kl create mode 100644 assets/resources/badusb/assets/layouts/es-ES.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-BE.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-CH.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-FR.kl create mode 100644 assets/resources/badusb/assets/layouts/hr-HR.kl create mode 100644 assets/resources/badusb/assets/layouts/hu-HU.kl create mode 100644 assets/resources/badusb/assets/layouts/it-IT.kl create mode 100644 assets/resources/badusb/assets/layouts/nb-NO.kl create mode 100644 assets/resources/badusb/assets/layouts/nl-NL.kl create mode 100644 assets/resources/badusb/assets/layouts/pt-BR.kl create mode 100644 assets/resources/badusb/assets/layouts/pt-PT.kl create mode 100644 assets/resources/badusb/assets/layouts/si-SI.kl create mode 100755 assets/resources/badusb/assets/layouts/sk-SK.kl create mode 100644 assets/resources/badusb/assets/layouts/sv-SE.kl create mode 100644 assets/resources/badusb/assets/layouts/tr-TR.kl diff --git a/applications/main/bad_usb/bad_usb_app.c b/applications/main/bad_usb/bad_usb_app.c index 6fd29cd70..5f2aa4789 100644 --- a/applications/main/bad_usb/bad_usb_app.c +++ b/applications/main/bad_usb/bad_usb_app.c @@ -1,9 +1,12 @@ #include "bad_usb_app_i.h" +#include "bad_usb_settings_filename.h" #include #include #include #include +#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/" BAD_USB_SETTINGS_FILE_NAME + static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); BadUsbApp* app = context; @@ -22,15 +25,62 @@ static void bad_usb_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } +static void bad_usb_load_settings(BadUsbApp* app) { + File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); + if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { + char chr; + while((storage_file_read(settings_file, &chr, 1) == 1) && + !storage_file_eof(settings_file) && !isspace(chr)) { + furi_string_push_back(app->keyboard_layout, chr); + } + } else { + furi_string_reset(app->keyboard_layout); + } + storage_file_close(settings_file); + storage_file_free(settings_file); + + if(!furi_string_empty(app->keyboard_layout)) { + Storage* fs_api = furi_record_open(RECORD_STORAGE); + FileInfo layout_file_info; + FS_Error file_check_err = storage_common_stat( + fs_api, furi_string_get_cstr(app->keyboard_layout), &layout_file_info); + furi_record_close(RECORD_STORAGE); + if(file_check_err != FSE_OK) { + furi_string_reset(app->keyboard_layout); + return; + } + if(layout_file_info.size != 256) { + furi_string_reset(app->keyboard_layout); + } + } +} + +static void bad_usb_save_settings(BadUsbApp* app) { + File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); + if(storage_file_open(settings_file, BAD_USB_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) { + storage_file_write( + settings_file, + furi_string_get_cstr(app->keyboard_layout), + furi_string_size(app->keyboard_layout)); + storage_file_write(settings_file, "\n", 1); + } + storage_file_close(settings_file); + storage_file_free(settings_file); +} + BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* app = malloc(sizeof(BadUsbApp)); - app->file_path = furi_string_alloc(); + app->bad_usb_script = NULL; + app->file_path = furi_string_alloc(); + app->keyboard_layout = furi_string_alloc(); if(arg && strlen(arg)) { furi_string_set(app->file_path, arg); } + bad_usb_load_settings(app); + app->gui = furi_record_open(RECORD_GUI); app->notifications = furi_record_open(RECORD_NOTIFICATION); app->dialogs = furi_record_open(RECORD_DIALOGS); @@ -53,6 +103,10 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { view_dispatcher_add_view( app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget)); + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BadUsbAppViewConfig, submenu_get_view(app->submenu)); + app->bad_usb_view = bad_usb_alloc(); view_dispatcher_add_view( app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); @@ -64,9 +118,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { scene_manager_next_scene(app->scene_manager, BadUsbSceneError); } else { if(!furi_string_empty(app->file_path)) { + app->bad_usb_script = bad_usb_script_open(app->file_path); + bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout); scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); } else { - furi_string_set(app->file_path, BAD_USB_APP_PATH_FOLDER); + furi_string_set(app->file_path, BAD_USB_APP_BASE_FOLDER); scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); } } @@ -77,6 +133,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { void bad_usb_app_free(BadUsbApp* app) { furi_assert(app); + if(app->bad_usb_script) { + bad_usb_script_close(app->bad_usb_script); + app->bad_usb_script = NULL; + } + // Views view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); bad_usb_free(app->bad_usb_view); @@ -85,6 +146,10 @@ void bad_usb_app_free(BadUsbApp* app) { view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError); widget_free(app->widget); + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig); + submenu_free(app->submenu); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); @@ -94,7 +159,10 @@ void bad_usb_app_free(BadUsbApp* app) { furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_DIALOGS); + bad_usb_save_settings(app); + furi_string_free(app->file_path); + furi_string_free(app->keyboard_layout); free(app); } diff --git a/applications/main/bad_usb/bad_usb_app_i.h b/applications/main/bad_usb/bad_usb_app_i.h index f333c36d8..1bd1964c8 100644 --- a/applications/main/bad_usb/bad_usb_app_i.h +++ b/applications/main/bad_usb/bad_usb_app_i.h @@ -15,8 +15,10 @@ #include #include "views/bad_usb_view.h" -#define BAD_USB_APP_PATH_FOLDER ANY_PATH("badusb") -#define BAD_USB_APP_EXTENSION ".txt" +#define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb") +#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts" +#define BAD_USB_APP_SCRIPT_EXTENSION ".txt" +#define BAD_USB_APP_LAYOUT_EXTENSION ".kl" typedef enum { BadUsbAppErrorNoFiles, @@ -30,9 +32,11 @@ struct BadUsbApp { NotificationApp* notifications; DialogsApp* dialogs; Widget* widget; + Submenu* submenu; BadUsbAppError error; FuriString* file_path; + FuriString* keyboard_layout; BadUsb* bad_usb_view; BadUsbScript* bad_usb_script; }; @@ -40,4 +44,5 @@ struct BadUsbApp { typedef enum { BadUsbAppViewError, BadUsbAppViewWork, -} BadUsbAppView; + BadUsbAppViewConfig, +} BadUsbAppView; \ No newline at end of file diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index e2281133f..1416acfee 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -16,6 +16,9 @@ #define SCRIPT_STATE_END (-2) #define SCRIPT_STATE_NEXT_LINE (-3) +#define BADUSB_ASCII_TO_KEY(script, x) \ + (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) + typedef enum { WorkerEvtToggle = (1 << 0), WorkerEvtEnd = (1 << 1), @@ -28,6 +31,7 @@ struct BadUsbScript { BadUsbState st; FuriString* file_path; uint32_t defdelay; + uint16_t layout[128]; FuriThread* thread; uint8_t file_buf[FILE_BUFFER_LEN + 1]; uint8_t buf_start; @@ -205,10 +209,10 @@ static bool ducky_altstring(const char* param) { return state; } -static bool ducky_string(const char* param) { +static bool ducky_string(BadUsbScript* bad_usb, const char* param) { uint32_t i = 0; while(param[i] != '\0') { - uint16_t keycode = HID_ASCII_TO_KEY(param[i]); + uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_usb, param[i]); if(keycode != HID_KEYBOARD_NONE) { furi_hal_hid_kb_press(keycode); furi_hal_hid_kb_release(keycode); @@ -218,7 +222,7 @@ static bool ducky_string(const char* param) { return true; } -static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { +static uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) { for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { size_t key_cmd_len = strlen(ducky_keys[i].name); if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && @@ -227,7 +231,7 @@ static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { } } if((accept_chars) && (strlen(param) > 0)) { - return (HID_ASCII_TO_KEY(param[0]) & 0xFF); + return (BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF); } return 0; } @@ -276,7 +280,7 @@ static int32_t } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) { // STRING line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; - state = ducky_string(line_tmp); + state = ducky_string(bad_usb, line_tmp); if(!state && error != NULL) { snprintf(error, error_len, "Invalid string %s", line_tmp); } @@ -312,14 +316,14 @@ static int32_t } else if(strncmp(line_tmp, ducky_cmd_sysrq, strlen(ducky_cmd_sysrq)) == 0) { // SYSRQ line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; - uint16_t key = ducky_get_keycode(line_tmp, true); + uint16_t key = ducky_get_keycode(bad_usb, line_tmp, true); furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); furi_hal_hid_kb_press(key); furi_hal_hid_kb_release_all(); return (0); } else { // Special keys + modifiers - uint16_t key = ducky_get_keycode(line_tmp, false); + uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false); if(key == HID_KEYBOARD_NONE) { if(error != NULL) { snprintf(error, error_len, "No keycode defined for %s", line_tmp); @@ -329,7 +333,7 @@ static int32_t if((key & 0xFF00) != 0) { // It's a modifier key line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; - key |= ducky_get_keycode(line_tmp, true); + key |= ducky_get_keycode(bad_usb, line_tmp, true); } furi_hal_hid_kb_press(key); furi_hal_hid_kb_release(key); @@ -650,12 +654,19 @@ static int32_t bad_usb_worker(void* context) { return 0; } +static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) { + furi_assert(bad_usb); + memset(bad_usb->layout, HID_KEYBOARD_NONE, sizeof(bad_usb->layout)); + memcpy(bad_usb->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_usb->layout))); +} + BadUsbScript* bad_usb_script_open(FuriString* file_path) { furi_assert(file_path); BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); bad_usb->file_path = furi_string_alloc(); furi_string_set(bad_usb->file_path, file_path); + bad_usb_script_set_default_keyboard_layout(bad_usb); bad_usb->st.state = BadUsbStateInit; bad_usb->st.error[0] = '\0'; @@ -674,6 +685,30 @@ void bad_usb_script_close(BadUsbScript* bad_usb) { free(bad_usb); } +void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layout_path) { + furi_assert(bad_usb); + + if((bad_usb->st.state == BadUsbStateRunning) || (bad_usb->st.state == BadUsbStateDelay)) { + // do not update keyboard layout while a script is running + return; + } + + File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); + if(!furi_string_empty(layout_path)) { + if(storage_file_open( + layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) { + uint16_t layout[128]; + if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) { + memcpy(bad_usb->layout, layout, sizeof(layout)); + } + } + storage_file_close(layout_file); + } else { + bad_usb_script_set_default_keyboard_layout(bad_usb); + } + storage_file_free(layout_file); +} + void bad_usb_script_toggle(BadUsbScript* bad_usb) { furi_assert(bad_usb); furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle); diff --git a/applications/main/bad_usb/bad_usb_script.h b/applications/main/bad_usb/bad_usb_script.h index 188142db8..1e4d98fe7 100644 --- a/applications/main/bad_usb/bad_usb_script.h +++ b/applications/main/bad_usb/bad_usb_script.h @@ -33,6 +33,8 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path); void bad_usb_script_close(BadUsbScript* bad_usb); +void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layout_path); + void bad_usb_script_start(BadUsbScript* bad_usb); void bad_usb_script_stop(BadUsbScript* bad_usb); diff --git a/applications/main/bad_usb/bad_usb_settings_filename.h b/applications/main/bad_usb/bad_usb_settings_filename.h new file mode 100644 index 000000000..12ba8f31c --- /dev/null +++ b/applications/main/bad_usb/bad_usb_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define BAD_USB_SETTINGS_FILE_NAME ".badusb.settings" diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config.c b/applications/main/bad_usb/scenes/bad_usb_scene_config.c new file mode 100644 index 000000000..2a9f2f76c --- /dev/null +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config.c @@ -0,0 +1,53 @@ +#include "../bad_usb_app_i.h" +#include "furi_hal_power.h" +#include "furi_hal_usb.h" + +enum SubmenuIndex { + SubmenuIndexKeyboardLayout, +}; + +void bad_usb_scene_config_submenu_callback(void* context, uint32_t index) { + BadUsbApp* bad_usb = context; + view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index); +} + +void bad_usb_scene_config_on_enter(void* context) { + BadUsbApp* bad_usb = context; + Submenu* submenu = bad_usb->submenu; + + submenu_add_item( + submenu, + "Keyboard layout", + SubmenuIndexKeyboardLayout, + bad_usb_scene_config_submenu_callback, + bad_usb); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(bad_usb->scene_manager, BadUsbSceneConfig)); + + view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfig); +} + +bool bad_usb_scene_config_on_event(void* context, SceneManagerEvent event) { + BadUsbApp* bad_usb = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfig, event.event); + consumed = true; + if(event.event == SubmenuIndexKeyboardLayout) { + scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout); + } else { + furi_crash("Unknown key type"); + } + } + + return consumed; +} + +void bad_usb_scene_config_on_exit(void* context) { + BadUsbApp* bad_usb = context; + Submenu* submenu = bad_usb->submenu; + + submenu_reset(submenu); +} diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config.h b/applications/main/bad_usb/scenes/bad_usb_scene_config.h index 0ab8f54f8..423aedc51 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_config.h +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config.h @@ -1,3 +1,5 @@ ADD_SCENE(bad_usb, file_select, FileSelect) ADD_SCENE(bad_usb, work, Work) ADD_SCENE(bad_usb, error, Error) +ADD_SCENE(bad_usb, config, Config) +ADD_SCENE(bad_usb, config_layout, ConfigLayout) diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config_layout.c b/applications/main/bad_usb/scenes/bad_usb_scene_config_layout.c new file mode 100644 index 000000000..7708ed1d8 --- /dev/null +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config_layout.c @@ -0,0 +1,50 @@ +#include "../bad_usb_app_i.h" +#include "furi_hal_power.h" +#include "furi_hal_usb.h" +#include + +static bool bad_usb_layout_select(BadUsbApp* bad_usb) { + furi_assert(bad_usb); + + FuriString* predefined_path; + predefined_path = furi_string_alloc(); + if(!furi_string_empty(bad_usb->keyboard_layout)) { + furi_string_set(predefined_path, bad_usb->keyboard_layout); + } else { + furi_string_set(predefined_path, BAD_USB_APP_PATH_LAYOUT_FOLDER); + } + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options( + &browser_options, BAD_USB_APP_LAYOUT_EXTENSION, &I_keyboard_10px); + browser_options.base_path = BAD_USB_APP_PATH_LAYOUT_FOLDER; + browser_options.skip_assets = false; + + // Input events and views are managed by file_browser + bool res = dialog_file_browser_show( + bad_usb->dialogs, bad_usb->keyboard_layout, predefined_path, &browser_options); + + furi_string_free(predefined_path); + return res; +} + +void bad_usb_scene_config_layout_on_enter(void* context) { + BadUsbApp* bad_usb = context; + + if(bad_usb_layout_select(bad_usb)) { + bad_usb_script_set_keyboard_layout(bad_usb->bad_usb_script, bad_usb->keyboard_layout); + } + scene_manager_previous_scene(bad_usb->scene_manager); +} + +bool bad_usb_scene_config_layout_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + // BadUsbApp* bad_usb = context; + return false; +} + +void bad_usb_scene_config_layout_on_exit(void* context) { + UNUSED(context); + // BadUsbApp* bad_usb = context; +} diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c index f1f34f5bc..b04669252 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c @@ -7,8 +7,10 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) { furi_assert(bad_usb); DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, BAD_USB_APP_EXTENSION, &I_badusb_10px); - browser_options.base_path = BAD_USB_APP_PATH_FOLDER; + dialog_file_browser_set_basic_options( + &browser_options, BAD_USB_APP_SCRIPT_EXTENSION, &I_badusb_10px); + browser_options.base_path = BAD_USB_APP_BASE_FOLDER; + browser_options.skip_assets = true; // Input events and views are managed by file_browser bool res = dialog_file_browser_show( @@ -21,12 +23,18 @@ void bad_usb_scene_file_select_on_enter(void* context) { BadUsbApp* bad_usb = context; furi_hal_usb_disable(); + if(bad_usb->bad_usb_script) { + bad_usb_script_close(bad_usb->bad_usb_script); + bad_usb->bad_usb_script = NULL; + } if(bad_usb_file_select(bad_usb)) { + bad_usb->bad_usb_script = bad_usb_script_open(bad_usb->file_path); + bad_usb_script_set_keyboard_layout(bad_usb->bad_usb_script, bad_usb->keyboard_layout); + scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork); } else { furi_hal_usb_enable(); - //scene_manager_previous_scene(bad_usb->scene_manager); view_dispatcher_stop(bad_usb->view_dispatcher); } } diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_work.c b/applications/main/bad_usb/scenes/bad_usb_scene_work.c index 1e3534822..187b83bd9 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_work.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_work.c @@ -4,10 +4,10 @@ #include #include "toolbox/path.h" -void bad_usb_scene_work_ok_callback(InputType type, void* context) { +void bad_usb_scene_work_button_callback(InputKey key, void* context) { furi_assert(context); BadUsbApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, type); + view_dispatcher_send_custom_event(app->view_dispatcher, key); } bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { @@ -15,8 +15,13 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - bad_usb_script_toggle(app->bad_usb_script); - consumed = true; + if(event.event == InputKeyLeft) { + scene_manager_next_scene(app->scene_manager, BadUsbSceneConfig); + consumed = true; + } else if(event.event == InputKeyOk) { + bad_usb_script_toggle(app->bad_usb_script); + consumed = true; + } } else if(event.type == SceneManagerEventTypeTick) { bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); } @@ -28,20 +33,22 @@ void bad_usb_scene_work_on_enter(void* context) { FuriString* file_name; file_name = furi_string_alloc(); - path_extract_filename(app->file_path, file_name, true); bad_usb_set_file_name(app->bad_usb_view, furi_string_get_cstr(file_name)); - app->bad_usb_script = bad_usb_script_open(app->file_path); - furi_string_free(file_name); + FuriString* layout; + layout = furi_string_alloc(); + path_extract_filename(app->keyboard_layout, layout, true); + bad_usb_set_layout(app->bad_usb_view, furi_string_get_cstr(layout)); + furi_string_free(layout); + bad_usb_set_state(app->bad_usb_view, bad_usb_script_get_state(app->bad_usb_script)); - bad_usb_set_ok_callback(app->bad_usb_view, bad_usb_scene_work_ok_callback, app); + bad_usb_set_button_callback(app->bad_usb_view, bad_usb_scene_work_button_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewWork); } void bad_usb_scene_work_on_exit(void* context) { - BadUsbApp* app = context; - bad_usb_script_close(app->bad_usb_script); + UNUSED(context); } diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index b3eb9bb56..bb9dc3b7e 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -1,5 +1,6 @@ #include "bad_usb_view.h" #include "../bad_usb_script.h" +#include #include #include @@ -7,12 +8,13 @@ struct BadUsb { View* view; - BadUsbOkCallback callback; + BadUsbButtonCallback callback; void* context; }; typedef struct { char file_name[MAX_NAME_LEN]; + char layout[MAX_NAME_LEN]; BadUsbState state; uint8_t anim_frame; } BadUsbModel; @@ -25,9 +27,23 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { elements_string_fit_width(canvas, disp_str, 128 - 2); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str)); + + if(strlen(model->layout) == 0) { + furi_string_set(disp_str, "(default)"); + } else { + furi_string_reset(disp_str); + furi_string_push_back(disp_str, '('); + for(size_t i = 0; i < strlen(model->layout); i++) + furi_string_push_back(disp_str, model->layout[i]); + furi_string_push_back(disp_str, ')'); + } + elements_string_fit_width(canvas, disp_str, 128 - 2); + canvas_draw_str( + canvas, 2, 8 + canvas_current_font_height(canvas), furi_string_get_cstr(disp_str)); + furi_string_reset(disp_str); - canvas_draw_icon(canvas, 22, 20, &I_UsbTree_48x22); + canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22); if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) || (model->state.state == BadUsbStateNotConnected)) { @@ -38,23 +54,28 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { elements_button_center(canvas, "Cancel"); } + if((model->state.state == BadUsbStateNotConnected) || + (model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone)) { + elements_button_left(canvas, "Config"); + } + if(model->state.state == BadUsbStateNotConnected) { - canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Connect"); - canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "to USB"); + canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect"); + canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB"); } else if(model->state.state == BadUsbStateWillRun) { - canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "Will run"); - canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "on connect"); + canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); + canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); } else if(model->state.state == BadUsbStateFileError) { - canvas_draw_icon(canvas, 4, 22, &I_Error_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 127, 27, AlignRight, AlignBottom, "File"); - canvas_draw_str_aligned(canvas, 127, 39, AlignRight, AlignBottom, "ERROR"); + canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File"); + canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR"); } else if(model->state.state == BadUsbStateScriptError) { - canvas_draw_icon(canvas, 4, 22, &I_Error_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Error_18x18); canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:"); canvas_set_font(canvas, FontSecondary); @@ -64,49 +85,49 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { furi_string_reset(disp_str); canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error); } else if(model->state.state == BadUsbStateIdle) { - canvas_draw_icon(canvas, 4, 22, &I_Smile_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18); canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "0"); - canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); + canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0"); + canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); } else if(model->state.state == BadUsbStateRunning) { if(model->anim_frame == 0) { - canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); + canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); } else { - canvas_draw_icon(canvas, 4, 19, &I_EviSmile2_18x21); + canvas_draw_icon(canvas, 4, 23, &I_EviSmile2_18x21); } canvas_set_font(canvas, FontBigNumbers); furi_string_printf( disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); canvas_draw_str_aligned( - canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); + canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); } else if(model->state.state == BadUsbStateDone) { - canvas_draw_icon(canvas, 4, 19, &I_EviSmile1_18x21); + canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21); canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 114, 36, AlignRight, AlignBottom, "100"); + canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100"); furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); + canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); } else if(model->state.state == BadUsbStateDelay) { if(model->anim_frame == 0) { - canvas_draw_icon(canvas, 4, 19, &I_EviWaiting1_18x21); + canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21); } else { - canvas_draw_icon(canvas, 4, 19, &I_EviWaiting2_18x21); + canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21); } canvas_set_font(canvas, FontBigNumbers); furi_string_printf( disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb); canvas_draw_str_aligned( - canvas, 114, 36, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); furi_string_reset(disp_str); - canvas_draw_icon(canvas, 117, 22, &I_Percent_10x14); + canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14); canvas_set_font(canvas, FontSecondary); furi_string_printf(disp_str, "delay %lus", model->state.delay_remain); canvas_draw_str_aligned( - canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); + canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); furi_string_reset(disp_str); } else { - canvas_draw_icon(canvas, 4, 22, &I_Clock_18x18); + canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); } furi_string_free(disp_str); @@ -118,10 +139,10 @@ static bool bad_usb_input_callback(InputEvent* event, void* context) { bool consumed = false; if(event->type == InputTypeShort) { - if(event->key == InputKeyOk) { + if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) { consumed = true; furi_assert(bad_usb->callback); - bad_usb->callback(InputTypeShort, bad_usb->context); + bad_usb->callback(event->key, bad_usb->context); } } @@ -151,7 +172,7 @@ View* bad_usb_get_view(BadUsb* bad_usb) { return bad_usb->view; } -void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context) { +void bad_usb_set_button_callback(BadUsb* bad_usb, BadUsbButtonCallback callback, void* context) { furi_assert(bad_usb); furi_assert(callback); with_view_model( @@ -174,6 +195,14 @@ void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { true); } +void bad_usb_set_layout(BadUsb* bad_usb, const char* layout) { + furi_assert(layout); + with_view_model( + bad_usb->view, + BadUsbModel * model, + { strlcpy(model->layout, layout, MAX_NAME_LEN); }, + true); +} void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { furi_assert(st); with_view_model( diff --git a/applications/main/bad_usb/views/bad_usb_view.h b/applications/main/bad_usb/views/bad_usb_view.h index 80a47e2ca..8447fb055 100644 --- a/applications/main/bad_usb/views/bad_usb_view.h +++ b/applications/main/bad_usb/views/bad_usb_view.h @@ -4,7 +4,7 @@ #include "../bad_usb_script.h" typedef struct BadUsb BadUsb; -typedef void (*BadUsbOkCallback)(InputType type, void* context); +typedef void (*BadUsbButtonCallback)(InputKey key, void* context); BadUsb* bad_usb_alloc(); @@ -12,8 +12,10 @@ void bad_usb_free(BadUsb* bad_usb); View* bad_usb_get_view(BadUsb* bad_usb); -void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context); +void bad_usb_set_button_callback(BadUsb* bad_usb, BadUsbButtonCallback callback, void* context); void bad_usb_set_file_name(BadUsb* bad_usb, const char* name); +void bad_usb_set_layout(BadUsb* bad_usb, const char* layout); + void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st); diff --git a/assets/icons/Archive/keyboard_10px.png b/assets/icons/Archive/keyboard_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..74a10e6db2e784486a6781c0db8346373b9c7409 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xGmzZ=C-xtZVhivIasB`QKad%E=yDy9;wgN=z( mnGc5;aHhO3XW%q4U|?wcz_Hx?k)a$=ErX}4pUXO@geCyYPARJZ literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/ba-BA.kl b/assets/resources/badusb/assets/layouts/ba-BA.kl new file mode 100644 index 0000000000000000000000000000000000000000..379f6c649c98ef7f38df9c6d1c2b1588167ee46a GIT binary patch literal 256 zcmaLL%XYy47y#ipa|DTNh+7ar(9@P>V)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHkcVK4j(2-*&PMujecVX$$ zm1{Rv)^6RqGmA3vIK<6U^hikQGaw^p$cQl$rpzdqv!GYm`cD?ePm*T4GZVB*m| zTln^pGi$gvZr&YZh&>B_Ym yx9;4VM-@dp{CKxUod!)>wCT{LN1p*hMvR#-WyYKZOIEDeuw}=dEbdXpBj69fFAeVi literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/de-CH.kl b/assets/resources/badusb/assets/layouts/de-CH.kl new file mode 100644 index 0000000000000000000000000000000000000000..1704bc9dbaae9fcc90213cb33b0132bca1b71866 GIT binary patch literal 256 zcmaLLH;%#p6adlDh@5i<8!$oa;st31l>ack{~4%hnC=aHcHxKf=lZH&ZYHL2XXoB4 z2al$1eDLB)=7|jnDO+~z$vAN2>BEAPg;$d(S+-);nspmCZP~VC*PeX`4jnmm;?$XQ z7cO19@-K?GMb69I5@jk>sZpmvlNN0{bm`G&z>pDRCQO+zXTg#+EB+&kd*lIc##;^x literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/de-DE.kl b/assets/resources/badusb/assets/layouts/de-DE.kl new file mode 100644 index 0000000000000000000000000000000000000000..67b05c042f1649ab6aa17c4d369b096c88ec2785 GIT binary patch literal 256 zcmaLLHx9y30KiboqW2Pd4WuBN!ay1SVRHX7Ftgz88Gbu+;q<%y>dMxg4`L4uK0?Afwu&6#5(8&;hd+qL7+fvJ5TwhjIGHgM$E s3wH`~pT4NjqeYV%GsZ+Ts4^j@ONSu?Qu;h-6Y}9rz=$sw?-ss^@Y|jPyWjO!M`q5wk-2p3gN<8r z&%QYE=EIg5a~5PQS+OQ(!`(YC&%FKkuw>baRci*;Z5Z0LW!sLCv58$%d-feTbmZ8H tQ!f-;S$XnFi82+c)Cj24Af!o)HXR~j61t@H=rdr*h%pnUTr9kL6TT^X3*7(! literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/en-US.kl b/assets/resources/badusb/assets/layouts/en-US.kl new file mode 100644 index 0000000000000000000000000000000000000000..8089d8257881765fe67691a206b6bf6e9cb2c97d GIT binary patch literal 256 zcmaLL#}dH+007aQ9YGK+QKLn)QG!wb|I3_nvA4HS?#PKldHvOyg-=&zuHE=#=iaS_ zZ!UcJvS-1P6&Y)CHf-7P@WI=Hk6)Ko46ItSZfL`%EhF1@?Ao($Y~sM7BgamhnmTjt sl{+_bFTSV{P^CtlkOoa!M6~J9rAMEbgaJcFjF~VcWyYMVcW=Ig9}}MoYybcN literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/es-ES.kl b/assets/resources/badusb/assets/layouts/es-ES.kl new file mode 100644 index 0000000000000000000000000000000000000000..15e9d7997c3f5178982fe212b5341f09469486bc GIT binary patch literal 256 zcmaLLH;%#p6adlDh@5lA#$@e+Y@}VF{DLgOx;B0)}2=l z9xW`m^W?$a6A39BGPdm4bKuCsyDv_@yqZSIvK6b=tlO|@%eEc6_Ut=w=*Y1Xr_P+a zaOujmdHhEaxleOSl&MgqMx6#tTD0lVrAMCuLq?35FlEM^1xr?}`HLiOkp;W~w>u5X literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/fr-BE.kl b/assets/resources/badusb/assets/layouts/fr-BE.kl new file mode 100644 index 0000000000000000000000000000000000000000..ea9e553e894a470639ee48648a386898ed5cfa67 GIT binary patch literal 256 zcmaLLNm9Z96adk#F6Mcj2}uy4P%#!3Wcd%1`=7xz8+-Q}Uc2(a<#qk5PfnzyQSfU* zM$Q+7r6X=Ue0nzVU}|RW(Kk=N`{Y4IN#)2x%&gn6Y0I`9yY}omaOmB!6Q|akyKw2s zwR^Yj+?YodMSOGfCuY=X(4ack{~4%hnC=aHcHxKf=lZH&ZYHL2XXoB4 z2al$1eDLB)=7|jnDO+~z$vAN2>BEAPg;$d(S+-);nspmCZP~VC*PeX`4jnmm;?$XQ z7cO19@-K?GMb69I5@jk>sZpmvlNN0{bm`G&z>pDRCQO+zXTg#+EB+&kd*lIc##;^x literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/fr-FR.kl b/assets/resources/badusb/assets/layouts/fr-FR.kl new file mode 100644 index 0000000000000000000000000000000000000000..f9193297e58722fd4f1547cb9ef62474beb2487b GIT binary patch literal 256 zcmaLLH*Nv}6adlDh@5i{8(2U#EVi(~}3$%7XqF9)7tV%3^;8#Zm(wqw_xeeVt(Ikw`|nR6E| z-MV(;$}Ebw#*KnQOsG<$PJ<>b+H~mBqtBfoBgRyiGGoqyC0o{PSdm5^W$Xj~0L-fm A_W%F@ literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/hr-HR.kl b/assets/resources/badusb/assets/layouts/hr-HR.kl new file mode 100644 index 0000000000000000000000000000000000000000..379f6c649c98ef7f38df9c6d1c2b1588167ee46a GIT binary patch literal 256 zcmaLL%XYy47y#ipa|DTNh+7ar(9@P>V)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHk)x=fVv{{L5{w#jy9;k{43_;_Fc>YIyakMR>% z$I*KC;Silq2439!rR7Y=g)29D?mT$;j68aqcv{8C#IX~nre@BZyKw2s+`_dROSkUa zd$6+hXyeH=%E+RN!9GSLjF~VcC1b{%1xr@s6s*}$vSr7f0~Iw#8crlpM-gqnA2aL@ AGynhq literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/it-IT.kl b/assets/resources/badusb/assets/layouts/it-IT.kl new file mode 100644 index 0000000000000000000000000000000000000000..059e428808a07b26d0da37d7f37d5d8d4614365b GIT binary patch literal 256 zcmaKnw++Go0KhCO)P&wbCv;IGQOAf|`2PmP$bvU}GyJk+&-OR{wF48UUbDox3y-W^ zo0@Xx$%CaECQO-;FlWJ%6>A>eeY5fH(MuMXGjGA7CCi3JR;*gHZo{T6+ji{QGq&%* yp(Dqhvm0r4@+k!5$Wx$5i83J(6{^&z)1XO96ECB#K@^L=Pq0t xyK-$Ft`y%!)Nxcub+H~j=&?BVJfFUEsOqeobPMlv%@{{ldJ?{*0 literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/pt-BR.kl b/assets/resources/badusb/assets/layouts/pt-BR.kl new file mode 100644 index 0000000000000000000000000000000000000000..d36421cfc45747687dba3cabe05ff84a4550050a GIT binary patch literal 256 zcmaKnM-ssR004J(1W9z!q7!8hWkx%CjQ_uZtBbwu-WGn@v1j|6{@Q_wH)qaWn0aIE z#+66!wV)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHk17S!45fq0~DYekR@*l?gpTRX7d-ob{d*zLn+x4&B`SxrR z=Qx?hB0l}{*Orbe7e0Kp_0GKq?|ty-qfcJ^p^Fo{=&Yh=Vrt)knYlwpj-5DlX5rk0 zrAt??-B?-MxN~b3W#qAstHmjD0& literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/sv-SE.kl b/assets/resources/badusb/assets/layouts/sv-SE.kl new file mode 100644 index 0000000000000000000000000000000000000000..5c55bb9ef1df3785fb143eb463a5375be10ce96f GIT binary patch literal 256 zcmaLLH*x|26u?l8hMaSTC2U}9uLl~S{D;~5pMjbNbx-iw55HVL*H`^JB+m2m(_8mBMwCT{LN1p*hMvR#-WyYKZOIEDeuw}=dG^!}#7VrkLXASNE literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/tr-TR.kl b/assets/resources/badusb/assets/layouts/tr-TR.kl new file mode 100644 index 0000000000000000000000000000000000000000..6377b770365ed544824108765ce2587f315bc1da GIT binary patch literal 256 zcmaLLM{dFZ6adlDh~A6oU~F)Sk{HDcB$od$x&IlmW|P^yf%iW7;^Te&t8Y@DWRb_s zyH`sq8**D7yeOY}m46&w(Q+&Ri(sH|qEa_ygc8 B4s!qi literal 0 HcmV?d00001 From 8288a08eb3ab1c49451c1abcf1bc38bbfdcc8c71 Mon Sep 17 00:00:00 2001 From: Brandon Weeks Date: Wed, 8 Feb 2023 07:26:45 -0800 Subject: [PATCH 10/34] SubGhz: add protocol "Linear Delta-3" (#2239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: add protocol "Linear Delta-3" * SubGhz: fix Leniar Delta 3 * BadUSB: mask pvs studio warning for valid code Co-authored-by: SkorP Co-authored-by: あく Co-authored-by: Skorpionm <85568270+Skorpionm@users.noreply.github.com> --- .../debug/unit_tests/subghz/subghz_test.c | 18 +- applications/main/bad_usb/bad_usb_script.c | 2 +- assets/unit_tests/subghz/linear_delta3.sub | 7 + .../unit_tests/subghz/linear_delta3_raw.sub | 8 + assets/unit_tests/subghz/test_random_raw.sub | 2 + lib/subghz/protocols/linear_delta3.c | 359 ++++++++++++++++++ lib/subghz/protocols/linear_delta3.h | 111 ++++++ lib/subghz/protocols/protocol_items.c | 49 ++- lib/subghz/protocols/protocol_items.h | 1 + 9 files changed, 543 insertions(+), 14 deletions(-) create mode 100644 assets/unit_tests/subghz/linear_delta3.sub create mode 100644 assets/unit_tests/subghz/linear_delta3_raw.sub create mode 100644 lib/subghz/protocols/linear_delta3.c create mode 100644 lib/subghz/protocols/linear_delta3.h diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 1dee1d59e..83fadeda9 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 273 +#define TEST_RANDOM_COUNT_PARSE 295 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -489,6 +489,14 @@ MU_TEST(subghz_decoder_linear_test) { "Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n"); } +MU_TEST(subghz_decoder_linear_delta3_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/linear_delta3_raw.sub"), + SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME), + "Test decoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n"); +} + MU_TEST(subghz_decoder_megacode_test) { mu_assert( subghz_decoder_test( @@ -647,6 +655,12 @@ MU_TEST(subghz_encoder_linear_test) { "Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n"); } +MU_TEST(subghz_encoder_linear_delta3_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/linear_delta3.sub")), + "Test encoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n"); +} + MU_TEST(subghz_encoder_megacode_test) { mu_assert( subghz_encoder_test(EXT_PATH("unit_tests/subghz/megacode.sub")), @@ -772,6 +786,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_somfy_telis_test); MU_RUN_TEST(subghz_decoder_star_line_test); MU_RUN_TEST(subghz_decoder_linear_test); + MU_RUN_TEST(subghz_decoder_linear_delta3_test); MU_RUN_TEST(subghz_decoder_megacode_test); MU_RUN_TEST(subghz_decoder_secplus_v1_test); MU_RUN_TEST(subghz_decoder_secplus_v2_test); @@ -796,6 +811,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_nice_flo_test); MU_RUN_TEST(subghz_encoder_keelog_test); MU_RUN_TEST(subghz_encoder_linear_test); + MU_RUN_TEST(subghz_encoder_linear_delta3_test); MU_RUN_TEST(subghz_encoder_megacode_test); MU_RUN_TEST(subghz_encoder_holtek_test); MU_RUN_TEST(subghz_encoder_secplus_v1_test); diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index 1416acfee..0fadbcc07 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -694,7 +694,7 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou } File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - if(!furi_string_empty(layout_path)) { + if(!furi_string_empty(layout_path)) { //-V1051 if(storage_file_open( layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) { uint16_t layout[128]; diff --git a/assets/unit_tests/subghz/linear_delta3.sub b/assets/unit_tests/subghz/linear_delta3.sub new file mode 100644 index 000000000..f00507428 --- /dev/null +++ b/assets/unit_tests/subghz/linear_delta3.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: LinearDelta3 +Bit: 8 +Key: 00 00 00 00 00 00 00 D0 diff --git a/assets/unit_tests/subghz/linear_delta3_raw.sub b/assets/unit_tests/subghz/linear_delta3_raw.sub new file mode 100644 index 000000000..1973622a5 --- /dev/null +++ b/assets/unit_tests/subghz/linear_delta3_raw.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -66 11813 -100 14655 -98 40111 -66 1625 -2116 1933 -34732 501 -11730 235 -3728 1887 -2106 1933 -2092 1971 -2072 1959 -34712 511 -3554 445 -3556 1997 -2036 455 -3594 1963 -2046 1979 -2076 1961 -2070 1989 -34690 483 -7724 1739 -2226 355 -3684 1857 -2138 1929 -2078 1965 -2074 1947 -34750 487 -3538 473 -3544 1993 -2042 485 -3548 1961 -2070 1965 -2070 1969 -2042 1997 -34716 443 -7734 1753 -2236 323 -3676 1903 -2098 1945 -2102 1927 -2070 1989 -34710 521 -3532 473 -3544 1991 -2032 481 -3556 1969 -2076 1967 -2036 1991 -2066 1969 -34718 467 -7756 1739 -2192 363 -3654 1889 -2132 1929 -2096 1935 -2070 1987 -34716 511 -3522 471 -3554 2009 -2036 459 -3550 2003 -2038 1979 -2042 1999 -2042 1999 -34704 471 -11774 225 -3710 1879 -2162 1885 -2112 1925 -2110 1939 -34738 459 -3636 403 -3612 1939 -2062 451 -3566 1985 -2044 1995 -2040 2009 -2032 2003 -34684 495 -3680 295 -3648 1935 -2098 423 -3562 2001 -2038 1989 -2044 2003 -2036 1977 -34718 461 -3678 295 -3684 1901 -2098 429 -3596 1967 -2036 1981 -2048 1993 -2042 2013 -34686 521 -3530 457 -3568 1999 -2036 455 -3552 1999 -2032 2019 -2024 1995 -2022 1997 -34716 441 -15774 1809 -2192 1905 -2100 1919 -2112 1961 -34720 417 -3830 167 -3710 1863 -2144 357 -3674 1909 -2100 1955 -2062 1977 -2072 1965 -34710 487 -3562 453 -3554 1985 -2052 481 -3536 2019 -2010 2001 -2042 1997 -2038 2005 -34716 451 -3602 433 -3584 1959 -2070 451 -3560 2001 -2038 1993 -2042 1967 -2072 1973 -34712 459 -3622 393 -3624 1933 -2068 457 -3584 1965 -2064 1979 -2052 1967 -2044 1981 -34722 477 -3608 397 -3588 1961 -2096 413 -3596 1971 -2040 1979 -2072 1963 -2070 1959 -34714 495 -3558 483 -3538 1985 -2042 479 -3562 1985 -2046 1967 -2070 1973 -2054 1995 -34688 493 -3578 413 -3614 1939 -2074 465 -3560 1971 -2038 2017 -2018 1995 -2042 2013 -34726 479 -3528 475 -3556 1999 -2036 455 -3570 1999 -2040 1973 -2054 2001 -2032 1987 -34720 477 -3562 445 -3602 1949 -2054 481 -3562 1975 -2060 1963 -2064 1977 -2038 2005 -34702 485 -3570 447 -3550 2015 -2020 479 -3564 1983 -2048 1999 -2034 1971 -2064 1993 -34688 517 -3516 497 -3532 1999 -2038 481 -3558 1997 -2004 2027 -2042 1963 -2038 1997 -34716 491 -3562 461 -3548 1995 -2032 491 -3524 2005 -2036 1989 -2038 1995 -2046 1979 -34714 465 -3682 293 -3680 1905 -2096 431 -3592 1969 -2070 1977 -2052 1965 -2044 1981 -34734 479 -3564 463 -3556 1999 -2032 457 -3550 1995 -2044 2011 -2042 1997 -2006 2027 -34680 531 -3524 483 -3538 1987 -2044 479 -3534 2013 -2048 1965 -2062 1987 -2030 1997 -34712 473 -3592 445 -3562 1975 -2072 451 -3566 1965 -2042 2013 -2046 1963 -2064 1993 -34700 459 -3632 371 -3638 1915 -2084 449 -3568 1987 -2046 1971 -2070 1983 -2022 1997 -34726 487 -3524 477 -3562 1985 -2044 481 -3542 2005 -2040 1995 -2038 1967 -2046 1993 -34710 511 -3528 471 -3560 1967 -2070 459 -3558 1971 +RAW_Data: -2072 1971 -2056 1971 -2074 1973 -34714 455 -3634 373 -3634 1901 -2110 419 -3620 1941 -2070 1991 -2040 1999 -2038 1965 -34740 467 -3562 481 -3534 1983 -2070 449 -3546 1999 -2044 1993 -2042 2003 -2036 1975 -34702 521 -3560 443 -3586 1969 -2044 449 -3562 1997 -2046 1987 -2042 2007 -2034 1973 -34732 487 -3562 443 -3582 1979 -2058 445 -3560 1995 -2044 1997 -2028 1987 -2034 2003 -34710 515 -3518 485 -3566 1977 -2036 483 -3536 1999 -2044 2009 -2024 1995 -2068 1973 -34710 487 -3564 471 -3558 1977 -2054 447 -3564 1991 -2042 1997 -2036 2007 -2034 2001 -34684 529 -3526 469 -3548 1989 -2038 483 -3562 1997 -2038 1973 -2034 1999 -2036 1997 -34728 487 -3536 479 -3534 2013 -2044 449 -3570 1985 -2042 1993 -2044 2005 -2014 1995 -34710 473 -3594 439 -3562 1995 -2040 457 -3564 2001 -2040 1975 -2046 1995 -2046 1999 -34704 491 -3548 451 -3570 1991 -2042 447 -3578 1967 -2046 1995 -2042 1999 -2034 2001 -34712 491 -3562 443 -3584 1981 -2018 479 -3562 1985 -2044 1997 -2030 1989 -2040 1997 -34722 489 -3554 459 -3560 1969 -2068 453 -3554 1999 -2034 1987 -2058 1997 -2046 1983 -34702 487 -3534 479 -3564 1983 -2040 483 -3538 1981 -2048 1993 -2048 2007 -2044 1995 -34696 489 -3550 453 -3570 1995 -2050 447 -3564 1983 -2040 1999 -2034 2003 -2034 1995 -34690 495 -3580 433 -3586 1969 -2064 453 -3552 1995 -2036 1991 -2056 1997 -2046 1987 -34706 441 -3636 373 -3626 1959 -2074 419 -3592 1963 -2074 1989 -2044 1971 -2070 1981 -34698 509 -3526 503 -3528 2005 -2034 481 -3528 1993 -2042 1999 -2066 1989 -2034 2003 -34678 495 -3540 481 -3546 1997 -2046 473 -3554 1999 -2034 2001 -2036 1995 -2046 1983 -34720 475 -3560 469 -3548 1997 -2030 485 -3566 1963 -2066 1983 -2046 1999 -2034 1973 -34734 487 -3560 443 -3584 1981 -2052 445 -3568 1987 -2044 1999 -2032 1993 -2034 2007 -34702 491 -3560 459 -3558 1967 -2070 455 -3556 2003 -2036 1977 -2042 2005 -2028 1997 -34730 461 -3564 473 -3536 2011 -2046 449 -3566 1989 -2044 1997 -2042 1971 -2054 2001 -34708 475 -3560 479 -3528 1999 -2040 485 -3566 1963 -2040 2013 -2042 1995 -2034 1987 -34694 519 -3554 441 -3582 1981 -2052 449 -3564 1985 -2040 1993 -2034 1991 -2062 1975 -34714 529 -3534 463 -3558 1969 -2068 451 -3560 2003 -2038 1993 -2042 1969 -2070 1975 -34720 493 -3582 383 -3616 1937 -2072 469 -3558 1995 -2036 1975 -2066 1995 -2042 1989 -34678 531 -3560 391 -3622 1937 -2094 429 -3588 1967 -2070 1981 -2054 1965 -2038 2021 -34682 525 -3524 481 -3564 1989 -2040 445 -3554 1997 -2040 2005 -2034 2001 -2024 1991 -34706 517 -3586 409 -3610 1927 -2076 451 -3558 1967 -2074 1993 -2038 2001 -2040 1975 -34714 495 -3588 409 -3602 1933 -2088 447 -3584 1965 -2044 1999 -2036 2007 -2030 1995 -34692 525 -3538 447 -3580 1981 -2042 487 -3542 1995 -2040 1969 -2072 1969 -2044 1991 -34714 443 -3636 399 -3630 1899 -2106 413 -3584 1997 +RAW_Data: -2034 2007 -2038 1969 -2076 1965 -34708 493 -3564 451 -3570 1965 -2074 449 -3548 2003 -2044 1987 -2038 1999 -2030 1991 -34710 493 -3602 403 -3612 1943 -2092 419 -3596 1963 -2062 1963 -2042 2001 -2064 1967 -34716 497 -3616 357 -3648 1903 -2132 399 -3596 1963 -2068 1977 -2052 1967 -2046 2019 -34684 497 -3614 359 -3650 1909 -2100 405 -3630 1925 -2098 1965 -2066 1965 -2056 1971 -34712 477 -3634 371 -3628 1931 -2104 391 -3624 1939 -2066 1975 -2052 2005 -2036 1985 -34714 449 -3668 337 -3664 1901 -2124 417 -3594 1963 -2048 1995 -2028 1993 -2066 1971 -34698 463 -3642 353 -3650 1943 -2066 433 -3594 1963 -2066 1995 -2034 1997 -2046 1981 -34730 479 -3560 445 -3562 1997 -2032 485 -3560 1965 -2062 1989 -2044 1999 -2032 1971 -34724 463 -3608 399 -3620 1943 -2096 421 -3592 1961 -2074 1979 -2036 2011 -2032 1971 -34734 469 -3558 485 -3552 1999 -2028 473 -3552 2003 -2032 2003 -2032 1997 -2044 1993 -34704 443 -3602 431 -3596 1967 -2076 447 -3556 1975 -2058 1997 -2040 1991 -2048 1971 -161100 97 -428 165 -200 395 -428 97 -100 559 -130 97 -164 129 -98 391 -98 295 -166 52395 -66 16239 -66 42541 -66 755 -132 14015 -98 2885 -68 10385 -98 40045 -100 987 -68 25539 -66 19799 -98 136101 -100 5141 -66 5709 -68 23177 -66 11097 -66 329 -100 261 -66 15755 -98 20575 -66 3645 -100 51411 -66 14441 -132 4467 -66 3965 -132 3707 -66 33107 -66 10373 -66 1775 -66 4185 -132 1429 -68 4675 -100 13419 -66 33985 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index be635f04d..7571d688d 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -173,3 +173,5 @@ RAW_Data: 107 -1501 77 -1518 53 -704 113 -390 107 -650 73 -932 51 -3641 169 -704 RAW_Data: 79 -4798 53 -918 83 -4847 51 -755 103 -732 81 -388 55 -1026 77 -1506 101 -242 107 -469 51 -2026 79 -686 77 -348 51 -104 131 -860 129 -148 73 -446 75 -440 97 -306 99 -600 51 -626 105 -1350 95 -674 83 -230 119 -1714 135 -396 155 -1111 109 -652 111 -482 51 -506 55 -1715 103 -968 207 -1156 81 -164 57 -404 99 -508 205 -126 75 -1417 51 -186 77 -588 53 -54 103 -2854 73 -1010 53 -800 51 -2494 53 -106 105 -52 51 -104 79 -1116 51 -654 103 -220 77 -162 71 -5385 137 -2232 79 -1159 79 -250 57 -108 79 -164 107 -1660 79 -3927 129 -992 73 -1913 51 -1430 51 -1498 55 -514 103 -586 81 -386 53 -2402 175 -1994 85 -3431 53 -3209 99 -372 79 -78 53 -1338 75 -682 97 -680 51 -206 101 -1708 101 -452 131 -1397 161 -2272 53 -456 77 -1413 193 -270 109 -466 53 -2432 77 -222 189 -474 107 -774 171 -192 79 -1327 75 -2141 51 -908 135 -3866 75 -804 129 -468 101 -1040 79 -1470 55 -869 77 -1448 105 -160 55 -1916 240 -588 79 -1587 53 -922 79 -2292 181 -1448 51 -552 77 -2189 75 -2545 77 -384 300 -2478 101 -1092 73 -558 79 -132 105 -884 103 -1177 109 -880 79 -2431 109 -1006 105 -468 53 -1378 235 -684 75 -285 73 -604 129 -528 77 -1582 51 -1240 105 -2750 75 -252 51 -1024 95 -1891 51 -864 107 -326 83 -887 159 -1058 163 -322 105 -722 83 -388 81 -936 155 -880 55 -220 83 -2123 135 -2100 73 -1926 103 -1633 149 -526 51 -324 51 -1538 103 -164 137 -964 81 -152 111 -781 225 -655 53 -2888 105 -151 131 -454 53 -4109 77 -1052 53 -178 163 -910 51 -733 207 -2070 53 -474 79 -54 53 -818 51 -1228 53 -2262 79 -788 79 -480 73 -2747 83 -316 183 -1880 105 -862 53 -662 53 -2287 153 -1630 51 -817 243 -806 55 -510 51 -1389 75 -986 135 -498 109 -532 131 -5521 99 -2948 209 -764 75 -1168 75 -886 83 -2065 53 -710 51 -596 77 -374 73 -628 99 -732 51 -202 73 -632 53 -222 55 -511 79 -4884 53 -1826 81 -1266 107 -356 55 -110 113 -280 83 -756 169 -252 81 -1854 51 -1556 157 -258 75 -748 53 -1438 291 -244 71 -1092 77 -1220 229 -1055 181 -1182 71 -1284 77 -864 79 -138 53 -160 53 -952 81 -80 127 -1272 51 -590 103 -502 77 -634 101 -74 51 -224 101 -912 77 -562 51 -164 83 -396 105 -4643 111 -3293 133 -1395 107 -3047 137 -2353 53 -298 83 -54 81 -80 53 -162 83 -392 105 -606 107 -787 53 -928 51 -2800 161 -1146 51 -182 103 -536 103 -994 81 -2044 83 -732 133 -1881 133 -2160 75 -178 RAW_Data: 75 -1694 101 -122 73 -864 51 -250 129 -406 77 -630 77 -610 101 -781 125 -128 51 -5075 77 -1992 83 -1272 176 -2100 53 -2044 53 -1234 79 -1704 157 -519 99 -2374 101 -100 103 -202 51 -360 77 -1962 103 -2153 77 -1820 191 -164 167 -1320 77 -1718 127 -1374 81 -1047 53 -54 79 -632 53 -656 51 -128 81 -216 51 -755 79 -2692 103 -1478 125 -452 51 -896 157 -3679 135 -632 105 -134 55 -112 77 -588 79 -188 55 -1118 79 -1152 51 -1950 109 -1858 103 -1104 81 -580 131 -226 255 -2932 77 -1536 51 -1044 159 -2135 67667 -252 333 -278 333 -276 333 -74 533 -280 307 -276 345 -6930 331 -276 329 -278 329 -278 327 -278 349 -270 325 -270 317 -290 313 -308 283 -306 309 -100 509 -306 283 -328 281 -6972 307 -302 281 -326 281 -326 281 -328 279 -328 281 -326 279 -328 279 -326 281 -328 279 -124 481 -308 281 -326 279 -6998 281 -326 279 -328 279 -328 277 -330 277 -328 279 -328 279 -328 277 -304 303 -302 303 -100 503 -306 295 -322 293 -6968 287 -342 259 -336 283 -332 257 -356 255 -328 283 -328 257 -352 257 -352 257 -352 255 -150 455 -334 281 -326 281 -6996 265 -342 253 -354 253 -354 253 -354 253 -354 267 -326 269 -350 263 -342 257 -336 259 -152 459 -360 257 -354 231 -7038 267 -338 255 -352 253 -354 253 -354 239 -354 269 -352 239 -372 233 -366 233 -358 257 -154 457 -360 231 -378 231 -7050 231 -380 231 -378 231 -380 231 -378 231 -354 255 -352 257 -352 255 -354 231 -378 229 -176 453 -358 229 -378 231 -7076 231 -378 231 -380 231 -380 229 -354 255 -354 257 -352 257 -352 257 -352 257 -354 255 -150 455 -358 265 -364 229 -4941 101 -1058 153 -670 157 -532 124 -1396 133 -82 165 -162 153 -258 207 -156 131 -1582 85 -714 53 -774 103 -396 274 -110 131 -1965 55 -402 159 -1026 79 -590 77 -3531 57 -500 51 -4770 109 -722 77 -186 53 -298 79 -502 165 -808 77 -438 53 -382 101 -1914 75 -504 77 -1969 135 -5517 99 -576 51 -608 243 -684 53 -2058 315 -1384 79 -1079 77 -232 79 -212 155 -1500 137 -258 75 -975 204 -752 83 -2542 51 -484 103 -78 77 -210 53 -922 157 -1900 107 -2173 83 -384 101 -80 128 -814 183 -978 127 -772 105 -2073 51 -708 53 -300 83 -739 237 -884 131 -3412 157 -1752 81 -164 83 -3373 53 -1406 105 -3809 79 -432 51 -724 77 -548 53 -1955 79 -807 81 -2096 103 -490 105 -1196 109 -108 79 -394 71 -1159 129 -126 143 -340 107 -556 81 -2390 135 -106 133 -690 133 -4347 189 -290 51 -110 53 -78 103 -1101 51 -1362 RAW_Data: 83 -320 81 -4648 101 -3726 173 -1418 85 -348 53 -2994 79 -1390 51 -1656 107 -764 53 -134 79 -1619 131 -932 55 -2810 107 -3218 79 -765 107 -654 103 -1498 77 -228 51 -134 247 -1526 51 -3903 103 -1495 179 -282 77 -392 53 -1756 105 -368 111 -486 51 -298 53 -216 113 -358 51 -266 187 -1059 81 -780 105 -238 51 -482 53 -791 109 -2169 77 -5304 53 -398 79 -650 51 -54 51 -1789 73 -198 101 -1580 101 -746 97 -4518 53 -744 51 -1064 101 -928 111 -392 185 -869 103 -320 133 -704 81 -244 53 -1628 75 -634 79 -666 183 -1276 83 -218 107 -1163 55 -1276 127 -1144 73 -1400 81 -266 77 -568 129 -806 121 -1420 103 -848 77 -982 103 -2132 81 -1610 101 -1218 55 -2208 75 -2735 53 -921 53 -724 51 -472 83 -3164 185 -400 77 -812 81 -306 215 -2167 53 -130 53 -272 81 -400 79 -1272 81 -418 51 -1381 73 -340 101 -2169 81 -2330 137 -2698 99 -2340 99 -126 51 -1714 55 -488 81 -3500 51 -404 77 -1422 77 -856 215 -80 51 -2308 53 -134 77 -2036 75 -5175 129 -946 239 -638 53 -244 55 -564 105 -826 71 -1632 77 -106 129 -246 135 -366 79 -724 79 -1535 57 -1085 113 -1320 79 -3111 127 -1578 75 -324 75 -102 173 -364 79 -1374 53 -1508 107 -622 51 -526 109 -584 187 -2648 51 -106 79 -380 103 -604 51 -1244 73 -5766 107 -1934 177 -702 51 -1277 53 -1643 79 -1446 81 -4098 75 -574 103 -432 189 -1436 107 -454 79 -132 105 -136 81 -112 113 -942 239 -1238 79 -952 157 -340 51 -314 191 -456 53 -3368 101 -150 99 -464 51 -718 73 -770 101 -150 73 -2132 75 -557 77 -680 81 -3512 151 -760 75 -332 75 -1212 131 -1468 79 -1955 101 -541 75 -344 79 -2146 53 -2299 97 -720 79 -2518 79 -3807 51 -1272 75 -352 77 -52 75 -586 53 -1142 79 -82 81 -2400 157 -324 81 -268 103 -1154 81 -1175 79 -1191 51 -1074 53 -2566 137 -854 75 -1497 51 -4533 51 -2290 51 -344 77 -348 55 -1182 77 -897 135 -874 51 -1064 51 -208 55 -140 55 -1334 133 -1238 157 -1669 113 -2128 75 -848 85 -510 83590 -126 333 -280 331 -252 331 -6946 331 -276 331 -276 329 -278 329 -276 331 -276 331 -276 331 -276 347 -238 351 -254 353 -268 323 -270 345 -6924 335 -282 307 -304 307 -304 281 -304 307 -302 307 -302 305 -302 307 -302 305 -302 281 -124 507 -282 305 -302 305 -6984 279 -328 277 -328 279 -328 277 -330 277 -304 303 -302 305 -302 305 -302 303 -304 303 -100 507 -314 295 -298 293 -6986 283 -334 281 -306 283 -328 283 -328 281 -328 283 -328 255 -352 +RAW_Data: -66 11813 -100 14655 -98 40111 -66 1625 -2116 1933 -34732 501 -11730 235 -3728 1887 -2106 1933 -2092 1971 -2072 1959 -34712 511 -3554 445 -3556 1997 -2036 455 -3594 1963 -2046 1979 -2076 1961 -2070 1989 -34690 483 -7724 1739 -2226 355 -3684 1857 -2138 1929 -2078 1965 -2074 1947 -34750 487 -3538 473 -3544 1993 -2042 485 -3548 1961 -2070 1965 -2070 1969 -2042 1997 -34716 443 -7734 1753 -2236 323 -3676 1903 -2098 1945 -2102 1927 -2070 1989 -34710 521 -3532 473 -3544 1991 -2032 481 -3556 1969 -2076 1967 -2036 1991 -2066 1969 -34718 467 -7756 1739 -2192 363 -3654 1889 -2132 1929 -2096 1935 -2070 1987 -34716 511 -3522 471 -3554 2009 -2036 459 -3550 2003 -2038 1979 -2042 1999 -2042 1999 -34704 471 -11774 225 -3710 1879 -2162 1885 -2112 1925 -2110 1939 -34738 459 -3636 403 -3612 1939 -2062 451 -3566 1985 -2044 1995 -2040 2009 -2032 2003 -34684 495 -3680 295 -3648 1935 -2098 423 -3562 2001 -2038 1989 -2044 2003 -2036 1977 -34718 461 -3678 295 -3684 1901 -2098 429 -3596 1967 -2036 1981 -2048 1993 -2042 2013 -34686 521 -3530 457 -3568 1999 -2036 455 -3552 1999 -2032 2019 -2024 1995 -2022 1997 -34716 441 -15774 1809 -2192 1905 -2100 1919 -2112 1961 -34720 417 -3830 167 -3710 1863 -2144 357 -3674 1909 -2100 1955 -2062 1977 -2072 1965 -34710 487 -3562 453 -3554 1985 -2052 481 -3536 2019 -2010 2001 -2042 1997 -2038 2005 -34716 451 -3602 433 -3584 1959 -2070 451 -3560 2001 -2038 1993 -2042 1967 -2072 1973 -34712 459 -3622 393 -3624 1933 -2068 457 -3584 1965 -2064 1979 -2052 1967 -2044 1981 -34722 477 -3608 397 -3588 1961 -2096 413 -3596 1971 -2040 1979 -2072 1963 -2070 1959 -34714 495 -3558 483 -3538 1985 -2042 479 -3562 1985 -2046 1967 -2070 1973 -2054 1995 -34688 493 -3578 413 -3614 1939 -2074 465 -3560 1971 -2038 2017 -2018 1995 -2042 2013 -34726 479 -3528 475 -3556 1999 -2036 455 -3570 1999 -2040 1973 -2054 2001 -2032 1987 -34720 477 -3562 445 -3602 1949 -2054 481 -3562 1975 -2060 1963 -2064 1977 -2038 2005 -34702 485 -3570 447 -3550 2015 -2020 479 -3564 1983 -2048 1999 -2034 1971 -2064 1993 -34688 517 -3516 497 -3532 1999 -2038 481 -3558 1997 -2004 2027 -2042 1963 -2038 1997 -34716 491 -3562 461 -3548 1995 -2032 491 -3524 2005 -2036 1989 -2038 1995 -2046 1979 -34714 465 -3682 293 -3680 1905 -2096 431 -3592 1969 -2070 1977 -2052 1965 -2044 1981 -34734 479 -3564 463 -3556 1999 -2032 457 -3550 1995 -2044 2011 -2042 1997 -2006 2027 -34680 531 -3524 483 -3538 1987 -2044 479 -3534 2013 -2048 1965 -2062 1987 -2030 1997 -34712 473 -3592 445 -3562 1975 -2072 451 -3566 1965 -2042 2013 -2046 1963 -2064 1993 -34700 459 -3632 371 -3638 1915 -2084 449 -3568 1987 -2046 1971 -2070 1983 -2022 1997 -34726 487 -3524 477 -3562 1985 -2044 481 -3542 2005 -2040 1995 -2038 1967 -2046 1993 -34710 511 -3528 471 -3560 1967 -2070 459 -3558 1971 +RAW_Data: -2072 1971 -2056 1971 -2074 1973 -34714 455 -3634 373 -3634 1901 -2110 419 -3620 1941 -2070 1991 -2040 1999 -2038 1965 -34740 467 -3562 481 -3534 1983 -2070 449 -3546 1999 -2044 1993 -2042 2003 -2036 1975 -34702 521 -3560 443 -3586 1969 -2044 449 -3562 1997 -2046 1987 -2042 2007 -2034 1973 -34732 487 -3562 443 -3582 1979 -2058 445 -3560 1995 -2044 1997 -2028 1987 -2034 2003 -34710 515 -3518 485 -3566 1977 -2036 483 -3536 1999 -2044 2009 -2024 1995 -2068 1973 -34710 487 -3564 471 -3558 1977 -2054 447 -3564 1991 -2042 1997 -2036 2007 -2034 2001 -34684 529 -3526 469 -3548 1989 -2038 483 -3562 1997 -2038 1973 -2034 1999 -2036 1997 -34728 487 -3536 479 -3534 2013 -2044 449 -3570 1985 -2042 1993 -2044 2005 -2014 1995 -34710 473 -3594 439 -3562 1995 -2040 457 -3564 2001 -2040 1975 -2046 1995 -2046 1999 -34704 491 -3548 451 -3570 1991 -2042 447 -3578 1967 -2046 1995 -2042 1999 -2034 2001 -34712 491 -3562 443 -3584 1981 -2018 479 -3562 1985 -2044 1997 -2030 1989 -2040 1997 -34722 489 -3554 459 -3560 1969 -2068 453 -3554 1999 -2034 1987 -2058 1997 -2046 1983 -34702 487 -3534 479 -3564 1983 -2040 483 -3538 1981 -2048 1993 -2048 2007 -2044 1995 -34696 489 -3550 453 -3570 1995 -2050 447 -3564 1983 -2040 1999 -2034 2003 -2034 1995 -34690 495 -3580 433 -3586 1969 -2064 453 -3552 1995 -2036 1991 -2056 1997 -2046 1987 -34706 441 -3636 373 -3626 1959 -2074 419 -3592 1963 -2074 1989 -2044 1971 -2070 1981 -34698 509 -3526 503 -3528 2005 -2034 481 -3528 1993 -2042 1999 -2066 1989 -2034 2003 -34678 495 -3540 481 -3546 1997 -2046 473 -3554 1999 -2034 2001 -2036 1995 -2046 1983 -34720 475 -3560 469 -3548 1997 -2030 485 -3566 1963 -2066 1983 -2046 1999 -2034 1973 -34734 487 -3560 443 -3584 1981 -2052 445 -3568 1987 -2044 1999 -2032 1993 -2034 2007 -34702 491 -3560 459 -3558 1967 -2070 455 -3556 2003 -2036 1977 -2042 2005 -2028 1997 -34730 461 -3564 473 -3536 2011 -2046 449 -3566 1989 -2044 1997 -2042 1971 -2054 2001 -34708 475 -3560 479 -3528 1999 -2040 485 -3566 1963 -2040 2013 -2042 1995 -2034 1987 -34694 519 -3554 441 -3582 1981 -2052 449 -3564 1985 -2040 1993 -2034 1991 -2062 1975 -34714 529 -3534 463 -3558 1969 -2068 451 -3560 2003 -2038 1993 -2042 1969 -2070 1975 -34720 493 -3582 383 -3616 1937 -2072 469 -3558 1995 -2036 1975 -2066 1995 -2042 1989 -34678 531 -3560 391 -3622 1937 -2094 429 -3588 1967 -2070 1981 -2054 1965 -2038 2021 -34682 525 -3524 481 -3564 1989 -2040 445 -3554 1997 -2040 2005 -2034 2001 -2024 1991 -34706 517 -3586 409 -3610 1927 -2076 451 -3558 1967 -2074 1993 -2038 2001 -2040 1975 -34714 495 -3588 409 -3602 1933 -2088 447 -3584 1965 -2044 1999 -2036 2007 -2030 1995 -34692 525 -3538 447 -3580 1981 -2042 487 -3542 1995 -2040 1969 -2072 1969 -2044 1991 -34714 443 -3636 399 -3630 1899 -2106 413 -3584 1997 diff --git a/lib/subghz/protocols/linear_delta3.c b/lib/subghz/protocols/linear_delta3.c new file mode 100644 index 000000000..869edac84 --- /dev/null +++ b/lib/subghz/protocols/linear_delta3.c @@ -0,0 +1,359 @@ +#include "linear_delta3.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolLinearDelta3" + +#define DIP_PATTERN "%c%c%c%c%c%c%c%c" +#define DATA_TO_DIP(dip) \ + (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), \ + (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), \ + (dip & 0x0002 ? '1' : '0'), (dip & 0x0001 ? '1' : '0') + +static const SubGhzBlockConst subghz_protocol_linear_delta3_const = { + .te_short = 500, + .te_long = 2000, + .te_delta = 150, + .min_count_bit_for_found = 8, +}; + +struct SubGhzProtocolDecoderLinearDelta3 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint32_t last_data; +}; + +struct SubGhzProtocolEncoderLinearDelta3 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + LinearDecoderStepReset = 0, + LinearDecoderStepSaveDuration, + LinearDecoderStepCheckDuration, +} LinearDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder = { + .alloc = subghz_protocol_decoder_linear_delta3_alloc, + .free = subghz_protocol_decoder_linear_delta3_free, + + .feed = subghz_protocol_decoder_linear_delta3_feed, + .reset = subghz_protocol_decoder_linear_delta3_reset, + + .get_hash_data = subghz_protocol_decoder_linear_delta3_get_hash_data, + .serialize = subghz_protocol_decoder_linear_delta3_serialize, + .deserialize = subghz_protocol_decoder_linear_delta3_deserialize, + .get_string = subghz_protocol_decoder_linear_delta3_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder = { + .alloc = subghz_protocol_encoder_linear_delta3_alloc, + .free = subghz_protocol_encoder_linear_delta3_free, + + .deserialize = subghz_protocol_encoder_linear_delta3_deserialize, + .stop = subghz_protocol_encoder_linear_delta3_stop, + .yield = subghz_protocol_encoder_linear_delta3_yield, +}; + +const SubGhzProtocol subghz_protocol_linear_delta3 = { + .name = SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_linear_delta3_decoder, + .encoder = &subghz_protocol_linear_delta3_encoder, +}; + +void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderLinearDelta3* instance = + malloc(sizeof(SubGhzProtocolEncoderLinearDelta3)); + + instance->base.protocol = &subghz_protocol_linear_delta3; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 16; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_linear_delta3_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderLinearDelta3* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @return true On success + */ +static bool + subghz_protocol_encoder_linear_delta3_get_upload(SubGhzProtocolEncoderLinearDelta3* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2); + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short); + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 7); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + } + } + //Send end bit + if(bit_read(instance->generic.data, 0)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short); + //Send PT_GUARD + instance->encoder.upload[index] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 73); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + //Send PT_GUARD + instance->encoder.upload[index] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 70); + } + + return true; +} + +bool subghz_protocol_encoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderLinearDelta3* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_linear_delta3_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_linear_delta3_stop(void* context) { + SubGhzProtocolEncoderLinearDelta3* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context) { + SubGhzProtocolEncoderLinearDelta3* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderLinearDelta3* instance = + malloc(sizeof(SubGhzProtocolDecoderLinearDelta3)); + instance->base.protocol = &subghz_protocol_linear_delta3; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_linear_delta3_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + free(instance); +} + +void subghz_protocol_decoder_linear_delta3_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + instance->decoder.parser_step = LinearDecoderStepReset; + instance->last_data = 0; +} + +void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + switch(instance->decoder.parser_step) { + case LinearDecoderStepReset: + if((!level) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 70) < + subghz_protocol_linear_delta3_const.te_delta * 24)) { + //Found header Linear + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } + break; + case LinearDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = LinearDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + break; + case LinearDecoderStepCheckDuration: + if(!level) { + if(duration >= (subghz_protocol_linear_delta3_const.te_short * 10)) { + instance->decoder.parser_step = LinearDecoderStepReset; + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) < + subghz_protocol_linear_delta3_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } + if(instance->decoder.decode_count_bit == + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + if((instance->last_data == instance->decoder.decode_data) && + instance->last_data) { + instance->generic.serial = 0x0; + instance->generic.btn = 0x0; + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + instance->last_data = instance->decoder.decode_data; + } + break; + } + + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) < + subghz_protocol_linear_delta3_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 7) < + subghz_protocol_linear_delta3_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8)); +} + +bool subghz_protocol_decoder_linear_delta3_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + + uint32_t data = instance->generic.data & 0xFF; + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX\r\n" + "DIP:" DIP_PATTERN "\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + data, + DATA_TO_DIP(data)); +} diff --git a/lib/subghz/protocols/linear_delta3.h b/lib/subghz/protocols/linear_delta3.h new file mode 100644 index 000000000..2f0a32e68 --- /dev/null +++ b/lib/subghz/protocols/linear_delta3.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME "LinearDelta3" + +typedef struct SubGhzProtocolDecoderLinearDelta3 SubGhzProtocolDecoderLinearDelta3; +typedef struct SubGhzProtocolEncoderLinearDelta3 SubGhzProtocolEncoderLinearDelta3; + +extern const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder; +extern const SubGhzProtocol subghz_protocol_linear_delta3; + +/** + * Allocate SubGhzProtocolEncoderLinearDelta3. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderLinearDelta3* pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void subghz_protocol_encoder_linear_delta3_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void subghz_protocol_encoder_linear_delta3_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderLinearDelta3. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderLinearDelta3* pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void subghz_protocol_decoder_linear_delta3_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void subghz_protocol_decoder_linear_delta3_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_linear_delta3_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 2022e9c47..a1f1bc149 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -1,19 +1,44 @@ #include "protocol_items.h" const SubGhzProtocol* subghz_protocol_registry_items[] = { - &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, - &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, - &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, - &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, - &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, - &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, - &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, - &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, - &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_smc5326, + &subghz_protocol_gate_tx, + &subghz_protocol_keeloq, + &subghz_protocol_star_line, + &subghz_protocol_nice_flo, + &subghz_protocol_came, + &subghz_protocol_faac_slh, + &subghz_protocol_nice_flor_s, + &subghz_protocol_came_twee, + &subghz_protocol_came_atomo, + &subghz_protocol_nero_sketch, + &subghz_protocol_ido, + &subghz_protocol_kia, + &subghz_protocol_hormann, + &subghz_protocol_nero_radio, + &subghz_protocol_somfy_telis, + &subghz_protocol_somfy_keytis, + &subghz_protocol_scher_khan, + &subghz_protocol_princeton, + &subghz_protocol_raw, + &subghz_protocol_linear, + &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, + &subghz_protocol_megacode, + &subghz_protocol_holtek, + &subghz_protocol_chamb_code, + &subghz_protocol_power_smart, + &subghz_protocol_marantec, + &subghz_protocol_bett, + &subghz_protocol_doitrand, + &subghz_protocol_phoenix_v2, + &subghz_protocol_honeywell_wdb, + &subghz_protocol_magellan, + &subghz_protocol_intertechno_v3, + &subghz_protocol_clemsa, + &subghz_protocol_ansonic, + &subghz_protocol_smc5326, &subghz_protocol_holtek_th12x, + &subghz_protocol_linear_delta3, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 998fb56b3..185e47394 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -21,6 +21,7 @@ #include "gate_tx.h" #include "raw.h" #include "linear.h" +#include "linear_delta3.h" #include "secplus_v2.h" #include "secplus_v1.h" #include "megacode.h" From 0afc4a8982265d432a473b26cc94973f105973ca Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 8 Feb 2023 20:37:24 +0400 Subject: [PATCH 11/34] [FL-3092] SubGhz: add DOOYA protocol (#2178) * SubGhz: add DOOYA protocol * SubGhz: add unit_test DOOYA protocol * SubGhz: fix protocol Dooya Co-authored-by: Aleksandr Kutuzov --- .../debug/unit_tests/subghz/subghz_test.c | 17 +- assets/unit_tests/subghz/dooya.sub | 7 + assets/unit_tests/subghz/dooya_raw.sub | 8 + assets/unit_tests/subghz/test_random_raw.sub | 3 + lib/subghz/protocols/dooya.c | 447 ++++++++++++++++++ lib/subghz/protocols/dooya.h | 107 +++++ lib/subghz/protocols/protocol_items.c | 3 +- lib/subghz/protocols/protocol_items.h | 1 + 8 files changed, 591 insertions(+), 2 deletions(-) create mode 100644 assets/unit_tests/subghz/dooya.sub create mode 100644 assets/unit_tests/subghz/dooya_raw.sub create mode 100644 lib/subghz/protocols/dooya.c create mode 100644 lib/subghz/protocols/dooya.h diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 83fadeda9..0dba19d90 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 295 +#define TEST_RANDOM_COUNT_PARSE 300 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -612,6 +612,13 @@ MU_TEST(subghz_decoder_holtek_ht12x_test) { "Test decoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n"); } +MU_TEST(subghz_decoder_dooya_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/dooya_raw.sub"), SUBGHZ_PROTOCOL_DOOYA_NAME), + "Test decoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -757,6 +764,12 @@ MU_TEST(subghz_encoder_holtek_ht12x_test) { "Test encoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n"); } +MU_TEST(subghz_encoder_dooya_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/dooya.sub")), + "Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -803,6 +816,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_ansonic_test); MU_RUN_TEST(subghz_decoder_smc5326_test); MU_RUN_TEST(subghz_decoder_holtek_ht12x_test); + MU_RUN_TEST(subghz_decoder_dooya_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -828,6 +842,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_ansonic_test); MU_RUN_TEST(subghz_encoder_smc5326_test); MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); + MU_RUN_TEST(subghz_encoder_dooya_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/assets/unit_tests/subghz/dooya.sub b/assets/unit_tests/subghz/dooya.sub new file mode 100644 index 000000000..0767a1a73 --- /dev/null +++ b/assets/unit_tests/subghz/dooya.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Dooya +Bit: 40 +Key: 00 00 00 E1 DC 03 05 11 diff --git a/assets/unit_tests/subghz/dooya_raw.sub b/assets/unit_tests/subghz/dooya_raw.sub new file mode 100644 index 000000000..6c3ca1627 --- /dev/null +++ b/assets/unit_tests/subghz/dooya_raw.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 4046 -17306 65 -298 97 -100 133 -268 265 -330 133 -132 1723 -16806 165 -132 99 -920 65 -622 789 -130 99 -66 361 -98 295 -166 73573 -17510 97 -492 129 -728 529 -100 1063 -164 295 -66 1119 -14962 627 -166 363 -264 427 -132 593 -100 633 -132 39555 -16938 99 -2024 65 -100 97 -164 99 -66 399 -100 123891 -16736 163 -200 97 -200 165 -264 65 -828 427 -132 871 -5132 591 -490 595 -486 605 -454 275 -822 241 -824 273 -784 321 -782 649 -444 653 -408 657 -428 321 -744 693 -388 699 -388 707 -392 313 -752 345 -750 317 -744 351 -730 355 -738 323 -774 327 -748 329 -750 695 -386 701 -354 381 -722 351 -720 385 -718 351 -718 345 -738 705 -382 329 -736 713 -360 387 -718 369 -718 367 -706 735 -352 375 -726 351 -722 351 -720 719 -7808 4845 -1474 743 -332 741 -370 705 -370 349 -718 383 -716 345 -712 381 -704 747 -326 747 -350 737 -352 351 -718 719 -360 741 -366 687 -362 375 -704 381 -724 351 -740 353 -712 357 -718 359 -744 363 -688 365 -722 727 -354 727 -354 379 -724 351 -722 353 -720 387 -718 353 -718 703 -374 351 -716 735 -354 365 -708 353 -734 351 -746 717 -356 359 -720 371 -704 371 -720 731 -7786 4847 -1482 711 -386 711 -358 743 -330 373 -708 359 -748 349 -740 351 -716 719 -356 727 -354 739 -354 351 -718 719 -362 743 -364 721 -330 373 -706 381 -722 351 -740 353 -712 359 -720 361 -722 361 -720 361 -720 725 -354 731 -354 381 -720 353 -722 385 -720 351 -720 349 -716 735 -354 361 -748 711 -364 347 -740 365 -722 365 -720 695 -384 371 -704 381 -702 377 -710 709 -7804 4853 -1468 743 -336 735 -358 719 -352 379 -724 353 -722 353 -720 387 -686 721 -360 721 -362 743 -332 387 -718 721 -366 701 -382 701 -350 377 -720 351 -740 353 -714 357 -710 397 -710 365 -702 385 -688 377 -724 731 -352 703 -354 379 -736 343 -740 357 -720 349 -706 385 -718 719 -354 365 -724 735 -352 377 -724 355 -720 353 -720 721 -358 387 -686 387 -718 353 -718 733 -7796 4821 -1492 739 -350 719 -334 737 -350 365 -722 373 -722 367 -708 371 -702 747 -352 711 -358 743 -364 343 -706 749 -352 717 -350 717 -384 327 -736 351 -746 355 -716 357 -720 359 -710 365 -742 365 -708 367 -704 711 -354 743 -356 387 -684 373 -706 381 -722 351 -740 353 -714 721 -356 361 -720 733 -352 375 -694 385 -724 353 -722 719 -356 385 -686 385 -718 351 -716 731 -7792 4843 -1480 717 -354 719 -386 717 -354 359 -720 351 -708 387 -712 355 -718 721 -356 727 -354 739 -356 351 -718 741 -364 +RAW_Data: 705 -370 703 -372 351 -718 383 -720 347 -720 347 -714 381 -704 353 -744 357 -718 355 -720 723 -356 725 -354 379 -722 351 -722 353 -722 385 -718 351 -718 721 -372 351 -716 719 -372 351 -718 383 -716 345 -714 743 -346 361 -740 353 -712 357 -710 725 -7818 4837 -1498 713 -356 709 -360 741 -332 375 -706 359 -750 351 -706 353 -748 719 -356 723 -352 739 -354 351 -718 709 -364 719 -362 721 -364 385 -718 353 -718 383 -682 377 -712 349 -734 353 -742 355 -712 359 -722 723 -354 729 -352 381 -722 353 -722 351 -720 387 -718 353 -716 701 -388 345 -722 737 -354 357 -722 351 -708 387 -712 717 -350 731 -354 741 -356 743 -330 375 -8180 4829 -1468 739 -364 707 -354 729 -352 379 -722 353 -720 387 -686 387 -718 707 -368 721 -366 707 -368 351 -718 735 -354 719 -354 719 -388 329 -746 349 -738 351 -712 359 -718 361 -742 365 -708 371 -706 373 -720 733 -320 733 -354 383 -720 353 -720 387 -718 351 -716 385 -714 703 -388 327 -746 705 -348 387 -702 385 -690 385 -724 713 -358 709 -362 743 -364 709 -370 351 -8162 4837 -1482 715 -388 715 -352 715 -384 325 -730 353 -744 353 -712 359 -720 723 -354 733 -354 745 -356 351 -720 719 -362 741 -330 737 -382 349 -722 345 -724 361 -744 349 -704 383 -716 357 -718 357 -720 361 -720 723 -354 733 -354 383 -720 387 -686 387 -718 353 -718 349 -716 731 -384 347 -724 721 -352 365 -706 353 -732 353 -746 717 -356 723 -352 739 -354 711 -360 385 -8146 4841 -1470 737 -344 739 -326 751 -352 377 -690 387 -724 353 -724 353 -722 711 -360 743 -364 721 -330 387 -716 703 -386 721 -356 721 -354 363 -706 349 -734 351 -746 355 -718 355 -712 363 -744 365 -708 369 -722 695 -352 731 -354 381 -722 353 -722 351 -734 351 -716 383 -720 723 -354 333 -736 739 -348 361 -708 351 -748 355 -712 725 -354 727 -352 741 -352 713 -358 385 -8134 4855 -1474 719 -358 709 -362 721 -364 387 -716 351 -718 385 -712 347 -712 739 -334 739 -354 729 -352 379 -722 717 -354 711 -360 743 -332 387 -718 351 -716 377 -708 349 -730 353 -742 355 -710 359 -720 359 -720 723 -354 729 -352 381 -720 353 -722 351 -722 387 -684 387 -716 703 -384 349 -722 737 -354 329 -750 349 -738 353 -712 719 -356 725 -354 741 -354 717 -358 385 -8126 4861 -1470 735 -344 731 -346 729 -348 383 -718 347 -712 353 -734 353 -746 715 -356 725 -350 741 -352 351 -718 741 -366 721 -366 705 -370 353 -718 385 -682 377 -710 349 -734 353 -744 355 -710 359 -710 397 -688 +RAW_Data: 727 -354 729 -352 379 -724 353 -722 353 -718 387 -716 353 -716 735 -348 383 -682 727 -386 347 -722 347 -712 381 -706 747 -326 747 -350 737 -352 711 -358 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 7571d688d..aee15a16d 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -175,3 +175,6 @@ RAW_Data: 75 -1694 101 -122 73 -864 51 -250 129 -406 77 -630 77 -610 101 -781 12 RAW_Data: 83 -320 81 -4648 101 -3726 173 -1418 85 -348 53 -2994 79 -1390 51 -1656 107 -764 53 -134 79 -1619 131 -932 55 -2810 107 -3218 79 -765 107 -654 103 -1498 77 -228 51 -134 247 -1526 51 -3903 103 -1495 179 -282 77 -392 53 -1756 105 -368 111 -486 51 -298 53 -216 113 -358 51 -266 187 -1059 81 -780 105 -238 51 -482 53 -791 109 -2169 77 -5304 53 -398 79 -650 51 -54 51 -1789 73 -198 101 -1580 101 -746 97 -4518 53 -744 51 -1064 101 -928 111 -392 185 -869 103 -320 133 -704 81 -244 53 -1628 75 -634 79 -666 183 -1276 83 -218 107 -1163 55 -1276 127 -1144 73 -1400 81 -266 77 -568 129 -806 121 -1420 103 -848 77 -982 103 -2132 81 -1610 101 -1218 55 -2208 75 -2735 53 -921 53 -724 51 -472 83 -3164 185 -400 77 -812 81 -306 215 -2167 53 -130 53 -272 81 -400 79 -1272 81 -418 51 -1381 73 -340 101 -2169 81 -2330 137 -2698 99 -2340 99 -126 51 -1714 55 -488 81 -3500 51 -404 77 -1422 77 -856 215 -80 51 -2308 53 -134 77 -2036 75 -5175 129 -946 239 -638 53 -244 55 -564 105 -826 71 -1632 77 -106 129 -246 135 -366 79 -724 79 -1535 57 -1085 113 -1320 79 -3111 127 -1578 75 -324 75 -102 173 -364 79 -1374 53 -1508 107 -622 51 -526 109 -584 187 -2648 51 -106 79 -380 103 -604 51 -1244 73 -5766 107 -1934 177 -702 51 -1277 53 -1643 79 -1446 81 -4098 75 -574 103 -432 189 -1436 107 -454 79 -132 105 -136 81 -112 113 -942 239 -1238 79 -952 157 -340 51 -314 191 -456 53 -3368 101 -150 99 -464 51 -718 73 -770 101 -150 73 -2132 75 -557 77 -680 81 -3512 151 -760 75 -332 75 -1212 131 -1468 79 -1955 101 -541 75 -344 79 -2146 53 -2299 97 -720 79 -2518 79 -3807 51 -1272 75 -352 77 -52 75 -586 53 -1142 79 -82 81 -2400 157 -324 81 -268 103 -1154 81 -1175 79 -1191 51 -1074 53 -2566 137 -854 75 -1497 51 -4533 51 -2290 51 -344 77 -348 55 -1182 77 -897 135 -874 51 -1064 51 -208 55 -140 55 -1334 133 -1238 157 -1669 113 -2128 75 -848 85 -510 83590 -126 333 -280 331 -252 331 -6946 331 -276 331 -276 329 -278 329 -276 331 -276 331 -276 331 -276 347 -238 351 -254 353 -268 323 -270 345 -6924 335 -282 307 -304 307 -304 281 -304 307 -302 307 -302 305 -302 307 -302 305 -302 281 -124 507 -282 305 -302 305 -6984 279 -328 277 -328 279 -328 277 -330 277 -304 303 -302 305 -302 305 -302 303 -304 303 -100 507 -314 295 -298 293 -6986 283 -334 281 -306 283 -328 283 -328 281 -328 283 -328 255 -352 RAW_Data: -66 11813 -100 14655 -98 40111 -66 1625 -2116 1933 -34732 501 -11730 235 -3728 1887 -2106 1933 -2092 1971 -2072 1959 -34712 511 -3554 445 -3556 1997 -2036 455 -3594 1963 -2046 1979 -2076 1961 -2070 1989 -34690 483 -7724 1739 -2226 355 -3684 1857 -2138 1929 -2078 1965 -2074 1947 -34750 487 -3538 473 -3544 1993 -2042 485 -3548 1961 -2070 1965 -2070 1969 -2042 1997 -34716 443 -7734 1753 -2236 323 -3676 1903 -2098 1945 -2102 1927 -2070 1989 -34710 521 -3532 473 -3544 1991 -2032 481 -3556 1969 -2076 1967 -2036 1991 -2066 1969 -34718 467 -7756 1739 -2192 363 -3654 1889 -2132 1929 -2096 1935 -2070 1987 -34716 511 -3522 471 -3554 2009 -2036 459 -3550 2003 -2038 1979 -2042 1999 -2042 1999 -34704 471 -11774 225 -3710 1879 -2162 1885 -2112 1925 -2110 1939 -34738 459 -3636 403 -3612 1939 -2062 451 -3566 1985 -2044 1995 -2040 2009 -2032 2003 -34684 495 -3680 295 -3648 1935 -2098 423 -3562 2001 -2038 1989 -2044 2003 -2036 1977 -34718 461 -3678 295 -3684 1901 -2098 429 -3596 1967 -2036 1981 -2048 1993 -2042 2013 -34686 521 -3530 457 -3568 1999 -2036 455 -3552 1999 -2032 2019 -2024 1995 -2022 1997 -34716 441 -15774 1809 -2192 1905 -2100 1919 -2112 1961 -34720 417 -3830 167 -3710 1863 -2144 357 -3674 1909 -2100 1955 -2062 1977 -2072 1965 -34710 487 -3562 453 -3554 1985 -2052 481 -3536 2019 -2010 2001 -2042 1997 -2038 2005 -34716 451 -3602 433 -3584 1959 -2070 451 -3560 2001 -2038 1993 -2042 1967 -2072 1973 -34712 459 -3622 393 -3624 1933 -2068 457 -3584 1965 -2064 1979 -2052 1967 -2044 1981 -34722 477 -3608 397 -3588 1961 -2096 413 -3596 1971 -2040 1979 -2072 1963 -2070 1959 -34714 495 -3558 483 -3538 1985 -2042 479 -3562 1985 -2046 1967 -2070 1973 -2054 1995 -34688 493 -3578 413 -3614 1939 -2074 465 -3560 1971 -2038 2017 -2018 1995 -2042 2013 -34726 479 -3528 475 -3556 1999 -2036 455 -3570 1999 -2040 1973 -2054 2001 -2032 1987 -34720 477 -3562 445 -3602 1949 -2054 481 -3562 1975 -2060 1963 -2064 1977 -2038 2005 -34702 485 -3570 447 -3550 2015 -2020 479 -3564 1983 -2048 1999 -2034 1971 -2064 1993 -34688 517 -3516 497 -3532 1999 -2038 481 -3558 1997 -2004 2027 -2042 1963 -2038 1997 -34716 491 -3562 461 -3548 1995 -2032 491 -3524 2005 -2036 1989 -2038 1995 -2046 1979 -34714 465 -3682 293 -3680 1905 -2096 431 -3592 1969 -2070 1977 -2052 1965 -2044 1981 -34734 479 -3564 463 -3556 1999 -2032 457 -3550 1995 -2044 2011 -2042 1997 -2006 2027 -34680 531 -3524 483 -3538 1987 -2044 479 -3534 2013 -2048 1965 -2062 1987 -2030 1997 -34712 473 -3592 445 -3562 1975 -2072 451 -3566 1965 -2042 2013 -2046 1963 -2064 1993 -34700 459 -3632 371 -3638 1915 -2084 449 -3568 1987 -2046 1971 -2070 1983 -2022 1997 -34726 487 -3524 477 -3562 1985 -2044 481 -3542 2005 -2040 1995 -2038 1967 -2046 1993 -34710 511 -3528 471 -3560 1967 -2070 459 -3558 1971 RAW_Data: -2072 1971 -2056 1971 -2074 1973 -34714 455 -3634 373 -3634 1901 -2110 419 -3620 1941 -2070 1991 -2040 1999 -2038 1965 -34740 467 -3562 481 -3534 1983 -2070 449 -3546 1999 -2044 1993 -2042 2003 -2036 1975 -34702 521 -3560 443 -3586 1969 -2044 449 -3562 1997 -2046 1987 -2042 2007 -2034 1973 -34732 487 -3562 443 -3582 1979 -2058 445 -3560 1995 -2044 1997 -2028 1987 -2034 2003 -34710 515 -3518 485 -3566 1977 -2036 483 -3536 1999 -2044 2009 -2024 1995 -2068 1973 -34710 487 -3564 471 -3558 1977 -2054 447 -3564 1991 -2042 1997 -2036 2007 -2034 2001 -34684 529 -3526 469 -3548 1989 -2038 483 -3562 1997 -2038 1973 -2034 1999 -2036 1997 -34728 487 -3536 479 -3534 2013 -2044 449 -3570 1985 -2042 1993 -2044 2005 -2014 1995 -34710 473 -3594 439 -3562 1995 -2040 457 -3564 2001 -2040 1975 -2046 1995 -2046 1999 -34704 491 -3548 451 -3570 1991 -2042 447 -3578 1967 -2046 1995 -2042 1999 -2034 2001 -34712 491 -3562 443 -3584 1981 -2018 479 -3562 1985 -2044 1997 -2030 1989 -2040 1997 -34722 489 -3554 459 -3560 1969 -2068 453 -3554 1999 -2034 1987 -2058 1997 -2046 1983 -34702 487 -3534 479 -3564 1983 -2040 483 -3538 1981 -2048 1993 -2048 2007 -2044 1995 -34696 489 -3550 453 -3570 1995 -2050 447 -3564 1983 -2040 1999 -2034 2003 -2034 1995 -34690 495 -3580 433 -3586 1969 -2064 453 -3552 1995 -2036 1991 -2056 1997 -2046 1987 -34706 441 -3636 373 -3626 1959 -2074 419 -3592 1963 -2074 1989 -2044 1971 -2070 1981 -34698 509 -3526 503 -3528 2005 -2034 481 -3528 1993 -2042 1999 -2066 1989 -2034 2003 -34678 495 -3540 481 -3546 1997 -2046 473 -3554 1999 -2034 2001 -2036 1995 -2046 1983 -34720 475 -3560 469 -3548 1997 -2030 485 -3566 1963 -2066 1983 -2046 1999 -2034 1973 -34734 487 -3560 443 -3584 1981 -2052 445 -3568 1987 -2044 1999 -2032 1993 -2034 2007 -34702 491 -3560 459 -3558 1967 -2070 455 -3556 2003 -2036 1977 -2042 2005 -2028 1997 -34730 461 -3564 473 -3536 2011 -2046 449 -3566 1989 -2044 1997 -2042 1971 -2054 2001 -34708 475 -3560 479 -3528 1999 -2040 485 -3566 1963 -2040 2013 -2042 1995 -2034 1987 -34694 519 -3554 441 -3582 1981 -2052 449 -3564 1985 -2040 1993 -2034 1991 -2062 1975 -34714 529 -3534 463 -3558 1969 -2068 451 -3560 2003 -2038 1993 -2042 1969 -2070 1975 -34720 493 -3582 383 -3616 1937 -2072 469 -3558 1995 -2036 1975 -2066 1995 -2042 1989 -34678 531 -3560 391 -3622 1937 -2094 429 -3588 1967 -2070 1981 -2054 1965 -2038 2021 -34682 525 -3524 481 -3564 1989 -2040 445 -3554 1997 -2040 2005 -2034 2001 -2024 1991 -34706 517 -3586 409 -3610 1927 -2076 451 -3558 1967 -2074 1993 -2038 2001 -2040 1975 -34714 495 -3588 409 -3602 1933 -2088 447 -3584 1965 -2044 1999 -2036 2007 -2030 1995 -34692 525 -3538 447 -3580 1981 -2042 487 -3542 1995 -2040 1969 -2072 1969 -2044 1991 -34714 443 -3636 399 -3630 1899 -2106 413 -3584 1997 +RAW_Data: 4046 -17306 65 -298 97 -100 133 -268 265 -330 133 -132 1723 -16806 165 -132 99 -920 65 -622 789 -130 99 -66 361 -98 295 -166 73573 -17510 97 -492 129 -728 529 -100 1063 -164 295 -66 1119 -14962 627 -166 363 -264 427 -132 593 -100 633 -132 39555 -16938 99 -2024 65 -100 97 -164 99 -66 399 -100 123891 -16736 163 -200 97 -200 165 -264 65 -828 427 -132 871 -5132 591 -490 595 -486 605 -454 275 -822 241 -824 273 -784 321 -782 649 -444 653 -408 657 -428 321 -744 693 -388 699 -388 707 -392 313 -752 345 -750 317 -744 351 -730 355 -738 323 -774 327 -748 329 -750 695 -386 701 -354 381 -722 351 -720 385 -718 351 -718 345 -738 705 -382 329 -736 713 -360 387 -718 369 -718 367 -706 735 -352 375 -726 351 -722 351 -720 719 -7808 4845 -1474 743 -332 741 -370 705 -370 349 -718 383 -716 345 -712 381 -704 747 -326 747 -350 737 -352 351 -718 719 -360 741 -366 687 -362 375 -704 381 -724 351 -740 353 -712 357 -718 359 -744 363 -688 365 -722 727 -354 727 -354 379 -724 351 -722 353 -720 387 -718 353 -718 703 -374 351 -716 735 -354 365 -708 353 -734 351 -746 717 -356 359 -720 371 -704 371 -720 731 -7786 4847 -1482 711 -386 711 -358 743 -330 373 -708 359 -748 349 -740 351 -716 719 -356 727 -354 739 -354 351 -718 719 -362 743 -364 721 -330 373 -706 381 -722 351 -740 353 -712 359 -720 361 -722 361 -720 361 -720 725 -354 731 -354 381 -720 353 -722 385 -720 351 -720 349 -716 735 -354 361 -748 711 -364 347 -740 365 -722 365 -720 695 -384 371 -704 381 -702 377 -710 709 -7804 4853 -1468 743 -336 735 -358 719 -352 379 -724 353 -722 353 -720 387 -686 721 -360 721 -362 743 -332 387 -718 721 -366 701 -382 701 -350 377 -720 351 -740 353 -714 357 -710 397 -710 365 -702 385 -688 377 -724 731 -352 703 -354 379 -736 343 -740 357 -720 349 -706 385 -718 719 -354 365 -724 735 -352 377 -724 355 -720 353 -720 721 -358 387 -686 387 -718 353 -718 733 -7796 4821 -1492 739 -350 719 -334 737 -350 365 -722 373 -722 367 -708 371 -702 747 -352 711 -358 743 -364 343 -706 749 -352 717 -350 717 -384 327 -736 351 -746 355 -716 357 -720 359 -710 365 -742 365 -708 367 -704 711 -354 743 -356 387 -684 373 -706 381 -722 351 -740 353 -714 721 -356 361 -720 733 -352 375 -694 385 -724 353 -722 719 -356 385 -686 385 -718 351 -716 731 -7792 4843 -1480 717 -354 719 -386 717 -354 359 -720 351 -708 387 -712 355 -718 721 -356 727 -354 739 -356 351 -718 741 -364 +RAW_Data: 705 -370 703 -372 351 -718 383 -720 347 -720 347 -714 381 -704 353 -744 357 -718 355 -720 723 -356 725 -354 379 -722 351 -722 353 -722 385 -718 351 -718 721 -372 351 -716 719 -372 351 -718 383 -716 345 -714 743 -346 361 -740 353 -712 357 -710 725 -7818 4837 -1498 713 -356 709 -360 741 -332 375 -706 359 -750 351 -706 353 -748 719 -356 723 -352 739 -354 351 -718 709 -364 719 -362 721 -364 385 -718 353 -718 383 -682 377 -712 349 -734 353 -742 355 -712 359 -722 723 -354 729 -352 381 -722 353 -722 351 -720 387 -718 353 -716 701 -388 345 -722 737 -354 357 -722 351 -708 387 -712 717 -350 731 -354 741 -356 743 -330 375 -8180 4829 -1468 739 -364 707 -354 729 -352 379 -722 353 -720 387 -686 387 -718 707 -368 721 -366 707 -368 351 -718 735 -354 719 -354 719 -388 329 -746 349 -738 351 -712 359 -718 361 -742 365 -708 371 -706 373 -720 733 -320 733 -354 383 -720 353 -720 387 -718 351 -716 385 -714 703 -388 327 -746 705 -348 387 -702 385 -690 385 -724 713 -358 709 -362 743 -364 709 -370 351 -8162 4837 -1482 715 -388 715 -352 715 -384 325 -730 353 -744 353 -712 359 -720 723 -354 733 -354 745 -356 351 -720 719 -362 741 -330 737 -382 349 -722 345 -724 361 -744 349 -704 383 -716 357 -718 357 -720 361 -720 723 -354 733 -354 383 -720 387 -686 387 -718 353 -718 349 -716 731 -384 347 -724 721 -352 365 -706 353 -732 353 -746 717 -356 723 -352 739 -354 711 -360 385 -8146 4841 -1470 737 -344 739 -326 751 -352 377 -690 387 -724 353 -724 353 -722 711 -360 743 -364 721 -330 387 -716 703 -386 721 -356 721 -354 363 -706 349 -734 351 -746 355 -718 355 -712 363 -744 365 -708 369 -722 695 -352 731 -354 381 -722 353 -722 351 -734 351 -716 383 -720 723 -354 333 -736 739 -348 361 -708 351 -748 355 -712 725 -354 727 -352 741 -352 713 -358 385 -8134 4855 -1474 719 -358 709 -362 721 -364 387 -716 351 -718 385 -712 347 -712 739 -334 739 -354 729 -352 379 -722 717 -354 711 -360 743 -332 387 -718 351 -716 377 -708 349 -730 353 -742 355 -710 359 -720 359 -720 723 -354 729 -352 381 -720 353 -722 351 -722 387 -684 387 -716 703 -384 349 -722 737 -354 329 -750 349 -738 353 -712 719 -356 725 -354 741 -354 717 -358 385 -8126 4861 -1470 735 -344 731 -346 729 -348 383 -718 347 -712 353 -734 353 -746 715 -356 725 -350 741 -352 351 -718 741 -366 721 -366 705 -370 353 -718 385 -682 377 -710 349 -734 353 -744 355 -710 359 -710 397 -688 +RAW_Data: 727 -354 729 -352 379 -724 353 -722 353 -718 387 -716 353 -716 735 -348 383 -682 727 -386 347 -722 347 -712 381 -706 747 -326 747 -350 737 -352 711 -358 diff --git a/lib/subghz/protocols/dooya.c b/lib/subghz/protocols/dooya.c new file mode 100644 index 000000000..c70b6d54e --- /dev/null +++ b/lib/subghz/protocols/dooya.c @@ -0,0 +1,447 @@ +#include "dooya.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolDooya" + +#define DOYA_SINGLE_CHANNEL 0xFF + +static const SubGhzBlockConst subghz_protocol_dooya_const = { + .te_short = 366, + .te_long = 733, + .te_delta = 120, + .min_count_bit_for_found = 40, +}; + +struct SubGhzProtocolDecoderDooya { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderDooya { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + DooyaDecoderStepReset = 0, + DooyaDecoderStepFoundStartBit, + DooyaDecoderStepSaveDuration, + DooyaDecoderStepCheckDuration, +} DooyaDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_dooya_decoder = { + .alloc = subghz_protocol_decoder_dooya_alloc, + .free = subghz_protocol_decoder_dooya_free, + + .feed = subghz_protocol_decoder_dooya_feed, + .reset = subghz_protocol_decoder_dooya_reset, + + .get_hash_data = subghz_protocol_decoder_dooya_get_hash_data, + .serialize = subghz_protocol_decoder_dooya_serialize, + .deserialize = subghz_protocol_decoder_dooya_deserialize, + .get_string = subghz_protocol_decoder_dooya_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_dooya_encoder = { + .alloc = subghz_protocol_encoder_dooya_alloc, + .free = subghz_protocol_encoder_dooya_free, + + .deserialize = subghz_protocol_encoder_dooya_deserialize, + .stop = subghz_protocol_encoder_dooya_stop, + .yield = subghz_protocol_encoder_dooya_yield, +}; + +const SubGhzProtocol subghz_protocol_dooya = { + .name = SUBGHZ_PROTOCOL_DOOYA_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | + SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_dooya_decoder, + .encoder = &subghz_protocol_dooya_encoder, +}; + +void* subghz_protocol_encoder_dooya_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderDooya* instance = malloc(sizeof(SubGhzProtocolEncoderDooya)); + + instance->base.protocol = &subghz_protocol_dooya; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_dooya_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderDooya* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderDooya instance + * @return true On success + */ +static bool subghz_protocol_encoder_dooya_get_upload(SubGhzProtocolEncoderDooya* instance) { + furi_assert(instance); + + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send header + if(bit_read(instance->generic.data, 0)) { + instance->encoder.upload[index++] = level_duration_make( + false, + (uint32_t)subghz_protocol_dooya_const.te_long * 12 + + subghz_protocol_dooya_const.te_long); + } else { + instance->encoder.upload[index++] = level_duration_make( + false, + (uint32_t)subghz_protocol_dooya_const.te_long * 12 + + subghz_protocol_dooya_const.te_short); + } + + //Send start bit + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_short * 13); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_long * 2); + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_long); + } + } + return true; +} + +bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderDooya* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_dooya_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_dooya_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_dooya_stop(void* context) { + SubGhzProtocolEncoderDooya* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_dooya_yield(void* context) { + SubGhzProtocolEncoderDooya* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_dooya_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderDooya* instance = malloc(sizeof(SubGhzProtocolDecoderDooya)); + instance->base.protocol = &subghz_protocol_dooya; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_dooya_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + free(instance); +} + +void subghz_protocol_decoder_dooya_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + instance->decoder.parser_step = DooyaDecoderStepReset; +} + +void subghz_protocol_decoder_dooya_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + + switch(instance->decoder.parser_step) { + case DooyaDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long * 12) < + subghz_protocol_dooya_const.te_delta * 20)) { + instance->decoder.parser_step = DooyaDecoderStepFoundStartBit; + } + break; + + case DooyaDecoderStepFoundStartBit: + if(!level) { + if(DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long * 2) < + subghz_protocol_dooya_const.te_delta * 3) { + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + } else if( + DURATION_DIFF(duration, subghz_protocol_dooya_const.te_short * 13) < + subghz_protocol_dooya_const.te_delta * 5) { + break; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + + case DooyaDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = DooyaDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + + case DooyaDecoderStepCheckDuration: + if(!level) { + if(duration >= (subghz_protocol_dooya_const.te_long * 4)) { + //add last bit + if(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else if( + DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + break; + } + instance->decoder.parser_step = DooyaDecoderStepFoundStartBit; + if(instance->decoder.decode_count_bit == + subghz_protocol_dooya_const.min_count_bit_for_found) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGeneric* instance) { + /* + * serial s/m ch key + * long press down X * E1DC030533, 40b 111000011101110000000011 0000 0101 0011 0011 + * + * short press down 3 * E1DC030533, 40b 111000011101110000000011 0000 0101 0011 0011 + * 3 * E1DC03053C, 40b 111000011101110000000011 0000 0101 0011 1100 + * + * press stop X * E1DC030555, 40b 111000011101110000000011 0000 0101 0101 0101 + * + * long press up X * E1DC030511, 40b 111000011101110000000011 0000 0101 0001 0001 + * + * short press up 3 * E1DC030511, 40b 111000011101110000000011 0000 0101 0001 0001 + * 3 * E1DC03051E, 40b 111000011101110000000011 0000 0101 0001 1110 + * + * serial: 3 byte serial number + * s/m: single (b0000) / multi (b0001) channel console + * ch: channel if single (always b0101) or multi + * key: 0b00010001 - long press up + * 0b00011110 - short press up + * 0b00110011 - long press down + * 0b00111100 - short press down + * 0b01010101 - press stop + * 0b01111001 - press up + down + * 0b10000000 - press up + stop + * 0b10000001 - press down + stop + * 0b11001100 - press P2 + * +*/ + + instance->serial = (instance->data >> 16); + if((instance->data >> 12) & 0x0F) { + instance->cnt = (instance->data >> 8) & 0x0F; + } else { + instance->cnt = DOYA_SINGLE_CHANNEL; + } + instance->btn = instance->data & 0xFF; +} + +uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_dooya_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_dooya_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +/** + * Get button name. + * @param btn Button number, 8 bit + */ +static const char* subghz_protocol_dooya_get_name_button(uint8_t btn) { + const char* btn_name; + switch(btn) { + case 0b00010001: + btn_name = "Up_Long"; + break; + case 0b00011110: + btn_name = "Up_Short"; + break; + case 0b00110011: + btn_name = "Down_Long"; + break; + case 0b00111100: + btn_name = "Down_Short"; + break; + case 0b01010101: + btn_name = "Stop"; + break; + case 0b01111001: + btn_name = "Up+Down"; + break; + case 0b10000000: + btn_name = "Up+Stop"; + break; + case 0b10000001: + btn_name = "Down+Stop"; + break; + case 0b11001100: + btn_name = "P2"; + break; + default: + btn_name = "Unknown"; + break; + } + return btn_name; +} + +void subghz_protocol_decoder_dooya_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + + subghz_protocol_somfy_telis_check_remote_controller(&instance->generic); + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%010llX\r\n" + "Sn:0x%08lX\r\n" + "Btn:%s\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + instance->generic.data, + instance->generic.serial, + subghz_protocol_dooya_get_name_button(instance->generic.btn)); + if(instance->generic.cnt == DOYA_SINGLE_CHANNEL) { + furi_string_cat_printf(output, "Ch:Single\r\n"); + } else { + furi_string_cat_printf(output, "Ch:%lu\r\n", instance->generic.cnt); + } +} diff --git a/lib/subghz/protocols/dooya.h b/lib/subghz/protocols/dooya.h new file mode 100644 index 000000000..f0cf843c0 --- /dev/null +++ b/lib/subghz/protocols/dooya.h @@ -0,0 +1,107 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_DOOYA_NAME "Dooya" + +typedef struct SubGhzProtocolDecoderDooya SubGhzProtocolDecoderDooya; +typedef struct SubGhzProtocolEncoderDooya SubGhzProtocolEncoderDooya; + +extern const SubGhzProtocolDecoder subghz_protocol_dooya_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_dooya_encoder; +extern const SubGhzProtocol subghz_protocol_dooya; + +/** + * Allocate SubGhzProtocolEncoderDooya. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderDooya* pointer to a SubGhzProtocolEncoderDooya instance + */ +void* subghz_protocol_encoder_dooya_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderDooya. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + */ +void subghz_protocol_encoder_dooya_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + */ +void subghz_protocol_encoder_dooya_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_dooya_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderDooya. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderDooya* pointer to a SubGhzProtocolDecoderDooya instance + */ +void* subghz_protocol_decoder_dooya_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + */ +void subghz_protocol_decoder_dooya_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + */ +void subghz_protocol_decoder_dooya_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_dooya_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_dooya_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param output Resulting text + */ +void subghz_protocol_decoder_dooya_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index a1f1bc149..99de18c93 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -39,8 +39,9 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_smc5326, &subghz_protocol_holtek_th12x, &subghz_protocol_linear_delta3, + &subghz_protocol_dooya, }; const SubGhzProtocolRegistry subghz_protocol_registry = { .items = subghz_protocol_registry_items, - .size = COUNT_OF(subghz_protocol_registry_items)}; \ No newline at end of file + .size = COUNT_OF(subghz_protocol_registry_items)}; diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 185e47394..4d1551bb3 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -39,5 +39,6 @@ #include "ansonic.h" #include "smc5326.h" #include "holtek_ht12x.h" +#include "dooya.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; From 31259d530499b2ff6e07fd24a5ec3b8583a41ac0 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 8 Feb 2023 20:59:49 +0400 Subject: [PATCH 12/34] [FL-3091] SubGhz: add protocol Alutech at-4n (#2352) * GubGhz: add protocol Alutech at-4n * SubGhz: fix syntax * SubGhz: fix subghz_protocol_decoder_alutech_at_4n_get_hash_data * SubGhz: add unit test alutech at-4n * SubGhz: add name key Co-authored-by: Aleksandr Kutuzov --- .../debug/unit_tests/subghz/subghz_test.c | 14 +- applications/main/subghz/subghz.c | 2 + applications/main/subghz/subghz_cli.c | 4 + assets/resources/subghz/assets/alutech_at_4n | 6 + .../unit_tests/subghz/alutech_at_4n_raw.sub | 10 + assets/unit_tests/subghz/test_random_raw.sub | 5 + firmware/targets/f7/api_symbols.csv | 2 + lib/subghz/environment.c | 16 + lib/subghz/environment.h | 17 + lib/subghz/protocols/alutech_at_4n.c | 455 ++++++++++++++++++ lib/subghz/protocols/alutech_at_4n.h | 74 +++ lib/subghz/protocols/came_atomo.c | 2 +- lib/subghz/protocols/keeloq.c | 13 +- lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + 15 files changed, 617 insertions(+), 5 deletions(-) create mode 100644 assets/resources/subghz/assets/alutech_at_4n create mode 100644 assets/unit_tests/subghz/alutech_at_4n_raw.sub create mode 100644 lib/subghz/protocols/alutech_at_4n.c create mode 100644 lib/subghz/protocols/alutech_at_4n.h diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 0dba19d90..705d6f2f6 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -12,8 +12,9 @@ #define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes") #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") +#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 300 +#define TEST_RANDOM_COUNT_PARSE 304 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -43,6 +44,8 @@ static void subghz_test_init(void) { environment_handler, CAME_ATOMO_DIR_NAME); subghz_environment_set_nice_flor_s_rainbow_table_file_name( environment_handler, NICE_FLOR_S_DIR_NAME); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + environment_handler, ALUTECH_AT_4N_DIR_NAME); subghz_environment_set_protocol_registry( environment_handler, (void*)&subghz_protocol_registry); @@ -619,6 +622,14 @@ MU_TEST(subghz_decoder_dooya_test) { "Test decoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n"); } +MU_TEST(subghz_decoder_alutech_at_4n_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/alutech_at_4n_raw.sub"), + SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME), + "Test decoder " SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -817,6 +828,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_smc5326_test); MU_RUN_TEST(subghz_decoder_holtek_ht12x_test); MU_RUN_TEST(subghz_decoder_dooya_test); + MU_RUN_TEST(subghz_decoder_alutech_at_4n_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index b7564ab57..200be6262 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -187,6 +187,8 @@ SubGhz* subghz_alloc() { subghz->txrx->environment = subghz_environment_alloc(); subghz_environment_set_came_atomo_rainbow_table_file_name( subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + subghz->txrx->environment, EXT_PATH("subghz/assets/alutech_at_4n")); subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s")); subghz_environment_set_protocol_registry( diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 9271443a8..ac19d65b4 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -257,6 +257,8 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); subghz_environment_set_came_atomo_rainbow_table_file_name( environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + environment, EXT_PATH("subghz/assets/alutech_at_4n")); subghz_environment_set_nice_flor_s_rainbow_table_file_name( environment, EXT_PATH("subghz/assets/nice_flor_s")); subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); @@ -452,6 +454,8 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { } subghz_environment_set_came_atomo_rainbow_table_file_name( environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + environment, EXT_PATH("subghz/assets/alutech_at_4n")); subghz_environment_set_nice_flor_s_rainbow_table_file_name( environment, EXT_PATH("subghz/assets/nice_flor_s")); subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry); diff --git a/assets/resources/subghz/assets/alutech_at_4n b/assets/resources/subghz/assets/alutech_at_4n new file mode 100644 index 000000000..5d7beacec --- /dev/null +++ b/assets/resources/subghz/assets/alutech_at_4n @@ -0,0 +1,6 @@ +Filetype: Flipper SubGhz Keystore RAW File +Version: 0 +Encryption: 1 +IV: 88 64 A6 A6 44 47 67 8A D6 32 36 F6 B9 06 57 31 +Encrypt_data: RAW +E811BD4F0955D217AE6677906E799D45D8DAAFD1F7923E1660B5E24574631B60 \ No newline at end of file diff --git a/assets/unit_tests/subghz/alutech_at_4n_raw.sub b/assets/unit_tests/subghz/alutech_at_4n_raw.sub new file mode 100644 index 000000000..ae5db9715 --- /dev/null +++ b/assets/unit_tests/subghz/alutech_at_4n_raw.sub @@ -0,0 +1,10 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -854 811 -454 811 -444 409 -838 811 -454 823 -432 385 -842 811 -454 389 -854 821 -418 837 -444 401 -850 417 -854 395 -830 417 -846 819 -432 811 -448 789 -444 839 -454 401 -856 381 -850 825 -410 841 -418 417 -834 411 -840 827 -442 417 -844 799 -472 809 -420 411 -842 419 -848 397 -822 413 -850 799 -486 381 -848 415 -854 423 -16394 449 -358 437 -386 411 -384 449 -382 417 -384 419 -386 417 -386 419 -388 419 -388 419 -388 419 -390 437 -4036 421 -810 425 -820 393 -866 813 -422 415 -856 397 -858 811 -456 427 -820 815 -416 419 -850 401 -854 805 -420 835 -444 409 -842 809 -454 433 -820 421 -838 813 -420 417 -822 435 -820 419 -834 431 -852 411 -866 805 -420 815 -444 805 -454 403 -824 809 -448 819 -448 413 -844 811 -446 811 -456 409 -816 809 -456 389 -866 387 -842 809 -454 827 -432 413 -850 829 -428 809 -452 381 -852 799 -452 413 -852 807 -450 801 -444 409 -872 411 -840 413 -812 413 -832 807 -450 815 -442 801 -454 809 -454 429 -820 419 -838 811 -456 785 -428 409 -842 439 -824 813 -448 415 -858 819 -418 831 -426 449 -808 427 -820 393 -866 421 -808 825 -436 413 -852 403 -884 421 -16394 407 -478 257 -574 229 -576 229 -564 231 -592 267 -490 305 -520 307 -486 309 -522 307 -458 341 -486 337 -4096 343 -882 389 -880 341 -874 807 -476 351 -882 397 -860 807 -450 431 -824 811 -450 399 -824 417 -844 817 -432 807 -448 411 -872 801 -460 417 -810 425 -836 809 -420 411 -838 409 -852 417 -844 425 -852 385 -872 801 -426 841 -420 811 -422 409 -844 809 -454 823 -432 415 -842 835 -450 805 -454 403 -822 809 -450 399 -826 417 -844 821 -434 807 -448 411 -876 801 -440 807 -450 383 -850 833 -416 415 -852 807 -456 811 -444 411 -838 419 -848 401 -852 377 -850 819 -454 795 -436 809 -448 821 -448 411 -846 417 -842 817 -432 811 -412 411 -864 417 -844 791 -438 415 -876 793 -458 809 -450 383 -832 413 -840 407 -866 387 -844 821 -434 413 -874 377 -868 419 -16408 411 -392 421 -390 421 -388 421 -376 427 -394 433 -388 409 -386 411 -384 449 -382 419 -384 419 -384 419 -4018 343 -89684 97 -430 65 -166 163 -66 231 -100 161 -392 161 -64 229 -1056 97 -198 97 -198 259 -166 691 -66 395 -98 131 -100 99 -66 199 -198 1657 -406 365 -462 361 -436 357 -438 387 -444 353 -444 385 -414 387 -448 355 -448 355 -444 395 -394 399 -4050 819 -434 811 -414 819 -450 409 -852 809 -450 805 -448 805 -446 831 -428 409 -846 389 -854 395 -862 811 +RAW_Data: -452 783 -462 811 -446 411 -874 383 -852 403 -852 777 -450 411 -838 805 -452 397 -858 805 -484 387 -872 803 -442 805 -448 383 -846 797 -484 777 -474 381 -846 831 -430 807 -482 387 -852 817 -418 805 -452 823 -430 385 -878 377 -876 411 -846 391 -884 811 -444 805 -420 415 -846 399 -852 807 -452 805 -444 803 -450 803 -454 807 -452 397 -850 395 -862 385 -844 427 -840 809 -456 379 -876 407 -880 383 -846 819 -432 387 -872 375 -854 413 -846 387 -886 779 -476 803 -450 801 -444 415 -846 793 -438 415 -846 417 -822 407 -852 417 -852 817 -444 409 -16426 443 -358 431 -388 409 -386 447 -350 449 -382 419 -386 419 -386 417 -386 419 -388 453 -354 453 -356 445 -4018 813 -416 839 -420 817 -418 451 -816 835 -444 809 -450 811 -440 803 -444 407 -830 419 -844 419 -836 805 -420 835 -444 803 -446 409 -868 421 -814 431 -822 807 -452 397 -828 819 -452 415 -856 787 -454 419 -848 837 -410 839 -416 395 -866 787 -450 811 -454 407 -850 805 -454 805 -470 381 -850 833 -418 805 -438 809 -448 397 -860 421 -810 431 -856 381 -888 791 -424 841 -422 415 -820 437 -818 813 -450 813 -454 803 -446 817 -448 829 -410 451 -816 403 -818 413 -850 409 -846 811 -448 415 -834 413 -884 399 -822 815 -452 381 -852 407 -846 415 -846 385 -866 807 -456 809 -446 835 -412 407 -834 815 -450 415 -822 405 -848 419 -844 427 -852 809 -442 407 -16420 425 -422 335 -486 309 -486 309 -522 307 -492 337 -454 351 -466 329 -498 327 -468 323 -472 355 -442 355 -4120 757 -456 773 -478 781 -458 381 -874 771 -482 801 -470 777 -482 805 -450 399 -826 415 -846 387 -866 805 -420 813 -446 831 -458 417 -846 401 -852 381 -840 835 -420 415 -846 795 -440 413 -842 835 -450 407 -860 811 -418 815 -424 413 -842 807 -454 823 -428 411 -842 801 -454 807 -488 401 -822 805 -448 803 -446 803 -426 447 -844 397 -856 381 -870 411 -870 777 -452 829 -432 385 -840 419 -848 797 -438 809 -450 815 -448 833 -440 803 -452 411 -820 415 -848 409 -844 411 -846 779 -462 409 -848 409 -864 421 -844 793 -438 385 -846 419 -850 399 -838 415 -872 777 -478 803 -448 799 -442 417 -848 799 -438 415 -842 409 -826 417 -844 427 -854 807 -452 409 -16402 461 -352 421 -386 421 -386 419 -388 453 -354 453 -354 447 -378 409 -386 439 -376 421 -410 385 -414 415 -4024 831 -418 809 -438 807 -444 409 -838 809 -456 821 -432 841 -414 255 -87638 131 -66 97 -296 97 -264 131 -196 65 -132 231 -632 197 -664 131 +RAW_Data: -500 395 -132 461 -132 689 -98 2685 -100 997 -1508 99 -2186 231 -166 231 -134 133 -932 65 -268 99 -132 65 -200 97 -68 163 -234 65 -68 99 -930 331 -98 763 -100 2025 -418 353 -446 385 -414 385 -416 387 -448 355 -442 383 -412 397 -424 405 -388 409 -418 379 -418 415 -4014 443 -814 413 -822 817 -454 801 -436 409 -842 409 -866 415 -838 441 -836 811 -432 387 -842 419 -846 793 -440 807 -448 837 -446 803 -448 835 -420 807 -448 383 -868 379 -850 409 -866 387 -844 825 -468 381 -884 793 -426 415 -842 427 -818 817 -440 407 -830 419 -844 429 -852 387 -872 409 -826 811 -450 813 -418 837 -412 409 -864 417 -844 397 -852 809 -454 805 -448 409 -840 809 -420 813 -458 409 -844 407 -860 385 -878 793 -470 809 -420 817 -416 417 -850 403 -852 381 -852 827 -428 447 -844 401 -854 813 -424 421 -840 419 -812 823 -438 415 -846 409 -844 415 -846 389 -868 809 -458 803 -416 409 -866 813 -418 417 -854 397 -862 419 -842 401 -854 415 -16404 435 -376 409 -410 407 -384 439 -384 409 -410 417 -368 421 -410 407 -378 447 -376 415 -378 447 -380 407 -4022 421 -844 423 -822 821 -418 807 -454 429 -820 421 -836 439 -854 421 -810 821 -436 385 -840 441 -822 813 -448 811 -452 803 -444 835 -444 801 -446 801 -426 447 -808 423 -834 413 -852 407 -840 819 -452 389 -856 813 -444 409 -848 415 -812 809 -458 409 -848 411 -842 415 -844 421 -834 415 -834 835 -418 819 -418 807 -456 393 -856 393 -866 421 -846 799 -474 809 -420 421 -836 811 -420 813 -458 407 -850 413 -842 415 -846 819 -428 835 -416 835 -412 407 -832 421 -842 423 -822 813 -446 407 -864 419 -846 799 -440 413 -850 419 -816 797 -442 413 -850 409 -844 417 -846 423 -834 841 -428 805 -414 435 -822 813 -450 413 -822 437 -818 421 -844 429 -854 411 -16406 427 -418 309 -522 307 -488 303 -520 289 -530 295 -500 323 -470 325 -504 321 -476 321 -476 355 -444 357 -4080 355 -906 339 -882 771 -476 777 -486 381 -874 383 -884 375 -884 387 -852 819 -418 417 -846 399 -854 809 -418 815 -446 837 -420 839 -454 801 -436 807 -452 399 -826 417 -844 391 -852 423 -838 809 -452 431 -852 811 -414 409 -836 417 -844 821 -432 385 -876 385 -850 409 -848 415 -854 421 -840 817 -420 815 -424 817 -448 409 -848 413 -844 389 -854 815 -446 829 -426 413 -842 819 -434 809 -446 409 -838 419 -846 401 -852 811 -456 811 -444 803 -418 417 -848 403 -850 381 -864 805 -450 395 -866 419 -848 801 -474 381 -848 411 +RAW_Data: -842 807 -446 381 -872 377 -866 421 -846 401 -854 813 -458 779 -446 407 -832 811 -450 415 -856 399 -856 385 -876 399 -854 411 -16398 435 -392 395 -400 421 -412 385 -412 417 -384 415 -386 415 -418 385 -420 385 -420 417 -390 417 -388 419 -4020 421 -838 421 -812 819 -434 809 -448 397 -864 421 -844 401 -850 413 -858 789 -426 413 -844 419 -836 807 -424 843 -410 829 -442 835 -446 801 -454 809 -420 417 -832 411 -848 249 -88020 133 -896 231 -466 67 -1062 131 -728 163 -98 621 -98 1051 -100 680933 -452 269 -522 273 -554 273 -558 239 -558 271 -490 337 -488 321 -498 295 -500 325 -470 323 -474 353 -4082 757 -492 375 -880 357 -872 777 -486 773 -480 807 -450 805 -444 805 -476 407 -812 413 -834 411 -848 407 -828 813 -450 811 -458 803 -448 835 -446 791 -424 447 -808 427 -818 423 -840 419 -848 401 -854 811 -458 809 -446 801 -416 439 -826 415 -848 813 -430 809 -450 395 -866 419 -846 403 -850 413 -820 407 -848 415 -846 781 -460 805 -446 803 -474 803 -448 835 -420 805 -454 389 -836 409 -842 407 -866 419 -842 399 -854 809 -456 809 -446 409 -840 385 -844 819 -434 809 -450 395 -860 811 -452 393 -886 779 -446 409 -830 419 -842 423 -818 423 -838 419 -844 799 -472 809 -454 385 -844 807 -454 391 -854 395 -860 385 -844 429 -852 809 -454 385 -874 409 -16402 427 -368 455 -358 433 -380 443 -378 415 -378 447 -380 411 -384 409 -406 421 -408 387 -412 415 -386 415 -4026 831 -398 441 -810 417 -832 837 -418 833 -444 803 -446 833 -448 801 -424 449 -810 427 -820 423 -838 419 -812 825 -438 841 -416 845 -446 825 -418 809 -422 419 -822 433 -822 419 -844 425 -820 421 -840 841 -458 797 -436 809 -414 435 -822 419 -844 819 -432 809 -448 395 -864 421 -846 407 -850 411 -808 433 -824 419 -844 819 -432 809 -446 823 -416 837 -454 807 -440 809 -414 435 -828 417 -844 425 -828 415 -848 419 -818 839 -446 807 -422 411 -844 419 -846 795 -438 807 -450 395 -866 811 -454 391 -854 845 -412 407 -832 421 -842 419 -832 411 -824 435 -820 815 -450 811 -460 409 -850 799 -454 407 -824 413 -848 411 -842 415 -844 815 -432 415 -848 405 -16400 441 -432 327 -492 301 -516 307 -484 309 -520 307 -492 339 -454 337 -490 331 -464 327 -500 325 -472 325 -4110 763 -480 373 -852 385 -878 759 -482 775 -474 813 -458 781 -482 789 -454 415 -846 397 -820 411 -840 405 -852 809 -450 811 -458 809 -450 817 -448 803 -426 411 -844 391 -854 393 -866 419 -848 399 -854 811 +RAW_Data: -454 811 -444 803 -418 417 -846 403 -850 809 -452 805 -444 411 -840 419 -846 407 -850 415 -836 385 -842 419 -850 797 -438 807 -452 817 -446 801 -486 813 -444 775 -450 409 -838 419 -810 431 -854 379 -848 405 -884 809 -450 817 -430 385 -874 375 -856 811 -446 809 -422 421 -836 835 -452 419 -848 783 -460 409 -814 407 -856 415 -846 383 -870 381 -848 819 -450 811 -472 383 -850 803 -454 415 -838 399 -854 379 -850 407 -848 811 -448 415 -872 387 -16400 451 -374 445 -374 415 -378 415 -412 411 -384 405 -422 409 -410 387 -410 417 -382 417 -384 415 -420 383 -4030 827 -428 411 -842 425 -820 817 -418 833 -426 845 -452 815 -428 837 -416 409 -842 421 -810 431 -820 421 -89106 265 -662 99 -532 131 -598 97 -668 65 -300 761 -198 231 -132 265 -100 233 -100 197 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index aee15a16d..44e1613c7 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -178,3 +178,8 @@ RAW_Data: -2072 1971 -2056 1971 -2074 1973 -34714 455 -3634 373 -3634 1901 -2110 RAW_Data: 4046 -17306 65 -298 97 -100 133 -268 265 -330 133 -132 1723 -16806 165 -132 99 -920 65 -622 789 -130 99 -66 361 -98 295 -166 73573 -17510 97 -492 129 -728 529 -100 1063 -164 295 -66 1119 -14962 627 -166 363 -264 427 -132 593 -100 633 -132 39555 -16938 99 -2024 65 -100 97 -164 99 -66 399 -100 123891 -16736 163 -200 97 -200 165 -264 65 -828 427 -132 871 -5132 591 -490 595 -486 605 -454 275 -822 241 -824 273 -784 321 -782 649 -444 653 -408 657 -428 321 -744 693 -388 699 -388 707 -392 313 -752 345 -750 317 -744 351 -730 355 -738 323 -774 327 -748 329 -750 695 -386 701 -354 381 -722 351 -720 385 -718 351 -718 345 -738 705 -382 329 -736 713 -360 387 -718 369 -718 367 -706 735 -352 375 -726 351 -722 351 -720 719 -7808 4845 -1474 743 -332 741 -370 705 -370 349 -718 383 -716 345 -712 381 -704 747 -326 747 -350 737 -352 351 -718 719 -360 741 -366 687 -362 375 -704 381 -724 351 -740 353 -712 357 -718 359 -744 363 -688 365 -722 727 -354 727 -354 379 -724 351 -722 353 -720 387 -718 353 -718 703 -374 351 -716 735 -354 365 -708 353 -734 351 -746 717 -356 359 -720 371 -704 371 -720 731 -7786 4847 -1482 711 -386 711 -358 743 -330 373 -708 359 -748 349 -740 351 -716 719 -356 727 -354 739 -354 351 -718 719 -362 743 -364 721 -330 373 -706 381 -722 351 -740 353 -712 359 -720 361 -722 361 -720 361 -720 725 -354 731 -354 381 -720 353 -722 385 -720 351 -720 349 -716 735 -354 361 -748 711 -364 347 -740 365 -722 365 -720 695 -384 371 -704 381 -702 377 -710 709 -7804 4853 -1468 743 -336 735 -358 719 -352 379 -724 353 -722 353 -720 387 -686 721 -360 721 -362 743 -332 387 -718 721 -366 701 -382 701 -350 377 -720 351 -740 353 -714 357 -710 397 -710 365 -702 385 -688 377 -724 731 -352 703 -354 379 -736 343 -740 357 -720 349 -706 385 -718 719 -354 365 -724 735 -352 377 -724 355 -720 353 -720 721 -358 387 -686 387 -718 353 -718 733 -7796 4821 -1492 739 -350 719 -334 737 -350 365 -722 373 -722 367 -708 371 -702 747 -352 711 -358 743 -364 343 -706 749 -352 717 -350 717 -384 327 -736 351 -746 355 -716 357 -720 359 -710 365 -742 365 -708 367 -704 711 -354 743 -356 387 -684 373 -706 381 -722 351 -740 353 -714 721 -356 361 -720 733 -352 375 -694 385 -724 353 -722 719 -356 385 -686 385 -718 351 -716 731 -7792 4843 -1480 717 -354 719 -386 717 -354 359 -720 351 -708 387 -712 355 -718 721 -356 727 -354 739 -356 351 -718 741 -364 RAW_Data: 705 -370 703 -372 351 -718 383 -720 347 -720 347 -714 381 -704 353 -744 357 -718 355 -720 723 -356 725 -354 379 -722 351 -722 353 -722 385 -718 351 -718 721 -372 351 -716 719 -372 351 -718 383 -716 345 -714 743 -346 361 -740 353 -712 357 -710 725 -7818 4837 -1498 713 -356 709 -360 741 -332 375 -706 359 -750 351 -706 353 -748 719 -356 723 -352 739 -354 351 -718 709 -364 719 -362 721 -364 385 -718 353 -718 383 -682 377 -712 349 -734 353 -742 355 -712 359 -722 723 -354 729 -352 381 -722 353 -722 351 -720 387 -718 353 -716 701 -388 345 -722 737 -354 357 -722 351 -708 387 -712 717 -350 731 -354 741 -356 743 -330 375 -8180 4829 -1468 739 -364 707 -354 729 -352 379 -722 353 -720 387 -686 387 -718 707 -368 721 -366 707 -368 351 -718 735 -354 719 -354 719 -388 329 -746 349 -738 351 -712 359 -718 361 -742 365 -708 371 -706 373 -720 733 -320 733 -354 383 -720 353 -720 387 -718 351 -716 385 -714 703 -388 327 -746 705 -348 387 -702 385 -690 385 -724 713 -358 709 -362 743 -364 709 -370 351 -8162 4837 -1482 715 -388 715 -352 715 -384 325 -730 353 -744 353 -712 359 -720 723 -354 733 -354 745 -356 351 -720 719 -362 741 -330 737 -382 349 -722 345 -724 361 -744 349 -704 383 -716 357 -718 357 -720 361 -720 723 -354 733 -354 383 -720 387 -686 387 -718 353 -718 349 -716 731 -384 347 -724 721 -352 365 -706 353 -732 353 -746 717 -356 723 -352 739 -354 711 -360 385 -8146 4841 -1470 737 -344 739 -326 751 -352 377 -690 387 -724 353 -724 353 -722 711 -360 743 -364 721 -330 387 -716 703 -386 721 -356 721 -354 363 -706 349 -734 351 -746 355 -718 355 -712 363 -744 365 -708 369 -722 695 -352 731 -354 381 -722 353 -722 351 -734 351 -716 383 -720 723 -354 333 -736 739 -348 361 -708 351 -748 355 -712 725 -354 727 -352 741 -352 713 -358 385 -8134 4855 -1474 719 -358 709 -362 721 -364 387 -716 351 -718 385 -712 347 -712 739 -334 739 -354 729 -352 379 -722 717 -354 711 -360 743 -332 387 -718 351 -716 377 -708 349 -730 353 -742 355 -710 359 -720 359 -720 723 -354 729 -352 381 -720 353 -722 351 -722 387 -684 387 -716 703 -384 349 -722 737 -354 329 -750 349 -738 353 -712 719 -356 725 -354 741 -354 717 -358 385 -8126 4861 -1470 735 -344 731 -346 729 -348 383 -718 347 -712 353 -734 353 -746 715 -356 725 -350 741 -352 351 -718 741 -366 721 -366 705 -370 353 -718 385 -682 377 -710 349 -734 353 -744 355 -710 359 -710 397 -688 RAW_Data: 727 -354 729 -352 379 -724 353 -722 353 -718 387 -716 353 -716 735 -348 383 -682 727 -386 347 -722 347 -712 381 -706 747 -326 747 -350 737 -352 711 -358 +RAW_Data: -854 811 -454 811 -444 409 -838 811 -454 823 -432 385 -842 811 -454 389 -854 821 -418 837 -444 401 -850 417 -854 395 -830 417 -846 819 -432 811 -448 789 -444 839 -454 401 -856 381 -850 825 -410 841 -418 417 -834 411 -840 827 -442 417 -844 799 -472 809 -420 411 -842 419 -848 397 -822 413 -850 799 -486 381 -848 415 -854 423 -16394 449 -358 437 -386 411 -384 449 -382 417 -384 419 -386 417 -386 419 -388 419 -388 419 -388 419 -390 437 -4036 421 -810 425 -820 393 -866 813 -422 415 -856 397 -858 811 -456 427 -820 815 -416 419 -850 401 -854 805 -420 835 -444 409 -842 809 -454 433 -820 421 -838 813 -420 417 -822 435 -820 419 -834 431 -852 411 -866 805 -420 815 -444 805 -454 403 -824 809 -448 819 -448 413 -844 811 -446 811 -456 409 -816 809 -456 389 -866 387 -842 809 -454 827 -432 413 -850 829 -428 809 -452 381 -852 799 -452 413 -852 807 -450 801 -444 409 -872 411 -840 413 -812 413 -832 807 -450 815 -442 801 -454 809 -454 429 -820 419 -838 811 -456 785 -428 409 -842 439 -824 813 -448 415 -858 819 -418 831 -426 449 -808 427 -820 393 -866 421 -808 825 -436 413 -852 403 -884 421 -16394 407 -478 257 -574 229 -576 229 -564 231 -592 267 -490 305 -520 307 -486 309 -522 307 -458 341 -486 337 -4096 343 -882 389 -880 341 -874 807 -476 351 -882 397 -860 807 -450 431 -824 811 -450 399 -824 417 -844 817 -432 807 -448 411 -872 801 -460 417 -810 425 -836 809 -420 411 -838 409 -852 417 -844 425 -852 385 -872 801 -426 841 -420 811 -422 409 -844 809 -454 823 -432 415 -842 835 -450 805 -454 403 -822 809 -450 399 -826 417 -844 821 -434 807 -448 411 -876 801 -440 807 -450 383 -850 833 -416 415 -852 807 -456 811 -444 411 -838 419 -848 401 -852 377 -850 819 -454 795 -436 809 -448 821 -448 411 -846 417 -842 817 -432 811 -412 411 -864 417 -844 791 -438 415 -876 793 -458 809 -450 383 -832 413 -840 407 -866 387 -844 821 -434 413 -874 377 -868 419 -16408 411 -392 421 -390 421 -388 421 -376 427 -394 433 -388 409 -386 411 -384 449 -382 419 -384 419 -384 419 -4018 343 -89684 97 -430 65 -166 163 -66 231 -100 161 -392 161 -64 229 -1056 97 -198 97 -198 259 -166 691 -66 395 -98 131 -100 99 -66 199 -198 1657 -406 365 -462 361 -436 357 -438 387 -444 353 -444 385 -414 387 -448 355 -448 355 -444 395 -394 399 -4050 819 -434 811 -414 819 -450 409 -852 809 -450 805 -448 805 -446 831 -428 409 -846 389 -854 395 -862 811 +RAW_Data: -452 783 -462 811 -446 411 -874 383 -852 403 -852 777 -450 411 -838 805 -452 397 -858 805 -484 387 -872 803 -442 805 -448 383 -846 797 -484 777 -474 381 -846 831 -430 807 -482 387 -852 817 -418 805 -452 823 -430 385 -878 377 -876 411 -846 391 -884 811 -444 805 -420 415 -846 399 -852 807 -452 805 -444 803 -450 803 -454 807 -452 397 -850 395 -862 385 -844 427 -840 809 -456 379 -876 407 -880 383 -846 819 -432 387 -872 375 -854 413 -846 387 -886 779 -476 803 -450 801 -444 415 -846 793 -438 415 -846 417 -822 407 -852 417 -852 817 -444 409 -16426 443 -358 431 -388 409 -386 447 -350 449 -382 419 -386 419 -386 417 -386 419 -388 453 -354 453 -356 445 -4018 813 -416 839 -420 817 -418 451 -816 835 -444 809 -450 811 -440 803 -444 407 -830 419 -844 419 -836 805 -420 835 -444 803 -446 409 -868 421 -814 431 -822 807 -452 397 -828 819 -452 415 -856 787 -454 419 -848 837 -410 839 -416 395 -866 787 -450 811 -454 407 -850 805 -454 805 -470 381 -850 833 -418 805 -438 809 -448 397 -860 421 -810 431 -856 381 -888 791 -424 841 -422 415 -820 437 -818 813 -450 813 -454 803 -446 817 -448 829 -410 451 -816 403 -818 413 -850 409 -846 811 -448 415 -834 413 -884 399 -822 815 -452 381 -852 407 -846 415 -846 385 -866 807 -456 809 -446 835 -412 407 -834 815 -450 415 -822 405 -848 419 -844 427 -852 809 -442 407 -16420 425 -422 335 -486 309 -486 309 -522 307 -492 337 -454 351 -466 329 -498 327 -468 323 -472 355 -442 355 -4120 757 -456 773 -478 781 -458 381 -874 771 -482 801 -470 777 -482 805 -450 399 -826 415 -846 387 -866 805 -420 813 -446 831 -458 417 -846 401 -852 381 -840 835 -420 415 -846 795 -440 413 -842 835 -450 407 -860 811 -418 815 -424 413 -842 807 -454 823 -428 411 -842 801 -454 807 -488 401 -822 805 -448 803 -446 803 -426 447 -844 397 -856 381 -870 411 -870 777 -452 829 -432 385 -840 419 -848 797 -438 809 -450 815 -448 833 -440 803 -452 411 -820 415 -848 409 -844 411 -846 779 -462 409 -848 409 -864 421 -844 793 -438 385 -846 419 -850 399 -838 415 -872 777 -478 803 -448 799 -442 417 -848 799 -438 415 -842 409 -826 417 -844 427 -854 807 -452 409 -16402 461 -352 421 -386 421 -386 419 -388 453 -354 453 -354 447 -378 409 -386 439 -376 421 -410 385 -414 415 -4024 831 -418 809 -438 807 -444 409 -838 809 -456 821 -432 841 -414 255 -87638 131 -66 97 -296 97 -264 131 -196 65 -132 231 -632 197 -664 131 +RAW_Data: -500 395 -132 461 -132 689 -98 2685 -100 997 -1508 99 -2186 231 -166 231 -134 133 -932 65 -268 99 -132 65 -200 97 -68 163 -234 65 -68 99 -930 331 -98 763 -100 2025 -418 353 -446 385 -414 385 -416 387 -448 355 -442 383 -412 397 -424 405 -388 409 -418 379 -418 415 -4014 443 -814 413 -822 817 -454 801 -436 409 -842 409 -866 415 -838 441 -836 811 -432 387 -842 419 -846 793 -440 807 -448 837 -446 803 -448 835 -420 807 -448 383 -868 379 -850 409 -866 387 -844 825 -468 381 -884 793 -426 415 -842 427 -818 817 -440 407 -830 419 -844 429 -852 387 -872 409 -826 811 -450 813 -418 837 -412 409 -864 417 -844 397 -852 809 -454 805 -448 409 -840 809 -420 813 -458 409 -844 407 -860 385 -878 793 -470 809 -420 817 -416 417 -850 403 -852 381 -852 827 -428 447 -844 401 -854 813 -424 421 -840 419 -812 823 -438 415 -846 409 -844 415 -846 389 -868 809 -458 803 -416 409 -866 813 -418 417 -854 397 -862 419 -842 401 -854 415 -16404 435 -376 409 -410 407 -384 439 -384 409 -410 417 -368 421 -410 407 -378 447 -376 415 -378 447 -380 407 -4022 421 -844 423 -822 821 -418 807 -454 429 -820 421 -836 439 -854 421 -810 821 -436 385 -840 441 -822 813 -448 811 -452 803 -444 835 -444 801 -446 801 -426 447 -808 423 -834 413 -852 407 -840 819 -452 389 -856 813 -444 409 -848 415 -812 809 -458 409 -848 411 -842 415 -844 421 -834 415 -834 835 -418 819 -418 807 -456 393 -856 393 -866 421 -846 799 -474 809 -420 421 -836 811 -420 813 -458 407 -850 413 -842 415 -846 819 -428 835 -416 835 -412 407 -832 421 -842 423 -822 813 -446 407 -864 419 -846 799 -440 413 -850 419 -816 797 -442 413 -850 409 -844 417 -846 423 -834 841 -428 805 -414 435 -822 813 -450 413 -822 437 -818 421 -844 429 -854 411 -16406 427 -418 309 -522 307 -488 303 -520 289 -530 295 -500 323 -470 325 -504 321 -476 321 -476 355 -444 357 -4080 355 -906 339 -882 771 -476 777 -486 381 -874 383 -884 375 -884 387 -852 819 -418 417 -846 399 -854 809 -418 815 -446 837 -420 839 -454 801 -436 807 -452 399 -826 417 -844 391 -852 423 -838 809 -452 431 -852 811 -414 409 -836 417 -844 821 -432 385 -876 385 -850 409 -848 415 -854 421 -840 817 -420 815 -424 817 -448 409 -848 413 -844 389 -854 815 -446 829 -426 413 -842 819 -434 809 -446 409 -838 419 -846 401 -852 811 -456 811 -444 803 -418 417 -848 403 -850 381 -864 805 -450 395 -866 419 -848 801 -474 381 -848 411 +RAW_Data: -842 807 -446 381 -872 377 -866 421 -846 401 -854 813 -458 779 -446 407 -832 811 -450 415 -856 399 -856 385 -876 399 -854 411 -16398 435 -392 395 -400 421 -412 385 -412 417 -384 415 -386 415 -418 385 -420 385 -420 417 -390 417 -388 419 -4020 421 -838 421 -812 819 -434 809 -448 397 -864 421 -844 401 -850 413 -858 789 -426 413 -844 419 -836 807 -424 843 -410 829 -442 835 -446 801 -454 809 -420 417 -832 411 -848 249 -88020 133 -896 231 -466 67 -1062 131 -728 163 -98 621 -98 1051 -100 680933 -452 269 -522 273 -554 273 -558 239 -558 271 -490 337 -488 321 -498 295 -500 325 -470 323 -474 353 -4082 757 -492 375 -880 357 -872 777 -486 773 -480 807 -450 805 -444 805 -476 407 -812 413 -834 411 -848 407 -828 813 -450 811 -458 803 -448 835 -446 791 -424 447 -808 427 -818 423 -840 419 -848 401 -854 811 -458 809 -446 801 -416 439 -826 415 -848 813 -430 809 -450 395 -866 419 -846 403 -850 413 -820 407 -848 415 -846 781 -460 805 -446 803 -474 803 -448 835 -420 805 -454 389 -836 409 -842 407 -866 419 -842 399 -854 809 -456 809 -446 409 -840 385 -844 819 -434 809 -450 395 -860 811 -452 393 -886 779 -446 409 -830 419 -842 423 -818 423 -838 419 -844 799 -472 809 -454 385 -844 807 -454 391 -854 395 -860 385 -844 429 -852 809 -454 385 -874 409 -16402 427 -368 455 -358 433 -380 443 -378 415 -378 447 -380 411 -384 409 -406 421 -408 387 -412 415 -386 415 -4026 831 -398 441 -810 417 -832 837 -418 833 -444 803 -446 833 -448 801 -424 449 -810 427 -820 423 -838 419 -812 825 -438 841 -416 845 -446 825 -418 809 -422 419 -822 433 -822 419 -844 425 -820 421 -840 841 -458 797 -436 809 -414 435 -822 419 -844 819 -432 809 -448 395 -864 421 -846 407 -850 411 -808 433 -824 419 -844 819 -432 809 -446 823 -416 837 -454 807 -440 809 -414 435 -828 417 -844 425 -828 415 -848 419 -818 839 -446 807 -422 411 -844 419 -846 795 -438 807 -450 395 -866 811 -454 391 -854 845 -412 407 -832 421 -842 419 -832 411 -824 435 -820 815 -450 811 -460 409 -850 799 -454 407 -824 413 -848 411 -842 415 -844 815 -432 415 -848 405 -16400 441 -432 327 -492 301 -516 307 -484 309 -520 307 -492 339 -454 337 -490 331 -464 327 -500 325 -472 325 -4110 763 -480 373 -852 385 -878 759 -482 775 -474 813 -458 781 -482 789 -454 415 -846 397 -820 411 -840 405 -852 809 -450 811 -458 809 -450 817 -448 803 -426 411 -844 391 -854 393 -866 419 -848 399 -854 811 +RAW_Data: -454 811 -444 803 -418 417 -846 403 -850 809 -452 805 -444 411 -840 419 -846 407 -850 415 -836 385 -842 419 -850 797 -438 807 -452 817 -446 801 -486 813 -444 775 -450 409 -838 419 -810 431 -854 379 -848 405 -884 809 -450 817 -430 385 -874 375 -856 811 -446 809 -422 421 -836 835 -452 419 -848 783 -460 409 -814 407 -856 415 -846 383 -870 381 -848 819 -450 811 -472 383 -850 803 -454 415 -838 399 -854 379 -850 407 -848 811 -448 415 -872 387 -16400 451 -374 445 -374 415 -378 415 -412 411 -384 405 -422 409 -410 387 -410 417 -382 417 -384 415 -420 383 -4030 827 -428 411 -842 425 -820 817 -418 833 -426 845 -452 815 -428 837 -416 409 -842 421 -810 431 -820 421 -89106 265 -662 99 -532 131 -598 97 -668 65 -300 761 -198 231 -132 265 -100 233 -100 197 diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 65ab375ef..846041c3e 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2569,12 +2569,14 @@ Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_free,void,SubGhzEnvironment* +Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment* Function,+,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_protocol_name_registry,const char*,"SubGhzEnvironment*, size_t" Function,+,subghz_environment_get_protocol_registry,void*,SubGhzEnvironment* Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*" +Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, void*" diff --git a/lib/subghz/environment.c b/lib/subghz/environment.c index 0a4b7b606..b39b259d4 100644 --- a/lib/subghz/environment.c +++ b/lib/subghz/environment.c @@ -6,6 +6,7 @@ struct SubGhzEnvironment { const SubGhzProtocolRegistry* protocol_registry; const char* came_atomo_rainbow_table_file_name; const char* nice_flor_s_rainbow_table_file_name; + const char* alutech_at_4n_rainbow_table_file_name; }; SubGhzEnvironment* subghz_environment_alloc() { @@ -57,6 +58,21 @@ const char* return instance->came_atomo_rainbow_table_file_name; } +void subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + SubGhzEnvironment* instance, + const char* filename) { + furi_assert(instance); + + instance->alutech_at_4n_rainbow_table_file_name = filename; +} + +const char* + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(SubGhzEnvironment* instance) { + furi_assert(instance); + + return instance->alutech_at_4n_rainbow_table_file_name; +} + void subghz_environment_set_nice_flor_s_rainbow_table_file_name( SubGhzEnvironment* instance, const char* filename) { diff --git a/lib/subghz/environment.h b/lib/subghz/environment.h index e994f7c97..7bd38ba2f 100644 --- a/lib/subghz/environment.h +++ b/lib/subghz/environment.h @@ -52,6 +52,23 @@ void subghz_environment_set_came_atomo_rainbow_table_file_name( */ const char* subghz_environment_get_came_atomo_rainbow_table_file_name(SubGhzEnvironment* instance); +/** + * Set filename to work with Alutech at-4n. + * @param instance Pointer to a SubGhzEnvironment instance + * @param filename Full path to the file + */ +void subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + SubGhzEnvironment* instance, + const char* filename); + +/** + * Get filename to work with Alutech at-4n. + * @param instance Pointer to a SubGhzEnvironment instance + * @return Full path to the file + */ +const char* + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(SubGhzEnvironment* instance); + /** * Set filename to work with Nice Flor-S. * @param instance Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c new file mode 100644 index 000000000..6bcf9f25d --- /dev/null +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -0,0 +1,455 @@ +#include "alutech_at_4n.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocoAlutech_at_4n" + +#define SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE 0xFFFFFFFF + +static const SubGhzBlockConst subghz_protocol_alutech_at_4n_const = { + .te_short = 400, + .te_long = 800, + .te_delta = 140, + .min_count_bit_for_found = 72, +}; + +struct SubGhzProtocolDecoderAlutech_at_4n { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint64_t data; + uint32_t crc; + uint16_t header_count; + + const char* alutech_at_4n_rainbow_table_file_name; +}; + +struct SubGhzProtocolEncoderAlutech_at_4n { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + Alutech_at_4nDecoderStepReset = 0, + Alutech_at_4nDecoderStepCheckPreambula, + Alutech_at_4nDecoderStepSaveDuration, + Alutech_at_4nDecoderStepCheckDuration, +} Alutech_at_4nDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_alutech_at_4n_decoder = { + .alloc = subghz_protocol_decoder_alutech_at_4n_alloc, + .free = subghz_protocol_decoder_alutech_at_4n_free, + + .feed = subghz_protocol_decoder_alutech_at_4n_feed, + .reset = subghz_protocol_decoder_alutech_at_4n_reset, + + .get_hash_data = subghz_protocol_decoder_alutech_at_4n_get_hash_data, + .serialize = subghz_protocol_decoder_alutech_at_4n_serialize, + .deserialize = subghz_protocol_decoder_alutech_at_4n_deserialize, + .get_string = subghz_protocol_decoder_alutech_at_4n_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_alutech_at_4n_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_alutech_at_4n = { + .name = SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_alutech_at_4n_decoder, + .encoder = &subghz_protocol_alutech_at_4n_encoder, +}; + +/** + * Read bytes from rainbow table + * @param file_name Full path to rainbow table the file + * @param number_alutech_at_4n_magic_data number in the array + * @return alutech_at_4n_magic_data + */ +static uint32_t subghz_protocol_alutech_at_4n_get_magic_data_in_file( + const char* file_name, + uint8_t number_alutech_at_4n_magic_data) { + if(!strcmp(file_name, "")) return SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE; + + uint8_t buffer[sizeof(uint32_t)] = {0}; + uint32_t address = number_alutech_at_4n_magic_data * sizeof(uint32_t); + uint32_t alutech_at_4n_magic_data = 0; + + if(subghz_keystore_raw_get_data(file_name, address, buffer, sizeof(uint32_t))) { + for(size_t i = 0; i < sizeof(uint32_t); i++) { + alutech_at_4n_magic_data = (alutech_at_4n_magic_data << 8) | buffer[i]; + } + } else { + alutech_at_4n_magic_data = SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE; + } + return alutech_at_4n_magic_data; +} + +static uint8_t subghz_protocol_alutech_at_4n_crc(uint64_t data) { + uint8_t* p = (uint8_t*)&data; + uint8_t crc = 0xff; + for(uint8_t y = 0; y < 8; y++) { + crc = crc ^ p[y]; + for(uint8_t i = 0; i < 8; i++) { + if((crc & 0x80) != 0) { + crc <<= 1; + crc ^= 0x31; + } else { + crc <<= 1; + } + } + } + return crc; +} + +static uint8_t subghz_protocol_alutech_at_4n_decrypt_data_crc(uint8_t data) { + uint8_t crc = data; + for(uint8_t i = 0; i < 8; i++) { + if((crc & 0x80) != 0) { + crc <<= 1; + crc ^= 0x31; + } else { + crc <<= 1; + } + } + return ~crc; +} + +static uint64_t subghz_protocol_alutech_at_4n_decrypt(uint64_t data, const char* file_name) { + uint8_t* p = (uint8_t*)&data; + uint32_t data1 = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + uint32_t data2 = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; + uint32_t data3 = 0; + uint32_t magic_data[] = { + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 0), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 1), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 2), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 3), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 4), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 5)}; + + uint32_t i = magic_data[0]; + do { + data2 = data2 - + ((magic_data[1] + (data1 << 4)) ^ ((magic_data[2] + (data1 >> 5)) ^ (data1 + i))); + data3 = data2 + i; + i += magic_data[3]; + data1 = + data1 - ((magic_data[4] + (data2 << 4)) ^ ((magic_data[5] + (data2 >> 5)) ^ data3)); + } while(i != 0); + + p[0] = (uint8_t)(data1 >> 24); + p[1] = (uint8_t)(data1 >> 16); + p[3] = (uint8_t)data1; + p[4] = (uint8_t)(data2 >> 24); + p[5] = (uint8_t)(data2 >> 16); + p[2] = (uint8_t)(data1 >> 8); + p[6] = (uint8_t)(data2 >> 8); + p[7] = (uint8_t)data2; + + return data; +} + +// static uint64_t subghz_protocol_alutech_at_4n_encrypt(uint64_t data, const char* file_name) { +// uint8_t* p = (uint8_t*)&data; +// uint32_t data1 = 0; +// uint32_t data2 = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +// uint32_t data3 = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; +// uint32_t magic_data[] = { +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 6), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 4), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 5), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 1), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 2), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 0)}; + +// do { +// data1 = data1 + magic_data[0]; +// data2 = data2 + ((magic_data[1] + (data3 << 4)) ^ +// ((magic_data[2] + (data3 >> 5)) ^ (data1 + data3))); +// data3 = data3 + ((magic_data[3] + (data2 << 4)) ^ +// ((magic_data[4] + (data2 >> 5)) ^ (data1 + data2))); +// } while(data1 != magic_data[5]); +// p[0] = (uint8_t)(data2 >> 24); +// p[1] = (uint8_t)(data2 >> 16); +// p[3] = (uint8_t)data2; +// p[4] = (uint8_t)(data3 >> 24); +// p[5] = (uint8_t)(data3 >> 16); +// p[2] = (uint8_t)(data2 >> 8); +// p[6] = (uint8_t)(data3 >> 8); +// p[7] = (uint8_t)data3; + +// return data; +// } + +void* subghz_protocol_decoder_alutech_at_4n_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderAlutech_at_4n* instance = + malloc(sizeof(SubGhzProtocolDecoderAlutech_at_4n)); + instance->base.protocol = &subghz_protocol_alutech_at_4n; + instance->generic.protocol_name = instance->base.protocol->name; + instance->alutech_at_4n_rainbow_table_file_name = + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(environment); + if(instance->alutech_at_4n_rainbow_table_file_name) { + FURI_LOG_I( + TAG, "Loading rainbow table from %s", instance->alutech_at_4n_rainbow_table_file_name); + } + return instance; +} + +void subghz_protocol_decoder_alutech_at_4n_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + instance->alutech_at_4n_rainbow_table_file_name = NULL; + free(instance); +} + +void subghz_protocol_decoder_alutech_at_4n_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; +} + +void subghz_protocol_decoder_alutech_at_4n_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + + switch(instance->decoder.parser_step) { + case Alutech_at_4nDecoderStepReset: + if((level) && DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) { + instance->decoder.parser_step = Alutech_at_4nDecoderStepCheckPreambula; + instance->header_count++; + } + break; + case Alutech_at_4nDecoderStepCheckPreambula: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta)) { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + break; + } + if((instance->header_count > 2) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short * 10) < + subghz_protocol_alutech_at_4n_const.te_delta * 10)) { + // Found header + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + break; + case Alutech_at_4nDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = Alutech_at_4nDecoderStepCheckDuration; + } + break; + case Alutech_at_4nDecoderStepCheckDuration: + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_alutech_at_4n_const.te_short * 2 + + subghz_protocol_alutech_at_4n_const.te_delta)) { + //add last bit + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } + + // Found end TX + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + if(instance->decoder.decode_count_bit == + subghz_protocol_alutech_at_4n_const.min_count_bit_for_found) { + if(instance->generic.data != instance->data) { + instance->generic.data = instance->data; + + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->crc = instance->decoder.decode_data; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + } + break; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + if(instance->decoder.decode_count_bit == 64) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + if(instance->decoder.decode_count_bit == 64) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + * @param file_name Full path to rainbow table the file + */ +static void subghz_protocol_alutech_at_4n_remote_controller( + SubGhzBlockGeneric* instance, + uint8_t crc, + const char* file_name) { + /** + * Message format 72bit LSB first + * data crc + * XXXXXXXXXXXXXXXX CC + * + * For analysis, you need to turn the package MSB + * in decoded messages format + * + * crc1 serial cnt key + * cc SSSSSSSS XXxx BB + * + * crc1 is calculated from the lower part of cnt + * key 1=0xff, 2=0x11, 3=0x22, 4=0x33, 5=0x44 + * + */ + + bool status = false; + uint64_t data = subghz_protocol_blocks_reverse_key(instance->data, 64); + crc = subghz_protocol_blocks_reverse_key(crc, 8); + + if(crc == subghz_protocol_alutech_at_4n_crc(data)) { + data = subghz_protocol_alutech_at_4n_decrypt(data, file_name); + status = true; + } + + if(status && ((uint8_t)(data >> 56) == + subghz_protocol_alutech_at_4n_decrypt_data_crc((uint8_t)((data >> 8) & 0xFF)))) { + instance->btn = (uint8_t)data & 0xFF; + instance->cnt = (uint16_t)(data >> 8) & 0xFFFF; + instance->serial = (uint32_t)(data >> 24) & 0xFFFFFFFF; + } + + if(!status) { + instance->btn = 0; + instance->cnt = 0; + instance->serial = 0; + } +} + +uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + return (uint8_t)instance->crc; +} + +bool subghz_protocol_decoder_alutech_at_4n_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(res && !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { + FURI_LOG_E(TAG, "Unable to add CRC"); + res = false; + } + return res; + + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_alutech_at_4n_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_alutech_at_4n_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "CRC", (uint32_t*)&instance->crc, 1)) { + FURI_LOG_E(TAG, "Missing CRC"); + break; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_alutech_at_4n_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + subghz_protocol_alutech_at_4n_remote_controller( + &instance->generic, instance->crc, instance->alutech_at_4n_rainbow_table_file_name); + uint32_t code_found_hi = instance->generic.data >> 32; + uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; + + furi_string_cat_printf( + output, + "%s %d\r\n" + "Key:0x%08lX%08lX%02X\r\n" + "Sn:0x%08lX Btn:0x%01X\r\n" + "Cnt:0x%03lX\r\n", + + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_hi, + code_found_lo, + (uint8_t)instance->crc, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/alutech_at_4n.h b/lib/subghz/protocols/alutech_at_4n.h new file mode 100644 index 000000000..38bac3ea6 --- /dev/null +++ b/lib/subghz/protocols/alutech_at_4n.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME "Alutech at-4n" + +typedef struct SubGhzProtocolDecoderAlutech_at_4n SubGhzProtocolDecoderAlutech_at_4n; +typedef struct SubGhzProtocolEncoderAlutech_at_4n SubGhzProtocolEncoderAlutech_at_4n; + +extern const SubGhzProtocolDecoder subghz_protocol_alutech_at_4n_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_alutech_at_4n_encoder; +extern const SubGhzProtocol subghz_protocol_alutech_at_4n; + +/** + * Allocate SubGhzProtocolDecoderAlutech_at_4n. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderAlutech_at_4n* pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void* subghz_protocol_decoder_alutech_at_4n_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void subghz_protocol_decoder_alutech_at_4n_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void subghz_protocol_decoder_alutech_at_4n_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_alutech_at_4n_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_alutech_at_4n_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_alutech_at_4n_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param output Resulting text + */ +void subghz_protocol_decoder_alutech_at_4n_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 3f6045bea..2e2718485 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -189,7 +189,7 @@ void subghz_protocol_decoder_came_atomo_feed(void* context, bool level, uint32_t /** * Read bytes from rainbow table * @param file_name Full path to rainbow table the file - * @param number_atomo_magic_xor Сell number in the array + * @param number_atomo_magic_xor number in the array * @return atomo_magic_xor */ static uint64_t subghz_protocol_came_atomo_get_magic_xor_in_file( diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 6a9c3468e..4a3602fbe 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -390,11 +390,14 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur subghz_protocol_keeloq_const.te_delta)) { // Found end TX instance->decoder.parser_step = KeeloqDecoderStepReset; - if(instance->decoder.decode_count_bit >= - subghz_protocol_keeloq_const.min_count_bit_for_found) { + if((instance->decoder.decode_count_bit >= + subghz_protocol_keeloq_const.min_count_bit_for_found) && + (instance->decoder.decode_count_bit <= + subghz_protocol_keeloq_const.min_count_bit_for_found + 2)) { if(instance->generic.data != instance->decoder.decode_data) { instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->generic.data_count_bit = + subghz_protocol_keeloq_const.min_count_bit_for_found; if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); } @@ -411,6 +414,8 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur if(instance->decoder.decode_count_bit < subghz_protocol_keeloq_const.min_count_bit_for_found) { subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else { + instance->decoder.decode_count_bit++; } instance->decoder.parser_step = KeeloqDecoderStepSaveDuration; } else if( @@ -421,6 +426,8 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur if(instance->decoder.decode_count_bit < subghz_protocol_keeloq_const.min_count_bit_for_found) { subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else { + instance->decoder.decode_count_bit++; } instance->decoder.parser_step = KeeloqDecoderStepSaveDuration; } else { diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 99de18c93..3904c1811 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -40,6 +40,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_holtek_th12x, &subghz_protocol_linear_delta3, &subghz_protocol_dooya, + &subghz_protocol_alutech_at_4n, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 4d1551bb3..cd9b7c6ed 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -40,5 +40,6 @@ #include "smc5326.h" #include "holtek_ht12x.h" #include "dooya.h" +#include "alutech_at_4n.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; From bf4d00a7d1cb94a2b17d26647359ab93207880c1 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 8 Feb 2023 21:20:28 +0400 Subject: [PATCH 13/34] [FL-3100] SubGhz: add protocol Nice One (#2358) * SubGhz: add protocol Nice One * SubGhz: fix annotation * SubGhz: add unit test Co-authored-by: Aleksandr Kutuzov --- .../debug/unit_tests/subghz/subghz_test.c | 10 +- assets/unit_tests/subghz/nice_one_raw.sub | 12 ++ assets/unit_tests/subghz/test_random_raw.sub | 7 + lib/subghz/protocols/nice_flor_s.c | 167 +++++++++++++++--- 4 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 assets/unit_tests/subghz/nice_one_raw.sub diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 705d6f2f6..97629efea 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -14,7 +14,7 @@ #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 304 +#define TEST_RANDOM_COUNT_PARSE 317 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -630,6 +630,13 @@ MU_TEST(subghz_decoder_alutech_at_4n_test) { "Test decoder " SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME " error\r\n"); } +MU_TEST(subghz_decoder_nice_one_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/nice_one_raw.sub"), SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME), + "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -829,6 +836,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_holtek_ht12x_test); MU_RUN_TEST(subghz_decoder_dooya_test); MU_RUN_TEST(subghz_decoder_alutech_at_4n_test); + MU_RUN_TEST(subghz_decoder_nice_one_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); diff --git a/assets/unit_tests/subghz/nice_one_raw.sub b/assets/unit_tests/subghz/nice_one_raw.sub new file mode 100644 index 000000000..169b3f088 --- /dev/null +++ b/assets/unit_tests/subghz/nice_one_raw.sub @@ -0,0 +1,12 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 7855 -12784 1413 -1544 469 -1040 465 -1010 479 -1020 967 -548 445 -1046 973 -524 967 -520 981 -516 483 -1042 449 -1034 949 -528 495 -1008 479 -1016 985 -518 453 -1042 449 -1052 949 -514 483 -1012 985 -512 477 -1042 445 -1050 951 -548 971 -512 975 -520 967 -554 949 -548 451 -1040 967 -520 987 -518 455 -1038 475 -1016 977 -518 983 -514 473 -1018 975 -518 487 -1002 475 -1020 965 -516 477 -1012 1007 -522 445 -1034 491 -1008 973 -524 +RAW_Data: 481 -992 481 -1010 483 -1030 977 -520 487 -1008 973 -522 987 -518 983 -514 965 -522 987 -520 489 -1004 473 -1018 471 -1016 1005 -476 511 -1012 457 -1018 1001 -510 975 -520 471 -1022 483 -1016 969 -536 1003 -454 981 -480 479 -986 981 -486 479 -946 989 -492 973 -484 473 -976 1503 -23606 1433 -1542 493 -1006 473 -1032 441 -1048 971 -514 483 -1012 985 -518 479 -1014 481 -1012 457 -1050 443 -1044 977 -520 473 -1004 495 -1004 969 -556 453 -1036 451 -1038 973 -520 485 -994 981 -520 457 -1050 477 -1014 977 -494 985 -538 961 -512 1005 -518 951 -526 491 -1006 969 -520 985 -524 455 -1044 447 -1048 983 -518 983 -514 441 -1050 981 -518 453 -1042 447 -1050 981 -518 451 -1046 975 -520 451 -1022 483 -1008 1001 -522 447 -1020 485 -1008 473 -1016 981 -550 449 -1044 977 -520 949 -550 979 -516 967 -520 983 -522 455 -1042 447 -1050 451 -1024 981 -520 483 -1018 963 -546 479 -1010 967 -520 483 -1022 975 -522 967 -552 487 -960 481 -990 451 -994 481 -980 479 -986 449 -984 969 -480 983 -510 1465 -23612 1473 -1520 479 -1026 453 -1044 451 -1036 943 -552 453 -1044 949 -518 481 -1018 977 -524 459 -1046 439 -1046 973 -528 463 -1012 471 -1046 943 -552 443 -1034 457 -1042 977 -518 479 -1028 949 -554 451 -1014 481 -1018 981 -524 985 -518 971 -514 979 -522 987 -512 477 -1016 977 -522 969 -552 449 -1016 483 -1014 985 -518 973 -516 481 -1012 967 -552 449 -1020 483 -1010 969 -554 447 -1022 977 -520 475 -1018 479 -1018 975 -522 457 -1036 479 -1016 479 -1002 969 -552 447 -1054 943 -548 969 -520 983 -520 983 -516 969 -518 479 -1030 453 -1044 449 -1048 943 -548 451 -1044 945 -552 975 -518 947 -552 449 -1034 975 -524 455 -1040 969 -520 449 -982 969 -518 945 -484 481 -984 481 -994 447 -986 477 -998 1435 -23658 1441 -1530 483 -1008 483 -1034 449 -1022 977 -520 485 -1018 479 -1018 975 -506 473 -1036 469 -1042 463 -1010 977 -520 487 -1030 451 -1010 981 -520 481 -1018 481 -1014 983 -518 479 -1016 975 -492 497 -1014 467 -1014 977 -520 975 -526 985 -516 979 -506 1005 -496 493 -1008 975 -522 983 -518 453 -1040 475 -1016 975 -524 987 -514 471 -1038 955 -514 473 -1046 445 -1044 967 -514 477 -1016 975 -520 457 -1050 477 -1010 973 -522 473 -1000 479 -1030 453 -1038 969 -506 473 -1050 971 -512 979 -524 955 -548 973 -512 975 -518 475 -1036 473 -1006 493 -1008 975 -520 973 -526 487 -1004 475 -1018 965 -516 1005 -512 481 -1014 985 -518 483 -986 975 -488 977 -480 977 -486 975 -482 481 -982 975 -480 977 -488 1477 -23618 1389 -1634 369 -1114 383 -1078 431 -1072 +RAW_Data: 931 -550 451 -1046 447 -1042 967 -552 945 -522 459 -1042 445 -1050 943 -552 439 -1036 459 -1046 977 -508 477 -1030 455 -1044 945 -552 451 -1020 979 -524 459 -1046 443 -1048 979 -518 967 -534 957 -516 977 -518 973 -528 455 -1042 973 -520 975 -526 459 -1040 481 -1020 969 -510 967 -546 447 -1050 955 -544 441 -1044 449 -1048 953 -550 443 -1046 975 -518 485 -1010 455 -1044 943 -554 447 -1054 449 -1010 475 -1048 943 -550 453 -1040 969 -520 973 -522 985 -514 969 -554 949 -524 459 -1040 477 -1014 483 -1034 947 -520 981 -554 447 -1016 977 -524 983 -516 973 -516 483 -1016 455 -1046 973 -484 977 -518 449 -986 447 -1016 971 -482 449 -1018 443 -1014 449 -984 1461 -129764 65 -3200 133 -464 133 -298 429 -132 265 -98 231 -134 265 -164 3439 -132 727 -132 199 -2058 133 -1644 361 -166 65 -492 165 -264 591 -428 197 -198 201 -98 831 -68 2313 -100 5839 -10922 65 -1320 425 -262 297 -428 97 -362 2463 -98 1025 -66 5263 -5030 99 -6924 461 -1092 133 -98 333 -166 2739 -132 3131 -66 10535 -2008 131 -434 297 -1058 65 -132 99 -198 529 -198 97 -526 97 -66 493 -664 99 -232 2613 -132 5371 -11166 229 -198 163 -394 199 -398 365 -132 99 -166 2121 -100 1195 -68 1821 -100 10635 -468 67 -1256 65 -2144 229 -100 163 -394 593 -98 67 -166 1677 -66 791 -66 335 -98 11033 -566 65 -1460 165 -1520 497 -1254 491 -564 99 -330 99 -232 1227 -132 2973 -66 3661 -11964 131 -132 99 -398 131 -328 97 -232 363 -396 1379 -98 99 -166 1591 -66 12171 -4136 65 -298 265 -298 199 -462 99 -330 65 -166 163 -66 1591 -66 165 -166 12079 -1002 65 -366 465 -530 97 -134 561 -66 497 -494 99 -64 131 -134 1095 -66 6537 -5066 65 -5458 397 -724 165 -466 131 -166 14293 -436 65 -1590 65 -1462 459 -332 65 -396 563 -794 197 -300 1255 -12100 99 -130 495 -166 97 -296 97 -658 757 -98 959 -66 1029 -1346 165 -2620 395 -494 197 -166 163 -198 65 -98 195 -394 821 -98 3063 -100 4469 -12120 497 -166 65 -462 195 -164 295 -66 4361 -100 1755 -100 131 -66 9415 -3840 99 -530 197 -364 463 -330 365 -332 133 -100 165 -166 2113 -100 1461 -132 4175 -3772 97 -7124 231 -1258 165 -100 429 -1326 995 -200 1755 -66 1519 -100 6437 -7198 133 -300 527 -398 165 -232 131 -166 67 -164 16443 -3270 131 -658 131 -726 97 -858 97 -300 331 -100 629 -10288 67 -164 133 -1458 297 -364 65 -98 163 -758 1189 -66 199 -68 1791 -66 897 -132 165 -3410 163 -364 99 -98 99 -66 365 -232 789 -494 65 -328 629 -66 1259 -66 365 -11422 7923 -12864 1405 -1562 +RAW_Data: 451 -1040 441 -1052 449 -1050 945 -554 449 -1052 451 -1020 481 -1010 473 -1050 449 -1052 451 -1040 969 -520 977 -520 455 -1042 977 -522 447 -1056 947 -518 979 -546 447 -1052 451 -1040 441 -1048 983 -518 455 -1044 449 -1018 979 -548 947 -554 449 -1032 481 -992 483 -1012 985 -514 999 -512 479 -1012 485 -1014 961 -544 477 -1010 965 -522 981 -512 483 -1012 487 -1020 477 -1014 479 -1016 459 -1014 471 -1012 1003 -492 997 -522 483 -1016 979 -522 985 -520 975 -512 975 -520 999 -488 985 -514 481 -1006 1001 -522 483 -990 483 -1008 483 -1020 977 -516 975 -518 999 -524 451 -1018 1009 -482 999 -506 983 -524 487 -1004 473 -980 501 -952 517 -940 497 -982 489 -974 987 -452 495 -974 487 -954 1485 -23662 1457 -1556 445 -1026 483 -1010 475 -1016 975 -518 483 -1014 487 -1034 447 -1022 977 -522 457 -1046 475 -1018 975 -524 985 -518 477 -1016 977 -524 459 -1048 969 -514 977 -522 457 -1038 479 -1018 481 -1002 1001 -520 447 -1054 449 -1008 1001 -520 977 -520 451 -1040 475 -1014 479 -1028 949 -518 983 -542 447 -1058 449 -1044 947 -552 447 -1024 977 -520 967 -542 479 -1024 451 -1040 441 -1050 451 -1028 481 -1014 483 -1010 965 -548 973 -518 485 -1010 981 -516 967 -520 983 -524 981 -514 969 -538 967 -518 481 -1016 973 -524 485 -1016 465 -1012 479 -1020 983 -532 959 -514 975 -554 949 -526 985 -512 969 -554 967 -534 461 -1042 443 -1014 967 -478 455 -1006 969 -486 967 -480 983 -486 969 -514 451 -982 1461 -23692 563 -4014 291 -1220 263 -1228 829 -620 883 -626 851 -608 903 -622 387 -1082 391 -1102 409 -1084 913 -588 941 -548 443 -1056 945 -522 445 -1046 971 -552 977 -516 441 -1048 481 -992 483 -1010 979 -554 451 -1018 481 -1014 983 -518 977 -514 479 -1040 447 -1034 485 -996 975 -520 979 -520 483 -1016 481 -1008 999 -506 471 -1050 971 -514 975 -520 473 -1000 483 -1020 481 -1008 473 -1018 481 -1020 481 -1008 967 -554 945 -518 481 -1038 967 -520 985 -520 981 -514 967 -520 985 -520 981 -508 479 -1016 1003 -518 479 -1010 479 -1010 473 -1018 975 -516 979 -520 983 -520 975 -514 977 -518 999 -520 979 -518 451 -1040 479 -986 479 -962 1007 -486 451 -986 975 -486 977 -482 483 -980 477 -982 1473 -23656 1453 -1548 447 -1016 485 -1012 491 -1012 973 -520 981 -526 983 -514 971 -554 947 -526 491 -1008 475 -1020 983 -498 989 -516 483 -1014 977 -524 453 -1044 979 -518 979 -520 453 -1042 449 -1048 447 -1022 975 -518 475 -1050 447 -1020 977 -522 983 -518 481 -1016 481 -1012 473 -1002 973 -550 945 -552 449 -1050 447 -1020 975 -522 487 -1034 973 -520 +RAW_Data: 979 -514 443 -1046 479 -1028 451 -1042 451 -1048 447 -1022 485 -1014 983 -520 973 -516 483 -1012 983 -518 973 -516 977 -520 1003 -520 975 -520 981 -514 475 -1034 969 -516 479 -1016 447 -1046 475 -1018 975 -516 975 -522 983 -510 469 -1010 1007 -518 951 -530 989 -516 973 -556 951 -494 481 -978 487 -978 975 -460 1005 -466 979 -486 969 -508 981 -450 1489 -23666 571 -4036 269 -1224 257 -1250 787 -642 867 -622 883 -622 359 -1136 373 -1086 421 -1080 417 -1074 935 -550 947 -552 445 -1048 939 -552 451 -1046 947 -552 947 -550 451 -1040 443 -1048 453 -1024 977 -522 471 -1034 449 -1020 973 -540 975 -508 479 -1032 453 -1042 449 -1050 977 -518 979 -518 449 -1018 481 -1018 975 -518 473 -1034 963 -542 961 -544 447 -1044 473 -1020 479 -1014 481 -1010 473 -1032 471 -1010 959 -546 973 -492 499 -1006 997 -510 977 -524 953 -552 971 -512 973 -508 979 -554 451 -1016 977 -518 471 -1038 485 -1010 457 -1036 969 -506 999 -520 481 -1014 975 -522 967 -520 975 -548 451 -1038 475 -1022 965 -518 463 -978 985 -486 465 -978 457 -1016 463 -978 985 -486 963 -480 1477 -129906 495 -726 197 -328 295 -132 2547 -66 233 -98 11033 -1856 233 -1458 65 -198 165 -134 199 -168 101 -694 463 -530 165 -300 99 -232 2479 -98 1745 -98 3029 -132 163 -1460 65 -500 65 -400 99 -664 895 -398 65 -564 331 -166 97 -66 197 -98 3813 -98 10097 -3848 165 -232 67 -266 397 -596 165 -66 199 -166 99 -66 199 -398 165 -166 1721 -232 429 -166 133 -330 133 -698 493 -200 197 -428 11029 -12118 65 -198 199 -68 231 -230 101 -166 99 -664 131 -132 3163 -4238 331 -298 531 -398 299 -98 199 -166 563 -100 131 -98 893 -66 3141 -1556 133 -1722 131 -830 197 -262 195 -66 163 -462 195 -396 195 -134 499 -132 265 -66 1717 -166 3175 -11366 199 -164 131 -66 163 -98 525 -98 363 -264 4495 -100 229 -66 131 -66 593 -3002 97 -394 131 -426 99 -462 597 -692 295 -298 431 -230 4231 -66 9711 -3246 131 -100 99 -400 263 -498 65 -100 297 -98 99 -132 65 -862 131 -66 365 -396 99 -166 1991 -98 1611 -132 10333 -790 65 -1984 99 -896 165 -332 365 -232 131 -830 65 -66 397 -166 197 -66 65 -496 199 -100 9975 -1728 67 -5008 727 -98 131 -100 2873 -66 12011 -3150 67 -960 99 -234 99 -298 231 -232 195 -266 165 -296 261 -166 757 -66 629 -196 657 -100 197 -134 297 -364 11237 -1684 65 -2076 165 -462 491 -100 663 -630 329 -264 263 -100 1357 -66 461 -1676 99 -1782 295 -296 65 -296 163 -230 99 -132 295 -66 163 -362 197 -724 757 -66 +RAW_Data: 3785 -66 13551 -1808 97 -730 65 -100 231 -132 131 -1230 593 -232 1579 -66 2667 -200 101 -3480 165 -692 133 -396 427 -1524 363 -66 431 -132 10305 -8288 461 -628 67 -430 725 -66 1053 -66 4501 -230 165 -66 331 -66 355 -266 263 -132 63 -562 459 -462 197 -66 129 -132 65 -100 2643 -132 2107 -66 9651 -3692 99 -100 195 -294 97 -660 759 -328 165 -560 891 -66 1953 -66 11305 -362 263 -662 131 -432 65 -134 563 -430 131 -132 1819 -100 165 -166 1061 -98 10089 -2476 65 -854 395 -198 99 -492 131 -164 229 -466 199 -428 299 -100 927 -200 1557 -134 4269 -10464 133 -1624 65 -198 265 -398 131 -430 729 -134 6189 -66 5421 -2082 165 -3342 19967 -12808 1439 -1536 453 -1046 449 -1032 449 -1056 947 -552 977 -522 977 -518 453 -1038 977 -522 977 -520 457 -1038 977 -506 1005 -496 495 -1008 975 -538 973 -530 465 -1008 975 -554 453 -1036 947 -518 487 -1008 475 -1042 443 -1050 461 -1008 1005 -510 447 -1048 985 -510 469 -1006 1005 -494 997 -514 975 -514 975 -504 999 -506 479 -1034 491 -1010 975 -508 973 -524 491 -1004 473 -1018 997 -520 975 -512 975 -518 473 -1030 983 -516 981 -514 471 -998 997 -522 481 -1012 481 -1012 457 -1050 973 -512 977 -524 459 -1016 1003 -512 479 -1014 459 -1016 475 -1012 1007 -522 969 -502 495 -1008 477 -1030 965 -522 975 -514 479 -1000 471 -1062 471 -964 483 -982 471 -1000 471 -980 979 -448 503 -988 465 -976 487 -974 1459 -23696 1407 -1616 401 -1068 429 -1080 419 -1058 935 -566 923 -584 417 -1078 939 -524 457 -1042 973 -550 443 -1028 949 -554 945 -552 447 -1022 979 -518 971 -542 479 -1024 947 -550 441 -1048 979 -518 453 -1044 449 -1050 449 -1020 485 -1014 981 -518 479 -1014 975 -524 459 -1036 973 -516 979 -518 971 -552 945 -550 945 -552 449 -1030 479 -1026 947 -554 949 -552 449 -1018 479 -1008 981 -518 975 -548 945 -554 451 -1034 967 -514 997 -514 445 -1036 967 -554 447 -1022 485 -1010 475 -1016 975 -518 977 -520 487 -1014 973 -552 451 -1040 441 -1050 447 -1022 485 -1014 987 -516 479 -1014 483 -1014 459 -1046 969 -514 449 -1044 967 -546 973 -488 447 -1016 443 -1000 973 -490 475 -980 983 -482 441 -1016 465 -976 1475 -23652 1451 -1548 479 -1014 461 -1014 471 -1044 975 -520 971 -502 495 -1012 977 -506 1005 -498 989 -516 481 -1016 975 -520 981 -514 475 -1014 979 -522 983 -512 475 -1022 965 -514 471 -1046 973 -494 473 -1016 475 -1046 447 -1050 463 -1012 999 -512 481 -1012 983 -520 477 -1014 977 -524 955 -548 973 -512 975 -520 967 -556 449 -1020 483 -1012 983 -520 973 -516 481 -1008 473 -1034 +RAW_Data: 967 -538 963 -544 973 -522 471 -1006 989 -512 1007 -520 443 -1036 985 -516 449 -1048 451 -1022 483 -1012 983 -520 977 -514 481 -1012 979 -514 483 -1022 481 -1010 471 -1020 479 -1020 979 -524 457 -1048 973 -514 483 -1012 981 -520 483 -1018 481 -1014 485 -986 467 -980 981 -486 469 -978 457 -1004 963 -480 983 -486 971 -514 1441 -23704 1383 -1628 389 -1112 385 -1092 407 -1092 915 -552 941 -570 441 -1064 423 -1046 451 -1044 939 -556 455 -1048 945 -552 973 -522 453 -1046 945 -552 947 -550 451 -1040 969 -518 479 -1028 951 -552 451 -1018 479 -1018 483 -1014 459 -1044 971 -514 483 -1010 971 -544 447 -1020 977 -524 987 -518 973 -516 979 -524 985 -518 479 -1016 447 -1050 953 -548 971 -514 483 -1014 459 -1048 967 -514 977 -526 953 -548 443 -1046 975 -492 995 -512 471 -1050 943 -552 445 -1032 455 -1044 449 -1048 941 -550 945 -552 449 -1050 945 -552 451 -1044 449 -1018 479 -1016 479 -1002 969 -542 973 -522 455 -1040 477 -1022 967 -534 959 -514 975 -554 469 -1008 449 -980 469 -1008 943 -484 1001 -484 467 -980 983 -482 961 -514 1439 -23700 1469 -1510 495 -1008 473 -1036 463 -1012 969 -546 973 -522 473 -1018 479 -1014 975 -526 955 -516 475 -1046 975 -490 999 -518 481 -1014 975 -520 967 -514 481 -1022 979 -524 457 -1048 971 -514 481 -1010 485 -1020 477 -1014 479 -1000 1001 -522 451 -1020 977 -520 473 -1032 967 -538 959 -514 1005 -522 965 -504 989 -514 475 -1046 441 -1050 971 -514 975 -520 473 -1018 481 -1014 979 -520 983 -520 977 -516 485 -1010 979 -544 975 -518 453 -1042 981 -520 453 -1024 483 -1010 457 -1050 975 -512 975 -524 459 -1048 973 -514 481 -1010 473 -1016 479 -1016 477 -1036 967 -506 995 -512 965 -546 445 -1048 957 -516 1005 -512 445 -1046 979 -486 473 -980 979 -486 473 -980 981 -486 473 -980 485 -986 467 -976 1477 -142204 197 -1486 165 -198 165 -664 295 -232 99 -266 231 -166 3045 -100 13411 -3670 197 -498 131 -166 231 -198 165 -66 265 -134 129 -1062 431 -130 465 -134 13447 -3848 329 -100 163 -298 99 -164 463 -98 197 -98 131 -198 65 -296 493 -264 789 -66 7225 -12438 99 -164 463 -132 197 -630 65 -198 2487 -66 165 -100 10097 -6554 459 -664 297 -460 4925 -132 6063 -12078 497 -98 99 -200 97 -234 165 -298 1721 -134 265 -100 3035 -100 12081 -3674 231 -100 97 -200 97 -264 461 -100 99 -132 231 -100 97 -430 527 -200 231 -64 2081 -132 327 -100 529 -66 831 -66 3067 -4704 99 -5520 97 -496 67 -198 167 -498 693 -462 2341 -15926 65 -1392 659 -134 131 -298 165 -66 99 -298 4777 -4208 429 -66 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 44e1613c7..12b08d48d 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -183,3 +183,10 @@ RAW_Data: -452 783 -462 811 -446 411 -874 383 -852 403 -852 777 -450 411 -838 80 RAW_Data: -500 395 -132 461 -132 689 -98 2685 -100 997 -1508 99 -2186 231 -166 231 -134 133 -932 65 -268 99 -132 65 -200 97 -68 163 -234 65 -68 99 -930 331 -98 763 -100 2025 -418 353 -446 385 -414 385 -416 387 -448 355 -442 383 -412 397 -424 405 -388 409 -418 379 -418 415 -4014 443 -814 413 -822 817 -454 801 -436 409 -842 409 -866 415 -838 441 -836 811 -432 387 -842 419 -846 793 -440 807 -448 837 -446 803 -448 835 -420 807 -448 383 -868 379 -850 409 -866 387 -844 825 -468 381 -884 793 -426 415 -842 427 -818 817 -440 407 -830 419 -844 429 -852 387 -872 409 -826 811 -450 813 -418 837 -412 409 -864 417 -844 397 -852 809 -454 805 -448 409 -840 809 -420 813 -458 409 -844 407 -860 385 -878 793 -470 809 -420 817 -416 417 -850 403 -852 381 -852 827 -428 447 -844 401 -854 813 -424 421 -840 419 -812 823 -438 415 -846 409 -844 415 -846 389 -868 809 -458 803 -416 409 -866 813 -418 417 -854 397 -862 419 -842 401 -854 415 -16404 435 -376 409 -410 407 -384 439 -384 409 -410 417 -368 421 -410 407 -378 447 -376 415 -378 447 -380 407 -4022 421 -844 423 -822 821 -418 807 -454 429 -820 421 -836 439 -854 421 -810 821 -436 385 -840 441 -822 813 -448 811 -452 803 -444 835 -444 801 -446 801 -426 447 -808 423 -834 413 -852 407 -840 819 -452 389 -856 813 -444 409 -848 415 -812 809 -458 409 -848 411 -842 415 -844 421 -834 415 -834 835 -418 819 -418 807 -456 393 -856 393 -866 421 -846 799 -474 809 -420 421 -836 811 -420 813 -458 407 -850 413 -842 415 -846 819 -428 835 -416 835 -412 407 -832 421 -842 423 -822 813 -446 407 -864 419 -846 799 -440 413 -850 419 -816 797 -442 413 -850 409 -844 417 -846 423 -834 841 -428 805 -414 435 -822 813 -450 413 -822 437 -818 421 -844 429 -854 411 -16406 427 -418 309 -522 307 -488 303 -520 289 -530 295 -500 323 -470 325 -504 321 -476 321 -476 355 -444 357 -4080 355 -906 339 -882 771 -476 777 -486 381 -874 383 -884 375 -884 387 -852 819 -418 417 -846 399 -854 809 -418 815 -446 837 -420 839 -454 801 -436 807 -452 399 -826 417 -844 391 -852 423 -838 809 -452 431 -852 811 -414 409 -836 417 -844 821 -432 385 -876 385 -850 409 -848 415 -854 421 -840 817 -420 815 -424 817 -448 409 -848 413 -844 389 -854 815 -446 829 -426 413 -842 819 -434 809 -446 409 -838 419 -846 401 -852 811 -456 811 -444 803 -418 417 -848 403 -850 381 -864 805 -450 395 -866 419 -848 801 -474 381 -848 411 RAW_Data: -842 807 -446 381 -872 377 -866 421 -846 401 -854 813 -458 779 -446 407 -832 811 -450 415 -856 399 -856 385 -876 399 -854 411 -16398 435 -392 395 -400 421 -412 385 -412 417 -384 415 -386 415 -418 385 -420 385 -420 417 -390 417 -388 419 -4020 421 -838 421 -812 819 -434 809 -448 397 -864 421 -844 401 -850 413 -858 789 -426 413 -844 419 -836 807 -424 843 -410 829 -442 835 -446 801 -454 809 -420 417 -832 411 -848 249 -88020 133 -896 231 -466 67 -1062 131 -728 163 -98 621 -98 1051 -100 680933 -452 269 -522 273 -554 273 -558 239 -558 271 -490 337 -488 321 -498 295 -500 325 -470 323 -474 353 -4082 757 -492 375 -880 357 -872 777 -486 773 -480 807 -450 805 -444 805 -476 407 -812 413 -834 411 -848 407 -828 813 -450 811 -458 803 -448 835 -446 791 -424 447 -808 427 -818 423 -840 419 -848 401 -854 811 -458 809 -446 801 -416 439 -826 415 -848 813 -430 809 -450 395 -866 419 -846 403 -850 413 -820 407 -848 415 -846 781 -460 805 -446 803 -474 803 -448 835 -420 805 -454 389 -836 409 -842 407 -866 419 -842 399 -854 809 -456 809 -446 409 -840 385 -844 819 -434 809 -450 395 -860 811 -452 393 -886 779 -446 409 -830 419 -842 423 -818 423 -838 419 -844 799 -472 809 -454 385 -844 807 -454 391 -854 395 -860 385 -844 429 -852 809 -454 385 -874 409 -16402 427 -368 455 -358 433 -380 443 -378 415 -378 447 -380 411 -384 409 -406 421 -408 387 -412 415 -386 415 -4026 831 -398 441 -810 417 -832 837 -418 833 -444 803 -446 833 -448 801 -424 449 -810 427 -820 423 -838 419 -812 825 -438 841 -416 845 -446 825 -418 809 -422 419 -822 433 -822 419 -844 425 -820 421 -840 841 -458 797 -436 809 -414 435 -822 419 -844 819 -432 809 -448 395 -864 421 -846 407 -850 411 -808 433 -824 419 -844 819 -432 809 -446 823 -416 837 -454 807 -440 809 -414 435 -828 417 -844 425 -828 415 -848 419 -818 839 -446 807 -422 411 -844 419 -846 795 -438 807 -450 395 -866 811 -454 391 -854 845 -412 407 -832 421 -842 419 -832 411 -824 435 -820 815 -450 811 -460 409 -850 799 -454 407 -824 413 -848 411 -842 415 -844 815 -432 415 -848 405 -16400 441 -432 327 -492 301 -516 307 -484 309 -520 307 -492 339 -454 337 -490 331 -464 327 -500 325 -472 325 -4110 763 -480 373 -852 385 -878 759 -482 775 -474 813 -458 781 -482 789 -454 415 -846 397 -820 411 -840 405 -852 809 -450 811 -458 809 -450 817 -448 803 -426 411 -844 391 -854 393 -866 419 -848 399 -854 811 RAW_Data: -454 811 -444 803 -418 417 -846 403 -850 809 -452 805 -444 411 -840 419 -846 407 -850 415 -836 385 -842 419 -850 797 -438 807 -452 817 -446 801 -486 813 -444 775 -450 409 -838 419 -810 431 -854 379 -848 405 -884 809 -450 817 -430 385 -874 375 -856 811 -446 809 -422 421 -836 835 -452 419 -848 783 -460 409 -814 407 -856 415 -846 383 -870 381 -848 819 -450 811 -472 383 -850 803 -454 415 -838 399 -854 379 -850 407 -848 811 -448 415 -872 387 -16400 451 -374 445 -374 415 -378 415 -412 411 -384 405 -422 409 -410 387 -410 417 -382 417 -384 415 -420 383 -4030 827 -428 411 -842 425 -820 817 -418 833 -426 845 -452 815 -428 837 -416 409 -842 421 -810 431 -820 421 -89106 265 -662 99 -532 131 -598 97 -668 65 -300 761 -198 231 -132 265 -100 233 -100 197 +RAW_Data: 7855 -12784 1413 -1544 469 -1040 465 -1010 479 -1020 967 -548 445 -1046 973 -524 967 -520 981 -516 483 -1042 449 -1034 949 -528 495 -1008 479 -1016 985 -518 453 -1042 449 -1052 949 -514 483 -1012 985 -512 477 -1042 445 -1050 951 -548 971 -512 975 -520 967 -554 949 -548 451 -1040 967 -520 987 -518 455 -1038 475 -1016 977 -518 983 -514 473 -1018 975 -518 487 -1002 475 -1020 965 -516 477 -1012 1007 -522 445 -1034 491 -1008 973 -524 +RAW_Data: 481 -992 481 -1010 483 -1030 977 -520 487 -1008 973 -522 987 -518 983 -514 965 -522 987 -520 489 -1004 473 -1018 471 -1016 1005 -476 511 -1012 457 -1018 1001 -510 975 -520 471 -1022 483 -1016 969 -536 1003 -454 981 -480 479 -986 981 -486 479 -946 989 -492 973 -484 473 -976 1503 -23606 1433 -1542 493 -1006 473 -1032 441 -1048 971 -514 483 -1012 985 -518 479 -1014 481 -1012 457 -1050 443 -1044 977 -520 473 -1004 495 -1004 969 -556 453 -1036 451 -1038 973 -520 485 -994 981 -520 457 -1050 477 -1014 977 -494 985 -538 961 -512 1005 -518 951 -526 491 -1006 969 -520 985 -524 455 -1044 447 -1048 983 -518 983 -514 441 -1050 981 -518 453 -1042 447 -1050 981 -518 451 -1046 975 -520 451 -1022 483 -1008 1001 -522 447 -1020 485 -1008 473 -1016 981 -550 449 -1044 977 -520 949 -550 979 -516 967 -520 983 -522 455 -1042 447 -1050 451 -1024 981 -520 483 -1018 963 -546 479 -1010 967 -520 483 -1022 975 -522 967 -552 487 -960 481 -990 451 -994 481 -980 479 -986 449 -984 969 -480 983 -510 1465 -23612 1473 -1520 479 -1026 453 -1044 451 -1036 943 -552 453 -1044 949 -518 481 -1018 977 -524 459 -1046 439 -1046 973 -528 463 -1012 471 -1046 943 -552 443 -1034 457 -1042 977 -518 479 -1028 949 -554 451 -1014 481 -1018 981 -524 985 -518 971 -514 979 -522 987 -512 477 -1016 977 -522 969 -552 449 -1016 483 -1014 985 -518 973 -516 481 -1012 967 -552 449 -1020 483 -1010 969 -554 447 -1022 977 -520 475 -1018 479 -1018 975 -522 457 -1036 479 -1016 479 -1002 969 -552 447 -1054 943 -548 969 -520 983 -520 983 -516 969 -518 479 -1030 453 -1044 449 -1048 943 -548 451 -1044 945 -552 975 -518 947 -552 449 -1034 975 -524 455 -1040 969 -520 449 -982 969 -518 945 -484 481 -984 481 -994 447 -986 477 -998 1435 -23658 1441 -1530 483 -1008 483 -1034 449 -1022 977 -520 485 -1018 479 -1018 975 -506 473 -1036 469 -1042 463 -1010 977 -520 487 -1030 451 -1010 981 -520 481 -1018 481 -1014 983 -518 479 -1016 975 -492 497 -1014 467 -1014 977 -520 975 -526 985 -516 979 -506 1005 -496 493 -1008 975 -522 983 -518 453 -1040 475 -1016 975 -524 987 -514 471 -1038 955 -514 473 -1046 445 -1044 967 -514 477 -1016 975 -520 457 -1050 477 -1010 973 -522 473 -1000 479 -1030 453 -1038 969 -506 473 -1050 971 -512 979 -524 955 -548 973 -512 975 -518 475 -1036 473 -1006 493 -1008 975 -520 973 -526 487 -1004 475 -1018 965 -516 1005 -512 481 -1014 985 -518 483 -986 975 -488 977 -480 977 -486 975 -482 481 -982 975 -480 977 -488 1477 -23618 1389 -1634 369 -1114 383 -1078 431 -1072 +RAW_Data: 931 -550 451 -1046 447 -1042 967 -552 945 -522 459 -1042 445 -1050 943 -552 439 -1036 459 -1046 977 -508 477 -1030 455 -1044 945 -552 451 -1020 979 -524 459 -1046 443 -1048 979 -518 967 -534 957 -516 977 -518 973 -528 455 -1042 973 -520 975 -526 459 -1040 481 -1020 969 -510 967 -546 447 -1050 955 -544 441 -1044 449 -1048 953 -550 443 -1046 975 -518 485 -1010 455 -1044 943 -554 447 -1054 449 -1010 475 -1048 943 -550 453 -1040 969 -520 973 -522 985 -514 969 -554 949 -524 459 -1040 477 -1014 483 -1034 947 -520 981 -554 447 -1016 977 -524 983 -516 973 -516 483 -1016 455 -1046 973 -484 977 -518 449 -986 447 -1016 971 -482 449 -1018 443 -1014 449 -984 1461 -129764 65 -3200 133 -464 133 -298 429 -132 265 -98 231 -134 265 -164 3439 -132 727 -132 199 -2058 133 -1644 361 -166 65 -492 165 -264 591 -428 197 -198 201 -98 831 -68 2313 -100 5839 -10922 65 -1320 425 -262 297 -428 97 -362 2463 -98 1025 -66 5263 -5030 99 -6924 461 -1092 133 -98 333 -166 2739 -132 3131 -66 10535 -2008 131 -434 297 -1058 65 -132 99 -198 529 -198 97 -526 97 -66 493 -664 99 -232 2613 -132 5371 -11166 229 -198 163 -394 199 -398 365 -132 99 -166 2121 -100 1195 -68 1821 -100 10635 -468 67 -1256 65 -2144 229 -100 163 -394 593 -98 67 -166 1677 -66 791 -66 335 -98 11033 -566 65 -1460 165 -1520 497 -1254 491 -564 99 -330 99 -232 1227 -132 2973 -66 3661 -11964 131 -132 99 -398 131 -328 97 -232 363 -396 1379 -98 99 -166 1591 -66 12171 -4136 65 -298 265 -298 199 -462 99 -330 65 -166 163 -66 1591 -66 165 -166 12079 -1002 65 -366 465 -530 97 -134 561 -66 497 -494 99 -64 131 -134 1095 -66 6537 -5066 65 -5458 397 -724 165 -466 131 -166 14293 -436 65 -1590 65 -1462 459 -332 65 -396 563 -794 197 -300 1255 -12100 99 -130 495 -166 97 -296 97 -658 757 -98 959 -66 1029 -1346 165 -2620 395 -494 197 -166 163 -198 65 -98 195 -394 821 -98 3063 -100 4469 -12120 497 -166 65 -462 195 -164 295 -66 4361 -100 1755 -100 131 -66 9415 -3840 99 -530 197 -364 463 -330 365 -332 133 -100 165 -166 2113 -100 1461 -132 4175 -3772 97 -7124 231 -1258 165 -100 429 -1326 995 -200 1755 -66 1519 -100 6437 -7198 133 -300 527 -398 165 -232 131 -166 67 -164 16443 -3270 131 -658 131 -726 97 -858 97 -300 331 -100 629 -10288 67 -164 133 -1458 297 -364 65 -98 163 -758 1189 -66 199 -68 1791 -66 897 -132 165 -3410 163 -364 99 -98 99 -66 365 -232 789 -494 65 -328 629 -66 1259 -66 365 -11422 7923 -12864 1405 -1562 +RAW_Data: 451 -1040 441 -1052 449 -1050 945 -554 449 -1052 451 -1020 481 -1010 473 -1050 449 -1052 451 -1040 969 -520 977 -520 455 -1042 977 -522 447 -1056 947 -518 979 -546 447 -1052 451 -1040 441 -1048 983 -518 455 -1044 449 -1018 979 -548 947 -554 449 -1032 481 -992 483 -1012 985 -514 999 -512 479 -1012 485 -1014 961 -544 477 -1010 965 -522 981 -512 483 -1012 487 -1020 477 -1014 479 -1016 459 -1014 471 -1012 1003 -492 997 -522 483 -1016 979 -522 985 -520 975 -512 975 -520 999 -488 985 -514 481 -1006 1001 -522 483 -990 483 -1008 483 -1020 977 -516 975 -518 999 -524 451 -1018 1009 -482 999 -506 983 -524 487 -1004 473 -980 501 -952 517 -940 497 -982 489 -974 987 -452 495 -974 487 -954 1485 -23662 1457 -1556 445 -1026 483 -1010 475 -1016 975 -518 483 -1014 487 -1034 447 -1022 977 -522 457 -1046 475 -1018 975 -524 985 -518 477 -1016 977 -524 459 -1048 969 -514 977 -522 457 -1038 479 -1018 481 -1002 1001 -520 447 -1054 449 -1008 1001 -520 977 -520 451 -1040 475 -1014 479 -1028 949 -518 983 -542 447 -1058 449 -1044 947 -552 447 -1024 977 -520 967 -542 479 -1024 451 -1040 441 -1050 451 -1028 481 -1014 483 -1010 965 -548 973 -518 485 -1010 981 -516 967 -520 983 -524 981 -514 969 -538 967 -518 481 -1016 973 -524 485 -1016 465 -1012 479 -1020 983 -532 959 -514 975 -554 949 -526 985 -512 969 -554 967 -534 461 -1042 443 -1014 967 -478 455 -1006 969 -486 967 -480 983 -486 969 -514 451 -982 1461 -23692 563 -4014 291 -1220 263 -1228 829 -620 883 -626 851 -608 903 -622 387 -1082 391 -1102 409 -1084 913 -588 941 -548 443 -1056 945 -522 445 -1046 971 -552 977 -516 441 -1048 481 -992 483 -1010 979 -554 451 -1018 481 -1014 983 -518 977 -514 479 -1040 447 -1034 485 -996 975 -520 979 -520 483 -1016 481 -1008 999 -506 471 -1050 971 -514 975 -520 473 -1000 483 -1020 481 -1008 473 -1018 481 -1020 481 -1008 967 -554 945 -518 481 -1038 967 -520 985 -520 981 -514 967 -520 985 -520 981 -508 479 -1016 1003 -518 479 -1010 479 -1010 473 -1018 975 -516 979 -520 983 -520 975 -514 977 -518 999 -520 979 -518 451 -1040 479 -986 479 -962 1007 -486 451 -986 975 -486 977 -482 483 -980 477 -982 1473 -23656 1453 -1548 447 -1016 485 -1012 491 -1012 973 -520 981 -526 983 -514 971 -554 947 -526 491 -1008 475 -1020 983 -498 989 -516 483 -1014 977 -524 453 -1044 979 -518 979 -520 453 -1042 449 -1048 447 -1022 975 -518 475 -1050 447 -1020 977 -522 983 -518 481 -1016 481 -1012 473 -1002 973 -550 945 -552 449 -1050 447 -1020 975 -522 487 -1034 973 -520 +RAW_Data: 979 -514 443 -1046 479 -1028 451 -1042 451 -1048 447 -1022 485 -1014 983 -520 973 -516 483 -1012 983 -518 973 -516 977 -520 1003 -520 975 -520 981 -514 475 -1034 969 -516 479 -1016 447 -1046 475 -1018 975 -516 975 -522 983 -510 469 -1010 1007 -518 951 -530 989 -516 973 -556 951 -494 481 -978 487 -978 975 -460 1005 -466 979 -486 969 -508 981 -450 1489 -23666 571 -4036 269 -1224 257 -1250 787 -642 867 -622 883 -622 359 -1136 373 -1086 421 -1080 417 -1074 935 -550 947 -552 445 -1048 939 -552 451 -1046 947 -552 947 -550 451 -1040 443 -1048 453 -1024 977 -522 471 -1034 449 -1020 973 -540 975 -508 479 -1032 453 -1042 449 -1050 977 -518 979 -518 449 -1018 481 -1018 975 -518 473 -1034 963 -542 961 -544 447 -1044 473 -1020 479 -1014 481 -1010 473 -1032 471 -1010 959 -546 973 -492 499 -1006 997 -510 977 -524 953 -552 971 -512 973 -508 979 -554 451 -1016 977 -518 471 -1038 485 -1010 457 -1036 969 -506 999 -520 481 -1014 975 -522 967 -520 975 -548 451 -1038 475 -1022 965 -518 463 -978 985 -486 465 -978 457 -1016 463 -978 985 -486 963 -480 1477 -129906 495 -726 197 -328 295 -132 2547 -66 233 -98 11033 -1856 233 -1458 65 -198 165 -134 199 -168 101 -694 463 -530 165 -300 99 -232 2479 -98 1745 -98 3029 -132 163 -1460 65 -500 65 -400 99 -664 895 -398 65 -564 331 -166 97 -66 197 -98 3813 -98 10097 -3848 165 -232 67 -266 397 -596 165 -66 199 -166 99 -66 199 -398 165 -166 1721 -232 429 -166 133 -330 133 -698 493 -200 197 -428 11029 -12118 65 -198 199 -68 231 -230 101 -166 99 -664 131 -132 3163 -4238 331 -298 531 -398 299 -98 199 -166 563 -100 131 -98 893 -66 3141 -1556 133 -1722 131 -830 197 -262 195 -66 163 -462 195 -396 195 -134 499 -132 265 -66 1717 -166 3175 -11366 199 -164 131 -66 163 -98 525 -98 363 -264 4495 -100 229 -66 131 -66 593 -3002 97 -394 131 -426 99 -462 597 -692 295 -298 431 -230 4231 -66 9711 -3246 131 -100 99 -400 263 -498 65 -100 297 -98 99 -132 65 -862 131 -66 365 -396 99 -166 1991 -98 1611 -132 10333 -790 65 -1984 99 -896 165 -332 365 -232 131 -830 65 -66 397 -166 197 -66 65 -496 199 -100 9975 -1728 67 -5008 727 -98 131 -100 2873 -66 12011 -3150 67 -960 99 -234 99 -298 231 -232 195 -266 165 -296 261 -166 757 -66 629 -196 657 -100 197 -134 297 -364 11237 -1684 65 -2076 165 -462 491 -100 663 -630 329 -264 263 -100 1357 -66 461 -1676 99 -1782 295 -296 65 -296 163 -230 99 -132 295 -66 163 -362 197 -724 757 -66 +RAW_Data: 3785 -66 13551 -1808 97 -730 65 -100 231 -132 131 -1230 593 -232 1579 -66 2667 -200 101 -3480 165 -692 133 -396 427 -1524 363 -66 431 -132 10305 -8288 461 -628 67 -430 725 -66 1053 -66 4501 -230 165 -66 331 -66 355 -266 263 -132 63 -562 459 -462 197 -66 129 -132 65 -100 2643 -132 2107 -66 9651 -3692 99 -100 195 -294 97 -660 759 -328 165 -560 891 -66 1953 -66 11305 -362 263 -662 131 -432 65 -134 563 -430 131 -132 1819 -100 165 -166 1061 -98 10089 -2476 65 -854 395 -198 99 -492 131 -164 229 -466 199 -428 299 -100 927 -200 1557 -134 4269 -10464 133 -1624 65 -198 265 -398 131 -430 729 -134 6189 -66 5421 -2082 165 -3342 19967 -12808 1439 -1536 453 -1046 449 -1032 449 -1056 947 -552 977 -522 977 -518 453 -1038 977 -522 977 -520 457 -1038 977 -506 1005 -496 495 -1008 975 -538 973 -530 465 -1008 975 -554 453 -1036 947 -518 487 -1008 475 -1042 443 -1050 461 -1008 1005 -510 447 -1048 985 -510 469 -1006 1005 -494 997 -514 975 -514 975 -504 999 -506 479 -1034 491 -1010 975 -508 973 -524 491 -1004 473 -1018 997 -520 975 -512 975 -518 473 -1030 983 -516 981 -514 471 -998 997 -522 481 -1012 481 -1012 457 -1050 973 -512 977 -524 459 -1016 1003 -512 479 -1014 459 -1016 475 -1012 1007 -522 969 -502 495 -1008 477 -1030 965 -522 975 -514 479 -1000 471 -1062 471 -964 483 -982 471 -1000 471 -980 979 -448 503 -988 465 -976 487 -974 1459 -23696 1407 -1616 401 -1068 429 -1080 419 -1058 935 -566 923 -584 417 -1078 939 -524 457 -1042 973 -550 443 -1028 949 -554 945 -552 447 -1022 979 -518 971 -542 479 -1024 947 -550 441 -1048 979 -518 453 -1044 449 -1050 449 -1020 485 -1014 981 -518 479 -1014 975 -524 459 -1036 973 -516 979 -518 971 -552 945 -550 945 -552 449 -1030 479 -1026 947 -554 949 -552 449 -1018 479 -1008 981 -518 975 -548 945 -554 451 -1034 967 -514 997 -514 445 -1036 967 -554 447 -1022 485 -1010 475 -1016 975 -518 977 -520 487 -1014 973 -552 451 -1040 441 -1050 447 -1022 485 -1014 987 -516 479 -1014 483 -1014 459 -1046 969 -514 449 -1044 967 -546 973 -488 447 -1016 443 -1000 973 -490 475 -980 983 -482 441 -1016 465 -976 1475 -23652 1451 -1548 479 -1014 461 -1014 471 -1044 975 -520 971 -502 495 -1012 977 -506 1005 -498 989 -516 481 -1016 975 -520 981 -514 475 -1014 979 -522 983 -512 475 -1022 965 -514 471 -1046 973 -494 473 -1016 475 -1046 447 -1050 463 -1012 999 -512 481 -1012 983 -520 477 -1014 977 -524 955 -548 973 -512 975 -520 967 -556 449 -1020 483 -1012 983 -520 973 -516 481 -1008 473 -1034 +RAW_Data: 967 -538 963 -544 973 -522 471 -1006 989 -512 1007 -520 443 -1036 985 -516 449 -1048 451 -1022 483 -1012 983 -520 977 -514 481 -1012 979 -514 483 -1022 481 -1010 471 -1020 479 -1020 979 -524 457 -1048 973 -514 483 -1012 981 -520 483 -1018 481 -1014 485 -986 467 -980 981 -486 469 -978 457 -1004 963 -480 983 -486 971 -514 1441 -23704 1383 -1628 389 -1112 385 -1092 407 -1092 915 -552 941 -570 441 -1064 423 -1046 451 -1044 939 -556 455 -1048 945 -552 973 -522 453 -1046 945 -552 947 -550 451 -1040 969 -518 479 -1028 951 -552 451 -1018 479 -1018 483 -1014 459 -1044 971 -514 483 -1010 971 -544 447 -1020 977 -524 987 -518 973 -516 979 -524 985 -518 479 -1016 447 -1050 953 -548 971 -514 483 -1014 459 -1048 967 -514 977 -526 953 -548 443 -1046 975 -492 995 -512 471 -1050 943 -552 445 -1032 455 -1044 449 -1048 941 -550 945 -552 449 -1050 945 -552 451 -1044 449 -1018 479 -1016 479 -1002 969 -542 973 -522 455 -1040 477 -1022 967 -534 959 -514 975 -554 469 -1008 449 -980 469 -1008 943 -484 1001 -484 467 -980 983 -482 961 -514 1439 -23700 1469 -1510 495 -1008 473 -1036 463 -1012 969 -546 973 -522 473 -1018 479 -1014 975 -526 955 -516 475 -1046 975 -490 999 -518 481 -1014 975 -520 967 -514 481 -1022 979 -524 457 -1048 971 -514 481 -1010 485 -1020 477 -1014 479 -1000 1001 -522 451 -1020 977 -520 473 -1032 967 -538 959 -514 1005 -522 965 -504 989 -514 475 -1046 441 -1050 971 -514 975 -520 473 -1018 481 -1014 979 -520 983 -520 977 -516 485 -1010 979 -544 975 -518 453 -1042 981 -520 453 -1024 483 -1010 457 -1050 975 -512 975 -524 459 -1048 973 -514 481 -1010 473 -1016 479 -1016 477 -1036 967 -506 995 -512 965 -546 445 -1048 957 -516 1005 -512 445 -1046 979 -486 473 -980 979 -486 473 -980 981 -486 473 -980 485 -986 467 -976 1477 -142204 197 -1486 165 -198 165 -664 295 -232 99 -266 231 -166 3045 -100 13411 -3670 197 -498 131 -166 231 -198 165 -66 265 -134 129 -1062 431 -130 465 -134 13447 -3848 329 -100 163 -298 99 -164 463 -98 197 -98 131 -198 65 -296 493 -264 789 -66 7225 -12438 99 -164 463 -132 197 -630 65 -198 2487 -66 165 -100 10097 -6554 459 -664 297 -460 4925 -132 6063 -12078 497 -98 99 -200 97 -234 165 -298 1721 -134 265 -100 3035 -100 12081 -3674 231 -100 97 -200 97 -264 461 -100 99 -132 231 -100 97 -430 527 -200 231 -64 2081 -132 327 -100 529 -66 831 -66 3067 -4704 99 -5520 97 -496 67 -198 167 -498 693 -462 2341 -15926 65 -1392 659 -134 131 -298 165 -66 99 -298 4777 -4208 429 -66 diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 411ceeacf..dd5521a64 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -14,6 +14,9 @@ #define TAG "SubGhzProtocoNiceFlorS" +#define NICE_ONE_COUNT_BIT 72 +#define NICE_ONE_NAME "Nice One" + static const SubGhzBlockConst subghz_protocol_nice_flor_s_const = { .te_short = 500, .te_long = 1000, @@ -28,6 +31,7 @@ struct SubGhzProtocolDecoderNiceFlorS { SubGhzBlockGeneric generic; const char* nice_flor_s_rainbow_table_file_name; + uint64_t data; }; struct SubGhzProtocolEncoderNiceFlorS { @@ -77,6 +81,64 @@ const SubGhzProtocol subghz_protocol_nice_flor_s = { .encoder = &subghz_protocol_nice_flor_s_encoder, }; +// /** +// * Read bytes from rainbow table +// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10 +// * @return crc +// */ +// static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) { +// uint8_t crc = 0; +// uint8_t crc_data = 0xff; +// for(uint8_t i = 4; i < 68; i++) { +// if(subghz_protocol_blocks_get_bit_array(p, i)) { +// crc = crc_data ^ 1; +// } else { +// crc = crc_data; +// } +// crc_data >>= 1; +// if((crc & 0x01)) { +// crc_data ^= 0x97; +// } +// } +// crc = 0; +// for(uint8_t i = 0; i < 8; i++) { +// crc <<= 1; +// if((crc_data >> i) & 0x01) crc = crc | 1; +// } +// return crc; +// } + +// /** +// * Read bytes from rainbow table +// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX +// * @param num_parcel parcel number 0..15 +// * @param hold_bit 0 - the button was only pressed, 1 - the button was held down +// */ +// static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) { +// uint8_t k = 0; +// uint8_t crc = 0; +// p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4); +// if(num_parcel < 4) { +// k = 0x8f; +// } else { +// k = 0x80; +// } + +// if(!hold_bit) { +// hold_bit = 0; +// } else { +// hold_bit = 0x10; +// } +// k = num_parcel ^ k; +// p[7] = k; +// p[8] = hold_bit ^ (k << 4); + +// crc = subghz_protocol_nice_one_crc(p); + +// p[8] |= crc >> 4; +// p[9] = crc << 4; +// } + /** * Read bytes from rainbow table * @param file_name Full path to rainbow table the file @@ -237,10 +299,14 @@ void subghz_protocol_decoder_nice_flor_s_feed(void* context, bool level, uint32_ subghz_protocol_nice_flor_s_const.te_delta) { //Found STOP bit instance->decoder.parser_step = NiceFlorSDecoderStepReset; - if(instance->decoder.decode_count_bit == - subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { - instance->generic.data = instance->decoder.decode_data; + if((instance->decoder.decode_count_bit == + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) || + (instance->decoder.decode_count_bit == NICE_ONE_COUNT_BIT)) { + instance->generic.data = instance->data; + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = instance->generic.data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; + if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); } @@ -274,6 +340,11 @@ void subghz_protocol_decoder_nice_flor_s_feed(void* context, bool level, uint32_ } else { instance->decoder.parser_step = NiceFlorSDecoderStepReset; } + if(instance->decoder.decode_count_bit == + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } break; } } @@ -287,6 +358,7 @@ static void subghz_protocol_nice_flor_s_remote_controller( SubGhzBlockGeneric* instance, const char* file_name) { /* + * Protocol Nice Flor-S * Packet format Nice Flor-s: START-P0-P1-P2-P3-P4-P5-P6-P7-STOP * P0 (4-bit) - button positional code - 1:0x1, 2:0x2, 3:0x4, 4:0x8; * P1 (4-bit) - batch repetition number, calculated by the formula: @@ -307,6 +379,24 @@ static void subghz_protocol_nice_flor_s_remote_controller( * data => 0x1c5783607f7b3 key serial cnt * decrypt => 0x10436c6820444 => 0x1 0436c682 0444 * + * Protocol Nice One + * Generally repeats the Nice Flor-S protocol, but there are a few changes + * Packet format first 52 bytes repeat Nice Flor-S protocol + * The additional 20 bytes contain the code of the pressed button, + * the button hold bit and the CRC of the entire message. + * START-P0-P1-P2-P3-P4-P5-P6-P7-P8-P9-P10-STOP + * P7 (byte) - if (n<4) k=0x8f : k=0x80; P7= k^n; + * P8 (byte) - if (hold bit) b=0x00 : b=0x10; P8= b^(k<<4) | 4 hi bit crc + * P10 (4-bit) - 4 lo bit crc + * key+b crc + * data => 0x1724A7D9A522F 899 D6 hold bit = 0 - just pressed the button + * data => 0x1424A7D9A522F 8AB 03 hold bit = 1 - button hold + * + * A small button hold counter (0..15) is stored between each press, + * i.e. if 1 press of the button stops counter 6, then the next press + * of the button will start from the value 7 (hold bit = 0), 8 (hold bit = 1)... + * further up to 15 with overflow + * */ if(!file_name) { instance->cnt = 0; @@ -333,7 +423,15 @@ bool subghz_protocol_decoder_nice_flor_s_serialize( SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; - return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + if(res && + !flipper_format_write_uint32(flipper_format, "Data", (uint32_t*)&instance->data, 1)) { + FURI_LOG_E(TAG, "Unable to add Data"); + res = false; + } + } + return res; } bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { @@ -344,11 +442,25 @@ bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperForma if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { break; } - if(instance->generic.data_count_bit != - subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { + if((instance->generic.data_count_bit != + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != NICE_ONE_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); break; } + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint32_t temp = 0; + if(!flipper_format_read_uint32(flipper_format, "Data", (uint32_t*)&temp, 1)) { + FURI_LOG_E(TAG, "Missing Data"); + break; + } + instance->data = (uint64_t)temp; + } + ret = true; } while(false); return ret; @@ -360,20 +472,33 @@ void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* o subghz_protocol_nice_flor_s_remote_controller( &instance->generic, instance->nice_flor_s_rainbow_table_file_name); - uint32_t code_found_hi = instance->generic.data >> 32; - uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - furi_string_cat_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:%05lX\r\n" - "Cnt:%04lX Btn:%02X\r\n", - instance->generic.protocol_name, - instance->generic.data_count_bit, - code_found_hi, - code_found_lo, - instance->generic.serial, - instance->generic.cnt, - instance->generic.btn); + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%013llX%llX\r\n" + "Sn:%05lX\r\n" + "Cnt:%04lX Btn:%02X\r\n", + NICE_ONE_NAME, + instance->generic.data_count_bit, + instance->generic.data, + instance->data, + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } else { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%013llX\r\n" + "Sn:%05lX\r\n" + "Cnt:%04lX Btn:%02X\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + instance->generic.data, + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } } From 39841bd5a9ad1d6b1f4d222ab0670be96aadc732 Mon Sep 17 00:00:00 2001 From: itsweekly <92674764+itsweekly@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:28:34 +0100 Subject: [PATCH 14/34] Universal Projector Remote (#2343) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Georgii Surkov Co-authored-by: あく --- applications/main/infrared/infrared_cli.c | 2 +- .../infrared/scenes/infrared_scene_config.h | 1 + .../scenes/infrared_scene_universal.c | 12 +- .../infrared_scene_universal_projector.c | 86 ++ assets/resources/infrared/assets/projector.ir | 829 ++++++++++++++++++ documentation/UniversalRemotes.md | 7 + 6 files changed, 935 insertions(+), 2 deletions(-) create mode 100644 applications/main/infrared/scenes/infrared_scene_universal_projector.c create mode 100644 assets/resources/infrared/assets/projector.ir diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index 5f5e2d4bb..3fa99cb02 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -86,7 +86,7 @@ static void infrared_cli_print_usage(void) { printf("\tir universal \r\n"); printf("\tir universal list \r\n"); // TODO: Do not hardcode universal remote names - printf("\tAvailable universal remotes: tv audio ac\r\n"); + printf("\tAvailable universal remotes: tv audio ac projector\r\n"); } static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) { diff --git a/applications/main/infrared/scenes/infrared_scene_config.h b/applications/main/infrared/scenes/infrared_scene_config.h index 111fd2d31..27eabe225 100644 --- a/applications/main/infrared/scenes/infrared_scene_config.h +++ b/applications/main/infrared/scenes/infrared_scene_config.h @@ -17,6 +17,7 @@ ADD_SCENE(infrared, universal, Universal) ADD_SCENE(infrared, universal_tv, UniversalTV) ADD_SCENE(infrared, universal_ac, UniversalAC) ADD_SCENE(infrared, universal_audio, UniversalAudio) +ADD_SCENE(infrared, universal_projector, UniversalProjector) ADD_SCENE(infrared, debug, Debug) ADD_SCENE(infrared, error_databases, ErrorDatabases) ADD_SCENE(infrared, rpc, Rpc) diff --git a/applications/main/infrared/scenes/infrared_scene_universal.c b/applications/main/infrared/scenes/infrared_scene_universal.c index 5043c9bd7..4ef7c5c26 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal.c +++ b/applications/main/infrared/scenes/infrared_scene_universal.c @@ -4,6 +4,7 @@ typedef enum { SubmenuIndexUniversalTV, SubmenuIndexUniversalAC, SubmenuIndexUniversalAudio, + SubmenuIndexUniversalProjector, } SubmenuIndex; static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) { @@ -27,6 +28,12 @@ void infrared_scene_universal_on_enter(void* context) { SubmenuIndexUniversalAudio, infrared_scene_universal_submenu_callback, context); + submenu_add_item( + submenu, + "Projectors", + SubmenuIndexUniversalProjector, + infrared_scene_universal_submenu_callback, + context); submenu_add_item( submenu, "Air Conditioners", @@ -54,6 +61,9 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubmenuIndexUniversalAudio) { scene_manager_next_scene(scene_manager, InfraredSceneUniversalAudio); consumed = true; + } else if(event.event == SubmenuIndexUniversalProjector) { + scene_manager_next_scene(scene_manager, InfraredSceneUniversalProjector); + consumed = true; } scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event); } @@ -64,4 +74,4 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { void infrared_scene_universal_on_exit(void* context) { Infrared* infrared = context; submenu_reset(infrared->submenu); -} +} \ No newline at end of file diff --git a/applications/main/infrared/scenes/infrared_scene_universal_projector.c b/applications/main/infrared/scenes/infrared_scene_universal_projector.c new file mode 100644 index 000000000..c1df91c34 --- /dev/null +++ b/applications/main/infrared/scenes/infrared_scene_universal_projector.c @@ -0,0 +1,86 @@ +#include "../infrared_i.h" + +#include "common/infrared_scene_universal_common.h" + +void infrared_scene_universal_projector_on_enter(void* context) { + infrared_scene_universal_common_on_enter(context); + + Infrared* infrared = context; + ButtonPanel* button_panel = infrared->button_panel; + InfraredBruteForce* brute_force = infrared->brute_force; + + infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/projector.ir")); + + button_panel_reserve(button_panel, 2, 2); + uint32_t i = 0; + button_panel_add_item( + button_panel, + i, + 0, + 0, + 3, + 19, + &I_Power_25x27, + &I_Power_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Power"); + button_panel_add_item( + button_panel, + i, + 1, + 0, + 36, + 19, + &I_Mute_25x27, + &I_Mute_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Mute"); + button_panel_add_item( + button_panel, + i, + 0, + 1, + 3, + 66, + &I_Vol_up_25x27, + &I_Vol_up_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Vol_up"); + button_panel_add_item( + button_panel, + i, + 1, + 1, + 36, + 66, + &I_Vol_down_25x27, + &I_Vol_down_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "Vol_dn"); + + button_panel_add_label(button_panel, 2, 11, FontPrimary, "Proj. remote"); + button_panel_add_label(button_panel, 17, 62, FontSecondary, "Volume"); + + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + + infrared_show_loading_popup(infrared, true); + bool success = infrared_brute_force_calculate_messages(brute_force); + infrared_show_loading_popup(infrared, false); + + if(!success) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); + } +} + +bool infrared_scene_universal_projector_on_event(void* context, SceneManagerEvent event) { + return infrared_scene_universal_common_on_event(context, event); +} + +void infrared_scene_universal_projector_on_exit(void* context) { + infrared_scene_universal_common_on_exit(context); +} diff --git a/assets/resources/infrared/assets/projector.ir b/assets/resources/infrared/assets/projector.ir new file mode 100644 index 000000000..e9861de21 --- /dev/null +++ b/assets/resources/infrared/assets/projector.ir @@ -0,0 +1,829 @@ +Filetype: IR library file +Version: 1 +# +# Model: Smart +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 8A 00 00 00 +# +# Model: Epson +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +# Model: Epson +name: Power +type: parsed +protocol: NECext +address: 81 03 00 00 +command: F0 0F 00 00 +# +# Model: Hitatchi +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 +# +name: Vol_up +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 49 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 0B 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 48 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 44 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 83 7C 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 82 7D 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 13 00 00 +command: 87 78 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9055 4338 672 1551 669 1553 618 1603 619 481 617 482 616 481 617 507 591 1605 645 479 619 1577 645 1578 644 1578 644 479 619 480 618 1581 641 480 617 1605 617 1606 616 1606 615 483 615 1608 614 484 614 484 614 484 614 484 614 484 614 484 614 1609 614 484 614 1609 614 1609 613 1609 613 40058 9000 2068 614 95467 9022 2068 614 +# +name: Mute +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 29 D6 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 08 F7 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 04 FB 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 93 6C 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4462 598 501 627 1604 627 530 598 531 677 423 706 422 706 421 707 451 677 1554 677 451 598 1633 598 1634 597 1634 598 1634 598 1634 625 1606 681 1550 626 502 598 530 599 529 600 1632 600 528 600 528 601 528 601 528 601 1631 600 1631 625 1607 625 504 625 1607 624 1608 624 1608 623 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 1D 00 00 00 +# +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9096 4436 620 505 647 478 648 501 623 1599 647 1624 623 502 623 503 621 504 619 1628 618 507 617 507 617 1630 617 508 616 1630 617 1630 617 1631 616 508 616 508 617 508 616 1631 616 508 617 508 617 508 616 508 616 1630 616 1630 616 1631 616 508 616 1630 617 1630 617 1630 617 1631 617 509 616 508 616 509 616 509 616 509 616 509 615 509 616 508 617 1631 616 1631 615 1631 616 1631 616 1631 616 1631 616 1631 615 1631 616 14435 9093 2186 615 96359 9095 2184 617 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9091 4465 594 530 595 530 594 530 594 1651 595 1652 595 529 621 504 620 504 619 1628 618 507 617 508 616 1631 616 509 615 1631 616 1631 616 1632 615 509 616 509 616 509 615 1631 616 509 616 508 616 1631 616 509 616 1631 615 1631 616 1631 617 508 616 1631 616 1631 616 508 616 1631 617 508 617 509 616 509 616 509 616 509 616 509 616 509 616 509 616 1631 616 1631 616 1631 616 1631 616 1631 615 1631 615 1631 615 1631 616 14435 9090 2190 615 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 619 506 618 530 593 1627 620 1630 643 504 620 505 618 506 617 1630 617 508 616 508 616 1632 616 508 617 1631 616 1631 616 1631 616 1631 616 509 616 508 616 1631 616 509 616 509 615 1632 616 509 616 508 616 1631 616 1631 616 508 616 1631 615 1631 616 509 615 1632 615 509 616 509 616 509 616 509 616 509 616 510 615 509 616 509 616 1631 616 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 615 14434 9088 2191 615 96339 9115 2189 616 96343 9117 2189 616 96343 9114 2189 616 +# AV-Mute +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 618 506 618 530 594 1627 619 1629 643 505 619 505 619 506 617 1629 617 508 616 508 616 1631 616 508 616 1630 616 1630 616 1630 617 1630 616 1630 616 1631 616 508 616 508 616 508 616 1631 616 508 617 508 616 508 616 508 616 1630 616 1631 615 1631 616 508 616 1631 616 508 617 508 616 509 615 509 616 508 616 509 615 509 616 508 616 1631 615 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 616 14433 9088 2191 615 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9014 4332 661 1570 661 471 660 473 658 474 657 476 655 498 633 498 634 502 633 499 633 1599 632 1599 632 1599 632 1599 632 1599 632 1600 631 1603 632 500 632 501 631 501 631 501 631 501 631 501 631 1601 631 504 631 1601 631 1601 631 1601 631 1601 631 1601 630 1601 630 501 631 1601 631 38177 8983 2149 630 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 4C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9042 4306 690 1541 665 468 664 468 664 469 663 470 662 471 660 495 636 499 636 497 634 1597 634 1598 633 1598 633 1599 633 1599 632 1599 633 1603 632 1599 633 499 633 499 633 500 632 499 633 500 632 1600 632 503 633 500 632 1600 632 1600 632 1600 633 1600 632 1600 632 500 632 1600 632 37912 8986 2145 633 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3522 1701 472 426 444 1269 472 426 444 426 443 427 443 427 443 426 444 427 443 426 444 427 442 428 441 429 440 431 438 1304 437 433 437 433 438 433 437 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1305 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 459 411 459 411 459 411 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 459 411 459 411 1330 411 1330 411 460 410 1330 411 1330 411 1331 410 1330 411 74392 3516 1736 436 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 435 435 1305 436 435 435 435 435 1306 435 435 435 435 435 435 435 436 434 436 434 436 434 435 435 436 434 436 434 436 434 1330 411 1331 410 1330 411 1330 411 1330 411 459 411 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 435 436 434 436 1306 435 435 435 435 435 1306 435 435 435 435 435 435 435 435 435 435 435 436 434 436 434 435 435 436 434 435 435 1306 435 1330 411 1307 434 1331 410 1308 433 436 434 436 434 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 435 435 434 436 434 436 434 436 434 436 434 436 1306 435 435 435 435 435 435 435 1306 435 435 435 436 434 1306 435 435 435 436 434 436 434 435 435 436 434 436 434 460 410 460 410 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 434 436 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 435 435 435 435 434 436 1306 435 434 436 435 435 435 435 1306 435 436 434 435 435 1306 435 435 435 436 434 436 434 436 434 436 434 460 410 437 433 459 411 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3514 1736 437 434 436 1304 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 435 435 434 436 434 436 435 435 434 436 1305 436 435 435 435 435 435 435 1306 435 435 435 435 435 1306 435 435 435 436 434 435 435 459 411 436 434 435 435 459 411 459 411 459 411 459 411 1330 411 1306 435 1330 411 1330 411 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9069 4362 622 486 621 487 621 491 622 1608 623 1603 622 487 621 487 621 491 622 1604 621 487 622 491 622 1604 621 491 622 1608 622 1609 621 1604 622 486 622 487 621 491 621 1605 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1604 622 491 621 1609 622 1604 621 491 621 1604 622 487 621 487 622 486 622 487 621 488 621 487 621 488 620 491 621 1609 622 1609 620 1609 621 1609 621 1609 621 1609 621 1609 621 1618 621 14330 9047 2137 620 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9047 4362 621 486 622 463 645 490 622 1609 622 1604 622 487 620 487 621 491 622 1604 622 484 625 490 621 1605 649 463 621 1609 620 1611 621 1608 622 1605 621 486 622 491 622 1604 621 487 621 492 620 1604 621 488 621 492 620 1609 622 1604 621 492 622 1609 620 1605 621 491 622 1603 622 488 621 488 620 488 620 488 621 488 620 487 622 485 621 492 596 1635 621 1609 622 1585 643 1611 620 1608 621 1610 619 1611 620 1619 619 14332 9074 2109 647 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9073 4336 648 461 647 484 624 489 623 1607 623 1603 622 486 622 486 622 491 622 1604 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1609 621 1608 622 1609 621 1604 621 486 622 486 622 491 622 1604 622 486 622 487 621 487 621 491 622 1608 622 1609 621 1604 622 491 621 1604 621 487 621 486 622 487 621 487 621 487 621 487 621 487 621 491 622 1608 622 1608 622 1609 621 1608 622 1608 622 1608 622 1609 621 1617 622 14330 9047 2137 620 +# ON +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4F B0 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 10 EF 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 46 B9 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 51 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 40 40 00 00 +command: 0A F5 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4E B1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0E F1 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0D F2 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4F B0 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 16 00 00 +command: 87 78 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 08 16 00 00 +command: C8 37 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 01 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 02 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 28 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 29 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 00 FF 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1D E2 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 99 66 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 98 67 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4F B0 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4B B4 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 2E 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 52 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 41 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 51 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 56 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 5A 00 00 00 +# +name: Power +type: parsed +protocol: SIRC15 +address: 54 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 82 7D 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 83 7C 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 91 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 90 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 31 00 00 00 +command: D0 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 89 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 00 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 30 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 31 00 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 32 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 30 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 0D 00 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4482 593 563 569 561 571 559 563 1698 566 1694 570 559 563 568 564 566 566 1695 569 560 572 559 563 1671 593 563 569 1692 562 1671 593 1693 571 558 564 567 565 565 567 1693 571 532 590 567 565 1695 569 560 562 1698 566 1694 570 1663 591 539 593 1693 571 1688 566 564 568 1691 563 567 565 565 567 563 569 561 571 559 563 567 565 565 567 563 569 1690 564 1695 569 1691 563 1696 568 1691 563 1697 567 1692 562 1697 567 13988 9030 2223 597 96250 9035 2219 591 96245 9032 2221 589 96240 9038 2215 595 96235 9033 2220 590 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9028 4482 593 563 569 561 571 558 564 1696 568 1690 564 566 566 563 569 561 571 1688 566 563 569 561 571 1688 566 563 569 1690 564 1695 569 1689 565 1668 596 560 562 568 564 1695 569 560 562 568 564 1695 569 560 562 568 564 1695 569 1690 564 566 566 1692 572 1687 567 563 569 1690 564 566 566 564 568 562 570 559 563 567 565 565 567 562 570 560 562 1696 568 1665 589 1670 594 1665 589 1670 594 1664 590 1669 647 1612 590 13987 9031 2220 590 96223 9033 2217 593 96223 9034 2218 592 96225 9032 2219 591 96221 9087 2164 595 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9031 4479 596 560 572 558 564 566 566 1693 571 1688 566 563 569 561 571 559 563 1696 568 561 571 559 563 1697 567 562 570 1689 565 1694 570 1688 566 1693 571 1661 593 1693 571 558 564 566 566 564 568 1691 563 541 591 564 568 562 570 560 562 1697 567 1692 562 1696 568 562 570 1689 565 564 568 561 571 559 563 567 565 564 568 562 570 560 562 567 565 1694 570 1689 565 1694 570 1688 566 1693 571 1688 566 1693 571 1662 592 13987 9031 2220 590 96231 9034 2217 593 96234 9030 2222 588 96247 9037 2215 595 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 14 00 00 00 +# OFF +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4E B1 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 1D 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 15 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: E6 00 00 00 +# +name: Vol_up +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 07 00 00 00 +# +name: Vol_dn +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0B 00 00 00 +# +name: Mute +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0F 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3523 1701 472 426 444 1269 472 426 444 426 442 429 443 427 443 426 444 426 444 426 443 427 442 429 440 430 439 432 438 1304 437 433 437 432 438 432 438 433 437 433 437 433 437 433 437 433 437 433 437 1304 437 433 437 433 437 433 437 1304 437 433 437 433 437 1304 437 433 437 434 436 433 437 434 436 434 436 434 436 433 437 433 437 434 436 1304 437 1305 436 1305 436 1305 436 1305 436 1305 436 434 436 434 436 1305 436 1305 436 1305 436 434 436 1305 436 1305 436 1306 435 1306 435 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 1304 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 436 434 435 435 1307 434 1331 410 1307 434 1307 434 1330 411 1307 434 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 434 436 433 437 433 437 1304 437 434 436 434 436 434 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 435 435 434 436 1305 436 434 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1306 435 1307 434 1307 434 1307 434 1331 410 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 1304 437 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 437 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9093 4441 620 507 618 530 594 531 593 1652 595 1653 620 505 620 505 619 506 617 1630 616 508 616 508 616 1632 615 509 615 1631 616 1632 615 1632 615 510 615 509 615 1632 615 509 615 1632 615 510 615 510 614 509 615 1632 614 1633 614 509 615 1633 614 509 615 1632 615 1632 614 1633 614 510 614 510 615 510 615 510 614 510 614 510 615 510 615 510 614 1632 615 1632 614 1632 615 1632 615 1632 615 1632 615 1632 615 1633 614 14439 9088 2192 614 96349 9112 2190 616 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 243 27700 170 27632 246 27694 282 27595 307 27497 241 27696 177 27710 164 27644 245 27629 246 27712 174 27638 211 27736 131 27741 306 27504 214 27727 135 27749 132 27761 126 27744 131 27753 127 27764 121 27767 132 27773 307 27577 131 27706 213 27761 129 27759 128 27770 125 27694 213 27751 307 27578 131 27737 131 27745 304 27575 335 27540 124 27752 132 27749 132 27747 134 27757 134 27758 127 27762 131 27748 131 27750 122 27749 130 27748 125 27772 131 27774 136 27762 135 27686 215 27742 131 27749 132 27756 133 27764 126 24073 9255 4460 672 488 618 541 619 541 619 1675 619 1676 618 542 618 542 618 542 618 1676 618 542 618 543 617 1678 616 568 592 1702 592 1702 592 1703 617 543 617 543 617 1677 617 543 617 1678 615 544 616 544 616 544 616 1678 616 1679 615 544 616 1679 615 545 615 1679 615 1679 615 1679 615 40240 9173 2273 591 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 219 27658 217 27663 216 27658 216 27634 216 27642 215 27646 217 27662 217 27637 216 27649 216 27649 218 27656 217 27658 215 27640 214 27636 217 27649 216 27644 218 27635 217 27630 215 27645 216 27631 215 27632 216 27650 216 27628 217 27630 214 27627 217 27623 215 27632 215 27641 216 27634 214 27633 215 27648 215 27648 217 27651 215 27635 216 27629 216 27630 216 2021 9254 4461 618 542 618 542 618 542 618 1675 619 1676 618 541 619 541 619 542 618 1677 617 543 617 543 617 1678 616 568 592 1702 592 1702 618 1676 618 542 618 542 618 543 617 1677 617 543 617 544 616 1678 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1678 616 544 616 1678 616 40239 9200 2247 617 99930 110 27739 119 27738 123 27750 126 27738 175 27617 214 27716 203 27604 213 27639 217 27631 214 27722 136 27753 119 27736 175 27618 246 27683 177 27619 245 27685 171 55486 244 27693 158 27635 241 27695 170 27693 129 27717 340 27530 113 27757 106 27751 124 27728 172 27707 126 27666 215 27708 123 27733 123 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 18 E9 00 00 +command: 49 B6 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 14 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 40 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 18 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0C F3 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0D F2 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1F E0 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 81 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8F 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9066 4428 608 507 609 1622 609 507 609 507 609 1623 608 1623 609 507 609 506 610 1623 609 507 609 1622 610 1623 608 507 609 506 610 1622 609 1623 609 506 610 1622 610 506 610 1623 637 478 690 425 638 478 637 1594 637 1594 664 451 636 1594 610 506 610 1621 611 1621 610 1621 610 505 611 40183 9065 2156 637 95953 9037 2185 608 +# +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: A8 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 88 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 9C 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 8C 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9064 4354 666 1559 666 1562 662 1586 638 475 636 477 635 477 635 478 635 1590 635 1591 634 478 635 1591 634 478 634 478 635 478 634 1591 635 478 634 1591 634 478 635 478 634 478 635 1591 634 478 634 1591 635 478 634 478 634 1591 634 1591 635 1591 634 478 635 1591 634 478 634 1591 635 40957 9035 2144 634 95483 9047 2155 632 95484 9048 2153 633 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 50 AF 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4385 638 1587 664 1562 663 1587 637 476 635 478 634 478 635 478 635 1591 634 1591 634 478 635 1591 635 478 634 478 635 478 635 1591 635 478 634 478 634 1591 634 478 635 479 634 1591 635 478 634 1591 635 478 634 1592 634 478 634 1591 635 1591 635 478 634 1592 634 478 634 1591 634 40958 9033 2144 635 +# +name: Power +type: parsed +protocol: NECext +address: FF FF 00 00 +command: E8 17 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: FF FF 00 00 +command: BD 42 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: FF FF 00 00 +command: F2 0D 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 05 00 00 00 +# +name: Vol_up +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 70 01 00 00 +# +name: Vol_dn +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 71 01 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9010 4413 532 1617 532 1617 533 489 533 489 533 489 558 464 558 465 557 1593 557 465 557 466 556 1594 555 467 555 1595 529 1621 554 1595 581 1569 581 441 581 1569 581 441 581 441 581 441 581 441 581 441 581 1569 581 1569 581 441 581 1569 580 1569 580 1570 580 1595 554 1595 555 468 554 42156 8983 2135 556 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9032 4390 556 1592 559 1591 559 463 559 463 558 464 557 465 556 465 557 1593 583 440 581 441 580 1569 581 441 581 1569 580 1569 581 1569 581 1570 580 1596 554 1596 554 468 554 468 554 468 554 442 580 442 580 1596 554 469 553 469 553 1596 554 1596 553 1597 550 1598 553 1598 552 469 551 42155 9008 2107 531 95218 9006 2108 582 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9011 4388 557 1617 532 1617 532 489 533 489 558 464 558 440 582 440 582 1593 556 466 556 466 556 1594 556 467 555 1595 555 1595 529 1620 554 1596 554 467 554 468 555 1595 579 443 581 1569 581 441 581 441 580 442 581 1569 581 1569 581 441 581 1569 580 441 581 1569 581 1569 581 1570 579 42152 8957 2159 556 \ No newline at end of file diff --git a/documentation/UniversalRemotes.md b/documentation/UniversalRemotes.md index 264829e16..325f640d7 100644 --- a/documentation/UniversalRemotes.md +++ b/documentation/UniversalRemotes.md @@ -25,6 +25,13 @@ Make sure that every signal does what it's supposed to. If everything checks out, append these signals **to the end** of the [audio player universal remote file](/assets/resources/infrared/assets/audio.ir). +## Projectors + +Adding your projector to the universal remote is really simple. Up to 4 signals can be recorded: `Power`, `Mute`, `Vol_up`, `Vol_dn`. Any of them can be omitted if not supported by your projector. +To save time, please make sure every recording has been named accordingly. +In case of omitting, on most projectors with the 4 following buttons, you should not have a problem. + + ## Air conditioners Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote. From db1a8f8014ebff5243ac624d0c7c62614e3fb428 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 8 Feb 2023 21:47:39 +0400 Subject: [PATCH 15/34] [FL-3099] SubGhz: add protocol KingGates Stylo4k (#2368) * [FL-3099] SubGhz: add protocol KingGates Stylo4k * SubGhz: add unit test file * f7: api: reverted symbols Co-authored-by: hedger Co-authored-by: Aleksandr Kutuzov --- .../debug/unit_tests/subghz/subghz_test.c | 11 +- assets/resources/subghz/assets/keeloq_mfcodes | 105 +++--- .../subghz/kinggates_stylo4k_raw.sub | 11 + assets/unit_tests/subghz/test_random_raw.sub | 6 + lib/subghz/protocols/kinggates_stylo_4k.c | 336 ++++++++++++++++++ lib/subghz/protocols/kinggates_stylo_4k.h | 74 ++++ lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + 8 files changed, 492 insertions(+), 53 deletions(-) create mode 100644 assets/unit_tests/subghz/kinggates_stylo4k_raw.sub create mode 100644 lib/subghz/protocols/kinggates_stylo_4k.c create mode 100644 lib/subghz/protocols/kinggates_stylo_4k.h diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 97629efea..c7e9c96f1 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -14,7 +14,7 @@ #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 317 +#define TEST_RANDOM_COUNT_PARSE 329 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -637,6 +637,14 @@ MU_TEST(subghz_decoder_nice_one_test) { "Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n"); } +MU_TEST(subghz_decoder_kinggates_stylo4k_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/kinggates_stylo4k_raw.sub"), + SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME), + "Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -837,6 +845,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_dooya_test); MU_RUN_TEST(subghz_decoder_alutech_at_4n_test); MU_RUN_TEST(subghz_decoder_nice_one_test); + MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); diff --git a/assets/resources/subghz/assets/keeloq_mfcodes b/assets/resources/subghz/assets/keeloq_mfcodes index 1b27bfb01..3eedc564f 100644 --- a/assets/resources/subghz/assets/keeloq_mfcodes +++ b/assets/resources/subghz/assets/keeloq_mfcodes @@ -1,55 +1,56 @@ Filetype: Flipper SubGhz Keystore File Version: 0 Encryption: 1 -IV: AA FF DE 54 A1 BB F1 21 83 46 FE 2A 1E B7 3D 33 -95B8CD65BBAC95EACE67CA94F679B82877A921396D461ECB479722F8A369454A -61065C41297B9FF8F8168814F49A03D1FE7B4CB79DFFCBBF0402AAA6A2211E84 -A1557AC139188FF105D1081A4B688C5CA440FB5DA7F40901B541120AD08A544F -AF0A6056D7F0D97DAD6C16C4E63204E4B3B1C5A20AC82B983B516F4F718EE29F -6861BFAE46A1AADB1DB2D6DFAA7E39D21D5B3E46A41BD50F4F2828879EB328EF0A406F2B9C79A031AB361257E6D69756 -0DDB3DAC53678541981CC46C22CED245CBA314C9BBE1BA9383B8505B75AC5E40 -99AB5D9404934F2D257ED04D9F8CCEE06D00F38157B121AFD63101E4E5C08268 -5114A6C42B342C7D933A76F9052FF963C2047E85EA524497C21B4C35C38EF6E7 -88CA2A1907D94B972FF93DBB9B88CB576F3E1BB0FE8F85A5B2CCA7D44B00374D -349C4153FE7CA8AE044E9F75F77D9694304474CE3F127CF968662B5F78A7F421 -62AA02E20CA7E691EFC0B55CA41C9BDF889FB23868289284241CD31AA1A0E499AE2A770B6B5AB3170CDCCDB8A246D36C -97901B5EB76228ADF8E5073F1BAB1502878DEFF1C4EBF12A43D105556CB7E80F947A8BD7831666BD838C57CDF64A6F3F -B05959D210B500943A93BDFAF783D9DB215FC84503B152EAFBCFB5B6237E3888 -B393DE4489BCAFD5DB80592A12E329E18913E185D2042580048029A8C4C3A257 -B4B30492A5F0C3C763E2F43C02D1451A5B9CFB468CFE62BE85B1F56FF49DAB9A -CE5D57C0EE3D717FC717EB725970A9F25D211546EE7AC5C237950CEA323D85D4 -4E9028944813FD40A17AF6DF5A97E76179B48EE79265BBD38B07E3A270587A813DADB51B3367479AC5644F754B5613F8 -3B3C3000B9D1361711ECE3DB77C90A059576F738CB167679DA36DD3D128B27A1 -997023148148DE7B9CBA47D3FD48DEF73AA1715FF4BC1E7A1DBA6D52A0DCB2C0 -C8428D18E69FB92486434FCE470F1FF37D40507F27D824679C132A70D516530367277F02DDB5C464D03450FF6B425A24 -3701200DF5DA7235971FD95844056E74C7D61A8EB12A8772E04F52037C63D50B6229A7F905F3E6F84C565FCC7632870C -BB392A464CDC0D5D923AA9EF8ECC3C6F020D0AD82165462DF0DE7C5025AAAAAC -999C82209B30638506E5D708471676D2CBB4A432E5AF86ABD61179111EDAE636 -FDE2A452A6B47261338117EC20FC57731DA492562ECD21BBC61F098A5442CF20 -D923BABB5C4DFB48E3F763898B2796C7830D3EE9A91DF904AC2223A0F4736507 -0987DDAC695DD5E4607048DF1D4EF96599E17ED52F41785E676AA048AB7213FE -26CB3E6CFA10338A8DDD99BFF6957C53DEF435CB0FF977B71B5164ADFE11292A -097908FD07A0A093CA80E6FF59524707C1A11169D0CB6F8E4967D8DAA725FE7A -8C629E70A5CC6FCB039DFA1A6AC58CB7B7E92C85BDA66266AB49E6B1285FC7A6 -39A2052350CD446EDC1B9AD0C2DD51C78B2E5F3A76AAD0EC200F74B40ACD4AC5 -A1685CF8C4A5401F2CA0C8172CB5B4B5726C61CE68A72AE834B0A472CEB2F3DE -1F5ED5793DB381D1B501BA8A4DF3E74FB11FC1A922DDC8AE62E5BA8934C37EA8 -D80EF661BF36E2F6C179E253CE5BC3732684ACBC7C65E526A628442A2EBF8FAA -7785BF721F21E19A8CFBFBBB56BD76B96A4E8EF9F8A2344009B14AB385909598F834A5533B648DA7D62BD6D4314A43A5 -C8F6F943DE615B5827569B283577344C0455B3279C73634FC4E0E9A8088DF633 -FB4F4C786FC51BBDA679A212B4A05EF120AC62F7EBFFE8263BD50A4D9BC9C6E0 -16EEC35CF69BA86DB3BE999CDF9B39F5736F3727B2AA2C5AB9141A48F176D831 -AD1AD6DE813E7710DA3AF546D4F9EA085831E6B3FA17B64F1B8765F48134EA54 -345D743BC35B4A8614632ADD11E809C0D1E6C78F9469256B9A738DA0B648B2B8 -7C876CECAC839EBB4609C3996966C3EC454F51C8ABCC51097E405370C4B6F086 -0F857C031FD3047607647148C534F969567F207FF1691D8D06DCDF4C2514695D -EC0630EDC82241C1952F49B6B1B0C1A954A7DDD6BDB1326ACC54AD449D1BF985 -286EF9F7FD0D09F2604CCE867C52144CD0C4773A3D8183066C61B8BF9860AE7C -EA55424097A08722A66966E3177E09DE91AC65175E5C68CB47B6153E6585DF85 -D54FCDF9EA4BD1FE4F316DB6D5CE4A2675F2D0144772865EDC781FBA7DFD23E4 -7A2F5C5CA9F97FE9527BAA760E64B930C407A27DE036476737E6BDD9422F4056A5F1F414F12F0982109FD7C30E8CC1CB -06BAD9B4EEEEB1BCF8C97672D271534FE84D772282EE9642698788D3842D7641 -101C1B2DBD963E23777294C22E553D145D5B40838F91355CA86D571A0CEFF68F -1B148C2B502B3E0A5BD40858E019C513DD4CCAF2A114CBB29C59BFB018079285 -8DF4D07EC20FF873EA989ACEF4AF96E9787FE6E0F71965858B4186C3AF302A31 -2317DC8C098CD60F3467B3644A19CCE887339708820CD37F6F5277D6648F837512F70CE90E23D7339CDDE002BD8D83DB +IV: 41 84 34 43 84 1D 43 04 45 44 34 38 41 24 3E 74 +8C5AEF725F0620DB3952B40BB8E76A815BCEE1D1B92F7E8E8E63D1894F1C7FD0 +1DFF1D6A322D6B3D8AD7C594A02462AADE723D417B9233585526982F08187DAA +0A9184F15D4A5589DDDA6422063BACD58580661CFE60EE600D87F73F0CB5013E +6E56802DAA049C3DFDEDC90432A0E694A172C369EBECD136F4C911B979AA098D +A659716B51053604059F7FC3651D6A153F5EAB1852F95B20C44C41A7889A0DE91A078B63E3C311280C4315F0A3C8BA1F +A315170EDC51627157725D9A96490DB75EBF8232957FBA313C03B2BA2884EA85 +DEAB3C2C2E2DC76FE45AEBAC7EBFB478CECCD970A63B8DE2024FBFDCCBD1B26E +7BBFC36CBA77468B4624C6B685610877D53985C985DAD8EFE47527EB7C7260CD +879EE18B314ED4F3F548B41176099176FB97F4F1A062481C935B2DDFBCE2FE4D +493372D7D47A96A66305DFDC8A915EB651620881AE1D603B7E9605E004C04CA9 +F80AAA4C447F8E8C0B039DDAECF9126119C32FF164118780BE268E326A8CBF8010DE2EBF94033CEAC39815D6A8958CF4 +41C1393A039E665F6A53A5E5D1C105008BD14D9755751545A667860C39B2E39AA47306E76E2BA7DDDAA2A286FDB58D23 +34853A4CDE42CB80045E641AB4800C86C1CF6907EAAFA399156CCC727A008584 +D0783A34BD6A36D31BFF5F70FA1116CAE48EF02716D80481AE406DABB3C3400E +0BB3582605434CF2A5D74A27773B88DA331B6033C444837E9F7A155897258B03 +E4E71F3EB290B9436FFF0FDADA468BE37D964E89BE8D9971A14776F821822769 +744AA59D129C892120B5DAB81C8A3D573B0AD80EF0708C1B9ECF13DA60CECA07DC0591A08611DB4D3A8B7C70994D5DEF +716F9F8D5D2C697BC4183EFCC97E52D08ECA07B613A0F389C801F65803DFF4A4 +560262DA8489D2C18C8D97E314DC663403AFE4DE9DCB6D453087D2BFBD36532D +9E31F7152C50B6940EE3E3894C98F75702C7897F702B48E5C9B54B6E25083641AD2E521267505066C7E5BAB7F6CF1433 +6630EDA18A6E58BD395792CCC656DD10CD9C5DD2B1949FE677122FA39A53C724E79C0D0752A3A39A03407BBA2282185E +00D15A06F5DD82A4B926B78809CC4D129AAFA9A92B0A81568F255D15697FE0FD +29FF9A4F5346ABEE8FEDE034988F87FCD29EA747735898F1E7207EF74FAB71A8 +C0E8EB6AE6F77EE38DF2AB1B7742E34ED5236F3D8E964845E66762A4675AA21F +00FC4C459DC4CE92B62D0AC2546F9FBBE0893F84D2AF0A20ED462A5EAE63DE3B +E92EF482A40CEEFC8339BBB713BBC452A266A09B2645EDEB12716544B2DB9B09 +D7D9C5C757831BCE2FF1DB25A080D77769FB36A1F3F48F4361418A0A45609280 +C19246F52AE1EE5CE968CED52F642D9CD78B020029632FE83C49C657D23ED075 +FEE3C05432FB3860D5D28562323F5D1B053B8F3ADCD416BD0C4645F6F4D43DCF +D780A4AADD0205E0BACDCC9AF46ED259E0946C5DA888C341BFE96E09A87CCCFA +CE3C13CFA08E532B637FDB707E29548D57EE92EAEF6516C3D67E9D36FCD59CF9 +5E88CE71258CB0D91631FEB41C9A2F47AE0FF4810A9A1EDF3F308BBDE6944D5E +1531F4107FC64810BA5DB5E46C7B9AD61531AF5430E137B7688109FBC06B6221 +68050A39C0B302E0B713FAAC5F829C79AB30E18B1D982A94005DBAC7CCFB95379A619C0B9F7409C44D19FF2C5E8E4546 +3F73E8BA22C602280496EF8E88E2CAA9EC442E3B3083B684942DBF9CB5121241 +FA1FCD7C9182FAE8FFF4E88433AE68F66076B3BDFF8AD0BF5CEA43870082E9BE +DFF7DD2678C03401656B093BF7AC7E033F15FD0F30188E48A62045740B423699 +371BCFF653E7811D99C048A1A39921AAA563E06AC86CB3D2F392C2C955A1ABD0 +F4F1766DEAEDE934478208B9EB3050326D9FFCC001C73EEE93407D8B12CD49E4 +A241C9FC62DDF67D645936245FAFFE2A42C86151F484B7BCE5410E8F36FC87901D3AC4E40334E08FFFC2AD676E490D94 +3566A94A9C0479E0C4387D9137375ADF2C921504364F3903F198D6757CDFD21B +7274E1B5A6445FDC29C355D550E981C17F349BC4A14251B3B51BC96FC334FBCA +04EEA5EDD9B3BC3E0638E53A5561DC8BF761D615A64D435BD31A94AF2650159E +B84818CC1695FE8B731CD653D0679D1AAA0578C0B06AD1E3510785B2DE20841C +4121343D6B79E38C06DD038D770D76D10336AFF47ED0D0DCDDD6B0FEA4DAE67C +75E49C839CCD7019D9CE90AC364F488468B2AB01E387A8BEF8815915925166A6 +CFAA9F4717568C1EC7B96E0D71D260B828A70484E1D9CA7C99A50D10704F8BBBAE62EE98C9FBDFF06F357F1C1E2F2677 +41E4D250B92BC57442B91DE2015C41226531CF9A8D77B83AFC8E4F3183DB11DE +45EA8BD854D7F044FB249C16F08A0C24FF117D54BC20A4CC667B3DAD09EAC4F9 +F455CA0BB8B496C301406DE4FB52C9B0F64645776803BC2935A2F38675318BE2 +22FF72A5D2E1A2EBFB6C55FFD0A3CEA0474CCBD13462D63229C9708276E87D3F +8470F9A300170F226C0216C07AA829591CBD4CE34AA918EAE49363BDE86CC77EEEBEEA84A097488D35B92F773F5DBB4C diff --git a/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub b/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub new file mode 100644 index 000000000..49b190002 --- /dev/null +++ b/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub @@ -0,0 +1,11 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 377 -386 1117 -410 1121 -352 1141 -384 1151 -378 1119 -350 1139 -386 1115 -1134 389 -1114 395 -1122 363 -1136 389 -358 1167 -356 1145 -1120 389 -1110 391 -356 1139 -1126 389 -1114 391 -1122 363 -1146 389 -1110 395 -1122 363 -1138 389 -1110 393 -1122 363 -1140 389 -1112 393 -1120 389 -1118 389 -1112 397 -1124 363 -1142 389 -1112 359 -1154 367 -1134 389 -1144 365 -1138 355 -394 1119 -380 1107 -1152 353 -398 1113 -384 1139 -1118 385 -376 1141 -386 1129 -350 1143 -388 1109 -1132 389 -1112 393 -390 1107 -1128 389 -1112 397 -388 1111 -1132 389 -358 1127 -1118 417 -1116 383 -1120 353 -1158 389 -1108 375 -384 1121 -408 1123 -350 1139 -386 1111 -1130 389 -1114 395 -1122 395 -1114 389 -1116 395 -1122 363 -1138 387 -9444 373 -374 379 -374 381 -346 403 -346 389 -376 389 -390 353 -376 359 -382 383 -360 419 -360 359 -386 359 -2264 777 -356 1127 -390 1143 -362 1131 -1138 365 -1122 359 -386 1153 -1106 377 -1152 385 -372 1113 -1140 385 -1118 381 -1114 383 -1150 383 -1120 355 -1122 389 -358 1165 -386 1113 -1128 389 -360 1125 -384 1131 -368 1157 -350 1139 -386 1115 -406 1099 -384 1141 -1122 383 -1110 373 -1130 385 -1128 393 -380 1131 -380 1129 -1112 383 -1132 391 -356 1143 -1124 383 -1130 367 -1136 385 -1136 387 -1112 371 -1120 389 -1118 383 -1130 371 -1130 383 -1110 383 -1120 413 -1118 383 -1144 347 -1144 389 -1110 393 -1122 363 -1140 389 -1112 359 -1154 363 -1146 389 -1110 393 -374 1115 -384 1115 -1144 385 -368 1141 -388 1111 -1110 421 -360 1125 -388 1109 -392 1137 -358 1125 -1144 365 -1138 389 -358 1123 -1118 401 -1138 389 -360 1121 -1120 417 -358 1109 -1154 355 -1120 375 -1138 385 -1130 391 -1136 355 -398 1115 -380 1141 -384 1121 -382 1119 -1104 413 -1118 355 -1156 387 -1112 377 -1122 389 -1118 387 -1112 397 -9422 417 -352 363 -416 355 -388 345 -382 377 -380 375 -380 375 -380 375 -380 385 -356 379 -366 385 -374 387 -2246 745 -380 1141 -386 1113 -370 1125 -1140 373 -1152 355 -394 1117 -1140 381 -1120 385 -374 1145 -1112 385 -1122 381 -1116 383 -1120 375 -1120 389 -1120 373 -380 1171 -358 1121 -1142 377 -356 1127 -384 1137 -378 1155 -390 1105 -366 1125 -386 1135 -386 1111 -1132 389 -1112 393 -1120 365 -1138 387 -360 1163 -356 1143 -1126 387 -1114 357 -386 1141 -1126 383 -1130 365 -1132 381 -1140 377 -1116 383 -1130 371 -1128 381 -1140 347 -1148 385 -1128 369 -1128 381 -1142 377 -1114 389 -1112 395 -1124 361 -1142 389 -1114 393 -1122 365 -1138 389 -1114 397 -1108 389 -392 1119 -350 1139 -1152 355 -396 1115 -382 1109 -1156 385 -374 1111 -384 1139 -368 1147 -388 1109 -1112 389 -1120 383 -388 1107 -1150 389 -1112 +RAW_Data: 393 -390 1109 -1128 389 -360 1125 -1120 381 -1152 383 -1118 353 -1158 387 -1112 375 -386 1117 -408 1121 -350 1143 -388 1109 -1132 389 -1114 391 -1122 395 -1120 389 -1112 393 -1122 365 -1136 389 -9442 373 -376 389 -354 377 -366 387 -384 357 -378 361 -418 347 -394 385 -358 363 -382 361 -414 357 -392 333 -2290 751 -384 1113 -406 1121 -350 1137 -1136 353 -1160 385 -356 1135 -1120 361 -1146 385 -388 1137 -1108 361 -1150 387 -1112 395 -1136 349 -1154 353 -1142 371 -384 1145 -378 1117 -1138 381 -382 1087 -410 1121 -382 1143 -380 1121 -380 1115 -384 1107 -418 1115 -1106 385 -1148 365 -1118 359 -1146 387 -388 1135 -388 1113 -1126 383 -1130 367 -376 1113 -1142 383 -1114 375 -1154 355 -1160 385 -1110 371 -1152 357 -1118 385 -1146 365 -1122 361 -1146 387 -1114 395 -1134 355 -1160 351 -1146 369 -1154 355 -1120 387 -1114 397 -1136 357 -1118 407 -1144 351 -1134 359 -420 1111 -366 1131 -1142 379 -384 1089 -410 1119 -1142 379 -366 1141 -386 1109 -388 1131 -350 1141 -1118 391 -1114 375 -378 1153 -1116 385 -1136 383 -358 1139 -1120 359 -420 1099 -1142 383 -1118 383 -1138 347 -1144 385 -1144 369 -386 1113 -404 1089 -386 1141 -382 1099 -1136 381 -1128 375 -1130 383 -1140 359 -1146 387 -1114 395 -1138 357 -9430 383 -378 359 -418 347 -392 387 -360 363 -384 361 -414 357 -386 347 -384 375 -382 385 -358 383 -364 387 -2252 773 -354 1131 -384 1137 -386 1111 -1132 387 -1112 397 -388 1113 -1124 389 -1116 387 -388 1115 -1132 389 -1114 393 -1120 365 -1140 389 -1114 357 -1154 365 -378 1151 -358 1127 -1156 367 -376 1135 -358 1125 -388 1141 -368 1125 -386 1133 -388 1109 -370 1155 -1106 375 -1122 389 -1118 389 -1114 395 -386 1117 -410 1123 -1106 377 -1130 383 -388 1107 -1152 353 -1148 353 -1150 367 -1142 389 -1110 397 -1120 365 -1138 389 -1110 391 -1122 363 -1142 387 -1116 389 -1120 391 -1116 389 -1116 395 -1122 365 -1140 389 -1114 357 -1154 363 -1138 389 -1142 365 -1138 355 -396 1115 -382 1141 -1118 353 -400 1111 -384 1139 -1120 381 -386 1139 -366 1119 -392 1121 -388 1107 -1152 389 -1114 355 -388 1139 -1126 387 -1114 397 -376 1111 -1144 375 -380 1129 -1138 375 -1098 385 -1140 377 -1118 387 -1144 371 -386 1115 -404 1121 -348 1137 -386 1113 -1134 389 -1112 395 -1124 395 -1118 389 -1110 395 -1122 363 -1138 389 -9418 391 -360 407 -384 361 -388 355 -390 367 -376 373 -380 387 -356 377 -366 385 -388 355 -378 359 -384 377 -2266 777 -346 1149 -388 1107 -390 1129 -1104 415 -1118 353 -398 1113 -1138 383 -1122 381 -388 1141 -1118 389 -1112 357 -1154 365 -1138 389 -1114 357 -1154 363 -378 1155 -358 1123 -1156 381 -360 1107 -384 +RAW_Data: 1153 -378 1119 -382 1143 -382 1121 -382 1117 -382 1113 -1120 389 -1120 387 -1112 399 -1120 393 -392 1119 -350 1141 -1154 357 -1116 389 -360 1163 -1120 365 -1138 387 -1114 389 -1122 389 -1116 387 -1114 397 -1104 379 -1156 353 -1148 367 -1118 377 -1122 423 -1110 373 -1122 389 -1118 383 -1130 373 -1128 383 -1140 345 -1146 383 -1130 399 -1130 353 -1142 377 -358 1127 -384 1143 -1118 385 -372 1111 -386 1137 -1120 381 -388 1141 -364 1127 -384 1133 -374 1111 -1148 383 -1114 373 -384 1115 -1136 387 -1144 371 -386 1115 -1132 387 -360 1123 -1150 345 -1148 383 -1128 371 -1132 381 -1140 379 -390 1123 -350 1139 -388 1113 -406 1089 -1142 373 -1120 389 -1118 423 -1110 371 -1120 379 -1122 407 -1104 417 -9440 389 -356 379 -366 385 -388 355 -378 359 -384 381 -394 387 -358 361 -386 359 -416 355 -388 345 -384 377 -2262 747 -384 1149 -380 1115 -382 1113 -1120 389 -1120 389 -360 1129 -1152 367 -1136 389 -358 1131 -1152 367 -1138 389 -1116 355 -1152 367 -1134 389 -1116 353 -388 1141 -368 1123 -1138 375 -386 1113 -408 1121 -350 1175 -372 1105 -386 1145 -352 1141 -366 1145 -1114 385 -1116 377 -1122 389 -1120 421 -354 1139 -388 1109 -1132 383 -1130 369 -374 1113 -1144 385 -1114 377 -1120 391 -1128 373 -1138 385 -1130 359 -1138 377 -1120 373 -1138 383 -1130 359 -1138 379 -1160 375 -1106 385 -1130 393 -1120 377 -1118 389 -1112 393 -1140 355 -1120 421 -1114 371 -1122 391 -390 1123 -350 1139 -1134 353 -402 1113 -384 1141 -1118 385 -376 1143 -352 1161 -352 1135 -386 1113 -1132 387 -1114 395 -388 1111 -1128 387 -1114 399 -374 1115 -1142 375 -380 1117 -1118 387 -1144 363 -1136 385 -1130 367 -1130 383 -388 1107 -392 1129 -380 1115 -384 1113 -1136 389 -1114 393 -1124 393 -1120 389 -1114 393 -1124 363 -1140 389 -9416 391 -360 405 -386 329 -416 357 -392 365 -374 377 -380 343 -412 341 -412 353 -390 375 -366 385 -386 355 -2264 743 -394 1123 -388 1111 -392 1133 -1110 395 -1120 363 -382 1133 -1142 381 -1118 383 -376 1111 -1146 383 -1122 383 -1146 347 -1150 381 -1116 353 -1158 343 -410 1133 -382 1111 -1152 355 -394 1119 -382 1109 -382 1153 -378 1131 -354 1137 -396 1119 -388 1111 -1150 351 -1152 351 -1150 365 -1136 387 -356 1131 -386 1143 -1122 387 -1112 357 -420 1107 -1128 387 -1114 359 -1152 363 -1148 387 -1114 395 -1122 361 -1140 387 -1110 395 -1120 361 -1140 387 -1114 393 -1154 355 -1120 387 -1146 365 -1118 361 -1146 387 -1112 395 -1120 363 -1140 385 -1144 367 -1120 359 -420 1099 -384 1139 -1118 383 -384 1109 -392 1129 -1138 379 -366 1147 -388 1109 -386 1099 -384 1139 -1132 349 -1158 375 -380 1131 -1104 411 -1122 351 -416 1111 -1148 +RAW_Data: 353 -396 1121 -1142 347 -1150 381 -1116 355 -1156 375 -1144 387 -360 1119 -388 1107 -394 1131 -386 1101 -1152 363 -1138 387 -1112 391 -1152 357 -1116 375 -1136 383 -1122 383 -9448 357 -392 357 -398 363 -378 385 -358 383 -364 389 -386 357 -380 389 -386 347 -382 375 -384 375 -380 373 -2262 747 -376 1145 -390 1107 -386 1129 -1104 413 -1120 353 -396 1115 -1140 381 -1122 383 -376 1143 -1110 385 -1118 383 -1114 417 -1114 383 -1120 353 -1156 389 -356 1135 -386 1113 -1134 389 -358 1129 -390 1107 -392 1153 -358 1127 -388 1143 -362 1131 -356 1131 -1154 365 -1136 389 -1114 357 -1150 363 -386 1153 -358 1125 -1118 417 -1120 381 -350 1123 -1134 391 -1112 395 -1124 395 -1116 389 -1112 393 -1124 363 -1140 389 -1114 359 -1154 363 -1138 389 -1114 391 -1124 361 -1144 389 -1112 393 -1122 363 -1138 389 -1112 391 -1122 363 -1138 389 -1144 365 -1124 361 -382 1155 -350 1137 -1120 391 -386 1131 -350 1151 -1120 383 -378 1141 -352 1137 -394 1117 -390 1107 -1150 389 -1114 355 -388 1143 -1120 387 -1112 397 -388 1113 -1130 385 -344 1163 -1104 379 -1122 373 -1140 383 -1130 389 -1124 359 -386 1127 -386 1139 -368 1141 -390 1107 -1112 387 -1116 385 -1150 367 -1140 389 -1112 393 -1124 363 -1136 389 -9444 379 -340 417 -360 359 -386 359 -416 355 -386 347 -384 375 -382 375 -380 375 -378 375 -380 385 -356 379 -2278 745 -354 1151 -368 1141 -390 1105 -1114 387 -1116 385 -386 1141 -1120 389 -1114 389 -388 1113 -1130 389 -1112 393 -1124 363 -1138 389 -1112 389 -1122 363 -380 1159 -350 1137 -1122 391 -388 1097 -384 1139 -382 1125 -386 1145 -352 1141 -366 1145 -390 1107 -1110 387 -1150 353 -1150 367 -1138 387 -360 1125 -390 1109 -1152 389 -1112 357 -388 1141 -1122 389 -1110 391 -1122 395 -1112 389 -1110 397 -1120 363 -1144 389 -1114 391 -1122 365 -1138 389 -1116 389 -1142 355 -1120 389 -1112 397 -1122 363 -1140 389 -1110 393 -1130 349 -1140 405 -1134 389 -1112 357 -388 1141 -364 1129 -1142 367 -388 1111 -370 1131 -1140 383 -364 1149 -388 1109 -388 1137 -356 1127 -1118 383 -1120 413 -350 1121 -1132 407 -1140 355 -364 1149 -1112 371 -406 1129 -1104 409 -1098 383 -1116 417 -1118 381 -1118 385 -388 1111 -390 1129 -350 1137 -386 1113 -1138 389 -1114 395 -1122 393 -1120 389 -1112 393 -1124 363 -1138 389 -9444 379 -340 417 -360 359 -386 361 -414 357 -386 347 -384 375 -382 375 -380 375 -380 375 -378 373 -380 373 -2262 749 -386 1111 -408 1117 -348 1143 -1120 391 -1116 389 -358 1127 -1154 365 -1136 387 -360 1129 -1154 365 -1136 389 -1114 357 -1154 365 -1134 389 -1112 357 -390 1137 -406 1119 -1106 377 -386 1117 -406 1123 -350 1143 -384 +RAW_Data: 1149 -378 1121 -350 1145 -380 1133 -1104 375 -1136 385 -1130 359 -1138 379 -400 1129 -354 1139 -1148 355 -1150 365 -378 1119 -1146 355 -1152 365 -1134 389 -1110 397 -1122 363 -1140 389 -1110 395 -1122 363 -1142 389 -1116 357 -1152 365 -1146 389 -1112 393 -1130 349 -1138 383 -1116 413 -1120 353 -1122 387 -1114 397 -1154 355 -1124 387 -360 1133 -384 1131 -1134 383 -376 1133 -352 1133 -1132 383 -376 1139 -378 1135 -380 1115 -382 1141 -1118 353 -1160 387 -356 1133 -1118 379 -1158 353 -392 1133 -1104 379 -398 1117 -1138 383 -1118 353 -1164 353 -1146 403 -1120 353 -398 1115 -382 1143 -384 1089 -412 1121 -1106 377 -1154 355 -1118 407 -1146 351 -1130 395 -1138 355 -1118 407 -9434 353 -396 363 -380 383 -360 383 -364 389 -386 357 -414 355 -386 345 -386 375 -382 375 -380 375 -378 375 -2256 769 -384 1119 -382 1117 -380 1113 -1122 389 -1118 389 -360 1131 -1140 377 -1118 421 -354 1139 -1140 355 -1118 405 -1104 387 -1128 391 -1122 363 -1138 387 -360 1157 -354 1143 -1128 387 -360 1121 -388 1141 -362 1129 -384 1139 -388 1111 -370 1127 -384 1135 -1122 363 -1140 389 -1116 393 -1122 395 -356 1129 -384 1141 -1120 383 -1134 387 -356 1133 -1130 349 -1140 383 -1116 413 -1118 381 -1110 377 -1146 389 -1114 391 -1124 365 -1138 391 -1112 357 -1150 365 -1144 387 -1112 395 -1122 361 -1140 387 -1112 393 -1104 379 -1158 353 -1144 403 -1118 353 -1158 353 -390 1133 -390 1107 -1130 389 -358 1125 -388 1111 -1154 389 -358 1129 -386 1131 -368 1129 -382 1139 -1118 353 -1164 387 -356 1135 -1120 393 -1118 389 -358 1131 -1154 365 -376 1135 -1108 395 -1136 347 -1126 387 -1144 403 -1120 353 -398 1115 -384 1141 -372 1103 -386 1145 -1108 387 -1120 383 -1116 403 -1140 389 -1116 353 -1146 361 -1144 389 -9420 393 -362 401 -338 377 -388 385 -374 361 -382 375 -382 375 -380 373 -380 373 -380 373 -380 389 -354 379 -2272 743 -388 1137 -360 1121 -386 1111 -1152 351 -1148 359 -384 1143 -1126 387 -1114 391 -384 1117 -1130 383 -1132 369 -1134 351 -1138 377 -1142 385 -1112 359 -420 1107 -406 1121 -1104 377 -384 1119 -406 1119 -352 1171 -382 1123 -378 1119 -384 1107 -384 1119 -1136 385 -1116 393 -1120 361 -1142 387 -388 1137 -386 1113 -1128 385 -1116 357 -420 1113 -1124 387 -1114 359 -1148 395 -1116 385 -1146 363 -1116 361 -1144 387 -1144 363 -1120 361 -1144 385 -1112 393 -1152 355 -1154 353 -1144 367 -1136 355 -1158 351 -1146 369 -1120 361 -1144 385 -1148 369 -1152 357 -392 1117 -380 1107 -1152 355 -398 1119 -382 1109 -1152 385 -374 1113 -386 1139 -366 1145 -388 1111 -1110 385 -1148 353 -386 1139 -1124 387 -1142 365 -386 1113 -1132 385 -360 1125 -1144 +RAW_Data: 363 -1140 387 -1114 357 -1152 363 -1146 387 -358 1129 -386 1139 -366 1125 -384 1139 -1120 363 -1140 387 -1112 393 -1130 381 -1136 383 -1114 371 -1132 383 -116626 65 -934 133 -1954 131 -102 133 -136 97 -332 65 -430 299 -296 129 -100 265 -168 367 -100 65 -66 231 -336 9643 -7766 529 -68 467 -166 65 -134 99 -500 331 -132 65 -130 329 -98 497 -100 1195 -100 1959 -66 4163 -7346 97 -392 165 -194 97 -2978 433 -298 531 -298 65 -200 131 -132 261 -98 229 -68 12837 -340 99 -268 165 -134 65 -898 67 -100 265 -66 165 -100 597 -166 199 -298 199 -200 99 -132 233 -132 299 -132 233 -166 65 -66 4021 -168 133 -68 231 -168 4647 -130 1399 -7750 133 -1714 197 -2480 131 -200 65 -100 265 -890 63 -1152 197 -98 293 -134 65 -300 361 -100 1035 -100 231 -132 299 -100 3399 -66 6287 -4506 99 -100 65 -130 99 -196 461 -98 331 -164 97 -162 227 -64 197 -98 229 -130 195 -100 425 -526 165 -130 95 -522 457 -560 233 -98 261 -66 1155 -100 259 -130 1407 -98 553 -66 7793 -494 65 -232 65 -3652 229 -2716 361 -266 333 -200 133 -166 99 -132 267 -66 133 -132 199 -166 331 -132 331 -166 197 -950 229 -198 303 -298 365 -100 4839 -3816 165 -130 229 -696 131 -130 261 -262 97 -166 263 -894 165 -230 365 -566 129 -560 197 -324 99 -98 261 -134 131 -100 67 -334 67 -232 199 -132 165 -302 67 -100 1467 -98 459 -100 1081 -130 131 -66 8927 -232 165 -3104 99 -2812 65 -982 131 -98 195 -98 263 -264 231 -66 195 -132 193 -164 65 -100 365 -132 1629 -66 1009 -132 8383 -632 131 -3060 131 -492 425 -100 763 -166 371 -132 1197 -134 229 -694 461 -366 365 -98 329 -198 267 -168 399 -68 131 -332 493 -132 231 -132 569 -66 7765 -7568 99 -532 65 -634 133 -3540 65 -100 263 -592 261 -1484 299 -302 265 -234 1129 -304 99 -436 163 -360 97 -556 231 -166 265 -1164 165 -134 235 -100 163 -332 297 -100 197 -132 99 -566 133 -234 133 -328 295 -98 985 -98 163 -396 399 -134 1557 -134 297 -266 6875 -68 1759 -7194 133 -166 99 -266 65 -432 67 -432 393 -5086 99 -66 199 -68 263 -866 429 -100 359 -130 261 -132 267 -134 533 -134 9251 -4184 65 -1156 165 -198 65 -426 297 -492 67 -164 131 -198 259 -164 199 -100 733 -134 865 -100 397 -132 65 -100 197 -66 327 -164 227 -98 231 -132 97 -262 99 -130 229 -66 589 -96 1119 -98 1905 -7486 599 -66 561 -66 359 -98 757 -162 261 -66 323 -130 5573 -8538 99 -894 131 -594 229 -364 63 -1378 197 -1682 331 -100 199 -166 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 12b08d48d..949a44458 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -190,3 +190,9 @@ RAW_Data: 451 -1040 441 -1052 449 -1050 945 -554 449 -1052 451 -1020 481 -1010 4 RAW_Data: 979 -514 443 -1046 479 -1028 451 -1042 451 -1048 447 -1022 485 -1014 983 -520 973 -516 483 -1012 983 -518 973 -516 977 -520 1003 -520 975 -520 981 -514 475 -1034 969 -516 479 -1016 447 -1046 475 -1018 975 -516 975 -522 983 -510 469 -1010 1007 -518 951 -530 989 -516 973 -556 951 -494 481 -978 487 -978 975 -460 1005 -466 979 -486 969 -508 981 -450 1489 -23666 571 -4036 269 -1224 257 -1250 787 -642 867 -622 883 -622 359 -1136 373 -1086 421 -1080 417 -1074 935 -550 947 -552 445 -1048 939 -552 451 -1046 947 -552 947 -550 451 -1040 443 -1048 453 -1024 977 -522 471 -1034 449 -1020 973 -540 975 -508 479 -1032 453 -1042 449 -1050 977 -518 979 -518 449 -1018 481 -1018 975 -518 473 -1034 963 -542 961 -544 447 -1044 473 -1020 479 -1014 481 -1010 473 -1032 471 -1010 959 -546 973 -492 499 -1006 997 -510 977 -524 953 -552 971 -512 973 -508 979 -554 451 -1016 977 -518 471 -1038 485 -1010 457 -1036 969 -506 999 -520 481 -1014 975 -522 967 -520 975 -548 451 -1038 475 -1022 965 -518 463 -978 985 -486 465 -978 457 -1016 463 -978 985 -486 963 -480 1477 -129906 495 -726 197 -328 295 -132 2547 -66 233 -98 11033 -1856 233 -1458 65 -198 165 -134 199 -168 101 -694 463 -530 165 -300 99 -232 2479 -98 1745 -98 3029 -132 163 -1460 65 -500 65 -400 99 -664 895 -398 65 -564 331 -166 97 -66 197 -98 3813 -98 10097 -3848 165 -232 67 -266 397 -596 165 -66 199 -166 99 -66 199 -398 165 -166 1721 -232 429 -166 133 -330 133 -698 493 -200 197 -428 11029 -12118 65 -198 199 -68 231 -230 101 -166 99 -664 131 -132 3163 -4238 331 -298 531 -398 299 -98 199 -166 563 -100 131 -98 893 -66 3141 -1556 133 -1722 131 -830 197 -262 195 -66 163 -462 195 -396 195 -134 499 -132 265 -66 1717 -166 3175 -11366 199 -164 131 -66 163 -98 525 -98 363 -264 4495 -100 229 -66 131 -66 593 -3002 97 -394 131 -426 99 -462 597 -692 295 -298 431 -230 4231 -66 9711 -3246 131 -100 99 -400 263 -498 65 -100 297 -98 99 -132 65 -862 131 -66 365 -396 99 -166 1991 -98 1611 -132 10333 -790 65 -1984 99 -896 165 -332 365 -232 131 -830 65 -66 397 -166 197 -66 65 -496 199 -100 9975 -1728 67 -5008 727 -98 131 -100 2873 -66 12011 -3150 67 -960 99 -234 99 -298 231 -232 195 -266 165 -296 261 -166 757 -66 629 -196 657 -100 197 -134 297 -364 11237 -1684 65 -2076 165 -462 491 -100 663 -630 329 -264 263 -100 1357 -66 461 -1676 99 -1782 295 -296 65 -296 163 -230 99 -132 295 -66 163 -362 197 -724 757 -66 RAW_Data: 3785 -66 13551 -1808 97 -730 65 -100 231 -132 131 -1230 593 -232 1579 -66 2667 -200 101 -3480 165 -692 133 -396 427 -1524 363 -66 431 -132 10305 -8288 461 -628 67 -430 725 -66 1053 -66 4501 -230 165 -66 331 -66 355 -266 263 -132 63 -562 459 -462 197 -66 129 -132 65 -100 2643 -132 2107 -66 9651 -3692 99 -100 195 -294 97 -660 759 -328 165 -560 891 -66 1953 -66 11305 -362 263 -662 131 -432 65 -134 563 -430 131 -132 1819 -100 165 -166 1061 -98 10089 -2476 65 -854 395 -198 99 -492 131 -164 229 -466 199 -428 299 -100 927 -200 1557 -134 4269 -10464 133 -1624 65 -198 265 -398 131 -430 729 -134 6189 -66 5421 -2082 165 -3342 19967 -12808 1439 -1536 453 -1046 449 -1032 449 -1056 947 -552 977 -522 977 -518 453 -1038 977 -522 977 -520 457 -1038 977 -506 1005 -496 495 -1008 975 -538 973 -530 465 -1008 975 -554 453 -1036 947 -518 487 -1008 475 -1042 443 -1050 461 -1008 1005 -510 447 -1048 985 -510 469 -1006 1005 -494 997 -514 975 -514 975 -504 999 -506 479 -1034 491 -1010 975 -508 973 -524 491 -1004 473 -1018 997 -520 975 -512 975 -518 473 -1030 983 -516 981 -514 471 -998 997 -522 481 -1012 481 -1012 457 -1050 973 -512 977 -524 459 -1016 1003 -512 479 -1014 459 -1016 475 -1012 1007 -522 969 -502 495 -1008 477 -1030 965 -522 975 -514 479 -1000 471 -1062 471 -964 483 -982 471 -1000 471 -980 979 -448 503 -988 465 -976 487 -974 1459 -23696 1407 -1616 401 -1068 429 -1080 419 -1058 935 -566 923 -584 417 -1078 939 -524 457 -1042 973 -550 443 -1028 949 -554 945 -552 447 -1022 979 -518 971 -542 479 -1024 947 -550 441 -1048 979 -518 453 -1044 449 -1050 449 -1020 485 -1014 981 -518 479 -1014 975 -524 459 -1036 973 -516 979 -518 971 -552 945 -550 945 -552 449 -1030 479 -1026 947 -554 949 -552 449 -1018 479 -1008 981 -518 975 -548 945 -554 451 -1034 967 -514 997 -514 445 -1036 967 -554 447 -1022 485 -1010 475 -1016 975 -518 977 -520 487 -1014 973 -552 451 -1040 441 -1050 447 -1022 485 -1014 987 -516 479 -1014 483 -1014 459 -1046 969 -514 449 -1044 967 -546 973 -488 447 -1016 443 -1000 973 -490 475 -980 983 -482 441 -1016 465 -976 1475 -23652 1451 -1548 479 -1014 461 -1014 471 -1044 975 -520 971 -502 495 -1012 977 -506 1005 -498 989 -516 481 -1016 975 -520 981 -514 475 -1014 979 -522 983 -512 475 -1022 965 -514 471 -1046 973 -494 473 -1016 475 -1046 447 -1050 463 -1012 999 -512 481 -1012 983 -520 477 -1014 977 -524 955 -548 973 -512 975 -520 967 -556 449 -1020 483 -1012 983 -520 973 -516 481 -1008 473 -1034 RAW_Data: 967 -538 963 -544 973 -522 471 -1006 989 -512 1007 -520 443 -1036 985 -516 449 -1048 451 -1022 483 -1012 983 -520 977 -514 481 -1012 979 -514 483 -1022 481 -1010 471 -1020 479 -1020 979 -524 457 -1048 973 -514 483 -1012 981 -520 483 -1018 481 -1014 485 -986 467 -980 981 -486 469 -978 457 -1004 963 -480 983 -486 971 -514 1441 -23704 1383 -1628 389 -1112 385 -1092 407 -1092 915 -552 941 -570 441 -1064 423 -1046 451 -1044 939 -556 455 -1048 945 -552 973 -522 453 -1046 945 -552 947 -550 451 -1040 969 -518 479 -1028 951 -552 451 -1018 479 -1018 483 -1014 459 -1044 971 -514 483 -1010 971 -544 447 -1020 977 -524 987 -518 973 -516 979 -524 985 -518 479 -1016 447 -1050 953 -548 971 -514 483 -1014 459 -1048 967 -514 977 -526 953 -548 443 -1046 975 -492 995 -512 471 -1050 943 -552 445 -1032 455 -1044 449 -1048 941 -550 945 -552 449 -1050 945 -552 451 -1044 449 -1018 479 -1016 479 -1002 969 -542 973 -522 455 -1040 477 -1022 967 -534 959 -514 975 -554 469 -1008 449 -980 469 -1008 943 -484 1001 -484 467 -980 983 -482 961 -514 1439 -23700 1469 -1510 495 -1008 473 -1036 463 -1012 969 -546 973 -522 473 -1018 479 -1014 975 -526 955 -516 475 -1046 975 -490 999 -518 481 -1014 975 -520 967 -514 481 -1022 979 -524 457 -1048 971 -514 481 -1010 485 -1020 477 -1014 479 -1000 1001 -522 451 -1020 977 -520 473 -1032 967 -538 959 -514 1005 -522 965 -504 989 -514 475 -1046 441 -1050 971 -514 975 -520 473 -1018 481 -1014 979 -520 983 -520 977 -516 485 -1010 979 -544 975 -518 453 -1042 981 -520 453 -1024 483 -1010 457 -1050 975 -512 975 -524 459 -1048 973 -514 481 -1010 473 -1016 479 -1016 477 -1036 967 -506 995 -512 965 -546 445 -1048 957 -516 1005 -512 445 -1046 979 -486 473 -980 979 -486 473 -980 981 -486 473 -980 485 -986 467 -976 1477 -142204 197 -1486 165 -198 165 -664 295 -232 99 -266 231 -166 3045 -100 13411 -3670 197 -498 131 -166 231 -198 165 -66 265 -134 129 -1062 431 -130 465 -134 13447 -3848 329 -100 163 -298 99 -164 463 -98 197 -98 131 -198 65 -296 493 -264 789 -66 7225 -12438 99 -164 463 -132 197 -630 65 -198 2487 -66 165 -100 10097 -6554 459 -664 297 -460 4925 -132 6063 -12078 497 -98 99 -200 97 -234 165 -298 1721 -134 265 -100 3035 -100 12081 -3674 231 -100 97 -200 97 -264 461 -100 99 -132 231 -100 97 -430 527 -200 231 -64 2081 -132 327 -100 529 -66 831 -66 3067 -4704 99 -5520 97 -496 67 -198 167 -498 693 -462 2341 -15926 65 -1392 659 -134 131 -298 165 -66 99 -298 4777 -4208 429 -66 +RAW_Data: 377 -386 1117 -410 1121 -352 1141 -384 1151 -378 1119 -350 1139 -386 1115 -1134 389 -1114 395 -1122 363 -1136 389 -358 1167 -356 1145 -1120 389 -1110 391 -356 1139 -1126 389 -1114 391 -1122 363 -1146 389 -1110 395 -1122 363 -1138 389 -1110 393 -1122 363 -1140 389 -1112 393 -1120 389 -1118 389 -1112 397 -1124 363 -1142 389 -1112 359 -1154 367 -1134 389 -1144 365 -1138 355 -394 1119 -380 1107 -1152 353 -398 1113 -384 1139 -1118 385 -376 1141 -386 1129 -350 1143 -388 1109 -1132 389 -1112 393 -390 1107 -1128 389 -1112 397 -388 1111 -1132 389 -358 1127 -1118 417 -1116 383 -1120 353 -1158 389 -1108 375 -384 1121 -408 1123 -350 1139 -386 1111 -1130 389 -1114 395 -1122 395 -1114 389 -1116 395 -1122 363 -1138 387 -9444 373 -374 379 -374 381 -346 403 -346 389 -376 389 -390 353 -376 359 -382 383 -360 419 -360 359 -386 359 -2264 777 -356 1127 -390 1143 -362 1131 -1138 365 -1122 359 -386 1153 -1106 377 -1152 385 -372 1113 -1140 385 -1118 381 -1114 383 -1150 383 -1120 355 -1122 389 -358 1165 -386 1113 -1128 389 -360 1125 -384 1131 -368 1157 -350 1139 -386 1115 -406 1099 -384 1141 -1122 383 -1110 373 -1130 385 -1128 393 -380 1131 -380 1129 -1112 383 -1132 391 -356 1143 -1124 383 -1130 367 -1136 385 -1136 387 -1112 371 -1120 389 -1118 383 -1130 371 -1130 383 -1110 383 -1120 413 -1118 383 -1144 347 -1144 389 -1110 393 -1122 363 -1140 389 -1112 359 -1154 363 -1146 389 -1110 393 -374 1115 -384 1115 -1144 385 -368 1141 -388 1111 -1110 421 -360 1125 -388 1109 -392 1137 -358 1125 -1144 365 -1138 389 -358 1123 -1118 401 -1138 389 -360 1121 -1120 417 -358 1109 -1154 355 -1120 375 -1138 385 -1130 391 -1136 355 -398 1115 -380 1141 -384 1121 -382 1119 -1104 413 -1118 355 -1156 387 -1112 377 -1122 389 -1118 387 -1112 397 -9422 417 -352 363 -416 355 -388 345 -382 377 -380 375 -380 375 -380 375 -380 385 -356 379 -366 385 -374 387 -2246 745 -380 1141 -386 1113 -370 1125 -1140 373 -1152 355 -394 1117 -1140 381 -1120 385 -374 1145 -1112 385 -1122 381 -1116 383 -1120 375 -1120 389 -1120 373 -380 1171 -358 1121 -1142 377 -356 1127 -384 1137 -378 1155 -390 1105 -366 1125 -386 1135 -386 1111 -1132 389 -1112 393 -1120 365 -1138 387 -360 1163 -356 1143 -1126 387 -1114 357 -386 1141 -1126 383 -1130 365 -1132 381 -1140 377 -1116 383 -1130 371 -1128 381 -1140 347 -1148 385 -1128 369 -1128 381 -1142 377 -1114 389 -1112 395 -1124 361 -1142 389 -1114 393 -1122 365 -1138 389 -1114 397 -1108 389 -392 1119 -350 1139 -1152 355 -396 1115 -382 1109 -1156 385 -374 1111 -384 1139 -368 1147 -388 1109 -1112 389 -1120 383 -388 1107 -1150 389 -1112 +RAW_Data: 393 -390 1109 -1128 389 -360 1125 -1120 381 -1152 383 -1118 353 -1158 387 -1112 375 -386 1117 -408 1121 -350 1143 -388 1109 -1132 389 -1114 391 -1122 395 -1120 389 -1112 393 -1122 365 -1136 389 -9442 373 -376 389 -354 377 -366 387 -384 357 -378 361 -418 347 -394 385 -358 363 -382 361 -414 357 -392 333 -2290 751 -384 1113 -406 1121 -350 1137 -1136 353 -1160 385 -356 1135 -1120 361 -1146 385 -388 1137 -1108 361 -1150 387 -1112 395 -1136 349 -1154 353 -1142 371 -384 1145 -378 1117 -1138 381 -382 1087 -410 1121 -382 1143 -380 1121 -380 1115 -384 1107 -418 1115 -1106 385 -1148 365 -1118 359 -1146 387 -388 1135 -388 1113 -1126 383 -1130 367 -376 1113 -1142 383 -1114 375 -1154 355 -1160 385 -1110 371 -1152 357 -1118 385 -1146 365 -1122 361 -1146 387 -1114 395 -1134 355 -1160 351 -1146 369 -1154 355 -1120 387 -1114 397 -1136 357 -1118 407 -1144 351 -1134 359 -420 1111 -366 1131 -1142 379 -384 1089 -410 1119 -1142 379 -366 1141 -386 1109 -388 1131 -350 1141 -1118 391 -1114 375 -378 1153 -1116 385 -1136 383 -358 1139 -1120 359 -420 1099 -1142 383 -1118 383 -1138 347 -1144 385 -1144 369 -386 1113 -404 1089 -386 1141 -382 1099 -1136 381 -1128 375 -1130 383 -1140 359 -1146 387 -1114 395 -1138 357 -9430 383 -378 359 -418 347 -392 387 -360 363 -384 361 -414 357 -386 347 -384 375 -382 385 -358 383 -364 387 -2252 773 -354 1131 -384 1137 -386 1111 -1132 387 -1112 397 -388 1113 -1124 389 -1116 387 -388 1115 -1132 389 -1114 393 -1120 365 -1140 389 -1114 357 -1154 365 -378 1151 -358 1127 -1156 367 -376 1135 -358 1125 -388 1141 -368 1125 -386 1133 -388 1109 -370 1155 -1106 375 -1122 389 -1118 389 -1114 395 -386 1117 -410 1123 -1106 377 -1130 383 -388 1107 -1152 353 -1148 353 -1150 367 -1142 389 -1110 397 -1120 365 -1138 389 -1110 391 -1122 363 -1142 387 -1116 389 -1120 391 -1116 389 -1116 395 -1122 365 -1140 389 -1114 357 -1154 363 -1138 389 -1142 365 -1138 355 -396 1115 -382 1141 -1118 353 -400 1111 -384 1139 -1120 381 -386 1139 -366 1119 -392 1121 -388 1107 -1152 389 -1114 355 -388 1139 -1126 387 -1114 397 -376 1111 -1144 375 -380 1129 -1138 375 -1098 385 -1140 377 -1118 387 -1144 371 -386 1115 -404 1121 -348 1137 -386 1113 -1134 389 -1112 395 -1124 395 -1118 389 -1110 395 -1122 363 -1138 389 -9418 391 -360 407 -384 361 -388 355 -390 367 -376 373 -380 387 -356 377 -366 385 -388 355 -378 359 -384 377 -2266 777 -346 1149 -388 1107 -390 1129 -1104 415 -1118 353 -398 1113 -1138 383 -1122 381 -388 1141 -1118 389 -1112 357 -1154 365 -1138 389 -1114 357 -1154 363 -378 1155 -358 1123 -1156 381 -360 1107 -384 +RAW_Data: 1153 -378 1119 -382 1143 -382 1121 -382 1117 -382 1113 -1120 389 -1120 387 -1112 399 -1120 393 -392 1119 -350 1141 -1154 357 -1116 389 -360 1163 -1120 365 -1138 387 -1114 389 -1122 389 -1116 387 -1114 397 -1104 379 -1156 353 -1148 367 -1118 377 -1122 423 -1110 373 -1122 389 -1118 383 -1130 373 -1128 383 -1140 345 -1146 383 -1130 399 -1130 353 -1142 377 -358 1127 -384 1143 -1118 385 -372 1111 -386 1137 -1120 381 -388 1141 -364 1127 -384 1133 -374 1111 -1148 383 -1114 373 -384 1115 -1136 387 -1144 371 -386 1115 -1132 387 -360 1123 -1150 345 -1148 383 -1128 371 -1132 381 -1140 379 -390 1123 -350 1139 -388 1113 -406 1089 -1142 373 -1120 389 -1118 423 -1110 371 -1120 379 -1122 407 -1104 417 -9440 389 -356 379 -366 385 -388 355 -378 359 -384 381 -394 387 -358 361 -386 359 -416 355 -388 345 -384 377 -2262 747 -384 1149 -380 1115 -382 1113 -1120 389 -1120 389 -360 1129 -1152 367 -1136 389 -358 1131 -1152 367 -1138 389 -1116 355 -1152 367 -1134 389 -1116 353 -388 1141 -368 1123 -1138 375 -386 1113 -408 1121 -350 1175 -372 1105 -386 1145 -352 1141 -366 1145 -1114 385 -1116 377 -1122 389 -1120 421 -354 1139 -388 1109 -1132 383 -1130 369 -374 1113 -1144 385 -1114 377 -1120 391 -1128 373 -1138 385 -1130 359 -1138 377 -1120 373 -1138 383 -1130 359 -1138 379 -1160 375 -1106 385 -1130 393 -1120 377 -1118 389 -1112 393 -1140 355 -1120 421 -1114 371 -1122 391 -390 1123 -350 1139 -1134 353 -402 1113 -384 1141 -1118 385 -376 1143 -352 1161 -352 1135 -386 1113 -1132 387 -1114 395 -388 1111 -1128 387 -1114 399 -374 1115 -1142 375 -380 1117 -1118 387 -1144 363 -1136 385 -1130 367 -1130 383 -388 1107 -392 1129 -380 1115 -384 1113 -1136 389 -1114 393 -1124 393 -1120 389 -1114 393 -1124 363 -1140 389 -9416 391 -360 405 -386 329 -416 357 -392 365 -374 377 -380 343 -412 341 -412 353 -390 375 -366 385 -386 355 -2264 743 -394 1123 -388 1111 -392 1133 -1110 395 -1120 363 -382 1133 -1142 381 -1118 383 -376 1111 -1146 383 -1122 383 -1146 347 -1150 381 -1116 353 -1158 343 -410 1133 -382 1111 -1152 355 -394 1119 -382 1109 -382 1153 -378 1131 -354 1137 -396 1119 -388 1111 -1150 351 -1152 351 -1150 365 -1136 387 -356 1131 -386 1143 -1122 387 -1112 357 -420 1107 -1128 387 -1114 359 -1152 363 -1148 387 -1114 395 -1122 361 -1140 387 -1110 395 -1120 361 -1140 387 -1114 393 -1154 355 -1120 387 -1146 365 -1118 361 -1146 387 -1112 395 -1120 363 -1140 385 -1144 367 -1120 359 -420 1099 -384 1139 -1118 383 -384 1109 -392 1129 -1138 379 -366 1147 -388 1109 -386 1099 -384 1139 -1132 349 -1158 375 -380 1131 -1104 411 -1122 351 -416 1111 -1148 +RAW_Data: 353 -396 1121 -1142 347 -1150 381 -1116 355 -1156 375 -1144 387 -360 1119 -388 1107 -394 1131 -386 1101 -1152 363 -1138 387 -1112 391 -1152 357 -1116 375 -1136 383 -1122 383 -9448 357 -392 357 -398 363 -378 385 -358 383 -364 389 -386 357 -380 389 -386 347 -382 375 -384 375 -380 373 -2262 747 -376 1145 -390 1107 -386 1129 -1104 413 -1120 353 -396 1115 -1140 381 -1122 383 -376 1143 -1110 385 -1118 383 -1114 417 -1114 383 -1120 353 -1156 389 -356 1135 -386 1113 -1134 389 -358 1129 -390 1107 -392 1153 -358 1127 -388 1143 -362 1131 -356 1131 -1154 365 -1136 389 -1114 357 -1150 363 -386 1153 -358 1125 -1118 417 -1120 381 -350 1123 -1134 391 -1112 395 -1124 395 -1116 389 -1112 393 -1124 363 -1140 389 -1114 359 -1154 363 -1138 389 -1114 391 -1124 361 -1144 389 -1112 393 -1122 363 -1138 389 -1112 391 -1122 363 -1138 389 -1144 365 -1124 361 -382 1155 -350 1137 -1120 391 -386 1131 -350 1151 -1120 383 -378 1141 -352 1137 -394 1117 -390 1107 -1150 389 -1114 355 -388 1143 -1120 387 -1112 397 -388 1113 -1130 385 -344 1163 -1104 379 -1122 373 -1140 383 -1130 389 -1124 359 -386 1127 -386 1139 -368 1141 -390 1107 -1112 387 -1116 385 -1150 367 -1140 389 -1112 393 -1124 363 -1136 389 -9444 379 -340 417 -360 359 -386 359 -416 355 -386 347 -384 375 -382 375 -380 375 -378 375 -380 385 -356 379 -2278 745 -354 1151 -368 1141 -390 1105 -1114 387 -1116 385 -386 1141 -1120 389 -1114 389 -388 1113 -1130 389 -1112 393 -1124 363 -1138 389 -1112 389 -1122 363 -380 1159 -350 1137 -1122 391 -388 1097 -384 1139 -382 1125 -386 1145 -352 1141 -366 1145 -390 1107 -1110 387 -1150 353 -1150 367 -1138 387 -360 1125 -390 1109 -1152 389 -1112 357 -388 1141 -1122 389 -1110 391 -1122 395 -1112 389 -1110 397 -1120 363 -1144 389 -1114 391 -1122 365 -1138 389 -1116 389 -1142 355 -1120 389 -1112 397 -1122 363 -1140 389 -1110 393 -1130 349 -1140 405 -1134 389 -1112 357 -388 1141 -364 1129 -1142 367 -388 1111 -370 1131 -1140 383 -364 1149 -388 1109 -388 1137 -356 1127 -1118 383 -1120 413 -350 1121 -1132 407 -1140 355 -364 1149 -1112 371 -406 1129 -1104 409 -1098 383 -1116 417 -1118 381 -1118 385 -388 1111 -390 1129 -350 1137 -386 1113 -1138 389 -1114 395 -1122 393 -1120 389 -1112 393 -1124 363 -1138 389 -9444 379 -340 417 -360 359 -386 361 -414 357 -386 347 -384 375 -382 375 -380 375 -380 375 -378 373 -380 373 -2262 749 -386 1111 -408 1117 -348 1143 -1120 391 -1116 389 -358 1127 -1154 365 -1136 387 -360 1129 -1154 365 -1136 389 -1114 357 -1154 365 -1134 389 -1112 357 -390 1137 -406 1119 -1106 377 -386 1117 -406 1123 -350 1143 -384 +RAW_Data: 1149 -378 1121 -350 1145 -380 1133 -1104 375 -1136 385 -1130 359 -1138 379 -400 1129 -354 1139 -1148 355 -1150 365 -378 1119 -1146 355 -1152 365 -1134 389 -1110 397 -1122 363 -1140 389 -1110 395 -1122 363 -1142 389 -1116 357 -1152 365 -1146 389 -1112 393 -1130 349 -1138 383 -1116 413 -1120 353 -1122 387 -1114 397 -1154 355 -1124 387 -360 1133 -384 1131 -1134 383 -376 1133 -352 1133 -1132 383 -376 1139 -378 1135 -380 1115 -382 1141 -1118 353 -1160 387 -356 1133 -1118 379 -1158 353 -392 1133 -1104 379 -398 1117 -1138 383 -1118 353 -1164 353 -1146 403 -1120 353 -398 1115 -382 1143 -384 1089 -412 1121 -1106 377 -1154 355 -1118 407 -1146 351 -1130 395 -1138 355 -1118 407 -9434 353 -396 363 -380 383 -360 383 -364 389 -386 357 -414 355 -386 345 -386 375 -382 375 -380 375 -378 375 -2256 769 -384 1119 -382 1117 -380 1113 -1122 389 -1118 389 -360 1131 -1140 377 -1118 421 -354 1139 -1140 355 -1118 405 -1104 387 -1128 391 -1122 363 -1138 387 -360 1157 -354 1143 -1128 387 -360 1121 -388 1141 -362 1129 -384 1139 -388 1111 -370 1127 -384 1135 -1122 363 -1140 389 -1116 393 -1122 395 -356 1129 -384 1141 -1120 383 -1134 387 -356 1133 -1130 349 -1140 383 -1116 413 -1118 381 -1110 377 -1146 389 -1114 391 -1124 365 -1138 391 -1112 357 -1150 365 -1144 387 -1112 395 -1122 361 -1140 387 -1112 393 -1104 379 -1158 353 -1144 403 -1118 353 -1158 353 -390 1133 -390 1107 -1130 389 -358 1125 -388 1111 -1154 389 -358 1129 -386 1131 -368 1129 -382 1139 -1118 353 -1164 387 -356 1135 -1120 393 -1118 389 -358 1131 -1154 365 -376 1135 -1108 395 -1136 347 -1126 387 -1144 403 -1120 353 -398 1115 -384 1141 -372 1103 -386 1145 -1108 387 -1120 383 -1116 403 -1140 389 -1116 353 -1146 361 -1144 389 -9420 393 -362 401 -338 377 -388 385 -374 361 -382 375 -382 375 -380 373 -380 373 -380 373 -380 389 -354 379 -2272 743 -388 1137 -360 1121 -386 1111 -1152 351 -1148 359 -384 1143 -1126 387 -1114 391 -384 1117 -1130 383 -1132 369 -1134 351 -1138 377 -1142 385 -1112 359 -420 1107 -406 1121 -1104 377 -384 1119 -406 1119 -352 1171 -382 1123 -378 1119 -384 1107 -384 1119 -1136 385 -1116 393 -1120 361 -1142 387 -388 1137 -386 1113 -1128 385 -1116 357 -420 1113 -1124 387 -1114 359 -1148 395 -1116 385 -1146 363 -1116 361 -1144 387 -1144 363 -1120 361 -1144 385 -1112 393 -1152 355 -1154 353 -1144 367 -1136 355 -1158 351 -1146 369 -1120 361 -1144 385 -1148 369 -1152 357 -392 1117 -380 1107 -1152 355 -398 1119 -382 1109 -1152 385 -374 1113 -386 1139 -366 1145 -388 1111 -1110 385 -1148 353 -386 1139 -1124 387 -1142 365 -386 1113 -1132 385 -360 1125 -1144 +RAW_Data: 363 -1140 387 -1114 357 -1152 363 -1146 387 -358 1129 -386 1139 -366 1125 -384 1139 -1120 363 -1140 387 -1112 393 -1130 381 -1136 383 -1114 371 -1132 383 -116626 65 -934 133 -1954 131 -102 133 -136 97 -332 65 -430 299 -296 129 -100 265 -168 367 -100 65 -66 231 -336 9643 -7766 529 -68 467 -166 65 -134 99 -500 331 -132 65 -130 329 -98 497 -100 1195 -100 1959 -66 4163 -7346 97 -392 165 -194 97 -2978 433 -298 531 -298 65 -200 131 -132 261 -98 229 -68 12837 -340 99 -268 165 -134 65 -898 67 -100 265 -66 165 -100 597 -166 199 -298 199 -200 99 -132 233 -132 299 -132 233 -166 65 -66 4021 -168 133 -68 231 -168 4647 -130 1399 -7750 133 -1714 197 -2480 131 -200 65 -100 265 -890 63 -1152 197 -98 293 -134 65 -300 361 -100 1035 -100 231 -132 299 -100 3399 -66 6287 -4506 99 -100 65 -130 99 -196 461 -98 331 -164 97 -162 227 -64 197 -98 229 -130 195 -100 425 -526 165 -130 95 -522 457 -560 233 -98 261 -66 1155 -100 259 -130 1407 -98 553 -66 7793 -494 65 -232 65 -3652 229 -2716 361 -266 333 -200 133 -166 99 -132 267 -66 133 -132 199 -166 331 -132 331 -166 197 -950 229 -198 303 -298 365 -100 4839 -3816 165 -130 229 -696 131 -130 261 -262 97 -166 263 -894 165 -230 365 -566 129 -560 197 -324 99 -98 261 -134 131 -100 67 -334 67 -232 199 -132 165 -302 67 -100 1467 -98 459 -100 1081 -130 131 -66 8927 -232 165 -3104 99 -2812 65 -982 131 -98 195 -98 263 -264 231 -66 195 -132 193 -164 65 -100 365 -132 1629 -66 1009 -132 8383 -632 131 -3060 131 -492 425 -100 763 -166 371 -132 1197 -134 229 -694 461 -366 365 -98 329 -198 267 -168 399 -68 131 -332 493 -132 231 -132 569 -66 7765 -7568 99 -532 65 -634 133 -3540 65 -100 263 -592 261 -1484 299 -302 265 -234 1129 -304 99 -436 163 -360 97 -556 231 -166 265 -1164 165 -134 235 -100 163 -332 297 -100 197 -132 99 -566 133 -234 133 -328 295 -98 985 -98 163 -396 399 -134 1557 -134 297 -266 6875 -68 1759 -7194 133 -166 99 -266 65 -432 67 -432 393 -5086 99 -66 199 -68 263 -866 429 -100 359 -130 261 -132 267 -134 533 -134 9251 -4184 65 -1156 165 -198 65 -426 297 -492 67 -164 131 -198 259 -164 199 -100 733 -134 865 -100 397 -132 65 -100 197 -66 327 -164 227 -98 231 -132 97 -262 99 -130 229 -66 589 -96 1119 -98 1905 -7486 599 -66 561 -66 359 -98 757 -162 261 -66 323 -130 5573 -8538 99 -894 131 -594 229 -364 63 -1378 197 -1682 331 -100 199 -166 diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c new file mode 100644 index 000000000..2c8de0d2d --- /dev/null +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -0,0 +1,336 @@ +#include "kinggates_stylo_4k.h" +#include "keeloq_common.h" + +#include "../subghz_keystore.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocoKingGates_stylo_4k" + +static const SubGhzBlockConst subghz_protocol_kinggates_stylo_4k_const = { + .te_short = 400, + .te_long = 1100, + .te_delta = 140, + .min_count_bit_for_found = 89, +}; + +struct SubGhzProtocolDecoderKingGates_stylo_4k { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint64_t data; + uint16_t header_count; + SubGhzKeystore* keystore; +}; + +struct SubGhzProtocolEncoderKingGates_stylo_4k { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + KingGates_stylo_4kDecoderStepReset = 0, + KingGates_stylo_4kDecoderStepCheckPreambula, + KingGates_stylo_4kDecoderStepCheckStartBit, + KingGates_stylo_4kDecoderStepSaveDuration, + KingGates_stylo_4kDecoderStepCheckDuration, +} KingGates_stylo_4kDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder = { + .alloc = subghz_protocol_decoder_kinggates_stylo_4k_alloc, + .free = subghz_protocol_decoder_kinggates_stylo_4k_free, + + .feed = subghz_protocol_decoder_kinggates_stylo_4k_feed, + .reset = subghz_protocol_decoder_kinggates_stylo_4k_reset, + + .get_hash_data = subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data, + .serialize = subghz_protocol_decoder_kinggates_stylo_4k_serialize, + .deserialize = subghz_protocol_decoder_kinggates_stylo_4k_deserialize, + .get_string = subghz_protocol_decoder_kinggates_stylo_4k_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_kinggates_stylo_4k = { + .name = SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_kinggates_stylo_4k_decoder, + .encoder = &subghz_protocol_kinggates_stylo_4k_encoder, +}; + +void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderKingGates_stylo_4k* instance = + malloc(sizeof(SubGhzProtocolDecoderKingGates_stylo_4k)); + instance->base.protocol = &subghz_protocol_kinggates_stylo_4k; + instance->generic.protocol_name = instance->base.protocol->name; + instance->keystore = subghz_environment_get_keystore(environment); + return instance; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + free(instance); +} + +void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + + switch(instance->decoder.parser_step) { + case KingGates_stylo_4kDecoderStepReset: + if((level) && DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckPreambula; + instance->header_count++; + } + break; + case KingGates_stylo_4kDecoderStepCheckPreambula: + if((!level) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta)) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + break; + } + if((instance->header_count > 2) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long * 2) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) { + // Found header + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckStartBit; + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepCheckStartBit: + if((level) && + DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short * 2) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepSaveDuration: + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_kinggates_stylo_4k_const.te_long * 3)) { + if(instance->decoder.decode_count_bit == + subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) { + instance->generic.data = instance->data; + instance->data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + break; + } else { + instance->decoder.te_last = duration; + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckDuration; + } + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepCheckDuration: + if(level) { + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_long) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + if(instance->decoder.decode_count_bit == 53) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + * @param file_name Full path to rainbow table the file + */ +static void subghz_protocol_kinggates_stylo_4k_remote_controller( + SubGhzBlockGeneric* instance, + uint64_t data, + SubGhzKeystore* keystore) { + /** + * 9500us 12*(400/400) 2200/800|1-bit|0-bit| + * _ _ _ __ ___ _ + * ________| |_| |_..._| |_____| |_| |___| |..... + * + * 1-bit 400/1100 us + * 0-bit 1100/400 us + * + * The package consists of 89 bits of data, LSB first + * Data - 1C9037F0C80000 CE280BA00 + * S[3] S[2] 1 key S[1] S[0] 2 byte always 0 Hop[3] Hop[2] Hop[1] Hop[0] 0 + * 11100100 10000001 1 0111 11110000 11001000 00000000 00000000 11001110 00101000 00001011 10100000 0000 + * + * Encryption - keeloq Simple Learning + * key C S[3] CNT + * Decrypt - 0xEC270B9C => 0x E C 27 0B9C + * + * + * +*/ + + uint32_t hop = subghz_protocol_blocks_reverse_key(data >> 4, 32); + uint64_t fix = subghz_protocol_blocks_reverse_key(instance->data, 53); + bool ret = false; + uint32_t decrypt = 0; + instance->btn = (fix >> 17) & 0x0F; + instance->serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF); + + for + M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { + if(manufacture_code->type == KEELOQ_LEARNING_SIMPLE) { + decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); + if(((decrypt >> 28) == instance->btn) && (((decrypt >> 24) & 0x0F) == 0x0C) && + (((decrypt >> 16) & 0xFF) == (instance->serial & 0xFF))) { + ret = true; + break; + } + } + } + if(ret) { + instance->cnt = decrypt & 0xFFFF; + } else { + instance->btn = 0; + instance->serial = 0; + instance->cnt = 0; + } +} + +uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; + } + + if(res && !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Data"); + res = false; + } + return res; + + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Missing Data"); + break; + } + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + instance->data = instance->data << 8 | key_data[i]; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + subghz_protocol_kinggates_stylo_4k_remote_controller( + &instance->generic, instance->data, instance->keystore); + + furi_string_cat_printf( + output, + "%s\r\n" + "Key:0x%llX%07llX %dbit\r\n" + "Sn:0x%08lX Btn:0x%01X\r\n" + "Cnt:0x%04lX\r\n", + instance->generic.protocol_name, + instance->generic.data, + instance->data, + instance->generic.data_count_bit, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/kinggates_stylo_4k.h b/lib/subghz/protocols/kinggates_stylo_4k.h new file mode 100644 index 000000000..c9f1cf380 --- /dev/null +++ b/lib/subghz/protocols/kinggates_stylo_4k.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME "KingGates Stylo4k" + +typedef struct SubGhzProtocolDecoderKingGates_stylo_4k SubGhzProtocolDecoderKingGates_stylo_4k; +typedef struct SubGhzProtocolEncoderKingGates_stylo_4k SubGhzProtocolEncoderKingGates_stylo_4k; + +extern const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder; +extern const SubGhzProtocol subghz_protocol_kinggates_stylo_4k; + +/** + * Allocate SubGhzProtocolDecoderKingGates_stylo_4k. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderKingGates_stylo_4k* pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param output Resulting text + */ +void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 3904c1811..050904eec 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -41,6 +41,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_linear_delta3, &subghz_protocol_dooya, &subghz_protocol_alutech_at_4n, + &subghz_protocol_kinggates_stylo_4k, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index cd9b7c6ed..522931d22 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -41,5 +41,6 @@ #include "holtek_ht12x.h" #include "dooya.h" #include "alutech_at_4n.h" +#include "kinggates_stylo_4k.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; From 8f2f2d810ab4112605adee7f605613ff3c151f10 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Wed, 8 Feb 2023 10:06:42 -0800 Subject: [PATCH 16/34] Move CSN space to revent overflow (#2232) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../plugins/picopass/scenes/picopass_scene_read_card_success.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index bb170ac45..0d1cc78c3 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -33,7 +33,7 @@ void picopass_scene_read_card_success_on_enter(void* context) { uint8_t csn[PICOPASS_BLOCK_LEN]; memcpy(csn, &AA1->data[PICOPASS_CSN_BLOCK_INDEX], PICOPASS_BLOCK_LEN); for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { - furi_string_cat_printf(csn_str, " %02X", csn[i]); + furi_string_cat_printf(csn_str, "%02X ", csn[i]); } // Neither of these are valid. Indicates the block was all 0x00 or all 0xff From a00508763652a424049b337b26386adc2ad4248d Mon Sep 17 00:00:00 2001 From: hedger Date: Wed, 8 Feb 2023 22:16:05 +0400 Subject: [PATCH 17/34] fbt: building fap_dist for compact gh build; accessor: fixed for latest ibutton changes (#2377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt: building fap_dist as default target; accessor: fixed for latest ibutton changes * fbt: not building fap_dist as default target; github: doing fap_dist for compact builds Co-authored-by: あく --- .github/workflows/build.yml | 2 +- applications/debug/accessor/accessor_app.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6c9219c2..be9817684 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -188,5 +188,5 @@ jobs: set -e for TARGET in ${TARGETS}; do TARGET="$(echo "${TARGET}" | sed 's/f//')"; \ - ./fbt TARGET_HW=$TARGET DEBUG=0 COMPACT=1 updater_package + ./fbt TARGET_HW=$TARGET DEBUG=0 COMPACT=1 fap_dist updater_package done diff --git a/applications/debug/accessor/accessor_app.cpp b/applications/debug/accessor/accessor_app.cpp index 9d3708ebe..337437d0e 100644 --- a/applications/debug/accessor/accessor_app.cpp +++ b/applications/debug/accessor/accessor_app.cpp @@ -34,7 +34,7 @@ void AccessorApp::run(void) { AccessorApp::AccessorApp() : text_store{0} { notification = static_cast(furi_record_open(RECORD_NOTIFICATION)); - onewire_host = onewire_host_alloc(); + onewire_host = onewire_host_alloc(&ibutton_gpio); furi_hal_power_enable_otg(); } From 892adcc6956cf929457e42c6a2a5a167ff78b0af Mon Sep 17 00:00:00 2001 From: jbohack Date: Wed, 8 Feb 2023 13:46:33 -0500 Subject: [PATCH 18/34] added pager modulation, removed duplicate modulations, and cleaned up duplicate setting file --- applications/main/subghz/subghz.c | 27 +++++++---- applications/main/unirfremix/unirfremix_app.c | 2 +- applications/plugins/protoview/app.c | 2 +- assets/resources/subghz/assets/setting_user | 45 ------------------- .../resources/subghz/assets/setting_user.txt | 21 --------- 5 files changed, 21 insertions(+), 76 deletions(-) delete mode 100644 assets/resources/subghz/assets/setting_user diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index c39c35679..d95133da7 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -183,7 +183,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { //init setting subghz->setting = subghz_setting_alloc(); - subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user")); + subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user.txt")); // Custom Presets load without using config file @@ -208,26 +208,37 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { flipper_format_free(temp_fm_preset2); - // # HND - FM presets + // Pagers FlipperFormat* temp_fm_preset3 = flipper_format_string_alloc(); flipper_format_write_string_cstr( - temp_fm_preset3, + temp_fm_preset2, (const char*)"Custom_preset_data", - (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); + (const char*)"02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset3); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset3); + subghz_setting_load_custom_preset(subghz->setting, (const char*)"Pagers", temp_fm_preset3); flipper_format_free(temp_fm_preset3); + // # HND - FM presets FlipperFormat* temp_fm_preset4 = flipper_format_string_alloc(); flipper_format_write_string_cstr( temp_fm_preset4, (const char*)"Custom_preset_data", - (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); + (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset4); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset4); + subghz_setting_load_custom_preset(subghz->setting, (const char*)"Honda_1", temp_fm_preset4); - flipper_format_free(temp_fm_preset4); + flipper_format_free(temp_fm_preset3); + + FlipperFormat* temp_fm_preset5 = flipper_format_string_alloc(); + flipper_format_write_string_cstr( + temp_fm_preset5, + (const char*)"Custom_preset_data", + (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); + flipper_format_rewind(temp_fm_preset5); + subghz_setting_load_custom_preset(subghz->setting, (const char*)"Honda_2", temp_fm_preset5); + + flipper_format_free(temp_fm_preset5); // custom presets loading - end diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index 2c0b68ae7..2b12a12b2 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -706,7 +706,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { void unirfremix_subghz_alloc(UniRFRemix* app) { // load subghz presets app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user.txt")); // load mfcodes app->environment = subghz_environment_alloc(); diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c index d060e2242..4765da9e3 100644 --- a/applications/plugins/protoview/app.c +++ b/applications/plugins/protoview/app.c @@ -143,7 +143,7 @@ ProtoViewApp* protoview_app_alloc() { //init setting app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user.txt")); // GUI app->gui = furi_record_open(RECORD_GUI); diff --git a/assets/resources/subghz/assets/setting_user b/assets/resources/subghz/assets/setting_user deleted file mode 100644 index d10392341..000000000 --- a/assets/resources/subghz/assets/setting_user +++ /dev/null @@ -1,45 +0,0 @@ -# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user -Filetype: Flipper SubGhz Setting File -Version: 1 - -# Add Standard frequencies for your region -Add_standard_frequencies: true - -# Default Frequency: used as default for "Read" and "Read Raw" -Default_frequency: 433920000 - -# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer" -Frequency: 300000000 -Frequency: 310000000 -Frequency: 320000000 - -# Frequencies used for hopping mode (keep this list small or flipper will miss signal) -Hopper_frequency: 300000000 -Hopper_frequency: 310000000 -Hopper_frequency: 310000000 - -# Custom preset -# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register - -Custom_preset_name: AM_1 -Custom_preset_module: CC1101 -Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 - -Custom_preset_name: AM_2 -Custom_preset_module: CC1101 -Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 - -Custom_preset_name: FM95 -Custom_preset_module: CC1101 -Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 83 10 67 15 24 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00 - -# Honda Presets -Custom_preset_name: Honda1 -Custom_preset_module: CC1101 -# G2 G3 G4 D L0 L1 L2 -Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00 - -Custom_preset_name: Honda2 -Custom_preset_module: CC1101 -# G2 G3 G4 D L0 L1 L2 -Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00 \ No newline at end of file diff --git a/assets/resources/subghz/assets/setting_user.txt b/assets/resources/subghz/assets/setting_user.txt index 06a699a6c..173511f40 100644 --- a/assets/resources/subghz/assets/setting_user.txt +++ b/assets/resources/subghz/assets/setting_user.txt @@ -78,24 +78,3 @@ Hopper_frequency: 868350000 #Custom_preset_name: AM_2 #Custom_preset_module: CC1101 #Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 - -# Custom presets added in Unleashed FW -# -- Some presets from forum.flipperzero.one -- - -#2-FSK 200khz BW / 135kHz Filter/ 15.86Khz Deviation + Ramping -Custom_preset_name: FM15k -Custom_preset_module: CC1101 -Custom_preset_data: 02 0D 03 47 08 32 0B 06 15 32 14 00 13 00 12 00 11 32 10 A7 18 18 19 1D 1D 92 1C 00 1B 04 20 FB 22 17 21 B6 00 00 00 12 0E 34 60 C5 C1 C0 - -# -- Other presets -- - -# Honda Presets -Custom_preset_name: Honda1 -Custom_preset_module: CC1101 -# G2 G3 G4 D L0 L1 L2 -Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00 - -Custom_preset_name: Honda2 -Custom_preset_module: CC1101 -# G2 G3 G4 D L0 L1 L2 -Custom_preset_data: 02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00 From 65ed2ed27756ac051ddb07e9b3d3092d6b895ac3 Mon Sep 17 00:00:00 2001 From: jbohack Date: Wed, 8 Feb 2023 13:54:06 -0500 Subject: [PATCH 19/34] added pager bruteforce for lrs pagers thanks jimi! --- .../subghz/Misc/Pager_Bruteforce.sub | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 assets/resources/subghz/Misc/Pager_Bruteforce.sub diff --git a/assets/resources/subghz/Misc/Pager_Bruteforce.sub b/assets/resources/subghz/Misc/Pager_Bruteforce.sub new file mode 100644 index 000000000..27e8a5430 --- /dev/null +++ b/assets/resources/subghz/Misc/Pager_Bruteforce.sub @@ -0,0 +1,108 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 467750000 +Preset: FuriHalSubGhzPresetCustom +Custom_preset_module: CC1101 +Custom_preset_data: 02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00 +Protocol: RAW +RAW_Data: 2950 -8252 551 -184 549 -7528 1285 -554 369 -187658 219 -138090 28885 -1206 4003 -2610 3601 -3004 3401 -3002 3401 -3002 3403 -2994 3401 -3002 3393 -3004 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1402 3393 -3002 3401 -1398 1791 -3000 3401 -3002 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 3389 -3002 1801 -1400 3401 -3008 3397 -2994 3401 -1398 1791 -4422 621 -2182 1689 -2756 3511 -3098 3253 -3022 3413 -3010 3403 -3002 3407 -3004 3399 -3006 3393 -2994 3401 -3002 3395 -3002 3393 -3002 3395 -3002 3405 -1400 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3407 -3004 3393 -1398 1791 -3000 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 3397 -3006 1805 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 3401 -2998 1805 -1396 3391 -3002 3393 -1402 1799 -3002 1797 -1398 3801 -2190 219 -1768 1767 -2596 3795 -2728 3493 -2872 3443 -3022 3417 -3002 3407 -3006 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3403 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -2994 1799 -1402 1795 -1398 1801 -1400 3407 -3006 3393 -1398 1791 -2998 3403 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 3389 -3002 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 +RAW_Data: 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 3395 -3002 1795 -1398 3401 -3002 3403 -1396 1791 -3000 3401 -7590 1961 -2458 3749 -2762 3575 -2990 3395 -2998 3393 -2994 3407 -2998 3393 -2994 3407 -2998 3397 -2998 3393 -3002 3395 -3002 3407 -2996 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3393 -1402 1799 -3002 3395 -3002 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 3393 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 3403 -2994 1799 -1402 3407 -2996 3395 -1400 1795 -1394 1797 -3002 3603 -200 1143 -188 1487 -1226 1827 -2996 3419 -3010 3401 -3002 3401 -3004 3401 -2994 3401 -3002 3399 -3006 3393 -2994 3401 -2996 3401 -3002 3399 -2996 3395 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1799 -1402 3401 -3002 3395 -1400 1795 -2992 3401 -3002 1801 -1402 1799 -1402 1801 -1396 1791 -1398 3403 -3002 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 3407 -2996 1797 -1394 3397 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -6446 2633 -2932 3363 -3180 +RAW_Data: 3189 -3190 3395 -2994 3393 -3002 3393 -3004 3393 -3002 3393 -3002 3403 -3002 3393 -3002 3395 -3002 3405 -2998 3393 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1795 -1402 1801 -1400 3401 -2996 3401 -1400 1801 -3002 3393 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 3403 -3002 3399 -3004 1795 -1396 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 3401 -2996 1799 -1402 3401 -1398 1791 -2998 1801 -1402 1799 -1402 1799 -1402 4405 -2974 1981 -3218 3193 -3160 3241 -3164 3313 -3118 3309 -3084 3243 -3026 3413 -3002 3407 -3010 3409 -3002 3399 -2996 3391 -2994 3401 -2994 3403 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1396 1797 -3002 1801 -1400 1801 -1396 1791 -1400 3401 -3002 3401 -1402 1799 -2996 3401 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 3401 -1402 1795 -2990 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 3407 -2998 1795 -1394 3389 -1402 1801 -3002 1799 -1402 1801 -1400 3401 -3596 385 -560 373 -2330 8379 -2512 3729 -2750 3565 -2984 3385 -2990 3395 -3002 3393 -3002 3393 -3004 3401 -2998 3405 -2994 3395 -2994 3401 -3002 3403 -1400 1795 -1394 1793 -1398 1799 -1402 1799 -1402 1801 -3002 1799 -1402 1801 -1396 1791 -1398 3407 -3006 3393 -1402 1795 -2998 3403 -2994 1801 -1400 1801 -1396 1797 -1400 1801 -1402 3401 -1396 1793 -1398 1799 -3002 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 +RAW_Data: 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -3002 1799 -1402 3407 -1400 1789 -2990 1799 -1402 3401 -3002 3609 -3274 2973 -2884 3537 -2960 3375 -2986 3389 -2996 3393 -2994 3393 -3002 3403 -3002 3401 -2994 3407 -2998 3393 -2994 3401 -3004 3393 -3002 3393 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -2990 1801 -1402 1799 -1402 1799 -1402 3393 -3002 3403 -1400 1795 -2992 3401 -3002 1801 -1402 1795 -1398 1801 -1400 3401 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 3401 -3002 1797 -1398 3401 -1396 1797 -3002 1801 -1400 3403 -1396 1791 -3800 205 -3344 203 -612 2395 -2560 3555 -2896 3655 -2830 3419 -3014 3407 -3004 3393 -3004 3401 -2994 3401 -2994 3395 -3002 3401 -3002 3395 -3002 3401 -2998 3397 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -3004 1799 -1402 1799 -1398 1791 -1398 3403 -3002 3401 -1400 1801 -3002 3395 -3002 1799 -1398 1791 -1398 1801 -1400 3407 -3006 1795 -1394 3389 -3002 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 3407 -2998 1795 -1394 3397 -1402 1799 -3002 3395 -3002 1795 -1398 4003 -4020 1655 -3022 3323 -3148 3163 -3176 3385 -2990 3393 -2996 3401 -3002 3401 -2994 +RAW_Data: 3395 -3002 3401 -3002 3395 -3002 3401 -2994 3393 -3004 3401 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 3401 -2994 3401 -1402 1799 -3004 3397 -3006 1795 -1394 1791 -1400 1799 -1402 3401 -3002 3401 -2996 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1398 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 3401 -3002 1801 -1400 3407 -1400 1789 -2990 3407 -3004 3395 -8162 1623 -2776 3591 -2998 3389 -3000 3397 -2994 3393 -3002 3395 -3002 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3395 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -3002 1799 -1398 1797 -1400 1801 -1400 3395 -3002 3401 -1398 1791 -3000 3401 -3002 1801 -1400 1795 -1394 1797 -1402 3405 -3006 3393 -1402 1799 -2996 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 3403 -3002 1799 -1398 3389 -1402 1801 -3002 3401 -1396 1793 -2998 3403 -1030 647 -3066 1817 -2644 3739 -2768 3575 -2986 3389 -2994 3395 -3002 3393 -3002 3399 -3006 3393 -2994 3401 -3004 3393 -3002 3393 -3002 3395 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3407 -3004 3399 -1404 1793 -2986 3401 -3002 1797 -1394 1795 -1402 1801 -1400 3407 -1404 1795 -2992 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 +RAW_Data: 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 3407 -3004 1795 -1394 3391 -1404 1801 -2994 3403 -1400 1795 -1394 1797 -6646 2743 -2920 3547 -2968 3181 -3190 3391 -2994 3393 -3002 3403 -2994 3401 -3002 3393 -3004 3393 -3002 3393 -3002 3403 -2994 3401 -3002 3393 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -3006 1799 -1394 1791 -1398 1801 -1400 3403 -3002 3401 -1398 1791 -2998 3403 -3002 1795 -1398 1801 -1400 1801 -1400 3407 -1400 1791 -2996 3405 -2994 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -3002 1799 -1402 3401 -1402 1799 -1398 1791 -3000 1799 -1402 1801 -1400 3595 -1062 1325 -884 2861 -2628 3677 -2784 3481 -2744 3683 -2912 3513 -2916 3333 -3156 3175 -3182 3191 -3190 3393 -2994 3403 -2994 3401 -3002 3393 -3004 3393 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 3405 -2998 3393 -1402 1795 -2992 3401 -3002 1801 -1400 1795 -1398 1801 -1402 3401 -1396 1793 -1398 1799 -3004 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 3401 -3002 1801 -1396 3389 -1402 1801 -1400 1801 -3002 1801 -1396 3391 -6068 219 -1318 1767 -2830 3479 -2936 3489 -2910 3509 -2922 3341 -3162 3175 -3186 3391 -2994 3393 -2998 3407 -2994 3393 -3002 3393 -3004 3401 -3002 3401 -1398 1791 -1394 +RAW_Data: 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -3002 3407 -1400 1789 -2990 3401 -3004 1799 -1402 1799 -1402 1795 -1394 3397 -1402 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 3401 -3002 1797 -1398 3401 -1396 1797 -1402 1799 -3002 3403 -2994 4221 -2588 2113 -3134 3299 -3086 3259 -3026 3409 -3002 3407 -3006 3397 -3006 3393 -3002 3395 -3002 3393 -3002 3407 -2998 3393 -3002 3393 -3004 3401 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1801 -1400 1801 -1396 1793 -1398 3401 -3002 3401 -1402 1795 -2992 3401 -3002 1801 -1396 1797 -1402 3401 -3002 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 3401 -3006 1795 -1394 3391 -1400 1801 -1400 1801 -3002 3393 -1402 1801 -3802 207 -2344 219 -1326 1669 -2836 3513 -3130 3147 -3176 3181 -3186 3391 -2994 3393 -3002 3395 -3002 3401 -2994 3401 -3004 3393 -3002 3399 -3004 3395 -2994 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -3002 1795 -1396 1795 -1402 1799 -1402 3401 -3002 3403 -1396 1791 -3000 3407 -3004 1797 -1394 1791 -1398 3401 -3002 1801 -1400 1797 -1394 3397 -3002 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 +RAW_Data: 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 3401 -2998 1805 -1396 3391 -1400 1801 -1402 1799 -1398 1791 -3000 1799 -1402 3607 -4140 2069 -2820 3359 -2938 3533 -2914 3513 -2916 3337 -3160 3173 -3184 3393 -2998 3389 -2996 3393 -3002 3393 -3002 3403 -2994 3401 -3002 3395 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -3002 1799 -1398 1797 -1400 1801 -1400 3395 -3002 3401 -1398 1791 -2998 3403 -3002 1799 -1402 1801 -1396 3391 -3002 1799 -1402 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 3399 -3002 1799 -1402 3401 -1402 1795 -1394 1797 -1400 1801 -3002 3401 -7030 2161 -3078 3391 -2994 3389 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3403 -2994 3393 -3002 3403 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -3006 1799 -1394 1791 -1398 1801 -1400 3403 -2994 3401 -1402 1799 -2994 3403 -3002 1799 -1398 1791 -1398 3403 -3002 1799 -1402 3401 -1398 1791 -2998 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1396 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -3002 1799 -1402 3393 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -3002 3795 -3692 2201 -2812 3459 -2876 3485 -3104 3309 -2934 3359 -3176 3181 -3190 3395 -2994 3393 -3006 3399 -2994 3401 -2994 3407 -3006 3389 -2994 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -3002 1801 -1398 1791 -1398 +RAW_Data: 1801 -1400 3401 -3004 3393 -1400 1801 -3002 3399 -3006 1795 -1394 1797 -1400 3401 -2994 3403 -2994 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3004 1799 -1402 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -3394 399 -3496 2327 -2200 3995 -2554 3791 -2544 3685 -2710 3691 -2920 3333 -3156 3373 -2984 3391 -2996 3389 -2996 3401 -2994 3401 -2996 3405 -3002 3397 -1398 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1801 -1398 1791 -1398 1801 -1400 3401 -3002 3395 -1400 1801 -3002 3401 -2996 1795 -1398 1799 -1402 3401 -2994 3403 -3002 3393 -3002 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 3401 -3002 3403 -3002 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 3593 -4356 1945 -2932 3435 -3014 3415 -3004 3401 -3004 3393 -3002 3401 -2994 3407 -3006 3393 -2994 3395 -3002 3401 -3002 3399 -3004 3395 -2994 3407 -1400 1789 -1392 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3407 -3004 3395 -1396 1793 -2998 3401 -3004 1799 -1398 1791 -1398 3401 -3002 3403 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 +RAW_Data: 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3002 3407 -3006 1795 -1394 1791 -1398 1801 -1400 1801 -1402 3401 -4768 389 -390 193 -2086 1793 -2908 3435 -3014 3409 -3002 3407 -3006 3401 -3002 3393 -2996 3401 -3002 3407 -2996 3395 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -3002 3395 -1400 1797 -2998 3401 -3004 1799 -1398 1791 -1398 3401 -3002 3403 -1396 1797 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 3393 -3002 3403 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3593 -1506 4053 -3028 3495 -2918 3323 -3148 3167 -3182 3185 -3192 3389 -2994 3401 -3004 3393 -3002 3401 -2994 3395 -3002 3401 -3002 3395 -3002 3393 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -3002 1801 -1400 1801 -1402 1799 -1402 3393 -3002 3401 -1402 1795 -2992 3401 -3002 1801 -1400 1801 -1398 3389 -1400 1801 -3002 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 3397 -3002 3401 -3002 1801 -1398 1795 -1402 1801 -1400 3393 -1402 1801 -5898 771 -378 2029 -2840 3559 -2776 3585 -2986 3395 -2994 3393 -3002 3403 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -2998 3407 -2994 3401 -2994 3395 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -3002 1799 -1402 1801 -1396 1791 -1398 3403 -3002 3401 -1398 1795 -3002 3403 -2994 1799 -1402 +RAW_Data: 1795 -1398 3401 -1402 1801 -3002 1795 -1394 3403 -3004 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 3403 -3002 3401 -2994 1801 -1400 1795 -1400 3405 -3006 1795 -1394 3591 -3806 2201 -2824 3453 -2878 3493 -2908 3521 -2926 3349 -3164 3177 -3190 3387 -2990 3393 -2996 3401 -3006 3397 -2994 3403 -2994 3401 -2994 3401 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1801 -3002 1795 -1398 1801 -1400 1795 -1398 3407 -3006 3393 -1398 1791 -2998 3403 -3002 1799 -1398 1791 -1398 3401 -1402 1801 -3002 3401 -2994 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 3401 -2996 3401 -3002 1795 -1394 1797 -1402 3401 -3002 3401 -5912 1929 -3004 3419 -3010 3411 -2996 3395 -2994 3401 -3002 3401 -2994 3407 -2998 3393 -2994 3403 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -3002 3403 -1396 1793 -2998 3401 -3002 1797 -1394 1795 -1402 3401 -1402 1799 -3004 3401 -1396 1793 -2998 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 +RAW_Data: 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 3401 -2994 3403 -2994 1801 -1400 1801 -1400 3395 -1400 1801 -2994 3401 -2922 1031 -1104 1767 -3090 3163 -3166 3183 -3186 3393 -2994 3395 -3002 3401 -2994 3403 -3002 3397 -3006 3393 -2996 3401 -2994 3401 -2994 3403 -3002 3399 -1404 1795 -1394 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1795 -1400 1799 -1402 1799 -1402 3407 -2996 3395 -1400 1795 -2992 3401 -3002 1801 -1402 1799 -1398 3389 -1402 1799 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 3401 -3002 3403 -2994 1799 -1398 1797 -1400 3407 -1400 1791 -1394 1797 -8408 1655 -3216 3289 -3110 3319 -3136 3159 -3176 3185 -3200 3197 -3194 3389 -2996 3393 -2994 3401 -3002 3403 -2994 3401 -2994 3403 -3002 3397 -1404 1797 -1394 1795 -1402 1795 -1398 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 1795 -1398 1801 -1402 3401 -1396 1793 -1398 1799 -3004 3405 -3006 1795 -1394 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3393 -3002 3401 -2996 1799 -1402 3401 -3002 1795 -1394 1793 -1398 4403 -1594 579 -948 2021 -2944 3439 -3026 3417 -3002 3411 -3002 3401 -3002 3393 -3004 3401 -2994 3407 -2996 3399 -3006 3393 -2994 3395 -3002 3401 -2994 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1797 -1400 1801 -1400 3401 -3004 3393 -1400 1801 -3002 3395 -3002 1799 -1402 1795 -1394 3397 -1402 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 +RAW_Data: 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 3401 -3004 3397 -3006 1795 -1394 3391 -3002 1799 -1402 3401 -7960 1797 -3000 3435 -3014 3415 -3004 3407 -3006 3393 -2994 3407 -3002 3397 -2994 3393 -3004 3393 -3002 3401 -2994 3403 -3002 3393 -3002 3393 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -3002 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3405 -1400 1793 -2990 3403 -3002 1799 -1402 1795 -1398 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -3002 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 3407 -3006 3393 -2994 1801 -1396 3391 -3006 3405 -2994 3803 -4598 1425 -3262 3367 -2984 3185 -3190 3391 -2994 3405 -3006 3393 -2996 3401 -2994 3393 -3002 3403 -2994 3401 -3002 3393 -3004 3401 -2994 3401 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -3002 1801 -1402 1799 -1402 1795 -1394 3397 -3004 3401 -1400 1801 -2994 3401 -3004 1795 -1394 3397 -3002 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 +RAW_Data: 1791 -1398 1801 -1400 3401 -3002 3403 -2994 1799 -1402 3401 -2994 3407 -1400 1791 -4212 203 -2976 1877 -3038 3175 -3164 3353 -2932 3519 -3106 3309 -3122 3147 -3168 3183 -3182 3389 -2994 3395 -3002 3393 -3002 3395 -3006 3397 -2994 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1797 -1400 1801 -1400 3403 -2998 3405 -1396 1793 -2998 3403 -3002 1799 -1398 3397 -3002 1797 -1398 1799 -1402 1799 -1402 3407 -2996 1797 -1394 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -3002 1795 -1394 3399 -1400 1801 -3002 1801 -1396 3397 -804 201 -2984 1719 -3010 3487 -2908 3515 -3134 3147 -3168 3183 -3186 3389 -2998 3399 -2994 3393 -3002 3407 -2998 3393 -2994 3401 -3004 3401 -2994 3393 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -2998 1805 -1398 1791 -1394 1797 -1400 3401 -3002 3403 -1400 1801 -2994 3401 -3002 1797 -1394 3397 -3002 1801 -1400 1801 -1402 3401 -2994 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 3393 -3002 3403 -2994 1799 -1402 3393 -1402 1799 -3004 3393 -3202 803 -3626 2215 -2456 3759 -2776 3585 -2990 3391 -2994 3393 -3002 3403 -2994 3401 -3002 3393 -3004 3393 -3006 3397 -2994 3403 -2994 3401 -3002 3395 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -3002 1799 -1402 1795 -1394 1797 -1400 3407 -3006 3393 -1398 1795 -3002 3403 -3002 1795 -1394 3397 -3002 1801 -1402 1799 -1398 3389 -1402 1799 -3002 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 +RAW_Data: 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 3403 -3002 3393 -3002 1801 -1400 3395 -1400 1801 -1396 1797 -3002 4211 -4018 1715 -2938 3433 -3018 3411 -3010 3401 -3002 3401 -3002 3407 -2998 3393 -3002 3395 -3002 3393 -3002 3393 -3004 3401 -3002 3393 -3002 3395 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -3002 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -1402 1795 -2992 3401 -3002 1801 -1400 3401 -2994 1801 -1402 3393 -3002 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 3403 -3002 3401 -3002 1795 -1394 3403 -1404 1795 -1394 1797 -1402 1799 -4574 383 -2458 2107 -3020 3263 -3042 3423 -3010 3405 -3006 3401 -3002 3407 -2998 3393 -2994 3403 -3002 3393 -3002 3393 -3004 3401 -2994 3401 -2994 3403 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -3006 1805 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1398 1791 -3000 3405 -3006 1795 -1394 3391 -3002 1799 -1402 3401 -3002 3401 -2996 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 3403 -2994 3401 -3002 3395 -3002 1799 -1398 1791 -1398 1801 -1400 3603 -838 437 -2646 1921 -2808 +RAW_Data: 3533 -2914 3495 -2868 3443 -3022 3417 -3002 3407 -3010 3401 -2998 3393 -2996 3393 -3002 3401 -2994 3403 -3006 3397 -2994 3407 -1400 1789 -1392 1797 -1402 1799 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3393 -1402 1799 -3002 3395 -3002 1795 -1398 3401 -3002 1797 -1398 3401 -1400 1797 -2994 1805 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 3403 -2994 3401 -3002 3393 -3004 1795 -1398 1799 -1402 3393 -3804 421 -1492 221 -1726 1751 -3022 3331 -3148 3177 -3180 3185 -3194 3199 -3190 3393 -3002 3395 -3002 3393 -3002 3403 -2998 3405 -2998 3397 -2996 3393 -3002 3393 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -3002 1801 -1402 1795 -1394 1797 -1400 3401 -3002 3403 -1396 1793 -2998 3401 -3004 1799 -1402 3393 -3002 1801 -1396 3399 -1400 1801 -1400 1801 -2998 1805 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 3401 -3002 3395 -3006 3397 -2994 1801 -1402 3401 -2994 3801 -416 429 -2326 1741 -2894 3367 -2982 3385 -2992 3393 -3002 3401 -2994 3403 -2994 3401 -2994 3403 -3002 3405 -2998 3393 -2996 3401 -2994 3401 -3002 3395 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -3002 1799 -1402 1801 -1400 1801 -1400 3395 -3002 3401 -1398 1791 -2998 3403 -3002 1801 -1400 3401 -2994 3403 -2998 1799 -1394 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 +RAW_Data: 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 3403 -2994 3401 -3006 3397 -2996 1799 -1398 3389 -1402 1799 -7642 1653 -2952 3443 -3022 3413 -3014 3411 -3006 3393 -3002 3407 -2996 3395 -2994 3401 -3002 3395 -2994 3401 -3002 3401 -2996 3401 -2994 3407 -1400 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3006 1801 -1392 1789 -1398 1801 -1400 3401 -3008 3405 -1396 1793 -2990 3403 -3006 1803 -1398 3389 -3002 3403 -2994 1799 -1402 3393 -3002 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 3401 -3004 3393 -3002 3401 -2994 3403 -3002 1795 -1394 4397 -596 1899 -1104 1803 -2886 3411 -3002 3401 -3002 3401 -3002 3403 -3002 3393 -3002 3403 -2998 3405 -2994 3393 -3004 3393 -2994 3401 -3002 3403 -2994 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -3002 1795 -1396 1795 -1402 1799 -1402 3401 -3002 3395 -1400 1801 -3002 3393 -3002 1801 -1398 3389 -3002 3401 -3002 3395 -3002 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 3393 -3002 3401 -3004 3393 -3002 3393 -3002 3403 -3394 2509 -408 609 -1044 209 -420 1601 -3178 3319 -3096 3253 -3022 3419 -3014 3405 -3010 3403 -2996 3395 -2994 3401 -3002 3395 -2998 3405 -2994 3401 -3000 3397 -2994 3401 -1398 1791 -1398 +RAW_Data: 1801 -1400 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1799 -1402 1801 -1396 3397 -3004 3401 -1400 1801 -2994 3401 -3004 1795 -1394 3397 -3002 3403 -3002 3393 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 3397 -3002 3403 -2994 3401 -2994 3403 -1400 1795 -2992 4001 -212 211 -424 845 -2058 1877 -3244 3181 -3188 3389 -2994 3401 -2996 3401 -2994 3401 -2994 3403 -3002 3393 -3002 3395 -3002 3401 -2994 3401 -2994 3403 -3002 3393 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -2990 1801 -1402 1799 -1402 1799 -1402 3401 -2994 3407 -1400 1791 -2992 3401 -3002 1801 -1402 3401 -2994 3401 -1402 1799 -2996 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 3397 -3002 3403 -3006 3397 -2994 3401 -1402 1801 -1396 1791 -8006 2651 -1824 3861 -2834 3417 -3014 3407 -3002 3401 -3002 3401 -3002 3395 -3002 3393 -3002 3395 -3006 3405 -2994 3393 -3004 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -2994 1801 -1402 1799 -1398 1791 -1398 3401 -3004 3401 -1400 1801 -2998 3405 -2996 1795 -1394 3397 -3006 3405 -1398 1791 -3000 3401 -2994 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 +RAW_Data: 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3407 -3004 3395 -3002 3393 -1402 1795 -2992 1799 -1402 1799 -1402 3401 -4546 1981 -2786 3481 -2908 3497 -2922 3337 -3160 3175 -3186 3389 -2994 3399 -2994 3393 -3002 3403 -3002 3393 -2994 3401 -2996 3401 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -2998 1801 -1402 1799 -1398 1797 -1400 3401 -3002 3403 -1400 1801 -2994 3401 -2994 1801 -1402 3401 -2994 3401 -1402 1795 -1394 1797 -3002 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 3401 -3002 3395 -3006 3405 -1398 1789 -2990 1799 -1402 3401 -4586 587 -746 551 -1102 2019 -2888 3497 -2864 3439 -3018 3413 -3002 3401 -3002 3403 -2994 3401 -2998 3407 -2994 3393 -3002 3393 -3004 3401 -2998 3397 -2998 3407 -1396 1791 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3393 -1402 1799 -3004 3393 -3002 1795 -1398 3401 -3004 3405 -1400 1793 -1394 1791 -1398 1801 -3002 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 3403 -2994 3401 -3006 3399 -1396 1791 -2992 3401 -3002 3603 -400 201 -1420 877 -1100 1971 -3176 3319 -2904 3511 -3132 3147 -3168 3181 -3186 3395 -2994 3393 -3002 3393 -3004 3401 -3002 3393 -2994 3403 -3002 3393 -3002 3403 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -2994 1799 -1402 1801 -1396 1797 -1400 3403 -3002 3393 -1402 1795 -2998 3403 -3002 1795 -1394 +RAW_Data: 3397 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 3395 -3002 3401 -3002 3393 -1402 1795 -2992 3401 -1400 1801 -5262 401 -2280 2005 -2706 3647 -2842 3423 -3010 3405 -3006 3401 -3002 3403 -2994 3401 -3002 3395 -3002 3401 -2994 3393 -3002 3403 -2998 3405 -2998 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -3000 1801 -1400 1801 -1400 1801 -1396 3391 -3002 3401 -1402 1799 -3002 3395 -3006 1805 -1396 3389 -1402 1801 -3002 1795 -1394 1797 -1400 3401 -3004 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -3002 3401 -3002 3407 -1404 1793 -1392 1793 -2998 1801 -1400 3603 -2686 1231 -664 1505 -3148 3313 -3126 3149 -3166 3175 -3190 3193 -3192 3393 -2994 3401 -2996 3401 -3006 3397 -2998 3399 -2994 3401 -2994 3403 -3002 3401 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3006 3397 -1402 1795 -2996 3405 -2998 1805 -1396 3391 -1400 1801 -2994 1801 -1400 3403 -2994 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 +RAW_Data: 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 3401 -3002 3407 -3006 3393 -1396 1793 -1398 1799 -3002 3403 -3602 861 -1102 1545 -442 1983 -3002 3277 -3092 3513 -3124 3147 -3168 3173 -3194 3195 -3190 3393 -3002 3395 -3006 3397 -2994 3395 -3002 3401 -2998 3405 -3000 3397 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -3002 1801 -1400 1801 -1400 1801 -1398 3401 -3006 3393 -1402 1795 -2992 3401 -3002 1801 -1400 3395 -1400 1801 -3002 1795 -1394 3399 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 3401 -3002 3401 -3002 3403 -1396 1793 -1398 1799 -1402 1799 -3004 3593 -610 3645 -2950 3285 -3122 3311 -3116 3323 -3138 3163 -3174 3187 -3194 3397 -2996 3393 -2994 3401 -2994 3403 -3002 3393 -3002 3401 -2996 3401 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 1795 -1394 3399 -1400 1801 -3002 3401 -2994 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 3401 -3002 3393 -2994 3403 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -4212 1599 -1486 1653 -3012 3347 -3168 3181 -3188 3389 -2994 3395 -2994 3401 -3002 3401 -2996 3393 -3002 3401 -3002 3395 -3002 3399 -3004 3393 -2996 3401 -1396 1797 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3399 -1404 1795 -2996 3405 -2994 1801 -1396 3391 -1400 1801 -3002 3401 -2996 3401 -3006 1799 -1392 1789 -1398 1801 -1402 1799 -1402 +RAW_Data: 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 3401 -2994 3401 -1402 1795 -2992 1801 -1400 1801 -1400 1801 -1400 1801 -1402 4617 -3624 1617 -3122 3183 -3190 3389 -2994 3403 -2998 3405 -2994 3393 -3004 3393 -3006 3397 -2994 3403 -2994 3401 -3002 3395 -3002 3401 -2994 3401 -1402 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1799 -3004 1799 -1402 1799 -1398 1791 -1398 3403 -3002 3401 -1400 1801 -3002 3393 -3004 1795 -1394 3397 -1402 1799 -3002 3403 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3004 3401 -1400 1797 -2990 1801 -1400 1801 -1402 1799 -1402 3401 -3200 601 -3982 1955 -2718 3687 -2842 3425 -3016 3405 -3006 3401 -3002 3403 -2994 3401 -3002 3393 -2996 3401 -3006 3397 -2998 3407 -2994 3393 -3006 3399 -1396 1791 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1400 3403 -2998 3405 -1398 1791 -2992 3401 -3006 1799 -1394 3391 -1400 1801 -3002 3401 -1402 1799 -1398 1791 -3000 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 +RAW_Data: 1799 -1402 1801 -1400 1801 -1400 1795 -1394 3399 -3002 3401 -1402 1795 -2998 1801 -1402 1799 -1398 3389 -3002 3603 -608 209 -3446 2219 -2994 3443 -3026 3417 -3002 3407 -3008 3399 -2998 3405 -2994 3395 -2998 3405 -2994 3395 -3002 3405 -2998 3393 -3002 3395 -2994 3401 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -3002 1801 -1402 1799 -1402 1799 -1402 3393 -3002 3403 -1396 1797 -2994 3401 -3002 1801 -1398 3393 -1406 1799 -1402 1795 -3000 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 3389 -3002 3403 -1400 1801 -3002 1795 -1394 1797 -1400 3403 -1400 1801 -5432 663 -1710 1925 -2726 3617 -3010 3419 -3006 3401 -3002 3401 -2998 3407 -2994 3393 -3002 3403 -2994 3401 -3002 3393 -3004 3393 -2994 3401 -3002 3403 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1398 1797 -3002 1801 -1400 1795 -1398 1801 -1400 3403 -2994 3401 -1402 1795 -2992 3401 -3002 1801 -1400 3401 -1398 1791 -1398 1801 -3002 1801 -1400 3401 -3004 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -3002 3401 -1402 1799 -3002 1801 -1402 3393 -2994 1801 -1400 3603 -3858 2219 -3186 3253 -3036 3417 -3006 3405 -3002 3403 -2998 3405 -2994 3401 -2996 3401 -2998 3405 -2994 3395 -2994 3401 -3002 3395 -3002 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -2998 1799 -1394 1797 -1402 1799 -1402 3401 -2998 3405 -1398 1791 -2992 3401 -3002 1801 -1400 3403 -1400 1795 -1396 1795 -3002 3403 -3002 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 +RAW_Data: 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 3405 -3002 3397 -1398 1791 -2992 1801 -1400 3401 -3002 3395 -6072 1197 -792 1865 -2724 3513 -2896 3455 -3034 3419 -3002 3401 -3002 3401 -3004 3401 -2994 3401 -2998 3407 -2994 3401 -2994 3403 -2994 3401 -3002 3393 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1799 -1402 1801 -1400 3401 -3000 3405 -1396 1793 -2990 3407 -3006 1795 -1394 3397 -1402 1799 -1402 1801 -3002 3393 -1400 1797 -2998 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1797 -1400 3401 -3004 3393 -1400 1801 -3002 1795 -1394 3399 -1400 1801 -3002 4189 -3552 1729 -2986 3429 -3022 3419 -3006 3393 -3002 3399 -3004 3395 -2994 3401 -3002 3395 -3002 3393 -3006 3397 -3000 3405 -2994 3401 -2994 3395 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 1801 -1400 3395 -1400 1801 -1400 1795 -1394 1797 -3002 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 3395 -3002 3393 -1402 1799 -3002 1797 -1394 +RAW_Data: 3397 -1402 1799 -1402 1799 -7326 2401 -2060 4155 -2504 3723 -2690 3661 -2838 3421 -3010 3411 -3002 3401 -3002 3401 -3002 3403 -2994 3401 -3002 3401 -2996 3393 -2994 3401 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -3004 1799 -1398 1795 -1402 1801 -1400 3401 -3004 3393 -1400 1801 -2994 3401 -3004 1795 -1394 3397 -1402 1799 -1402 1799 -1398 1791 -3000 3401 -3002 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3002 3403 -1396 1791 -3000 3401 -3004 1799 -1398 1791 -1398 3601 -4120 1733 -2886 3559 -2960 3351 -3094 3255 -3044 3421 -3010 3401 -3006 3407 -3002 3393 -3002 3393 -3004 3401 -3002 3393 -3002 3395 -3002 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -2998 1801 -1400 1801 -1398 1791 -1398 3401 -3002 3403 -1400 1795 -2992 3401 -3002 1801 -1400 3403 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -2994 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3393 -1402 1801 -3002 3393 -3002 1801 -1396 3399 -5588 365 -1116 2145 -3134 3189 -3190 3395 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -3002 3401 -2998 3405 -2996 3393 -1400 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 1801 -1396 3391 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -2992 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 +RAW_Data: 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 3401 -3002 3393 -1402 1795 -3000 3401 -3002 3393 -3004 3593 -3932 2743 -2594 3595 -3002 3393 -3002 3395 -3002 3401 -2994 3401 -2996 3401 -3002 3401 -2994 3403 -2994 3401 -2994 3403 -2998 3405 -2994 3393 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -3000 1799 -1402 1799 -1402 1801 -1400 3401 -2996 3401 -1400 1797 -2990 3403 -3002 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 3393 -3004 3401 -1396 1793 -2998 3401 -3004 3401 -1396 1793 -7038 2817 -3032 3167 -3182 3385 -2996 3393 -2994 3401 -3002 3399 -3006 3393 -2994 3403 -2994 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3407 -1404 1795 -1394 1793 -1398 1799 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3395 -3002 3401 -1398 1795 -3002 3403 -2994 3401 -3002 1801 -1396 1793 -1398 1799 -1402 1801 -1400 3401 -3004 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -1402 1795 -2990 3403 -1400 1801 -3002 1801 -1396 3591 -4298 1767 -2654 3559 -2912 3513 -2914 3491 -2868 3443 -3022 3417 -3002 3407 -3006 3393 -3002 +RAW_Data: 3393 -3002 3403 -2994 3407 -3004 3395 -2994 3399 -1404 1795 -1394 1797 -1400 1801 -1400 1801 -1396 1793 -2998 1801 -1400 1801 -1402 1795 -1398 3401 -3006 3399 -1400 1795 -2992 3401 -3002 3403 -2994 1799 -1402 1801 -1396 1791 -1398 3403 -3002 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -3002 3395 -1396 1797 -3002 3407 -1404 1795 -2992 3401 -3400 1713 -1100 3677 -3172 3377 -2982 3187 -3190 3393 -2996 3401 -2994 3401 -3002 3395 -3002 3399 -3004 3393 -2996 3401 -3002 3393 -3002 3395 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -2998 1801 -1402 1799 -1398 1791 -1398 3401 -3002 3403 -1400 1795 -2992 3401 -3002 3403 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 3401 -3002 3403 -1396 1791 -3000 3401 -1402 1799 -1402 1795 -3000 3801 -1120 181 -920 553 -1654 1653 -3052 3481 -2942 3489 -2908 3299 -3120 3335 -3164 3175 -3182 3389 -2996 3393 -3002 3401 -2996 3393 -3002 3401 -2994 3403 -3002 3393 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -3002 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 3403 -3006 1599 -1592 1789 -1398 3401 -3004 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 +RAW_Data: 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3401 -1398 1797 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -3402 1057 -3748 1469 -3298 3149 -3174 3175 -3190 3393 -2994 3395 -3002 3393 -3002 3403 -3002 3393 -3002 3399 -3004 3395 -2994 3401 -2994 3403 -2994 3401 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3395 -1400 1801 -3002 3401 -2994 3403 -2994 1799 -1402 1801 -1400 3393 -3004 3393 -3002 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -3002 3393 -1402 1801 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 3601 -3262 435 -874 1833 -3302 3235 -3018 3405 -3002 3407 -2998 3393 -3002 3393 -3002 3399 -3006 3393 -2994 3403 -3002 3393 -3002 3393 -3008 3397 -3002 3393 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -3002 1801 -1402 1799 -1402 1801 -1396 3403 -3004 3395 -1396 1793 -2998 3401 -3004 3401 -2994 1801 -1400 1795 -1394 3399 -1400 1801 -3002 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1801 -1400 3401 -2994 3403 -1396 1797 -1400 1801 -3002 1795 -1396 1795 -1402 3401 -7588 1923 -3068 3393 -2994 3403 -2994 3407 -3004 3399 -2998 3393 -2994 3393 -3004 3401 -2994 3401 -3002 3403 -2994 3393 -3002 3403 -2998 3409 -1400 1789 -1394 1795 -1402 1801 -1400 +RAW_Data: 1801 -1400 1797 -2998 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3403 -1400 1801 -2994 3407 -2996 3395 -3002 1795 -1394 1797 -1400 3401 -1402 1801 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 3401 -3002 3401 -1398 1791 -1398 1801 -3002 1801 -1400 3401 -2996 3607 -1728 833 -1396 2303 -2880 3581 -2986 3391 -2994 3393 -3002 3395 -3002 3401 -2998 3405 -2996 3393 -2994 3401 -3002 3403 -2994 3401 -3002 3395 -3002 3393 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3407 -1400 1791 -2992 3401 -3002 3407 -2998 1795 -1394 3389 -3002 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 3407 -2996 3395 -1400 1795 -1398 1801 -3002 1801 -1400 3395 -1400 1801 -7606 1737 -3220 3235 -3022 3417 -3002 3407 -3004 3403 -2994 3401 -2994 3407 -3006 3393 -2994 3393 -3004 3401 -2994 3393 -3002 3403 -3002 3393 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3407 -1400 1789 -2990 3401 -3002 3403 -3002 1799 -1398 3389 -3002 1801 -1402 3401 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 +RAW_Data: 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3401 -1402 1795 -1394 1797 -3002 3401 -3002 1801 -1398 4195 -1886 1105 -442 1765 -3046 3269 -3160 3341 -3122 3291 -3112 3319 -3140 3163 -3176 3185 -3190 3391 -2994 3393 -2998 3411 -2998 3393 -3002 3393 -3004 3393 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 3401 -2994 3401 -1402 1795 -2992 3401 -3002 3401 -3004 1795 -1394 3397 -3002 3401 -3004 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 3401 -3002 3407 -1400 1791 -1394 1797 -3002 3401 -3002 3395 -5516 1583 -3012 3489 -2910 3305 -3120 3337 -3164 3173 -3186 3191 -3190 3399 -3004 3395 -2994 3401 -2994 3403 -2994 3401 -2994 3401 -3004 3393 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -3002 1801 -1400 1795 -1394 1797 -1402 3405 -3006 3393 -1402 1795 -2992 3401 -3002 3401 -3002 1797 -1394 3397 -3002 3407 -1404 1795 -2992 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 3401 -3002 3401 -1398 1791 -1398 1801 -3002 3401 -1398 1795 -3002 3595 -3624 415 -206 2483 -2414 3585 -3002 3401 -2994 3401 -3004 3393 -2994 3401 -3002 3403 -2998 3411 -2996 3395 -2994 3393 -3002 3393 -3004 3401 -2994 3401 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 3407 -3004 3399 -1400 1789 -2990 3403 -3002 3401 -3002 1795 -1394 3403 -1404 1795 -2992 1801 -1400 1801 -1400 1801 -1402 1795 -1394 +RAW_Data: 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 3389 -3004 3401 -1400 1801 -1402 1799 -2994 3403 -1400 1795 -1398 1801 -8014 1843 -2840 3389 -2994 3403 -2994 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -2994 3401 -2994 3407 -3006 3393 -2994 3401 -2998 3399 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 3405 -3006 3393 -1398 1791 -3000 3405 -3006 3393 -2994 1801 -1398 3389 -1402 1799 -3002 3403 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 3401 -2994 3401 -1398 1795 -1402 1801 -1400 1801 -2994 1801 -1400 1801 -1400 3395 -4724 1853 -2864 3547 -2976 3181 -3186 3391 -2994 3393 -2994 3407 -3006 3399 -2996 3399 -2998 3393 -3002 3399 -3006 3393 -2994 3401 -2994 3403 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1396 3391 -3002 3401 -1402 1799 -3004 3393 -3002 3401 -2994 1801 -1402 3393 -1400 1797 -1398 1799 -3002 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 +RAW_Data: 1799 -1402 1799 -1402 1795 -1398 1801 -1400 3403 -2994 3401 -1402 1795 -1398 1801 -1400 1801 -3002 1795 -1394 3397 -5708 365 -1470 9113 -1824 3823 -2614 3609 -3002 3403 -3002 3401 -3002 3401 -2994 3403 -3002 3393 -3002 3399 -3006 3393 -2994 3401 -3004 3393 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3393 -1402 1801 -3002 3393 -3006 3397 -2996 1799 -1398 3397 -1402 1799 -1402 1799 -1398 1791 -3000 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 3397 -3002 3407 -1404 1795 -1394 1791 -1398 1801 -3002 3401 -2996 3601 -1690 629 -2154 1905 -2832 3651 -2830 3423 -3006 3401 -3002 3401 -3002 3395 -3002 3401 -3002 3395 -3002 3405 -2998 3393 -2996 3401 -3002 3407 -2996 3395 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1797 -3002 1801 -1400 1795 -1394 1797 -1402 3401 -3002 3401 -1402 1795 -2996 3409 -2998 3393 -2994 3403 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 3401 -3002 3393 -1402 1799 -1398 1791 -1398 1801 -3002 3401 -1402 1795 -3600 639 -3748 1839 -2644 3729 -2756 3567 -2982 3391 -2990 3393 -2994 3403 -3002 3401 -2994 3401 -2994 3403 -3002 3393 -3002 3403 -2994 3393 -3002 3401 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1797 -1400 1801 -1400 3401 -3004 3397 -1404 1797 -2990 3403 -3002 3405 -2998 3393 -2996 1799 -1398 1795 -1402 3401 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 +RAW_Data: 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 3401 -2996 3401 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -3000 1801 -1400 3801 -4494 1987 -2568 3839 -2822 3413 -3002 3403 -3002 3401 -3002 3401 -3002 3407 -3010 3393 -2994 3395 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -3002 3403 -1396 1793 -2998 3401 -3004 3393 -3002 3401 -3002 1797 -1394 3389 -3002 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 3401 -3002 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -3002 3405 -8042 1841 -2856 3557 -2932 3531 -2910 3509 -2922 3345 -3160 3173 -3188 3395 -2996 3391 -2994 3401 -3002 3399 -2998 3393 -3002 3401 -2994 3395 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3407 -1400 1791 -2992 3401 -3002 3401 -3002 3403 -2994 1795 -1398 3407 -1404 1795 -2992 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 3395 -3002 3393 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -2994 3603 -4452 +RAW_Data: 1771 -2854 3567 -2986 3389 -2992 3393 -3002 3393 -3004 3393 -3002 3401 -2994 3395 -3002 3401 -3002 3393 -3004 3393 -3002 3401 -2994 3403 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1795 -1400 3401 -3002 3393 -1402 1799 -3004 3393 -3002 3401 -2994 3403 -2994 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3407 -1404 1795 -1394 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -7856 8207 -2522 3741 -2764 3573 -2988 3393 -2994 3393 -3004 3393 -3002 3393 -3002 3403 -2994 3401 -3006 3399 -2994 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1799 -1402 1801 -1400 3401 -2996 3401 -1400 1797 -2990 3403 -3002 3401 -3002 3401 -2994 3395 -3002 3401 -2998 1805 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 3401 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 3601 -4768 1587 -3096 3397 -2990 3395 -2994 3401 -3002 3395 -3006 3397 -2994 3401 -2996 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -3002 3393 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3393 -1402 1801 -3002 3401 -2998 3399 -2994 3401 -2994 3401 -1402 1795 -3000 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 +RAW_Data: 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -1402 1799 -2994 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3403 -5196 383 -1652 1837 -3050 3375 -2986 3393 -2996 3393 -3002 3401 -2994 3403 -2998 3405 -2994 3395 -3002 3405 -2998 3393 -2996 3401 -3002 3393 -3006 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -3000 1801 -1400 1801 -1400 1801 -1400 3395 -3002 3407 -1400 1791 -2992 3401 -3002 3401 -3002 3395 -3002 3393 -1402 1799 -1398 1795 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 3403 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 3401 -2994 3603 -836 655 -2854 1731 -2816 3487 -2910 3517 -2910 3481 -2856 3443 -3016 3407 -3006 3401 -3006 3399 -2994 3393 -3006 3397 -2996 3393 -3002 3401 -3002 3395 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1400 3395 -3002 3401 -1398 1791 -3000 3401 -3002 3401 -2994 3407 -1404 1795 -2992 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 3403 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 1799 -1398 3389 -1402 1799 -7638 2209 -2584 3689 -2704 3511 -2934 3347 -3168 3179 -3186 3389 -2994 3395 -2994 3401 -3002 3393 -3004 3393 -3002 +RAW_Data: 3401 -2994 3403 -2994 3401 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -3002 1801 -1398 1791 -1398 1799 -1402 3401 -3002 3395 -1400 1801 -3002 3407 -3000 3399 -2994 3393 -1402 1795 -2992 1799 -1402 3401 -3002 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1799 -3004 1799 -1402 1795 -1394 1797 -1400 3401 -3004 1799 -1402 3601 -4312 1887 -2802 3527 -2906 3523 -3128 3147 -3164 3181 -3188 3389 -2994 3395 -2994 3401 -3002 3393 -3004 3393 -3002 3393 -3002 3403 -3002 3393 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3403 -1396 1797 -3002 3407 -2996 3395 -2994 3401 -1402 1795 -2998 3395 -3006 1803 -1398 1791 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -1398 1791 -3000 1799 -1402 1799 -1402 1801 -1400 3401 -2996 3401 -7934 8393 -2332 3759 -2774 3583 -2990 3389 -2994 3403 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -2994 3403 -3002 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -2994 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -1398 1791 -2998 3403 -3006 3405 -2998 3397 -1398 1791 -3000 3401 -1402 1799 -2994 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 +RAW_Data: 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -1400 1801 -3006 1805 -1396 1791 -1398 1801 -1402 3401 -1396 1797 -3002 3603 -4584 1767 -2612 3777 -2734 3539 -2912 3505 -2916 3331 -3156 3173 -3182 3187 -3190 3393 -2996 3401 -3002 3401 -2994 3395 -3002 3401 -2994 3407 -1400 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -2994 1799 -1402 1801 -1396 1797 -1400 3403 -3002 3401 -1398 1791 -2990 3403 -3002 3401 -3002 3401 -1398 1791 -1398 1801 -3006 1805 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -1400 1801 -3002 1801 -1396 1797 -1400 1801 -1400 3395 -1400 1801 -1398 1795 -8110 2015 -2632 3843 -2818 3415 -3002 3407 -3004 3401 -2996 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -2998 3405 -2994 3393 -3004 3393 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1396 1797 -1400 1801 -1402 3401 -2994 3401 -1402 1801 -3002 3393 -2994 3401 -3002 3395 -1400 1801 -1402 1799 -2994 3407 -2998 1795 -1394 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 3397 -1400 1801 -3002 1801 -1396 1793 -1398 3401 -3002 1795 -1398 1801 -1400 3603 -4032 1885 -2658 3649 -2852 3473 -2950 3571 -2718 3513 -2898 3455 -3040 3421 -3010 3401 -3006 3411 -2998 3393 -3002 3395 -3002 3393 -3002 3393 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -3008 1799 -1394 1791 -1398 1801 -1400 3401 -3004 3401 -1396 +RAW_Data: 1793 -3002 3407 -2994 3401 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 3401 -1402 1801 -2998 1803 -1398 1791 -1394 3399 -3002 1799 -1402 3401 -8194 21409 -2410 3595 -3000 3401 -3002 3403 -3006 3405 -2994 3395 -3002 3401 -2994 3401 -3002 3395 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -2990 1801 -1402 1799 -1402 1799 -1402 3401 -2994 3407 -1404 1795 -2992 3401 -3002 3395 -3006 3397 -1398 1791 -1394 1797 -1400 1801 -1400 1801 -3002 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 3393 -1402 1795 -3000 1799 -1402 1799 -1398 3397 -3002 3403 -3002 3593 -4590 8471 -2416 3813 -2802 3403 -3002 3401 -3002 3401 -3004 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -3002 3401 -2994 3393 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -3004 1795 -1398 1799 -1402 1795 -1398 3401 -3004 3401 -1396 1793 -2998 3401 -3004 3401 -1396 1793 -2998 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 +RAW_Data: 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 3397 -1402 1801 -3006 1803 -1398 1791 -1398 3401 -3004 3393 -1400 1801 -6470 1853 -2954 3275 -3044 3425 -3014 3405 -3004 3401 -3002 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -2998 3405 -2994 3395 -3006 3397 -1398 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1801 -1398 1791 -1398 1801 -1400 3401 -3002 3403 -1396 1791 -3000 3401 -3002 3403 -1396 1793 -2998 1801 -1400 1801 -1402 1799 -1402 3401 -2994 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 3393 -1402 1799 -3000 1803 -1398 1791 -1398 3401 -1402 1799 -3004 1795 -1394 3797 -4442 2001 -2426 3829 -2818 3415 -3014 3401 -3002 3393 -3002 3395 -3002 3401 -3002 3393 -2996 3401 -2994 3401 -3002 3395 -3002 3401 -3002 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -3002 1799 -1398 1791 -1398 1801 -1400 3403 -3002 3393 -1402 1799 -3006 3399 -2994 3401 -1398 1791 -2998 1801 -1402 1799 -1402 3393 -3002 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 3403 -1400 1801 -3002 1801 -1396 1791 -1398 3403 -1400 1801 -3002 3401 -8088 1813 -2902 3441 -3020 3417 -3010 3411 -3004 3399 -3002 3397 -2994 3395 -3002 3393 -3002 3393 -3004 3401 -2998 3405 -2994 3395 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -3002 1795 -1396 1795 -1402 1799 -1402 3401 -3002 3403 -1400 1795 -2992 3401 -3002 3403 -1400 1795 -2992 1801 -1400 1801 -1400 3403 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 +RAW_Data: 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -1402 1799 -3002 1797 -1394 1795 -1402 3401 -1402 1799 -1402 1795 -2992 3601 -4130 1967 -2648 3605 -2874 3687 -2732 3527 -2902 3507 -2930 3349 -3168 3173 -3186 3395 -2998 3397 -2994 3395 -3002 3401 -2994 3401 -3000 3405 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -3002 3401 -1402 1795 -2992 1799 -1402 3401 -3002 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 3397 -1400 1801 -3002 1801 -1400 1797 -1398 3401 -1400 1801 -1402 1795 -1394 1797 -3402 1061 -2794 2197 -2242 4043 -2320 3991 -2722 3497 -2880 3643 -2830 3415 -3010 3401 -3002 3401 -3002 3403 -3002 3401 -3002 3399 -3006 3393 -2994 3393 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1799 -1402 1801 -1400 3407 -2998 3393 -1396 1793 -3002 3407 -3002 3393 -1398 1795 -3002 1801 -1402 3401 -3002 3393 -3002 1797 -1394 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1398 +RAW_Data: 1799 -1398 1797 -1400 3401 -1402 1795 -2992 1801 -1400 3401 -3002 1801 -1402 1799 -1398 1791 -1398 3601 -2170 4255 -2912 3537 -2960 3375 -2986 3189 -3192 3393 -3002 3401 -2994 3403 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -3002 3395 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1795 -1396 1795 -1402 1799 -1402 3401 -3006 3399 -1396 1791 -3000 3401 -3002 3403 -1400 1795 -2992 1801 -1400 3401 -1402 1795 -3000 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 3401 -1402 1799 -3002 1797 -1398 3401 -3002 1801 -1396 1793 -1398 3401 -8220 2607 -1888 3817 -2618 3609 -3002 3403 -3002 3401 -3002 3401 -3006 3399 -2994 3401 -2994 3403 -2998 3405 -2994 3393 -3004 3401 -2998 3405 -1398 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -2996 1799 -1402 1799 -1398 1797 -1400 3401 -2996 3401 -1400 1801 -2994 3401 -3004 3393 -1400 1801 -3002 1795 -1394 3399 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 3401 -1398 1791 -3004 1803 -1402 3393 -3002 1795 -1396 3397 -3002 3401 -4962 8235 -2580 3581 -2994 3403 -2994 3401 -2994 3401 -3004 3393 -3002 3393 -3002 3403 -3002 3393 -2994 3403 -3006 3397 -2998 3405 -1398 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1795 -1402 1801 -1400 3401 -2996 3401 -1400 1801 -3002 3395 -3002 3397 -1404 1797 -2990 3403 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 +RAW_Data: 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 3401 -1398 1791 -3000 1799 -1402 3401 -2998 1805 -1398 3389 -1400 1801 -8008 2567 -1896 3829 -2822 3413 -3014 3407 -3002 3401 -2994 3401 -3002 3395 -3002 3399 -3004 3395 -3002 3399 -3004 3393 -2996 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -3002 1801 -1402 1799 -1402 1795 -1394 3397 -3004 3401 -1400 1797 -2990 3401 -3004 3401 -1400 1801 -2998 3397 -3004 1795 -1394 3397 -3002 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 3403 -1404 1795 -2992 1799 -1402 3401 -2998 3407 -2998 1799 -1394 3791 -4154 1719 -2816 3391 -3170 3285 -3136 3323 -3106 3317 -3134 3147 -3164 3173 -3188 3389 -2994 3395 -3002 3393 -3002 3401 -3002 3395 -3002 3393 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3006 1801 -1394 1791 -1398 1801 -1400 3401 -3002 3403 -1396 1791 -3000 3401 -3002 3403 -1396 1793 -2998 3401 -3008 3405 -2994 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1801 -3002 1799 -1402 3401 -2994 3403 -2994 3405 -8152 1939 -2656 3635 -2818 3409 -3014 3405 -3002 3403 -2994 3401 -2994 +RAW_Data: 3401 -3004 3393 -3002 3401 -2998 3211 -3198 3393 -2994 3395 -3002 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -2990 1801 -1400 1801 -1402 1799 -1398 3397 -3002 3401 -1402 1795 -3000 3401 -2994 3403 -1400 1795 -2992 3401 -3006 3407 -1396 1791 -2996 1805 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -1402 1799 -2994 1801 -1402 3401 -3002 3393 -1398 1797 -3002 3601 -4348 1837 -2790 3659 -2830 3417 -3016 3405 -3002 3401 -3002 3403 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3006 3205 -1598 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -3000 1799 -1398 1797 -1400 1801 -1396 3399 -3002 3401 -1398 1795 -3002 3403 -3002 3393 -1402 1799 -3002 3395 -1400 1801 -2998 1805 -1396 1791 -1398 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 3399 -1400 1801 -2994 1801 -1400 3401 -3002 3395 -1400 1801 -1398 1791 -8144 1783 -2880 3443 -3018 3419 -3004 3403 -3002 3401 -3002 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3403 -2994 3401 -3002 3393 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1795 -3000 1799 -1402 1799 -1402 1801 -1400 3393 -3004 3401 -1396 1793 -2998 3403 -3002 3401 -1400 1797 -2990 3407 -1404 1795 -2992 3401 -3002 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 +RAW_Data: 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 3397 -1402 1801 -3002 1799 -1398 3397 -1402 1799 -3004 1795 -1394 1797 -1400 4407 -3438 2423 -2508 3661 -2838 3421 -3020 3405 -3002 3401 -3002 3403 -3006 3397 -2994 3393 -3004 3401 -2994 3401 -3002 3403 -2994 3401 -3002 3399 -1400 1791 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3401 -1398 1791 -2998 3403 -3002 3401 -1398 1791 -2998 3403 -1400 1795 -1398 1801 -3002 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 3407 -1400 1791 -2992 1801 -1400 3401 -1402 1801 -2994 1799 -1402 3401 -5710 183 -2022 2537 -1884 3815 -2610 3601 -3002 3401 -3002 3403 -3002 3393 -3002 3403 -2994 3405 -3006 3393 -2996 3393 -3002 3401 -2994 3403 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3407 -1400 1791 -2996 3405 -2994 3403 -1396 1791 -3000 3401 -1402 1795 -1394 1797 -1400 1801 -3002 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 3397 -1402 1799 -3008 1803 -1398 3395 -1404 1795 -2990 3403 -3002 3593 -4580 1655 -3024 3321 -2950 3563 -2974 3385 -2992 3397 -2998 3393 -3000 3397 -3002 3393 -2996 3401 -3006 3397 -2994 3403 -3002 3399 -3004 3399 -1400 1789 -1392 1797 -1402 1799 -1402 1799 -1402 1801 -3002 +RAW_Data: 1795 -1394 1791 -1398 1801 -1400 3403 -3002 3401 -1402 1799 -2994 3403 -2994 3401 -1402 1799 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -1400 1795 -3000 1801 -1400 3401 -1402 1801 -2994 3401 -1400 1797 -7502 3329 -1154 3985 -2602 3601 -3008 3397 -2994 3393 -3002 3407 -2998 3393 -2998 3407 -2994 3401 -2994 3401 -2996 3401 -2994 3401 -2994 3403 -1400 1801 -1396 1797 -1402 1799 -1398 1797 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1400 3403 -3002 3401 -1402 1795 -2992 3401 -3002 3401 -1398 1791 -1398 1801 -3002 1799 -1402 1801 -1396 3389 -3004 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 3403 -1400 1801 -3002 1795 -1394 3399 -1400 1801 -1400 1801 -2994 1801 -1400 4395 -3776 14743 -2408 3811 -2802 3401 -3002 3401 -3002 3403 -3002 3393 -3002 3401 -2996 3401 -3002 3401 -2994 3395 -3002 3393 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -2990 1801 -1400 1801 -1402 1799 -1398 3397 -3002 3407 -1404 1795 -2992 3407 -2996 3395 -1400 1795 -1398 1801 -3002 1801 -1396 3391 -3002 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 +RAW_Data: 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1799 -1398 3397 -1402 1799 -3002 1797 -1394 3397 -1402 1799 -1402 1799 -2996 3401 -3996 385 -3102 2063 -3036 3275 -3042 3425 -3020 3405 -3006 3411 -2996 3395 -3002 3393 -3002 3395 -3002 3393 -3002 3401 -3002 3395 -3002 3393 -3002 3403 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -3002 1799 -1402 1801 -1396 1791 -1398 3403 -3002 3407 -1404 1595 -3194 3407 -2994 3393 -1402 1795 -1394 1797 -3002 1799 -1402 3401 -1398 1795 -3004 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 3403 -1400 1801 -3002 1795 -1394 3391 -1400 1801 -1400 1801 -1400 1801 -3002 3603 -1478 645 -1724 2035 -3064 3173 -3182 3187 -3190 3393 -2996 3401 -3002 3393 -3002 3403 -2994 3401 -2994 3407 -2998 3393 -3002 3393 -3002 3403 -2994 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -2998 1801 -1402 1799 -1402 1795 -1394 3397 -3002 3403 -1400 1795 -3000 3401 -3002 3395 -1400 1801 -1396 1797 -3002 3407 -2998 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 3407 -1400 1791 -2992 1799 -1402 3401 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -8088 1731 -3044 3437 -3028 3261 -3072 3287 -3118 3295 -3118 3323 -3148 3167 -3180 3185 -3190 3395 -2994 3399 -3004 3393 -2996 3401 -2994 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -2996 1799 -1402 1799 -1402 1801 -1396 3397 -2996 3401 -1400 1801 -3006 3403 -2998 3397 -1400 +RAW_Data: 1793 -1394 1795 -3004 3401 -3002 3393 -2994 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 3393 -1402 1801 -3002 3393 -3002 1801 -1396 1797 -1402 1799 -1402 1795 -1398 3401 -4926 8515 -2468 3839 -2822 3413 -3010 3407 -3004 3403 -3002 3393 -3002 3393 -3004 3401 -2994 3393 -3002 3403 -3002 3401 -2994 3395 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -3002 1799 -1402 1795 -1398 1801 -1400 3403 -2994 3401 -1402 1799 -2994 3403 -3002 3393 -1402 1799 -1398 1795 -3004 3401 -1396 1793 -2998 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 3403 -1396 1791 -3000 3401 -3002 1801 -1400 1797 -1394 1795 -1402 3407 -8138 1617 -2850 3563 -2976 3385 -2990 3395 -2994 3401 -2994 3401 -2996 3401 -3002 3401 -2994 3403 -2994 3401 -2994 3407 -3006 3393 -2994 3407 -1400 1791 -1394 1797 -1400 1801 -1402 1799 -1398 1795 -3004 1799 -1402 1795 -1398 1801 -1400 3401 -2996 3401 -1400 1797 -2990 3403 -3002 3401 -1400 1801 -1398 1791 -2998 3403 -1400 1801 -1400 1801 -2994 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 +RAW_Data: 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 3401 -1402 1801 -3002 3397 -3006 1795 -1394 1793 -1398 3401 -3002 3601 -4378 1989 -2806 3493 -2902 3511 -2930 3349 -3166 3183 -3186 3389 -2994 3403 -2994 3407 -3004 3395 -2994 3393 -3002 3401 -3004 3393 -3002 3393 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -3002 1801 -1398 1795 -1402 1801 -1400 3393 -3002 3403 -1396 1793 -3002 3405 -2996 3405 -1400 1793 -1394 1795 -1402 1801 -3002 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1801 -3002 3401 -2994 1801 -1400 1801 -1402 3393 -1400 1801 -7422 9169 -1802 3795 -2600 3611 -3002 3401 -3006 3405 -2996 3393 -3002 3407 -2996 3395 -2994 3401 -3002 3403 -2994 3401 -2994 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1400 3401 -2996 3401 -1396 1797 -3002 3403 -3002 3393 -1400 1801 -1398 1791 -1398 1801 -3002 1799 -1402 3401 -2994 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 3393 -1402 1795 -3000 3401 -3002 1795 -1394 3399 -3002 1799 -1402 3801 -1286 649 -2066 2205 -3008 3427 -3012 3407 -3006 3393 -2994 3393 -3002 3403 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -3002 1799 -1402 1801 -1396 1797 -1400 3403 -2994 3401 -1402 1795 -2998 3403 -3002 3393 -1402 1799 -1398 1791 -1398 1801 -3002 3401 -3002 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1795 -1398 +RAW_Data: 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -1400 1801 -3002 3393 -3002 1797 -1394 3397 -3002 3401 -7732 14869 -2460 3833 -2818 3409 -3004 3401 -3002 3401 -3002 3403 -3002 3405 -2998 3393 -3004 3393 -2994 3407 -3008 3199 -1596 1789 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -2994 1801 -1400 1801 -1400 1801 -1398 3397 -3002 3401 -1398 1791 -3000 3401 -2994 3401 -1402 1801 -1400 1801 -1400 1795 -2992 3401 -1402 1801 -3002 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3407 -1400 1791 -2992 3401 -3004 1799 -1402 3407 -1400 1789 -2988 3403 -3830 2193 -2986 3375 -2944 3501 -3050 3235 -3018 3409 -3002 3403 -3002 3401 -3002 3401 -3002 3395 -3002 3393 -3006 3207 -3194 3399 -3004 3393 -1398 1791 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -3002 1799 -1398 1791 -1398 1801 -1400 3403 -3002 3401 -1398 1795 -3002 3395 -3002 3393 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -3006 1601 -1592 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 3399 -1400 1801 -3002 3401 -2994 +RAW_Data: 1801 -1400 3403 -1400 1795 -1396 1795 -6110 417 -1290 1655 -3016 3535 -2958 3375 -2982 3187 -3194 3399 -2996 3395 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -3002 3395 -3002 3407 -2996 3393 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -3000 1799 -1402 1801 -1396 1791 -1398 3403 -3002 3401 -1402 1799 -2994 3407 -2998 3393 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 3401 -2994 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 3395 -1400 1801 -2994 3401 -3002 3395 -3002 1799 -1398 1791 -1398 3603 -200 965 -3206 1811 -2896 3423 -3010 3405 -3006 3401 -3002 3395 -3002 3393 -3002 3403 -2994 3401 -3002 3401 -2994 3403 -2994 3393 -3002 3407 -2998 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3403 -1396 1791 -3000 3401 -3002 3403 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -3002 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -1402 1795 -2990 3403 -3002 3401 -3002 1801 -1396 3391 -7600 1899 -3004 3287 -3106 3315 -3134 3159 -3176 3185 -3190 3391 -2994 3393 -3002 3395 -3002 3401 -2994 3401 -3004 3393 -3002 3407 -2996 3395 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1396 1797 -3002 1795 -1398 1801 -1400 1801 -1402 3401 -2994 3401 -1402 1795 -3000 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -3000 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 +RAW_Data: 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 3403 -1404 1795 -2992 3401 -3004 3393 -3002 3401 -2994 3403 -4206 2011 -3272 3159 -3176 3181 -3186 3195 -3190 3393 -3002 3395 -3002 3401 -2998 3405 -2996 3405 -2998 3393 -2994 3403 -2994 3401 -3006 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -3002 1801 -1400 1801 -1400 1801 -1396 3391 -3002 3401 -1402 1799 -3002 3403 -1396 1797 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 3407 -1404 1597 -3190 3401 -2994 3403 -3002 3393 -1402 1795 -7316 8443 -2572 3577 -2988 3393 -3002 3393 -3004 3393 -3006 3405 -2994 3395 -3002 3393 -3002 3395 -3002 3401 -3002 3393 -3006 3399 -1396 1793 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1797 -1400 1801 -1402 3401 -2998 3397 -1398 1791 -3000 3401 -1400 1801 -3002 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 3395 -3002 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1793 -1398 3401 -1400 1801 -3002 3401 -3004 3393 -1400 1801 -2994 1801 -1400 3603 -4490 1839 -2642 3731 -2746 3573 -2988 3389 -2990 3393 -3000 +RAW_Data: 3405 -2994 3393 -3002 3403 -2994 3401 -2994 3401 -2996 3401 -2994 3401 -3002 3403 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -3000 1801 -1400 1801 -1396 1793 -1398 3401 -3002 3401 -1402 1795 -3004 3405 -1396 1793 -2990 1801 -1400 1801 -1402 1799 -1402 1799 -1398 3397 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 3401 -1400 1801 -3002 3393 -3002 3403 -1396 1793 -2998 3401 -8350 1743 -2940 3389 -3000 3397 -2994 3393 -3004 3401 -2994 3401 -2994 3403 -3002 3401 -2994 3401 -2996 3401 -2994 3401 -3002 3407 -2998 3393 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -2990 1801 -1402 1799 -1402 1799 -1402 3401 -2998 3407 -1396 1791 -2992 3401 -1402 1801 -3002 1799 -1398 1797 -1400 1801 -1400 1795 -1396 3397 -1400 1801 -3002 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 3393 -1402 1799 -3002 3395 -3002 3407 -1400 1789 -1392 1797 -3006 3605 -4930 1985 -2864 3367 -2982 3185 -3192 3393 -2994 3393 -3002 3403 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -2998 3207 -3194 3393 -3002 3403 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -2992 1801 -1400 1801 -1400 1801 -1400 3407 -2998 3393 -1398 1791 -3000 3401 -1400 1801 -3002 1795 -1398 1801 -1402 1799 -1398 3389 -3002 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 +RAW_Data: 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 3403 -1400 1801 -3002 3393 -3002 3407 -1400 1789 -1392 1797 -1402 1799 -8070 9613 -1418 3825 -2614 3609 -3002 3401 -3004 3401 -3002 3401 -3002 3403 -2994 3393 -3002 3401 -2996 3401 -3002 3401 -2994 3403 -1396 1797 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -3002 1799 -1402 1795 -1398 1801 -1400 3403 -2994 3401 -1398 1791 -2998 3403 -1400 1801 -3002 1801 -1400 1795 -1398 1801 -1402 3401 -2994 3401 -2996 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 3403 -1400 1801 -3002 3393 -1402 1795 -3000 1799 -1402 1799 -1398 1791 -1398 3603 -4754 8207 -2562 3569 -2984 3389 -2996 3401 -2994 3401 -2994 3403 -3002 3401 -2994 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -2990 1801 -1402 1799 -1402 1799 -1402 3401 -3002 3395 -1400 1795 -2992 3401 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 3403 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 3401 -1402 1799 -3002 3395 -1400 1801 -2994 1801 -1400 1801 -1398 3389 -7746 8811 -2430 3817 -2810 3411 -3002 3401 -3002 3401 -3002 3395 -3002 3401 -2994 3403 -2994 3401 -3006 3397 -2996 3393 -3002 3401 -1402 1795 -1394 1797 -1400 1801 -1400 +RAW_Data: 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1799 -1402 3401 -2994 3403 -1400 1801 -3002 3401 -1398 1791 -3000 1799 -1402 1801 -1396 1797 -1400 3403 -1396 1791 -1398 1801 -3002 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 3393 -1402 1799 -3004 3393 -1400 1797 -2998 1801 -1400 3403 -3002 3993 -3076 14679 -2816 3619 -2804 3401 -3002 3403 -3002 3393 -3002 3401 -3004 3393 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3393 -1402 1799 -2994 3403 -1396 1797 -3002 1801 -1400 1801 -1396 3391 -3002 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 3395 -1400 1801 -3002 3393 -1402 1799 -3002 1801 -1398 3389 -1400 1801 -6990 1657 -3042 3285 -3122 3305 -3118 3323 -3152 3167 -3174 3187 -3190 3389 -2996 3401 -2994 3401 -3002 3395 -3002 3401 -2994 3393 -3004 3401 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1400 1801 -1398 3389 -3006 3405 -1398 1791 -3000 3401 -1402 1795 -2990 1801 -1402 1799 -1402 3401 -3002 1795 -1394 3399 -3002 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 +RAW_Data: 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 3401 -1400 1801 -3006 3399 -1396 1797 -3002 3393 -3002 1797 -1394 3597 -4444 1939 -2940 3439 -3026 3413 -3006 3407 -3002 3397 -3006 3393 -2996 3393 -3002 3393 -3006 3207 -3194 3393 -2994 3403 -3002 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -2996 3401 -1400 1801 -3002 3393 -1398 1791 -3004 1803 -1402 1795 -1398 3403 -3002 3401 -2998 1799 -1394 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 3393 -1402 1801 -3002 3393 -1402 1799 -3002 3399 -3006 3393 -7892 1731 -2682 3593 -2994 3403 -3002 3393 -3002 3393 -3004 3401 -2994 3401 -3002 3403 -2994 3393 -3002 3399 -3006 3393 -2994 3401 -3006 3399 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3006 3397 -1402 1795 -2992 3401 -1402 1799 -3002 1795 -1400 1799 -1402 3401 -2994 3401 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 3401 -1400 1797 -2994 3407 -1400 1795 -3000 3401 -1402 1795 -2992 3601 -4720 1955 -2804 3439 -3022 3413 -3002 3401 -3002 3403 -3002 3401 -2994 3403 -3002 3393 -3002 3393 -3002 3403 -2994 3401 -3002 3395 -3002 3393 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1400 1797 -1394 1795 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -1402 1799 -3002 1801 -1402 1795 -1394 3397 -1402 +RAW_Data: 1799 -3002 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 3401 -1400 1801 -2994 3403 -1400 1801 -2998 3411 -1400 1789 -1392 1797 -7942 14895 -2618 3611 -2810 3401 -3002 3401 -3002 3403 -3002 3393 -3002 3401 -2996 3401 -3002 3393 -2998 3407 -2994 3393 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3403 -1400 1795 -2992 3401 -1402 1799 -3008 1599 -1594 1795 -1402 3401 -1402 1795 -2992 3401 -3002 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 3401 -1402 1799 -2994 3403 -1400 1795 -1398 1801 -3002 1795 -1400 1799 -1402 3801 -1294 1075 -840 2397 -2992 3435 -3022 3249 -3164 3313 -2942 3519 -3068 3247 -3026 3413 -3010 3401 -3002 3403 -3002 3393 -3002 3403 -3002 3393 -3002 3393 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -3004 1799 -1398 1791 -1398 1801 -1400 3401 -3004 3401 -1396 1793 -2998 3403 -1400 1801 -3002 1795 -1394 1797 -1400 3403 -1400 1801 -1400 1795 -3000 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 +RAW_Data: 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 3401 -1402 1801 -2994 3401 -1402 1795 -1398 1799 -3004 1795 -1394 3397 -7240 3691 -1402 3855 -2834 3419 -3018 3413 -3002 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -3002 3407 -2996 3399 -1404 1597 -1590 1791 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1402 1795 -2992 3401 -1400 1801 -3002 1801 -1396 1793 -1398 3405 -1404 1797 -1394 1795 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 3403 -1396 1797 -3002 3401 -1402 1795 -1394 1797 -3002 3407 -3004 3595 -4610 1539 -3058 3381 -2988 3193 -3194 3393 -2996 3401 -3002 3393 -3002 3403 -2994 3407 -3004 3395 -2994 3393 -3002 3401 -2996 3401 -2994 3401 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -3002 1801 -1402 1799 -1402 1795 -1398 3401 -3002 3403 -1396 1791 -3000 3401 -1402 1801 -2994 1799 -1402 3401 -3002 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1799 -3004 3401 -1396 1793 -1398 1799 -3002 3403 -1400 1801 -6986 367 -734 1837 -2952 3531 -2896 3279 -3050 3435 -3018 3401 -3002 3401 -3008 3405 -2998 3205 -3198 3399 -2994 3401 -2998 3399 -2994 3393 -3002 3401 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3393 -1400 1801 -3002 3395 -1400 1801 -3002 1795 -1394 3397 -3004 1799 -1402 1799 -1398 3395 -3004 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 +RAW_Data: 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 3399 -1400 1801 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1400 3793 -4322 1655 -3012 3323 -3148 3167 -3186 3189 -3192 3389 -2994 3401 -2996 3401 -3002 3393 -3002 3403 -2994 3401 -2998 3407 -2994 3401 -2994 3393 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3004 1795 -1398 1799 -1402 1801 -1396 3397 -3004 3401 -1396 1793 -2998 3403 -1400 1801 -3002 1795 -1394 3397 -3002 1801 -1402 3401 -2994 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 3401 -1402 1801 -2994 3401 -1398 1795 -1402 1799 -1402 1801 -2994 3401 -3594 835 -1436 377 -1140 1711 -3242 3159 -3176 3181 -3190 3193 -3200 3201 -3202 3197 -3196 3393 -2994 3407 -2996 3395 -2994 3401 -3002 3403 -2994 3401 -2994 3407 -1404 1597 -1592 1791 -1398 1801 -1402 1799 -1402 1795 -3000 1799 -1402 1801 -1400 1801 -1396 3391 -3002 3401 -1396 1797 -3002 3403 -1400 1801 -2994 1801 -1400 3401 -3002 1797 -1394 3397 -1402 1799 -3002 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 +RAW_Data: 1801 -1402 1799 -1402 1799 -1398 1791 -1398 3401 -1402 1801 -3006 3397 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3006 3799 -1526 441 -1060 2475 -2980 3315 -2928 3499 -3076 3249 -3030 3417 -3014 3411 -3006 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -3000 3209 -3202 3197 -1596 1787 -1392 1797 -1400 1801 -1402 1799 -1402 1799 -2996 1799 -1402 1801 -1400 1801 -1396 3399 -3002 3401 -1396 1793 -2998 3403 -1396 1797 -3002 1801 -1400 3401 -3002 3395 -2994 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 3401 -1402 1801 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -7480 27707 -2512 3729 -2756 3573 -2984 3385 -2994 3399 -2990 3393 -3006 3205 -3192 3393 -3002 3393 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -3002 1799 -1402 1801 -1396 1791 -1398 3403 -3002 3401 -1400 1797 -2998 3403 -1400 1795 -2992 1801 -1400 3401 -3008 3205 -3194 3393 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 3403 -1400 1801 -1400 1795 -3000 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 3803 -4446 1433 -3026 3349 -3164 3173 -3188 3189 -3198 3197 -3194 3395 -3002 3393 -3002 3403 -2994 3401 -2994 3401 -3004 3401 -2998 3397 -2994 3403 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 3401 -2994 3401 -1402 1799 -3004 3393 -1400 1797 -2990 1801 -1400 3403 -3002 3401 -1398 1791 -2998 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 +RAW_Data: 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 1801 -1400 3393 -7770 21481 -2430 3819 -2810 3401 -3002 3401 -3002 3403 -3002 3401 -3002 3393 -3002 3407 -2998 3393 -3002 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -3000 1801 -1400 1801 -1396 1791 -1400 3401 -3002 3401 -1402 1799 -3002 3395 -1400 1801 -2994 1801 -1400 3395 -3002 3401 -1402 1795 -1394 1795 -3004 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1398 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 3403 -1400 1801 -1396 1797 -3002 1801 -1400 1801 -1398 1795 -1402 3401 -3002 3795 -3852 2121 -3066 3329 -3156 3167 -3174 3189 -3192 3393 -3002 3393 -3004 3393 -3002 3401 -2994 3403 -2994 3401 -2994 3401 -3004 3401 -2994 3401 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -3002 1801 -1402 1799 -1402 1795 -1394 3397 -3004 3401 -1400 1801 -3002 3393 -1402 1801 -2994 1799 -1402 3401 -1398 1795 -2996 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 3401 -1402 1795 -1394 1797 -3002 1801 -1400 1801 -1400 1795 -1396 3397 -1400 1801 -7618 +RAW_Data: 15035 -2418 3813 -2810 3403 -3002 3401 -3002 3401 -2996 3401 -3002 3393 -3002 3403 -3002 3393 -2994 3401 -3004 3401 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -2996 1805 -1400 1795 -1398 1801 -1402 3401 -2994 3401 -1402 1795 -2992 3401 -1402 1799 -3002 1801 -1402 3393 -1400 1801 -2994 1801 -1400 3403 -2994 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1795 -1398 1801 -1400 1801 -1400 1801 -1402 3393 -1400 1801 -1402 1795 -2990 1801 -1402 1799 -1402 3401 -3002 1795 -1394 3399 -4894 8261 -2584 3593 -3002 3395 -3002 3393 -3002 3403 -2994 3401 -2994 3401 -2996 3405 -3006 3393 -2994 3395 -3002 3401 -2994 3403 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3401 -1398 1791 -2998 3403 -1400 1801 -2998 1805 -1396 3395 -1404 1795 -2992 3401 -3006 1805 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 3403 -1396 1797 -1400 1801 -3002 1795 -1394 1797 -1402 3401 -3006 3397 -7586 1729 -3040 3443 -3022 3417 -3004 3401 -3002 3401 -3002 3403 -2994 3401 -3002 3393 -3000 3405 -2994 3401 -2994 3403 -2998 3205 -3198 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1396 3395 -3006 3393 -1402 1799 -3002 3395 -1400 1801 -3002 1795 -1394 3399 -1400 1801 -3002 3401 -1398 1791 -3000 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1398 1797 -1400 +RAW_Data: 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 3403 -1400 1801 -1400 1801 -3002 1801 -1396 1793 -1398 3401 -1400 1801 -3002 3803 -3690 8945 -2004 3805 -2802 3407 -3006 3401 -3002 3393 -3002 3395 -3002 3401 -2998 3211 -3198 3393 -2994 3395 -3002 3401 -3002 3393 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -3008 1803 -1398 1791 -1394 1797 -1400 3401 -3004 3401 -1400 1801 -3002 3393 -1402 1801 -2994 1799 -1402 3401 -1398 1797 -1396 1797 -3002 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 3401 -1402 1795 -1394 1797 -3002 1801 -1400 1801 -1396 3399 -1400 1801 -1400 1801 -8146 15111 -2438 3821 -2814 3409 -3004 3401 -3002 3401 -3002 3403 -2994 3401 -3002 3393 -3002 3403 -2994 3401 -2994 3407 -1404 1597 -1592 1793 -1398 1799 -1402 1799 -1402 1801 -2994 1801 -1400 1801 -1396 1797 -1400 3407 -3006 3393 -1398 1791 -3000 3401 -1400 1801 -2994 1801 -1400 3403 -1400 1795 -1394 1797 -3002 3401 -3004 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3403 -1400 1795 -1394 1797 -3002 1801 -1400 3407 -3006 1595 -1592 1789 -1398 3603 -4270 1767 -2816 3481 -2910 3319 -3118 3293 -3244 3229 -3014 3409 -3006 3407 -3002 3407 -3004 3395 -2994 3401 -2994 3401 -2996 3401 -3002 3399 -1404 +RAW_Data: 1595 -1594 1797 -1400 1801 -1400 1797 -1398 1799 -3002 1801 -1398 1791 -1398 1801 -1400 3401 -3006 3207 -1596 1791 -2992 3401 -1402 1801 -3002 1795 -1398 3401 -1402 1795 -1398 1801 -1400 1801 -3002 1795 -1394 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 3401 -1402 1795 -1394 1797 -3002 1801 -1400 3407 -3004 1597 -1594 3393 -8044 8285 -2600 3601 -3004 3401 -2994 3401 -2994 3403 -3002 3407 -2996 3393 -3004 3393 -3002 3399 -3004 3395 -2994 3401 -3002 3399 -1404 1597 -1592 1793 -1398 1799 -1402 1799 -1402 1801 -3002 1799 -1398 1797 -1396 1797 -1400 3407 -3006 3393 -1398 1791 -3000 3405 -1404 1597 -3190 1801 -1400 3403 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3403 -1396 1791 -1400 1799 -3002 1801 -1400 3403 -3002 3393 -3002 4003 -3520 1767 -3000 3331 -3084 3243 -3026 3409 -3002 3407 -3010 3405 -2998 3397 -2996 3401 -2994 3401 -2994 3403 -3002 3401 -2994 3403 -2994 3401 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3393 -1402 1801 -2994 3407 -1404 1793 -2988 3403 -3002 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 +RAW_Data: 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1394 3397 -1402 1799 -1402 1799 -3004 1799 -1402 3393 -3002 3393 -1402 1801 -4796 787 -2262 1869 -2942 3419 -3010 3405 -3006 3393 -3004 3393 -3002 3401 -2994 3403 -2994 3401 -3002 3393 -3004 3401 -2994 3401 -3002 3399 -3010 3193 -1598 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1799 -1402 3401 -3002 3395 -1400 1795 -3000 3401 -1402 1795 -2992 3401 -3002 1801 -1400 1801 -1400 1797 -1394 3397 -3002 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 3401 -1398 1791 -1398 1801 -3002 1799 -1402 3393 -1402 1799 -3004 1799 -1398 4199 -2960 2227 -2872 3355 -3174 3183 -3186 3389 -2994 3395 -3002 3393 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -2994 3401 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -1402 1799 -3002 3395 -3002 1795 -1398 1801 -1400 3407 -2998 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 3397 -1402 1799 -1402 1799 -3004 1799 -1398 3389 -1402 1799 -3002 3403 -7954 27839 -2554 3573 -2988 3389 -2994 3393 -3002 3395 -3002 3399 -3004 3395 -2994 3393 -3002 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -3002 1799 -1398 1791 -1398 1801 -1400 3403 -3002 3393 -1400 1801 -3002 3395 -1400 +RAW_Data: 1801 -2994 3401 -3002 1797 -1394 1795 -1402 3401 -1402 1799 -3002 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 3401 -1402 1795 -1394 1797 -3002 1801 -1400 3401 -1398 1797 -1400 1801 -3002 3393 -4822 15921 -1406 3809 -2610 3601 -3002 3403 -3002 3401 -3002 3401 -3004 3393 -2994 3407 -3004 3395 -2994 3407 -2996 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3399 -1404 1595 -3190 3403 -1400 1801 -3002 3393 -3006 1601 -1594 3389 -3002 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 3403 -1396 1791 -1398 1801 -3002 1801 -1400 3403 -1396 1791 -1398 1801 -1402 1799 -6668 1963 -2566 3673 -2838 3421 -3014 3411 -3006 3393 -3002 3393 -3004 3401 -2994 3407 -2996 3395 -3002 3393 -3002 3395 -3002 3405 -2998 3399 -1400 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -3002 1799 -1398 1791 -1398 1801 -1400 3403 -3002 3393 -1402 1799 -3002 3395 -1400 1801 -3002 3393 -3002 1797 -1394 3397 -3002 3401 -3002 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1402 +RAW_Data: 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 3407 -1400 1791 -1394 1797 -3002 3401 -3002 1797 -1394 1795 -1402 1801 -1400 3803 -4242 1899 -2672 3763 -2746 3509 -2864 3439 -3026 3417 -3002 3401 -3008 3405 -3002 3393 -2994 3403 -3002 3405 -2998 3393 -2996 3401 -2994 3401 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -3002 1797 -1394 1795 -1402 1801 -1400 3401 -3002 3403 -1396 1793 -2998 3401 -1398 1797 -3002 3401 -3002 1795 -1394 3399 -1400 1801 -3002 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 3401 -1398 1791 -1398 1801 -3002 3401 -3002 1795 -1394 1797 -1402 3401 -7512 21165 -2482 3841 -2832 3413 -3010 3401 -3002 3403 -3002 3401 -3002 3407 -2998 3393 -3002 3393 -3002 3403 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -2994 1801 -1400 1795 -1398 1801 -1400 3403 -2994 3401 -1402 1799 -3002 3395 -1400 1797 -2990 3401 -3004 1799 -1402 3401 -1398 1791 -1398 1799 -3004 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1795 -1398 3403 -1400 1801 -1400 1797 -2998 3395 -3002 1799 -1402 3401 -3002 3399 -3900 661 -442 1987 -2846 3333 -3156 3167 -3182 3185 -3192 3393 -3002 3393 -3004 3393 -3002 3407 -2996 3395 -2994 3401 -3002 3401 -2996 3393 -3002 3401 -1402 1795 -1398 1795 -1398 1801 -1402 1799 -1402 1799 -2996 1799 -1402 1799 -1402 1801 -1396 3389 -3004 3401 -1400 1801 -2994 3401 -1402 1801 -2994 3407 -3004 3193 -3196 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 +RAW_Data: 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 3407 -1400 1789 -1392 1797 -3002 3401 -3002 1801 -1402 3393 -1400 1801 -5854 1449 -3028 3481 -2910 3519 -2928 3493 -2856 3433 -3014 3415 -3010 3405 -2998 3397 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3407 -1404 1595 -1588 1795 -1402 1799 -1402 1799 -1402 1801 -2994 1799 -1402 1801 -1396 1791 -1398 3403 -3002 3401 -1402 1799 -2994 3403 -1400 1801 -2994 3393 -3002 3403 -3002 1795 -1394 3397 -3002 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 3403 -1400 1801 -1400 1801 -2994 3401 -2996 3401 -3002 1801 -1396 4197 -2116 2985 -3040 3495 -2924 3333 -3160 3173 -3184 3189 -3198 3189 -3196 3393 -3002 3393 -3002 3407 -2998 3393 -3002 3395 -3002 3401 -2994 3393 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -3002 1799 -1402 1795 -1398 1801 -1400 3403 -2994 3401 -1400 1801 -3002 3395 -1400 1801 -2994 3407 -2996 3395 -3002 3401 -2994 1801 -1396 1797 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 3395 -1400 1801 -1400 1795 -2992 3401 -3006 +RAW_Data: 3207 -3194 3407 -3798 1471 -2756 1731 -2764 3451 -3026 3423 -3014 3401 -3002 3393 -3008 3401 -2998 3393 -3002 3403 -2994 3401 -2994 3395 -3002 3401 -3002 3393 -3002 3395 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1402 3405 -2998 3393 -1398 1797 -3002 3393 -1400 1801 -3002 3395 -3002 3401 -2998 3209 -1602 1591 -3184 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 3401 -1400 1801 -1398 1791 -3000 3401 -3002 3401 -1398 1795 -3002 3603 -3528 2573 -2892 3567 -2982 3387 -2990 3393 -2994 3407 -3006 3393 -2994 3401 -2996 3393 -3002 3401 -3002 3403 -2994 3401 -2994 3399 -3006 3393 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1402 1795 -1394 3403 -3004 3401 -1398 1791 -3000 3401 -1402 1795 -3000 3401 -3006 3403 -1400 1791 -2992 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 3401 -1398 1795 -1402 1801 -3006 3197 -3194 3393 -1402 1801 -1400 1801 -7732 2037 -2694 3601 -2994 3401 -2994 3403 -2994 3401 -3002 3403 -2994 3393 -3002 3401 -2996 3401 -3002 3399 -3004 3399 -2998 3399 -2996 3395 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -3000 1799 -1402 1801 -1400 1801 -1396 3399 -3002 3393 -1402 1799 -3002 3395 -1396 1797 -3006 3397 -3002 3395 -1400 1801 -3002 3393 -3002 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 +RAW_Data: 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1398 1801 -1400 3403 -1396 1797 -1400 1801 -3002 3393 -1402 1795 -3004 1803 -1398 1791 -1398 3403 -4578 1767 -2596 3785 -2526 3699 -2874 3441 -3022 3419 -3010 3401 -3002 3401 -3002 3403 -3002 3393 -3002 3403 -2994 3401 -2994 3401 -3004 3401 -1396 1793 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -3002 1801 -1400 1801 -1396 1793 -1398 3401 -3002 3407 -1404 1595 -3192 3401 -1396 1793 -2998 3403 -3002 3393 -1402 1799 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 3401 -1396 1797 -1402 1799 -3002 3395 -1400 1801 -3002 1795 -1398 3401 -7634 8423 -2600 3601 -3002 3403 -3002 3401 -3002 3403 -2994 3401 -3002 3393 -3002 3395 -3002 3401 -2994 3403 -2994 3401 -3002 3393 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3004 1799 -1402 1799 -1398 1791 -1398 3403 -3002 3401 -1396 1793 -2998 3403 -1400 1801 -3002 3407 -2996 3395 -1396 1791 -1398 1801 -1402 1799 -3002 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 3401 -1402 1795 -1398 1801 -3002 3401 -1398 1795 -3004 3401 -2994 3601 -5084 8583 -2458 3835 -2822 3413 -3010 3403 -3002 3401 -3002 3395 -3002 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3403 -3002 +RAW_Data: 3393 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -1402 1799 -3002 3403 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3407 -1404 1595 -1594 1791 -3000 3405 -1404 1597 -3190 3407 -1404 1597 -7988 1673 -3042 3323 -3148 3363 -2976 3185 -3194 3399 -2998 3393 -3002 3401 -2994 3395 -3006 3397 -2994 3403 -2994 3407 -3004 3393 -2996 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -1402 1799 -3002 3403 -1396 1791 -3000 1801 -1400 1801 -1400 3403 -3002 1795 -1394 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 3393 -1400 1801 -1398 1791 -3000 3401 -1400 1801 -1400 1801 -3002 1795 -1396 3597 -4754 1619 -2850 3567 -2982 3389 -2990 3395 -3002 3393 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -3002 3407 -2996 3395 -2998 3397 -2994 3403 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -3002 1799 -1402 1801 -1400 1801 -1400 3395 -3002 3401 -1398 1791 -2998 3403 -1400 1801 -2994 3401 -1402 1795 -2992 1799 -1402 3401 -3002 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 +RAW_Data: 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 3403 -1400 1795 -1394 1797 -3002 3401 -1402 1795 -1398 1801 -3002 3401 -7874 2005 -2696 3647 -2838 3423 -3002 3401 -3002 3401 -3004 3401 -3006 3397 -3002 3395 -2994 3401 -3002 3395 -3002 3401 -2994 3407 -2998 3397 -1400 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1398 3401 -3006 3393 -1398 1791 -3000 3401 -1402 1799 -2994 3403 -1400 1795 -2992 1801 -1400 3401 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 3401 -1396 1797 -1402 1799 -2994 3403 -1400 1795 -1396 1795 -1402 1799 -3004 3801 -4428 14941 -2434 3819 -2810 3415 -3004 3403 -3002 3405 -2998 3393 -3000 3397 -3002 3393 -3002 3395 -3002 3393 -3002 3403 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -3004 1803 -1398 1791 -1398 1801 -1400 3407 -2998 3393 -1402 1799 -3002 3395 -1400 1801 -2994 3401 -1398 1797 -3002 3401 -2998 1805 -1396 1793 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 3395 -1400 1801 -1400 1801 -2994 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -7354 2019 -2886 3413 -3002 3401 -3002 3403 -3002 3401 -3002 3393 -3004 3393 -3002 3401 -2994 3403 -3002 3407 -2996 3395 -2994 3393 -3002 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1795 -1402 1801 -1400 3401 -3004 +RAW_Data: 3205 -1600 1591 -3188 3403 -1400 1801 -3002 3407 -1400 1791 -2992 3401 -3002 3401 -2994 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 3401 -1402 1801 -1396 1791 -1398 1801 -3006 1805 -1396 1793 -1398 1799 -1402 1801 -1400 3401 -1476 3223 -2870 3519 -2934 3559 -2974 3187 -3190 3389 -2994 3395 -3002 3401 -2994 3403 -3002 3393 -3002 3401 -2996 3401 -2994 3407 -3004 3395 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -3000 1801 -1400 1801 -1396 1797 -1400 3403 -3002 3401 -1398 1791 -3000 3401 -1400 1801 -3002 3393 -1402 1801 -3002 3393 -1402 1799 -3002 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3403 -1400 1801 -1396 1793 -1398 1799 -3002 1801 -1402 1799 -1402 1795 -1394 3397 -7212 2943 -1710 3963 -2582 3587 -2990 3389 -2994 3403 -2994 3401 -2994 3401 -3004 3393 -3002 3401 -3002 3399 -3006 3393 -2994 3401 -2996 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1396 1797 -1402 3401 -3002 3393 -1402 1801 -2994 3401 -1402 1795 -2990 3403 -1400 1801 -3002 3401 -1398 1791 -1398 1801 -3002 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 +RAW_Data: 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 3401 -1400 1801 -1402 1795 -1394 1797 -3002 1799 -1402 1801 -1400 3401 -3002 3795 -412 421 -3620 8315 -2598 3797 -2810 3401 -3002 3403 -3002 3401 -2994 3403 -3002 3393 -3002 3393 -3002 3395 -3002 3407 -2996 3395 -3002 3393 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3395 -1400 1801 -3002 3393 -1402 1799 -3002 3395 -1400 1801 -1400 1797 -2990 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 3401 -1402 1795 -1394 1797 -1400 1801 -3002 1799 -1402 1801 -1400 3395 -1400 1801 -7154 1989 -2800 3335 -3110 3489 -3052 3239 -3024 3411 -3006 3393 -3002 3401 -3002 3395 -3006 3397 -2994 3407 -3002 3197 -3194 3395 -3002 3393 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3393 -1402 1801 -3002 3393 -1402 1799 -3002 3395 -1400 1801 -1396 1797 -3006 1605 -1596 3391 -3002 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1797 -1398 1799 -1402 3401 -1402 1795 -1394 1795 -1402 1801 -3002 1799 -1402 3401 -2994 1801 -1402 3393 -4578 1987 -2610 3585 -2746 3685 -2908 3493 -2922 3337 -3160 3375 -2982 3389 -2990 3395 -3002 3393 -3002 3395 -3002 3401 -2994 3401 -3002 3395 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -3006 1805 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1398 1791 -3004 3405 -1396 1793 -2998 3403 -1400 1801 -1396 +RAW_Data: 1793 -2998 3401 -3004 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 3401 -1400 1797 -1394 1795 -1402 1801 -3002 1799 -1402 3401 -2994 3401 -7890 1857 -2976 3401 -3002 3401 -3002 3403 -2994 3401 -3006 3397 -2996 3405 -3002 3197 -3194 3395 -3002 3205 -3198 3395 -2994 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -2996 1799 -1402 1799 -1402 1795 -1394 3403 -3006 3393 -1402 1799 -2998 3207 -1596 1791 -2996 3405 -1402 1795 -1398 1801 -3006 3397 -1398 1791 -3000 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 3403 -1400 1801 -1400 1797 -1394 1795 -3002 1801 -1402 3401 -1400 1801 -3006 3397 -4660 9619 -1422 3829 -2818 3415 -3014 3405 -3002 3401 -3002 3395 -2994 3401 -3002 3395 -3002 3401 -2994 3393 -3004 3401 -3002 3393 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -3002 1801 -1398 1795 -1402 1801 -1400 3393 -3002 3403 -1396 1793 -2998 3401 -1402 1801 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -3006 1803 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 +RAW_Data: 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 3401 -1402 1795 -1394 1797 -1400 1801 -3002 1801 -1400 3403 -1396 1791 -1398 1801 -4378 191 -1688 551 -1116 1659 -3106 3309 -3094 3259 -3038 3421 -3012 3405 -3006 3401 -2994 3403 -2994 3401 -3002 3395 -3002 3401 -2994 3401 -2994 3403 -3002 3393 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -3002 1801 -1402 1795 -1394 1795 -1402 3401 -3002 3403 -1396 1791 -3000 3401 -1402 1799 -3004 3401 -1396 1793 -1398 1799 -1402 1801 -3002 3401 -2994 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 3397 -1402 1799 -1402 1801 -1400 1801 -3002 3393 -3002 1797 -1394 1795 -1402 3401 -4704 2681 -1944 3813 -2610 3603 -3002 3401 -3002 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3401 -2994 3403 -3002 3393 -3002 3401 -2998 3399 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -3000 1801 -1400 1795 -1398 1801 -1402 3401 -2994 3401 -1402 1799 -2996 3401 -1400 1797 -2990 3407 -1404 1801 -1396 1793 -1398 1799 -1402 1799 -3004 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 3397 -1400 1801 -1402 1795 -1394 1797 -3002 3401 -3002 1801 -1400 3395 -8456 8271 -2610 3601 -3002 3401 -3002 3403 -2994 3401 -3002 3395 -3002 3401 -2994 3393 -3006 3399 -2994 3401 -2994 3403 -3002 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -3002 1805 -1396 1797 -1402 1799 -1402 3401 -2998 3205 -1598 1791 -2992 3401 -1402 1799 -3004 3401 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 +RAW_Data: 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 3397 -1402 1799 -1402 1801 -1400 1801 -3002 3393 -3002 3395 -3002 3601 -3880 2553 -2922 3559 -2976 3381 -2988 3389 -2994 3401 -3004 3393 -2994 3401 -3002 3203 -3198 3397 -2994 3403 -2994 3401 -3002 3407 -2996 3395 -1396 1797 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -3002 1801 -1400 1801 -1396 1793 -1398 3401 -3002 3401 -1402 1795 -2992 3401 -1400 1801 -1402 1799 -3006 1601 -1594 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 3389 -1400 1801 -1402 1799 -1402 1799 -3004 3393 -3002 3393 -1402 1801 -4436 421 -3014 1755 -3064 3393 -2996 3401 -2998 3205 -3194 3403 -2998 3397 -2994 3403 -3002 3393 -2994 3401 -3002 3395 -3002 3401 -2994 3403 -2994 3401 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3395 -1400 1801 -3002 3393 -1402 1799 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1400 1801 -1400 3395 -3002 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 +RAW_Data: 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 3401 -1402 1799 -1402 1799 -1402 1801 -2994 3401 -1398 1795 -3006 1605 -1598 4387 -1926 735 -564 1715 -3138 3393 -2994 3403 -3006 3197 -3194 3393 -3004 3401 -3002 3393 -3002 3395 -2994 3401 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -3002 1801 -1400 1801 -1400 1801 -1402 3393 -3006 3205 -1598 1791 -2992 3401 -1400 1801 -1402 1795 -2998 1801 -1402 1799 -1398 1791 -1398 3401 -3002 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 3401 -1400 1801 -1398 1791 -1398 1799 -3004 3401 -1400 1797 -2998 3401 -7510 1767 -2584 3763 -2696 3659 -2834 3419 -3010 3409 -3002 3401 -3002 3403 -3006 3397 -2994 3401 -2996 3401 -3002 3393 -3002 3403 -2994 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -2990 1801 -1402 1799 -1402 1799 -1402 3407 -3004 3195 -1596 1791 -2992 3401 -1402 1801 -1400 1801 -2994 1801 -1400 1801 -1400 1795 -1398 3403 -1400 1801 -2994 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 3401 -1402 1799 -1402 1795 -1394 1797 -3002 3401 -1402 1799 -1402 1795 -2992 3601 -4408 9397 -1404 3805 -2602 3601 -3002 3401 -3006 3407 -2998 3405 -2994 3395 -3006 3397 -2994 3395 -3002 3401 -2994 3401 -2994 3403 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1402 3393 -3006 3397 -1402 1795 -2992 3401 -1400 1801 -1402 1795 -2998 1801 -1402 1799 -1398 3389 -3002 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 +RAW_Data: 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 3401 -1396 1797 -1402 1799 -1402 1799 -2996 3401 -1400 1797 -1394 1795 -1402 1799 -7782 2983 -1722 3737 -2764 3575 -2986 3389 -2994 3395 -2994 3401 -3002 3403 -2994 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3403 -2994 3401 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -2994 1801 -1400 1801 -1402 1795 -1394 3397 -3002 3403 -1400 1795 -3004 3205 -1598 1791 -1394 1797 -3002 1801 -1400 1801 -1400 3401 -3004 3393 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 3401 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -3002 1801 -1400 1801 -1402 1799 -1398 3789 -3630 9707 -1196 3995 -2602 3601 -3004 3401 -3002 3393 -3002 3403 -2994 3407 -3004 3193 -3200 3397 -2994 3401 -2996 3401 -3002 3393 -1402 1799 -1402 1795 -1398 1795 -1394 1797 -1402 1799 -3002 1801 -1402 1799 -1402 1799 -1398 3397 -3002 3407 -1400 1791 -2992 3401 -1402 1801 -1400 1795 -3000 1801 -1400 1795 -1398 3403 -1400 1795 -2992 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 +RAW_Data: 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -2998 1801 -1400 1801 -1402 3401 -7046 2191 -2780 3479 -2930 3487 -3108 3315 -2934 3349 -3166 3383 -2990 3389 -2994 3395 -3002 3401 -2998 3399 -2994 3401 -3002 3393 -3004 3393 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1402 1795 -2996 3409 -1400 1789 -1394 1795 -3004 1799 -1402 1799 -1402 3407 -1404 1595 -1594 1791 -3000 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 3393 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -3002 1801 -1400 3401 -2996 3401 -5646 14913 -2416 3815 -2810 3401 -3002 3401 -3006 3407 -2994 3401 -2998 3205 -3196 3201 -3194 3393 -3008 3205 -3194 3393 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -3004 1799 -1402 1799 -1402 1795 -1398 3401 -3002 3395 -1400 1797 -2998 3401 -1402 1801 -1396 1791 -3000 1801 -1400 3401 -3004 1795 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1795 -1398 3395 -1400 1801 -6192 2021 -2460 3747 -2764 3583 -2986 3389 -2994 3395 -3002 3393 -3002 3403 -2994 3405 -3002 3197 -3196 3393 -3002 3393 -3002 3403 -2998 3205 -1598 1791 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -3002 1795 -1396 1795 -1402 1799 -1402 3401 -3002 3395 -1400 1801 -3002 3393 -1402 1795 -1398 1801 -3002 1795 -1398 3401 -3002 1797 -1398 3401 -3002 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 +RAW_Data: 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 3401 -1402 1795 -1398 1801 -1400 1795 -1394 1797 -3002 3401 -3002 1797 -1398 3601 -4152 2483 -2464 3741 -2764 3575 -2986 3385 -2994 3395 -3002 3393 -3002 3395 -3002 3401 -2994 3401 -2996 3401 -3002 3393 -3002 3403 -3002 3393 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -3006 1601 -1592 1793 -1394 1795 -1402 3401 -3002 3403 -1400 1795 -3000 3401 -1398 1795 -1402 1801 -3006 1599 -1594 3389 -3002 3403 -3002 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1795 -1398 1801 -1400 1801 -1402 1799 -1402 3393 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -3002 3393 -3002 3403 -5836 199 -800 2239 -2970 3487 -2904 3313 -3324 3147 -3168 3173 -3188 3389 -2998 3397 -2996 3401 -2994 3401 -3002 3403 -2994 3393 -3002 3401 -3000 3205 -1596 1793 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -3002 1801 -1396 1793 -1398 1799 -1402 3401 -3002 3393 -1402 1801 -3002 3393 -1402 1799 -1398 1795 -3004 1799 -1402 3393 -3006 3205 -1598 1791 -2992 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 3401 -1402 1799 -1402 1799 -1402 1795 -1394 +RAW_Data: 1797 -3002 3401 -1402 1799 -3004 4001 -1452 1311 -1732 1679 -2834 3579 -2986 3395 -2998 3189 -3198 3199 -3194 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3403 -2994 3401 -2994 3403 -2994 3401 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -1402 1795 -2992 3401 -1402 1799 -1402 1799 -3000 1799 -1394 3397 -1402 1799 -3002 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 3389 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -3000 3401 -1402 1799 -1402 1801 -7878 14949 -2414 3809 -2802 3401 -3004 3401 -3002 3401 -3002 3395 -2994 3401 -3002 3393 -3004 3401 -2998 3205 -3194 3395 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3006 3403 -1404 1595 -3188 3401 -1400 1801 -1398 1791 -2998 1801 -1402 3401 -1400 1801 -2994 3403 -2994 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 3401 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1396 1797 -1400 3603 -4378 1987 -2808 3349 -2882 3487 -3116 3325 -2936 3561 -2974 3385 -2992 3389 -2994 3393 -3004 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -3000 1799 -1402 1801 -1400 1801 -1400 3395 -3002 3401 -1400 1797 -2990 3403 -1400 1801 -1400 1801 -3006 1601 -1592 3391 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 +RAW_Data: 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 3399 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -3004 1803 -1398 3389 -7766 3599 -1180 3997 -2602 3601 -3002 3401 -3002 3403 -2994 3401 -3002 3401 -2996 3393 -3006 3397 -2994 3403 -3002 3401 -2994 3403 -2994 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -2994 1801 -1400 1801 -1398 1791 -1398 3401 -3002 3403 -1400 1801 -2994 3401 -1398 1791 -1398 1801 -3002 1799 -1402 3401 -1402 1799 -1398 1791 -1398 1801 -3002 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -2990 3401 -3004 3801 -4548 2039 -2540 3875 -2646 3423 -3026 3413 -3006 3405 -2996 3401 -2994 3401 -3002 3395 -3002 3393 -3002 3407 -2998 3393 -2994 3401 -3000 3205 -1596 1793 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1791 -1400 1799 -1402 3401 -3002 3393 -1402 1801 -3002 3393 -1402 1799 -1402 1799 -2996 3401 -2994 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 3397 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -3002 3407 -1404 +RAW_Data: 1595 -7378 2189 -2976 3371 -2942 3489 -2908 3291 -3120 3341 -3164 3173 -3188 3189 -3190 3393 -3006 3399 -2998 3205 -3194 3395 -2994 3401 -3006 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -3002 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -1402 1795 -2994 3407 -1396 1791 -1398 1801 -3002 3403 -2994 1799 -1402 1801 -1400 3401 -2994 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -2994 1801 -1400 3401 -4138 9989 -410 4445 -2630 3617 -2814 3415 -3006 3401 -3002 3401 -3004 3393 -3002 3393 -3002 3403 -2994 3401 -3002 3395 -3006 3197 -1598 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -3006 1605 -1596 1793 -1394 1795 -1402 3401 -3002 3401 -1398 1791 -3000 3401 -1402 1799 -1402 1801 -3002 3393 -3002 1795 -1394 3399 -3002 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 3401 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -3002 3395 -7518 2025 -2782 3651 -2826 3417 -3010 3407 -3010 3409 -2998 3389 -2996 3397 -3010 3397 -2994 3203 -3194 3393 -3002 3395 -3002 3401 -2994 3401 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1398 1799 -1402 1801 -1396 3389 -3004 3401 -1400 1801 -3006 3397 -1398 1791 -1398 1801 -3002 3401 -2994 1801 -1402 3401 -1400 1597 -3190 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 +RAW_Data: 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 3401 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -2994 4001 -3412 1945 -2826 3517 -2924 3347 -3164 3381 -2988 3389 -2994 3393 -2996 3401 -3002 3393 -3002 3403 -2994 3401 -2994 3401 -3004 3393 -3002 3393 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -2992 1799 -1402 1799 -1402 1801 -1400 3393 -3004 3401 -1396 1793 -3002 3405 -1398 1797 -1400 1801 -3002 3393 -3006 3399 -2994 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1394 3397 -3004 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 3601 -1280 5101 -3078 3271 -3238 3223 -3014 3409 -3006 3405 -2996 3401 -3002 3401 -2994 3395 -3002 3401 -3002 3393 -3004 3393 -3002 3393 -3002 3395 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -3002 1801 -1400 1801 -1396 1791 -1400 3401 -3002 3401 -1402 1799 -3002 3395 -1400 1797 -1394 1795 -3002 3403 -3002 3393 -3006 3205 -3196 1595 -1594 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 3395 -3002 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 3401 -7728 1751 -3100 3263 -3030 3413 -3014 3415 -3006 3209 -3202 +RAW_Data: 3193 -3200 3197 -3194 3393 -2998 3407 -2994 3393 -3002 3403 -2994 3401 -3002 3393 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1394 1797 -3002 1799 -1402 1801 -1400 1801 -1396 3391 -3002 3401 -1400 1801 -3002 3403 -1396 1791 -1398 1801 -3002 3401 -2996 3401 -1400 1797 -2990 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 3401 -3004 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1797 -1398 3401 -3002 4405 -2758 2807 -2942 3325 -2938 3367 -3180 3379 -2990 3189 -3190 3393 -2996 3401 -2994 3401 -3002 3395 -3002 3401 -2998 3205 -3196 3393 -2994 3401 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -3004 1799 -1402 1799 -1402 1801 -1396 3397 -3004 3393 -1400 1801 -3002 3395 -1400 1801 -1400 1795 -2996 3405 -2996 3401 -1400 1801 -1402 1795 -2990 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1398 1801 -1400 3401 -3004 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 3401 -1400 1801 -5956 861 -1316 1441 -3046 3355 -3176 3381 -2988 3389 -2994 3201 -3196 3393 -3002 3401 -2994 3403 -2994 3401 -3006 3397 -2996 3401 -2994 3401 -2994 3403 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -3002 1801 -1400 1801 -1400 1801 -1398 3389 -3002 3401 -1402 1799 -3004 3401 -1396 1793 -1398 1799 -3002 3403 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 +RAW_Data: 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1398 3403 -3002 1801 -1400 1801 -1400 1795 -1396 1795 -1402 3401 -3002 1801 -1396 3991 -4480 15153 -2008 3809 -2602 3603 -3002 3401 -3002 3407 -3006 3393 -2994 3393 -3004 3405 -2998 3393 -3002 3395 -3002 3393 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -2994 1805 -1396 1797 -1402 1795 -1398 3401 -3002 3395 -1400 1801 -3006 3397 -1398 1791 -1398 1801 -3002 3401 -1398 1795 -3002 1801 -1402 3401 -3002 1597 -1592 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1597 -1592 1797 -1402 1799 -1402 3401 -3002 1801 -1396 1793 -1398 1799 -1402 1801 -1400 3401 -3002 3395 -7734 2455 -2034 3851 -2834 3419 -3014 3405 -3002 3401 -3002 3403 -3002 3393 -3002 3403 -2994 3401 -3002 3393 -2996 3401 -3002 3407 -2996 3399 -1404 1795 -1392 1795 -1402 1799 -1398 1797 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3006 3397 -1398 1791 -3000 3401 -1400 1801 -1398 1791 -2998 3403 -1400 1801 -3002 3401 -2994 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 3403 -3002 1795 -1394 1797 -1400 1801 -1402 1799 -1402 3401 -1398 1791 -3002 3607 -3594 2481 -2584 3775 -2732 3541 -2914 3491 -2916 3333 -3160 3375 -2982 3389 -2992 3393 -2994 3401 -3004 3393 -3002 3401 -2994 3395 -3002 3401 -1402 +RAW_Data: 1795 -1394 1797 -1400 1801 -1396 1797 -1400 1801 -3002 1801 -1400 1801 -1398 1795 -1402 3401 -3002 3395 -1400 1801 -2994 3401 -1402 1799 -1398 1791 -3000 3401 -1402 1799 -3002 3395 -1400 1801 -3002 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 3401 -3002 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -1402 1801 -1400 1801 -7478 1559 -3038 3563 -2982 3391 -2992 3395 -3002 3399 -2996 3391 -2994 3393 -2994 3403 -3002 3407 -3004 3393 -2996 3393 -3002 3401 -2994 3403 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -2994 1801 -1400 1801 -1396 1797 -1402 3401 -2994 3401 -1402 1799 -2996 3401 -1400 1801 -1402 1795 -2990 3407 -1404 1795 -1394 1797 -3002 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1597 -1594 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 3403 -2998 1603 -1598 1791 -1394 1797 -1402 3401 -3006 1605 -1596 1791 -1394 3399 -4468 1663 -3040 3363 -2940 3339 -3112 3293 -3122 3329 -3156 3367 -2982 3387 -2990 3393 -2994 3403 -3002 3401 -2994 3401 -3002 3395 -2994 3401 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -3002 1801 -1398 1791 -1398 1801 -1400 3401 -3006 3207 -1594 1789 -2992 3401 -1402 1801 -1400 1801 -2994 3401 -1402 1799 -1398 1797 -3002 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 +RAW_Data: 1797 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 3401 -3002 1801 -1398 1795 -1402 1799 -1398 3403 -3004 1597 -1594 3389 -3402 1499 -440 419 -600 599 -766 1693 -3100 3401 -3002 3395 -2994 3401 -3002 3395 -3002 3393 -3006 3205 -3200 3197 -3194 3201 -3194 3403 -2994 3401 -3002 3395 -3006 3397 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1793 -2998 1801 -1400 1801 -1402 1799 -1402 3393 -3002 3401 -1398 1797 -3002 3401 -1398 1795 -1398 1797 -3002 3401 -1400 1797 -1398 1799 -1402 1801 -2994 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 3401 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3401 -2996 4203 -806 201 -2874 1835 -2990 3405 -2996 3393 -3002 3393 -3004 3405 -2998 3393 -2994 3403 -2994 3401 -2994 3403 -3002 3401 -2994 3401 -2994 3403 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -3002 1801 -1398 1795 -1402 1799 -1398 3397 -3002 3403 -1396 1791 -3000 3401 -1402 1799 -1402 1801 -2998 3205 -1598 1791 -1394 1797 -1400 1801 -1400 1801 -3006 1605 -1596 1793 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 3401 -3002 1801 -1402 1799 -1402 1799 -1402 3393 -3002 3395 -1400 1801 -6000 21381 -2268 3645 -2836 3417 -3010 3407 -3008 3403 -2998 3399 -2996 3395 -2994 3401 -2994 3401 -2996 3401 -1400 1801 -1402 1795 -1398 1799 -1402 1795 -1394 1797 -3002 1801 -1400 +RAW_Data: 1801 -1400 1801 -1398 3397 -3002 3401 -1398 1791 -3000 3405 -1406 1795 -1394 1795 -1402 1801 -3006 1599 -1594 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 3401 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -1398 1795 -3002 1801 -1402 3601 -4730 8239 -2608 3611 -3002 3401 -3002 3401 -3002 3395 -3002 3401 -2998 3399 -3002 3393 -3002 3401 -2996 3401 -2994 3407 -2996 3399 -1404 1795 -1396 1791 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3006 3397 -1398 1791 -3000 3401 -1400 1801 -1398 1795 -1402 1801 -3002 1795 -1398 1801 -1400 1801 -1396 3391 -3002 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 3401 -2994 1801 -1400 1801 -1396 1793 -1398 3401 -1400 1801 -3006 3397 -7406 3789 -200 4429 -2816 3413 -3014 3407 -3002 3407 -3004 3393 -3000 3397 -2994 3401 -2996 3401 -3002 3399 -3004 3395 -2994 3401 -2994 3401 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -3002 3393 -1402 1799 -3002 3395 -1400 1801 -1396 1793 -1398 1799 -3006 1805 -1398 1791 -1398 3401 -3002 1801 -1396 1797 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 +RAW_Data: 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 3403 -2994 1799 -1402 1801 -1396 1797 -1400 3403 -1400 1795 -1394 1797 -3002 3401 -4904 1617 -2646 3741 -2764 3575 -2986 3385 -2994 3395 -3002 3393 -3002 3393 -3004 3393 -3002 3401 -3002 3395 -3002 3393 -3002 3403 -2994 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -2994 3401 -1402 1801 -2998 3205 -1598 1791 -1394 1797 -1400 1801 -3002 1801 -1400 1801 -1396 3399 -1400 1801 -3002 1595 -1594 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 3401 -3002 1801 -1400 1801 -1400 1797 -1394 3397 -1402 1799 -1402 1799 -1402 1795 -6010 3547 -1150 3953 -2576 3585 -2990 3395 -2994 3393 -3002 3403 -3002 3393 -3002 3407 -2996 3395 -2994 3401 -3002 3395 -3002 3401 -2994 3393 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -3002 1799 -1402 1795 -1398 1801 -1400 3403 -2994 3401 -1400 1797 -2998 3407 -1404 1597 -1592 1793 -1398 1799 -3002 1801 -1402 3401 -2998 1605 -1596 1791 -1398 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 3403 -2994 1799 -1402 1801 -1400 3401 -2998 1805 -1398 1791 -1398 1801 -1400 3601 -4812 1887 -2884 3391 -2994 3393 -2994 3395 -2994 3401 -3002 3393 -3004 3401 -2994 3401 -3002 3395 -3002 3201 -3198 3205 -3196 3393 -2998 3205 -1598 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1398 1799 -1402 1801 -1400 3393 -3004 +RAW_Data: 3393 -1400 1801 -3002 3395 -1400 1801 -1400 1801 -1396 1793 -2998 1801 -1400 3403 -2994 3401 -3002 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 3401 -3002 1797 -1394 1795 -1402 3401 -3002 1801 -1398 1791 -1398 3401 -4786 197 -1694 1655 -3046 3275 -3160 3351 -3136 3317 -2902 3311 -3324 3147 -3168 3181 -3186 3191 -3194 3393 -3002 3401 -2996 3401 -3002 3393 -3002 3395 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 3401 -3002 3401 -1398 1791 -3004 3405 -1396 1793 -1398 1799 -1402 1801 -3002 1799 -1398 3397 -1402 1799 -2994 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1400 3401 -2998 1805 -1396 1791 -1394 3399 -3002 1801 -1400 3401 -3002 4219 -3452 1989 -2654 3675 -2776 3467 -2882 3487 -3110 3319 -2932 3561 -2974 3381 -2992 3393 -2998 3393 -2996 3393 -3002 3401 -3002 3395 -3002 3393 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1795 -1398 1801 -1402 1799 -1402 3401 -2994 3403 -1400 1795 -2992 3401 -1402 1799 -1402 1801 -1400 1795 -2992 1801 -1396 3397 -1402 1801 -1400 1801 -3002 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1597 -1592 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 +RAW_Data: 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 3401 -2998 1805 -1400 1797 -1394 3397 -3002 1801 -1396 3399 -1400 1801 -7622 2021 -2904 3499 -2872 3443 -3018 3413 -3006 3411 -3006 3397 -3006 3393 -2994 3403 -2994 3401 -3002 3395 -3002 3393 -3002 3401 -2994 3403 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -2998 1605 -1596 1791 -1394 1797 -1402 3401 -3002 3401 -1402 1799 -3004 3393 -1396 1797 -1402 1799 -1402 1801 -2994 3401 -3002 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 3397 -3002 1801 -1396 1797 -1400 3403 -3002 3393 -3002 1801 -1396 4405 -3580 2203 -2680 3433 -3018 3415 -3006 3401 -3002 3401 -3002 3395 -3002 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3203 -3194 3399 -3004 3393 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -3002 1795 -1394 1797 -1400 1801 -1400 3403 -2998 3205 -1598 1791 -2998 3403 -1400 1801 -1396 1793 -1398 1799 -3002 3403 -3006 1599 -1592 3401 -3004 1597 -1594 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 3391 -3002 1799 -1402 1801 -1400 3401 -2996 3401 -2994 3401 -7234 3089 -2524 3707 -2718 3733 -2896 3467 -2840 3421 -3020 3405 -3002 3401 -3002 3403 -3002 3393 -3002 3407 -2998 3393 -3002 3399 -2996 3399 -1404 1795 -1394 1793 -1398 1799 -1402 1801 -1400 1801 -3002 1801 -1400 1795 -1394 1793 -1398 3401 -3002 3401 -1402 1799 -3004 3401 -1396 1793 -1398 1799 -1402 1799 -3004 3401 -2994 3401 -2998 1805 -1398 +RAW_Data: 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1595 -1594 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1400 3401 -3006 1599 -1594 1791 -1398 3403 -3002 3401 -1398 1791 -2998 4003 -4646 1945 -2714 3615 -2814 3409 -3002 3407 -3004 3395 -3006 3397 -2994 3395 -3002 3401 -3002 3393 -3004 3401 -2994 3393 -3002 3403 -2994 3401 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -3002 1795 -1398 1801 -1402 1799 -1402 3401 -2994 3395 -1400 1801 -3002 3393 -1402 1795 -1398 1801 -1400 1801 -2990 3401 -3002 3403 -1400 1801 -3002 1597 -1592 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 3401 -3002 1801 -1396 1797 -1402 3401 -3002 3393 -1398 1797 -1400 1801 -7714 15297 -1990 4001 -2594 3603 -2994 3401 -3002 3393 -3004 3393 -3002 3401 -3002 3395 -3002 3393 -2994 3407 -3006 3393 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -2998 1801 -1396 1797 -1402 1799 -1402 3401 -2994 3401 -1402 1795 -3000 3401 -1402 1795 -1398 1799 -1398 1797 -3002 3401 -1402 1799 -2994 1801 -1402 1799 -1402 1595 -1594 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 +RAW_Data: 1795 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 3401 -3002 1801 -1396 1797 -1402 3401 -1396 1797 -3002 1801 -1400 1801 -1398 3389 -4226 1665 -3024 3337 -3164 3373 -2986 3387 -2994 3393 -3002 3395 -3002 3407 -2996 3395 -2994 3401 -3002 3393 -2996 3401 -3002 3401 -2998 3399 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -2994 1799 -1398 1797 -1400 1801 -1400 3407 -3006 3193 -1598 1791 -3000 3401 -1396 1797 -1402 1799 -1402 1799 -3002 3395 -1396 1797 -3002 3401 -2996 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1597 -1592 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 3403 -2998 1603 -1598 1791 -1394 3399 -1400 1801 -3002 1801 -1400 3401 -7946 8393 -2610 3601 -3002 3403 -3002 3401 -3002 3393 -3004 3401 -3002 3393 -2994 3407 -3006 3393 -2994 3401 -2996 3401 -2994 3401 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3002 1801 -1398 1791 -1394 1797 -1400 3407 -3006 3401 -1396 1793 -2998 3407 -1404 1795 -1394 1797 -1400 1801 -3002 3403 -1396 1791 -1394 1797 -3002 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1791 -1400 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 3401 -3004 1595 -1594 1795 -1402 3401 -1402 1799 -3004 3393 -3002 4001 -3612 15189 -2202 3801 -2602 3601 -3004 3401 -3002 3401 -2994 3403 -2994 3407 -2996 3399 -3010 3397 -2990 3393 -3004 3393 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1801 -1396 1791 -1398 1801 -1402 3401 -3002 3401 -1402 1795 -2992 3401 -1400 1801 -1402 1799 -1402 1795 -2992 3401 -1402 1799 -1402 1799 -1398 1791 -3000 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 +RAW_Data: 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 3401 -3006 1601 -1596 1791 -1398 3403 -1400 1801 -3002 3393 -1402 1801 -4208 1657 -1960 1633 -3076 3349 -3166 3183 -3186 3189 -3194 3395 -3002 3401 -2994 3403 -2994 3401 -3002 3399 -3004 3395 -3002 3393 -2994 3403 -3002 3201 -1598 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1793 -2998 1801 -1400 1801 -1402 1799 -1402 3401 -2994 3403 -1396 1791 -3000 3401 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -3002 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1597 -1592 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 3395 -3004 1601 -1596 1793 -1398 3401 -1400 1801 -1402 1799 -3002 1797 -1394 3797 -4466 8859 -2000 3797 -2810 3401 -3002 3401 -3002 3403 -3002 3393 -2994 3403 -3002 3401 -3002 3393 -3002 3407 -2998 3399 -2996 3395 -1396 1797 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -3002 1799 -1402 1801 -1396 1797 -1400 3403 -2998 3205 -1598 1791 -3000 3401 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -3002 1799 -1398 1791 -1398 3401 -3004 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 3403 -2994 1799 -1402 1795 -1394 +RAW_Data: 3399 -1400 1801 -1400 1801 -3002 3205 -4194 389 -3580 1837 -3274 3173 -3082 3345 -3118 3293 -3118 3317 -3142 3163 -3174 3183 -3190 3393 -2996 3401 -2994 3401 -3002 3395 -3002 3205 -3198 3393 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -2992 1799 -1402 1801 -1400 1801 -1400 3403 -2994 3401 -1400 1801 -3002 3395 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3004 1799 -1398 3389 -3002 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1595 -1594 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 3401 -3004 1799 -1402 1795 -1398 3401 -1398 1797 -1400 1801 -1400 1801 -2994 4407 -3396 2177 -2946 3427 -3018 3407 -3004 3407 -3006 3389 -3002 3393 -3004 3393 -3002 3401 -2994 3403 -3002 3393 -3002 3395 -3002 3393 -3002 3393 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 1799 -2996 1799 -1402 1795 -1398 1801 -1400 3407 -3004 3395 -1396 1793 -2998 3407 -1400 1791 -1394 1797 -1400 1801 -1402 1799 -3002 1801 -1402 3401 -1396 1793 -2998 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3004 1799 -1402 1795 -1394 3397 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -7678 1989 -2426 3963 -2528 3683 -2904 3519 -2930 3347 -3168 3373 -2988 3389 -2994 3401 -2996 3401 -2994 3401 -3002 3395 -3002 3401 -2994 3401 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -3002 1799 -1402 1801 -1396 1797 -1400 3403 -3002 3393 -1400 1801 -2994 3403 -1400 1795 -1398 1801 -1402 1799 -1402 1795 -2992 3401 -3002 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 +RAW_Data: 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1599 -1598 1791 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1601 -1598 1791 -1398 1799 -1402 1801 -1396 3397 -3004 1799 -1402 3401 -2994 1801 -1400 1601 -1598 1791 -1398 1801 -1400 3401 -4800 1839 -2646 3737 -2764 3573 -2988 3385 -2994 3395 -3002 3393 -3002 3401 -2994 3403 -3002 3393 -2994 3407 -3006 3393 -2994 3401 -3004 3393 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1400 1801 -1402 3405 -3006 3389 -1398 1797 -3002 3405 -1402 1789 -1392 1797 -1400 1801 -1400 1801 -3002 3401 -3002 3395 -3002 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1795 -1400 1799 -1402 1799 -1402 1795 -1398 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1398 1801 -1402 3401 -2994 1801 -1400 3403 -3002 1595 -1594 1797 -1400 1801 -1400 3403 -7764 1463 -3208 3319 -2936 3563 -2976 3385 -2986 3391 -2994 3401 -2994 3401 -2996 3401 -3002 3401 -2994 3403 -2994 3401 -3002 3395 -3002 3401 -1396 1793 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -3002 1801 -1396 1797 -1402 1799 -1402 3405 -2998 3399 -1404 1597 -3190 3401 -1402 1795 -1398 1801 -1400 1795 -1394 1797 -3002 3401 -1402 1801 -2994 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 3401 -3002 1801 -1396 3391 -3002 1799 -1402 1801 -1400 3401 -2996 3401 -1706 +RAW_Data: 219 -2872 1657 -2822 3519 -2942 3559 -2974 3385 -2992 3389 -3002 3401 -2994 3403 -2994 3407 -2996 3395 -3002 3393 -3002 3393 -3004 3401 -2994 3401 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -3000 1803 -1398 1791 -1398 1801 -1400 3401 -3004 3393 -1400 1801 -2994 3401 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -3002 3403 -1400 1597 -1592 1797 -3002 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 3401 -2994 1801 -1402 3401 -2994 1801 -1400 1795 -1396 3397 -1400 1801 -7342 2387 -2176 3817 -2614 3601 -3002 3403 -3002 3401 -3002 3401 -2996 3405 -2998 3393 -3002 3395 -3002 3393 -3002 3407 -2998 3401 -2994 3393 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -3004 1799 -1402 1795 -1394 1797 -1400 3403 -3002 3401 -1400 1597 -3190 3403 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1795 -3000 1799 -1402 1795 -1398 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 3401 -3004 1799 -1398 3389 -3002 1801 -1400 3395 -3002 1799 -1402 3593 -4558 1793 -2438 3923 -2740 3563 -2976 3385 -2990 3395 -2994 3401 -2994 3403 -2994 3401 -2994 3401 -3004 3401 -2994 3401 -2994 3407 -2998 3393 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -2994 1801 -1402 1799 -1402 1799 -1398 3389 -3002 3403 -1400 1801 -3002 3401 -1398 1791 -1398 1801 -1396 1797 -1400 1801 -1402 1799 -3002 1801 -1398 3397 -3002 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 +RAW_Data: 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1597 -1592 1797 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 3401 -2994 1801 -1400 3403 -3002 1595 -1594 3397 -3002 3395 -7924 1529 -3076 3409 -3002 3403 -3002 3401 -3002 3401 -2996 3393 -3002 3401 -2994 3407 -2998 3393 -3002 3401 -2996 3401 -2994 3401 -3002 3399 -1404 1795 -1394 1793 -1398 1799 -1402 1801 -1396 1797 -3002 1801 -1400 1801 -1400 1801 -1402 3397 -3010 3197 -1598 1791 -2992 3401 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -3002 3401 -3000 1603 -1598 1791 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1597 -1592 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1394 3397 -3002 1801 -1400 3401 -2996 1799 -1402 3407 -1400 1591 -3192 3601 -4992 1735 -2952 3401 -3006 3401 -3002 3403 -3002 3401 -2998 3397 -2996 3405 -2998 3399 -3004 3195 -3194 3401 -2994 3403 -2994 3405 -3006 3193 -1598 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1791 -3000 1799 -1402 1799 -1402 1801 -1400 3395 -3002 3401 -1396 1793 -2990 3403 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -3002 3401 -1398 1791 -2998 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1396 1797 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1402 1599 -1598 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1398 1795 -1402 1801 -1400 1801 -1400 1601 -1596 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1797 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 3401 -3004 1795 -1394 3397 -3002 1801 -1400 3403 -1396 1791 -1398 1801 -8002 1987 -2168 4109 -2272 4115 -2502 3705 -2690 3651 -2834 3423 -3016 +RAW_Data: 3403 -3002 3401 -3002 3401 -3002 3395 -3002 3407 -2996 3395 -2994 3401 -1402 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -3002 1795 -1394 1797 -1402 1799 -1402 3401 -3002 3395 -1400 1795 -3000 3407 -1404 1795 -1394 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -3004 1795 -1394 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1799 -1402 1801 -1396 1791 -1398 1801 -1402 1799 -1402 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1402 1597 -1592 1797 -1400 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1400 1801 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -1398 1795 -1402 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1402 3401 -2994 1801 -1400 3403 -2994 3401 -3002 1795 -1394 1797 -1402 3601 -1036 421 -848 843 -1518 1659 -2912 3565 -2984 3385 -2994 3395 -2994 3401 -2994 3401 -3004 3401 -2994 3401 -2994 3403 -2994 3401 -3002 3393 -3004 3393 -3002 3401 -1402 1795 -1394 1797 -1400 1801 -1400 1801 -1402 1799 -3002 1597 -1594 1795 -1402 1801 -1400 3401 -2996 3401 -1396 1797 -3002 3407 -1404 1597 -1592 1791 -1398 1801 -1402 1799 -1402 1799 -1402 1801 -2994 3401 -2994 1801 -1400 1801 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1801 -1402 1795 -1398 1795 -1398 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1801 -1400 1795 -1394 1797 -1402 1799 -1402 1801 -1396 1797 -1400 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1795 -1396 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1797 -1402 1799 -1398 1795 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1398 1797 -1400 1801 -1400 1797 -1398 1799 -1402 1799 -1402 1795 -1398 1801 -1400 1801 -1402 1795 -1394 1797 -1400 3401 -3002 1801 -1402 3393 -3002 3401 -3002 1597 -1594 3389 -7770 2021 -2912 3517 -3074 3245 -3022 3423 -3008 3411 -2998 3393 -2994 3401 -2994 3403 -3002 3393 -3002 3407 -2998 3393 -2994 3401 -3008 3397 -1396 1793 -1398 1799 -1402 1801 -1400 1801 -1396 1791 -3000 1801 -1400 1801 -1400 1801 -1402 3401 -2994 3393 -1402 1801 -3002 3401 -1398 1791 -1398 1799 -1402 1801 -1400 1801 -1400 1597 -1594 1795 -1402 1799 -3004 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1795 -1398 1801 -1400 1801 -1400 1797 -1394 1795 -1402 1801 -1400 1801 -1400 1801 -1400 1801 -1398 1791 -1398 1801 -1400 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 +RAW_Data: 1791 -1398 1801 -1400 1801 -1402 1799 -1402 1799 -1398 1791 -1398 1801 -1400 1801 -1402 1799 -1398 1797 -1400 1801 -1400 1801 -1400 1797 -1398 1799 -1402 1801 -1400 1795 -1398 1801 -1400 1801 -1402 1795 -1398 1801 -1400 1801 -1400 1597 -1594 1795 -1402 1799 -1402 1801 -1400 1801 -1396 1793 -1398 1799 -1402 1799 -1402 1801 -1400 1795 -1398 1801 -1402 1799 -1402 1799 -1402 1795 -1394 1797 -1400 1801 -1402 3401 -3002 1795 -1394 3399 -3002 3401 -2998 3405 -2996 3599 -1948 429 -20132 735 -734 1509 -192 387 -196272 217 -93450 441 -8180 183 -495896 381 -952 379 -594116 183 -209314 209 -296722 651 -199272 381 -98996 441 From 8370367f31536a1ce97028e18c1d5ad0767038fb Mon Sep 17 00:00:00 2001 From: jbohack Date: Wed, 8 Feb 2023 13:56:31 -0500 Subject: [PATCH 20/34] added common lrs pager frequency to subghz read & analyzer --- assets/resources/subghz/assets/setting_user.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/resources/subghz/assets/setting_user.txt b/assets/resources/subghz/assets/setting_user.txt index 173511f40..67e89dceb 100644 --- a/assets/resources/subghz/assets/setting_user.txt +++ b/assets/resources/subghz/assets/setting_user.txt @@ -51,6 +51,7 @@ Frequency: 438900000 Frequency: 440175000 Frequency: 446000000 Frequency: 464000000 +Frequency: 467750000 Frequency: 779000000 Frequency: 868350000 Frequency: 868400000 From 7bde578a368f198ae92eda136d7a6f36bf170fab Mon Sep 17 00:00:00 2001 From: jbohack Date: Wed, 8 Feb 2023 14:04:53 -0500 Subject: [PATCH 21/34] added pager bruteforce playlist for looping --- assets/resources/subghz/playlist/Pager_bruteforce_playlist.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 assets/resources/subghz/playlist/Pager_bruteforce_playlist.txt diff --git a/assets/resources/subghz/playlist/Pager_bruteforce_playlist.txt b/assets/resources/subghz/playlist/Pager_bruteforce_playlist.txt new file mode 100644 index 000000000..5ea4e2df5 --- /dev/null +++ b/assets/resources/subghz/playlist/Pager_bruteforce_playlist.txt @@ -0,0 +1,2 @@ +# Pager Bruteforce Playlist +sub: /ext/subghz/Misc/Pager_Bruteforce.sub From d7ecc95de44d3b4d57a80cab045ba787807dc50b Mon Sep 17 00:00:00 2001 From: Victor Nikitchuk Date: Thu, 9 Feb 2023 06:40:04 +0300 Subject: [PATCH 22/34] Firmware fixes and improvements for flashing via blackmagic (#2321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: quen0n Co-authored-by: あく Co-authored-by: hedger --- scripts/fbt_tools/fbt_debugopts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index f4b021c20..9abe59893 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -47,6 +47,7 @@ def generate(env, **kw): "source ${FBT_DEBUG_DIR}/gdbinit", ], GDBOPTS_BLACKMAGIC=[ + "-q", "-ex", "monitor swdp_scan", "-ex", From 71871949ec6999ab71fff5d25be8fb18a17a8186 Mon Sep 17 00:00:00 2001 From: Patrick Cunningham Date: Wed, 8 Feb 2023 19:47:16 -0800 Subject: [PATCH 23/34] Picopass: show elite key used from dictionary (#2119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * show elite key used from dictionary * remove space so it fits on screen Co-authored-by: あく --- .../scenes/picopass_scene_read_card_success.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index 0d1cc78c3..d89a5d89b 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -69,6 +69,19 @@ void picopass_scene_read_card_success_on_enter(void* context) { furi_string_cat_printf(sio_str, "+SIO"); } + if(pacs->key) { + if(pacs->sio) { + furi_string_cat_printf(sio_str, " "); + } + furi_string_cat_printf(sio_str, "Key: "); + + uint8_t key[PICOPASS_BLOCK_LEN]; + memcpy(key, &pacs->key, PICOPASS_BLOCK_LEN); + for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) { + furi_string_cat_printf(sio_str, "%02X", key[i]); + } + } + widget_add_button_element( widget, GuiButtonTypeLeft, From 163be139ebb7a56d495d97ca87b662dfcd8a0bb8 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 9 Feb 2023 08:48:06 +0400 Subject: [PATCH 24/34] SubGhz: add protocol BinRAW (binarization of data quantized by the minimum correlated duration) (#2322) * SubGhz: add protocol DataRAW (binarization of data quantized by the minimum correlated duration) * SubGhz: fix name history * SubGhz: add encoder Data_RAW protocol * SubGhz: decreasing the size of the LevelDuration structure * SubGhz: history, added check that there is free RAM * SubGhz: checking for free memory, support to pass without gap * SubGhz: add running average to average the result, auto cut noise at the end of a burst * SubGhz: support for repeating sequences * SubGhz: fix secplus_v2 decoder * SubGhz: bin_RAW fix add history * SubGhz: add debug * SubGhz: debug refactoring * FURI_LOG: add FURI_LOG_RAW_x formatted string output like printf * SubGhz: fix new FURI_LOG metod * FURI_LOG: fix unit test * SubGhz: add enable/disable BinRAW protocol decoding * SubGhz: fix PVS * SubGhz: forcibly turn off the speaker when exiting SubGhz * SubGhz: adaptive adjustment to the noise level Co-authored-by: Aleksandr Kutuzov --- applications/debug/unit_tests/test_index.c | 2 +- applications/main/subghz/application.fam | 2 +- .../subghz/scenes/subghz_scene_read_raw.c | 2 +- .../subghz/scenes/subghz_scene_receiver.c | 13 + .../scenes/subghz_scene_receiver_config.c | 32 + applications/main/subghz/subghz.c | 5 +- applications/main/subghz/subghz_history.c | 40 +- applications/main/subghz/subghz_i.h | 1 + applications/main/subghz/views/receiver.c | 33 +- applications/main/subghz/views/receiver.h | 2 + .../subghz/views/subghz_frequency_analyzer.c | 1 - applications/main/subghz/views/transmitter.c | 7 +- firmware/targets/f7/api_symbols.csv | 3 +- furi/core/log.c | 31 +- furi/core/log.h | 51 +- lib/subghz/blocks/encoder.c | 23 +- lib/subghz/blocks/encoder.h | 11 +- lib/subghz/blocks/generic.c | 2 +- lib/subghz/blocks/generic.h | 2 +- lib/subghz/protocols/bin_raw.c | 1120 +++++++++++++++++ lib/subghz/protocols/bin_raw.h | 111 ++ lib/subghz/protocols/chamberlain_code.c | 5 +- lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + lib/subghz/protocols/secplus_v2.c | 8 +- lib/subghz/receiver.c | 2 +- lib/subghz/types.h | 1 + lib/toolbox/level_duration.h | 4 +- 28 files changed, 1451 insertions(+), 65 deletions(-) create mode 100644 lib/subghz/protocols/bin_raw.c create mode 100644 lib/subghz/protocols/bin_raw.h diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 2bb9c423f..ac71ca397 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -70,7 +70,7 @@ void minunit_print_progress() { } void minunit_print_fail(const char* str) { - printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str); + printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); } void unit_tests_cli(Cli* cli, FuriString* args, void* context) { diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 6df4b1a8a..f0dc66e89 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -12,7 +12,7 @@ App( ], provides=["subghz_start"], icon="A_Sub1ghz_14", - stack_size=2 * 1024, + stack_size=3 * 1024, order=10, ) diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 6f95c4169..96acc90ee 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -411,5 +411,5 @@ void subghz_scene_read_raw_on_exit(void* context) { notification_message(subghz->notifications, &sequence_reset_rgb); //filter restoration - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 2b01e2975..93c369092 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -1,6 +1,7 @@ #include "../subghz_i.h" #include "../views/receiver.h" #include +#include static const NotificationSequence subghs_sequence_rx = { &message_green_255, @@ -143,6 +144,11 @@ void subghz_scene_receiver_on_enter(void* context) { } subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); + //to use a universal decoder, we are looking for a link to it + subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( + subghz->txrx->receiver, SUBGHZ_PROTOCOL_BIN_RAW_NAME); + furi_assert(subghz->txrx->decoder_result); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); } @@ -208,6 +214,13 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { subghz_hopper_update(subghz); subghz_scene_receiver_update_statusbar(subghz); } + + //get RSSI + float rssi = furi_hal_subghz_get_rssi(); + subghz_receiver_rssi(subghz->subghz_receiver, rssi); + subghz_protocol_decoder_bin_raw_data_input_rssi( + (SubGhzProtocolDecoderBinRAW*)subghz->txrx->decoder_result, rssi); + switch(subghz->state_notifications) { case SubGhzNotificationStateRx: notification_message(subghz->notifications, &sequence_blink_cyan_10); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index b49aac922..895e43342 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -5,6 +5,7 @@ enum SubGhzSettingIndex { SubGhzSettingIndexFrequency, SubGhzSettingIndexHopping, SubGhzSettingIndexModulation, + SubGhzSettingIndexBinRAW, SubGhzSettingIndexSound, SubGhzSettingIndexLock, SubGhzSettingIndexRAWThesholdRSSI, @@ -58,6 +59,15 @@ const uint32_t speaker_value[SPEAKER_COUNT] = { SubGhzSpeakerStateShutdown, SubGhzSpeakerStateEnable, }; +#define BIN_RAW_COUNT 2 +const char* const bin_raw_text[BIN_RAW_COUNT] = { + "OFF", + "ON", +}; +const uint32_t bin_raw_value[BIN_RAW_COUNT] = { + SubGhzProtocolFlag_Decodable, + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW, +}; uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) { furi_assert(context); @@ -186,6 +196,15 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) { subghz->txrx->speaker_state = speaker_value[index]; } +static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, bin_raw_text[index]); + subghz->txrx->filter = bin_raw_value[index]; + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); +} + static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -254,6 +273,19 @@ void subghz_scene_receiver_config_on_enter(void* context) { variable_item_set_current_value_text( item, subghz_setting_get_preset_name(subghz->setting, value_index)); + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != + SubGhzCustomEventManagerSet) { + item = variable_item_list_add( + subghz->variable_item_list, + "Bin_RAW:", + BIN_RAW_COUNT, + subghz_scene_receiver_config_set_bin_raw, + subghz); + value_index = value_index_uint32(subghz->txrx->filter, bin_raw_value, BIN_RAW_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, bin_raw_text[value_index]); + } + item = variable_item_list_add( subghz->variable_item_list, "Sound:", diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 200be6262..25233fe21 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -194,7 +194,8 @@ SubGhz* subghz_alloc() { subghz_environment_set_protocol_registry( subghz->txrx->environment, (void*)&subghz_protocol_registry); subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz->txrx->filter = SubGhzProtocolFlag_Decodable; + subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); subghz_worker_set_overrun_callback( subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); @@ -218,6 +219,8 @@ void subghz_free(SubGhz* subghz) { subghz->rpc_ctx = NULL; } + subghz_speaker_off(subghz); + // Packet Test view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket); subghz_test_packet_free(subghz->subghz_test_packet); diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index beecc6e8b..e6c93e05c 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -5,6 +5,7 @@ #include #define SUBGHZ_HISTORY_MAX 50 +#define SUBGHZ_HISTORY_FREE_HEAP 20480 #define TAG "SubGhzHistory" typedef struct { @@ -121,8 +122,12 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx } bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) { furi_assert(instance); + if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) { + if(output != NULL) furi_string_printf(output, " Free heap LOW"); + return true; + } if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, "Memory is FULL"); + if(output != NULL) furi_string_printf(output, " Memory is FULL"); return true; } if(output != NULL) @@ -142,6 +147,7 @@ bool subghz_history_add_to_history( furi_assert(instance); furi_assert(context); + if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) return false; if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; SubGhzProtocolDecoderBase* decoder_base = context; @@ -200,27 +206,31 @@ bool subghz_history_add_to_history( } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(item->flipper_string, "Key", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Missing Key"); - break; + FURI_LOG_D(TAG, "No Key"); } uint64_t data = 0; for(uint8_t i = 0; i < sizeof(uint64_t); i++) { data = (data << 8) | key_data[i]; } - if(!(uint32_t)(data >> 32)) { - furi_string_printf( - item->item_str, - "%s %lX", - furi_string_get_cstr(instance->tmp_string), - (uint32_t)(data & 0xFFFFFFFF)); + if(data != 0) { + if(!(uint32_t)(data >> 32)) { + furi_string_printf( + item->item_str, + "%s %lX", + furi_string_get_cstr(instance->tmp_string), + (uint32_t)(data & 0xFFFFFFFF)); + } else { + furi_string_printf( + item->item_str, + "%s %lX%08lX", + furi_string_get_cstr(instance->tmp_string), + (uint32_t)(data >> 32), + (uint32_t)(data & 0xFFFFFFFF)); + } } else { - furi_string_printf( - item->item_str, - "%s %lX%08lX", - furi_string_get_cstr(instance->tmp_string), - (uint32_t)(data >> 32), - (uint32_t)(data & 0xFFFFFFFF)); + furi_string_printf(item->item_str, "%s", furi_string_get_cstr(instance->tmp_string)); } + } while(false); furi_string_free(text); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index cd33da447..65480c6fd 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -45,6 +45,7 @@ struct SubGhzTxRx { SubGhzEnvironment* environment; SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; + SubGhzProtocolFlag filter; SubGhzProtocolDecoderBase* decoder_result; FlipperFormat* fff_data; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index aaec2adda..acc39e258 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -12,6 +12,8 @@ #define MENU_ITEMS 4u #define UNLOCK_CNT 3 +#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f + typedef struct { FuriString* item_str; uint8_t type; @@ -59,8 +61,24 @@ typedef struct { uint16_t list_offset; uint16_t history_item; SubGhzViewReceiverBarShow bar_show; + uint8_t u_rssi; } SubGhzViewReceiverModel; +void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { + furi_assert(instance); + with_view_model( + instance->view, + SubGhzViewReceiverModel * model, + { + if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) { + model->u_rssi = 0; + } else { + model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN); + } + }, + true); +} + void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) { furi_assert(subghz_receiver); subghz_receiver->lock_count = 0; @@ -168,13 +186,22 @@ static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool s canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); } +static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { + for(uint8_t i = 1; i < model->u_rssi; i++) { + if(i % 5) { + canvas_draw_dot(canvas, 46 + i, 50); + canvas_draw_dot(canvas, 47 + i, 51); + canvas_draw_dot(canvas, 46 + i, 52); + } + } +} + void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); elements_button_left(canvas, "Config"); - canvas_draw_line(canvas, 46, 51, 125, 51); bool scrollbar = model->history_item > 4; FuriString* str_buff; @@ -206,11 +233,11 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { if(model->history_item == 0) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_draw_line(canvas, 46, 51, 125, 51); + canvas_draw_str(canvas, 63, 44, "Scanning..."); canvas_set_font(canvas, FontSecondary); } + subghz_view_rssi_draw(canvas, model); switch(model->bar_show) { case SubGhzViewReceiverBarShowLock: canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); diff --git a/applications/main/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h index aab7a76c5..9b12ccfee 100644 --- a/applications/main/subghz/views/receiver.h +++ b/applications/main/subghz/views/receiver.h @@ -8,6 +8,8 @@ typedef struct SubGhzViewReceiver SubGhzViewReceiver; typedef void (*SubGhzViewReceiverCallback)(SubGhzCustomEvent event, void* context); +void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi); + void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard); void subghz_view_receiver_set_callback( diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index 94419084b..325664f4a 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -79,7 +79,6 @@ void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, uint8_t rssi, uint8_t x void subghz_frequency_analyzer_draw_log_rssi(Canvas* canvas, uint8_t rssi, uint8_t x, uint8_t y) { uint8_t column_height = 6; if(rssi) { - //rssi = rssi if(rssi > 54) rssi = 54; for(uint8_t i = 1; i < rssi; i++) { if(i % 5) { diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index 833805ccb..4a13460a3 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -84,9 +84,10 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 8, furi_string_get_cstr(model->key_str)); - canvas_draw_str(canvas, 78, 8, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 113, 8, furi_string_get_cstr(model->preset_str)); + elements_multiline_text_aligned( + canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); + canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send"); } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 846041c3e..906ab357a 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1409,6 +1409,7 @@ Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." +Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel Function,-,furi_log_set_puts,void,FuriLogPuts Function,-,furi_log_set_timestamp,void,FuriLogTimestamp @@ -2599,7 +2600,7 @@ Function,+,subghz_protocol_blocks_crc8le,uint8_t,"const uint8_t[], size_t, uint8 Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t" Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t" Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t" -Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t" +Function,+,subghz_protocol_blocks_get_upload_from_bit_array,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t, SubGhzProtocolBlockAlignBit" Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], size_t, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" diff --git a/furi/core/log.c b/furi/core/log.c index a3967ed92..d910ecf21 100644 --- a/furi/core/log.c +++ b/furi/core/log.c @@ -28,27 +28,27 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form FuriString* string; string = furi_string_alloc(); - const char* color = FURI_LOG_CLR_RESET; + const char* color = _FURI_LOG_CLR_RESET; const char* log_letter = " "; switch(level) { case FuriLogLevelError: - color = FURI_LOG_CLR_E; + color = _FURI_LOG_CLR_E; log_letter = "E"; break; case FuriLogLevelWarn: - color = FURI_LOG_CLR_W; + color = _FURI_LOG_CLR_W; log_letter = "W"; break; case FuriLogLevelInfo: - color = FURI_LOG_CLR_I; + color = _FURI_LOG_CLR_I; log_letter = "I"; break; case FuriLogLevelDebug: - color = FURI_LOG_CLR_D; + color = _FURI_LOG_CLR_D; log_letter = "D"; break; case FuriLogLevelTrace: - color = FURI_LOG_CLR_T; + color = _FURI_LOG_CLR_T; log_letter = "T"; break; default: @@ -58,7 +58,7 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form // Timestamp furi_string_printf( string, - "%lu %s[%s][%s] " FURI_LOG_CLR_RESET, + "%lu %s[%s][%s] " _FURI_LOG_CLR_RESET, furi_log.timestamp(), color, log_letter, @@ -80,6 +80,23 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form } } +void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) { + if(level <= furi_log.log_level && + furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) { + FuriString* string; + string = furi_string_alloc(); + va_list args; + va_start(args, format); + furi_string_vprintf(string, format, args); + va_end(args); + + furi_log.puts(furi_string_get_cstr(string)); + furi_string_free(string); + + furi_mutex_release(furi_log.mutex); + } +} + void furi_log_set_level(FuriLogLevel level) { if(level == FuriLogLevelDefault) { level = FURI_LOG_LEVEL_DEFAULT; diff --git a/furi/core/log.h b/furi/core/log.h index cb8b3d9cc..46ae7f007 100644 --- a/furi/core/log.h +++ b/furi/core/log.h @@ -22,21 +22,21 @@ typedef enum { FuriLogLevelTrace = 6, } FuriLogLevel; -#define FURI_LOG_CLR(clr) "\033[0;" clr "m" -#define FURI_LOG_CLR_RESET "\033[0m" +#define _FURI_LOG_CLR(clr) "\033[0;" clr "m" +#define _FURI_LOG_CLR_RESET "\033[0m" -#define FURI_LOG_CLR_BLACK "30" -#define FURI_LOG_CLR_RED "31" -#define FURI_LOG_CLR_GREEN "32" -#define FURI_LOG_CLR_BROWN "33" -#define FURI_LOG_CLR_BLUE "34" -#define FURI_LOG_CLR_PURPLE "35" +#define _FURI_LOG_CLR_BLACK "30" +#define _FURI_LOG_CLR_RED "31" +#define _FURI_LOG_CLR_GREEN "32" +#define _FURI_LOG_CLR_BROWN "33" +#define _FURI_LOG_CLR_BLUE "34" +#define _FURI_LOG_CLR_PURPLE "35" -#define FURI_LOG_CLR_E FURI_LOG_CLR(FURI_LOG_CLR_RED) -#define FURI_LOG_CLR_W FURI_LOG_CLR(FURI_LOG_CLR_BROWN) -#define FURI_LOG_CLR_I FURI_LOG_CLR(FURI_LOG_CLR_GREEN) -#define FURI_LOG_CLR_D FURI_LOG_CLR(FURI_LOG_CLR_BLUE) -#define FURI_LOG_CLR_T FURI_LOG_CLR(FURI_LOG_CLR_PURPLE) +#define _FURI_LOG_CLR_E _FURI_LOG_CLR(_FURI_LOG_CLR_RED) +#define _FURI_LOG_CLR_W _FURI_LOG_CLR(_FURI_LOG_CLR_BROWN) +#define _FURI_LOG_CLR_I _FURI_LOG_CLR(_FURI_LOG_CLR_GREEN) +#define _FURI_LOG_CLR_D _FURI_LOG_CLR(_FURI_LOG_CLR_BLUE) +#define _FURI_LOG_CLR_T _FURI_LOG_CLR(_FURI_LOG_CLR_PURPLE) typedef void (*FuriLogPuts)(const char* data); typedef uint32_t (*FuriLogTimestamp)(void); @@ -54,6 +54,15 @@ void furi_log_init(); void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) _ATTRIBUTE((__format__(__printf__, 3, 4))); +/** Print log record + * + * @param level + * @param format + * @param ... + */ +void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) + _ATTRIBUTE((__format__(__printf__, 2, 3))); + /** Set log level * * @param[in] level The level @@ -95,6 +104,22 @@ void furi_log_set_timestamp(FuriLogTimestamp timestamp); #define FURI_LOG_T(tag, format, ...) \ furi_log_print_format(FuriLogLevelTrace, tag, format, ##__VA_ARGS__) +/** Log methods + * + * @param format The raw format + * @param ... VA Args + */ +#define FURI_LOG_RAW_E(format, ...) \ + furi_log_print_raw_format(FuriLogLevelError, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_W(format, ...) \ + furi_log_print_raw_format(FuriLogLevelWarn, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_I(format, ...) \ + furi_log_print_raw_format(FuriLogLevelInfo, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_D(format, ...) \ + furi_log_print_raw_format(FuriLogLevelDebug, format, ##__VA_ARGS__) +#define FURI_LOG_RAW_T(format, ...) \ + furi_log_print_raw_format(FuriLogLevelTrace, format, ##__VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/lib/subghz/blocks/encoder.c b/lib/subghz/blocks/encoder.c index f3349b5fc..49ec4f177 100644 --- a/lib/subghz/blocks/encoder.c +++ b/lib/subghz/blocks/encoder.c @@ -2,6 +2,8 @@ #include "math.h" #include +#include "furi.h" + #define TAG "SubGhzBlockEncoder" void subghz_protocol_blocks_set_bit_array( @@ -17,21 +19,32 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde return bit_read(data_array[read_index_bit >> 3], 7 - (read_index_bit & 0x7)); } -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit) { - size_t index_bit = 0; + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit) { + size_t bias_bit = 0; size_t size_upload = 0; uint32_t duration = duration_bit; + + if(align_bit == SubGhzProtocolBlockAlignBitRight) { + if(count_bit_data_array & 0x7) { + bias_bit = 8 - (count_bit_data_array & 0x7); + } + } + size_t index_bit = bias_bit; + bool last_bit = subghz_protocol_blocks_get_bit_array(data_array, index_bit++); - for(size_t i = 1; i < count_bit_data_array; i++) { + for(size_t i = 1 + bias_bit; i < count_bit_data_array + bias_bit; i++) { if(last_bit == subghz_protocol_blocks_get_bit_array(data_array, index_bit)) { duration += duration_bit; } else { - furi_assert(max_size_upload > size_upload); + if(size_upload > max_size_upload) { + furi_crash("SubGhz: Encoder buffer overflow"); + } upload[size_upload++] = level_duration_make( subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); last_bit = !last_bit; diff --git a/lib/subghz/blocks/encoder.h b/lib/subghz/blocks/encoder.h index 1ff077726..aeaa2add0 100644 --- a/lib/subghz/blocks/encoder.h +++ b/lib/subghz/blocks/encoder.h @@ -19,6 +19,11 @@ typedef struct { } SubGhzProtocolBlockEncoder; +typedef enum { + SubGhzProtocolBlockAlignBitLeft, + SubGhzProtocolBlockAlignBitRight, +} SubGhzProtocolBlockAlignBit; + /** * Set data bit when encoding HEX array. * @param bit_value The value of the bit to be set @@ -47,13 +52,15 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde * @param upload Pointer to a LevelDuration * @param max_size_upload upload size, check not to overflow * @param duration_bit duration 1 bit + * @param align_bit alignment of useful bits in an array */ -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit); + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit); #ifdef __cplusplus } diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 94114676d..3d59adc82 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -100,7 +100,7 @@ bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperForma FURI_LOG_E(TAG, "Missing Bit"); break; } - instance->data_count_bit = (uint8_t)temp_data; + instance->data_count_bit = (uint16_t)temp_data; uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index d1c7dc356..284df51ae 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -19,7 +19,7 @@ struct SubGhzBlockGeneric { const char* protocol_name; uint64_t data; uint32_t serial; - uint8_t data_count_bit; + uint16_t data_count_bit; uint8_t btn; uint32_t cnt; }; diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c new file mode 100644 index 000000000..c3f544110 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.c @@ -0,0 +1,1120 @@ +#include "bin_raw.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" +#include +#include +#include + +#define TAG "SubGhzProtocolBinRAW" + +//change very carefully, RAM ends at the most inopportune moment +#define BIN_RAW_BUF_RAW_SIZE 2048 +#define BIN_RAW_BUF_DATA_SIZE 512 + +#define BIN_RAW_THRESHOLD_RSSI -85.0f +#define BIN_RAW_DELTA_RSSI 7.0f +#define BIN_RAW_SEARCH_CLASSES 20 +#define BIN_RAW_TE_MIN_COUNT 40 +#define BIN_RAW_BUF_MIN_DATA_COUNT 128 +#define BIN_RAW_MAX_MARKUP_COUNT 20 + +//#define BIN_RAW_DEBUG + +#ifdef BIN_RAW_DEBUG +#define bin_raw_debug(...) FURI_LOG_RAW_D(__VA_ARGS__) +#define bin_raw_debug_tag(tag, ...) \ + FURI_LOG_RAW_D("\033[0;32m[" tag "]\033[0m "); \ + FURI_LOG_RAW_D(__VA_ARGS__) +#else +#define bin_raw_debug(...) +#define bin_raw_debug_tag(...) +#endif + +static const SubGhzBlockConst subghz_protocol_bin_raw_const = { + .te_short = 30, + .te_long = 65000, + .te_delta = 0, + .min_count_bit_for_found = 0, +}; + +typedef enum { + BinRAWDecoderStepReset = 0, + BinRAWDecoderStepWrite, + BinRAWDecoderStepBufFull, + BinRAWDecoderStepNoParse, +} BinRAWDecoderStep; + +typedef enum { + BinRAWTypeUnknown = 0, + BinRAWTypeNoGap, + BinRAWTypeGap, + BinRAWTypeGapRecurring, + BinRAWTypeGapRolling, + BinRAWTypeGapUnknown, +} BinRAWType; + +struct BinRAW_Markup { + uint16_t byte_bias; + uint16_t bit_count; +}; +typedef struct BinRAW_Markup BinRAW_Markup; + +struct SubGhzProtocolDecoderBinRAW { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + int32_t* data_raw; + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + size_t data_raw_ind; + uint32_t te; + float adaptive_threshold_rssi; +}; + +struct SubGhzProtocolEncoderBinRAW { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; + + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + uint32_t te; +}; + +const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder = { + .alloc = subghz_protocol_decoder_bin_raw_alloc, + .free = subghz_protocol_decoder_bin_raw_free, + + .feed = subghz_protocol_decoder_bin_raw_feed, + .reset = subghz_protocol_decoder_bin_raw_reset, + + .get_hash_data = subghz_protocol_decoder_bin_raw_get_hash_data, + .serialize = subghz_protocol_decoder_bin_raw_serialize, + .deserialize = subghz_protocol_decoder_bin_raw_deserialize, + .get_string = subghz_protocol_decoder_bin_raw_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder = { + .alloc = subghz_protocol_encoder_bin_raw_alloc, + .free = subghz_protocol_encoder_bin_raw_free, + + .deserialize = subghz_protocol_encoder_bin_raw_deserialize, + .stop = subghz_protocol_encoder_bin_raw_stop, + .yield = subghz_protocol_encoder_bin_raw_yield, +}; + +const SubGhzProtocol subghz_protocol_bin_raw = { + .name = SUBGHZ_PROTOCOL_BIN_RAW_NAME, + .type = SubGhzProtocolTypeStatic, +#ifdef BIN_RAW_DEBUG + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#else + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_BinRAW | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#endif + .decoder = &subghz_protocol_bin_raw_decoder, + .encoder = &subghz_protocol_bin_raw_encoder, +}; + +static uint16_t subghz_protocol_bin_raw_get_full_byte(uint16_t bit_count) { + if(bit_count & 0x7) { + return (bit_count >> 3) + 1; + } else { + return (bit_count >> 3); + } +} + +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderBinRAW* instance = malloc(sizeof(SubGhzProtocolEncoderBinRAW)); + + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = BIN_RAW_BUF_DATA_SIZE * 5; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->data = malloc(instance->encoder.size_upload * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + free(instance->encoder.upload); + free(instance->data); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return true On success + */ +static bool subghz_protocol_encoder_bin_raw_get_upload(SubGhzProtocolEncoderBinRAW* instance) { + furi_assert(instance); + + //we glue all the pieces of the package into 1 long sequence with left alignment, + //in the uploaded data we have right alignment. + + bin_raw_debug_tag(TAG, "Recovery of offset bits in sequences\r\n"); + uint16_t i = 0; + uint16_t ind = 0; + bin_raw_debug("\tind byte_bias\tbit_count\tbit_bias\r\n"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + uint8_t bit_bias = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + instance->data_markup[i].bit_count; + bin_raw_debug( + "\t%d\t%d\t%d :\t\t%d\r\n", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count, + bit_bias); + for(uint16_t y = instance->data_markup[i].byte_bias * 8; + y < instance->data_markup[i].byte_bias * 8 + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + bit_bias; + y++) { + subghz_protocol_blocks_set_bit_array( + subghz_protocol_blocks_get_bit_array(instance->data, y + bit_bias), + instance->data, + ind++, + BIN_RAW_BUF_DATA_SIZE); + } + i++; + } + bin_raw_debug("\r\n"); +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Restored Sequence left aligned\r\n"); + for(uint16_t y = 0; y < subghz_protocol_bin_raw_get_full_byte(ind); y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + bin_raw_debug("\r\n\tbin_count_result= %d\r\n\r\n", ind); + + bin_raw_debug_tag( + TAG, "Maximum levels encoded in upload %zu\r\n", instance->encoder.size_upload); +#endif + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( + instance->data, + ind, + instance->encoder.upload, + instance->encoder.size_upload, + instance->te, + SubGhzProtocolBlockAlignBitLeft); + + bin_raw_debug_tag(TAG, "The result %zu is levels\r\n", instance->encoder.size_upload); + bin_raw_debug_tag(TAG, "Remaining free memory %zu\r\n", memmgr_get_free_heap()); + return true; +} + +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + +#ifdef BIN_RAW_DEBUG + uint16_t i = 0; + bin_raw_debug_tag(TAG, "Download data to encoder\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + i++; + } + bin_raw_debug("\r\n\r\n"); +#endif + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_encoder_bin_raw_stop(void* context) { + SubGhzProtocolEncoderBinRAW* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context) { + SubGhzProtocolEncoderBinRAW* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderBinRAW* instance = malloc(sizeof(SubGhzProtocolDecoderBinRAW)); + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + instance->data_raw_ind = 0; + instance->data_raw = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + instance->data = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->adaptive_threshold_rssi = BIN_RAW_THRESHOLD_RSSI; + return instance; +} + +void subghz_protocol_decoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + free(instance->data_raw); + free(instance->data); + free(instance); +} + +void subghz_protocol_decoder_bin_raw_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; +#ifdef BIN_RAW_DEBUG + UNUSED(instance); +#else + instance->decoder.parser_step = BinRAWDecoderStepNoParse; + instance->data_raw_ind = 0; +#endif +} + +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + if(instance->decoder.parser_step == BinRAWDecoderStepWrite) { + if(instance->data_raw_ind == BIN_RAW_BUF_RAW_SIZE) { + instance->decoder.parser_step = BinRAWDecoderStepBufFull; + } else { + instance->data_raw[instance->data_raw_ind++] = (level ? duration : -duration); + } + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzProtocolDecoderBinRAW* instance + */ +static bool + subghz_protocol_bin_raw_check_remote_controller(SubGhzProtocolDecoderBinRAW* instance) { + struct { + float data; + uint16_t count; + } classes[BIN_RAW_SEARCH_CLASSES]; + + size_t ind = 0; + + memset(classes, 0x00, sizeof(classes)); + + uint16_t data_markup_ind = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + if(instance->data_raw_ind < 512) { + ind = + instance->data_raw_ind - + 100; //there is usually garbage at the end of the record, we exclude it from the classification + } else { + ind = 512; + } + + //sort the durations to find the shortest correlated interval + for(size_t i = 0; i < ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = (float)(abs(instance->data_raw[i])); + classes[k].count++; + break; + } else if( + DURATION_DIFF((float)(abs(instance->data_raw[i])), (classes[k].data)) < + (classes[k].data / 4)) { //if the test value does not differ by more than 25% + classes[k].data += ((float)(abs(instance->data_raw[i])) - classes[k].data) * + 0.05f; //running average k=0.05 + classes[k].count++; + break; + } + } + } + + // if(classes[BIN_RAW_SEARCH_CLASSES - 1].count != 0) { + // //filling the classifier, it means that they received an unclean signal + // return false; + // } + + //looking for the minimum te with an occurrence greater than BIN_RAW_TE_MIN_COUNT + instance->te = subghz_protocol_bin_raw_const.te_long * 2; + + bool te_ok = false; + uint16_t gap_ind = 0; + uint16_t gap_delta = 0; + uint32_t gap = 0; + int data_temp = 0; + BinRAWType bin_raw_type = BinRAWTypeUnknown; + + //sort by number of occurrences + bool swap = true; + while(swap) { + swap = false; + for(size_t i = 1; i < BIN_RAW_SEARCH_CLASSES; i++) { + if(classes[i].count > classes[i - 1].count) { + uint32_t data = classes[i - 1].data; + uint32_t count = classes[i - 1].count; + classes[i - 1].data = classes[i].data; + classes[i - 1].count = classes[i].count; + classes[i].data = data; + classes[i].count = count; + swap = true; + } + } + } +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Sorted durations\r\n"); + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + if((classes[0].count > BIN_RAW_TE_MIN_COUNT) && (classes[1].count == 0)) { + //adopted only the preamble + instance->te = (uint32_t)classes[0].data; + te_ok = true; + gap = 0; //gap no + } else { + //take the 2 most common durations + //check that there are enough + if((classes[0].count < BIN_RAW_TE_MIN_COUNT) || + (classes[1].count < (BIN_RAW_TE_MIN_COUNT >> 1))) + return false; + //arrange the first 2 date values in ascending order + if(classes[0].data > classes[1].data) { + uint32_t data = classes[1].data; + classes[0].data = classes[1].data; + classes[1].data = data; + } + + //determine the value to be corrected + for(uint8_t k = 1; k < 5; k++) { + float delta = (classes[1].data / (classes[0].data / k)); + bin_raw_debug_tag(TAG, "K_div= %f\r\n", (double)(delta)); + delta -= (uint32_t)delta; + + if((delta < 0.20f) || (delta > 0.80f)) { + instance->te = (uint32_t)classes[0].data / k; + bin_raw_debug_tag(TAG, "K= %d\r\n", k); + te_ok = true; //found a correlated duration + break; + } + } + if(!te_ok) { + //did not find the minimum TE satisfying the condition + return false; + } + bin_raw_debug_tag(TAG, "TE= %lu\r\n\r\n", instance->te); + + //looking for a gap + for(size_t k = 2; k < BIN_RAW_SEARCH_CLASSES; k++) { + if((classes[k].count > 2) && (classes[k].data > gap)) { + gap = (uint32_t)classes[k].data; + gap_delta = gap / 5; //calculate 20% deviation from ideal value + } + } + + if((gap / instance->te) < + 10) { //make an assumption, the longest gap should be more than 10 TE + gap = 0; //check that our signal has a gap greater than 10*TE + bin_raw_type = BinRAWTypeNoGap; + } else { + bin_raw_type = BinRAWTypeGap; + //looking for the last occurrence of gap + ind = instance->data_raw_ind - 1; + while((ind > 0) && (DURATION_DIFF(abs(instance->data_raw[ind]), gap) > gap_delta)) { + ind--; + } + gap_ind = ind; + } + } + + //if we consider that there is a gap, then we divide the signal with respect to this gap + //processing input data from the end + if(bin_raw_type == BinRAWTypeGap) { + bin_raw_debug_tag(TAG, "Tinted sequence\r\n"); + ind = (BIN_RAW_BUF_DATA_SIZE * 8); + uint16_t bit_count = 0; + do { + gap_ind--; + data_temp = (int)(round((float)(instance->data_raw[gap_ind]) / instance->te)); + bin_raw_debug("%d ", data_temp); + if(data_temp == 0) bit_count++; //there is noise in the package + for(size_t i = 0; i < abs(data_temp); i++) { + bit_count++; + if(ind) { + ind--; + } else { + break; + } + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } + } + //split into full bytes if gap is caught + if(DURATION_DIFF(abs(instance->data_raw[gap_ind]), gap) < gap_delta) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + bit_count = 0; + + if(data_markup_ind == BIN_RAW_MAX_MARKUP_COUNT) break; + ind &= 0xFFFFFFF8; //jump to the pre whole byte + } + } while(gap_ind != 0); + if((data_markup_ind != BIN_RAW_MAX_MARKUP_COUNT) && (ind != 0)) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + } + + bin_raw_debug("\r\n\t count bit= %zu\r\n\r\n", (BIN_RAW_BUF_DATA_SIZE * 8) - ind); + + //reset the classifier and classify the received data + memset(classes, 0x00, sizeof(classes)); + + bin_raw_debug_tag(TAG, "Sort the found pieces by the number of bits in them\r\n"); + for(size_t i = 0; i < data_markup_ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = instance->data_markup[i].bit_count; + classes[k].count++; + break; + } else if(instance->data_markup[i].bit_count == (uint16_t)classes[k].data) { + classes[k].count++; + break; + } + } + } + +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + + //choose the value with the maximum repetition + data_temp = 0; + for(size_t i = 0; i < BIN_RAW_SEARCH_CLASSES; i++) { + if((classes[i].count > 1) && (data_temp < classes[i].count)) + data_temp = (int)classes[i].data; + } + + //if(data_markup_ind == 0) return false; + +#ifdef BIN_RAW_DEBUG + //output in reverse order + bin_raw_debug_tag(TAG, "Found sequences\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + uint16_t data_markup_ind_temp = data_markup_ind; + if(data_markup_ind) { + data_markup_ind_temp--; + for(size_t i = (ind / 8); i < BIN_RAW_BUF_DATA_SIZE; i++) { + if(instance->data_markup[data_markup_ind_temp].byte_bias == i) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + data_markup_ind_temp, + instance->data_markup[data_markup_ind_temp].byte_bias, + instance->data_markup[data_markup_ind_temp].bit_count); + if(data_markup_ind_temp != 0) data_markup_ind_temp--; + } + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); + } + //compare data in chunks with the same number of bits + bin_raw_debug_tag(TAG, "Analyze sequences of long %d bit\r\n\r\n", data_temp); +#endif + + //if(data_temp == 0) data_temp = (int)classes[0].data; + + if(data_temp != 0) { + //check that data in transmission is repeated every packet + for(uint16_t i = 0; i < data_markup_ind - 1; i++) { + if((instance->data_markup[i].bit_count == data_temp) && + (instance->data_markup[i + 1].bit_count == data_temp)) { + //if the number of bits in adjacent parcels is the same, compare the data + bin_raw_debug_tag( + TAG, + "Comparison of neighboring sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + i + 1, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[i + 1].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[i + 1].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i + 1].bit_count) - + 1]); + + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + if(memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[i + 1].byte_bias, + byte_count - 1) == 0) { + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRecurring\r\n\r\n"); + + //place in 1 element the offset to valid data + instance->data_markup[0].bit_count = instance->data_markup[i].bit_count; + instance->data_markup[0].byte_bias = instance->data_markup[i].byte_bias; + //markup end sign + instance->data_markup[1].bit_count = 0; + instance->data_markup[1].byte_bias = 0; + + bin_raw_type = BinRAWTypeGapRecurring; + i = data_markup_ind; + break; + } + } + } + } + + if(bin_raw_type == BinRAWTypeGap) { + // check that retry occurs every n packets + for(uint16_t i = 0; i < data_markup_ind - 2; i++) { + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + for(uint16_t y = i + 1; y < data_markup_ind - 1; y++) { + bin_raw_debug_tag( + TAG, + "Comparison every N sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + y, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[y].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[y].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count) - + 1]); + + if(byte_count == + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count)) { //if the length in bytes matches + + if((memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[y].byte_bias, + byte_count - 1) == 0) && + (memcmp( + instance->data + instance->data_markup[i + 1].byte_bias, + instance->data + instance->data_markup[y + 1].byte_bias, + byte_count - 1) == 0)) { + uint8_t index = 0; +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRolling\r\n\r\n"); + //output in reverse order + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + index = y - 1; + for(size_t z = instance->data_markup[y].byte_bias + byte_count; + z < instance->data_markup[i].byte_bias + byte_count; + z++) { + if(instance->data_markup[index].byte_bias == z) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + index, + instance->data_markup[index].byte_bias, + instance->data_markup[index].bit_count); + if(index != 0) index--; + } + bin_raw_debug("%02X ", instance->data[z]); + } + + bin_raw_debug("\r\n\r\n"); +#endif + //todo can be optimized + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, + 0x00, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + for(index = i; index < y; index++) { + instance->data_markup[index - i].bit_count = + markup_temp[y - index - 1].bit_count; + instance->data_markup[index - i].byte_bias = + markup_temp[y - index - 1].byte_bias; + } + + bin_raw_type = BinRAWTypeGapRolling; + i = data_markup_ind; + break; + } + } + } + } + } + //todo can be optimized + if(bin_raw_type == BinRAWTypeGap) { + if(data_temp != 0) { //there are sequences with the same number of bits + + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(data_temp); + uint16_t index = 0; + uint16_t it = BIN_RAW_MAX_MARKUP_COUNT; + do { + it--; + if(subghz_protocol_bin_raw_get_full_byte(markup_temp[it].bit_count) == + byte_count) { + instance->data_markup[index].bit_count = markup_temp[it].bit_count; + instance->data_markup[index].byte_bias = markup_temp[it].byte_bias; + index++; + bin_raw_type = BinRAWTypeGapUnknown; + } + } while(it != 0); + } + } + + if(bin_raw_type != BinRAWTypeGap) + return true; + else + return false; + + } else { + // if bin_raw_type == BinRAWTypeGap + bin_raw_debug_tag(TAG, "Sequence analysis without gap\r\n"); + ind = 0; + for(size_t i = 0; i < instance->data_raw_ind; i++) { + int data_temp = (int)(round((float)(instance->data_raw[i]) / instance->te)); + if(data_temp == 0) break; //found an interval 2 times shorter than TE, this is noise + bin_raw_debug("%d ", data_temp); + + for(size_t k = 0; k < abs(data_temp); k++) { + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } + if(ind == BIN_RAW_BUF_DATA_SIZE * 8) { + i = instance->data_raw_ind; + break; + } + } + } + + if(ind != 0) { + bin_raw_type = BinRAWTypeNoGap; + //right alignment + uint8_t bit_bias = (subghz_protocol_bin_raw_get_full_byte(ind) << 3) - ind; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t count bit= %zu\tcount full byte= %d\tbias bit= %d\r\n\r\n", + ind, + subghz_protocol_bin_raw_get_full_byte(ind), + bit_bias); + + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + //checking that the received sequence contains useful data + bool data_check = false; + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + if(instance->data[i] != 0) { + data_check = true; + break; + } + } + + if(data_check) { + for(size_t i = subghz_protocol_bin_raw_get_full_byte(ind) - 1; i > 0; i--) { + instance->data[i] = (instance->data[i - 1] << (8 - bit_bias)) | + (instance->data[i] >> bit_bias); + } + instance->data[0] = (instance->data[0] >> bit_bias); + +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Data right alignment\r\n"); + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + instance->data_markup[0].bit_count = ind; + instance->data_markup[0].byte_bias = 0; + + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; +} + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi) { + furi_assert(instance); + switch(instance->decoder.parser_step) { + case BinRAWDecoderStepReset: + + bin_raw_debug("%ld %ld :", (int32_t)rssi, (int32_t)instance->adaptive_threshold_rssi); + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + instance->data_raw_ind = 0; + memset(instance->data_raw, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + memset(instance->data, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + instance->decoder.parser_step = BinRAWDecoderStepWrite; + bin_raw_debug_tag(TAG, "RSSI\r\n"); + } else { + //adaptive noise level adjustment + instance->adaptive_threshold_rssi += (rssi - instance->adaptive_threshold_rssi) * 0.2f; + } + break; + + case BinRAWDecoderStepBufFull: + case BinRAWDecoderStepWrite: +#ifdef BIN_RAW_DEBUG + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + bin_raw_debug("\033[0;32m%ld \033[0m ", (int32_t)rssi); + } else { + bin_raw_debug("%ld ", (int32_t)rssi); + } +#endif + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\r\n\r\n"); + bin_raw_debug_tag(TAG, "Data for analysis, positive high, negative low, us\r\n"); + for(size_t i = 0; i < instance->data_raw_ind; i++) { + bin_raw_debug("%ld ", instance->data_raw[i]); + } + bin_raw_debug("\r\n\t count data= %zu\r\n\r\n", instance->data_raw_ind); +#endif + instance->decoder.parser_step = BinRAWDecoderStepReset; + instance->generic.data_count_bit = 0; + if(instance->data_raw_ind >= BIN_RAW_BUF_MIN_DATA_COUNT) { + if(subghz_protocol_bin_raw_check_remote_controller(instance)) { + bin_raw_debug_tag(TAG, "Sequence found\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && + (instance->data_markup[i].bit_count != 0)) { + instance->generic.data_count_bit += instance->data_markup[i].bit_count; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } +#endif + i++; + } + bin_raw_debug("\r\n"); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + } + break; + + default: + //if instance->decoder.parser_step == BinRAWDecoderStepNoParse or others, restore the initial state + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { + instance->decoder.parser_step = BinRAWDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + return subghz_protocol_blocks_add_bytes( + instance->data + instance->data_markup[0].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[0].bit_count)); +} + +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + FuriString* temp_str; + temp_str = furi_string_alloc(); + do { + stream_clean(flipper_format_get_raw_stream(flipper_format)); + if(!flipper_format_write_header_cstr( + flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { + FURI_LOG_E(TAG, "Unable to add header"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { + FURI_LOG_E(TAG, "Unable to add Frequency"); + break; + } + + subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); + if(!flipper_format_write_string_cstr( + flipper_format, "Preset", furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Unable to add Preset"); + break; + } + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!flipper_format_write_string_cstr( + flipper_format, "Custom_preset_module", "CC1101")) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + break; + } + if(!flipper_format_write_hex( + flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + break; + } + } + if(!flipper_format_write_string_cstr( + flipper_format, "Protocol", instance->generic.protocol_name)) { + FURI_LOG_E(TAG, "Unable to add Protocol"); + break; + } + + uint32_t temp = instance->generic.data_count_bit; + if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) { + FURI_LOG_E(TAG, "Unable to add Bit"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + FURI_LOG_E(TAG, "Unable to add TE"); + break; + } + + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + temp = instance->data_markup[i].bit_count; + if(!flipper_format_write_uint32(flipper_format, "Bit_RAW", &temp, 1)) { + FURI_LOG_E(TAG, "Bit_RAW"); + break; + } + if(!flipper_format_write_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[i].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count))) { + FURI_LOG_E(TAG, "Unable to add Data_RAW"); + break; + } + i++; + } + + res = true; + } while(false); + furi_string_free(temp_str); + return res; +} + +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:", + instance->generic.protocol_name, + instance->generic.data_count_bit); + + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(instance->generic.data_count_bit); + for(size_t i = 0; (byte_count < 36 ? i < byte_count : i < 36); i++) { + furi_string_cat_printf(output, "%02X", instance->data[i]); + } + + furi_string_cat_printf(output, "\r\nTe:%luus\r\n", instance->te); +} diff --git a/lib/subghz/protocols/bin_raw.h b/lib/subghz/protocols/bin_raw.h new file mode 100644 index 000000000..c63f86ce6 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_BIN_RAW_NAME "BinRAW" + +typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; +typedef struct SubGhzProtocolEncoderBinRAW SubGhzProtocolEncoderBinRAW; + +extern const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder; +extern const SubGhzProtocol subghz_protocol_bin_raw; + +/** + * Allocate SubGhzProtocolEncoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderBinRAW* pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderBinRAW. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderBinRAW* pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context); + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi); + +/** + * Serialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param output Resulting text + */ +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 32f4e9520..9c8e5ee4a 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -196,12 +196,13 @@ static bool break; } - instance->encoder.size_upload = subghz_protocol_blocks_get_upload( + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( upload_hex_data, upload_hex_count_bit, instance->encoder.upload, instance->encoder.size_upload, - subghz_protocol_chamb_code_const.te_short); + subghz_protocol_chamb_code_const.te_short, + SubGhzProtocolBlockAlignBitLeft); return true; } diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 050904eec..74244c5ff 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -42,6 +42,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_dooya, &subghz_protocol_alutech_at_4n, &subghz_protocol_kinggates_stylo_4k, + &subghz_protocol_bin_raw, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 522931d22..4ca1c4679 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -42,5 +42,6 @@ #include "dooya.h" #include "alutech_at_4n.h" #include "kinggates_stylo_4k.h" +#include "bin_raw.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 7b79892b0..f7262bd17 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -261,16 +261,16 @@ static bool data = order << 4 | invert; int k = 0; for(int i = 6; i >= 0; i -= 2) { - roll_array[k++] = (data >> i) & 0x03; - if(roll_array[k] == 3) { + roll_array[k] = (data >> i) & 0x03; + if(roll_array[k++] == 3) { FURI_LOG_E(TAG, "Roll_Array FAIL"); return false; } } for(int i = 8; i >= 0; i -= 2) { - roll_array[k++] = (p[2] >> i) & 0x03; - if(roll_array[k] == 3) { + roll_array[k] = (p[2] >> i) & 0x03; + if(roll_array[k++] == 3) { FURI_LOG_E(TAG, "Roll_Array FAIL"); return false; } diff --git a/lib/subghz/receiver.c b/lib/subghz/receiver.c index fd6f1493e..698fe098e 100644 --- a/lib/subghz/receiver.c +++ b/lib/subghz/receiver.c @@ -64,7 +64,7 @@ void subghz_receiver_decode(SubGhzReceiver* instance, bool level, uint32_t durat for M_EACH(slot, instance->slots, SubGhzReceiverSlotArray_t) { - if((slot->base->protocol->flag & instance->filter) == instance->filter) { + if((slot->base->protocol->flag & instance->filter) != 0) { slot->base->protocol->decoder->feed(slot->base, level, duration); } } diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 6c34dc728..1b8ef6a14 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -90,6 +90,7 @@ typedef enum { SubGhzProtocolFlag_Save = (1 << 7), SubGhzProtocolFlag_Load = (1 << 8), SubGhzProtocolFlag_Send = (1 << 9), + SubGhzProtocolFlag_BinRAW = (1 << 10), } SubGhzProtocolFlag; typedef struct { diff --git a/lib/toolbox/level_duration.h b/lib/toolbox/level_duration.h index 9406cef31..7618344ac 100644 --- a/lib/toolbox/level_duration.h +++ b/lib/toolbox/level_duration.h @@ -13,8 +13,8 @@ #define LEVEL_DURATION_RESERVED 0x800000U typedef struct { - uint32_t level; - uint32_t duration; + uint32_t duration : 30; + uint8_t level : 2; } LevelDuration; static inline LevelDuration level_duration_make(bool level, uint32_t duration) { From 4265057ee864a8d68a68e9a9ef4088b39d2b1e5c Mon Sep 17 00:00:00 2001 From: Petr Portnov | PROgrm_JARvis Date: Thu, 9 Feb 2023 07:58:01 +0300 Subject: [PATCH 25/34] feat: add missing `const` qualifiers (#2233) * feat: make `ViewPort` getters const * feat: make tx-buffers const * feat: make `canvas_get_buffer_size` const * feat: make `canvas` methods const * feat: make `icon_animation` methods const * feat: make `scene_manager` methods const * feat: make `loader` method const * feat: make `canvas_get_font_params` const Co-authored-by: Aleksandr Kutuzov --- applications/services/gui/canvas.c | 12 +++--- applications/services/gui/canvas.h | 8 ++-- applications/services/gui/canvas_i.h | 2 +- applications/services/gui/elements.c | 2 +- applications/services/gui/gui.c | 2 +- applications/services/gui/gui.h | 2 +- applications/services/gui/icon_animation.c | 8 ++-- applications/services/gui/icon_animation.h | 6 +-- applications/services/gui/icon_animation_i.h | 2 +- .../widget_element_text_scroll.c | 4 +- applications/services/gui/scene_manager.c | 4 +- applications/services/gui/scene_manager.h | 4 +- applications/services/gui/view_port.c | 6 +-- applications/services/gui/view_port.h | 6 +-- applications/services/loader/loader.c | 2 +- applications/services/loader/loader.h | 2 +- applications/services/locale/locale.h | 2 +- firmware/targets/f18/api_symbols.csv | 35 ++++++++--------- firmware/targets/f7/api_symbols.csv | 38 +++++++++---------- firmware/targets/f7/furi_hal/furi_hal_spi.c | 4 +- .../targets/furi_hal_include/furi_hal_spi.h | 4 +- 21 files changed, 78 insertions(+), 77 deletions(-) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 18636eced..d47bba6b2 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -57,7 +57,7 @@ uint8_t* canvas_get_buffer(Canvas* canvas) { return u8g2_GetBufferPtr(&canvas->fb); } -size_t canvas_get_buffer_size(Canvas* canvas) { +size_t canvas_get_buffer_size(const Canvas* canvas) { furi_assert(canvas); return u8g2_GetBufferTileWidth(&canvas->fb) * u8g2_GetBufferTileHeight(&canvas->fb) * 8; } @@ -75,17 +75,17 @@ void canvas_frame_set( canvas->height = height; } -uint8_t canvas_width(Canvas* canvas) { +uint8_t canvas_width(const Canvas* canvas) { furi_assert(canvas); return canvas->width; } -uint8_t canvas_height(Canvas* canvas) { +uint8_t canvas_height(const Canvas* canvas) { furi_assert(canvas); return canvas->height; } -uint8_t canvas_current_font_height(Canvas* canvas) { +uint8_t canvas_current_font_height(const Canvas* canvas) { furi_assert(canvas); uint8_t font_height = u8g2_GetMaxCharHeight(&canvas->fb); @@ -96,10 +96,10 @@ uint8_t canvas_current_font_height(Canvas* canvas) { return font_height; } -CanvasFontParameters* canvas_get_font_params(Canvas* canvas, Font font) { +const CanvasFontParameters* canvas_get_font_params(const Canvas* canvas, Font font) { furi_assert(canvas); furi_assert(font < FontTotalNumber); - return (CanvasFontParameters*)&canvas_font_params[font]; + return &canvas_font_params[font]; } void canvas_clear(Canvas* canvas) { diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index b2a065ca7..f8fe2c1db 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -85,7 +85,7 @@ void canvas_commit(Canvas* canvas); * * @return width in pixels. */ -uint8_t canvas_width(Canvas* canvas); +uint8_t canvas_width(const Canvas* canvas); /** Get Canvas height * @@ -93,7 +93,7 @@ uint8_t canvas_width(Canvas* canvas); * * @return height in pixels. */ -uint8_t canvas_height(Canvas* canvas); +uint8_t canvas_height(const Canvas* canvas); /** Get current font height * @@ -101,7 +101,7 @@ uint8_t canvas_height(Canvas* canvas); * * @return height in pixels. */ -uint8_t canvas_current_font_height(Canvas* canvas); +uint8_t canvas_current_font_height(const Canvas* canvas); /** Get font parameters * @@ -110,7 +110,7 @@ uint8_t canvas_current_font_height(Canvas* canvas); * * @return pointer to CanvasFontParameters structure */ -CanvasFontParameters* canvas_get_font_params(Canvas* canvas, Font font); +const CanvasFontParameters* canvas_get_font_params(const Canvas* canvas, Font font); /** Clear canvas * diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index 2b6849235..12cabfa7d 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -45,7 +45,7 @@ uint8_t* canvas_get_buffer(Canvas* canvas); * * @return size of canvas in bytes */ -size_t canvas_get_buffer_size(Canvas* canvas); +size_t canvas_get_buffer_size(const Canvas* canvas); /** Set drawing region relative to real screen buffer * diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 54c36af76..9b7c84ece 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -639,7 +639,7 @@ void elements_text_box( bool inversed_present = false; Font current_font = FontSecondary; Font prev_font = FontSecondary; - CanvasFontParameters* font_params = canvas_get_font_params(canvas, current_font); + const CanvasFontParameters* font_params = canvas_get_font_params(canvas, current_font); // Fill line parameters uint8_t line_leading_min = font_params->leading_min; diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index af5cf862d..94bab1402 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -467,7 +467,7 @@ void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, gui_unlock(gui); } -size_t gui_get_framebuffer_size(Gui* gui) { +size_t gui_get_framebuffer_size(const Gui* gui) { furi_assert(gui); return canvas_get_buffer_size(gui->canvas); } diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index 4e7fc2e4d..d7d73f27b 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -94,7 +94,7 @@ void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, * @param gui Gui instance * @return size_t size of frame buffer in bytes */ -size_t gui_get_framebuffer_size(Gui* gui); +size_t gui_get_framebuffer_size(const Gui* gui); /** Set lockdown mode * diff --git a/applications/services/gui/icon_animation.c b/applications/services/gui/icon_animation.c index 48c862208..b63d233f3 100644 --- a/applications/services/gui/icon_animation.c +++ b/applications/services/gui/icon_animation.c @@ -29,7 +29,7 @@ void icon_animation_set_update_callback( instance->callback_context = context; } -const uint8_t* icon_animation_get_data(IconAnimation* instance) { +const uint8_t* icon_animation_get_data(const IconAnimation* instance) { return instance->icon->frames[instance->frame]; } @@ -51,12 +51,12 @@ void icon_animation_timer_callback(void* context) { } } -uint8_t icon_animation_get_width(IconAnimation* instance) { +uint8_t icon_animation_get_width(const IconAnimation* instance) { furi_assert(instance); return instance->icon->width; } -uint8_t icon_animation_get_height(IconAnimation* instance) { +uint8_t icon_animation_get_height(const IconAnimation* instance) { furi_assert(instance); return instance->icon->height; } @@ -83,7 +83,7 @@ void icon_animation_stop(IconAnimation* instance) { } } -bool icon_animation_is_last_frame(IconAnimation* instance) { +bool icon_animation_is_last_frame(const IconAnimation* instance) { furi_assert(instance); return instance->icon->frame_count - instance->frame <= 1; } diff --git a/applications/services/gui/icon_animation.h b/applications/services/gui/icon_animation.h index 684790353..6e58df31d 100644 --- a/applications/services/gui/icon_animation.h +++ b/applications/services/gui/icon_animation.h @@ -55,7 +55,7 @@ void icon_animation_set_update_callback( * * @return width in pixels */ -uint8_t icon_animation_get_width(IconAnimation* instance); +uint8_t icon_animation_get_width(const IconAnimation* instance); /** Get icon animation height * @@ -63,7 +63,7 @@ uint8_t icon_animation_get_width(IconAnimation* instance); * * @return height in pixels */ -uint8_t icon_animation_get_height(IconAnimation* instance); +uint8_t icon_animation_get_height(const IconAnimation* instance); /** Start icon animation * @@ -83,7 +83,7 @@ void icon_animation_stop(IconAnimation* instance); * * @return true if last frame */ -bool icon_animation_is_last_frame(IconAnimation* instance); +bool icon_animation_is_last_frame(const IconAnimation* instance); #ifdef __cplusplus } diff --git a/applications/services/gui/icon_animation_i.h b/applications/services/gui/icon_animation_i.h index 4053a120d..62858d288 100644 --- a/applications/services/gui/icon_animation_i.h +++ b/applications/services/gui/icon_animation_i.h @@ -24,7 +24,7 @@ struct IconAnimation { * * @return pointer to current frame XBM bitmap data */ -const uint8_t* icon_animation_get_data(IconAnimation* instance); +const uint8_t* icon_animation_get_data(const IconAnimation* instance); /** Advance to next frame * diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c index d8fc11311..5d522c74b 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c @@ -74,7 +74,7 @@ static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* } // Set canvas font canvas_set_font(canvas, line_tmp.font); - CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); + const CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); total_height += params->height; if(total_height > model->height) { model->scroll_pos_total++; @@ -138,7 +138,7 @@ static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* eleme TextScrollLineArray_next(it), curr_line++) { if(curr_line < model->scroll_pos_current) continue; TextScrollLineArray* line = TextScrollLineArray_ref(it); - CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); + const CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); if(y + params->descender > model->y + model->height) break; canvas_set_font(canvas, line->font); if(line->horizontal == AlignLeft) { diff --git a/applications/services/gui/scene_manager.c b/applications/services/gui/scene_manager.c index 590145e1e..4064dafb6 100644 --- a/applications/services/gui/scene_manager.c +++ b/applications/services/gui/scene_manager.c @@ -34,7 +34,7 @@ void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_i scene_manager->scene[scene_id].state = state; } -uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id) { +uint32_t scene_manager_get_scene_state(const SceneManager* scene_manager, uint32_t scene_id) { furi_assert(scene_manager); furi_assert(scene_id < scene_manager->scene_handlers->scene_num); @@ -184,7 +184,7 @@ bool scene_manager_search_and_switch_to_previous_scene_one_of( return scene_found; } -bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) { +bool scene_manager_has_previous_scene(const SceneManager* scene_manager, uint32_t scene_id) { furi_assert(scene_manager); bool scene_found = false; diff --git a/applications/services/gui/scene_manager.h b/applications/services/gui/scene_manager.h index 5b833e5de..c349a12ce 100644 --- a/applications/services/gui/scene_manager.h +++ b/applications/services/gui/scene_manager.h @@ -63,7 +63,7 @@ void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_i * * @return Scene state */ -uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id); +uint32_t scene_manager_get_scene_state(const SceneManager* scene_manager, uint32_t scene_id); /** Scene Manager allocation and configuration * @@ -134,7 +134,7 @@ bool scene_manager_previous_scene(SceneManager* scene_manager); * * @return true if previous scene was found, false otherwise */ -bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id); +bool scene_manager_has_previous_scene(const SceneManager* scene_manager, uint32_t scene_id); /** Search and switch to previous Scene * diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index ffd01450b..5760ed577 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -89,7 +89,7 @@ void view_port_set_width(ViewPort* view_port, uint8_t width) { view_port->width = width; } -uint8_t view_port_get_width(ViewPort* view_port) { +uint8_t view_port_get_width(const ViewPort* view_port) { furi_assert(view_port); return view_port->width; } @@ -99,7 +99,7 @@ void view_port_set_height(ViewPort* view_port, uint8_t height) { view_port->height = height; } -uint8_t view_port_get_height(ViewPort* view_port) { +uint8_t view_port_get_height(const ViewPort* view_port) { furi_assert(view_port); return view_port->height; } @@ -112,7 +112,7 @@ void view_port_enabled_set(ViewPort* view_port, bool enabled) { } } -bool view_port_is_enabled(ViewPort* view_port) { +bool view_port_is_enabled(const ViewPort* view_port) { furi_assert(view_port); return view_port->is_enabled; } diff --git a/applications/services/gui/view_port.h b/applications/services/gui/view_port.h index 703e99248..752fc46ba 100644 --- a/applications/services/gui/view_port.h +++ b/applications/services/gui/view_port.h @@ -56,7 +56,7 @@ void view_port_free(ViewPort* view_port); * @param width wanted width, 0 - auto. */ void view_port_set_width(ViewPort* view_port, uint8_t width); -uint8_t view_port_get_width(ViewPort* view_port); +uint8_t view_port_get_width(const ViewPort* view_port); /** Set view_port height. * @@ -66,7 +66,7 @@ uint8_t view_port_get_width(ViewPort* view_port); * @param height wanted height, 0 - auto. */ void view_port_set_height(ViewPort* view_port, uint8_t height); -uint8_t view_port_get_height(ViewPort* view_port); +uint8_t view_port_get_height(const ViewPort* view_port); /** Enable or disable view_port rendering. * @@ -75,7 +75,7 @@ uint8_t view_port_get_height(ViewPort* view_port); * @warning automatically dispatches update event */ void view_port_enabled_set(ViewPort* view_port, bool enabled); -bool view_port_is_enabled(ViewPort* view_port); +bool view_port_is_enabled(const ViewPort* view_port); /** ViewPort event callbacks * diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 97d1e6e4e..caaf9f11b 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -262,7 +262,7 @@ void loader_unlock(Loader* instance) { FURI_CRITICAL_EXIT(); } -bool loader_is_locked(Loader* instance) { +bool loader_is_locked(const Loader* instance) { return instance->lock_count > 0; } diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index 954e79c57..8dbc4fc35 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -43,7 +43,7 @@ bool loader_lock(Loader* instance); void loader_unlock(Loader* instance); /** Get loader lock status */ -bool loader_is_locked(Loader* instance); +bool loader_is_locked(const Loader* instance); /** Show primary loader */ void loader_show_menu(); diff --git a/applications/services/locale/locale.h b/applications/services/locale/locale.h index 5f2a4d87f..61fb4c605 100644 --- a/applications/services/locale/locale.h +++ b/applications/services/locale/locale.h @@ -81,7 +81,7 @@ void locale_format_time( * * @return The Locale DateFormat. */ -LocaleDateFormat locale_get_date_format(); +LocaleDateFormat locale_get_date_format(void); /** Set Locale DateFormat * diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index d29d696fc..462fbf739 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.1,, +Version,+,14.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -522,7 +522,7 @@ Function,-,bzero,void,"void*, size_t" Function,-,calloc,void*,"size_t, size_t" Function,+,canvas_clear,void,Canvas* Function,+,canvas_commit,void,Canvas* -Function,+,canvas_current_font_height,uint8_t,Canvas* +Function,+,canvas_current_font_height,uint8_t,const Canvas* Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t" @@ -539,9 +539,9 @@ Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" -Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font" +Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, char" -Function,+,canvas_height,uint8_t,Canvas* +Function,+,canvas_height,uint8_t,const Canvas* Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" @@ -550,7 +550,7 @@ Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" -Function,+,canvas_width,uint8_t,Canvas* +Function,+,canvas_width,uint8_t,const Canvas* Function,-,cfree,void,void* Function,-,clearerr,void,FILE* Function,-,clearerr_unlocked,void,FILE* @@ -1063,9 +1063,9 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, @@ -1123,6 +1123,7 @@ Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." +Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel Function,-,furi_log_set_puts,void,FuriLogPuts Function,-,furi_log_set_timestamp,void,FuriLogTimestamp @@ -1287,7 +1288,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,+,gui_get_framebuffer_size,size_t,Gui* +Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" Function,+,gui_set_lockdown,void,"Gui*, _Bool" @@ -1301,9 +1302,9 @@ Function,+,hmac_sha256_init,void,"hmac_sha256_context*, const uint8_t*" Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, unsigned" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* -Function,+,icon_animation_get_height,uint8_t,IconAnimation* -Function,+,icon_animation_get_width,uint8_t,IconAnimation* -Function,+,icon_animation_is_last_frame,_Bool,IconAnimation* +Function,+,icon_animation_get_height,uint8_t,const IconAnimation* +Function,+,icon_animation_get_width,uint8_t,const IconAnimation* +Function,+,icon_animation_is_last_frame,_Bool,const IconAnimation* Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*" Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* @@ -1352,7 +1353,7 @@ Function,-,ldiv,ldiv_t,"long, long" Function,-,llabs,long long,long long Function,-,lldiv,lldiv_t,"long long, long long" Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,Loader* +Function,+,loader_is_locked,_Bool,const Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void, Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" @@ -1570,11 +1571,11 @@ Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t Function,-,scanf,int,"const char*, ..." Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" Function,+,scene_manager_free,void,SceneManager* -Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t" +Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t" Function,+,scene_manager_handle_back_event,_Bool,SceneManager* Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t" Function,+,scene_manager_handle_tick_event,void,SceneManager* -Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_has_previous_scene,_Bool,"const SceneManager*, uint32_t" Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t" Function,+,scene_manager_previous_scene,_Bool,SceneManager* Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t" @@ -1946,11 +1947,11 @@ Function,+,view_port_alloc,ViewPort*, Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" Function,+,view_port_enabled_set,void,"ViewPort*, _Bool" Function,+,view_port_free,void,ViewPort* -Function,+,view_port_get_height,uint8_t,ViewPort* +Function,+,view_port_get_height,uint8_t,const ViewPort* Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort* -Function,+,view_port_get_width,uint8_t,ViewPort* +Function,+,view_port_get_width,uint8_t,const ViewPort* Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*" -Function,+,view_port_is_enabled,_Bool,ViewPort* +Function,+,view_port_is_enabled,_Bool,const ViewPort* Function,+,view_port_set_height,void,"ViewPort*, uint8_t" Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation" Function,+,view_port_set_width,void,"ViewPort*, uint8_t" diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 906ab357a..33c443ae0 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.1,, +Version,+,14.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -607,7 +607,7 @@ Function,-,bzero,void,"void*, size_t" Function,-,calloc,void*,"size_t, size_t" Function,+,canvas_clear,void,Canvas* Function,+,canvas_commit,void,Canvas* -Function,+,canvas_current_font_height,uint8_t,Canvas* +Function,+,canvas_current_font_height,uint8_t,const Canvas* Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t" @@ -624,18 +624,18 @@ Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" -Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font" +Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, char" -Function,+,canvas_height,uint8_t,Canvas* +Function,+,canvas_height,uint8_t,const Canvas* Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" Function,+,canvas_set_color,void,"Canvas*, Color" -Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" +Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" -Function,+,canvas_width,uint8_t,Canvas* +Function,+,canvas_width,uint8_t,const Canvas* Function,-,cbrt,double,double Function,-,cbrtf,float,float Function,-,cbrtl,long double,long double @@ -1095,7 +1095,6 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t" Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*" Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin* Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin* -Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed" Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn" Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode" @@ -1249,6 +1248,7 @@ Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t Function,+,furi_hal_region_is_provisioned,_Bool, Function,+,furi_hal_region_set,void,FuriHalRegion* Function,-,furi_hal_resources_deinit_early,void, +Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin* Function,-,furi_hal_resources_init,void, Function,-,furi_hal_resources_init_early,void, Function,+,furi_hal_rfid_change_read_config,void,"float, float" @@ -1319,9 +1319,9 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, @@ -1578,7 +1578,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,+,gui_get_framebuffer_size,size_t,Gui* +Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" Function,+,gui_set_lockdown,void,"Gui*, _Bool" @@ -1621,9 +1621,9 @@ Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorker Function,+,ibutton_worker_write_start,void,"iButtonWorker*, iButtonKey*" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* -Function,+,icon_animation_get_height,uint8_t,IconAnimation* -Function,+,icon_animation_get_width,uint8_t,IconAnimation* -Function,+,icon_animation_is_last_frame,_Bool,IconAnimation* +Function,+,icon_animation_get_height,uint8_t,const IconAnimation* +Function,+,icon_animation_get_width,uint8_t,const IconAnimation* +Function,+,icon_animation_is_last_frame,_Bool,const IconAnimation* Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*" Function,+,icon_animation_start,void,IconAnimation* Function,+,icon_animation_stop,void,IconAnimation* @@ -1763,7 +1763,7 @@ Function,-,llround,long long int,double Function,-,llroundf,long long int,float Function,-,llroundl,long long int,long double Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,Loader* +Function,+,loader_is_locked,_Bool,const Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void, Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" @@ -2372,11 +2372,11 @@ Function,-,scalbnl,long double,"long double, int" Function,-,scanf,int,"const char*, ..." Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" Function,+,scene_manager_free,void,SceneManager* -Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t" +Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t" Function,+,scene_manager_handle_back_event,_Bool,SceneManager* Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t" Function,+,scene_manager_handle_tick_event,void,SceneManager* -Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t" +Function,+,scene_manager_has_previous_scene,_Bool,"const SceneManager*, uint32_t" Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t" Function,+,scene_manager_previous_scene,_Bool,SceneManager* Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t" @@ -2895,11 +2895,11 @@ Function,+,view_port_alloc,ViewPort*, Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*" Function,+,view_port_enabled_set,void,"ViewPort*, _Bool" Function,+,view_port_free,void,ViewPort* -Function,+,view_port_get_height,uint8_t,ViewPort* +Function,+,view_port_get_height,uint8_t,const ViewPort* Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort* -Function,+,view_port_get_width,uint8_t,ViewPort* +Function,+,view_port_get_width,uint8_t,const ViewPort* Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*" -Function,+,view_port_is_enabled,_Bool,ViewPort* +Function,+,view_port_is_enabled,_Bool,const ViewPort* Function,+,view_port_set_height,void,"ViewPort*, uint8_t" Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation" Function,+,view_port_set_width,void,"ViewPort*, uint8_t" diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index 8dba8327f..42b854799 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -103,7 +103,7 @@ bool furi_hal_spi_bus_rx( bool furi_hal_spi_bus_tx( FuriHalSpiBusHandle* handle, - uint8_t* buffer, + const uint8_t* buffer, size_t size, uint32_t timeout) { furi_assert(handle); @@ -128,7 +128,7 @@ bool furi_hal_spi_bus_tx( bool furi_hal_spi_bus_trx( FuriHalSpiBusHandle* handle, - uint8_t* tx_buffer, + const uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/firmware/targets/furi_hal_include/furi_hal_spi.h index 79e809317..af15a8838 100644 --- a/firmware/targets/furi_hal_include/furi_hal_spi.h +++ b/firmware/targets/furi_hal_include/furi_hal_spi.h @@ -85,7 +85,7 @@ bool furi_hal_spi_bus_rx( */ bool furi_hal_spi_bus_tx( FuriHalSpiBusHandle* handle, - uint8_t* buffer, + const uint8_t* buffer, size_t size, uint32_t timeout); @@ -101,7 +101,7 @@ bool furi_hal_spi_bus_tx( */ bool furi_hal_spi_bus_trx( FuriHalSpiBusHandle* handle, - uint8_t* tx_buffer, + const uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); From 82c730b6bec8095fea3aef1aaf2014212b90410a Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 9 Feb 2023 09:45:30 +0400 Subject: [PATCH 26/34] SubGhz: fix cc1101_read_fifo func (#2379) --- lib/drivers/cc1101.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/drivers/cc1101.c b/lib/drivers/cc1101.c index d563c30c3..d0feb0218 100644 --- a/lib/drivers/cc1101.c +++ b/lib/drivers/cc1101.c @@ -150,9 +150,8 @@ uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint } uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size) { - uint8_t buff_tx[64]; - buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; - uint8_t buff_rx[2]; + uint8_t buff_trx[2]; + buff_trx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; // Start transaction // Wait IC to become ready @@ -160,15 +159,15 @@ uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* si ; // First byte - packet length - furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT); + furi_hal_spi_bus_trx(handle, buff_trx, buff_trx, 2, CC1101_TIMEOUT); // Check that the packet is placed in the receive buffer - if(buff_rx[1] > 64) { + if(buff_trx[1] > 64) { *size = 64; } else { - *size = buff_rx[1]; + *size = buff_trx[1]; } - furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT); + furi_hal_spi_bus_trx(handle, NULL, data, *size, CC1101_TIMEOUT); return *size; -} +} \ No newline at end of file From 67c2d1cf6144da79e0077427b6ca09ee85f730ea Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Thu, 9 Feb 2023 13:42:41 +0300 Subject: [PATCH 27/34] Migrating CI/CD to Linode S3 (#2380) * Test PVS linode S3 * Migrating to Linode S3 * Disable PVS action debug * Fix pvs_studio.yml --- .github/workflows/build.yml | 11 +++++------ .github/workflows/pvs_studio.yml | 21 ++++++++++----------- scripts/merge_report_qa.py | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be9817684..689dd2037 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -96,14 +96,14 @@ jobs: - name: 'Upload map analyser files to storage' if: ${{ !github.event.pull_request.head.repo.fork }} - uses: keithweaver/aws-s3-github-action@v1.0.0 + uses: prewk/s3-cp-action@v2 with: - source: map_analyser_files/ - destination: "s3://${{ secrets.MAP_REPORT_AWS_BUCKET }}/${{steps.names.outputs.random_hash}}" + aws_s3_endpoint: "${{ secrets.MAP_REPORT_AWS_ENDPOINT }}" aws_access_key_id: "${{ secrets.MAP_REPORT_AWS_ACCESS_KEY }}" aws_secret_access_key: "${{ secrets.MAP_REPORT_AWS_SECRET_KEY }}" - aws_region: "${{ secrets.MAP_REPORT_AWS_REGION }}" - flags: --recursive + source: "./map_analyser_files/" + dest: "s3://${{ secrets.MAP_REPORT_AWS_BUCKET }}/${{steps.names.outputs.random_hash}}" + flags: "--recursive --acl public-read" - name: 'Trigger map file reporter' if: ${{ !github.event.pull_request.head.repo.fork }} @@ -114,7 +114,6 @@ jobs: event-type: map-file-analyse client-payload: '{"random_hash": "${{steps.names.outputs.random_hash}}", "event_type": "${{steps.names.outputs.event_type}}"}' - - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} run: | diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index a4ac6e301..65a8b6150 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -54,17 +54,16 @@ jobs: ./fbt COMPACT=1 PVSNOBROWSER=1 firmware_pvs || WARNINGS=1 echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT - - name: 'Upload artifacts to update server' + - name: 'Upload report' if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} - run: | - mkdir -p ~/.ssh - ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts - echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; - chmod 600 ./deploy_key; - rsync -avrzP --mkpath \ - -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ - build/f7-firmware-DC/pvsreport/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/"; - rm ./deploy_key; + uses: prewk/s3-cp-action@v2 + with: + aws_s3_endpoint: "${{ secrets.PVS_AWS_ENDPOINT }}" + aws_access_key_id: "${{ secrets.PVS_AWS_ACCESS_KEY }}" + aws_secret_access_key: "${{ secrets.PVS_AWS_SECRET_KEY }}" + source: "./build/f7-firmware-DC/pvsreport" + dest: "s3://${{ secrets.PVS_AWS_BUCKET }}/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/" + flags: "--recursive --acl public-read" - name: 'Find Previous Comment' if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} @@ -83,7 +82,7 @@ jobs: issue-number: ${{ github.event.pull_request.number }} body: | **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** - - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) + - [Report](https://pvs.flipp.dev/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) edit-mode: replace - name: 'Raise exception' diff --git a/scripts/merge_report_qa.py b/scripts/merge_report_qa.py index c0707848e..caa742408 100755 --- a/scripts/merge_report_qa.py +++ b/scripts/merge_report_qa.py @@ -17,7 +17,7 @@ def parse_args(): def checkCommitMessage(msg): - regex = re.compile(r"^'?\[FL-\d+\]") + regex = re.compile(r"^'?\[(FL-\d+,?\s?)+\]") if regex.match(msg): return True return False From af869ef8d2f62d878a8571f29e7bfb2230aa6db7 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Thu, 9 Feb 2023 18:34:56 +0100 Subject: [PATCH 28/34] Merging OFW | Suffering | Part 1 | Wont build as is I honestly dont even know anymore... --- .github/workflows/pvs_studio.yml | 93 ++ .../debug/example_custom_font/application.fam | 9 + .../example_custom_font/example_custom_font.c | 98 ++ .../examples/example_thermo/README.md | 44 + .../examples/example_thermo/application.fam | 10 + .../examples/example_thermo/example_thermo.c | 356 ++++++ .../example_thermo/example_thermo_10px.png | Bin 0 -> 7293 bytes .../resources/badusb/assets/layouts/ba-BA.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/cz_CS.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/da-DA.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/de-CH.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/de-DE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/dvorak.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/en-UK.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/en-US.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/es-ES.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-BE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-CH.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/fr-FR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/hr-HR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/hu-HU.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/it-IT.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/nb-NO.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/nl-NL.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/pt-BR.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/pt-PT.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/si-SI.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/sk-SK.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/sv-SE.kl | Bin 0 -> 256 bytes .../resources/badusb/assets/layouts/tr-TR.kl | Bin 0 -> 256 bytes assets/resources/infrared/assets/projector.ir | 829 ++++++++++++ assets/resources/subghz/assets/alutech_at_4n | 6 + .../unit_tests/subghz/alutech_at_4n_raw.sub | 10 + assets/unit_tests/subghz/dooya.sub | 7 + assets/unit_tests/subghz/dooya_raw.sub | 8 + .../subghz/kinggates_stylo4k_raw.sub | 11 + assets/unit_tests/subghz/linear_delta3.sub | 7 + .../unit_tests/subghz/linear_delta3_raw.sub | 8 + assets/unit_tests/subghz/nice_one_raw.sub | 12 + documentation/UniversalRemotes.md | 76 ++ firmware/targets/f7/api_symbols.csv | 75 +- firmware/targets/f7/fatfs/sd_spi_io.c | 877 +++++++++++++ firmware/targets/f7/fatfs/sd_spi_io.h | 157 +++ firmware/targets/f7/furi_hal/furi_hal_spi.c | 235 +++- .../targets/furi_hal_include/furi_hal_spi.h | 25 +- lib/subghz/blocks/encoder.c | 25 +- lib/subghz/blocks/encoder.h | 11 +- lib/subghz/environment.c | 16 + lib/subghz/environment.h | 17 + lib/subghz/protocols/alutech_at_4n.c | 455 +++++++ lib/subghz/protocols/alutech_at_4n.h | 74 ++ lib/subghz/protocols/bin_raw.c | 1120 +++++++++++++++++ lib/subghz/protocols/bin_raw.h | 111 ++ lib/subghz/protocols/chamberlain_code.c | 5 +- lib/subghz/protocols/dooya.c | 447 +++++++ lib/subghz/protocols/dooya.h | 107 ++ lib/subghz/protocols/keeloq.c | 13 +- lib/subghz/protocols/kinggates_stylo_4k.c | 336 +++++ lib/subghz/protocols/kinggates_stylo_4k.h | 74 ++ lib/subghz/protocols/linear_delta3.c | 359 ++++++ lib/subghz/protocols/linear_delta3.h | 111 ++ lib/subghz/protocols/nice_flor_s.c | 167 ++- lib/subghz/protocols/protocol_items.c | 57 +- lib/subghz/protocols/protocol_items.h | 4 + lib/subghz/protocols/secplus_v1.c | 4 +- lib/subghz/protocols/somfy_keytis.c | 366 +++++- lib/subghz/protocols/somfy_keytis.h | 52 + lib/subghz/protocols/somfy_telis.c | 298 ++++- lib/subghz/protocols/somfy_telis.h | 52 + lib/subghz/subghz_setting.c | 5 +- lib/subghz/subghz_tx_rx_worker.c | 10 +- lib/subghz/types.h | 1 + 72 files changed, 7144 insertions(+), 106 deletions(-) create mode 100644 .github/workflows/pvs_studio.yml create mode 100644 applications/debug/example_custom_font/application.fam create mode 100644 applications/debug/example_custom_font/example_custom_font.c create mode 100644 applications/examples/example_thermo/README.md create mode 100644 applications/examples/example_thermo/application.fam create mode 100644 applications/examples/example_thermo/example_thermo.c create mode 100644 applications/examples/example_thermo/example_thermo_10px.png create mode 100644 assets/resources/badusb/assets/layouts/ba-BA.kl create mode 100644 assets/resources/badusb/assets/layouts/cz_CS.kl create mode 100644 assets/resources/badusb/assets/layouts/da-DA.kl create mode 100644 assets/resources/badusb/assets/layouts/de-CH.kl create mode 100644 assets/resources/badusb/assets/layouts/de-DE.kl create mode 100644 assets/resources/badusb/assets/layouts/dvorak.kl create mode 100644 assets/resources/badusb/assets/layouts/en-UK.kl create mode 100644 assets/resources/badusb/assets/layouts/en-US.kl create mode 100644 assets/resources/badusb/assets/layouts/es-ES.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-BE.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-CH.kl create mode 100644 assets/resources/badusb/assets/layouts/fr-FR.kl create mode 100644 assets/resources/badusb/assets/layouts/hr-HR.kl create mode 100644 assets/resources/badusb/assets/layouts/hu-HU.kl create mode 100644 assets/resources/badusb/assets/layouts/it-IT.kl create mode 100644 assets/resources/badusb/assets/layouts/nb-NO.kl create mode 100644 assets/resources/badusb/assets/layouts/nl-NL.kl create mode 100644 assets/resources/badusb/assets/layouts/pt-BR.kl create mode 100644 assets/resources/badusb/assets/layouts/pt-PT.kl create mode 100644 assets/resources/badusb/assets/layouts/si-SI.kl create mode 100644 assets/resources/badusb/assets/layouts/sk-SK.kl create mode 100644 assets/resources/badusb/assets/layouts/sv-SE.kl create mode 100644 assets/resources/badusb/assets/layouts/tr-TR.kl create mode 100644 assets/resources/infrared/assets/projector.ir create mode 100644 assets/resources/subghz/assets/alutech_at_4n create mode 100644 assets/unit_tests/subghz/alutech_at_4n_raw.sub create mode 100644 assets/unit_tests/subghz/dooya.sub create mode 100644 assets/unit_tests/subghz/dooya_raw.sub create mode 100644 assets/unit_tests/subghz/kinggates_stylo4k_raw.sub create mode 100644 assets/unit_tests/subghz/linear_delta3.sub create mode 100644 assets/unit_tests/subghz/linear_delta3_raw.sub create mode 100644 assets/unit_tests/subghz/nice_one_raw.sub create mode 100644 documentation/UniversalRemotes.md create mode 100644 firmware/targets/f7/fatfs/sd_spi_io.c create mode 100644 firmware/targets/f7/fatfs/sd_spi_io.h create mode 100644 lib/subghz/protocols/alutech_at_4n.c create mode 100644 lib/subghz/protocols/alutech_at_4n.h create mode 100644 lib/subghz/protocols/bin_raw.c create mode 100644 lib/subghz/protocols/bin_raw.h create mode 100644 lib/subghz/protocols/dooya.c create mode 100644 lib/subghz/protocols/dooya.h create mode 100644 lib/subghz/protocols/kinggates_stylo_4k.c create mode 100644 lib/subghz/protocols/kinggates_stylo_4k.h create mode 100644 lib/subghz/protocols/linear_delta3.c create mode 100644 lib/subghz/protocols/linear_delta3.h diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml new file mode 100644 index 000000000..65a8b6150 --- /dev/null +++ b/.github/workflows/pvs_studio.yml @@ -0,0 +1,93 @@ +name: 'Static C/C++ analysis with PVS-Studio' + +on: + push: + branches: + - dev + - "release*" + tags: + - '*' + pull_request: + +env: + TARGETS: f7 + DEFAULT_TARGET: f7 + FBT_TOOLCHAIN_PATH: /runner/_work + +jobs: + analyse_c_cpp: + if: ${{ !github.event.pull_request.head.repo.fork }} + runs-on: [self-hosted, FlipperZeroShell] + steps: + - name: 'Decontaminate previous build leftovers' + run: | + if [ -d .git ]; then + git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" + fi + + - name: 'Checkout code' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: 'Get commit details' + id: names + run: | + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + TYPE="pull" + elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + TYPE="tag" + else + TYPE="other" + fi + python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" + + - name: 'Supply PVS credentials' + run: | + pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} + + - name: 'Convert PVS-Studio output to html and detect warnings' + id: pvs-warn + run: | + WARNINGS=0 + ./fbt COMPACT=1 PVSNOBROWSER=1 firmware_pvs || WARNINGS=1 + echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT + + - name: 'Upload report' + if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} + uses: prewk/s3-cp-action@v2 + with: + aws_s3_endpoint: "${{ secrets.PVS_AWS_ENDPOINT }}" + aws_access_key_id: "${{ secrets.PVS_AWS_ACCESS_KEY }}" + aws_secret_access_key: "${{ secrets.PVS_AWS_SECRET_KEY }}" + source: "./build/f7-firmware-DC/pvsreport" + dest: "s3://${{ secrets.PVS_AWS_BUCKET }}/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/" + flags: "--recursive --acl public-read" + + - name: 'Find Previous Comment' + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} + uses: peter-evans/find-comment@v2 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'PVS-Studio report for commit' + + - name: 'Create or update comment' + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** + - [Report](https://pvs.flipp.dev/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) + edit-mode: replace + + - name: 'Raise exception' + if: ${{ steps.pvs-warn.outputs.warnings != 0 }} + run: | + echo "Please fix all PVS warnings before merge" + exit 1 + diff --git a/applications/debug/example_custom_font/application.fam b/applications/debug/example_custom_font/application.fam new file mode 100644 index 000000000..02285b8a0 --- /dev/null +++ b/applications/debug/example_custom_font/application.fam @@ -0,0 +1,9 @@ +App( + appid="example_custom_font", + name="Example: custom font", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_custom_font_main", + requires=["gui"], + stack_size=1 * 1024, + fap_category="Debug", +) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c new file mode 100644 index 000000000..15eeb5f02 --- /dev/null +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -0,0 +1,98 @@ +#include +#include + +#include +#include + +//This arrays contains the font itself. You can use any u8g2 font you want + +/* +Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1 +Copyright: +Glyphs: 95/203 +BBX Build Mode: 0 +*/ +const uint8_t u8g2_font_tom_thumb_4x6_tr[725] = + "_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310" + "\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1" + "&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244" + "\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60" + "\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227" + "\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227" + "\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32" + "d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3" + "\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0" + "E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12" + "I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227" + "\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310" + "Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$" + "W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U" + "V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^" + "\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7" + "\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35" + "\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T" + "\1l\7\227\310\310\326\0m\7\223\310 +#include + +#include +#include + +#include + +#include +#include + +#define UPDATE_PERIOD_MS 1000UL +#define TEXT_STORE_SIZE 64U + +#define DS18B20_CMD_CONVERT 0x44U +#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU + +#define DS18B20_CFG_RESOLUTION_POS 5U +#define DS18B20_CFG_RESOLUTION_MASK 0x03U +#define DS18B20_DECIMAL_PART_MASK 0x0fU + +#define DS18B20_SIGN_MASK 0xf0U + +/* Possible GPIO pin choices: + - gpio_ext_pc0 + - gpio_ext_pc1 + - gpio_ext_pc3 + - gpio_ext_pb2 + - gpio_ext_pb3 + - gpio_ext_pa4 + - gpio_ext_pa6 + - gpio_ext_pa7 + - ibutton_gpio +*/ + +#define THERMO_GPIO_PIN (ibutton_gpio) + +/* Flags which the reader thread responds to */ +typedef enum { + ReaderThreadFlagExit = 1, +} ReaderThreadFlag; + +typedef union { + struct { + uint8_t temp_lsb; /* Least significant byte of the temperature */ + uint8_t temp_msb; /* Most significant byte of the temperature */ + uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */ + uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */ + uint8_t config; /* Configuration register */ + uint8_t reserved[3]; /* Not used */ + uint8_t crc; /* CRC checksum for error detection */ + } fields; + uint8_t bytes[9]; +} DS18B20Scratchpad; + +/* Application context structure */ +typedef struct { + Gui* gui; + ViewPort* view_port; + FuriThread* reader_thread; + FuriMessageQueue* event_queue; + OneWireHost* onewire; + float temp_celsius; + bool has_device; +} ExampleThermoContext; + +/*************** 1-Wire Communication and Processing *****************/ + +/* Commands the thermometer to begin measuring the temperature. */ +static void example_thermo_request_temperature(ExampleThermoContext* context) { + OneWireHost* onewire = context->onewire; + + /* All 1-wire transactions must happen in a critical section, i.e + not interrupted by other threads. */ + FURI_CRITICAL_ENTER(); + + bool success = false; + do { + /* Each communication with a 1-wire device starts by a reset. + The functon will return true if a device responded with a presence pulse. */ + if(!onewire_host_reset(onewire)) break; + /* After the reset, a ROM operation must follow. + If there is only one device connected, the "Skip ROM" command is most appropriate + (it can also be used to address all of the connected devices in some cases).*/ + onewire_host_skip(onewire); + /* After the ROM operation, a device-specific command is issued. + In this case, it's a request to start measuring the temperature. */ + onewire_host_write(onewire, DS18B20_CMD_CONVERT); + + success = true; + } while(false); + + context->has_device = success; + + FURI_CRITICAL_EXIT(); +} + +/* Reads the measured temperature from the thermometer. */ +static void example_thermo_read_temperature(ExampleThermoContext* context) { + /* If there was no device detected, don't try to read the temperature */ + if(!context->has_device) { + return; + } + + OneWireHost* onewire = context->onewire; + + /* All 1-wire transactions must happen in a critical section, i.e + not interrupted by other threads. */ + FURI_CRITICAL_ENTER(); + + bool success = false; + + do { + DS18B20Scratchpad buf; + + /* Attempt reading the temperature 10 times before giving up */ + size_t attempts_left = 10; + do { + /* Each communication with a 1-wire device starts by a reset. + The functon will return true if a device responded with a presence pulse. */ + if(!onewire_host_reset(onewire)) continue; + + /* After the reset, a ROM operation must follow. + If there is only one device connected, the "Skip ROM" command is most appropriate + (it can also be used to address all of the connected devices in some cases).*/ + onewire_host_skip(onewire); + + /* After the ROM operation, a device-specific command is issued. + This time, it will be the "Read Scratchpad" command which will + prepare the device's internal buffer memory for reading. */ + onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD); + + /* The actual reading happens here. A total of 9 bytes is read. */ + onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes)); + + /* Calculate the checksum and compare it with one provided by the device. */ + const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT); + + /* Checksums match, exit the loop */ + if(crc == buf.fields.crc) break; + + } while(--attempts_left); + + if(attempts_left == 0) break; + + /* Get the measurement resolution from the configuration register. (See [1] page 9) */ + const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) & + DS18B20_CFG_RESOLUTION_MASK; + + /* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */ + const uint8_t decimal_mask = + (DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) & + DS18B20_DECIMAL_PART_MASK; + + /* Get the integer and decimal part of the temperature (See [1] page 6) */ + const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U); + const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask; + + /* Calculate the sign of the temperature (See [1] page 6) */ + const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0; + + /* Combine the integer and decimal part together */ + const float temp_celsius_abs = integer_part + decimal_part / 16.f; + + /* Set the appropriate sign */ + context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs; + + success = true; + } while(false); + + context->has_device = success; + + FURI_CRITICAL_EXIT(); +} + +/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */ +static int32_t example_thermo_reader_thread_callback(void* ctx) { + ExampleThermoContext* context = ctx; + + for(;;) { + /* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */ + example_thermo_request_temperature(context); + + /* Wait for the measurement to finish. At the same time wait for an exit signal. */ + const uint32_t flags = + furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS); + + /* If an exit signal was received, return from this thread. */ + if(flags != (unsigned)FuriFlagErrorTimeout) break; + + /* The measurement is now ready, read it from the termometer. */ + example_thermo_read_temperature(context); + } + + return 0; +} + +/*************** GUI, Input and Main Loop *****************/ + +/* Draw the GUI of the application. The screen is completely redrawn during each call. */ +static void example_thermo_draw_callback(Canvas* canvas, void* ctx) { + ExampleThermoContext* context = ctx; + char text_store[TEXT_STORE_SIZE]; + const size_t middle_x = canvas_width(canvas) / 2U; + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo"); + canvas_draw_line(canvas, 0, 16, 128, 16); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer"); + + snprintf( + text_store, + TEXT_STORE_SIZE, + "to GPIO pin %ld", + furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN)); + canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store); + + canvas_set_font(canvas, FontKeyboard); + + if(context->has_device) { + float temp; + char temp_units; + + /* The applicaton is locale-aware. + Change Settings->System->Units to check it out. */ + switch(locale_get_measurement_unit()) { + case LocaleMeasurementUnitsMetric: + temp = context->temp_celsius; + temp_units = 'C'; + break; + case LocaleMeasurementUnitsImperial: + temp = locale_celsius_to_fahrenheit(context->temp_celsius); + temp_units = 'F'; + break; + default: + furi_crash("Illegal measurement units"); + } + /* If a reading is available, display it */ + snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units); + } else { + /* Or show a message that no data is available */ + strncpy(text_store, "-- No data --", TEXT_STORE_SIZE); + } + + canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store); +} + +/* This function is called from the GUI thread. All it does is put the event + into the application's queue so it can be processed later. */ +static void example_thermo_input_callback(InputEvent* event, void* ctx) { + ExampleThermoContext* context = ctx; + furi_message_queue_put(context->event_queue, event, FuriWaitForever); +} + +/* Starts the reader thread and handles the input */ +static void example_thermo_run(ExampleThermoContext* context) { + /* Configure the hardware in host mode */ + onewire_host_start(context->onewire); + + /* Start the reader thread. It will talk to the thermometer in the background. */ + furi_thread_start(context->reader_thread); + + /* An endless loop which handles the input*/ + for(bool is_running = true; is_running;) { + InputEvent event; + /* Wait for an input event. Input events come from the GUI thread via a callback. */ + const FuriStatus status = + furi_message_queue_get(context->event_queue, &event, FuriWaitForever); + + /* This application is only interested in short button presses. */ + if((status != FuriStatusOk) || (event.type != InputTypeShort)) { + continue; + } + + /* When the user presses the "Back" button, break the loop and exit the application. */ + if(event.key == InputKeyBack) { + is_running = false; + } + } + + /* Signal the reader thread to cease operation and exit */ + furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit); + + /* Wait for the reader thread to finish */ + furi_thread_join(context->reader_thread); + + /* Reset the hardware */ + onewire_host_stop(context->onewire); +} + +/******************** Initialisation & startup *****************************/ + +/* Allocate the memory and initialise the variables */ +static ExampleThermoContext* example_thermo_context_alloc() { + ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext)); + + context->view_port = view_port_alloc(); + view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context); + view_port_input_callback_set(context->view_port, example_thermo_input_callback, context); + + context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); + + context->reader_thread = furi_thread_alloc(); + furi_thread_set_stack_size(context->reader_thread, 1024U); + furi_thread_set_context(context->reader_thread, context); + furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback); + + context->gui = furi_record_open(RECORD_GUI); + gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen); + + context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN); + + return context; +} + +/* Release the unused resources and deallocate memory */ +static void example_thermo_context_free(ExampleThermoContext* context) { + view_port_enabled_set(context->view_port, false); + gui_remove_view_port(context->gui, context->view_port); + + onewire_host_free(context->onewire); + furi_thread_free(context->reader_thread); + furi_message_queue_free(context->event_queue); + view_port_free(context->view_port); + + furi_record_close(RECORD_GUI); +} + +/* The application's entry point. Execution starts from here. */ +int32_t example_thermo_main(void* p) { + UNUSED(p); + + /* Allocate all of the necessary structures */ + ExampleThermoContext* context = example_thermo_context_alloc(); + + /* Start the applicaton's main loop. It won't return until the application was requested to exit. */ + example_thermo_run(context); + + /* Release all unneeded resources */ + example_thermo_context_free(context); + + return 0; +} diff --git a/applications/examples/example_thermo/example_thermo_10px.png b/applications/examples/example_thermo/example_thermo_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..3d527f306c2d325fc72380856f14860f51b3742c GIT binary patch literal 7293 zcmeHMcTkhr*A7x6NLK_ALQoVWh4chN3sne3kSb^z5F`mCp^7v?QHrvl6hTCBL5hNu zr78#tyMiuNk+Rqj6ahuC!}o%&>(2L^`DSOn-+!B#G&lf!DOee-p$;^GBJ^qYwG zu0k1IO#B$Gb(B+3AoDV=`A*lv!-15DO|QA$l_Ms@Xll-MW5R=b!OPJNaUtyR1q|np zl$|khVskbfHgkL54QYnI8?OL|f0;``)KARM?tEzZLbc#alyTGpbR5O!!}Ma7!G%KS zbqHQ$%Fu^juNm>qURXbR?WQr2IF^REyJ^!tD^}wYia+t?SMu57Kz!QS<}1sc@*093 zcMCB1vi(7)XS*l2jk*~m$o5D$+e$u+NdV_wNl_6kS?82-Ve|SczSSX8_bS_t!$R*H zo#?^Y8Ps#t=}+?x+_{^Pa-Vgt`4(d8wyc%WK~wd79(ty&X=Lw=I!?2vyLY2@^394n zH?nU$e3A8GQIg@W=YDX$$1OWc@I26tqFp>!zfPfwVTiStEV%N_IJL}5>_Vi6^Op9i zkerg<@toGXCI?412JfAw+ti8FOHr)sZbh1doT`l;Fy;7Z<%!y=B6``43vGMMTjT4* zGK6iP67E;_7rs)uy5Op^*?v==WR8|%?>2`d>Y{ktTCFw4${RQ8^;(_WZ-~d{L2mmorjXS3$w~=No55t?cc(^BS00WNY+frmo;lgK~<;{)UNr;`q$n-fyu3 z{sE;f4U?W~6a8k%Fl@jmf5)Q^>GzbMPF6B?$3jgm9o0Dae4yc(kHk4#vns74U1FU^ zM5fn3sC!KFwWQoJCjokQr1sePBh}``;4+~i)>mp{X_7^U4FzOkm^$2s6Dv;d&)z(& zwc~vImJ7G+$}MFSWX2i^GpdGnb&&lB zmU7H8L<;4bOzuqR7pezkl4c4gNyQD_r@gl-D;42>(vhtSu0Jf1eQdnPl@u{9f zLQCWGSgGlB^mETpTD_R{e0@CS^?KD!D)YY`lgZqbbgQ@R_f}K1BgWAf+%Rst84S+w zc6oK7(Clo3?2?I@lpShl_ISBeL9a&@+c#07DpE5~Rc*AeO|}2biK?7*1BSR|XLeki z_CtHZ`r?3#vpUKUk;xm#ksA7Gl5y;?*0Q-Rto3{>m+QoLXDJedTbD})Kk(}RlFgfOL}r|8GL)3T^cq^bl8wwcwp}nx0CxLJG+u7rjg)I<;k(_ zpCpodaa77hDN{rA{R8$*?wQp(JK1rVJ4}+=+9xQVv^>4-R{0$4b)EJEj)U{-nqryg z>XOB}T8^zq6Q^w$>E}k6TjX2#Ug+HMo45SJnCWS-={-4uZj;Z%tMQ3|C!DJJ47SYl z30FqKlZ$S_G3A`e_$n_QPD*~x8&Fjkm}9hmMuh(Us%hxqXQEx*pQ3#7Uh8idXNyT>!wdzf!94d2>*le-8)<2dA-KX~{cdO9a2vx7ahP#xHn&n33 zqY1<&ZU3YB1}$1}lc&^5SLa+AQ@?uz6meUe4gg zqtq=$R9GUju}J|~%h?uTCY0*kIfcC#ba>mEEpYW07wwu4A-)(XJh0g|`G?{IFm8bd zekqn4(IoT1?t}CK{A@PflOP1|G`%j}IVU~y(jP9qSg^B5e33&xlO?|B7jbC%!T}C; z?)AsQW-}Dt;qg@KUULNWWV~a%=S_)d4~QDoawH+Rd@ZrBg(&B)*E5_hUeV)v#X0Cw zv=_!_=Ji^eJ+SH;;KWdi6E(v)bCuTr6cbJ%CGELgEw*m zOB0=bilQcqw`!r;ruxCjzuh0a#1HsQy*Q}N4grC^Z{4-1bK);N8;|Fwhck!lcPQ1xII?EOIU2PA;+dFNpzugYovG_`D`i}mj+=maZ{g>cLn&g1AnBHz5;_c5zYNFdcCZ+wN zp6D-Z>iZ~CreY!Wxpm{lQz3h`WrymNWv43J zj~`31)D2x4o;3<>IzD?&bn&JodN`!kaCqI-{IEL7#y1lxi@iGPqle>!hc>Of`=vg@ zziX~rP%w0MfUdEn>$YB^azkfcy5{dQ@-`=58f9&mc|P!Eyib0*sxS^tJTY)ksJExk zq*I~(MMiFs!zO6QP0cjY!Z7^Ir6*~Ze=~l&m3iLceOu+hh4Z@0zA91Ejj80|0fAJ} zSopwEjevnX&1emq%J&T+MfW3HB3wpnwpe=2-!p$5o#bY<@Y*cUzsG4Va9X~ovE5Zn zQ_v<}Z!EK|-my$6I9k_v3#V@C%+DC{l3Hw+z^dF#!g+aYD`-l!ex~GkZOR_VUGCh>Ti@`k^A=Z*N-f9d z9NApWTs~~z4a+pEPWG%&x}m#8ueq=90VOZ5hj&S4N1m5G_%kw=zM%l+DXy#Qc17pR zi7CYkVi}b|w=ZT!Z!xWM^++{0Hx->feU%se7JNX|Kj^aaeI*3z_h&At0iSDoi_~I% zRq_8^gN+uWo*lc>>OjsMY8kQVp-76{O1R}PlJ8kc_21{#)DEU6`~K3O2}3>_XReEW zdMp*~AeMvLRC%4tR{z*)k_B$9n1x*_F}(~cP25{{uV;KmJ-()P&SzqF+VhWYKPOr2 zE&pQgk}iDIthQ7xM_GN;nPJgs?NZZ#oClxuNju^x{`NQ&T0?l&P>K>WqM=Jv+jKMo)yj(+Hab6*|#!2eGpLjhvq|zy@c$)*tjy zxPiQpq@{-fm6T3rBA8@XA}@GI4?EPj zErz!J$`yS<{-o4T?j4F-k{lf=s_XA3^_OPQwWy!Kn#(6&WOZFUStetdChk&b8v11- zX1>X*3`u;rHBr&zUGn3oj@Yx_=RCsl<`|vqv!FJ=iCw%;W$X4&X1s~?O4bm0$eDQ5 zSfP8c^{FiKJ+tfQnO&y2W`&^Uf?oX7*f_6qyq*^owI})|Ar$Y6+}OjE{WaFZFO249 zU(USz16{Ec4JxnaUmMB7Z3cm4z1YCD%bjXRV(>U{8k0w7!NWO0z_knn+G!jfL}MIa z2_bZrADc^t&NW?!LfA|))D25TQiCWgf3|fbpXD5B@4|>Yz#uZA#zt#*hLZpS4ogUb zgmVJ90#Y~`y2?ue+AC%R6tW5t9w0;Asg4i|kI#Z&;21a(W)aQ~ML~_$LU!_*zNFpe zmft9V9vSK{6b6wHh_J9Qco-Va|Ed z`R34nd_&*@++Gp8Spr@NpTV*SWpRbtKT=rPP#wQBtc2vp<^-(<1&H^z$(W4qxS$Yz z;3|g6K(GQ?9Dq~+_-F7pypZktmso%EZDnLNoF5$lru)wSH}s#euYv&-l}a+_F+x@* zwJ|3{SNtV0c?>p_wAw^6XapjjhJoRIfmC4VEHsRO!eU`49F2fOV(Azbo%REj4Obwf zaT%-?Du5i$26$LZ100cwVZazTA|8feFz_%M4TXj=eDOFI3x&ZTnZ7?zIPlp(Rnh`~ z^lF8Q2~Zgja5N$Yg@Iu)3?vLg#Q4I97z_%ACE(~N7K@1?5Ll~JD|sN9I@*w-C^+&j zi(?>7=*#1C$WS{rHzfS80T(uhU%P?q)ujZ1tS$-?jqx=E0WFlpT=f&+`Z~n$r*ZvQ z!0z#_T>rGQ|3fLD(ReH#V}OS-Ff=R-gJYs$GymMobkHG&{*S~W8BL)5u z_}}XKf0JwNUpGb;7dYsJ0rx?cL&P=UE-B$?=VAdomzS3>4i}68EfKn{l{qL$e6uys z0S8%o2!KBUl~%qYpxnHTfKgItL$#2cl-VSwBf)ExO#w`rHs+=-Qui3|BVr#Wi?+LM n{LmKn@Uh4d70Hbn>L3*8aiyH^d~eG#00r4t*qdKA+aLcw^(CDL literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/ba-BA.kl b/assets/resources/badusb/assets/layouts/ba-BA.kl new file mode 100644 index 0000000000000000000000000000000000000000..379f6c649c98ef7f38df9c6d1c2b1588167ee46a GIT binary patch literal 256 zcmaLL%XYy47y#ipa|DTNh+7ar(9@P>V)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHkcVK4j(2-*&PMujecVX$$ zm1{Rv)^6RqGmA3vIK<6U^hikQGaw^p$cQl$rpzdqv!GYm`cD?ePm*T4GZVB*m| zTln^pGi$gvZr&YZh&>B_Ym yx9;4VM-@dp{CKxUod!)>wCT{LN1p*hMvR#-WyYKZOIEDeuw}=dEbdXpBj69fFAeVi literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/de-CH.kl b/assets/resources/badusb/assets/layouts/de-CH.kl new file mode 100644 index 0000000000000000000000000000000000000000..1704bc9dbaae9fcc90213cb33b0132bca1b71866 GIT binary patch literal 256 zcmaLLH;%#p6adlDh@5i<8!$oa;st31l>ack{~4%hnC=aHcHxKf=lZH&ZYHL2XXoB4 z2al$1eDLB)=7|jnDO+~z$vAN2>BEAPg;$d(S+-);nspmCZP~VC*PeX`4jnmm;?$XQ z7cO19@-K?GMb69I5@jk>sZpmvlNN0{bm`G&z>pDRCQO+zXTg#+EB+&kd*lIc##;^x literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/de-DE.kl b/assets/resources/badusb/assets/layouts/de-DE.kl new file mode 100644 index 0000000000000000000000000000000000000000..67b05c042f1649ab6aa17c4d369b096c88ec2785 GIT binary patch literal 256 zcmaLLHx9y30KiboqW2Pd4WuBN!ay1SVRHX7Ftgz88Gbu+;q<%y>dMxg4`L4uK0?Afwu&6#5(8&;hd+qL7+fvJ5TwhjIGHgM$E s3wH`~pT4NjqeYV%GsZ+Ts4^j@ONSu?Qu;h-6Y}9rz=$sw?-ss^@Y|jPyWjO!M`q5wk-2p3gN<8r z&%QYE=EIg5a~5PQS+OQ(!`(YC&%FKkuw>baRci*;Z5Z0LW!sLCv58$%d-feTbmZ8H tQ!f-;S$XnFi82+c)Cj24Af!o)HXR~j61t@H=rdr*h%pnUTr9kL6TT^X3*7(! literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/en-US.kl b/assets/resources/badusb/assets/layouts/en-US.kl new file mode 100644 index 0000000000000000000000000000000000000000..8089d8257881765fe67691a206b6bf6e9cb2c97d GIT binary patch literal 256 zcmaLL#}dH+007aQ9YGK+QKLn)QG!wb|I3_nvA4HS?#PKldHvOyg-=&zuHE=#=iaS_ zZ!UcJvS-1P6&Y)CHf-7P@WI=Hk6)Ko46ItSZfL`%EhF1@?Ao($Y~sM7BgamhnmTjt sl{+_bFTSV{P^CtlkOoa!M6~J9rAMEbgaJcFjF~VcWyYMVcW=Ig9}}MoYybcN literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/es-ES.kl b/assets/resources/badusb/assets/layouts/es-ES.kl new file mode 100644 index 0000000000000000000000000000000000000000..15e9d7997c3f5178982fe212b5341f09469486bc GIT binary patch literal 256 zcmaLLH;%#p6adlDh@5lA#$@e+Y@}VF{DLgOx;B0)}2=l z9xW`m^W?$a6A39BGPdm4bKuCsyDv_@yqZSIvK6b=tlO|@%eEc6_Ut=w=*Y1Xr_P+a zaOujmdHhEaxleOSl&MgqMx6#tTD0lVrAMCuLq?35FlEM^1xr?}`HLiOkp;W~w>u5X literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/fr-BE.kl b/assets/resources/badusb/assets/layouts/fr-BE.kl new file mode 100644 index 0000000000000000000000000000000000000000..ea9e553e894a470639ee48648a386898ed5cfa67 GIT binary patch literal 256 zcmaLLNm9Z96adk#F6Mcj2}uy4P%#!3Wcd%1`=7xz8+-Q}Uc2(a<#qk5PfnzyQSfU* zM$Q+7r6X=Ue0nzVU}|RW(Kk=N`{Y4IN#)2x%&gn6Y0I`9yY}omaOmB!6Q|akyKw2s zwR^Yj+?YodMSOGfCuY=X(4ack{~4%hnC=aHcHxKf=lZH&ZYHL2XXoB4 z2al$1eDLB)=7|jnDO+~z$vAN2>BEAPg;$d(S+-);nspmCZP~VC*PeX`4jnmm;?$XQ z7cO19@-K?GMb69I5@jk>sZpmvlNN0{bm`G&z>pDRCQO+zXTg#+EB+&kd*lIc##;^x literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/fr-FR.kl b/assets/resources/badusb/assets/layouts/fr-FR.kl new file mode 100644 index 0000000000000000000000000000000000000000..f9193297e58722fd4f1547cb9ef62474beb2487b GIT binary patch literal 256 zcmaLLH*Nv}6adlDh@5i{8(2U#EVi(~}3$%7XqF9)7tV%3^;8#Zm(wqw_xeeVt(Ikw`|nR6E| z-MV(;$}Ebw#*KnQOsG<$PJ<>b+H~mBqtBfoBgRyiGGoqyC0o{PSdm5^W$Xj~0L-fm A_W%F@ literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/hr-HR.kl b/assets/resources/badusb/assets/layouts/hr-HR.kl new file mode 100644 index 0000000000000000000000000000000000000000..379f6c649c98ef7f38df9c6d1c2b1588167ee46a GIT binary patch literal 256 zcmaLL%XYy47y#ipa|DTNh+7ar(9@P>V)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHk)x=fVv{{L5{w#jy9;k{43_;_Fc>YIyakMR>% z$I*KC;Silq2439!rR7Y=g)29D?mT$;j68aqcv{8C#IX~nre@BZyKw2s+`_dROSkUa zd$6+hXyeH=%E+RN!9GSLjF~VcC1b{%1xr@s6s*}$vSr7f0~Iw#8crlpM-gqnA2aL@ AGynhq literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/it-IT.kl b/assets/resources/badusb/assets/layouts/it-IT.kl new file mode 100644 index 0000000000000000000000000000000000000000..059e428808a07b26d0da37d7f37d5d8d4614365b GIT binary patch literal 256 zcmaKnw++Go0KhCO)P&wbCv;IGQOAf|`2PmP$bvU}GyJk+&-OR{wF48UUbDox3y-W^ zo0@Xx$%CaECQO-;FlWJ%6>A>eeY5fH(MuMXGjGA7CCi3JR;*gHZo{T6+ji{QGq&%* yp(Dqhvm0r4@+k!5$Wx$5i83J(6{^&z)1XO96ECB#K@^L=Pq0t xyK-$Ft`y%!)Nxcub+H~j=&?BVJfFUEsOqeobPMlv%@{{ldJ?{*0 literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/pt-BR.kl b/assets/resources/badusb/assets/layouts/pt-BR.kl new file mode 100644 index 0000000000000000000000000000000000000000..d36421cfc45747687dba3cabe05ff84a4550050a GIT binary patch literal 256 zcmaKnM-ssR004J(1W9z!q7!8hWkx%CjQ_uZtBbwu-WGn@v1j|6{@Q_wH)qaWn0aIE z#+66!wV)?)SQ*~|A*?j|_ee=WD=lWN_RGzFod-3X% zn|EKnXnE7o_@LrM&6x{V8gAU_Y;EIV7f*N5GqLZ$p{bc8$4;C&b8ha!rG+ckZrr-F ybnnrFX%vw~9dDcHk17S!45fq0~DYekR@*l?gpTRX7d-ob{d*zLn+x4&B`SxrR z=Qx?hB0l}{*Orbe7e0Kp_0GKq?|ty-qfcJ^p^Fo{=&Yh=Vrt)knYlwpj-5DlX5rk0 zrAt??-B?-MxN~b3W#qAstHmjD0& literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/sv-SE.kl b/assets/resources/badusb/assets/layouts/sv-SE.kl new file mode 100644 index 0000000000000000000000000000000000000000..5c55bb9ef1df3785fb143eb463a5375be10ce96f GIT binary patch literal 256 zcmaLLH*x|26u?l8hMaSTC2U}9uLl~S{D;~5pMjbNbx-iw55HVL*H`^JB+m2m(_8mBMwCT{LN1p*hMvR#-WyYKZOIEDeuw}=dG^!}#7VrkLXASNE literal 0 HcmV?d00001 diff --git a/assets/resources/badusb/assets/layouts/tr-TR.kl b/assets/resources/badusb/assets/layouts/tr-TR.kl new file mode 100644 index 0000000000000000000000000000000000000000..6377b770365ed544824108765ce2587f315bc1da GIT binary patch literal 256 zcmaLLM{dFZ6adlDh~A6oU~F)Sk{HDcB$od$x&IlmW|P^yf%iW7;^Te&t8Y@DWRb_s zyH`sq8**D7yeOY}m46&w(Q+&Ri(sH|qEa_ygc8 B4s!qi literal 0 HcmV?d00001 diff --git a/assets/resources/infrared/assets/projector.ir b/assets/resources/infrared/assets/projector.ir new file mode 100644 index 000000000..e9861de21 --- /dev/null +++ b/assets/resources/infrared/assets/projector.ir @@ -0,0 +1,829 @@ +Filetype: IR library file +Version: 1 +# +# Model: Smart +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 8A 00 00 00 +# +# Model: Epson +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +# Model: Epson +name: Power +type: parsed +protocol: NECext +address: 81 03 00 00 +command: F0 0F 00 00 +# +# Model: Hitatchi +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 +# +name: Vol_up +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 49 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 08 00 00 00 +command: 0B 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 40 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 48 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 44 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 83 7C 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 82 7D 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 13 00 00 +command: 87 78 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9055 4338 672 1551 669 1553 618 1603 619 481 617 482 616 481 617 507 591 1605 645 479 619 1577 645 1578 644 1578 644 479 619 480 618 1581 641 480 617 1605 617 1606 616 1606 615 483 615 1608 614 484 614 484 614 484 614 484 614 484 614 484 614 1609 614 484 614 1609 614 1609 613 1609 613 40058 9000 2068 614 95467 9022 2068 614 +# +name: Mute +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 29 D6 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 08 F7 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 04 FB 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 93 6C 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4462 598 501 627 1604 627 530 598 531 677 423 706 422 706 421 707 451 677 1554 677 451 598 1633 598 1634 597 1634 598 1634 598 1634 625 1606 681 1550 626 502 598 530 599 529 600 1632 600 528 600 528 601 528 601 528 601 1631 600 1631 625 1607 625 504 625 1607 624 1608 624 1608 623 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 1D 00 00 00 +# +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9096 4436 620 505 647 478 648 501 623 1599 647 1624 623 502 623 503 621 504 619 1628 618 507 617 507 617 1630 617 508 616 1630 617 1630 617 1631 616 508 616 508 617 508 616 1631 616 508 617 508 617 508 616 508 616 1630 616 1630 616 1631 616 508 616 1630 617 1630 617 1630 617 1631 617 509 616 508 616 509 616 509 616 509 616 509 615 509 616 508 617 1631 616 1631 615 1631 616 1631 616 1631 616 1631 616 1631 615 1631 616 14435 9093 2186 615 96359 9095 2184 617 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9091 4465 594 530 595 530 594 530 594 1651 595 1652 595 529 621 504 620 504 619 1628 618 507 617 508 616 1631 616 509 615 1631 616 1631 616 1632 615 509 616 509 616 509 615 1631 616 509 616 508 616 1631 616 509 616 1631 615 1631 616 1631 617 508 616 1631 616 1631 616 508 616 1631 617 508 617 509 616 509 616 509 616 509 616 509 616 509 616 509 616 1631 616 1631 616 1631 616 1631 616 1631 615 1631 615 1631 615 1631 616 14435 9090 2190 615 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 619 506 618 530 593 1627 620 1630 643 504 620 505 618 506 617 1630 617 508 616 508 616 1632 616 508 617 1631 616 1631 616 1631 616 1631 616 509 616 508 616 1631 616 509 616 509 615 1632 616 509 616 508 616 1631 616 1631 616 508 616 1631 615 1631 616 509 615 1632 615 509 616 509 616 509 616 509 616 509 616 510 615 509 616 509 616 1631 616 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 615 14434 9088 2191 615 96339 9115 2189 616 96343 9117 2189 616 96343 9114 2189 616 +# AV-Mute +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9092 4439 620 506 618 506 618 530 594 1627 619 1629 643 505 619 505 619 506 617 1629 617 508 616 508 616 1631 616 508 616 1630 616 1630 616 1630 617 1630 616 1630 616 1631 616 508 616 508 616 508 616 1631 616 508 617 508 616 508 616 508 616 1630 616 1631 615 1631 616 508 616 1631 616 508 617 508 616 509 615 509 616 508 616 509 615 509 616 508 616 1631 615 1631 615 1631 616 1631 615 1631 615 1631 615 1631 615 1631 616 14433 9088 2191 615 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9014 4332 661 1570 661 471 660 473 658 474 657 476 655 498 633 498 634 502 633 499 633 1599 632 1599 632 1599 632 1599 632 1599 632 1600 631 1603 632 500 632 501 631 501 631 501 631 501 631 501 631 1601 631 504 631 1601 631 1601 631 1601 631 1601 631 1601 630 1601 630 501 631 1601 631 38177 8983 2149 630 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 4C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9042 4306 690 1541 665 468 664 468 664 469 663 470 662 471 660 495 636 499 636 497 634 1597 634 1598 633 1598 633 1599 633 1599 632 1599 633 1603 632 1599 633 499 633 499 633 500 632 499 633 500 632 1600 632 503 633 500 632 1600 632 1600 632 1600 633 1600 632 1600 632 500 632 1600 632 37912 8986 2145 633 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3522 1701 472 426 444 1269 472 426 444 426 443 427 443 427 443 426 444 427 443 426 444 427 442 428 441 429 440 431 438 1304 437 433 437 433 438 433 437 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1305 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 459 411 459 411 459 411 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 459 411 459 411 1330 411 1330 411 460 410 1330 411 1330 411 1331 410 1330 411 74392 3516 1736 436 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 435 435 1305 436 435 435 435 435 1306 435 435 435 435 435 435 435 436 434 436 434 436 434 435 435 436 434 436 434 436 434 1330 411 1331 410 1330 411 1330 411 1330 411 459 411 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 435 436 434 436 1306 435 435 435 435 435 1306 435 435 435 435 435 435 435 435 435 435 435 436 434 436 434 435 435 436 434 435 435 1306 435 1330 411 1307 434 1331 410 1308 433 436 434 436 434 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 435 435 434 436 434 436 434 436 434 436 434 436 1306 435 435 435 435 435 435 435 1306 435 435 435 436 434 1306 435 435 435 436 434 436 434 435 435 436 434 436 434 460 410 460 410 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74392 3515 1736 437 433 437 1304 437 433 437 434 436 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 434 436 434 436 435 435 435 435 434 436 1306 435 434 436 435 435 435 435 1306 435 436 434 435 435 1306 435 435 435 436 434 436 434 436 434 436 434 460 410 437 433 459 411 460 410 460 410 1331 410 1331 410 1331 410 1331 410 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3514 1736 437 434 436 1304 437 433 437 434 436 433 437 434 436 433 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 434 436 435 435 434 436 434 436 435 435 434 436 1305 436 435 435 435 435 435 435 1306 435 435 435 435 435 1306 435 435 435 436 434 435 435 459 411 436 434 435 435 459 411 459 411 459 411 459 411 1330 411 1306 435 1330 411 1330 411 1331 410 460 410 460 410 460 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# ON +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 529 7218 126 6585 219 703 180 5362 427 18618 177 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9069 4362 622 486 621 487 621 491 622 1608 623 1603 622 487 621 487 621 491 622 1604 621 487 622 491 622 1604 621 491 622 1608 622 1609 621 1604 622 486 622 487 621 491 621 1605 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1604 622 491 621 1609 622 1604 621 491 621 1604 622 487 621 487 622 486 622 487 621 488 621 487 621 488 620 491 621 1609 622 1609 620 1609 621 1609 621 1609 621 1609 621 1609 621 1618 621 14330 9047 2137 620 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9047 4362 621 486 622 463 645 490 622 1609 622 1604 622 487 620 487 621 491 622 1604 622 484 625 490 621 1605 649 463 621 1609 620 1611 621 1608 622 1605 621 486 622 491 622 1604 621 487 621 492 620 1604 621 488 621 492 620 1609 622 1604 621 492 622 1609 620 1605 621 491 622 1603 622 488 621 488 620 488 620 488 621 488 620 487 622 485 621 492 596 1635 621 1609 622 1585 643 1611 620 1608 621 1610 619 1611 620 1619 619 14332 9074 2109 647 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9073 4336 648 461 647 484 624 489 623 1607 623 1603 622 486 622 486 622 491 622 1604 621 487 621 491 622 1604 622 491 621 1609 621 1609 621 1609 621 1608 622 1609 621 1604 621 486 622 486 622 491 622 1604 622 486 622 487 621 487 621 491 622 1608 622 1609 621 1604 622 491 621 1604 621 487 621 486 622 487 621 487 621 487 621 487 621 487 621 491 622 1608 622 1608 622 1609 621 1608 622 1608 622 1608 622 1609 621 1617 622 14330 9047 2137 620 +# ON +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4F B0 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 10 EF 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 80 19 00 00 +command: 46 B9 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 51 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 40 40 00 00 +command: 0A F5 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4E B1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0E F1 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 0D F2 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 4F B0 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 00 30 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 08 16 00 00 +command: 87 78 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 08 16 00 00 +command: C8 37 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 01 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 02 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 28 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 29 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 84 F4 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 00 FF 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 1D E2 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 33 00 00 00 +command: 0B F4 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 90 6F 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 99 66 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 55 00 00 +command: 98 67 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 1C E3 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4F B0 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 00 DF 00 00 +command: 4B B4 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 02 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 2E 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 52 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 41 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 51 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 56 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 5A 00 00 00 +# +name: Power +type: parsed +protocol: SIRC15 +address: 54 00 00 00 +command: 15 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 82 7D 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 83 7C 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 14 EB 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 91 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 90 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 31 00 00 00 +command: D0 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 89 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 00 00 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 30 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 31 00 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 86 00 00 00 +command: 32 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 30 00 00 00 +command: 00 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 4E 00 00 +command: 0D 00 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9032 4479 597 560 572 558 564 566 566 1666 589 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 1669 596 560 562 1671 594 1666 588 1671 594 562 570 560 562 568 564 1669 596 560 562 568 564 566 566 563 569 1664 591 1669 596 1664 590 565 567 1667 598 1661 593 1666 588 1671 594 562 570 560 562 568 564 565 567 563 569 560 562 568 564 565 567 1666 588 1671 594 1665 589 1670 595 1665 590 1669 596 1664 590 1668 597 13983 9029 2222 599 96237 9030 2221 589 96244 9034 2217 594 96244 9033 2218 592 96249 9038 2213 597 96239 9037 2214 596 96238 9028 2223 598 96221 9032 2215 595 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4482 593 563 569 561 571 559 563 1698 566 1694 570 559 563 568 564 566 566 1695 569 560 572 559 563 1671 593 563 569 1692 562 1671 593 1693 571 558 564 567 565 565 567 1693 571 532 590 567 565 1695 569 560 562 1698 566 1694 570 1663 591 539 593 1693 571 1688 566 564 568 1691 563 567 565 565 567 563 569 561 571 559 563 567 565 565 567 563 569 1690 564 1695 569 1691 563 1696 568 1691 563 1697 567 1692 562 1697 567 13988 9030 2223 597 96250 9035 2219 591 96245 9032 2221 589 96240 9038 2215 595 96235 9033 2220 590 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9028 4482 593 563 569 561 571 558 564 1696 568 1690 564 566 566 563 569 561 571 1688 566 563 569 561 571 1688 566 563 569 1690 564 1695 569 1689 565 1668 596 560 562 568 564 1695 569 560 562 568 564 1695 569 560 562 568 564 1695 569 1690 564 566 566 1692 572 1687 567 563 569 1690 564 566 566 564 568 562 570 559 563 567 565 565 567 562 570 560 562 1696 568 1665 589 1670 594 1665 589 1670 594 1664 590 1669 647 1612 590 13987 9031 2220 590 96223 9033 2217 593 96223 9034 2218 592 96225 9032 2219 591 96221 9087 2164 595 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9031 4479 596 560 572 558 564 566 566 1693 571 1688 566 563 569 561 571 559 563 1696 568 561 571 559 563 1697 567 562 570 1689 565 1694 570 1688 566 1693 571 1661 593 1693 571 558 564 566 566 564 568 1691 563 541 591 564 568 562 570 560 562 1697 567 1692 562 1696 568 562 570 1689 565 564 568 561 571 559 563 567 565 564 568 562 570 560 562 567 565 1694 570 1689 565 1694 570 1688 566 1693 571 1688 566 1693 571 1662 592 13987 9031 2220 590 96231 9034 2217 593 96234 9030 2222 588 96247 9037 2215 595 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 14 00 00 00 +# OFF +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 4E B1 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 1D 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 11 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 03 00 00 00 +command: 15 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9075 4307 677 433 675 456 651 461 651 1579 650 1576 649 459 649 460 648 465 648 1578 647 461 622 491 622 1604 647 465 647 1583 622 1608 647 1579 647 461 647 466 622 1604 647 465 647 1579 647 461 645 463 648 465 648 1583 646 1580 646 466 647 1579 622 491 647 1583 622 1608 647 1579 647 461 647 461 622 486 622 486 647 461 647 462 646 462 622 491 646 1584 622 1608 647 1584 621 1608 647 1583 646 1584 647 1584 646 1592 622 14330 9047 2137 621 +# +name: Power +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: E6 00 00 00 +# +name: Vol_up +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 07 00 00 00 +# +name: Vol_dn +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0B 00 00 00 +# +name: Mute +type: parsed +protocol: Samsung32 +address: 07 00 00 00 +command: 0F 00 00 00 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3523 1701 472 426 444 1269 472 426 444 426 442 429 443 427 443 426 444 426 444 426 443 427 442 429 440 430 439 432 438 1304 437 433 437 432 438 432 438 433 437 433 437 433 437 433 437 433 437 433 437 1304 437 433 437 433 437 433 437 1304 437 433 437 433 437 1304 437 433 437 434 436 433 437 434 436 434 436 434 436 433 437 433 437 434 436 1304 437 1305 436 1305 436 1305 436 1305 436 1305 436 434 436 434 436 1305 436 1305 436 1305 436 434 436 1305 436 1305 436 1306 435 1306 435 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 1304 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 436 434 435 435 1307 434 1331 410 1307 434 1307 434 1330 411 1307 434 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 434 436 433 437 433 437 1304 437 434 436 434 436 434 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 435 435 434 436 1305 436 434 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1306 435 1307 434 1307 434 1307 434 1331 410 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 1304 437 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 437 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9093 4441 620 507 618 530 594 531 593 1652 595 1653 620 505 620 505 619 506 617 1630 616 508 616 508 616 1632 615 509 615 1631 616 1632 615 1632 615 510 615 509 615 1632 615 509 615 1632 615 510 615 510 614 509 615 1632 614 1633 614 509 615 1633 614 509 615 1632 615 1632 614 1633 614 510 614 510 615 510 615 510 614 510 614 510 615 510 615 510 614 1632 615 1632 614 1632 615 1632 615 1632 615 1632 615 1632 615 1633 614 14439 9088 2192 614 96349 9112 2190 616 +# OFF +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 243 27700 170 27632 246 27694 282 27595 307 27497 241 27696 177 27710 164 27644 245 27629 246 27712 174 27638 211 27736 131 27741 306 27504 214 27727 135 27749 132 27761 126 27744 131 27753 127 27764 121 27767 132 27773 307 27577 131 27706 213 27761 129 27759 128 27770 125 27694 213 27751 307 27578 131 27737 131 27745 304 27575 335 27540 124 27752 132 27749 132 27747 134 27757 134 27758 127 27762 131 27748 131 27750 122 27749 130 27748 125 27772 131 27774 136 27762 135 27686 215 27742 131 27749 132 27756 133 27764 126 24073 9255 4460 672 488 618 541 619 541 619 1675 619 1676 618 542 618 542 618 542 618 1676 618 542 618 543 617 1678 616 568 592 1702 592 1702 592 1703 617 543 617 543 617 1677 617 543 617 1678 615 544 616 544 616 544 616 1678 616 1679 615 544 616 1679 615 545 615 1679 615 1679 615 1679 615 40240 9173 2273 591 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 219 27658 217 27663 216 27658 216 27634 216 27642 215 27646 217 27662 217 27637 216 27649 216 27649 218 27656 217 27658 215 27640 214 27636 217 27649 216 27644 218 27635 217 27630 215 27645 216 27631 215 27632 216 27650 216 27628 217 27630 214 27627 217 27623 215 27632 215 27641 216 27634 214 27633 215 27648 215 27648 217 27651 215 27635 216 27629 216 27630 216 2021 9254 4461 618 542 618 542 618 542 618 1675 619 1676 618 541 619 541 619 542 618 1677 617 543 617 543 617 1678 616 568 592 1702 592 1702 618 1676 618 542 618 542 618 543 617 1677 617 543 617 544 616 1678 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1678 616 544 616 1678 616 40239 9200 2247 617 99930 110 27739 119 27738 123 27750 126 27738 175 27617 214 27716 203 27604 213 27639 217 27631 214 27722 136 27753 119 27736 175 27618 246 27683 177 27619 245 27685 171 55486 244 27693 158 27635 241 27695 170 27693 129 27717 340 27530 113 27757 106 27751 124 27728 172 27707 126 27666 215 27708 123 27733 123 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 18 E9 00 00 +command: 49 B6 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 14 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 48 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 40 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 18 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0C F3 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0D F2 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1E E1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1F E0 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 81 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8F 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8C 00 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9066 4428 608 507 609 1622 609 507 609 507 609 1623 608 1623 609 507 609 506 610 1623 609 507 609 1622 610 1623 608 507 609 506 610 1622 609 1623 609 506 610 1622 610 506 610 1623 637 478 690 425 638 478 637 1594 637 1594 664 451 636 1594 610 506 610 1621 611 1621 610 1621 610 505 611 40183 9065 2156 637 95953 9037 2185 608 +# +name: Power +type: parsed +protocol: NEC +address: 00 00 00 00 +command: A8 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 88 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 9C 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 8C 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9064 4354 666 1559 666 1562 662 1586 638 475 636 477 635 477 635 478 635 1590 635 1591 634 478 635 1591 634 478 634 478 635 478 634 1591 635 478 634 1591 634 478 635 478 634 478 635 1591 634 478 634 1591 635 478 634 478 634 1591 634 1591 635 1591 634 478 635 1591 634 478 634 1591 635 40957 9035 2144 634 95483 9047 2155 632 95484 9048 2153 633 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 87 45 00 00 +command: 50 AF 00 00 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9034 4385 638 1587 664 1562 663 1587 637 476 635 478 634 478 635 478 635 1591 634 1591 634 478 635 1591 635 478 634 478 635 478 635 1591 635 478 634 478 634 1591 634 478 635 479 634 1591 635 478 634 1591 635 478 634 1592 634 478 634 1591 635 1591 635 478 634 1592 634 478 634 1591 634 40958 9033 2144 635 +# +name: Power +type: parsed +protocol: NECext +address: FF FF 00 00 +command: E8 17 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: FF FF 00 00 +command: BD 42 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: FF FF 00 00 +command: F2 0D 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 05 00 00 00 +# +name: Vol_up +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 70 01 00 00 +# +name: Vol_dn +type: parsed +protocol: Kaseikyo +address: 41 54 32 00 +command: 71 01 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 31 00 00 00 +command: 81 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 83 F4 00 00 +command: 17 E8 00 00 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9010 4413 532 1617 532 1617 533 489 533 489 533 489 558 464 558 465 557 1593 557 465 557 466 556 1594 555 467 555 1595 529 1621 554 1595 581 1569 581 441 581 1569 581 441 581 441 581 441 581 441 581 441 581 1569 581 1569 581 441 581 1569 580 1569 580 1570 580 1595 554 1595 555 468 554 42156 8983 2135 556 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9032 4390 556 1592 559 1591 559 463 559 463 558 464 557 465 556 465 557 1593 583 440 581 441 580 1569 581 441 581 1569 580 1569 581 1569 581 1570 580 1596 554 1596 554 468 554 468 554 468 554 442 580 442 580 1596 554 469 553 469 553 1596 554 1596 553 1597 550 1598 553 1598 552 469 551 42155 9008 2107 531 95218 9006 2108 582 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9011 4388 557 1617 532 1617 532 489 533 489 558 464 558 440 582 440 582 1593 556 466 556 466 556 1594 556 467 555 1595 555 1595 529 1620 554 1596 554 467 554 468 555 1595 579 443 581 1569 581 441 581 441 580 442 581 1569 581 1569 581 441 581 1569 580 441 581 1569 581 1569 581 1570 579 42152 8957 2159 556 \ No newline at end of file diff --git a/assets/resources/subghz/assets/alutech_at_4n b/assets/resources/subghz/assets/alutech_at_4n new file mode 100644 index 000000000..5d7beacec --- /dev/null +++ b/assets/resources/subghz/assets/alutech_at_4n @@ -0,0 +1,6 @@ +Filetype: Flipper SubGhz Keystore RAW File +Version: 0 +Encryption: 1 +IV: 88 64 A6 A6 44 47 67 8A D6 32 36 F6 B9 06 57 31 +Encrypt_data: RAW +E811BD4F0955D217AE6677906E799D45D8DAAFD1F7923E1660B5E24574631B60 \ No newline at end of file diff --git a/assets/unit_tests/subghz/alutech_at_4n_raw.sub b/assets/unit_tests/subghz/alutech_at_4n_raw.sub new file mode 100644 index 000000000..ae5db9715 --- /dev/null +++ b/assets/unit_tests/subghz/alutech_at_4n_raw.sub @@ -0,0 +1,10 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -854 811 -454 811 -444 409 -838 811 -454 823 -432 385 -842 811 -454 389 -854 821 -418 837 -444 401 -850 417 -854 395 -830 417 -846 819 -432 811 -448 789 -444 839 -454 401 -856 381 -850 825 -410 841 -418 417 -834 411 -840 827 -442 417 -844 799 -472 809 -420 411 -842 419 -848 397 -822 413 -850 799 -486 381 -848 415 -854 423 -16394 449 -358 437 -386 411 -384 449 -382 417 -384 419 -386 417 -386 419 -388 419 -388 419 -388 419 -390 437 -4036 421 -810 425 -820 393 -866 813 -422 415 -856 397 -858 811 -456 427 -820 815 -416 419 -850 401 -854 805 -420 835 -444 409 -842 809 -454 433 -820 421 -838 813 -420 417 -822 435 -820 419 -834 431 -852 411 -866 805 -420 815 -444 805 -454 403 -824 809 -448 819 -448 413 -844 811 -446 811 -456 409 -816 809 -456 389 -866 387 -842 809 -454 827 -432 413 -850 829 -428 809 -452 381 -852 799 -452 413 -852 807 -450 801 -444 409 -872 411 -840 413 -812 413 -832 807 -450 815 -442 801 -454 809 -454 429 -820 419 -838 811 -456 785 -428 409 -842 439 -824 813 -448 415 -858 819 -418 831 -426 449 -808 427 -820 393 -866 421 -808 825 -436 413 -852 403 -884 421 -16394 407 -478 257 -574 229 -576 229 -564 231 -592 267 -490 305 -520 307 -486 309 -522 307 -458 341 -486 337 -4096 343 -882 389 -880 341 -874 807 -476 351 -882 397 -860 807 -450 431 -824 811 -450 399 -824 417 -844 817 -432 807 -448 411 -872 801 -460 417 -810 425 -836 809 -420 411 -838 409 -852 417 -844 425 -852 385 -872 801 -426 841 -420 811 -422 409 -844 809 -454 823 -432 415 -842 835 -450 805 -454 403 -822 809 -450 399 -826 417 -844 821 -434 807 -448 411 -876 801 -440 807 -450 383 -850 833 -416 415 -852 807 -456 811 -444 411 -838 419 -848 401 -852 377 -850 819 -454 795 -436 809 -448 821 -448 411 -846 417 -842 817 -432 811 -412 411 -864 417 -844 791 -438 415 -876 793 -458 809 -450 383 -832 413 -840 407 -866 387 -844 821 -434 413 -874 377 -868 419 -16408 411 -392 421 -390 421 -388 421 -376 427 -394 433 -388 409 -386 411 -384 449 -382 419 -384 419 -384 419 -4018 343 -89684 97 -430 65 -166 163 -66 231 -100 161 -392 161 -64 229 -1056 97 -198 97 -198 259 -166 691 -66 395 -98 131 -100 99 -66 199 -198 1657 -406 365 -462 361 -436 357 -438 387 -444 353 -444 385 -414 387 -448 355 -448 355 -444 395 -394 399 -4050 819 -434 811 -414 819 -450 409 -852 809 -450 805 -448 805 -446 831 -428 409 -846 389 -854 395 -862 811 +RAW_Data: -452 783 -462 811 -446 411 -874 383 -852 403 -852 777 -450 411 -838 805 -452 397 -858 805 -484 387 -872 803 -442 805 -448 383 -846 797 -484 777 -474 381 -846 831 -430 807 -482 387 -852 817 -418 805 -452 823 -430 385 -878 377 -876 411 -846 391 -884 811 -444 805 -420 415 -846 399 -852 807 -452 805 -444 803 -450 803 -454 807 -452 397 -850 395 -862 385 -844 427 -840 809 -456 379 -876 407 -880 383 -846 819 -432 387 -872 375 -854 413 -846 387 -886 779 -476 803 -450 801 -444 415 -846 793 -438 415 -846 417 -822 407 -852 417 -852 817 -444 409 -16426 443 -358 431 -388 409 -386 447 -350 449 -382 419 -386 419 -386 417 -386 419 -388 453 -354 453 -356 445 -4018 813 -416 839 -420 817 -418 451 -816 835 -444 809 -450 811 -440 803 -444 407 -830 419 -844 419 -836 805 -420 835 -444 803 -446 409 -868 421 -814 431 -822 807 -452 397 -828 819 -452 415 -856 787 -454 419 -848 837 -410 839 -416 395 -866 787 -450 811 -454 407 -850 805 -454 805 -470 381 -850 833 -418 805 -438 809 -448 397 -860 421 -810 431 -856 381 -888 791 -424 841 -422 415 -820 437 -818 813 -450 813 -454 803 -446 817 -448 829 -410 451 -816 403 -818 413 -850 409 -846 811 -448 415 -834 413 -884 399 -822 815 -452 381 -852 407 -846 415 -846 385 -866 807 -456 809 -446 835 -412 407 -834 815 -450 415 -822 405 -848 419 -844 427 -852 809 -442 407 -16420 425 -422 335 -486 309 -486 309 -522 307 -492 337 -454 351 -466 329 -498 327 -468 323 -472 355 -442 355 -4120 757 -456 773 -478 781 -458 381 -874 771 -482 801 -470 777 -482 805 -450 399 -826 415 -846 387 -866 805 -420 813 -446 831 -458 417 -846 401 -852 381 -840 835 -420 415 -846 795 -440 413 -842 835 -450 407 -860 811 -418 815 -424 413 -842 807 -454 823 -428 411 -842 801 -454 807 -488 401 -822 805 -448 803 -446 803 -426 447 -844 397 -856 381 -870 411 -870 777 -452 829 -432 385 -840 419 -848 797 -438 809 -450 815 -448 833 -440 803 -452 411 -820 415 -848 409 -844 411 -846 779 -462 409 -848 409 -864 421 -844 793 -438 385 -846 419 -850 399 -838 415 -872 777 -478 803 -448 799 -442 417 -848 799 -438 415 -842 409 -826 417 -844 427 -854 807 -452 409 -16402 461 -352 421 -386 421 -386 419 -388 453 -354 453 -354 447 -378 409 -386 439 -376 421 -410 385 -414 415 -4024 831 -418 809 -438 807 -444 409 -838 809 -456 821 -432 841 -414 255 -87638 131 -66 97 -296 97 -264 131 -196 65 -132 231 -632 197 -664 131 +RAW_Data: -500 395 -132 461 -132 689 -98 2685 -100 997 -1508 99 -2186 231 -166 231 -134 133 -932 65 -268 99 -132 65 -200 97 -68 163 -234 65 -68 99 -930 331 -98 763 -100 2025 -418 353 -446 385 -414 385 -416 387 -448 355 -442 383 -412 397 -424 405 -388 409 -418 379 -418 415 -4014 443 -814 413 -822 817 -454 801 -436 409 -842 409 -866 415 -838 441 -836 811 -432 387 -842 419 -846 793 -440 807 -448 837 -446 803 -448 835 -420 807 -448 383 -868 379 -850 409 -866 387 -844 825 -468 381 -884 793 -426 415 -842 427 -818 817 -440 407 -830 419 -844 429 -852 387 -872 409 -826 811 -450 813 -418 837 -412 409 -864 417 -844 397 -852 809 -454 805 -448 409 -840 809 -420 813 -458 409 -844 407 -860 385 -878 793 -470 809 -420 817 -416 417 -850 403 -852 381 -852 827 -428 447 -844 401 -854 813 -424 421 -840 419 -812 823 -438 415 -846 409 -844 415 -846 389 -868 809 -458 803 -416 409 -866 813 -418 417 -854 397 -862 419 -842 401 -854 415 -16404 435 -376 409 -410 407 -384 439 -384 409 -410 417 -368 421 -410 407 -378 447 -376 415 -378 447 -380 407 -4022 421 -844 423 -822 821 -418 807 -454 429 -820 421 -836 439 -854 421 -810 821 -436 385 -840 441 -822 813 -448 811 -452 803 -444 835 -444 801 -446 801 -426 447 -808 423 -834 413 -852 407 -840 819 -452 389 -856 813 -444 409 -848 415 -812 809 -458 409 -848 411 -842 415 -844 421 -834 415 -834 835 -418 819 -418 807 -456 393 -856 393 -866 421 -846 799 -474 809 -420 421 -836 811 -420 813 -458 407 -850 413 -842 415 -846 819 -428 835 -416 835 -412 407 -832 421 -842 423 -822 813 -446 407 -864 419 -846 799 -440 413 -850 419 -816 797 -442 413 -850 409 -844 417 -846 423 -834 841 -428 805 -414 435 -822 813 -450 413 -822 437 -818 421 -844 429 -854 411 -16406 427 -418 309 -522 307 -488 303 -520 289 -530 295 -500 323 -470 325 -504 321 -476 321 -476 355 -444 357 -4080 355 -906 339 -882 771 -476 777 -486 381 -874 383 -884 375 -884 387 -852 819 -418 417 -846 399 -854 809 -418 815 -446 837 -420 839 -454 801 -436 807 -452 399 -826 417 -844 391 -852 423 -838 809 -452 431 -852 811 -414 409 -836 417 -844 821 -432 385 -876 385 -850 409 -848 415 -854 421 -840 817 -420 815 -424 817 -448 409 -848 413 -844 389 -854 815 -446 829 -426 413 -842 819 -434 809 -446 409 -838 419 -846 401 -852 811 -456 811 -444 803 -418 417 -848 403 -850 381 -864 805 -450 395 -866 419 -848 801 -474 381 -848 411 +RAW_Data: -842 807 -446 381 -872 377 -866 421 -846 401 -854 813 -458 779 -446 407 -832 811 -450 415 -856 399 -856 385 -876 399 -854 411 -16398 435 -392 395 -400 421 -412 385 -412 417 -384 415 -386 415 -418 385 -420 385 -420 417 -390 417 -388 419 -4020 421 -838 421 -812 819 -434 809 -448 397 -864 421 -844 401 -850 413 -858 789 -426 413 -844 419 -836 807 -424 843 -410 829 -442 835 -446 801 -454 809 -420 417 -832 411 -848 249 -88020 133 -896 231 -466 67 -1062 131 -728 163 -98 621 -98 1051 -100 680933 -452 269 -522 273 -554 273 -558 239 -558 271 -490 337 -488 321 -498 295 -500 325 -470 323 -474 353 -4082 757 -492 375 -880 357 -872 777 -486 773 -480 807 -450 805 -444 805 -476 407 -812 413 -834 411 -848 407 -828 813 -450 811 -458 803 -448 835 -446 791 -424 447 -808 427 -818 423 -840 419 -848 401 -854 811 -458 809 -446 801 -416 439 -826 415 -848 813 -430 809 -450 395 -866 419 -846 403 -850 413 -820 407 -848 415 -846 781 -460 805 -446 803 -474 803 -448 835 -420 805 -454 389 -836 409 -842 407 -866 419 -842 399 -854 809 -456 809 -446 409 -840 385 -844 819 -434 809 -450 395 -860 811 -452 393 -886 779 -446 409 -830 419 -842 423 -818 423 -838 419 -844 799 -472 809 -454 385 -844 807 -454 391 -854 395 -860 385 -844 429 -852 809 -454 385 -874 409 -16402 427 -368 455 -358 433 -380 443 -378 415 -378 447 -380 411 -384 409 -406 421 -408 387 -412 415 -386 415 -4026 831 -398 441 -810 417 -832 837 -418 833 -444 803 -446 833 -448 801 -424 449 -810 427 -820 423 -838 419 -812 825 -438 841 -416 845 -446 825 -418 809 -422 419 -822 433 -822 419 -844 425 -820 421 -840 841 -458 797 -436 809 -414 435 -822 419 -844 819 -432 809 -448 395 -864 421 -846 407 -850 411 -808 433 -824 419 -844 819 -432 809 -446 823 -416 837 -454 807 -440 809 -414 435 -828 417 -844 425 -828 415 -848 419 -818 839 -446 807 -422 411 -844 419 -846 795 -438 807 -450 395 -866 811 -454 391 -854 845 -412 407 -832 421 -842 419 -832 411 -824 435 -820 815 -450 811 -460 409 -850 799 -454 407 -824 413 -848 411 -842 415 -844 815 -432 415 -848 405 -16400 441 -432 327 -492 301 -516 307 -484 309 -520 307 -492 339 -454 337 -490 331 -464 327 -500 325 -472 325 -4110 763 -480 373 -852 385 -878 759 -482 775 -474 813 -458 781 -482 789 -454 415 -846 397 -820 411 -840 405 -852 809 -450 811 -458 809 -450 817 -448 803 -426 411 -844 391 -854 393 -866 419 -848 399 -854 811 +RAW_Data: -454 811 -444 803 -418 417 -846 403 -850 809 -452 805 -444 411 -840 419 -846 407 -850 415 -836 385 -842 419 -850 797 -438 807 -452 817 -446 801 -486 813 -444 775 -450 409 -838 419 -810 431 -854 379 -848 405 -884 809 -450 817 -430 385 -874 375 -856 811 -446 809 -422 421 -836 835 -452 419 -848 783 -460 409 -814 407 -856 415 -846 383 -870 381 -848 819 -450 811 -472 383 -850 803 -454 415 -838 399 -854 379 -850 407 -848 811 -448 415 -872 387 -16400 451 -374 445 -374 415 -378 415 -412 411 -384 405 -422 409 -410 387 -410 417 -382 417 -384 415 -420 383 -4030 827 -428 411 -842 425 -820 817 -418 833 -426 845 -452 815 -428 837 -416 409 -842 421 -810 431 -820 421 -89106 265 -662 99 -532 131 -598 97 -668 65 -300 761 -198 231 -132 265 -100 233 -100 197 diff --git a/assets/unit_tests/subghz/dooya.sub b/assets/unit_tests/subghz/dooya.sub new file mode 100644 index 000000000..0767a1a73 --- /dev/null +++ b/assets/unit_tests/subghz/dooya.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Dooya +Bit: 40 +Key: 00 00 00 E1 DC 03 05 11 diff --git a/assets/unit_tests/subghz/dooya_raw.sub b/assets/unit_tests/subghz/dooya_raw.sub new file mode 100644 index 000000000..6c3ca1627 --- /dev/null +++ b/assets/unit_tests/subghz/dooya_raw.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 4046 -17306 65 -298 97 -100 133 -268 265 -330 133 -132 1723 -16806 165 -132 99 -920 65 -622 789 -130 99 -66 361 -98 295 -166 73573 -17510 97 -492 129 -728 529 -100 1063 -164 295 -66 1119 -14962 627 -166 363 -264 427 -132 593 -100 633 -132 39555 -16938 99 -2024 65 -100 97 -164 99 -66 399 -100 123891 -16736 163 -200 97 -200 165 -264 65 -828 427 -132 871 -5132 591 -490 595 -486 605 -454 275 -822 241 -824 273 -784 321 -782 649 -444 653 -408 657 -428 321 -744 693 -388 699 -388 707 -392 313 -752 345 -750 317 -744 351 -730 355 -738 323 -774 327 -748 329 -750 695 -386 701 -354 381 -722 351 -720 385 -718 351 -718 345 -738 705 -382 329 -736 713 -360 387 -718 369 -718 367 -706 735 -352 375 -726 351 -722 351 -720 719 -7808 4845 -1474 743 -332 741 -370 705 -370 349 -718 383 -716 345 -712 381 -704 747 -326 747 -350 737 -352 351 -718 719 -360 741 -366 687 -362 375 -704 381 -724 351 -740 353 -712 357 -718 359 -744 363 -688 365 -722 727 -354 727 -354 379 -724 351 -722 353 -720 387 -718 353 -718 703 -374 351 -716 735 -354 365 -708 353 -734 351 -746 717 -356 359 -720 371 -704 371 -720 731 -7786 4847 -1482 711 -386 711 -358 743 -330 373 -708 359 -748 349 -740 351 -716 719 -356 727 -354 739 -354 351 -718 719 -362 743 -364 721 -330 373 -706 381 -722 351 -740 353 -712 359 -720 361 -722 361 -720 361 -720 725 -354 731 -354 381 -720 353 -722 385 -720 351 -720 349 -716 735 -354 361 -748 711 -364 347 -740 365 -722 365 -720 695 -384 371 -704 381 -702 377 -710 709 -7804 4853 -1468 743 -336 735 -358 719 -352 379 -724 353 -722 353 -720 387 -686 721 -360 721 -362 743 -332 387 -718 721 -366 701 -382 701 -350 377 -720 351 -740 353 -714 357 -710 397 -710 365 -702 385 -688 377 -724 731 -352 703 -354 379 -736 343 -740 357 -720 349 -706 385 -718 719 -354 365 -724 735 -352 377 -724 355 -720 353 -720 721 -358 387 -686 387 -718 353 -718 733 -7796 4821 -1492 739 -350 719 -334 737 -350 365 -722 373 -722 367 -708 371 -702 747 -352 711 -358 743 -364 343 -706 749 -352 717 -350 717 -384 327 -736 351 -746 355 -716 357 -720 359 -710 365 -742 365 -708 367 -704 711 -354 743 -356 387 -684 373 -706 381 -722 351 -740 353 -714 721 -356 361 -720 733 -352 375 -694 385 -724 353 -722 719 -356 385 -686 385 -718 351 -716 731 -7792 4843 -1480 717 -354 719 -386 717 -354 359 -720 351 -708 387 -712 355 -718 721 -356 727 -354 739 -356 351 -718 741 -364 +RAW_Data: 705 -370 703 -372 351 -718 383 -720 347 -720 347 -714 381 -704 353 -744 357 -718 355 -720 723 -356 725 -354 379 -722 351 -722 353 -722 385 -718 351 -718 721 -372 351 -716 719 -372 351 -718 383 -716 345 -714 743 -346 361 -740 353 -712 357 -710 725 -7818 4837 -1498 713 -356 709 -360 741 -332 375 -706 359 -750 351 -706 353 -748 719 -356 723 -352 739 -354 351 -718 709 -364 719 -362 721 -364 385 -718 353 -718 383 -682 377 -712 349 -734 353 -742 355 -712 359 -722 723 -354 729 -352 381 -722 353 -722 351 -720 387 -718 353 -716 701 -388 345 -722 737 -354 357 -722 351 -708 387 -712 717 -350 731 -354 741 -356 743 -330 375 -8180 4829 -1468 739 -364 707 -354 729 -352 379 -722 353 -720 387 -686 387 -718 707 -368 721 -366 707 -368 351 -718 735 -354 719 -354 719 -388 329 -746 349 -738 351 -712 359 -718 361 -742 365 -708 371 -706 373 -720 733 -320 733 -354 383 -720 353 -720 387 -718 351 -716 385 -714 703 -388 327 -746 705 -348 387 -702 385 -690 385 -724 713 -358 709 -362 743 -364 709 -370 351 -8162 4837 -1482 715 -388 715 -352 715 -384 325 -730 353 -744 353 -712 359 -720 723 -354 733 -354 745 -356 351 -720 719 -362 741 -330 737 -382 349 -722 345 -724 361 -744 349 -704 383 -716 357 -718 357 -720 361 -720 723 -354 733 -354 383 -720 387 -686 387 -718 353 -718 349 -716 731 -384 347 -724 721 -352 365 -706 353 -732 353 -746 717 -356 723 -352 739 -354 711 -360 385 -8146 4841 -1470 737 -344 739 -326 751 -352 377 -690 387 -724 353 -724 353 -722 711 -360 743 -364 721 -330 387 -716 703 -386 721 -356 721 -354 363 -706 349 -734 351 -746 355 -718 355 -712 363 -744 365 -708 369 -722 695 -352 731 -354 381 -722 353 -722 351 -734 351 -716 383 -720 723 -354 333 -736 739 -348 361 -708 351 -748 355 -712 725 -354 727 -352 741 -352 713 -358 385 -8134 4855 -1474 719 -358 709 -362 721 -364 387 -716 351 -718 385 -712 347 -712 739 -334 739 -354 729 -352 379 -722 717 -354 711 -360 743 -332 387 -718 351 -716 377 -708 349 -730 353 -742 355 -710 359 -720 359 -720 723 -354 729 -352 381 -720 353 -722 351 -722 387 -684 387 -716 703 -384 349 -722 737 -354 329 -750 349 -738 353 -712 719 -356 725 -354 741 -354 717 -358 385 -8126 4861 -1470 735 -344 731 -346 729 -348 383 -718 347 -712 353 -734 353 -746 715 -356 725 -350 741 -352 351 -718 741 -366 721 -366 705 -370 353 -718 385 -682 377 -710 349 -734 353 -744 355 -710 359 -710 397 -688 +RAW_Data: 727 -354 729 -352 379 -724 353 -722 353 -718 387 -716 353 -716 735 -348 383 -682 727 -386 347 -722 347 -712 381 -706 747 -326 747 -350 737 -352 711 -358 diff --git a/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub b/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub new file mode 100644 index 000000000..49b190002 --- /dev/null +++ b/assets/unit_tests/subghz/kinggates_stylo4k_raw.sub @@ -0,0 +1,11 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 377 -386 1117 -410 1121 -352 1141 -384 1151 -378 1119 -350 1139 -386 1115 -1134 389 -1114 395 -1122 363 -1136 389 -358 1167 -356 1145 -1120 389 -1110 391 -356 1139 -1126 389 -1114 391 -1122 363 -1146 389 -1110 395 -1122 363 -1138 389 -1110 393 -1122 363 -1140 389 -1112 393 -1120 389 -1118 389 -1112 397 -1124 363 -1142 389 -1112 359 -1154 367 -1134 389 -1144 365 -1138 355 -394 1119 -380 1107 -1152 353 -398 1113 -384 1139 -1118 385 -376 1141 -386 1129 -350 1143 -388 1109 -1132 389 -1112 393 -390 1107 -1128 389 -1112 397 -388 1111 -1132 389 -358 1127 -1118 417 -1116 383 -1120 353 -1158 389 -1108 375 -384 1121 -408 1123 -350 1139 -386 1111 -1130 389 -1114 395 -1122 395 -1114 389 -1116 395 -1122 363 -1138 387 -9444 373 -374 379 -374 381 -346 403 -346 389 -376 389 -390 353 -376 359 -382 383 -360 419 -360 359 -386 359 -2264 777 -356 1127 -390 1143 -362 1131 -1138 365 -1122 359 -386 1153 -1106 377 -1152 385 -372 1113 -1140 385 -1118 381 -1114 383 -1150 383 -1120 355 -1122 389 -358 1165 -386 1113 -1128 389 -360 1125 -384 1131 -368 1157 -350 1139 -386 1115 -406 1099 -384 1141 -1122 383 -1110 373 -1130 385 -1128 393 -380 1131 -380 1129 -1112 383 -1132 391 -356 1143 -1124 383 -1130 367 -1136 385 -1136 387 -1112 371 -1120 389 -1118 383 -1130 371 -1130 383 -1110 383 -1120 413 -1118 383 -1144 347 -1144 389 -1110 393 -1122 363 -1140 389 -1112 359 -1154 363 -1146 389 -1110 393 -374 1115 -384 1115 -1144 385 -368 1141 -388 1111 -1110 421 -360 1125 -388 1109 -392 1137 -358 1125 -1144 365 -1138 389 -358 1123 -1118 401 -1138 389 -360 1121 -1120 417 -358 1109 -1154 355 -1120 375 -1138 385 -1130 391 -1136 355 -398 1115 -380 1141 -384 1121 -382 1119 -1104 413 -1118 355 -1156 387 -1112 377 -1122 389 -1118 387 -1112 397 -9422 417 -352 363 -416 355 -388 345 -382 377 -380 375 -380 375 -380 375 -380 385 -356 379 -366 385 -374 387 -2246 745 -380 1141 -386 1113 -370 1125 -1140 373 -1152 355 -394 1117 -1140 381 -1120 385 -374 1145 -1112 385 -1122 381 -1116 383 -1120 375 -1120 389 -1120 373 -380 1171 -358 1121 -1142 377 -356 1127 -384 1137 -378 1155 -390 1105 -366 1125 -386 1135 -386 1111 -1132 389 -1112 393 -1120 365 -1138 387 -360 1163 -356 1143 -1126 387 -1114 357 -386 1141 -1126 383 -1130 365 -1132 381 -1140 377 -1116 383 -1130 371 -1128 381 -1140 347 -1148 385 -1128 369 -1128 381 -1142 377 -1114 389 -1112 395 -1124 361 -1142 389 -1114 393 -1122 365 -1138 389 -1114 397 -1108 389 -392 1119 -350 1139 -1152 355 -396 1115 -382 1109 -1156 385 -374 1111 -384 1139 -368 1147 -388 1109 -1112 389 -1120 383 -388 1107 -1150 389 -1112 +RAW_Data: 393 -390 1109 -1128 389 -360 1125 -1120 381 -1152 383 -1118 353 -1158 387 -1112 375 -386 1117 -408 1121 -350 1143 -388 1109 -1132 389 -1114 391 -1122 395 -1120 389 -1112 393 -1122 365 -1136 389 -9442 373 -376 389 -354 377 -366 387 -384 357 -378 361 -418 347 -394 385 -358 363 -382 361 -414 357 -392 333 -2290 751 -384 1113 -406 1121 -350 1137 -1136 353 -1160 385 -356 1135 -1120 361 -1146 385 -388 1137 -1108 361 -1150 387 -1112 395 -1136 349 -1154 353 -1142 371 -384 1145 -378 1117 -1138 381 -382 1087 -410 1121 -382 1143 -380 1121 -380 1115 -384 1107 -418 1115 -1106 385 -1148 365 -1118 359 -1146 387 -388 1135 -388 1113 -1126 383 -1130 367 -376 1113 -1142 383 -1114 375 -1154 355 -1160 385 -1110 371 -1152 357 -1118 385 -1146 365 -1122 361 -1146 387 -1114 395 -1134 355 -1160 351 -1146 369 -1154 355 -1120 387 -1114 397 -1136 357 -1118 407 -1144 351 -1134 359 -420 1111 -366 1131 -1142 379 -384 1089 -410 1119 -1142 379 -366 1141 -386 1109 -388 1131 -350 1141 -1118 391 -1114 375 -378 1153 -1116 385 -1136 383 -358 1139 -1120 359 -420 1099 -1142 383 -1118 383 -1138 347 -1144 385 -1144 369 -386 1113 -404 1089 -386 1141 -382 1099 -1136 381 -1128 375 -1130 383 -1140 359 -1146 387 -1114 395 -1138 357 -9430 383 -378 359 -418 347 -392 387 -360 363 -384 361 -414 357 -386 347 -384 375 -382 385 -358 383 -364 387 -2252 773 -354 1131 -384 1137 -386 1111 -1132 387 -1112 397 -388 1113 -1124 389 -1116 387 -388 1115 -1132 389 -1114 393 -1120 365 -1140 389 -1114 357 -1154 365 -378 1151 -358 1127 -1156 367 -376 1135 -358 1125 -388 1141 -368 1125 -386 1133 -388 1109 -370 1155 -1106 375 -1122 389 -1118 389 -1114 395 -386 1117 -410 1123 -1106 377 -1130 383 -388 1107 -1152 353 -1148 353 -1150 367 -1142 389 -1110 397 -1120 365 -1138 389 -1110 391 -1122 363 -1142 387 -1116 389 -1120 391 -1116 389 -1116 395 -1122 365 -1140 389 -1114 357 -1154 363 -1138 389 -1142 365 -1138 355 -396 1115 -382 1141 -1118 353 -400 1111 -384 1139 -1120 381 -386 1139 -366 1119 -392 1121 -388 1107 -1152 389 -1114 355 -388 1139 -1126 387 -1114 397 -376 1111 -1144 375 -380 1129 -1138 375 -1098 385 -1140 377 -1118 387 -1144 371 -386 1115 -404 1121 -348 1137 -386 1113 -1134 389 -1112 395 -1124 395 -1118 389 -1110 395 -1122 363 -1138 389 -9418 391 -360 407 -384 361 -388 355 -390 367 -376 373 -380 387 -356 377 -366 385 -388 355 -378 359 -384 377 -2266 777 -346 1149 -388 1107 -390 1129 -1104 415 -1118 353 -398 1113 -1138 383 -1122 381 -388 1141 -1118 389 -1112 357 -1154 365 -1138 389 -1114 357 -1154 363 -378 1155 -358 1123 -1156 381 -360 1107 -384 +RAW_Data: 1153 -378 1119 -382 1143 -382 1121 -382 1117 -382 1113 -1120 389 -1120 387 -1112 399 -1120 393 -392 1119 -350 1141 -1154 357 -1116 389 -360 1163 -1120 365 -1138 387 -1114 389 -1122 389 -1116 387 -1114 397 -1104 379 -1156 353 -1148 367 -1118 377 -1122 423 -1110 373 -1122 389 -1118 383 -1130 373 -1128 383 -1140 345 -1146 383 -1130 399 -1130 353 -1142 377 -358 1127 -384 1143 -1118 385 -372 1111 -386 1137 -1120 381 -388 1141 -364 1127 -384 1133 -374 1111 -1148 383 -1114 373 -384 1115 -1136 387 -1144 371 -386 1115 -1132 387 -360 1123 -1150 345 -1148 383 -1128 371 -1132 381 -1140 379 -390 1123 -350 1139 -388 1113 -406 1089 -1142 373 -1120 389 -1118 423 -1110 371 -1120 379 -1122 407 -1104 417 -9440 389 -356 379 -366 385 -388 355 -378 359 -384 381 -394 387 -358 361 -386 359 -416 355 -388 345 -384 377 -2262 747 -384 1149 -380 1115 -382 1113 -1120 389 -1120 389 -360 1129 -1152 367 -1136 389 -358 1131 -1152 367 -1138 389 -1116 355 -1152 367 -1134 389 -1116 353 -388 1141 -368 1123 -1138 375 -386 1113 -408 1121 -350 1175 -372 1105 -386 1145 -352 1141 -366 1145 -1114 385 -1116 377 -1122 389 -1120 421 -354 1139 -388 1109 -1132 383 -1130 369 -374 1113 -1144 385 -1114 377 -1120 391 -1128 373 -1138 385 -1130 359 -1138 377 -1120 373 -1138 383 -1130 359 -1138 379 -1160 375 -1106 385 -1130 393 -1120 377 -1118 389 -1112 393 -1140 355 -1120 421 -1114 371 -1122 391 -390 1123 -350 1139 -1134 353 -402 1113 -384 1141 -1118 385 -376 1143 -352 1161 -352 1135 -386 1113 -1132 387 -1114 395 -388 1111 -1128 387 -1114 399 -374 1115 -1142 375 -380 1117 -1118 387 -1144 363 -1136 385 -1130 367 -1130 383 -388 1107 -392 1129 -380 1115 -384 1113 -1136 389 -1114 393 -1124 393 -1120 389 -1114 393 -1124 363 -1140 389 -9416 391 -360 405 -386 329 -416 357 -392 365 -374 377 -380 343 -412 341 -412 353 -390 375 -366 385 -386 355 -2264 743 -394 1123 -388 1111 -392 1133 -1110 395 -1120 363 -382 1133 -1142 381 -1118 383 -376 1111 -1146 383 -1122 383 -1146 347 -1150 381 -1116 353 -1158 343 -410 1133 -382 1111 -1152 355 -394 1119 -382 1109 -382 1153 -378 1131 -354 1137 -396 1119 -388 1111 -1150 351 -1152 351 -1150 365 -1136 387 -356 1131 -386 1143 -1122 387 -1112 357 -420 1107 -1128 387 -1114 359 -1152 363 -1148 387 -1114 395 -1122 361 -1140 387 -1110 395 -1120 361 -1140 387 -1114 393 -1154 355 -1120 387 -1146 365 -1118 361 -1146 387 -1112 395 -1120 363 -1140 385 -1144 367 -1120 359 -420 1099 -384 1139 -1118 383 -384 1109 -392 1129 -1138 379 -366 1147 -388 1109 -386 1099 -384 1139 -1132 349 -1158 375 -380 1131 -1104 411 -1122 351 -416 1111 -1148 +RAW_Data: 353 -396 1121 -1142 347 -1150 381 -1116 355 -1156 375 -1144 387 -360 1119 -388 1107 -394 1131 -386 1101 -1152 363 -1138 387 -1112 391 -1152 357 -1116 375 -1136 383 -1122 383 -9448 357 -392 357 -398 363 -378 385 -358 383 -364 389 -386 357 -380 389 -386 347 -382 375 -384 375 -380 373 -2262 747 -376 1145 -390 1107 -386 1129 -1104 413 -1120 353 -396 1115 -1140 381 -1122 383 -376 1143 -1110 385 -1118 383 -1114 417 -1114 383 -1120 353 -1156 389 -356 1135 -386 1113 -1134 389 -358 1129 -390 1107 -392 1153 -358 1127 -388 1143 -362 1131 -356 1131 -1154 365 -1136 389 -1114 357 -1150 363 -386 1153 -358 1125 -1118 417 -1120 381 -350 1123 -1134 391 -1112 395 -1124 395 -1116 389 -1112 393 -1124 363 -1140 389 -1114 359 -1154 363 -1138 389 -1114 391 -1124 361 -1144 389 -1112 393 -1122 363 -1138 389 -1112 391 -1122 363 -1138 389 -1144 365 -1124 361 -382 1155 -350 1137 -1120 391 -386 1131 -350 1151 -1120 383 -378 1141 -352 1137 -394 1117 -390 1107 -1150 389 -1114 355 -388 1143 -1120 387 -1112 397 -388 1113 -1130 385 -344 1163 -1104 379 -1122 373 -1140 383 -1130 389 -1124 359 -386 1127 -386 1139 -368 1141 -390 1107 -1112 387 -1116 385 -1150 367 -1140 389 -1112 393 -1124 363 -1136 389 -9444 379 -340 417 -360 359 -386 359 -416 355 -386 347 -384 375 -382 375 -380 375 -378 375 -380 385 -356 379 -2278 745 -354 1151 -368 1141 -390 1105 -1114 387 -1116 385 -386 1141 -1120 389 -1114 389 -388 1113 -1130 389 -1112 393 -1124 363 -1138 389 -1112 389 -1122 363 -380 1159 -350 1137 -1122 391 -388 1097 -384 1139 -382 1125 -386 1145 -352 1141 -366 1145 -390 1107 -1110 387 -1150 353 -1150 367 -1138 387 -360 1125 -390 1109 -1152 389 -1112 357 -388 1141 -1122 389 -1110 391 -1122 395 -1112 389 -1110 397 -1120 363 -1144 389 -1114 391 -1122 365 -1138 389 -1116 389 -1142 355 -1120 389 -1112 397 -1122 363 -1140 389 -1110 393 -1130 349 -1140 405 -1134 389 -1112 357 -388 1141 -364 1129 -1142 367 -388 1111 -370 1131 -1140 383 -364 1149 -388 1109 -388 1137 -356 1127 -1118 383 -1120 413 -350 1121 -1132 407 -1140 355 -364 1149 -1112 371 -406 1129 -1104 409 -1098 383 -1116 417 -1118 381 -1118 385 -388 1111 -390 1129 -350 1137 -386 1113 -1138 389 -1114 395 -1122 393 -1120 389 -1112 393 -1124 363 -1138 389 -9444 379 -340 417 -360 359 -386 361 -414 357 -386 347 -384 375 -382 375 -380 375 -380 375 -378 373 -380 373 -2262 749 -386 1111 -408 1117 -348 1143 -1120 391 -1116 389 -358 1127 -1154 365 -1136 387 -360 1129 -1154 365 -1136 389 -1114 357 -1154 365 -1134 389 -1112 357 -390 1137 -406 1119 -1106 377 -386 1117 -406 1123 -350 1143 -384 +RAW_Data: 1149 -378 1121 -350 1145 -380 1133 -1104 375 -1136 385 -1130 359 -1138 379 -400 1129 -354 1139 -1148 355 -1150 365 -378 1119 -1146 355 -1152 365 -1134 389 -1110 397 -1122 363 -1140 389 -1110 395 -1122 363 -1142 389 -1116 357 -1152 365 -1146 389 -1112 393 -1130 349 -1138 383 -1116 413 -1120 353 -1122 387 -1114 397 -1154 355 -1124 387 -360 1133 -384 1131 -1134 383 -376 1133 -352 1133 -1132 383 -376 1139 -378 1135 -380 1115 -382 1141 -1118 353 -1160 387 -356 1133 -1118 379 -1158 353 -392 1133 -1104 379 -398 1117 -1138 383 -1118 353 -1164 353 -1146 403 -1120 353 -398 1115 -382 1143 -384 1089 -412 1121 -1106 377 -1154 355 -1118 407 -1146 351 -1130 395 -1138 355 -1118 407 -9434 353 -396 363 -380 383 -360 383 -364 389 -386 357 -414 355 -386 345 -386 375 -382 375 -380 375 -378 375 -2256 769 -384 1119 -382 1117 -380 1113 -1122 389 -1118 389 -360 1131 -1140 377 -1118 421 -354 1139 -1140 355 -1118 405 -1104 387 -1128 391 -1122 363 -1138 387 -360 1157 -354 1143 -1128 387 -360 1121 -388 1141 -362 1129 -384 1139 -388 1111 -370 1127 -384 1135 -1122 363 -1140 389 -1116 393 -1122 395 -356 1129 -384 1141 -1120 383 -1134 387 -356 1133 -1130 349 -1140 383 -1116 413 -1118 381 -1110 377 -1146 389 -1114 391 -1124 365 -1138 391 -1112 357 -1150 365 -1144 387 -1112 395 -1122 361 -1140 387 -1112 393 -1104 379 -1158 353 -1144 403 -1118 353 -1158 353 -390 1133 -390 1107 -1130 389 -358 1125 -388 1111 -1154 389 -358 1129 -386 1131 -368 1129 -382 1139 -1118 353 -1164 387 -356 1135 -1120 393 -1118 389 -358 1131 -1154 365 -376 1135 -1108 395 -1136 347 -1126 387 -1144 403 -1120 353 -398 1115 -384 1141 -372 1103 -386 1145 -1108 387 -1120 383 -1116 403 -1140 389 -1116 353 -1146 361 -1144 389 -9420 393 -362 401 -338 377 -388 385 -374 361 -382 375 -382 375 -380 373 -380 373 -380 373 -380 389 -354 379 -2272 743 -388 1137 -360 1121 -386 1111 -1152 351 -1148 359 -384 1143 -1126 387 -1114 391 -384 1117 -1130 383 -1132 369 -1134 351 -1138 377 -1142 385 -1112 359 -420 1107 -406 1121 -1104 377 -384 1119 -406 1119 -352 1171 -382 1123 -378 1119 -384 1107 -384 1119 -1136 385 -1116 393 -1120 361 -1142 387 -388 1137 -386 1113 -1128 385 -1116 357 -420 1113 -1124 387 -1114 359 -1148 395 -1116 385 -1146 363 -1116 361 -1144 387 -1144 363 -1120 361 -1144 385 -1112 393 -1152 355 -1154 353 -1144 367 -1136 355 -1158 351 -1146 369 -1120 361 -1144 385 -1148 369 -1152 357 -392 1117 -380 1107 -1152 355 -398 1119 -382 1109 -1152 385 -374 1113 -386 1139 -366 1145 -388 1111 -1110 385 -1148 353 -386 1139 -1124 387 -1142 365 -386 1113 -1132 385 -360 1125 -1144 +RAW_Data: 363 -1140 387 -1114 357 -1152 363 -1146 387 -358 1129 -386 1139 -366 1125 -384 1139 -1120 363 -1140 387 -1112 393 -1130 381 -1136 383 -1114 371 -1132 383 -116626 65 -934 133 -1954 131 -102 133 -136 97 -332 65 -430 299 -296 129 -100 265 -168 367 -100 65 -66 231 -336 9643 -7766 529 -68 467 -166 65 -134 99 -500 331 -132 65 -130 329 -98 497 -100 1195 -100 1959 -66 4163 -7346 97 -392 165 -194 97 -2978 433 -298 531 -298 65 -200 131 -132 261 -98 229 -68 12837 -340 99 -268 165 -134 65 -898 67 -100 265 -66 165 -100 597 -166 199 -298 199 -200 99 -132 233 -132 299 -132 233 -166 65 -66 4021 -168 133 -68 231 -168 4647 -130 1399 -7750 133 -1714 197 -2480 131 -200 65 -100 265 -890 63 -1152 197 -98 293 -134 65 -300 361 -100 1035 -100 231 -132 299 -100 3399 -66 6287 -4506 99 -100 65 -130 99 -196 461 -98 331 -164 97 -162 227 -64 197 -98 229 -130 195 -100 425 -526 165 -130 95 -522 457 -560 233 -98 261 -66 1155 -100 259 -130 1407 -98 553 -66 7793 -494 65 -232 65 -3652 229 -2716 361 -266 333 -200 133 -166 99 -132 267 -66 133 -132 199 -166 331 -132 331 -166 197 -950 229 -198 303 -298 365 -100 4839 -3816 165 -130 229 -696 131 -130 261 -262 97 -166 263 -894 165 -230 365 -566 129 -560 197 -324 99 -98 261 -134 131 -100 67 -334 67 -232 199 -132 165 -302 67 -100 1467 -98 459 -100 1081 -130 131 -66 8927 -232 165 -3104 99 -2812 65 -982 131 -98 195 -98 263 -264 231 -66 195 -132 193 -164 65 -100 365 -132 1629 -66 1009 -132 8383 -632 131 -3060 131 -492 425 -100 763 -166 371 -132 1197 -134 229 -694 461 -366 365 -98 329 -198 267 -168 399 -68 131 -332 493 -132 231 -132 569 -66 7765 -7568 99 -532 65 -634 133 -3540 65 -100 263 -592 261 -1484 299 -302 265 -234 1129 -304 99 -436 163 -360 97 -556 231 -166 265 -1164 165 -134 235 -100 163 -332 297 -100 197 -132 99 -566 133 -234 133 -328 295 -98 985 -98 163 -396 399 -134 1557 -134 297 -266 6875 -68 1759 -7194 133 -166 99 -266 65 -432 67 -432 393 -5086 99 -66 199 -68 263 -866 429 -100 359 -130 261 -132 267 -134 533 -134 9251 -4184 65 -1156 165 -198 65 -426 297 -492 67 -164 131 -198 259 -164 199 -100 733 -134 865 -100 397 -132 65 -100 197 -66 327 -164 227 -98 231 -132 97 -262 99 -130 229 -66 589 -96 1119 -98 1905 -7486 599 -66 561 -66 359 -98 757 -162 261 -66 323 -130 5573 -8538 99 -894 131 -594 229 -364 63 -1378 197 -1682 331 -100 199 -166 diff --git a/assets/unit_tests/subghz/linear_delta3.sub b/assets/unit_tests/subghz/linear_delta3.sub new file mode 100644 index 000000000..f00507428 --- /dev/null +++ b/assets/unit_tests/subghz/linear_delta3.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: LinearDelta3 +Bit: 8 +Key: 00 00 00 00 00 00 00 D0 diff --git a/assets/unit_tests/subghz/linear_delta3_raw.sub b/assets/unit_tests/subghz/linear_delta3_raw.sub new file mode 100644 index 000000000..1973622a5 --- /dev/null +++ b/assets/unit_tests/subghz/linear_delta3_raw.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: -66 11813 -100 14655 -98 40111 -66 1625 -2116 1933 -34732 501 -11730 235 -3728 1887 -2106 1933 -2092 1971 -2072 1959 -34712 511 -3554 445 -3556 1997 -2036 455 -3594 1963 -2046 1979 -2076 1961 -2070 1989 -34690 483 -7724 1739 -2226 355 -3684 1857 -2138 1929 -2078 1965 -2074 1947 -34750 487 -3538 473 -3544 1993 -2042 485 -3548 1961 -2070 1965 -2070 1969 -2042 1997 -34716 443 -7734 1753 -2236 323 -3676 1903 -2098 1945 -2102 1927 -2070 1989 -34710 521 -3532 473 -3544 1991 -2032 481 -3556 1969 -2076 1967 -2036 1991 -2066 1969 -34718 467 -7756 1739 -2192 363 -3654 1889 -2132 1929 -2096 1935 -2070 1987 -34716 511 -3522 471 -3554 2009 -2036 459 -3550 2003 -2038 1979 -2042 1999 -2042 1999 -34704 471 -11774 225 -3710 1879 -2162 1885 -2112 1925 -2110 1939 -34738 459 -3636 403 -3612 1939 -2062 451 -3566 1985 -2044 1995 -2040 2009 -2032 2003 -34684 495 -3680 295 -3648 1935 -2098 423 -3562 2001 -2038 1989 -2044 2003 -2036 1977 -34718 461 -3678 295 -3684 1901 -2098 429 -3596 1967 -2036 1981 -2048 1993 -2042 2013 -34686 521 -3530 457 -3568 1999 -2036 455 -3552 1999 -2032 2019 -2024 1995 -2022 1997 -34716 441 -15774 1809 -2192 1905 -2100 1919 -2112 1961 -34720 417 -3830 167 -3710 1863 -2144 357 -3674 1909 -2100 1955 -2062 1977 -2072 1965 -34710 487 -3562 453 -3554 1985 -2052 481 -3536 2019 -2010 2001 -2042 1997 -2038 2005 -34716 451 -3602 433 -3584 1959 -2070 451 -3560 2001 -2038 1993 -2042 1967 -2072 1973 -34712 459 -3622 393 -3624 1933 -2068 457 -3584 1965 -2064 1979 -2052 1967 -2044 1981 -34722 477 -3608 397 -3588 1961 -2096 413 -3596 1971 -2040 1979 -2072 1963 -2070 1959 -34714 495 -3558 483 -3538 1985 -2042 479 -3562 1985 -2046 1967 -2070 1973 -2054 1995 -34688 493 -3578 413 -3614 1939 -2074 465 -3560 1971 -2038 2017 -2018 1995 -2042 2013 -34726 479 -3528 475 -3556 1999 -2036 455 -3570 1999 -2040 1973 -2054 2001 -2032 1987 -34720 477 -3562 445 -3602 1949 -2054 481 -3562 1975 -2060 1963 -2064 1977 -2038 2005 -34702 485 -3570 447 -3550 2015 -2020 479 -3564 1983 -2048 1999 -2034 1971 -2064 1993 -34688 517 -3516 497 -3532 1999 -2038 481 -3558 1997 -2004 2027 -2042 1963 -2038 1997 -34716 491 -3562 461 -3548 1995 -2032 491 -3524 2005 -2036 1989 -2038 1995 -2046 1979 -34714 465 -3682 293 -3680 1905 -2096 431 -3592 1969 -2070 1977 -2052 1965 -2044 1981 -34734 479 -3564 463 -3556 1999 -2032 457 -3550 1995 -2044 2011 -2042 1997 -2006 2027 -34680 531 -3524 483 -3538 1987 -2044 479 -3534 2013 -2048 1965 -2062 1987 -2030 1997 -34712 473 -3592 445 -3562 1975 -2072 451 -3566 1965 -2042 2013 -2046 1963 -2064 1993 -34700 459 -3632 371 -3638 1915 -2084 449 -3568 1987 -2046 1971 -2070 1983 -2022 1997 -34726 487 -3524 477 -3562 1985 -2044 481 -3542 2005 -2040 1995 -2038 1967 -2046 1993 -34710 511 -3528 471 -3560 1967 -2070 459 -3558 1971 +RAW_Data: -2072 1971 -2056 1971 -2074 1973 -34714 455 -3634 373 -3634 1901 -2110 419 -3620 1941 -2070 1991 -2040 1999 -2038 1965 -34740 467 -3562 481 -3534 1983 -2070 449 -3546 1999 -2044 1993 -2042 2003 -2036 1975 -34702 521 -3560 443 -3586 1969 -2044 449 -3562 1997 -2046 1987 -2042 2007 -2034 1973 -34732 487 -3562 443 -3582 1979 -2058 445 -3560 1995 -2044 1997 -2028 1987 -2034 2003 -34710 515 -3518 485 -3566 1977 -2036 483 -3536 1999 -2044 2009 -2024 1995 -2068 1973 -34710 487 -3564 471 -3558 1977 -2054 447 -3564 1991 -2042 1997 -2036 2007 -2034 2001 -34684 529 -3526 469 -3548 1989 -2038 483 -3562 1997 -2038 1973 -2034 1999 -2036 1997 -34728 487 -3536 479 -3534 2013 -2044 449 -3570 1985 -2042 1993 -2044 2005 -2014 1995 -34710 473 -3594 439 -3562 1995 -2040 457 -3564 2001 -2040 1975 -2046 1995 -2046 1999 -34704 491 -3548 451 -3570 1991 -2042 447 -3578 1967 -2046 1995 -2042 1999 -2034 2001 -34712 491 -3562 443 -3584 1981 -2018 479 -3562 1985 -2044 1997 -2030 1989 -2040 1997 -34722 489 -3554 459 -3560 1969 -2068 453 -3554 1999 -2034 1987 -2058 1997 -2046 1983 -34702 487 -3534 479 -3564 1983 -2040 483 -3538 1981 -2048 1993 -2048 2007 -2044 1995 -34696 489 -3550 453 -3570 1995 -2050 447 -3564 1983 -2040 1999 -2034 2003 -2034 1995 -34690 495 -3580 433 -3586 1969 -2064 453 -3552 1995 -2036 1991 -2056 1997 -2046 1987 -34706 441 -3636 373 -3626 1959 -2074 419 -3592 1963 -2074 1989 -2044 1971 -2070 1981 -34698 509 -3526 503 -3528 2005 -2034 481 -3528 1993 -2042 1999 -2066 1989 -2034 2003 -34678 495 -3540 481 -3546 1997 -2046 473 -3554 1999 -2034 2001 -2036 1995 -2046 1983 -34720 475 -3560 469 -3548 1997 -2030 485 -3566 1963 -2066 1983 -2046 1999 -2034 1973 -34734 487 -3560 443 -3584 1981 -2052 445 -3568 1987 -2044 1999 -2032 1993 -2034 2007 -34702 491 -3560 459 -3558 1967 -2070 455 -3556 2003 -2036 1977 -2042 2005 -2028 1997 -34730 461 -3564 473 -3536 2011 -2046 449 -3566 1989 -2044 1997 -2042 1971 -2054 2001 -34708 475 -3560 479 -3528 1999 -2040 485 -3566 1963 -2040 2013 -2042 1995 -2034 1987 -34694 519 -3554 441 -3582 1981 -2052 449 -3564 1985 -2040 1993 -2034 1991 -2062 1975 -34714 529 -3534 463 -3558 1969 -2068 451 -3560 2003 -2038 1993 -2042 1969 -2070 1975 -34720 493 -3582 383 -3616 1937 -2072 469 -3558 1995 -2036 1975 -2066 1995 -2042 1989 -34678 531 -3560 391 -3622 1937 -2094 429 -3588 1967 -2070 1981 -2054 1965 -2038 2021 -34682 525 -3524 481 -3564 1989 -2040 445 -3554 1997 -2040 2005 -2034 2001 -2024 1991 -34706 517 -3586 409 -3610 1927 -2076 451 -3558 1967 -2074 1993 -2038 2001 -2040 1975 -34714 495 -3588 409 -3602 1933 -2088 447 -3584 1965 -2044 1999 -2036 2007 -2030 1995 -34692 525 -3538 447 -3580 1981 -2042 487 -3542 1995 -2040 1969 -2072 1969 -2044 1991 -34714 443 -3636 399 -3630 1899 -2106 413 -3584 1997 +RAW_Data: -2034 2007 -2038 1969 -2076 1965 -34708 493 -3564 451 -3570 1965 -2074 449 -3548 2003 -2044 1987 -2038 1999 -2030 1991 -34710 493 -3602 403 -3612 1943 -2092 419 -3596 1963 -2062 1963 -2042 2001 -2064 1967 -34716 497 -3616 357 -3648 1903 -2132 399 -3596 1963 -2068 1977 -2052 1967 -2046 2019 -34684 497 -3614 359 -3650 1909 -2100 405 -3630 1925 -2098 1965 -2066 1965 -2056 1971 -34712 477 -3634 371 -3628 1931 -2104 391 -3624 1939 -2066 1975 -2052 2005 -2036 1985 -34714 449 -3668 337 -3664 1901 -2124 417 -3594 1963 -2048 1995 -2028 1993 -2066 1971 -34698 463 -3642 353 -3650 1943 -2066 433 -3594 1963 -2066 1995 -2034 1997 -2046 1981 -34730 479 -3560 445 -3562 1997 -2032 485 -3560 1965 -2062 1989 -2044 1999 -2032 1971 -34724 463 -3608 399 -3620 1943 -2096 421 -3592 1961 -2074 1979 -2036 2011 -2032 1971 -34734 469 -3558 485 -3552 1999 -2028 473 -3552 2003 -2032 2003 -2032 1997 -2044 1993 -34704 443 -3602 431 -3596 1967 -2076 447 -3556 1975 -2058 1997 -2040 1991 -2048 1971 -161100 97 -428 165 -200 395 -428 97 -100 559 -130 97 -164 129 -98 391 -98 295 -166 52395 -66 16239 -66 42541 -66 755 -132 14015 -98 2885 -68 10385 -98 40045 -100 987 -68 25539 -66 19799 -98 136101 -100 5141 -66 5709 -68 23177 -66 11097 -66 329 -100 261 -66 15755 -98 20575 -66 3645 -100 51411 -66 14441 -132 4467 -66 3965 -132 3707 -66 33107 -66 10373 -66 1775 -66 4185 -132 1429 -68 4675 -100 13419 -66 33985 diff --git a/assets/unit_tests/subghz/nice_one_raw.sub b/assets/unit_tests/subghz/nice_one_raw.sub new file mode 100644 index 000000000..169b3f088 --- /dev/null +++ b/assets/unit_tests/subghz/nice_one_raw.sub @@ -0,0 +1,12 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 7855 -12784 1413 -1544 469 -1040 465 -1010 479 -1020 967 -548 445 -1046 973 -524 967 -520 981 -516 483 -1042 449 -1034 949 -528 495 -1008 479 -1016 985 -518 453 -1042 449 -1052 949 -514 483 -1012 985 -512 477 -1042 445 -1050 951 -548 971 -512 975 -520 967 -554 949 -548 451 -1040 967 -520 987 -518 455 -1038 475 -1016 977 -518 983 -514 473 -1018 975 -518 487 -1002 475 -1020 965 -516 477 -1012 1007 -522 445 -1034 491 -1008 973 -524 +RAW_Data: 481 -992 481 -1010 483 -1030 977 -520 487 -1008 973 -522 987 -518 983 -514 965 -522 987 -520 489 -1004 473 -1018 471 -1016 1005 -476 511 -1012 457 -1018 1001 -510 975 -520 471 -1022 483 -1016 969 -536 1003 -454 981 -480 479 -986 981 -486 479 -946 989 -492 973 -484 473 -976 1503 -23606 1433 -1542 493 -1006 473 -1032 441 -1048 971 -514 483 -1012 985 -518 479 -1014 481 -1012 457 -1050 443 -1044 977 -520 473 -1004 495 -1004 969 -556 453 -1036 451 -1038 973 -520 485 -994 981 -520 457 -1050 477 -1014 977 -494 985 -538 961 -512 1005 -518 951 -526 491 -1006 969 -520 985 -524 455 -1044 447 -1048 983 -518 983 -514 441 -1050 981 -518 453 -1042 447 -1050 981 -518 451 -1046 975 -520 451 -1022 483 -1008 1001 -522 447 -1020 485 -1008 473 -1016 981 -550 449 -1044 977 -520 949 -550 979 -516 967 -520 983 -522 455 -1042 447 -1050 451 -1024 981 -520 483 -1018 963 -546 479 -1010 967 -520 483 -1022 975 -522 967 -552 487 -960 481 -990 451 -994 481 -980 479 -986 449 -984 969 -480 983 -510 1465 -23612 1473 -1520 479 -1026 453 -1044 451 -1036 943 -552 453 -1044 949 -518 481 -1018 977 -524 459 -1046 439 -1046 973 -528 463 -1012 471 -1046 943 -552 443 -1034 457 -1042 977 -518 479 -1028 949 -554 451 -1014 481 -1018 981 -524 985 -518 971 -514 979 -522 987 -512 477 -1016 977 -522 969 -552 449 -1016 483 -1014 985 -518 973 -516 481 -1012 967 -552 449 -1020 483 -1010 969 -554 447 -1022 977 -520 475 -1018 479 -1018 975 -522 457 -1036 479 -1016 479 -1002 969 -552 447 -1054 943 -548 969 -520 983 -520 983 -516 969 -518 479 -1030 453 -1044 449 -1048 943 -548 451 -1044 945 -552 975 -518 947 -552 449 -1034 975 -524 455 -1040 969 -520 449 -982 969 -518 945 -484 481 -984 481 -994 447 -986 477 -998 1435 -23658 1441 -1530 483 -1008 483 -1034 449 -1022 977 -520 485 -1018 479 -1018 975 -506 473 -1036 469 -1042 463 -1010 977 -520 487 -1030 451 -1010 981 -520 481 -1018 481 -1014 983 -518 479 -1016 975 -492 497 -1014 467 -1014 977 -520 975 -526 985 -516 979 -506 1005 -496 493 -1008 975 -522 983 -518 453 -1040 475 -1016 975 -524 987 -514 471 -1038 955 -514 473 -1046 445 -1044 967 -514 477 -1016 975 -520 457 -1050 477 -1010 973 -522 473 -1000 479 -1030 453 -1038 969 -506 473 -1050 971 -512 979 -524 955 -548 973 -512 975 -518 475 -1036 473 -1006 493 -1008 975 -520 973 -526 487 -1004 475 -1018 965 -516 1005 -512 481 -1014 985 -518 483 -986 975 -488 977 -480 977 -486 975 -482 481 -982 975 -480 977 -488 1477 -23618 1389 -1634 369 -1114 383 -1078 431 -1072 +RAW_Data: 931 -550 451 -1046 447 -1042 967 -552 945 -522 459 -1042 445 -1050 943 -552 439 -1036 459 -1046 977 -508 477 -1030 455 -1044 945 -552 451 -1020 979 -524 459 -1046 443 -1048 979 -518 967 -534 957 -516 977 -518 973 -528 455 -1042 973 -520 975 -526 459 -1040 481 -1020 969 -510 967 -546 447 -1050 955 -544 441 -1044 449 -1048 953 -550 443 -1046 975 -518 485 -1010 455 -1044 943 -554 447 -1054 449 -1010 475 -1048 943 -550 453 -1040 969 -520 973 -522 985 -514 969 -554 949 -524 459 -1040 477 -1014 483 -1034 947 -520 981 -554 447 -1016 977 -524 983 -516 973 -516 483 -1016 455 -1046 973 -484 977 -518 449 -986 447 -1016 971 -482 449 -1018 443 -1014 449 -984 1461 -129764 65 -3200 133 -464 133 -298 429 -132 265 -98 231 -134 265 -164 3439 -132 727 -132 199 -2058 133 -1644 361 -166 65 -492 165 -264 591 -428 197 -198 201 -98 831 -68 2313 -100 5839 -10922 65 -1320 425 -262 297 -428 97 -362 2463 -98 1025 -66 5263 -5030 99 -6924 461 -1092 133 -98 333 -166 2739 -132 3131 -66 10535 -2008 131 -434 297 -1058 65 -132 99 -198 529 -198 97 -526 97 -66 493 -664 99 -232 2613 -132 5371 -11166 229 -198 163 -394 199 -398 365 -132 99 -166 2121 -100 1195 -68 1821 -100 10635 -468 67 -1256 65 -2144 229 -100 163 -394 593 -98 67 -166 1677 -66 791 -66 335 -98 11033 -566 65 -1460 165 -1520 497 -1254 491 -564 99 -330 99 -232 1227 -132 2973 -66 3661 -11964 131 -132 99 -398 131 -328 97 -232 363 -396 1379 -98 99 -166 1591 -66 12171 -4136 65 -298 265 -298 199 -462 99 -330 65 -166 163 -66 1591 -66 165 -166 12079 -1002 65 -366 465 -530 97 -134 561 -66 497 -494 99 -64 131 -134 1095 -66 6537 -5066 65 -5458 397 -724 165 -466 131 -166 14293 -436 65 -1590 65 -1462 459 -332 65 -396 563 -794 197 -300 1255 -12100 99 -130 495 -166 97 -296 97 -658 757 -98 959 -66 1029 -1346 165 -2620 395 -494 197 -166 163 -198 65 -98 195 -394 821 -98 3063 -100 4469 -12120 497 -166 65 -462 195 -164 295 -66 4361 -100 1755 -100 131 -66 9415 -3840 99 -530 197 -364 463 -330 365 -332 133 -100 165 -166 2113 -100 1461 -132 4175 -3772 97 -7124 231 -1258 165 -100 429 -1326 995 -200 1755 -66 1519 -100 6437 -7198 133 -300 527 -398 165 -232 131 -166 67 -164 16443 -3270 131 -658 131 -726 97 -858 97 -300 331 -100 629 -10288 67 -164 133 -1458 297 -364 65 -98 163 -758 1189 -66 199 -68 1791 -66 897 -132 165 -3410 163 -364 99 -98 99 -66 365 -232 789 -494 65 -328 629 -66 1259 -66 365 -11422 7923 -12864 1405 -1562 +RAW_Data: 451 -1040 441 -1052 449 -1050 945 -554 449 -1052 451 -1020 481 -1010 473 -1050 449 -1052 451 -1040 969 -520 977 -520 455 -1042 977 -522 447 -1056 947 -518 979 -546 447 -1052 451 -1040 441 -1048 983 -518 455 -1044 449 -1018 979 -548 947 -554 449 -1032 481 -992 483 -1012 985 -514 999 -512 479 -1012 485 -1014 961 -544 477 -1010 965 -522 981 -512 483 -1012 487 -1020 477 -1014 479 -1016 459 -1014 471 -1012 1003 -492 997 -522 483 -1016 979 -522 985 -520 975 -512 975 -520 999 -488 985 -514 481 -1006 1001 -522 483 -990 483 -1008 483 -1020 977 -516 975 -518 999 -524 451 -1018 1009 -482 999 -506 983 -524 487 -1004 473 -980 501 -952 517 -940 497 -982 489 -974 987 -452 495 -974 487 -954 1485 -23662 1457 -1556 445 -1026 483 -1010 475 -1016 975 -518 483 -1014 487 -1034 447 -1022 977 -522 457 -1046 475 -1018 975 -524 985 -518 477 -1016 977 -524 459 -1048 969 -514 977 -522 457 -1038 479 -1018 481 -1002 1001 -520 447 -1054 449 -1008 1001 -520 977 -520 451 -1040 475 -1014 479 -1028 949 -518 983 -542 447 -1058 449 -1044 947 -552 447 -1024 977 -520 967 -542 479 -1024 451 -1040 441 -1050 451 -1028 481 -1014 483 -1010 965 -548 973 -518 485 -1010 981 -516 967 -520 983 -524 981 -514 969 -538 967 -518 481 -1016 973 -524 485 -1016 465 -1012 479 -1020 983 -532 959 -514 975 -554 949 -526 985 -512 969 -554 967 -534 461 -1042 443 -1014 967 -478 455 -1006 969 -486 967 -480 983 -486 969 -514 451 -982 1461 -23692 563 -4014 291 -1220 263 -1228 829 -620 883 -626 851 -608 903 -622 387 -1082 391 -1102 409 -1084 913 -588 941 -548 443 -1056 945 -522 445 -1046 971 -552 977 -516 441 -1048 481 -992 483 -1010 979 -554 451 -1018 481 -1014 983 -518 977 -514 479 -1040 447 -1034 485 -996 975 -520 979 -520 483 -1016 481 -1008 999 -506 471 -1050 971 -514 975 -520 473 -1000 483 -1020 481 -1008 473 -1018 481 -1020 481 -1008 967 -554 945 -518 481 -1038 967 -520 985 -520 981 -514 967 -520 985 -520 981 -508 479 -1016 1003 -518 479 -1010 479 -1010 473 -1018 975 -516 979 -520 983 -520 975 -514 977 -518 999 -520 979 -518 451 -1040 479 -986 479 -962 1007 -486 451 -986 975 -486 977 -482 483 -980 477 -982 1473 -23656 1453 -1548 447 -1016 485 -1012 491 -1012 973 -520 981 -526 983 -514 971 -554 947 -526 491 -1008 475 -1020 983 -498 989 -516 483 -1014 977 -524 453 -1044 979 -518 979 -520 453 -1042 449 -1048 447 -1022 975 -518 475 -1050 447 -1020 977 -522 983 -518 481 -1016 481 -1012 473 -1002 973 -550 945 -552 449 -1050 447 -1020 975 -522 487 -1034 973 -520 +RAW_Data: 979 -514 443 -1046 479 -1028 451 -1042 451 -1048 447 -1022 485 -1014 983 -520 973 -516 483 -1012 983 -518 973 -516 977 -520 1003 -520 975 -520 981 -514 475 -1034 969 -516 479 -1016 447 -1046 475 -1018 975 -516 975 -522 983 -510 469 -1010 1007 -518 951 -530 989 -516 973 -556 951 -494 481 -978 487 -978 975 -460 1005 -466 979 -486 969 -508 981 -450 1489 -23666 571 -4036 269 -1224 257 -1250 787 -642 867 -622 883 -622 359 -1136 373 -1086 421 -1080 417 -1074 935 -550 947 -552 445 -1048 939 -552 451 -1046 947 -552 947 -550 451 -1040 443 -1048 453 -1024 977 -522 471 -1034 449 -1020 973 -540 975 -508 479 -1032 453 -1042 449 -1050 977 -518 979 -518 449 -1018 481 -1018 975 -518 473 -1034 963 -542 961 -544 447 -1044 473 -1020 479 -1014 481 -1010 473 -1032 471 -1010 959 -546 973 -492 499 -1006 997 -510 977 -524 953 -552 971 -512 973 -508 979 -554 451 -1016 977 -518 471 -1038 485 -1010 457 -1036 969 -506 999 -520 481 -1014 975 -522 967 -520 975 -548 451 -1038 475 -1022 965 -518 463 -978 985 -486 465 -978 457 -1016 463 -978 985 -486 963 -480 1477 -129906 495 -726 197 -328 295 -132 2547 -66 233 -98 11033 -1856 233 -1458 65 -198 165 -134 199 -168 101 -694 463 -530 165 -300 99 -232 2479 -98 1745 -98 3029 -132 163 -1460 65 -500 65 -400 99 -664 895 -398 65 -564 331 -166 97 -66 197 -98 3813 -98 10097 -3848 165 -232 67 -266 397 -596 165 -66 199 -166 99 -66 199 -398 165 -166 1721 -232 429 -166 133 -330 133 -698 493 -200 197 -428 11029 -12118 65 -198 199 -68 231 -230 101 -166 99 -664 131 -132 3163 -4238 331 -298 531 -398 299 -98 199 -166 563 -100 131 -98 893 -66 3141 -1556 133 -1722 131 -830 197 -262 195 -66 163 -462 195 -396 195 -134 499 -132 265 -66 1717 -166 3175 -11366 199 -164 131 -66 163 -98 525 -98 363 -264 4495 -100 229 -66 131 -66 593 -3002 97 -394 131 -426 99 -462 597 -692 295 -298 431 -230 4231 -66 9711 -3246 131 -100 99 -400 263 -498 65 -100 297 -98 99 -132 65 -862 131 -66 365 -396 99 -166 1991 -98 1611 -132 10333 -790 65 -1984 99 -896 165 -332 365 -232 131 -830 65 -66 397 -166 197 -66 65 -496 199 -100 9975 -1728 67 -5008 727 -98 131 -100 2873 -66 12011 -3150 67 -960 99 -234 99 -298 231 -232 195 -266 165 -296 261 -166 757 -66 629 -196 657 -100 197 -134 297 -364 11237 -1684 65 -2076 165 -462 491 -100 663 -630 329 -264 263 -100 1357 -66 461 -1676 99 -1782 295 -296 65 -296 163 -230 99 -132 295 -66 163 -362 197 -724 757 -66 +RAW_Data: 3785 -66 13551 -1808 97 -730 65 -100 231 -132 131 -1230 593 -232 1579 -66 2667 -200 101 -3480 165 -692 133 -396 427 -1524 363 -66 431 -132 10305 -8288 461 -628 67 -430 725 -66 1053 -66 4501 -230 165 -66 331 -66 355 -266 263 -132 63 -562 459 -462 197 -66 129 -132 65 -100 2643 -132 2107 -66 9651 -3692 99 -100 195 -294 97 -660 759 -328 165 -560 891 -66 1953 -66 11305 -362 263 -662 131 -432 65 -134 563 -430 131 -132 1819 -100 165 -166 1061 -98 10089 -2476 65 -854 395 -198 99 -492 131 -164 229 -466 199 -428 299 -100 927 -200 1557 -134 4269 -10464 133 -1624 65 -198 265 -398 131 -430 729 -134 6189 -66 5421 -2082 165 -3342 19967 -12808 1439 -1536 453 -1046 449 -1032 449 -1056 947 -552 977 -522 977 -518 453 -1038 977 -522 977 -520 457 -1038 977 -506 1005 -496 495 -1008 975 -538 973 -530 465 -1008 975 -554 453 -1036 947 -518 487 -1008 475 -1042 443 -1050 461 -1008 1005 -510 447 -1048 985 -510 469 -1006 1005 -494 997 -514 975 -514 975 -504 999 -506 479 -1034 491 -1010 975 -508 973 -524 491 -1004 473 -1018 997 -520 975 -512 975 -518 473 -1030 983 -516 981 -514 471 -998 997 -522 481 -1012 481 -1012 457 -1050 973 -512 977 -524 459 -1016 1003 -512 479 -1014 459 -1016 475 -1012 1007 -522 969 -502 495 -1008 477 -1030 965 -522 975 -514 479 -1000 471 -1062 471 -964 483 -982 471 -1000 471 -980 979 -448 503 -988 465 -976 487 -974 1459 -23696 1407 -1616 401 -1068 429 -1080 419 -1058 935 -566 923 -584 417 -1078 939 -524 457 -1042 973 -550 443 -1028 949 -554 945 -552 447 -1022 979 -518 971 -542 479 -1024 947 -550 441 -1048 979 -518 453 -1044 449 -1050 449 -1020 485 -1014 981 -518 479 -1014 975 -524 459 -1036 973 -516 979 -518 971 -552 945 -550 945 -552 449 -1030 479 -1026 947 -554 949 -552 449 -1018 479 -1008 981 -518 975 -548 945 -554 451 -1034 967 -514 997 -514 445 -1036 967 -554 447 -1022 485 -1010 475 -1016 975 -518 977 -520 487 -1014 973 -552 451 -1040 441 -1050 447 -1022 485 -1014 987 -516 479 -1014 483 -1014 459 -1046 969 -514 449 -1044 967 -546 973 -488 447 -1016 443 -1000 973 -490 475 -980 983 -482 441 -1016 465 -976 1475 -23652 1451 -1548 479 -1014 461 -1014 471 -1044 975 -520 971 -502 495 -1012 977 -506 1005 -498 989 -516 481 -1016 975 -520 981 -514 475 -1014 979 -522 983 -512 475 -1022 965 -514 471 -1046 973 -494 473 -1016 475 -1046 447 -1050 463 -1012 999 -512 481 -1012 983 -520 477 -1014 977 -524 955 -548 973 -512 975 -520 967 -556 449 -1020 483 -1012 983 -520 973 -516 481 -1008 473 -1034 +RAW_Data: 967 -538 963 -544 973 -522 471 -1006 989 -512 1007 -520 443 -1036 985 -516 449 -1048 451 -1022 483 -1012 983 -520 977 -514 481 -1012 979 -514 483 -1022 481 -1010 471 -1020 479 -1020 979 -524 457 -1048 973 -514 483 -1012 981 -520 483 -1018 481 -1014 485 -986 467 -980 981 -486 469 -978 457 -1004 963 -480 983 -486 971 -514 1441 -23704 1383 -1628 389 -1112 385 -1092 407 -1092 915 -552 941 -570 441 -1064 423 -1046 451 -1044 939 -556 455 -1048 945 -552 973 -522 453 -1046 945 -552 947 -550 451 -1040 969 -518 479 -1028 951 -552 451 -1018 479 -1018 483 -1014 459 -1044 971 -514 483 -1010 971 -544 447 -1020 977 -524 987 -518 973 -516 979 -524 985 -518 479 -1016 447 -1050 953 -548 971 -514 483 -1014 459 -1048 967 -514 977 -526 953 -548 443 -1046 975 -492 995 -512 471 -1050 943 -552 445 -1032 455 -1044 449 -1048 941 -550 945 -552 449 -1050 945 -552 451 -1044 449 -1018 479 -1016 479 -1002 969 -542 973 -522 455 -1040 477 -1022 967 -534 959 -514 975 -554 469 -1008 449 -980 469 -1008 943 -484 1001 -484 467 -980 983 -482 961 -514 1439 -23700 1469 -1510 495 -1008 473 -1036 463 -1012 969 -546 973 -522 473 -1018 479 -1014 975 -526 955 -516 475 -1046 975 -490 999 -518 481 -1014 975 -520 967 -514 481 -1022 979 -524 457 -1048 971 -514 481 -1010 485 -1020 477 -1014 479 -1000 1001 -522 451 -1020 977 -520 473 -1032 967 -538 959 -514 1005 -522 965 -504 989 -514 475 -1046 441 -1050 971 -514 975 -520 473 -1018 481 -1014 979 -520 983 -520 977 -516 485 -1010 979 -544 975 -518 453 -1042 981 -520 453 -1024 483 -1010 457 -1050 975 -512 975 -524 459 -1048 973 -514 481 -1010 473 -1016 479 -1016 477 -1036 967 -506 995 -512 965 -546 445 -1048 957 -516 1005 -512 445 -1046 979 -486 473 -980 979 -486 473 -980 981 -486 473 -980 485 -986 467 -976 1477 -142204 197 -1486 165 -198 165 -664 295 -232 99 -266 231 -166 3045 -100 13411 -3670 197 -498 131 -166 231 -198 165 -66 265 -134 129 -1062 431 -130 465 -134 13447 -3848 329 -100 163 -298 99 -164 463 -98 197 -98 131 -198 65 -296 493 -264 789 -66 7225 -12438 99 -164 463 -132 197 -630 65 -198 2487 -66 165 -100 10097 -6554 459 -664 297 -460 4925 -132 6063 -12078 497 -98 99 -200 97 -234 165 -298 1721 -134 265 -100 3035 -100 12081 -3674 231 -100 97 -200 97 -264 461 -100 99 -132 231 -100 97 -430 527 -200 231 -64 2081 -132 327 -100 529 -66 831 -66 3067 -4704 99 -5520 97 -496 67 -198 167 -498 693 -462 2341 -15926 65 -1392 659 -134 131 -298 165 -66 99 -298 4777 -4208 429 -66 diff --git a/documentation/UniversalRemotes.md b/documentation/UniversalRemotes.md new file mode 100644 index 000000000..325f640d7 --- /dev/null +++ b/documentation/UniversalRemotes.md @@ -0,0 +1,76 @@ +# Universal Remotes + +## Televisions + +Adding your TV set to the universal remote is quite straightforward. Up to 6 signals can be recorded: `Power`, `Mute`, `Vol_up`, `Vol_dn`, `Ch_next`, and `Ch_prev`. Any of them can be omitted if not supported by your TV. + +Each signal is recorded using the following algorithm: + +1. Get the remote and point it to Flipper's IR receiver. +2. Start learning a new remote if it's the first button or press `+` to add a new button otherwise. +3. Press a remote button and save it under a corresponding name. +4. Repeat steps 2-3 until all required signals are saved. + +The signal names are self-explanatory. Remember to make sure that every recorded signal does what it's supposed to. + +If everything checks out, append these signals **to the end** of the [TV universal remote file](/assets/resources/infrared/assets/tv.ir). + +## Audio players + +Adding your audio player to the universal remote is done in the same manner as described above. Up to 8 signals can be recorded: `Power`, `Play`, `Pause`, `Vol_up`, `Vol_dn`, `Next`, `Prev`, and `Mute`. Any of them can be omitted if not supported by the player. + +The signal names are self-explanatory. +On many remotes, the `Play` button doubles as `Pause`. In this case, record it as `Play` omitting the `Pause`. +Make sure that every signal does what it's supposed to. + +If everything checks out, append these signals **to the end** of the [audio player universal remote file](/assets/resources/infrared/assets/audio.ir). + +## Projectors + +Adding your projector to the universal remote is really simple. Up to 4 signals can be recorded: `Power`, `Mute`, `Vol_up`, `Vol_dn`. Any of them can be omitted if not supported by your projector. +To save time, please make sure every recording has been named accordingly. +In case of omitting, on most projectors with the 4 following buttons, you should not have a problem. + + +## Air conditioners + +Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote. +The majority of A/C remotes have a small display that shows the current mode, temperature, and other settings. +When the user presses a button, a whole set of parameters is transmitted to the device, which must be recorded and used as a whole. + +In order to add a particular air conditioner to the universal remote, 6 signals must be recorded: `Off`, `Dh`, `Cool_hi`, `Cool_lo`, `Heat_hi`, and `Heat_lo`. +Each signal (except `Off`) is recorded using the following algorithm: + +1. Get the remote and press the **Power Button** so that the display shows that A/C is ON. +2. Set the A/C to the corresponding mode (see table below), leaving other parameters such as fan speed or vane on **AUTO** (if applicable). +3. Press the **POWER** button to switch the A/C off. +4. Start learning a new remote on Flipper if it's the first button or press `+` to add a new button otherwise. +5. Point the remote to Flipper's IR receiver as directed and press **POWER** button once again. +6. Save the resulting signal under the specified name. +7. Repeat steps 2-6 for each signal from the table below. + +| Signal | Mode | Temperature | Note | +| :-----: | :--------: | :---------: | ----------------------------------- | +| Dh | Dehumidify | N/A | | +| Cool_hi | Cooling | See note | Lowest temperature in cooling mode | +| Cool_lo | Cooling | 23°C | | +| Heat_hi | Heating | See note | Highest temperature in heating mode | +| Heat_lo | Heating | 23°C | | + +Finally, record the `Off` signal: + +1. Make sure the display shows that the A/C is ON. +2. Start learning a new signal on Flipper and point the remote towards the IR receiver. +3. Press the **POWER** button so that the remote shows the OFF state. +4. Save the resulting signal under the name `Off`. + +The resulting remote file should now contain 6 signals. You can omit any of them, but you then won't be able to use their functionality. +Test the file against the actual device. Make sure that every signal does what it's supposed to. + +If everything checks out, append these signals **to the end** of the [A/C universal remote file](/assets/resources/infrared/assets/ac.ir). + +## Final steps + +The order of signals is not important, but they should be preceded by the following comment: `# Model: ` in order to keep the library organized. + +When done, open a pull request containing the changed file. diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3d88c7cc1..3a687f32e 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.8,, +Version,+,14.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1348,8 +1348,7 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" -Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, @@ -2651,12 +2650,14 @@ Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_free,void,SubGhzEnvironment* +Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment* Function,+,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment* Function,+,subghz_environment_get_protocol_name_registry,const char*,"SubGhzEnvironment*, size_t" Function,+,subghz_environment_get_protocol_registry,void*,SubGhzEnvironment* Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*" +Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, void*" @@ -2679,7 +2680,7 @@ Function,+,subghz_protocol_blocks_crc8le,uint8_t,"const uint8_t[], size_t, uint8 Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t" Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t" Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t" -Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t" +Function,+,subghz_protocol_blocks_get_upload_from_bit_array,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t, SubGhzProtocolBlockAlignBit" Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], size_t, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t" @@ -2688,6 +2689,14 @@ Function,+,subghz_protocol_blocks_parity_bytes,uint8_t,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t" Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t" Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t" +Function,+,subghz_protocol_decoder_alutech_at_4n_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_alutech_at_4n_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_alutech_at_4n_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_alutech_at_4n_free,void,void* +Function,+,subghz_protocol_decoder_alutech_at_4n_get_hash_data,uint8_t,void* +Function,+,subghz_protocol_decoder_alutech_at_4n_get_string,void,"void*, FuriString*" +Function,+,subghz_protocol_decoder_alutech_at_4n_reset,void,void* +Function,+,subghz_protocol_decoder_alutech_at_4n_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_ansonic_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_ansonic_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_ansonic_feed,void,"void*, _Bool, uint32_t" @@ -2757,6 +2766,14 @@ Function,-,subghz_protocol_decoder_doitrand_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_doitrand_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_doitrand_reset,void,void* Function,-,subghz_protocol_decoder_doitrand_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_protocol_decoder_dooya_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_dooya_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_dooya_free,void,void* +Function,+,subghz_protocol_decoder_dooya_get_hash_data,uint8_t,void* +Function,+,subghz_protocol_decoder_dooya_get_string,void,"void*, FuriString*" +Function,+,subghz_protocol_decoder_dooya_reset,void,void* +Function,+,subghz_protocol_decoder_dooya_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_faac_slh_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_faac_slh_feed,void,"void*, _Bool, uint32_t" @@ -2837,7 +2854,23 @@ Function,-,subghz_protocol_decoder_kia_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_kia_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_kia_reset,void,void* Function,-,subghz_protocol_decoder_kia_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_free,void,void* +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data,uint8_t,void* +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_get_string,void,"void*, FuriString*" +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_reset,void,void* +Function,+,subghz_protocol_decoder_kinggates_stylo_4k_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_linear_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_linear_delta3_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_linear_delta3_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_linear_delta3_free,void,void* +Function,+,subghz_protocol_decoder_linear_delta3_get_hash_data,uint8_t,void* +Function,+,subghz_protocol_decoder_linear_delta3_get_string,void,"void*, FuriString*" +Function,+,subghz_protocol_decoder_linear_delta3_reset,void,void* +Function,+,subghz_protocol_decoder_linear_delta3_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_linear_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_linear_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_linear_free,void,void* @@ -3032,6 +3065,11 @@ Function,-,subghz_protocol_encoder_doitrand_deserialize,_Bool,"void*, FlipperFor Function,-,subghz_protocol_encoder_doitrand_free,void,void* Function,-,subghz_protocol_encoder_doitrand_stop,void,void* Function,-,subghz_protocol_encoder_doitrand_yield,LevelDuration,void* +Function,+,subghz_protocol_encoder_dooya_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_dooya_free,void,void* +Function,+,subghz_protocol_encoder_dooya_stop,void,void* +Function,+,subghz_protocol_encoder_dooya_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_faac_slh_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_faac_slh_free,void,void* @@ -3074,6 +3112,11 @@ Function,-,subghz_protocol_encoder_keeloq_free,void,void* Function,-,subghz_protocol_encoder_keeloq_stop,void,void* Function,-,subghz_protocol_encoder_keeloq_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_linear_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_linear_delta3_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_linear_delta3_free,void,void* +Function,+,subghz_protocol_encoder_linear_delta3_stop,void,void* +Function,+,subghz_protocol_encoder_linear_delta3_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_linear_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_linear_free,void,void* Function,-,subghz_protocol_encoder_linear_stop,void,void* @@ -3148,6 +3191,16 @@ Function,-,subghz_protocol_encoder_smc5326_deserialize,_Bool,"void*, FlipperForm Function,-,subghz_protocol_encoder_smc5326_free,void,void* Function,-,subghz_protocol_encoder_smc5326_stop,void,void* Function,-,subghz_protocol_encoder_smc5326_yield,LevelDuration,void* +Function,+,subghz_protocol_encoder_somfy_keytis_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_somfy_keytis_free,void,void* +Function,+,subghz_protocol_encoder_somfy_keytis_stop,void,void* +Function,+,subghz_protocol_encoder_somfy_keytis_yield,LevelDuration,void* +Function,+,subghz_protocol_encoder_somfy_telis_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_somfy_telis_free,void,void* +Function,+,subghz_protocol_encoder_somfy_telis_stop,void,void* +Function,+,subghz_protocol_encoder_somfy_telis_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_star_line_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_star_line_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_star_line_free,void,void* @@ -3169,6 +3222,8 @@ Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const Su Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*" Function,-,subghz_protocol_secplus_v1_check_fixed,_Bool,uint32_t Function,-,subghz_protocol_secplus_v2_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzRadioPreset*" +Function,+,subghz_protocol_somfy_keytis_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" +Function,+,subghz_protocol_somfy_telis_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" Function,-,subghz_protocol_star_line_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzRadioPreset*" Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" @@ -4879,6 +4934,9 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence, +Variable,+,subghz_protocol_alutech_at_4n,const SubGhzProtocol, +Variable,+,subghz_protocol_alutech_at_4n_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_alutech_at_4n_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_ansonic,const SubGhzProtocol, Variable,-,subghz_protocol_ansonic_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_ansonic_encoder,const SubGhzProtocolEncoder, @@ -4903,6 +4961,9 @@ Variable,-,subghz_protocol_clemsa_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_doitrand,const SubGhzProtocol, Variable,-,subghz_protocol_doitrand_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_doitrand_encoder,const SubGhzProtocolEncoder, +Variable,+,subghz_protocol_dooya,const SubGhzProtocol, +Variable,+,subghz_protocol_dooya_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_dooya_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_faac_slh,const SubGhzProtocol, Variable,-,subghz_protocol_faac_slh_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_faac_slh_encoder,const SubGhzProtocolEncoder, @@ -4933,8 +4994,14 @@ Variable,-,subghz_protocol_keeloq_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_kia,const SubGhzProtocol, Variable,-,subghz_protocol_kia_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_kia_encoder,const SubGhzProtocolEncoder, +Variable,+,subghz_protocol_kinggates_stylo_4k,const SubGhzProtocol, +Variable,+,subghz_protocol_kinggates_stylo_4k_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_kinggates_stylo_4k_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_linear,const SubGhzProtocol, Variable,-,subghz_protocol_linear_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_linear_delta3,const SubGhzProtocol, +Variable,+,subghz_protocol_linear_delta3_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_linear_delta3_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_linear_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_magellan,const SubGhzProtocol, Variable,-,subghz_protocol_magellan_decoder,const SubGhzProtocolDecoder, diff --git a/firmware/targets/f7/fatfs/sd_spi_io.c b/firmware/targets/f7/fatfs/sd_spi_io.c new file mode 100644 index 000000000..93b837e85 --- /dev/null +++ b/firmware/targets/f7/fatfs/sd_spi_io.c @@ -0,0 +1,877 @@ +#include "sd_spi_io.h" +#include "sector_cache.h" +#include +#include +#include + +// #define SD_SPI_DEBUG 1 +#define TAG "SdSpi" + +#ifdef SD_SPI_DEBUG +#define sd_spi_debug(...) FURI_LOG_I(TAG, __VA_ARGS__) +#else +#define sd_spi_debug(...) +#endif + +#define SD_CMD_LENGTH 6 +#define SD_DUMMY_BYTE 0xFF +#define SD_ANSWER_RETRY_COUNT 8 +#define SD_IDLE_RETRY_COUNT 100 +#define SD_BLOCK_SIZE 512 + +#define FLAG_SET(x, y) (((x) & (y)) == (y)) + +static bool sd_high_capacity = false; + +typedef enum { + SdSpiDataResponceOK = 0x05, + SdSpiDataResponceCRCError = 0x0B, + SdSpiDataResponceWriteError = 0x0D, + SdSpiDataResponceOtherError = 0xFF, +} SdSpiDataResponce; + +typedef struct { + uint8_t r1; + uint8_t r2; + uint8_t r3; + uint8_t r4; + uint8_t r5; +} SdSpiCmdAnswer; + +typedef enum { + SdSpiCmdAnswerTypeR1, + SdSpiCmdAnswerTypeR1B, + SdSpiCmdAnswerTypeR2, + SdSpiCmdAnswerTypeR3, + SdSpiCmdAnswerTypeR4R5, + SdSpiCmdAnswerTypeR7, +} SdSpiCmdAnswerType; + +/* + SdSpiCmd and SdSpiToken use non-standard enum value names convention, + because it is more convenient to look for documentation on a specific command. + For example, to find out what the SD_CMD23_SET_BLOCK_COUNT command does, you need to look for + SET_BLOCK_COUNT or CMD23 in the "Part 1 Physical Layer Simplified Specification". + + Do not use that naming convention in other places. +*/ + +typedef enum { + SD_CMD0_GO_IDLE_STATE = 0, + SD_CMD1_SEND_OP_COND = 1, + SD_CMD8_SEND_IF_COND = 8, + SD_CMD9_SEND_CSD = 9, + SD_CMD10_SEND_CID = 10, + SD_CMD12_STOP_TRANSMISSION = 12, + SD_CMD13_SEND_STATUS = 13, + SD_CMD16_SET_BLOCKLEN = 16, + SD_CMD17_READ_SINGLE_BLOCK = 17, + SD_CMD18_READ_MULT_BLOCK = 18, + SD_CMD23_SET_BLOCK_COUNT = 23, + SD_CMD24_WRITE_SINGLE_BLOCK = 24, + SD_CMD25_WRITE_MULT_BLOCK = 25, + SD_CMD27_PROG_CSD = 27, + SD_CMD28_SET_WRITE_PROT = 28, + SD_CMD29_CLR_WRITE_PROT = 29, + SD_CMD30_SEND_WRITE_PROT = 30, + SD_CMD32_SD_ERASE_GRP_START = 32, + SD_CMD33_SD_ERASE_GRP_END = 33, + SD_CMD34_UNTAG_SECTOR = 34, + SD_CMD35_ERASE_GRP_START = 35, + SD_CMD36_ERASE_GRP_END = 36, + SD_CMD37_UNTAG_ERASE_GROUP = 37, + SD_CMD38_ERASE = 38, + SD_CMD41_SD_APP_OP_COND = 41, + SD_CMD55_APP_CMD = 55, + SD_CMD58_READ_OCR = 58, +} SdSpiCmd; + +/** Data tokens */ +typedef enum { + SD_TOKEN_START_DATA_SINGLE_BLOCK_READ = 0xFE, + SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ = 0xFE, + SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE = 0xFE, + SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE = 0xFC, + SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE = 0xFD, +} SdSpiToken; + +/** R1 answer value */ +typedef enum { + SdSpi_R1_NO_ERROR = 0x00, + SdSpi_R1_IN_IDLE_STATE = 0x01, + SdSpi_R1_ERASE_RESET = 0x02, + SdSpi_R1_ILLEGAL_COMMAND = 0x04, + SdSpi_R1_COM_CRC_ERROR = 0x08, + SdSpi_R1_ERASE_SEQUENCE_ERROR = 0x10, + SdSpi_R1_ADDRESS_ERROR = 0x20, + SdSpi_R1_PARAMETER_ERROR = 0x40, +} SdSpiR1; + +/** R2 answer value */ +typedef enum { + /* R2 answer value */ + SdSpi_R2_NO_ERROR = 0x00, + SdSpi_R2_CARD_LOCKED = 0x01, + SdSpi_R2_LOCKUNLOCK_ERROR = 0x02, + SdSpi_R2_ERROR = 0x04, + SdSpi_R2_CC_ERROR = 0x08, + SdSpi_R2_CARD_ECC_FAILED = 0x10, + SdSpi_R2_WP_VIOLATION = 0x20, + SdSpi_R2_ERASE_PARAM = 0x40, + SdSpi_R2_OUTOFRANGE = 0x80, +} SdSpiR2; + +static inline void sd_spi_select_card() { + furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false); + furi_delay_us(10); // Entry guard time for some SD cards +} + +static inline void sd_spi_deselect_card() { + furi_delay_us(10); // Exit guard time for some SD cards + furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true); +} + +static void sd_spi_bus_to_ground() { + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->miso, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->mosi, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->sck, + GpioModeOutputPushPull, + GpioPullNo, + GpioSpeedVeryHigh, + GpioAltFnUnused); + + sd_spi_select_card(); + furi_hal_gpio_write(furi_hal_sd_spi_handle->miso, false); + furi_hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); + furi_hal_gpio_write(furi_hal_sd_spi_handle->sck, false); +} + +static void sd_spi_bus_rise_up() { + sd_spi_deselect_card(); + + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->miso, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->mosi, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); + furi_hal_gpio_init_ex( + furi_hal_sd_spi_handle->sck, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn5SPI2); +} + +static inline uint8_t sd_spi_read_byte(void) { + uint8_t responce; + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, &responce, 1, SD_TIMEOUT_MS)); + return responce; +} + +static inline void sd_spi_write_byte(uint8_t data) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, NULL, 1, SD_TIMEOUT_MS)); +} + +static inline uint8_t sd_spi_write_and_read_byte(uint8_t data) { + uint8_t responce; + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, &responce, 1, SD_TIMEOUT_MS)); + return responce; +} + +static inline void sd_spi_write_bytes(uint8_t* data, uint32_t size) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS)); +} + +static inline void sd_spi_read_bytes(uint8_t* data, uint32_t size) { + furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS)); +} + +static inline void sd_spi_write_bytes_dma(uint8_t* data, uint32_t size) { + uint32_t timeout_mul = (size / 512) + 1; + furi_check(furi_hal_spi_bus_trx_dma( + furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS * timeout_mul)); +} + +static inline void sd_spi_read_bytes_dma(uint8_t* data, uint32_t size) { + uint32_t timeout_mul = (size / 512) + 1; + furi_check(furi_hal_spi_bus_trx_dma( + furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS * timeout_mul)); +} + +static uint8_t sd_spi_wait_for_data_and_read(void) { + uint8_t retry_count = SD_ANSWER_RETRY_COUNT; + uint8_t responce; + + // Wait until we get a valid data + do { + responce = sd_spi_read_byte(); + retry_count--; + + } while((responce == SD_DUMMY_BYTE) && retry_count); + + return responce; +} + +static SdSpiStatus sd_spi_wait_for_data(uint8_t data, uint32_t timeout_ms) { + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_ms * 1000); + uint8_t byte; + + do { + byte = sd_spi_read_byte(); + if(furi_hal_cortex_timer_is_expired(timer)) { + return SdSpiStatusTimeout; + } + } while((byte != data)); + + return SdSpiStatusOK; +} + +static inline void sd_spi_deselect_card_and_purge() { + sd_spi_deselect_card(); + sd_spi_read_byte(); +} + +static inline void sd_spi_purge_crc() { + sd_spi_read_byte(); + sd_spi_read_byte(); +} + +static SdSpiCmdAnswer + sd_spi_send_cmd(SdSpiCmd cmd, uint32_t arg, uint8_t crc, SdSpiCmdAnswerType answer_type) { + uint8_t frame[SD_CMD_LENGTH]; + SdSpiCmdAnswer cmd_answer = { + .r1 = SD_DUMMY_BYTE, + .r2 = SD_DUMMY_BYTE, + .r3 = SD_DUMMY_BYTE, + .r4 = SD_DUMMY_BYTE, + .r5 = SD_DUMMY_BYTE, + }; + + // R1 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 1 Bytes answer + NEC(0) = 15bytes + // R1b identical to R1 + Busy information + // R2 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 2 Bytes answer + NEC(0) = 16bytes + + frame[0] = ((uint8_t)cmd | 0x40); + frame[1] = (uint8_t)(arg >> 24); + frame[2] = (uint8_t)(arg >> 16); + frame[3] = (uint8_t)(arg >> 8); + frame[4] = (uint8_t)(arg); + frame[5] = (crc | 0x01); + + sd_spi_select_card(); + sd_spi_write_bytes(frame, sizeof(frame)); + + switch(answer_type) { + case SdSpiCmdAnswerTypeR1: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + break; + case SdSpiCmdAnswerTypeR1B: + // TODO: can be wrong, at least for SD_CMD12_STOP_TRANSMISSION you need to purge one byte before reading R1 + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + + // In general this shenenigans seems suspicious, please double check SD specs if you are using SdSpiCmdAnswerTypeR1B + // reassert card + sd_spi_deselect_card(); + furi_delay_us(1000); + sd_spi_deselect_card(); + + // and wait for it to be ready + while(sd_spi_read_byte() != 0xFF) { + }; + + break; + case SdSpiCmdAnswerTypeR2: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + cmd_answer.r2 = sd_spi_read_byte(); + break; + case SdSpiCmdAnswerTypeR3: + case SdSpiCmdAnswerTypeR7: + cmd_answer.r1 = sd_spi_wait_for_data_and_read(); + cmd_answer.r2 = sd_spi_read_byte(); + cmd_answer.r3 = sd_spi_read_byte(); + cmd_answer.r4 = sd_spi_read_byte(); + cmd_answer.r5 = sd_spi_read_byte(); + break; + default: + break; + } + return cmd_answer; +} + +static SdSpiDataResponce sd_spi_get_data_response(uint32_t timeout_ms) { + SdSpiDataResponce responce = sd_spi_read_byte(); + // read busy response byte + sd_spi_read_byte(); + + switch(responce & 0x1F) { + case SdSpiDataResponceOK: + // TODO: check timings + sd_spi_deselect_card(); + sd_spi_select_card(); + + // wait for 0xFF + if(sd_spi_wait_for_data(0xFF, timeout_ms) == SdSpiStatusOK) { + return SdSpiDataResponceOK; + } else { + return SdSpiDataResponceOtherError; + } + case SdSpiDataResponceCRCError: + return SdSpiDataResponceCRCError; + case SdSpiDataResponceWriteError: + return SdSpiDataResponceWriteError; + default: + return SdSpiDataResponceOtherError; + } +} + +static SdSpiStatus sd_spi_init_spi_mode_v1(void) { + SdSpiCmdAnswer response; + uint8_t retry_count = 0; + + sd_spi_debug("Init SD card in SPI mode v1"); + + do { + retry_count++; + + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + + sd_spi_debug("Init SD card in SPI mode v1 done"); + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_init_spi_mode_v2(void) { + SdSpiCmdAnswer response; + uint8_t retry_count = 0; + + sd_spi_debug("Init SD card in SPI mode v2"); + + do { + retry_count++; + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + // ACMD41 (APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = + sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0x40000000, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("ACMD41 failed"); + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + + if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) { + sd_spi_debug("ACMD41 is illegal command"); + retry_count = 0; + do { + retry_count++; + // CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_IN_IDLE_STATE) { + sd_spi_debug("CMD55 failed"); + return SdSpiStatusError; + } + // ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) + response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("ACMD41 failed"); + return SdSpiStatusError; + } + } while(response.r1 == SdSpi_R1_IN_IDLE_STATE); + } + + sd_spi_debug("Init SD card in SPI mode v2 done"); + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_init_spi_mode(void) { + SdSpiCmdAnswer response; + uint8_t retry_count; + + // CMD0 (GO_IDLE_STATE) to put SD in SPI mode and + // wait for In Idle State Response (R1 Format) equal to 0x01 + retry_count = 0; + do { + retry_count++; + response = sd_spi_send_cmd(SD_CMD0_GO_IDLE_STATE, 0, 0x95, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(retry_count >= SD_IDLE_RETRY_COUNT) { + sd_spi_debug("CMD0 failed"); + return SdSpiStatusError; + } + } while(response.r1 != SdSpi_R1_IN_IDLE_STATE); + + // CMD8 (SEND_IF_COND) to check the power supply status + // and wait until response (R7 Format) equal to 0xAA and + response = sd_spi_send_cmd(SD_CMD8_SEND_IF_COND, 0x1AA, 0x87, SdSpiCmdAnswerTypeR7); + sd_spi_deselect_card_and_purge(); + + if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) { + if(sd_spi_init_spi_mode_v1() != SdSpiStatusOK) { + sd_spi_debug("Init mode v1 failed"); + return SdSpiStatusError; + } + sd_high_capacity = 0; + } else if(response.r1 == SdSpi_R1_IN_IDLE_STATE) { + if(sd_spi_init_spi_mode_v2() != SdSpiStatusOK) { + sd_spi_debug("Init mode v2 failed"); + return SdSpiStatusError; + } + + // CMD58 (READ_OCR) to initialize SDHC or SDXC cards: R3 response + response = sd_spi_send_cmd(SD_CMD58_READ_OCR, 0, 0xFF, SdSpiCmdAnswerTypeR3); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_debug("CMD58 failed"); + return SdSpiStatusError; + } + sd_high_capacity = (response.r2 & 0x40) >> 6; + } else { + return SdSpiStatusError; + } + + sd_spi_debug("SD card is %s", sd_high_capacity ? "SDHC or SDXC" : "SDSC"); + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_get_csd(SD_CSD* csd) { + uint16_t counter = 0; + uint8_t csd_data[16]; + SdSpiStatus ret = SdSpiStatusError; + SdSpiCmdAnswer response; + + // CMD9 (SEND_CSD): R1 format (0x00 is no errors) + response = sd_spi_send_cmd(SD_CMD9_SEND_CSD, 0, 0xFF, SdSpiCmdAnswerTypeR1); + + if(response.r1 == SdSpi_R1_NO_ERROR) { + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + // read CSD data + for(counter = 0; counter < 16; counter++) { + csd_data[counter] = sd_spi_read_byte(); + } + + sd_spi_purge_crc(); + + /************************************************************************* + CSD header decoding + *************************************************************************/ + + csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; + csd->Reserved1 = csd_data[0] & 0x3F; + csd->TAAC = csd_data[1]; + csd->NSAC = csd_data[2]; + csd->MaxBusClkFrec = csd_data[3]; + csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); + csd->RdBlockLen = csd_data[5] & 0x0F; + csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; + csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; + csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; + csd->DSRImpl = (csd_data[6] & 0x10) >> 4; + + /************************************************************************* + CSD v1/v2 decoding + *************************************************************************/ + + if(sd_high_capacity == 0) { + csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); + csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | + ((csd_data[8] & 0xC0) >> 6); + csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; + csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); + csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; + csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; + csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | + ((csd_data[10] & 0x80) >> 7); + } else { + csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | + ((csd_data[7] & 0xC0) >> 6); + csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | + csd_data[9]; + csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); + } + + csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; + csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); + csd->WrProtectGrSize = (csd_data[11] & 0x7F); + csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; + csd->Reserved2 = (csd_data[12] & 0x60) >> 5; + csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; + csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); + csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; + csd->Reserved3 = (csd_data[13] & 0x1F); + csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; + csd->CopyFlag = (csd_data[14] & 0x40) >> 6; + csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; + csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; + csd->FileFormat = (csd_data[14] & 0x0C) >> 2; + csd->Reserved4 = (csd_data[14] & 0x03); + csd->crc = (csd_data[15] & 0xFE) >> 1; + csd->Reserved5 = (csd_data[15] & 0x01); + + ret = SdSpiStatusOK; + } + } + + sd_spi_deselect_card_and_purge(); + + return ret; +} + +static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) { + uint16_t counter = 0; + uint8_t cid_data[16]; + SdSpiStatus ret = SdSpiStatusError; + SdSpiCmdAnswer response; + + // CMD10 (SEND_CID): R1 format (0x00 is no errors) + response = sd_spi_send_cmd(SD_CMD10_SEND_CID, 0, 0xFF, SdSpiCmdAnswerTypeR1); + + if(response.r1 == SdSpi_R1_NO_ERROR) { + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) == + SdSpiStatusOK) { + // read CID data + for(counter = 0; counter < 16; counter++) { + cid_data[counter] = sd_spi_read_byte(); + } + + sd_spi_purge_crc(); + + Cid->ManufacturerID = cid_data[0]; + memcpy(Cid->OEM_AppliID, cid_data + 1, 2); + memcpy(Cid->ProdName, cid_data + 3, 5); + Cid->ProdRev = cid_data[8]; + Cid->ProdSN = cid_data[9] << 24; + Cid->ProdSN |= cid_data[10] << 16; + Cid->ProdSN |= cid_data[11] << 8; + Cid->ProdSN |= cid_data[12]; + Cid->Reserved1 = (cid_data[13] & 0xF0) >> 4; + Cid->ManufactYear = (cid_data[13] & 0x0F) << 4; + Cid->CID_CRC = (cid_data[15] & 0xFE) >> 1; + Cid->Reserved2 = 1; + + ret = SdSpiStatusOK; + } + } + + sd_spi_deselect_card_and_purge(); + + return ret; +} + +static inline bool sd_cache_get(uint32_t address, uint32_t* data) { + uint8_t* cached_data = sector_cache_get(address); + if(cached_data) { + memcpy(data, cached_data, SD_BLOCK_SIZE); + return true; + } + return false; +} + +static inline void sd_cache_put(uint32_t address, uint32_t* data) { + sector_cache_put(address, (uint8_t*)data); +} + +static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) { + sector_cache_invalidate_range(start_sector, end_sector); +} + +static SdSpiStatus + sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + uint32_t block_address = address; + uint32_t offset = 0; + + // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors) + SdSpiCmdAnswer response = + sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + return SdSpiStatusError; + } + + if(!sd_high_capacity) { + block_address = address * SD_BLOCK_SIZE; + } + + while(blocks--) { + // CMD17 (READ_SINGLE_BLOCK): R1 response (0x00: no errors) + response = + sd_spi_send_cmd(SD_CMD17_READ_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1); + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + // Wait for the data start token + if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, timeout_ms) == + SdSpiStatusOK) { + // Read the data block + sd_spi_read_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE); + sd_spi_purge_crc(); + + // increase offset + offset += SD_BLOCK_SIZE; + + // increase block address + if(sd_high_capacity) { + block_address += 1; + } else { + block_address += SD_BLOCK_SIZE; + } + } else { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + sd_spi_deselect_card_and_purge(); + } + + return SdSpiStatusOK; +} + +static SdSpiStatus sd_spi_cmd_write_blocks( + uint32_t* data, + uint32_t address, + uint32_t blocks, + uint32_t timeout_ms) { + uint32_t block_address = address; + uint32_t offset = 0; + + // CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors) + SdSpiCmdAnswer response = + sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1); + sd_spi_deselect_card_and_purge(); + + if(response.r1 != SdSpi_R1_NO_ERROR) { + return SdSpiStatusError; + } + + if(!sd_high_capacity) { + block_address = address * SD_BLOCK_SIZE; + } + + while(blocks--) { + // CMD24 (WRITE_SINGLE_BLOCK): R1 response (0x00: no errors) + response = sd_spi_send_cmd( + SD_CMD24_WRITE_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1); + if(response.r1 != SdSpi_R1_NO_ERROR) { + sd_spi_deselect_card_and_purge(); + return SdSpiStatusError; + } + + // Send dummy byte for NWR timing : one byte between CMD_WRITE and TOKEN + // TODO: check bytes count + sd_spi_write_byte(SD_DUMMY_BYTE); + sd_spi_write_byte(SD_DUMMY_BYTE); + + // Send the data start token + sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE); + sd_spi_write_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE); + sd_spi_purge_crc(); + + // Read data response + SdSpiDataResponce data_responce = sd_spi_get_data_response(timeout_ms); + sd_spi_deselect_card_and_purge(); + + if(data_responce != SdSpiDataResponceOK) { + return SdSpiStatusError; + } + + // increase offset + offset += SD_BLOCK_SIZE; + + // increase block address + if(sd_high_capacity) { + block_address += 1; + } else { + block_address += SD_BLOCK_SIZE; + } + } + + return SdSpiStatusOK; +} + +uint8_t sd_max_mount_retry_count() { + return 10; +} + +SdSpiStatus sd_init(bool power_reset) { + // Slow speed init + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); + furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; + + // We reset card in spi_lock context, so it is safe to disturb spi bus + if(power_reset) { + sd_spi_debug("Power reset"); + + // disable power and set low on all bus pins + furi_hal_power_disable_external_3_3v(); + sd_spi_bus_to_ground(); + hal_sd_detect_set_low(); + furi_delay_ms(250); + + // reinit bus and enable power + sd_spi_bus_rise_up(); + hal_sd_detect_init(); + furi_hal_power_enable_external_3_3v(); + furi_delay_ms(100); + } + + SdSpiStatus status = SdSpiStatusError; + + // Send 80 dummy clocks with CS high + sd_spi_deselect_card(); + for(uint8_t i = 0; i < 80; i++) { + sd_spi_write_byte(SD_DUMMY_BYTE); + } + + for(uint8_t i = 0; i < 128; i++) { + status = sd_spi_init_spi_mode(); + if(status == SdSpiStatusOK) { + // SD initialized and init to SPI mode properly + sd_spi_debug("SD init OK after %d retries", i); + break; + } + } + + furi_hal_sd_spi_handle = NULL; + furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); + + // Init sector cache + sector_cache_init(); + + return status; +} + +SdSpiStatus sd_get_card_state(void) { + SdSpiCmdAnswer response; + + // Send CMD13 (SEND_STATUS) to get SD status + response = sd_spi_send_cmd(SD_CMD13_SEND_STATUS, 0, 0xFF, SdSpiCmdAnswerTypeR2); + sd_spi_deselect_card_and_purge(); + + // Return status OK if response is valid + if((response.r1 == SdSpi_R1_NO_ERROR) && (response.r2 == SdSpi_R2_NO_ERROR)) { + return SdSpiStatusOK; + } + + return SdSpiStatusError; +} + +SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) { + SdSpiStatus status; + + status = sd_spi_get_csd(&(card_info->Csd)); + + if(status != SdSpiStatusOK) { + return status; + } + + status = sd_spi_get_cid(&(card_info->Cid)); + + if(status != SdSpiStatusOK) { + return status; + } + + if(sd_high_capacity == 1) { + card_info->LogBlockSize = 512; + card_info->CardBlockSize = 512; + card_info->CardCapacity = ((uint64_t)card_info->Csd.version.v2.DeviceSize + 1UL) * 1024UL * + (uint64_t)card_info->LogBlockSize; + card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize); + } else { + card_info->CardCapacity = (card_info->Csd.version.v1.DeviceSize + 1); + card_info->CardCapacity *= (1UL << (card_info->Csd.version.v1.DeviceSizeMul + 2)); + card_info->LogBlockSize = 512; + card_info->CardBlockSize = 1UL << (card_info->Csd.RdBlockLen); + card_info->CardCapacity *= card_info->CardBlockSize; + card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize); + } + + return status; +} + +SdSpiStatus + sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + SdSpiStatus status = SdSpiStatusError; + + bool single_sector_read = (blocks == 1); + + if(single_sector_read) { + if(sd_cache_get(address, data)) { + return SdSpiStatusOK; + } + + status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms); + + if(status == SdSpiStatusOK) { + sd_cache_put(address, data); + } + } else { + status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms); + } + + return status; +} + +SdSpiStatus + sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) { + sd_cache_invalidate_range(address, address + blocks); + SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms); + return status; +} + +SdSpiStatus sd_get_cid(SD_CID* cid) { + SdSpiStatus status; + + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); + furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; + + memset(cid, 0, sizeof(SD_CID)); + status = sd_spi_get_cid(cid); + + furi_hal_sd_spi_handle = NULL; + furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); + + return status; +} \ No newline at end of file diff --git a/firmware/targets/f7/fatfs/sd_spi_io.h b/firmware/targets/f7/fatfs/sd_spi_io.h new file mode 100644 index 000000000..8850eceb7 --- /dev/null +++ b/firmware/targets/f7/fatfs/sd_spi_io.h @@ -0,0 +1,157 @@ +#pragma once +#include +#include + +#define __IO volatile + +#define SD_TIMEOUT_MS (1000) + +typedef enum { + SdSpiStatusOK, + SdSpiStatusError, + SdSpiStatusTimeout, +} SdSpiStatus; + +/** + * @brief Card Specific Data: CSD Register + */ +typedef struct { + /* Header part */ + uint8_t CSDStruct : 2; /* CSD structure */ + uint8_t Reserved1 : 6; /* Reserved */ + uint8_t TAAC : 8; /* Data read access-time 1 */ + uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */ + uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */ + uint16_t CardComdClasses : 12; /* Card command classes */ + uint8_t RdBlockLen : 4; /* Max. read data block length */ + uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */ + uint8_t WrBlockMisalign : 1; /* Write block misalignment */ + uint8_t RdBlockMisalign : 1; /* Read block misalignment */ + uint8_t DSRImpl : 1; /* DSR implemented */ + + /* v1 or v2 struct */ + union csd_version { + struct { + uint8_t Reserved1 : 2; /* Reserved */ + uint16_t DeviceSize : 12; /* Device Size */ + uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */ + uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */ + uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */ + uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */ + uint8_t DeviceSizeMul : 3; /* Device size multiplier */ + } v1; + struct { + uint8_t Reserved1 : 6; /* Reserved */ + uint32_t DeviceSize : 22; /* Device Size */ + uint8_t Reserved2 : 1; /* Reserved */ + } v2; + } version; + + uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */ + uint8_t EraseSectorSize : 7; /* Erase group size multiplier */ + uint8_t WrProtectGrSize : 7; /* Write protect group size */ + uint8_t WrProtectGrEnable : 1; /* Write protect group enable */ + uint8_t Reserved2 : 2; /* Reserved */ + uint8_t WrSpeedFact : 3; /* Write speed factor */ + uint8_t MaxWrBlockLen : 4; /* Max. write data block length */ + uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */ + uint8_t Reserved3 : 5; /* Reserved */ + uint8_t FileFormatGrouop : 1; /* File format group */ + uint8_t CopyFlag : 1; /* Copy flag (OTP) */ + uint8_t PermWrProtect : 1; /* Permanent write protection */ + uint8_t TempWrProtect : 1; /* Temporary write protection */ + uint8_t FileFormat : 2; /* File Format */ + uint8_t Reserved4 : 2; /* Reserved */ + uint8_t crc : 7; /* Reserved */ + uint8_t Reserved5 : 1; /* always 1*/ + +} SD_CSD; + +/** + * @brief Card Identification Data: CID Register + */ +typedef struct { + uint8_t ManufacturerID; /* ManufacturerID */ + char OEM_AppliID[2]; /* OEM/Application ID */ + char ProdName[5]; /* Product Name */ + uint8_t ProdRev; /* Product Revision */ + uint32_t ProdSN; /* Product Serial Number */ + uint8_t Reserved1; /* Reserved1 */ + uint8_t ManufactYear; /* Manufacturing Year */ + uint8_t ManufactMonth; /* Manufacturing Month */ + uint8_t CID_CRC; /* CID CRC */ + uint8_t Reserved2; /* always 1 */ +} SD_CID; + +/** + * @brief SD Card information structure + */ +typedef struct { + SD_CSD Csd; + SD_CID Cid; + uint64_t CardCapacity; /*!< Card Capacity */ + uint32_t CardBlockSize; /*!< Card Block Size */ + uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ + uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ +} SD_CardInfo; + +/** + * @brief SD card max mount retry count + * + * @return uint8_t + */ +uint8_t sd_max_mount_retry_count(); + +/** + * @brief Init sd card + * + * @param power_reset reset card power + * @return SdSpiStatus + */ +SdSpiStatus sd_init(bool power_reset); + +/** + * @brief Get card state + * + * @return SdSpiStatus + */ +SdSpiStatus sd_get_card_state(void); + +/** + * @brief Get card info + * + * @param card_info + * @return SdSpiStatus + */ +SdSpiStatus sd_get_card_info(SD_CardInfo* card_info); + +/** + * @brief Read blocks + * + * @param data + * @param address + * @param blocks + * @param timeout_ms + * @return SdSpiStatus + */ +SdSpiStatus sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms); + +/** + * @brief Write blocks + * + * @param data + * @param address + * @param blocks + * @param timeout_ms + * @return SdSpiStatus + */ +SdSpiStatus + sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms); + +/** + * @brief Get card CSD register + * + * @param Cid + * @return SdSpiStatus + */ +SdSpiStatus sd_get_cid(SD_CID* cid); \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index 2f9d87080..42b854799 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -1,14 +1,33 @@ +#include #include #include #include +#include -#include -#include - +#include #include #include #include +#define TAG "FuriHalSpi" + +#define SPI_DMA DMA2 +#define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_3 +#define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_4 +#define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch3 +#define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch4 +#define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL +#define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL + +// For simplicity, I assume that only one SPI DMA transaction can occur at a time. +static FuriSemaphore* spi_dma_lock = NULL; +static FuriSemaphore* spi_dma_completed = NULL; + +void furi_hal_spi_dma_init() { + spi_dma_lock = furi_semaphore_alloc(1, 1); + spi_dma_completed = furi_semaphore_alloc(1, 1); +} + void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { furi_assert(bus); bus->callback(bus, FuriHalSpiBusEventInit); @@ -84,7 +103,7 @@ bool furi_hal_spi_bus_rx( bool furi_hal_spi_bus_tx( FuriHalSpiBusHandle* handle, - uint8_t* buffer, + const uint8_t* buffer, size_t size, uint32_t timeout) { furi_assert(handle); @@ -109,7 +128,7 @@ bool furi_hal_spi_bus_tx( bool furi_hal_spi_bus_trx( FuriHalSpiBusHandle* handle, - uint8_t* tx_buffer, + const uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { @@ -149,3 +168,209 @@ bool furi_hal_spi_bus_trx( return ret; } + +static void spi_dma_isr() { +#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 + if(LL_DMA_IsActiveFlag_TC3(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) { + LL_DMA_ClearFlag_TC3(SPI_DMA); + furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); + } +#else +#error Update this code. Would you kindly? +#endif + +#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 + if(LL_DMA_IsActiveFlag_TC4(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) { + LL_DMA_ClearFlag_TC4(SPI_DMA); + furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk); + } +#else +#error Update this code. Would you kindly? +#endif +} + +bool furi_hal_spi_bus_trx_dma( + FuriHalSpiBusHandle* handle, + uint8_t* tx_buffer, + uint8_t* rx_buffer, + size_t size, + uint32_t timeout_ms) { + furi_assert(handle); + furi_assert(handle->bus->current_handle == handle); + furi_assert(size > 0); + + // If scheduler is not running, use blocking mode + if(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + return furi_hal_spi_bus_trx(handle, tx_buffer, rx_buffer, size, timeout_ms); + } + + // Lock DMA + furi_check(furi_semaphore_acquire(spi_dma_lock, FuriWaitForever) == FuriStatusOk); + + const uint32_t dma_dummy_u32 = 0xFFFFFFFF; + + bool ret = true; + SPI_TypeDef* spi = handle->bus->spi; + uint32_t dma_rx_req; + uint32_t dma_tx_req; + + if(spi == SPI1) { + dma_rx_req = LL_DMAMUX_REQ_SPI1_RX; + dma_tx_req = LL_DMAMUX_REQ_SPI1_TX; + } else if(spi == SPI2) { + dma_rx_req = LL_DMAMUX_REQ_SPI2_RX; + dma_tx_req = LL_DMAMUX_REQ_SPI2_TX; + } else { + furi_crash(NULL); + } + + if(rx_buffer == NULL) { + // Only TX mode, do not use RX channel + + LL_DMA_InitTypeDef dma_config = {0}; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_tx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); + +#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4 + LL_DMA_ClearFlag_TC4(SPI_DMA); +#else +#error Update this code. Would you kindly? +#endif + + furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, spi_dma_isr, NULL); + + bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi); + if(!dma_tx_was_enabled) { + LL_SPI_EnableDMAReq_TX(spi); + } + + // acquire semaphore before enabling DMA + furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk); + + LL_DMA_EnableIT_TC(SPI_DMA_TX_DEF); + LL_DMA_EnableChannel(SPI_DMA_TX_DEF); + + // and wait for it to be released (DMA transfer complete) + if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) { + ret = false; + FURI_LOG_E(TAG, "DMA timeout\r\n"); + } + // release semaphore, because we are using it as a flag + furi_semaphore_release(spi_dma_completed); + + LL_DMA_DisableIT_TC(SPI_DMA_TX_DEF); + LL_DMA_DisableChannel(SPI_DMA_TX_DEF); + if(!dma_tx_was_enabled) { + LL_SPI_DisableDMAReq_TX(spi); + } + furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, NULL, NULL); + + LL_DMA_DeInit(SPI_DMA_TX_DEF); + } else { + // TRX or RX mode, use both channels + uint32_t tx_mem_increase_mode; + + if(tx_buffer == NULL) { + // RX mode, use dummy data instead of TX buffer + tx_buffer = (uint8_t*)&dma_dummy_u32; + tx_mem_increase_mode = LL_DMA_PERIPH_NOINCREMENT; + } else { + tx_mem_increase_mode = LL_DMA_MEMORY_INCREMENT; + } + + LL_DMA_InitTypeDef dma_config = {0}; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = tx_mem_increase_mode; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_tx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config); + + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR); + dma_config.MemoryOrM2MDstAddress = (uint32_t)rx_buffer; + dma_config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + dma_config.Mode = LL_DMA_MODE_NORMAL; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + dma_config.NbData = size; + dma_config.PeriphRequest = dma_rx_req; + dma_config.Priority = LL_DMA_PRIORITY_MEDIUM; + LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config); + +#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3 + LL_DMA_ClearFlag_TC3(SPI_DMA); +#else +#error Update this code. Would you kindly? +#endif + + furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, spi_dma_isr, NULL); + + bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi); + bool dma_rx_was_enabled = LL_SPI_IsEnabledDMAReq_RX(spi); + + if(!dma_tx_was_enabled) { + LL_SPI_EnableDMAReq_TX(spi); + } + + if(!dma_rx_was_enabled) { + LL_SPI_EnableDMAReq_RX(spi); + } + + // acquire semaphore before enabling DMA + furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk); + + LL_DMA_EnableIT_TC(SPI_DMA_RX_DEF); + LL_DMA_EnableChannel(SPI_DMA_RX_DEF); + LL_DMA_EnableChannel(SPI_DMA_TX_DEF); + + // and wait for it to be released (DMA transfer complete) + if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) { + ret = false; + FURI_LOG_E(TAG, "DMA timeout\r\n"); + } + // release semaphore, because we are using it as a flag + furi_semaphore_release(spi_dma_completed); + + LL_DMA_DisableIT_TC(SPI_DMA_RX_DEF); + + LL_DMA_DisableChannel(SPI_DMA_TX_DEF); + LL_DMA_DisableChannel(SPI_DMA_RX_DEF); + + if(!dma_tx_was_enabled) { + LL_SPI_DisableDMAReq_TX(spi); + } + + if(!dma_rx_was_enabled) { + LL_SPI_DisableDMAReq_RX(spi); + } + + furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, NULL, NULL); + + LL_DMA_DeInit(SPI_DMA_TX_DEF); + LL_DMA_DeInit(SPI_DMA_RX_DEF); + } + + furi_hal_spi_bus_end_txrx(handle, timeout_ms); + + furi_check(furi_semaphore_release(spi_dma_lock) == FuriStatusOk); + + return ret; +} \ No newline at end of file diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/firmware/targets/furi_hal_include/furi_hal_spi.h index ab00ef0d7..9c54befb4 100644 --- a/firmware/targets/furi_hal_include/furi_hal_spi.h +++ b/firmware/targets/furi_hal_include/furi_hal_spi.h @@ -71,38 +71,23 @@ bool furi_hal_spi_bus_rx( size_t size, uint32_t timeout); -/** SPI Transmit - * - * @param handle pointer to FuriHalSpiBusHandle instance - * @param buffer transmit buffer - * @param size transaction size (buffer size) - * @param timeout operation timeout in ms - * - * @return true on success - */ -bool furi_hal_spi_bus_tx( - FuriHalSpiBusHandle* handle, - uint8_t* buffer, - size_t size, - uint32_t timeout); - -/** SPI Transmit and Receive +/** SPI Transmit and Receive with DMA * * @param handle pointer to FuriHalSpiBusHandle instance * @param tx_buffer pointer to tx buffer * @param rx_buffer pointer to rx buffer * @param size transaction size (buffer size) - * @param timeout operation timeout in ms + * @param timeout_ms operation timeout in ms * * @return true on success */ -bool furi_hal_spi_bus_trx( +bool furi_hal_spi_bus_trx_dma( FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, - uint32_t timeout); + uint32_t timeout_ms); #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/lib/subghz/blocks/encoder.c b/lib/subghz/blocks/encoder.c index f3349b5fc..e325be21c 100644 --- a/lib/subghz/blocks/encoder.c +++ b/lib/subghz/blocks/encoder.c @@ -2,6 +2,8 @@ #include "math.h" #include +#include "furi.h" + #define TAG "SubGhzBlockEncoder" void subghz_protocol_blocks_set_bit_array( @@ -17,21 +19,32 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde return bit_read(data_array[read_index_bit >> 3], 7 - (read_index_bit & 0x7)); } -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit) { - size_t index_bit = 0; + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit) { + size_t bias_bit = 0; size_t size_upload = 0; uint32_t duration = duration_bit; + + if(align_bit == SubGhzProtocolBlockAlignBitRight) { + if(count_bit_data_array & 0x7) { + bias_bit = 8 - (count_bit_data_array & 0x7); + } + } + size_t index_bit = bias_bit; + bool last_bit = subghz_protocol_blocks_get_bit_array(data_array, index_bit++); - for(size_t i = 1; i < count_bit_data_array; i++) { + for(size_t i = 1 + bias_bit; i < count_bit_data_array + bias_bit; i++) { if(last_bit == subghz_protocol_blocks_get_bit_array(data_array, index_bit)) { duration += duration_bit; } else { - furi_assert(max_size_upload > size_upload); + if(size_upload > max_size_upload) { + furi_crash("SubGhz: Encoder buffer overflow"); + } upload[size_upload++] = level_duration_make( subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); last_bit = !last_bit; @@ -42,4 +55,4 @@ size_t subghz_protocol_blocks_get_upload( upload[size_upload++] = level_duration_make( subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); return size_upload; -} +} \ No newline at end of file diff --git a/lib/subghz/blocks/encoder.h b/lib/subghz/blocks/encoder.h index 1ff077726..aeaa2add0 100644 --- a/lib/subghz/blocks/encoder.h +++ b/lib/subghz/blocks/encoder.h @@ -19,6 +19,11 @@ typedef struct { } SubGhzProtocolBlockEncoder; +typedef enum { + SubGhzProtocolBlockAlignBitLeft, + SubGhzProtocolBlockAlignBitRight, +} SubGhzProtocolBlockAlignBit; + /** * Set data bit when encoding HEX array. * @param bit_value The value of the bit to be set @@ -47,13 +52,15 @@ bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_inde * @param upload Pointer to a LevelDuration * @param max_size_upload upload size, check not to overflow * @param duration_bit duration 1 bit + * @param align_bit alignment of useful bits in an array */ -size_t subghz_protocol_blocks_get_upload( +size_t subghz_protocol_blocks_get_upload_from_bit_array( uint8_t data_array[], size_t count_bit_data_array, LevelDuration* upload, size_t max_size_upload, - uint32_t duration_bit); + uint32_t duration_bit, + SubGhzProtocolBlockAlignBit align_bit); #ifdef __cplusplus } diff --git a/lib/subghz/environment.c b/lib/subghz/environment.c index 0a4b7b606..b39b259d4 100644 --- a/lib/subghz/environment.c +++ b/lib/subghz/environment.c @@ -6,6 +6,7 @@ struct SubGhzEnvironment { const SubGhzProtocolRegistry* protocol_registry; const char* came_atomo_rainbow_table_file_name; const char* nice_flor_s_rainbow_table_file_name; + const char* alutech_at_4n_rainbow_table_file_name; }; SubGhzEnvironment* subghz_environment_alloc() { @@ -57,6 +58,21 @@ const char* return instance->came_atomo_rainbow_table_file_name; } +void subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + SubGhzEnvironment* instance, + const char* filename) { + furi_assert(instance); + + instance->alutech_at_4n_rainbow_table_file_name = filename; +} + +const char* + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(SubGhzEnvironment* instance) { + furi_assert(instance); + + return instance->alutech_at_4n_rainbow_table_file_name; +} + void subghz_environment_set_nice_flor_s_rainbow_table_file_name( SubGhzEnvironment* instance, const char* filename) { diff --git a/lib/subghz/environment.h b/lib/subghz/environment.h index e994f7c97..7bd38ba2f 100644 --- a/lib/subghz/environment.h +++ b/lib/subghz/environment.h @@ -52,6 +52,23 @@ void subghz_environment_set_came_atomo_rainbow_table_file_name( */ const char* subghz_environment_get_came_atomo_rainbow_table_file_name(SubGhzEnvironment* instance); +/** + * Set filename to work with Alutech at-4n. + * @param instance Pointer to a SubGhzEnvironment instance + * @param filename Full path to the file + */ +void subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + SubGhzEnvironment* instance, + const char* filename); + +/** + * Get filename to work with Alutech at-4n. + * @param instance Pointer to a SubGhzEnvironment instance + * @return Full path to the file + */ +const char* + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(SubGhzEnvironment* instance); + /** * Set filename to work with Nice Flor-S. * @param instance Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c new file mode 100644 index 000000000..6bcf9f25d --- /dev/null +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -0,0 +1,455 @@ +#include "alutech_at_4n.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocoAlutech_at_4n" + +#define SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE 0xFFFFFFFF + +static const SubGhzBlockConst subghz_protocol_alutech_at_4n_const = { + .te_short = 400, + .te_long = 800, + .te_delta = 140, + .min_count_bit_for_found = 72, +}; + +struct SubGhzProtocolDecoderAlutech_at_4n { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint64_t data; + uint32_t crc; + uint16_t header_count; + + const char* alutech_at_4n_rainbow_table_file_name; +}; + +struct SubGhzProtocolEncoderAlutech_at_4n { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + Alutech_at_4nDecoderStepReset = 0, + Alutech_at_4nDecoderStepCheckPreambula, + Alutech_at_4nDecoderStepSaveDuration, + Alutech_at_4nDecoderStepCheckDuration, +} Alutech_at_4nDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_alutech_at_4n_decoder = { + .alloc = subghz_protocol_decoder_alutech_at_4n_alloc, + .free = subghz_protocol_decoder_alutech_at_4n_free, + + .feed = subghz_protocol_decoder_alutech_at_4n_feed, + .reset = subghz_protocol_decoder_alutech_at_4n_reset, + + .get_hash_data = subghz_protocol_decoder_alutech_at_4n_get_hash_data, + .serialize = subghz_protocol_decoder_alutech_at_4n_serialize, + .deserialize = subghz_protocol_decoder_alutech_at_4n_deserialize, + .get_string = subghz_protocol_decoder_alutech_at_4n_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_alutech_at_4n_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_alutech_at_4n = { + .name = SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_alutech_at_4n_decoder, + .encoder = &subghz_protocol_alutech_at_4n_encoder, +}; + +/** + * Read bytes from rainbow table + * @param file_name Full path to rainbow table the file + * @param number_alutech_at_4n_magic_data number in the array + * @return alutech_at_4n_magic_data + */ +static uint32_t subghz_protocol_alutech_at_4n_get_magic_data_in_file( + const char* file_name, + uint8_t number_alutech_at_4n_magic_data) { + if(!strcmp(file_name, "")) return SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE; + + uint8_t buffer[sizeof(uint32_t)] = {0}; + uint32_t address = number_alutech_at_4n_magic_data * sizeof(uint32_t); + uint32_t alutech_at_4n_magic_data = 0; + + if(subghz_keystore_raw_get_data(file_name, address, buffer, sizeof(uint32_t))) { + for(size_t i = 0; i < sizeof(uint32_t); i++) { + alutech_at_4n_magic_data = (alutech_at_4n_magic_data << 8) | buffer[i]; + } + } else { + alutech_at_4n_magic_data = SUBGHZ_NO_ALUTECH_AT_4N_RAINBOW_TABLE; + } + return alutech_at_4n_magic_data; +} + +static uint8_t subghz_protocol_alutech_at_4n_crc(uint64_t data) { + uint8_t* p = (uint8_t*)&data; + uint8_t crc = 0xff; + for(uint8_t y = 0; y < 8; y++) { + crc = crc ^ p[y]; + for(uint8_t i = 0; i < 8; i++) { + if((crc & 0x80) != 0) { + crc <<= 1; + crc ^= 0x31; + } else { + crc <<= 1; + } + } + } + return crc; +} + +static uint8_t subghz_protocol_alutech_at_4n_decrypt_data_crc(uint8_t data) { + uint8_t crc = data; + for(uint8_t i = 0; i < 8; i++) { + if((crc & 0x80) != 0) { + crc <<= 1; + crc ^= 0x31; + } else { + crc <<= 1; + } + } + return ~crc; +} + +static uint64_t subghz_protocol_alutech_at_4n_decrypt(uint64_t data, const char* file_name) { + uint8_t* p = (uint8_t*)&data; + uint32_t data1 = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + uint32_t data2 = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; + uint32_t data3 = 0; + uint32_t magic_data[] = { + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 0), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 1), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 2), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 3), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 4), + subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 5)}; + + uint32_t i = magic_data[0]; + do { + data2 = data2 - + ((magic_data[1] + (data1 << 4)) ^ ((magic_data[2] + (data1 >> 5)) ^ (data1 + i))); + data3 = data2 + i; + i += magic_data[3]; + data1 = + data1 - ((magic_data[4] + (data2 << 4)) ^ ((magic_data[5] + (data2 >> 5)) ^ data3)); + } while(i != 0); + + p[0] = (uint8_t)(data1 >> 24); + p[1] = (uint8_t)(data1 >> 16); + p[3] = (uint8_t)data1; + p[4] = (uint8_t)(data2 >> 24); + p[5] = (uint8_t)(data2 >> 16); + p[2] = (uint8_t)(data1 >> 8); + p[6] = (uint8_t)(data2 >> 8); + p[7] = (uint8_t)data2; + + return data; +} + +// static uint64_t subghz_protocol_alutech_at_4n_encrypt(uint64_t data, const char* file_name) { +// uint8_t* p = (uint8_t*)&data; +// uint32_t data1 = 0; +// uint32_t data2 = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +// uint32_t data3 = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; +// uint32_t magic_data[] = { +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 6), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 4), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 5), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 1), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 2), +// subghz_protocol_alutech_at_4n_get_magic_data_in_file(file_name, 0)}; + +// do { +// data1 = data1 + magic_data[0]; +// data2 = data2 + ((magic_data[1] + (data3 << 4)) ^ +// ((magic_data[2] + (data3 >> 5)) ^ (data1 + data3))); +// data3 = data3 + ((magic_data[3] + (data2 << 4)) ^ +// ((magic_data[4] + (data2 >> 5)) ^ (data1 + data2))); +// } while(data1 != magic_data[5]); +// p[0] = (uint8_t)(data2 >> 24); +// p[1] = (uint8_t)(data2 >> 16); +// p[3] = (uint8_t)data2; +// p[4] = (uint8_t)(data3 >> 24); +// p[5] = (uint8_t)(data3 >> 16); +// p[2] = (uint8_t)(data2 >> 8); +// p[6] = (uint8_t)(data3 >> 8); +// p[7] = (uint8_t)data3; + +// return data; +// } + +void* subghz_protocol_decoder_alutech_at_4n_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderAlutech_at_4n* instance = + malloc(sizeof(SubGhzProtocolDecoderAlutech_at_4n)); + instance->base.protocol = &subghz_protocol_alutech_at_4n; + instance->generic.protocol_name = instance->base.protocol->name; + instance->alutech_at_4n_rainbow_table_file_name = + subghz_environment_get_alutech_at_4n_rainbow_table_file_name(environment); + if(instance->alutech_at_4n_rainbow_table_file_name) { + FURI_LOG_I( + TAG, "Loading rainbow table from %s", instance->alutech_at_4n_rainbow_table_file_name); + } + return instance; +} + +void subghz_protocol_decoder_alutech_at_4n_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + instance->alutech_at_4n_rainbow_table_file_name = NULL; + free(instance); +} + +void subghz_protocol_decoder_alutech_at_4n_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; +} + +void subghz_protocol_decoder_alutech_at_4n_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + + switch(instance->decoder.parser_step) { + case Alutech_at_4nDecoderStepReset: + if((level) && DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) { + instance->decoder.parser_step = Alutech_at_4nDecoderStepCheckPreambula; + instance->header_count++; + } + break; + case Alutech_at_4nDecoderStepCheckPreambula: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta)) { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + break; + } + if((instance->header_count > 2) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short * 10) < + subghz_protocol_alutech_at_4n_const.te_delta * 10)) { + // Found header + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + break; + case Alutech_at_4nDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = Alutech_at_4nDecoderStepCheckDuration; + } + break; + case Alutech_at_4nDecoderStepCheckDuration: + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_alutech_at_4n_const.te_short * 2 + + subghz_protocol_alutech_at_4n_const.te_delta)) { + //add last bit + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } + + // Found end TX + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + if(instance->decoder.decode_count_bit == + subghz_protocol_alutech_at_4n_const.min_count_bit_for_found) { + if(instance->generic.data != instance->data) { + instance->generic.data = instance->data; + + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->crc = instance->decoder.decode_data; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + } + break; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + if(instance->decoder.decode_count_bit == 64) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_alutech_at_4n_const.te_long) < + subghz_protocol_alutech_at_4n_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_alutech_at_4n_const.te_short) < + subghz_protocol_alutech_at_4n_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + if(instance->decoder.decode_count_bit == 64) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + instance->decoder.parser_step = Alutech_at_4nDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + } else { + instance->decoder.parser_step = Alutech_at_4nDecoderStepReset; + instance->header_count = 0; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + * @param file_name Full path to rainbow table the file + */ +static void subghz_protocol_alutech_at_4n_remote_controller( + SubGhzBlockGeneric* instance, + uint8_t crc, + const char* file_name) { + /** + * Message format 72bit LSB first + * data crc + * XXXXXXXXXXXXXXXX CC + * + * For analysis, you need to turn the package MSB + * in decoded messages format + * + * crc1 serial cnt key + * cc SSSSSSSS XXxx BB + * + * crc1 is calculated from the lower part of cnt + * key 1=0xff, 2=0x11, 3=0x22, 4=0x33, 5=0x44 + * + */ + + bool status = false; + uint64_t data = subghz_protocol_blocks_reverse_key(instance->data, 64); + crc = subghz_protocol_blocks_reverse_key(crc, 8); + + if(crc == subghz_protocol_alutech_at_4n_crc(data)) { + data = subghz_protocol_alutech_at_4n_decrypt(data, file_name); + status = true; + } + + if(status && ((uint8_t)(data >> 56) == + subghz_protocol_alutech_at_4n_decrypt_data_crc((uint8_t)((data >> 8) & 0xFF)))) { + instance->btn = (uint8_t)data & 0xFF; + instance->cnt = (uint16_t)(data >> 8) & 0xFFFF; + instance->serial = (uint32_t)(data >> 24) & 0xFFFFFFFF; + } + + if(!status) { + instance->btn = 0; + instance->cnt = 0; + instance->serial = 0; + } +} + +uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + return (uint8_t)instance->crc; +} + +bool subghz_protocol_decoder_alutech_at_4n_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(res && !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { + FURI_LOG_E(TAG, "Unable to add CRC"); + res = false; + } + return res; + + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_alutech_at_4n_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_alutech_at_4n_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "CRC", (uint32_t*)&instance->crc, 1)) { + FURI_LOG_E(TAG, "Missing CRC"); + break; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_alutech_at_4n_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderAlutech_at_4n* instance = context; + subghz_protocol_alutech_at_4n_remote_controller( + &instance->generic, instance->crc, instance->alutech_at_4n_rainbow_table_file_name); + uint32_t code_found_hi = instance->generic.data >> 32; + uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; + + furi_string_cat_printf( + output, + "%s %d\r\n" + "Key:0x%08lX%08lX%02X\r\n" + "Sn:0x%08lX Btn:0x%01X\r\n" + "Cnt:0x%03lX\r\n", + + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_hi, + code_found_lo, + (uint8_t)instance->crc, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/alutech_at_4n.h b/lib/subghz/protocols/alutech_at_4n.h new file mode 100644 index 000000000..38bac3ea6 --- /dev/null +++ b/lib/subghz/protocols/alutech_at_4n.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME "Alutech at-4n" + +typedef struct SubGhzProtocolDecoderAlutech_at_4n SubGhzProtocolDecoderAlutech_at_4n; +typedef struct SubGhzProtocolEncoderAlutech_at_4n SubGhzProtocolEncoderAlutech_at_4n; + +extern const SubGhzProtocolDecoder subghz_protocol_alutech_at_4n_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_alutech_at_4n_encoder; +extern const SubGhzProtocol subghz_protocol_alutech_at_4n; + +/** + * Allocate SubGhzProtocolDecoderAlutech_at_4n. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderAlutech_at_4n* pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void* subghz_protocol_decoder_alutech_at_4n_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void subghz_protocol_decoder_alutech_at_4n_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + */ +void subghz_protocol_decoder_alutech_at_4n_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_alutech_at_4n_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_alutech_at_4n_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderAlutech_at_4n. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_alutech_at_4n_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance + * @param output Resulting text + */ +void subghz_protocol_decoder_alutech_at_4n_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c new file mode 100644 index 000000000..3fef76af2 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.c @@ -0,0 +1,1120 @@ +#include "bin_raw.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" +#include +#include +#include + +#define TAG "SubGhzProtocolBinRAW" + +//change very carefully, RAM ends at the most inopportune moment +#define BIN_RAW_BUF_RAW_SIZE 2048 +#define BIN_RAW_BUF_DATA_SIZE 512 + +#define BIN_RAW_THRESHOLD_RSSI -85.0f +#define BIN_RAW_DELTA_RSSI 7.0f +#define BIN_RAW_SEARCH_CLASSES 20 +#define BIN_RAW_TE_MIN_COUNT 40 +#define BIN_RAW_BUF_MIN_DATA_COUNT 128 +#define BIN_RAW_MAX_MARKUP_COUNT 20 + +//#define BIN_RAW_DEBUG + +#ifdef BIN_RAW_DEBUG +#define bin_raw_debug(...) FURI_LOG_RAW_D(__VA_ARGS__) +#define bin_raw_debug_tag(tag, ...) \ + FURI_LOG_RAW_D("\033[0;32m[" tag "]\033[0m "); \ + FURI_LOG_RAW_D(__VA_ARGS__) +#else +#define bin_raw_debug(...) +#define bin_raw_debug_tag(...) +#endif + +static const SubGhzBlockConst subghz_protocol_bin_raw_const = { + .te_short = 30, + .te_long = 65000, + .te_delta = 0, + .min_count_bit_for_found = 0, +}; + +typedef enum { + BinRAWDecoderStepReset = 0, + BinRAWDecoderStepWrite, + BinRAWDecoderStepBufFull, + BinRAWDecoderStepNoParse, +} BinRAWDecoderStep; + +typedef enum { + BinRAWTypeUnknown = 0, + BinRAWTypeNoGap, + BinRAWTypeGap, + BinRAWTypeGapRecurring, + BinRAWTypeGapRolling, + BinRAWTypeGapUnknown, +} BinRAWType; + +struct BinRAW_Markup { + uint16_t byte_bias; + uint16_t bit_count; +}; +typedef struct BinRAW_Markup BinRAW_Markup; + +struct SubGhzProtocolDecoderBinRAW { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + int32_t* data_raw; + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + size_t data_raw_ind; + uint32_t te; + float adaptive_threshold_rssi; +}; + +struct SubGhzProtocolEncoderBinRAW { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; + + uint8_t* data; + BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT]; + uint32_t te; +}; + +const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder = { + .alloc = subghz_protocol_decoder_bin_raw_alloc, + .free = subghz_protocol_decoder_bin_raw_free, + + .feed = subghz_protocol_decoder_bin_raw_feed, + .reset = subghz_protocol_decoder_bin_raw_reset, + + .get_hash_data = subghz_protocol_decoder_bin_raw_get_hash_data, + .serialize = subghz_protocol_decoder_bin_raw_serialize, + .deserialize = subghz_protocol_decoder_bin_raw_deserialize, + .get_string = subghz_protocol_decoder_bin_raw_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder = { + .alloc = subghz_protocol_encoder_bin_raw_alloc, + .free = subghz_protocol_encoder_bin_raw_free, + + .deserialize = subghz_protocol_encoder_bin_raw_deserialize, + .stop = subghz_protocol_encoder_bin_raw_stop, + .yield = subghz_protocol_encoder_bin_raw_yield, +}; + +const SubGhzProtocol subghz_protocol_bin_raw = { + .name = SUBGHZ_PROTOCOL_BIN_RAW_NAME, + .type = SubGhzProtocolTypeStatic, +#ifdef BIN_RAW_DEBUG + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#else + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_BinRAW | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, +#endif + .decoder = &subghz_protocol_bin_raw_decoder, + .encoder = &subghz_protocol_bin_raw_encoder, +}; + +static uint16_t subghz_protocol_bin_raw_get_full_byte(uint16_t bit_count) { + if(bit_count & 0x7) { + return (bit_count >> 3) + 1; + } else { + return (bit_count >> 3); + } +} + +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderBinRAW* instance = malloc(sizeof(SubGhzProtocolEncoderBinRAW)); + + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = BIN_RAW_BUF_DATA_SIZE * 5; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->data = malloc(instance->encoder.size_upload * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + free(instance->encoder.upload); + free(instance->data); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return true On success + */ +static bool subghz_protocol_encoder_bin_raw_get_upload(SubGhzProtocolEncoderBinRAW* instance) { + furi_assert(instance); + + //we glue all the pieces of the package into 1 long sequence with left alignment, + //in the uploaded data we have right alignment. + + bin_raw_debug_tag(TAG, "Recovery of offset bits in sequences\r\n"); + uint16_t i = 0; + uint16_t ind = 0; + bin_raw_debug("\tind byte_bias\tbit_count\tbit_bias\r\n"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + uint8_t bit_bias = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + instance->data_markup[i].bit_count; + bin_raw_debug( + "\t%d\t%d\t%d :\t\t%d\r\n", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count, + bit_bias); + for(uint16_t y = instance->data_markup[i].byte_bias * 8; + y < instance->data_markup[i].byte_bias * 8 + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 - + bit_bias; + y++) { + subghz_protocol_blocks_set_bit_array( + subghz_protocol_blocks_get_bit_array(instance->data, y + bit_bias), + instance->data, + ind++, + BIN_RAW_BUF_DATA_SIZE); + } + i++; + } + bin_raw_debug("\r\n"); +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Restored Sequence left aligned\r\n"); + for(uint16_t y = 0; y < subghz_protocol_bin_raw_get_full_byte(ind); y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + bin_raw_debug("\r\n\tbin_count_result= %d\r\n\r\n", ind); + + bin_raw_debug_tag( + TAG, "Maximum levels encoded in upload %zu\r\n", instance->encoder.size_upload); +#endif + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( + instance->data, + ind, + instance->encoder.upload, + instance->encoder.size_upload, + instance->te, + SubGhzProtocolBlockAlignBitLeft); + + bin_raw_debug_tag(TAG, "The result %zu is levels\r\n", instance->encoder.size_upload); + bin_raw_debug_tag(TAG, "Remaining free memory %zu\r\n", memmgr_get_free_heap()); + return true; +} + +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + +#ifdef BIN_RAW_DEBUG + uint16_t i = 0; + bin_raw_debug_tag(TAG, "Download data to encoder\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } + i++; + } + bin_raw_debug("\r\n\r\n"); +#endif + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_encoder_bin_raw_stop(void* context) { + SubGhzProtocolEncoderBinRAW* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context) { + SubGhzProtocolEncoderBinRAW* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderBinRAW* instance = malloc(sizeof(SubGhzProtocolDecoderBinRAW)); + instance->base.protocol = &subghz_protocol_bin_raw; + instance->generic.protocol_name = instance->base.protocol->name; + instance->data_raw_ind = 0; + instance->data_raw = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + instance->data = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + instance->adaptive_threshold_rssi = BIN_RAW_THRESHOLD_RSSI; + return instance; +} + +void subghz_protocol_decoder_bin_raw_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + free(instance->data_raw); + free(instance->data); + free(instance); +} + +void subghz_protocol_decoder_bin_raw_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; +#ifdef BIN_RAW_DEBUG + UNUSED(instance); +#else + instance->decoder.parser_step = BinRAWDecoderStepNoParse; + instance->data_raw_ind = 0; +#endif +} + +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + if(instance->decoder.parser_step == BinRAWDecoderStepWrite) { + if(instance->data_raw_ind == BIN_RAW_BUF_RAW_SIZE) { + instance->decoder.parser_step = BinRAWDecoderStepBufFull; + } else { + instance->data_raw[instance->data_raw_ind++] = (level ? duration : -duration); + } + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzProtocolDecoderBinRAW* instance + */ +static bool + subghz_protocol_bin_raw_check_remote_controller(SubGhzProtocolDecoderBinRAW* instance) { + struct { + float data; + uint16_t count; + } classes[BIN_RAW_SEARCH_CLASSES]; + + size_t ind = 0; + + memset(classes, 0x00, sizeof(classes)); + + uint16_t data_markup_ind = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + if(instance->data_raw_ind < 512) { + ind = + instance->data_raw_ind - + 100; //there is usually garbage at the end of the record, we exclude it from the classification + } else { + ind = 512; + } + + //sort the durations to find the shortest correlated interval + for(size_t i = 0; i < ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = (float)(abs(instance->data_raw[i])); + classes[k].count++; + break; + } else if( + DURATION_DIFF((float)(abs(instance->data_raw[i])), (classes[k].data)) < + (classes[k].data / 4)) { //if the test value does not differ by more than 25% + classes[k].data += ((float)(abs(instance->data_raw[i])) - classes[k].data) * + 0.05f; //running average k=0.05 + classes[k].count++; + break; + } + } + } + + // if(classes[BIN_RAW_SEARCH_CLASSES - 1].count != 0) { + // //filling the classifier, it means that they received an unclean signal + // return false; + // } + + //looking for the minimum te with an occurrence greater than BIN_RAW_TE_MIN_COUNT + instance->te = subghz_protocol_bin_raw_const.te_long * 2; + + bool te_ok = false; + uint16_t gap_ind = 0; + uint16_t gap_delta = 0; + uint32_t gap = 0; + int data_temp = 0; + BinRAWType bin_raw_type = BinRAWTypeUnknown; + + //sort by number of occurrences + bool swap = true; + while(swap) { + swap = false; + for(size_t i = 1; i < BIN_RAW_SEARCH_CLASSES; i++) { + if(classes[i].count > classes[i - 1].count) { + uint32_t data = classes[i - 1].data; + uint32_t count = classes[i - 1].count; + classes[i - 1].data = classes[i].data; + classes[i - 1].count = classes[i].count; + classes[i].data = data; + classes[i].count = count; + swap = true; + } + } + } +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Sorted durations\r\n"); + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + if((classes[0].count > BIN_RAW_TE_MIN_COUNT) && (classes[1].count == 0)) { + //adopted only the preamble + instance->te = (uint32_t)classes[0].data; + te_ok = true; + gap = 0; //gap no + } else { + //take the 2 most common durations + //check that there are enough + if((classes[0].count < BIN_RAW_TE_MIN_COUNT) || + (classes[1].count < (BIN_RAW_TE_MIN_COUNT >> 1))) + return false; + //arrange the first 2 date values in ascending order + if(classes[0].data > classes[1].data) { + uint32_t data = classes[1].data; + classes[0].data = classes[1].data; + classes[1].data = data; + } + + //determine the value to be corrected + for(uint8_t k = 1; k < 5; k++) { + float delta = (classes[1].data / (classes[0].data / k)); + bin_raw_debug_tag(TAG, "K_div= %f\r\n", (double)(delta)); + delta -= (uint32_t)delta; + + if((delta < 0.20f) || (delta > 0.80f)) { + instance->te = (uint32_t)classes[0].data / k; + bin_raw_debug_tag(TAG, "K= %d\r\n", k); + te_ok = true; //found a correlated duration + break; + } + } + if(!te_ok) { + //did not find the minimum TE satisfying the condition + return false; + } + bin_raw_debug_tag(TAG, "TE= %lu\r\n\r\n", instance->te); + + //looking for a gap + for(size_t k = 2; k < BIN_RAW_SEARCH_CLASSES; k++) { + if((classes[k].count > 2) && (classes[k].data > gap)) { + gap = (uint32_t)classes[k].data; + gap_delta = gap / 5; //calculate 20% deviation from ideal value + } + } + + if((gap / instance->te) < + 10) { //make an assumption, the longest gap should be more than 10 TE + gap = 0; //check that our signal has a gap greater than 10*TE + bin_raw_type = BinRAWTypeNoGap; + } else { + bin_raw_type = BinRAWTypeGap; + //looking for the last occurrence of gap + ind = instance->data_raw_ind - 1; + while((ind > 0) && (DURATION_DIFF(abs(instance->data_raw[ind]), gap) > gap_delta)) { + ind--; + } + gap_ind = ind; + } + } + + //if we consider that there is a gap, then we divide the signal with respect to this gap + //processing input data from the end + if(bin_raw_type == BinRAWTypeGap) { + bin_raw_debug_tag(TAG, "Tinted sequence\r\n"); + ind = (BIN_RAW_BUF_DATA_SIZE * 8); + uint16_t bit_count = 0; + do { + gap_ind--; + data_temp = (int)(round((float)(instance->data_raw[gap_ind]) / instance->te)); + bin_raw_debug("%d ", data_temp); + if(data_temp == 0) bit_count++; //there is noise in the package + for(size_t i = 0; i < abs(data_temp); i++) { + bit_count++; + if(ind) { + ind--; + } else { + break; + } + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind, BIN_RAW_BUF_DATA_SIZE); + } + } + //split into full bytes if gap is caught + if(DURATION_DIFF(abs(instance->data_raw[gap_ind]), gap) < gap_delta) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + bit_count = 0; + + if(data_markup_ind == BIN_RAW_MAX_MARKUP_COUNT) break; + ind &= 0xFFFFFFF8; //jump to the pre whole byte + } + } while(gap_ind != 0); + if((data_markup_ind != BIN_RAW_MAX_MARKUP_COUNT) && (ind != 0)) { + instance->data_markup[data_markup_ind].byte_bias = ind >> 3; + instance->data_markup[data_markup_ind++].bit_count = bit_count; + } + + bin_raw_debug("\r\n\t count bit= %zu\r\n\r\n", (BIN_RAW_BUF_DATA_SIZE * 8) - ind); + + //reset the classifier and classify the received data + memset(classes, 0x00, sizeof(classes)); + + bin_raw_debug_tag(TAG, "Sort the found pieces by the number of bits in them\r\n"); + for(size_t i = 0; i < data_markup_ind; i++) { + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + if(classes[k].count == 0) { + classes[k].data = instance->data_markup[i].bit_count; + classes[k].count++; + break; + } else if(instance->data_markup[i].bit_count == (uint16_t)classes[k].data) { + classes[k].count++; + break; + } + } + } + +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\t\tind\tcount\tus\r\n"); + for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) { + bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data); + } + bin_raw_debug("\r\n"); +#endif + + //choose the value with the maximum repetition + data_temp = 0; + for(size_t i = 0; i < BIN_RAW_SEARCH_CLASSES; i++) { + if((classes[i].count > 1) && (data_temp < classes[i].count)) + data_temp = (int)classes[i].data; + } + + //if(data_markup_ind == 0) return false; + +#ifdef BIN_RAW_DEBUG + //output in reverse order + bin_raw_debug_tag(TAG, "Found sequences\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + uint16_t data_markup_ind_temp = data_markup_ind; + if(data_markup_ind) { + data_markup_ind_temp--; + for(size_t i = (ind / 8); i < BIN_RAW_BUF_DATA_SIZE; i++) { + if(instance->data_markup[data_markup_ind_temp].byte_bias == i) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + data_markup_ind_temp, + instance->data_markup[data_markup_ind_temp].byte_bias, + instance->data_markup[data_markup_ind_temp].bit_count); + if(data_markup_ind_temp != 0) data_markup_ind_temp--; + } + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); + } + //compare data in chunks with the same number of bits + bin_raw_debug_tag(TAG, "Analyze sequences of long %d bit\r\n\r\n", data_temp); +#endif + + //if(data_temp == 0) data_temp = (int)classes[0].data; + + if(data_temp != 0) { + //check that data in transmission is repeated every packet + for(uint16_t i = 0; i < data_markup_ind - 1; i++) { + if((instance->data_markup[i].bit_count == data_temp) && + (instance->data_markup[i + 1].bit_count == data_temp)) { + //if the number of bits in adjacent parcels is the same, compare the data + bin_raw_debug_tag( + TAG, + "Comparison of neighboring sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + i + 1, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[i + 1].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[i + 1].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i + 1].bit_count) - + 1]); + + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + if(memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[i + 1].byte_bias, + byte_count - 1) == 0) { + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRecurring\r\n\r\n"); + + //place in 1 element the offset to valid data + instance->data_markup[0].bit_count = instance->data_markup[i].bit_count; + instance->data_markup[0].byte_bias = instance->data_markup[i].byte_bias; + //markup end sign + instance->data_markup[1].bit_count = 0; + instance->data_markup[1].byte_bias = 0; + + bin_raw_type = BinRAWTypeGapRecurring; + i = data_markup_ind; + break; + } + } + } + } + + if(bin_raw_type == BinRAWTypeGap) { + // check that retry occurs every n packets + for(uint16_t i = 0; i < data_markup_ind - 2; i++) { + uint16_t byte_count = + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count); + for(uint16_t y = i + 1; y < data_markup_ind - 1; y++) { + bin_raw_debug_tag( + TAG, + "Comparison every N sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n", + i, + y, + instance->data[instance->data_markup[i].byte_bias], + instance->data[instance->data_markup[y].byte_bias], + instance->data + [instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count) - + 1], + instance->data + [instance->data_markup[y].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count) - + 1]); + + if(byte_count == + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[y].bit_count)) { //if the length in bytes matches + + if((memcmp( + instance->data + instance->data_markup[i].byte_bias, + instance->data + instance->data_markup[y].byte_bias, + byte_count - 1) == 0) && + (memcmp( + instance->data + instance->data_markup[i + 1].byte_bias, + instance->data + instance->data_markup[y + 1].byte_bias, + byte_count - 1) == 0)) { + uint8_t index = 0; +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag( + TAG, "Match found bin_raw_type=BinRAWTypeGapRolling\r\n\r\n"); + //output in reverse order + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n"); + index = y - 1; + for(size_t z = instance->data_markup[y].byte_bias + byte_count; + z < instance->data_markup[i].byte_bias + byte_count; + z++) { + if(instance->data_markup[index].byte_bias == z) { + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + index, + instance->data_markup[index].byte_bias, + instance->data_markup[index].bit_count); + if(index != 0) index--; + } + bin_raw_debug("%02X ", instance->data[z]); + } + + bin_raw_debug("\r\n\r\n"); +#endif + //todo can be optimized + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, + 0x00, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + + for(index = i; index < y; index++) { + instance->data_markup[index - i].bit_count = + markup_temp[y - index - 1].bit_count; + instance->data_markup[index - i].byte_bias = + markup_temp[y - index - 1].byte_bias; + } + + bin_raw_type = BinRAWTypeGapRolling; + i = data_markup_ind; + break; + } + } + } + } + } + //todo can be optimized + if(bin_raw_type == BinRAWTypeGap) { + if(data_temp != 0) { //there are sequences with the same number of bits + + BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; + memcpy( + markup_temp, + instance->data_markup, + BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + memset( + instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(data_temp); + uint16_t index = 0; + uint16_t it = BIN_RAW_MAX_MARKUP_COUNT; + do { + it--; + if(subghz_protocol_bin_raw_get_full_byte(markup_temp[it].bit_count) == + byte_count) { + instance->data_markup[index].bit_count = markup_temp[it].bit_count; + instance->data_markup[index].byte_bias = markup_temp[it].byte_bias; + index++; + bin_raw_type = BinRAWTypeGapUnknown; + } + } while(it != 0); + } + } + + if(bin_raw_type != BinRAWTypeGap) + return true; + else + return false; + + } else { + // if bin_raw_type == BinRAWTypeGap + bin_raw_debug_tag(TAG, "Sequence analysis without gap\r\n"); + ind = 0; + for(size_t i = 0; i < instance->data_raw_ind; i++) { + int data_temp = (int)(round((float)(instance->data_raw[i]) / instance->te)); + if(data_temp == 0) break; //found an interval 2 times shorter than TE, this is noise + bin_raw_debug("%d ", data_temp); + + for(size_t k = 0; k < abs(data_temp); k++) { + if(data_temp > 0) { + subghz_protocol_blocks_set_bit_array( + true, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } else { + subghz_protocol_blocks_set_bit_array( + false, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE); + } + if(ind == BIN_RAW_BUF_DATA_SIZE * 8) { + i = instance->data_raw_ind; + break; + } + } + } + + if(ind != 0) { + bin_raw_type = BinRAWTypeNoGap; + //right alignment + uint8_t bit_bias = (subghz_protocol_bin_raw_get_full_byte(ind) << 3) - ind; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t count bit= %zu\tcount full byte= %d\tbias bit= %d\r\n\r\n", + ind, + subghz_protocol_bin_raw_get_full_byte(ind), + bit_bias); + + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + //checking that the received sequence contains useful data + bool data_check = false; + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + if(instance->data[i] != 0) { + data_check = true; + break; + } + } + + if(data_check) { + for(size_t i = subghz_protocol_bin_raw_get_full_byte(ind) - 1; i > 0; i--) { + instance->data[i] = (instance->data[i - 1] << (8 - bit_bias)) | + (instance->data[i] >> bit_bias); + } + instance->data[0] = (instance->data[0] >> bit_bias); + +#ifdef BIN_RAW_DEBUG + bin_raw_debug_tag(TAG, "Data right alignment\r\n"); + for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) { + bin_raw_debug("%02X ", instance->data[i]); + } + bin_raw_debug("\r\n\r\n"); +#endif + instance->data_markup[0].bit_count = ind; + instance->data_markup[0].byte_bias = 0; + + return true; + } else { + return false; + } + } else { + return false; + } + } + return false; +} + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi) { + furi_assert(instance); + switch(instance->decoder.parser_step) { + case BinRAWDecoderStepReset: + + bin_raw_debug("%ld %ld :", (int32_t)rssi, (int32_t)instance->adaptive_threshold_rssi); + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + instance->data_raw_ind = 0; + memset(instance->data_raw, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t)); + memset(instance->data, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t)); + instance->decoder.parser_step = BinRAWDecoderStepWrite; + bin_raw_debug_tag(TAG, "RSSI\r\n"); + } else { + //adaptive noise level adjustment + instance->adaptive_threshold_rssi += (rssi - instance->adaptive_threshold_rssi) * 0.2f; + } + break; + + case BinRAWDecoderStepBufFull: + case BinRAWDecoderStepWrite: +#ifdef BIN_RAW_DEBUG + if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) { + bin_raw_debug("\033[0;32m%ld \033[0m ", (int32_t)rssi); + } else { + bin_raw_debug("%ld ", (int32_t)rssi); + } +#endif + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { +#ifdef BIN_RAW_DEBUG + bin_raw_debug("\r\n\r\n"); + bin_raw_debug_tag(TAG, "Data for analysis, positive high, negative low, us\r\n"); + for(size_t i = 0; i < instance->data_raw_ind; i++) { + bin_raw_debug("%ld ", instance->data_raw[i]); + } + bin_raw_debug("\r\n\t count data= %zu\r\n\r\n", instance->data_raw_ind); +#endif + instance->decoder.parser_step = BinRAWDecoderStepReset; + instance->generic.data_count_bit = 0; + if(instance->data_raw_ind >= BIN_RAW_BUF_MIN_DATA_COUNT) { + if(subghz_protocol_bin_raw_check_remote_controller(instance)) { + bin_raw_debug_tag(TAG, "Sequence found\r\n"); + bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data"); + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && + (instance->data_markup[i].bit_count != 0)) { + instance->generic.data_count_bit += instance->data_markup[i].bit_count; +#ifdef BIN_RAW_DEBUG + bin_raw_debug( + "\r\n\t%d\t%d\t%d :\t", + i, + instance->data_markup[i].byte_bias, + instance->data_markup[i].bit_count); + for(uint16_t y = instance->data_markup[i].byte_bias; + y < instance->data_markup[i].byte_bias + + subghz_protocol_bin_raw_get_full_byte( + instance->data_markup[i].bit_count); + y++) { + bin_raw_debug("%02X ", instance->data[y]); + } +#endif + i++; + } + bin_raw_debug("\r\n"); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + } + break; + + default: + //if instance->decoder.parser_step == BinRAWDecoderStepNoParse or others, restore the initial state + if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) { + instance->decoder.parser_step = BinRAWDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + return subghz_protocol_blocks_add_bytes( + instance->data + instance->data_markup[0].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[0].bit_count)); +} + +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + FuriString* temp_str; + temp_str = furi_string_alloc(); + do { + stream_clean(flipper_format_get_raw_stream(flipper_format)); + if(!flipper_format_write_header_cstr( + flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { + FURI_LOG_E(TAG, "Unable to add header"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { + FURI_LOG_E(TAG, "Unable to add Frequency"); + break; + } + + subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str); + if(!flipper_format_write_string_cstr( + flipper_format, "Preset", furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Unable to add Preset"); + break; + } + if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!flipper_format_write_string_cstr( + flipper_format, "Custom_preset_module", "CC1101")) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + break; + } + if(!flipper_format_write_hex( + flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { + FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + break; + } + } + if(!flipper_format_write_string_cstr( + flipper_format, "Protocol", instance->generic.protocol_name)) { + FURI_LOG_E(TAG, "Unable to add Protocol"); + break; + } + + uint32_t temp = instance->generic.data_count_bit; + if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) { + FURI_LOG_E(TAG, "Unable to add Bit"); + break; + } + + if(!flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + FURI_LOG_E(TAG, "Unable to add TE"); + break; + } + + uint16_t i = 0; + while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) { + temp = instance->data_markup[i].bit_count; + if(!flipper_format_write_uint32(flipper_format, "Bit_RAW", &temp, 1)) { + FURI_LOG_E(TAG, "Bit_RAW"); + break; + } + if(!flipper_format_write_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[i].byte_bias, + subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count))) { + FURI_LOG_E(TAG, "Unable to add Data_RAW"); + break; + } + i++; + } + + res = true; + } while(false); + furi_string_free(temp_str); + return res; +} + +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + + bool res = false; + uint32_t temp_data = 0; + + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { + FURI_LOG_E(TAG, "Missing Bit"); + break; + } + + instance->generic.data_count_bit = (uint16_t)temp_data; + + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + + temp_data = 0; + uint16_t ind = 0; + uint16_t byte_bias = 0; + uint16_t byte_count = 0; + memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup)); + while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { + if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { + FURI_LOG_E(TAG, "Markup overflow"); + break; + } + byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); + if(byte_count > BIN_RAW_BUF_DATA_SIZE) { + FURI_LOG_E(TAG, "Receive buffer overflow"); + break; + } + + instance->data_markup[ind].bit_count = temp_data; + instance->data_markup[ind].byte_bias = byte_bias; + byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data); + + if(!flipper_format_read_hex( + flipper_format, + "Data_RAW", + instance->data + instance->data_markup[ind].byte_bias, + subghz_protocol_bin_raw_get_full_byte(temp_data))) { + instance->data_markup[ind].bit_count = 0; + FURI_LOG_E(TAG, "Missing Data_RAW"); + break; + } + ind++; + } + + res = true; + } while(0); + + return res; +} + +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderBinRAW* instance = context; + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:", + instance->generic.protocol_name, + instance->generic.data_count_bit); + + uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(instance->generic.data_count_bit); + for(size_t i = 0; (byte_count < 36 ? i < byte_count : i < 36); i++) { + furi_string_cat_printf(output, "%02X", instance->data[i]); + } + + furi_string_cat_printf(output, "\r\nTe:%luus\r\n", instance->te); +} \ No newline at end of file diff --git a/lib/subghz/protocols/bin_raw.h b/lib/subghz/protocols/bin_raw.h new file mode 100644 index 000000000..c63f86ce6 --- /dev/null +++ b/lib/subghz/protocols/bin_raw.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_BIN_RAW_NAME "BinRAW" + +typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; +typedef struct SubGhzProtocolEncoderBinRAW SubGhzProtocolEncoderBinRAW; + +extern const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder; +extern const SubGhzProtocol subghz_protocol_bin_raw; + +/** + * Allocate SubGhzProtocolEncoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderBinRAW* pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderBinRAW. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + */ +void subghz_protocol_encoder_bin_raw_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderBinRAW. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderBinRAW* pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + */ +void subghz_protocol_decoder_bin_raw_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context); + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi); + +/** + * Serialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderBinRAW. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance + * @param output Resulting text + */ +void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 32f4e9520..9c8e5ee4a 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -196,12 +196,13 @@ static bool break; } - instance->encoder.size_upload = subghz_protocol_blocks_get_upload( + instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array( upload_hex_data, upload_hex_count_bit, instance->encoder.upload, instance->encoder.size_upload, - subghz_protocol_chamb_code_const.te_short); + subghz_protocol_chamb_code_const.te_short, + SubGhzProtocolBlockAlignBitLeft); return true; } diff --git a/lib/subghz/protocols/dooya.c b/lib/subghz/protocols/dooya.c new file mode 100644 index 000000000..c70b6d54e --- /dev/null +++ b/lib/subghz/protocols/dooya.c @@ -0,0 +1,447 @@ +#include "dooya.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolDooya" + +#define DOYA_SINGLE_CHANNEL 0xFF + +static const SubGhzBlockConst subghz_protocol_dooya_const = { + .te_short = 366, + .te_long = 733, + .te_delta = 120, + .min_count_bit_for_found = 40, +}; + +struct SubGhzProtocolDecoderDooya { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderDooya { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + DooyaDecoderStepReset = 0, + DooyaDecoderStepFoundStartBit, + DooyaDecoderStepSaveDuration, + DooyaDecoderStepCheckDuration, +} DooyaDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_dooya_decoder = { + .alloc = subghz_protocol_decoder_dooya_alloc, + .free = subghz_protocol_decoder_dooya_free, + + .feed = subghz_protocol_decoder_dooya_feed, + .reset = subghz_protocol_decoder_dooya_reset, + + .get_hash_data = subghz_protocol_decoder_dooya_get_hash_data, + .serialize = subghz_protocol_decoder_dooya_serialize, + .deserialize = subghz_protocol_decoder_dooya_deserialize, + .get_string = subghz_protocol_decoder_dooya_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_dooya_encoder = { + .alloc = subghz_protocol_encoder_dooya_alloc, + .free = subghz_protocol_encoder_dooya_free, + + .deserialize = subghz_protocol_encoder_dooya_deserialize, + .stop = subghz_protocol_encoder_dooya_stop, + .yield = subghz_protocol_encoder_dooya_yield, +}; + +const SubGhzProtocol subghz_protocol_dooya = { + .name = SUBGHZ_PROTOCOL_DOOYA_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | + SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_dooya_decoder, + .encoder = &subghz_protocol_dooya_encoder, +}; + +void* subghz_protocol_encoder_dooya_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderDooya* instance = malloc(sizeof(SubGhzProtocolEncoderDooya)); + + instance->base.protocol = &subghz_protocol_dooya; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_dooya_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderDooya* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderDooya instance + * @return true On success + */ +static bool subghz_protocol_encoder_dooya_get_upload(SubGhzProtocolEncoderDooya* instance) { + furi_assert(instance); + + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send header + if(bit_read(instance->generic.data, 0)) { + instance->encoder.upload[index++] = level_duration_make( + false, + (uint32_t)subghz_protocol_dooya_const.te_long * 12 + + subghz_protocol_dooya_const.te_long); + } else { + instance->encoder.upload[index++] = level_duration_make( + false, + (uint32_t)subghz_protocol_dooya_const.te_long * 12 + + subghz_protocol_dooya_const.te_short); + } + + //Send start bit + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_short * 13); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_long * 2); + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_dooya_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_dooya_const.te_long); + } + } + return true; +} + +bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderDooya* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_dooya_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_dooya_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_dooya_stop(void* context) { + SubGhzProtocolEncoderDooya* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_dooya_yield(void* context) { + SubGhzProtocolEncoderDooya* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_dooya_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderDooya* instance = malloc(sizeof(SubGhzProtocolDecoderDooya)); + instance->base.protocol = &subghz_protocol_dooya; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_dooya_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + free(instance); +} + +void subghz_protocol_decoder_dooya_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + instance->decoder.parser_step = DooyaDecoderStepReset; +} + +void subghz_protocol_decoder_dooya_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + + switch(instance->decoder.parser_step) { + case DooyaDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long * 12) < + subghz_protocol_dooya_const.te_delta * 20)) { + instance->decoder.parser_step = DooyaDecoderStepFoundStartBit; + } + break; + + case DooyaDecoderStepFoundStartBit: + if(!level) { + if(DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long * 2) < + subghz_protocol_dooya_const.te_delta * 3) { + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + } else if( + DURATION_DIFF(duration, subghz_protocol_dooya_const.te_short * 13) < + subghz_protocol_dooya_const.te_delta * 5) { + break; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + + case DooyaDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = DooyaDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + + case DooyaDecoderStepCheckDuration: + if(!level) { + if(duration >= (subghz_protocol_dooya_const.te_long * 4)) { + //add last bit + if(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else if( + DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + break; + } + instance->decoder.parser_step = DooyaDecoderStepFoundStartBit; + if(instance->decoder.decode_count_bit == + subghz_protocol_dooya_const.min_count_bit_for_found) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_dooya_const.te_long) < + subghz_protocol_dooya_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_dooya_const.te_short) < + subghz_protocol_dooya_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = DooyaDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + } else { + instance->decoder.parser_step = DooyaDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGeneric* instance) { + /* + * serial s/m ch key + * long press down X * E1DC030533, 40b 111000011101110000000011 0000 0101 0011 0011 + * + * short press down 3 * E1DC030533, 40b 111000011101110000000011 0000 0101 0011 0011 + * 3 * E1DC03053C, 40b 111000011101110000000011 0000 0101 0011 1100 + * + * press stop X * E1DC030555, 40b 111000011101110000000011 0000 0101 0101 0101 + * + * long press up X * E1DC030511, 40b 111000011101110000000011 0000 0101 0001 0001 + * + * short press up 3 * E1DC030511, 40b 111000011101110000000011 0000 0101 0001 0001 + * 3 * E1DC03051E, 40b 111000011101110000000011 0000 0101 0001 1110 + * + * serial: 3 byte serial number + * s/m: single (b0000) / multi (b0001) channel console + * ch: channel if single (always b0101) or multi + * key: 0b00010001 - long press up + * 0b00011110 - short press up + * 0b00110011 - long press down + * 0b00111100 - short press down + * 0b01010101 - press stop + * 0b01111001 - press up + down + * 0b10000000 - press up + stop + * 0b10000001 - press down + stop + * 0b11001100 - press P2 + * +*/ + + instance->serial = (instance->data >> 16); + if((instance->data >> 12) & 0x0F) { + instance->cnt = (instance->data >> 8) & 0x0F; + } else { + instance->cnt = DOYA_SINGLE_CHANNEL; + } + instance->btn = instance->data & 0xFF; +} + +uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_dooya_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_dooya_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +/** + * Get button name. + * @param btn Button number, 8 bit + */ +static const char* subghz_protocol_dooya_get_name_button(uint8_t btn) { + const char* btn_name; + switch(btn) { + case 0b00010001: + btn_name = "Up_Long"; + break; + case 0b00011110: + btn_name = "Up_Short"; + break; + case 0b00110011: + btn_name = "Down_Long"; + break; + case 0b00111100: + btn_name = "Down_Short"; + break; + case 0b01010101: + btn_name = "Stop"; + break; + case 0b01111001: + btn_name = "Up+Down"; + break; + case 0b10000000: + btn_name = "Up+Stop"; + break; + case 0b10000001: + btn_name = "Down+Stop"; + break; + case 0b11001100: + btn_name = "P2"; + break; + default: + btn_name = "Unknown"; + break; + } + return btn_name; +} + +void subghz_protocol_decoder_dooya_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderDooya* instance = context; + + subghz_protocol_somfy_telis_check_remote_controller(&instance->generic); + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%010llX\r\n" + "Sn:0x%08lX\r\n" + "Btn:%s\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + instance->generic.data, + instance->generic.serial, + subghz_protocol_dooya_get_name_button(instance->generic.btn)); + if(instance->generic.cnt == DOYA_SINGLE_CHANNEL) { + furi_string_cat_printf(output, "Ch:Single\r\n"); + } else { + furi_string_cat_printf(output, "Ch:%lu\r\n", instance->generic.cnt); + } +} diff --git a/lib/subghz/protocols/dooya.h b/lib/subghz/protocols/dooya.h new file mode 100644 index 000000000..f0cf843c0 --- /dev/null +++ b/lib/subghz/protocols/dooya.h @@ -0,0 +1,107 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_DOOYA_NAME "Dooya" + +typedef struct SubGhzProtocolDecoderDooya SubGhzProtocolDecoderDooya; +typedef struct SubGhzProtocolEncoderDooya SubGhzProtocolEncoderDooya; + +extern const SubGhzProtocolDecoder subghz_protocol_dooya_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_dooya_encoder; +extern const SubGhzProtocol subghz_protocol_dooya; + +/** + * Allocate SubGhzProtocolEncoderDooya. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderDooya* pointer to a SubGhzProtocolEncoderDooya instance + */ +void* subghz_protocol_encoder_dooya_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderDooya. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + */ +void subghz_protocol_encoder_dooya_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + */ +void subghz_protocol_encoder_dooya_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderDooya instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_dooya_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderDooya. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderDooya* pointer to a SubGhzProtocolDecoderDooya instance + */ +void* subghz_protocol_decoder_dooya_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + */ +void subghz_protocol_decoder_dooya_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + */ +void subghz_protocol_decoder_dooya_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_dooya_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_dooya_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderDooya. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderDooya instance + * @param output Resulting text + */ +void subghz_protocol_decoder_dooya_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index aaf573a57..a0970de4d 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -520,11 +520,14 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur subghz_protocol_keeloq_const.te_delta)) { // Found end TX instance->decoder.parser_step = KeeloqDecoderStepReset; - if(instance->decoder.decode_count_bit >= - subghz_protocol_keeloq_const.min_count_bit_for_found) { + if((instance->decoder.decode_count_bit >= + subghz_protocol_keeloq_const.min_count_bit_for_found) && + (instance->decoder.decode_count_bit <= + subghz_protocol_keeloq_const.min_count_bit_for_found + 2)) { if(instance->generic.data != instance->decoder.decode_data) { instance->generic.data = instance->decoder.decode_data; - instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->generic.data_count_bit = + subghz_protocol_keeloq_const.min_count_bit_for_found; if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); } @@ -541,6 +544,8 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur if(instance->decoder.decode_count_bit < subghz_protocol_keeloq_const.min_count_bit_for_found) { subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else { + instance->decoder.decode_count_bit++; } instance->decoder.parser_step = KeeloqDecoderStepSaveDuration; } else if( @@ -551,6 +556,8 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur if(instance->decoder.decode_count_bit < subghz_protocol_keeloq_const.min_count_bit_for_found) { subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else { + instance->decoder.decode_count_bit++; } instance->decoder.parser_step = KeeloqDecoderStepSaveDuration; } else { diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c new file mode 100644 index 000000000..2c8de0d2d --- /dev/null +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -0,0 +1,336 @@ +#include "kinggates_stylo_4k.h" +#include "keeloq_common.h" + +#include "../subghz_keystore.h" +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocoKingGates_stylo_4k" + +static const SubGhzBlockConst subghz_protocol_kinggates_stylo_4k_const = { + .te_short = 400, + .te_long = 1100, + .te_delta = 140, + .min_count_bit_for_found = 89, +}; + +struct SubGhzProtocolDecoderKingGates_stylo_4k { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint64_t data; + uint16_t header_count; + SubGhzKeystore* keystore; +}; + +struct SubGhzProtocolEncoderKingGates_stylo_4k { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + KingGates_stylo_4kDecoderStepReset = 0, + KingGates_stylo_4kDecoderStepCheckPreambula, + KingGates_stylo_4kDecoderStepCheckStartBit, + KingGates_stylo_4kDecoderStepSaveDuration, + KingGates_stylo_4kDecoderStepCheckDuration, +} KingGates_stylo_4kDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder = { + .alloc = subghz_protocol_decoder_kinggates_stylo_4k_alloc, + .free = subghz_protocol_decoder_kinggates_stylo_4k_free, + + .feed = subghz_protocol_decoder_kinggates_stylo_4k_feed, + .reset = subghz_protocol_decoder_kinggates_stylo_4k_reset, + + .get_hash_data = subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data, + .serialize = subghz_protocol_decoder_kinggates_stylo_4k_serialize, + .deserialize = subghz_protocol_decoder_kinggates_stylo_4k_deserialize, + .get_string = subghz_protocol_decoder_kinggates_stylo_4k_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol subghz_protocol_kinggates_stylo_4k = { + .name = SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME, + .type = SubGhzProtocolTypeDynamic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &subghz_protocol_kinggates_stylo_4k_decoder, + .encoder = &subghz_protocol_kinggates_stylo_4k_encoder, +}; + +void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderKingGates_stylo_4k* instance = + malloc(sizeof(SubGhzProtocolDecoderKingGates_stylo_4k)); + instance->base.protocol = &subghz_protocol_kinggates_stylo_4k; + instance->generic.protocol_name = instance->base.protocol->name; + instance->keystore = subghz_environment_get_keystore(environment); + return instance; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + free(instance); +} + +void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + + switch(instance->decoder.parser_step) { + case KingGates_stylo_4kDecoderStepReset: + if((level) && DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckPreambula; + instance->header_count++; + } + break; + case KingGates_stylo_4kDecoderStepCheckPreambula: + if((!level) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta)) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + break; + } + if((instance->header_count > 2) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long * 2) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) { + // Found header + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckStartBit; + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepCheckStartBit: + if((level) && + DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short * 2) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepSaveDuration: + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_kinggates_stylo_4k_const.te_long * 3)) { + if(instance->decoder.decode_count_bit == + subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) { + instance->generic.data = instance->data; + instance->data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->decoder.decode_data = 0; + instance->data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + break; + } else { + instance->decoder.te_last = duration; + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepCheckDuration; + } + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + case KingGates_stylo_4kDecoderStepCheckDuration: + if(level) { + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_long) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_kinggates_stylo_4k_const.te_long) < + subghz_protocol_kinggates_stylo_4k_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_kinggates_stylo_4k_const.te_short) < + subghz_protocol_kinggates_stylo_4k_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + if(instance->decoder.decode_count_bit == 53) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } + } else { + instance->decoder.parser_step = KingGates_stylo_4kDecoderStepReset; + instance->header_count = 0; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + * @param file_name Full path to rainbow table the file + */ +static void subghz_protocol_kinggates_stylo_4k_remote_controller( + SubGhzBlockGeneric* instance, + uint64_t data, + SubGhzKeystore* keystore) { + /** + * 9500us 12*(400/400) 2200/800|1-bit|0-bit| + * _ _ _ __ ___ _ + * ________| |_| |_..._| |_____| |_| |___| |..... + * + * 1-bit 400/1100 us + * 0-bit 1100/400 us + * + * The package consists of 89 bits of data, LSB first + * Data - 1C9037F0C80000 CE280BA00 + * S[3] S[2] 1 key S[1] S[0] 2 byte always 0 Hop[3] Hop[2] Hop[1] Hop[0] 0 + * 11100100 10000001 1 0111 11110000 11001000 00000000 00000000 11001110 00101000 00001011 10100000 0000 + * + * Encryption - keeloq Simple Learning + * key C S[3] CNT + * Decrypt - 0xEC270B9C => 0x E C 27 0B9C + * + * + * +*/ + + uint32_t hop = subghz_protocol_blocks_reverse_key(data >> 4, 32); + uint64_t fix = subghz_protocol_blocks_reverse_key(instance->data, 53); + bool ret = false; + uint32_t decrypt = 0; + instance->btn = (fix >> 17) & 0x0F; + instance->serial = ((fix >> 5) & 0xFFFF0000) | (fix & 0xFFFF); + + for + M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { + if(manufacture_code->type == KEELOQ_LEARNING_SIMPLE) { + decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); + if(((decrypt >> 28) == instance->btn) && (((decrypt >> 24) & 0x0F) == 0x0C) && + (((decrypt >> 16) & 0xFF) == (instance->serial & 0xFF))) { + ret = true; + break; + } + } + } + if(ret) { + instance->cnt = decrypt & 0xFFFF; + } else { + instance->btn = 0; + instance->serial = 0; + instance->cnt = 0; + } +} + +uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; + } + + if(res && !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Data"); + res = false; + } + return res; + + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Missing Data"); + break; + } + for(uint8_t i = 0; i < sizeof(uint64_t); i++) { + instance->data = instance->data << 8 | key_data[i]; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; + subghz_protocol_kinggates_stylo_4k_remote_controller( + &instance->generic, instance->data, instance->keystore); + + furi_string_cat_printf( + output, + "%s\r\n" + "Key:0x%llX%07llX %dbit\r\n" + "Sn:0x%08lX Btn:0x%01X\r\n" + "Cnt:0x%04lX\r\n", + instance->generic.protocol_name, + instance->generic.data, + instance->data, + instance->generic.data_count_bit, + instance->generic.serial, + instance->generic.btn, + instance->generic.cnt); +} diff --git a/lib/subghz/protocols/kinggates_stylo_4k.h b/lib/subghz/protocols/kinggates_stylo_4k.h new file mode 100644 index 000000000..c9f1cf380 --- /dev/null +++ b/lib/subghz/protocols/kinggates_stylo_4k.h @@ -0,0 +1,74 @@ +#pragma once +#include "base.h" + +#define SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME "KingGates Stylo4k" + +typedef struct SubGhzProtocolDecoderKingGates_stylo_4k SubGhzProtocolDecoderKingGates_stylo_4k; +typedef struct SubGhzProtocolEncoderKingGates_stylo_4k SubGhzProtocolEncoderKingGates_stylo_4k; + +extern const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_kinggates_stylo_4k_encoder; +extern const SubGhzProtocol subghz_protocol_kinggates_stylo_4k; + +/** + * Allocate SubGhzProtocolDecoderKingGates_stylo_4k. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderKingGates_stylo_4k* pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void* subghz_protocol_decoder_kinggates_stylo_4k_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void subghz_protocol_decoder_kinggates_stylo_4k_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + */ +void subghz_protocol_decoder_kinggates_stylo_4k_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_kinggates_stylo_4k_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderKingGates_stylo_4k. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance + * @param output Resulting text + */ +void subghz_protocol_decoder_kinggates_stylo_4k_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/linear_delta3.c b/lib/subghz/protocols/linear_delta3.c new file mode 100644 index 000000000..869edac84 --- /dev/null +++ b/lib/subghz/protocols/linear_delta3.c @@ -0,0 +1,359 @@ +#include "linear_delta3.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolLinearDelta3" + +#define DIP_PATTERN "%c%c%c%c%c%c%c%c" +#define DATA_TO_DIP(dip) \ + (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), \ + (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), \ + (dip & 0x0002 ? '1' : '0'), (dip & 0x0001 ? '1' : '0') + +static const SubGhzBlockConst subghz_protocol_linear_delta3_const = { + .te_short = 500, + .te_long = 2000, + .te_delta = 150, + .min_count_bit_for_found = 8, +}; + +struct SubGhzProtocolDecoderLinearDelta3 { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint32_t last_data; +}; + +struct SubGhzProtocolEncoderLinearDelta3 { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + LinearDecoderStepReset = 0, + LinearDecoderStepSaveDuration, + LinearDecoderStepCheckDuration, +} LinearDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder = { + .alloc = subghz_protocol_decoder_linear_delta3_alloc, + .free = subghz_protocol_decoder_linear_delta3_free, + + .feed = subghz_protocol_decoder_linear_delta3_feed, + .reset = subghz_protocol_decoder_linear_delta3_reset, + + .get_hash_data = subghz_protocol_decoder_linear_delta3_get_hash_data, + .serialize = subghz_protocol_decoder_linear_delta3_serialize, + .deserialize = subghz_protocol_decoder_linear_delta3_deserialize, + .get_string = subghz_protocol_decoder_linear_delta3_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder = { + .alloc = subghz_protocol_encoder_linear_delta3_alloc, + .free = subghz_protocol_encoder_linear_delta3_free, + + .deserialize = subghz_protocol_encoder_linear_delta3_deserialize, + .stop = subghz_protocol_encoder_linear_delta3_stop, + .yield = subghz_protocol_encoder_linear_delta3_yield, +}; + +const SubGhzProtocol subghz_protocol_linear_delta3 = { + .name = SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_linear_delta3_decoder, + .encoder = &subghz_protocol_linear_delta3_encoder, +}; + +void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderLinearDelta3* instance = + malloc(sizeof(SubGhzProtocolEncoderLinearDelta3)); + + instance->base.protocol = &subghz_protocol_linear_delta3; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 16; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_linear_delta3_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderLinearDelta3* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @return true On success + */ +static bool + subghz_protocol_encoder_linear_delta3_get_upload(SubGhzProtocolEncoderLinearDelta3* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2); + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short); + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 7); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + } + } + //Send end bit + if(bit_read(instance->generic.data, 0)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_short); + //Send PT_GUARD + instance->encoder.upload[index] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 73); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_linear_delta3_const.te_long); + //Send PT_GUARD + instance->encoder.upload[index] = level_duration_make( + false, (uint32_t)subghz_protocol_linear_delta3_const.te_short * 70); + } + + return true; +} + +bool subghz_protocol_encoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderLinearDelta3* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_linear_delta3_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_linear_delta3_stop(void* context) { + SubGhzProtocolEncoderLinearDelta3* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context) { + SubGhzProtocolEncoderLinearDelta3* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderLinearDelta3* instance = + malloc(sizeof(SubGhzProtocolDecoderLinearDelta3)); + instance->base.protocol = &subghz_protocol_linear_delta3; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_linear_delta3_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + free(instance); +} + +void subghz_protocol_decoder_linear_delta3_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + instance->decoder.parser_step = LinearDecoderStepReset; + instance->last_data = 0; +} + +void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + switch(instance->decoder.parser_step) { + case LinearDecoderStepReset: + if((!level) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 70) < + subghz_protocol_linear_delta3_const.te_delta * 24)) { + //Found header Linear + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } + break; + case LinearDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = LinearDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + break; + case LinearDecoderStepCheckDuration: + if(!level) { + if(duration >= (subghz_protocol_linear_delta3_const.te_short * 10)) { + instance->decoder.parser_step = LinearDecoderStepReset; + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) < + subghz_protocol_linear_delta3_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } + if(instance->decoder.decode_count_bit == + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + if((instance->last_data == instance->decoder.decode_data) && + instance->last_data) { + instance->generic.serial = 0x0; + instance->generic.btn = 0x0; + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + instance->last_data = instance->decoder.decode_data; + } + break; + } + + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_short) < + subghz_protocol_linear_delta3_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_short * 7) < + subghz_protocol_linear_delta3_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_linear_delta3_const.te_long) < + subghz_protocol_linear_delta3_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = LinearDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + + } else { + instance->decoder.parser_step = LinearDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8)); +} + +bool subghz_protocol_decoder_linear_delta3_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool subghz_protocol_decoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_linear_delta3_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderLinearDelta3* instance = context; + + uint32_t data = instance->generic.data & 0xFF; + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX\r\n" + "DIP:" DIP_PATTERN "\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + data, + DATA_TO_DIP(data)); +} diff --git a/lib/subghz/protocols/linear_delta3.h b/lib/subghz/protocols/linear_delta3.h new file mode 100644 index 000000000..2f0a32e68 --- /dev/null +++ b/lib/subghz/protocols/linear_delta3.h @@ -0,0 +1,111 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME "LinearDelta3" + +typedef struct SubGhzProtocolDecoderLinearDelta3 SubGhzProtocolDecoderLinearDelta3; +typedef struct SubGhzProtocolEncoderLinearDelta3 SubGhzProtocolEncoderLinearDelta3; + +extern const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_linear_delta3_encoder; +extern const SubGhzProtocol subghz_protocol_linear_delta3; + +/** + * Allocate SubGhzProtocolEncoderLinearDelta3. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderLinearDelta3* pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void* subghz_protocol_encoder_linear_delta3_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void subghz_protocol_encoder_linear_delta3_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + */ +void subghz_protocol_encoder_linear_delta3_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_linear_delta3_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderLinearDelta3. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderLinearDelta3* pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void* subghz_protocol_decoder_linear_delta3_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void subghz_protocol_decoder_linear_delta3_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + */ +void subghz_protocol_decoder_linear_delta3_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_linear_delta3_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_linear_delta3_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderLinearDelta3. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_linear_delta3_deserialize( + void* context, + FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance + * @param output Resulting text + */ +void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 5ca95901d..6447676cc 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -14,6 +14,9 @@ #define TAG "SubGhzProtocolNiceFlorS" +#define NICE_ONE_COUNT_BIT 72 +#define NICE_ONE_NAME "Nice One" + static const SubGhzBlockConst subghz_protocol_nice_flor_s_const = { .te_short = 500, .te_long = 1000, @@ -28,6 +31,7 @@ struct SubGhzProtocolDecoderNiceFlorS { SubGhzBlockGeneric generic; const char* nice_flor_s_rainbow_table_file_name; + uint64_t data; }; struct SubGhzProtocolEncoderNiceFlorS { @@ -243,6 +247,64 @@ LevelDuration subghz_protocol_encoder_nice_flor_s_yield(void* context) { return ret; } +// /** +// * Read bytes from rainbow table +// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10 +// * @return crc +// */ +// static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) { +// uint8_t crc = 0; +// uint8_t crc_data = 0xff; +// for(uint8_t i = 4; i < 68; i++) { +// if(subghz_protocol_blocks_get_bit_array(p, i)) { +// crc = crc_data ^ 1; +// } else { +// crc = crc_data; +// } +// crc_data >>= 1; +// if((crc & 0x01)) { +// crc_data ^= 0x97; +// } +// } +// crc = 0; +// for(uint8_t i = 0; i < 8; i++) { +// crc <<= 1; +// if((crc_data >> i) & 0x01) crc = crc | 1; +// } +// return crc; +// } + +// /** +// * Read bytes from rainbow table +// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX +// * @param num_parcel parcel number 0..15 +// * @param hold_bit 0 - the button was only pressed, 1 - the button was held down +// */ +// static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) { +// uint8_t k = 0; +// uint8_t crc = 0; +// p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4); +// if(num_parcel < 4) { +// k = 0x8f; +// } else { +// k = 0x80; +// } + +// if(!hold_bit) { +// hold_bit = 0; +// } else { +// hold_bit = 0x10; +// } +// k = num_parcel ^ k; +// p[7] = k; +// p[8] = hold_bit ^ (k << 4); + +// crc = subghz_protocol_nice_one_crc(p); + +// p[8] |= crc >> 4; +// p[9] = crc << 4; +// } + /** * Read bytes from rainbow table * @param file_name Full path to rainbow table the file @@ -427,10 +489,14 @@ void subghz_protocol_decoder_nice_flor_s_feed(void* context, bool level, uint32_ subghz_protocol_nice_flor_s_const.te_delta) { //Found STOP bit instance->decoder.parser_step = NiceFlorSDecoderStepReset; - if(instance->decoder.decode_count_bit == - subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { - instance->generic.data = instance->decoder.decode_data; + if((instance->decoder.decode_count_bit == + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) || + (instance->decoder.decode_count_bit == NICE_ONE_COUNT_BIT)) { + instance->generic.data = instance->data; + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = instance->generic.data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; + if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); } @@ -464,6 +530,11 @@ void subghz_protocol_decoder_nice_flor_s_feed(void* context, bool level, uint32_ } else { instance->decoder.parser_step = NiceFlorSDecoderStepReset; } + if(instance->decoder.decode_count_bit == + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { + instance->data = instance->decoder.decode_data; + instance->decoder.decode_data = 0; + } break; } } @@ -477,6 +548,7 @@ static void subghz_protocol_nice_flor_s_remote_controller( SubGhzBlockGeneric* instance, const char* file_name) { /* + * Protocol Nice Flor-S * Packet format Nice Flor-s: START-P0-P1-P2-P3-P4-P5-P6-P7-STOP * P0 (4-bit) - button positional code - 1:0x1, 2:0x2, 3:0x4, 4:0x8; * P1 (4-bit) - batch repetition number, calculated by the formula: @@ -497,6 +569,24 @@ static void subghz_protocol_nice_flor_s_remote_controller( * data => 0x1c5783607f7b3 key serial cnt * decrypt => 0x10436c6820444 => 0x1 0436c682 0444 * + * Protocol Nice One + * Generally repeats the Nice Flor-S protocol, but there are a few changes + * Packet format first 52 bytes repeat Nice Flor-S protocol + * The additional 20 bytes contain the code of the pressed button, + * the button hold bit and the CRC of the entire message. + * START-P0-P1-P2-P3-P4-P5-P6-P7-P8-P9-P10-STOP + * P7 (byte) - if (n<4) k=0x8f : k=0x80; P7= k^n; + * P8 (byte) - if (hold bit) b=0x00 : b=0x10; P8= b^(k<<4) | 4 hi bit crc + * P10 (4-bit) - 4 lo bit crc + * key+b crc + * data => 0x1724A7D9A522F 899 D6 hold bit = 0 - just pressed the button + * data => 0x1424A7D9A522F 8AB 03 hold bit = 1 - button hold + * + * A small button hold counter (0..15) is stored between each press, + * i.e. if 1 press of the button stops counter 6, then the next press + * of the button will start from the value 7 (hold bit = 0), 8 (hold bit = 1)... + * further up to 15 with overflow + * */ if(!file_name) { instance->cnt = 0; @@ -523,7 +613,15 @@ bool subghz_protocol_decoder_nice_flor_s_serialize( SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; - return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + if(res && + !flipper_format_write_uint32(flipper_format, "Data", (uint32_t*)&instance->data, 1)) { + FURI_LOG_E(TAG, "Unable to add Data"); + res = false; + } + } + return res; } bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { @@ -534,11 +632,25 @@ bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperForma if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { break; } - if(instance->generic.data_count_bit != - subghz_protocol_nice_flor_s_const.min_count_bit_for_found) { + if((instance->generic.data_count_bit != + subghz_protocol_nice_flor_s_const.min_count_bit_for_found) && + (instance->generic.data_count_bit != NICE_ONE_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); break; } + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint32_t temp = 0; + if(!flipper_format_read_uint32(flipper_format, "Data", (uint32_t*)&temp, 1)) { + FURI_LOG_E(TAG, "Missing Data"); + break; + } + instance->data = (uint64_t)temp; + } + ret = true; } while(false); return ret; @@ -550,20 +662,33 @@ void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* o subghz_protocol_nice_flor_s_remote_controller( &instance->generic, instance->nice_flor_s_rainbow_table_file_name); - uint32_t code_found_hi = instance->generic.data >> 32; - uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; - furi_string_cat_printf( - output, - "%s %dbit\r\n" - "Key:0x%lX%08lX\r\n" - "Sn:%05lX\r\n" - "Cnt:%04lX Btn:%02X\r\n", - instance->generic.protocol_name, - instance->generic.data_count_bit, - code_found_hi, - code_found_lo, - instance->generic.serial, - instance->generic.cnt, - instance->generic.btn); + if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%013llX%llX\r\n" + "Sn:%05lX\r\n" + "Cnt:%04lX Btn:%02X\r\n", + NICE_ONE_NAME, + instance->generic.data_count_bit, + instance->generic.data, + instance->data, + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } else { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%013llX\r\n" + "Sn:%05lX\r\n" + "Cnt:%04lX Btn:%02X\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + instance->generic.data, + instance->generic.serial, + instance->generic.cnt, + instance->generic.btn); + } } diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 5f733d6bd..96717e56f 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -1,21 +1,50 @@ #include "protocol_items.h" const SubGhzProtocol* subghz_protocol_registry_items[] = { - &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, - &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, - &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, - &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, - &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, - &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, - &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, - &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, - &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_pocsag, - &subghz_protocol_smc5326, &subghz_protocol_holtek_th12x, + &subghz_protocol_gate_tx, + &subghz_protocol_keeloq, + &subghz_protocol_star_line, + &subghz_protocol_nice_flo, + &subghz_protocol_came, + &subghz_protocol_faac_slh, + &subghz_protocol_nice_flor_s, + &subghz_protocol_came_twee, + &subghz_protocol_came_atomo, + &subghz_protocol_nero_sketch, + &subghz_protocol_ido, + &subghz_protocol_kia, + &subghz_protocol_hormann, + &subghz_protocol_nero_radio, + &subghz_protocol_somfy_telis, + &subghz_protocol_somfy_keytis, + &subghz_protocol_scher_khan, + &subghz_protocol_princeton, + &subghz_protocol_raw, + &subghz_protocol_linear, + &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, + &subghz_protocol_megacode, + &subghz_protocol_holtek, + &subghz_protocol_chamb_code, + &subghz_protocol_power_smart, + &subghz_protocol_marantec, + &subghz_protocol_bett, + &subghz_protocol_doitrand, + &subghz_protocol_phoenix_v2, + &subghz_protocol_honeywell_wdb, + &subghz_protocol_magellan, + &subghz_protocol_intertechno_v3, + &subghz_protocol_clemsa, + &subghz_protocol_ansonic, + &subghz_protocol_pocsag, + &subghz_protocol_smc5326, + &subghz_protocol_holtek_th12x, + &subghz_protocol_linear_delta3, + &subghz_protocol_dooya, + &subghz_protocol_alutech_at_4n, + &subghz_protocol_kinggates_stylo_4k, }; const SubGhzProtocolRegistry subghz_protocol_registry = { .items = subghz_protocol_registry_items, - .size = COUNT_OF(subghz_protocol_registry_items)}; \ No newline at end of file + .size = COUNT_OF(subghz_protocol_registry_items)}; diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 55a1ea860..362b0459a 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -21,6 +21,7 @@ #include "gate_tx.h" #include "raw.h" #include "linear.h" +#include "linear_delta3.h" #include "secplus_v2.h" #include "secplus_v1.h" #include "megacode.h" @@ -39,6 +40,9 @@ #include "pocsag.h" #include "smc5326.h" #include "holtek_ht12x.h" +#include "dooya.h" +#include "alutech_at_4n.h" +#include "kinggates_stylo_4k.h" #ifdef __cplusplus extern "C" { diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 9c3afeb46..3ef95db36 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -606,7 +606,7 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* ou furi_string_cat_printf( output, "Sn:0x%08lX\r\n" - "Cnt:0x%03lX\r\n" + "Cnt:0x%03lX " "Sw_id:0x%X\r\n", instance->generic.serial, instance->generic.cnt, @@ -625,7 +625,7 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* ou furi_string_cat_printf( output, "Sn:0x%08lX\r\n" - "Cnt:0x%03lX\r\n" + "Cnt:0x%03lX " "Sw_id:0x%X\r\n", instance->generic.serial, instance->generic.cnt, diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index 63a3e26d2..ab9202cc3 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -55,25 +55,40 @@ const SubGhzProtocolDecoder subghz_protocol_somfy_keytis_decoder = { .get_string = subghz_protocol_decoder_somfy_keytis_get_string, }; -const SubGhzProtocolEncoder subghz_protocol_somfy_keytis_encoder = { - .alloc = NULL, - .free = NULL, - - .deserialize = NULL, - .stop = NULL, - .yield = NULL, -}; - const SubGhzProtocol subghz_protocol_somfy_keytis = { .name = SUBGHZ_PROTOCOL_SOMFY_KEYTIS_NAME, .type = SubGhzProtocolTypeDynamic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_AM | - SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Save, + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, .decoder = &subghz_protocol_somfy_keytis_decoder, .encoder = &subghz_protocol_somfy_keytis_encoder, }; +const SubGhzProtocolEncoder subghz_protocol_somfy_keytis_encoder = { + .alloc = subghz_protocol_encoder_somfy_keytis_alloc, + .free = subghz_protocol_encoder_somfy_keytis_free, + + .deserialize = subghz_protocol_encoder_somfy_keytis_deserialize, + .stop = subghz_protocol_encoder_somfy_keytis_stop, + .yield = subghz_protocol_encoder_somfy_keytis_yield, +}; + +void* subghz_protocol_encoder_somfy_keytis_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderSomfyKeytis* instance = malloc(sizeof(SubGhzProtocolEncoderSomfyKeytis)); + + instance->base.protocol = &subghz_protocol_somfy_keytis; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 512; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + + return instance; +} + void* subghz_protocol_decoder_somfy_keytis_alloc(SubGhzEnvironment* environment) { UNUSED(environment); SubGhzProtocolDecoderSomfyKeytis* instance = malloc(sizeof(SubGhzProtocolDecoderSomfyKeytis)); @@ -83,6 +98,13 @@ void* subghz_protocol_decoder_somfy_keytis_alloc(SubGhzEnvironment* environment) return instance; } +void subghz_protocol_encoder_somfy_keytis_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderSomfyKeytis* instance = context; + free(instance->encoder.upload); + free(instance); +} + void subghz_protocol_decoder_somfy_keytis_free(void* context) { furi_assert(context); SubGhzProtocolDecoderSomfyKeytis* instance = context; @@ -100,6 +122,330 @@ void subghz_protocol_decoder_somfy_keytis_reset(void* context) { NULL); } +static bool + subghz_protocol_somfy_keytis_gen_data(SubGhzProtocolEncoderSomfyKeytis* instance, uint8_t btn) { + UNUSED(btn); + uint64_t data = instance->generic.data ^ (instance->generic.data >> 8); + instance->generic.btn = (data >> 48) & 0xF; + instance->generic.cnt = (data >> 24) & 0xFFFF; + instance->generic.serial = data & 0xFFFFFF; + + if(instance->generic.cnt < 0xFFFF) { + instance->generic.cnt++; + } else if(instance->generic.cnt >= 0xFFFF) { + instance->generic.cnt = 0; + } + + uint8_t frame[10]; + frame[0] = (0xA << 4) | instance->generic.btn; + frame[1] = 0xF << 4; + frame[2] = instance->generic.cnt >> 8; + frame[3] = instance->generic.cnt; + frame[4] = instance->generic.serial >> 16; + frame[5] = instance->generic.serial >> 8; + frame[6] = instance->generic.serial; + frame[7] = 0xC4; + frame[8] = 0x00; + frame[9] = 0x19; + + uint8_t checksum = 0; + for(uint8_t i = 0; i < 7; i++) { + checksum = checksum ^ frame[i] ^ (frame[i] >> 4); + } + checksum &= 0xF; + + frame[1] |= checksum; + + for(uint8_t i = 1; i < 7; i++) { + frame[i] ^= frame[i - 1]; + } + data = 0; + for(uint8_t i = 0; i < 7; ++i) { + data <<= 8; + data |= frame[i]; + } + instance->generic.data = data; + data = 0; + for(uint8_t i = 7; i < 10; ++i) { + data <<= 8; + data |= frame[i]; + } + instance->generic.data_2 = data; + return true; +} + +bool subghz_protocol_somfy_keytis_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolEncoderSomfyKeytis* instance = context; + instance->generic.serial = serial; + instance->generic.cnt = cnt; + instance->generic.data_count_bit = 80; + bool res = subghz_protocol_somfy_keytis_gen_data(instance, btn); + if(res) { + res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + } + return res; +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance + * @return true On success + */ +static bool subghz_protocol_encoder_somfy_keytis_get_upload( + SubGhzProtocolEncoderSomfyKeytis* instance, + uint8_t btn) { + furi_assert(instance); + + //gen new key + if(subghz_protocol_somfy_keytis_gen_data(instance, btn)) { + //ToDo if you need to add a callback to automatically update the data on the display + } else { + return false; + } + + size_t index = 0; + + //Send header + //Wake up + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)9415); // 1 + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)89565); // 0 + //Hardware sync + for(uint8_t i = 0; i < 12; ++i) { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 4); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 4); // 0 + } + //Software sync + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)4550); // 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + + //Send key data MSB manchester + + for(uint8_t i = instance->generic.data_count_bit - 24; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } + } + } + + for(uint8_t i = 24; i > 0; i--) { + if(bit_read(instance->generic.data_2, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } + } + } + + //Inter-frame silence + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration += + (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 3; + } else { + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 3); + } + + for(uint8_t i = 0; i < 2; ++i) { + //Hardware sync + for(uint8_t i = 0; i < 6; ++i) { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 4); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 4); // 0 + } + //Software sync + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)4550); // 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + + //Send key data MSB manchester + + for(uint8_t i = instance->generic.data_count_bit - 24; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } + } + } + + for(uint8_t i = 24; i > 0; i--) { + if(bit_read(instance->generic.data_2, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short); // 0 + } + } + } + //Inter-frame silence + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration += + (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 3; + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 3); + } + } + + //Inter-frame silence + instance->encoder.upload[index - 1].duration += + (uint32_t)30415 - (uint32_t)subghz_protocol_somfy_keytis_const.te_short * 3; + + size_t size_upload = index; + + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + return true; +} + +bool subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderSomfyKeytis* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_somfy_keytis_get_upload(instance, instance->generic.btn); + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; + } + if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Key"); + break; + } + + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_somfy_keytis_stop(void* context) { + SubGhzProtocolEncoderSomfyKeytis* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_somfy_keytis_yield(void* context) { + SubGhzProtocolEncoderSomfyKeytis* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + /** * Сhecksum calculation. * @param data Вata for checksum calculation diff --git a/lib/subghz/protocols/somfy_keytis.h b/lib/subghz/protocols/somfy_keytis.h index 3b5950611..b08da3641 100644 --- a/lib/subghz/protocols/somfy_keytis.h +++ b/lib/subghz/protocols/somfy_keytis.h @@ -11,6 +11,58 @@ extern const SubGhzProtocolDecoder subghz_protocol_somfy_keytis_decoder; extern const SubGhzProtocolEncoder subghz_protocol_somfy_keytis_encoder; extern const SubGhzProtocol subghz_protocol_somfy_keytis; +/** + * Allocate SubGhzProtocolEncoderSomfyKeytis. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderSomfyKeytis* pointer to a SubGhzProtocolEncoderSomfyKeytis instance + */ +void* subghz_protocol_encoder_somfy_keytis_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderSomfyKeytis. + * @param context Pointer to a SubGhzProtocolEncoderSomfyKeytis instance + */ +void subghz_protocol_encoder_somfy_keytis_free(void* context); + +/** + * Key generation from simple data. + * @param context Pointer to a SubGhzProtocolEncoderSomfyKeytis instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param serial Serial number, 24 bit + * @param btn Button number, 8 bit + * @param cnt Counter value, 16 bit + * @param preset Modulation, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_somfy_keytis_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderSomfyKeytis instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderSomfyKeytis instance + */ +void subghz_protocol_encoder_somfy_keytis_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderSomfyKeytis instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_somfy_keytis_yield(void* context); + /** * Allocate SubGhzProtocolDecoderSomfyKeytis. * @param environment Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 945a88405..96997c581 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -55,24 +55,301 @@ const SubGhzProtocolDecoder subghz_protocol_somfy_telis_decoder = { }; const SubGhzProtocolEncoder subghz_protocol_somfy_telis_encoder = { - .alloc = NULL, - .free = NULL, + .alloc = subghz_protocol_encoder_somfy_telis_alloc, + .free = subghz_protocol_encoder_somfy_telis_free, - .deserialize = NULL, - .stop = NULL, - .yield = NULL, + .deserialize = subghz_protocol_encoder_somfy_telis_deserialize, + .stop = subghz_protocol_encoder_somfy_telis_stop, + .yield = subghz_protocol_encoder_somfy_telis_yield, }; const SubGhzProtocol subghz_protocol_somfy_telis = { .name = SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME, .type = SubGhzProtocolTypeDynamic, .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_AM | - SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Save, + SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, .decoder = &subghz_protocol_somfy_telis_decoder, .encoder = &subghz_protocol_somfy_telis_encoder, }; +void* subghz_protocol_encoder_somfy_telis_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderSomfyTelis* instance = malloc(sizeof(SubGhzProtocolEncoderSomfyTelis)); + + instance->base.protocol = &subghz_protocol_somfy_telis; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 512; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + + return instance; +} + +void subghz_protocol_encoder_somfy_telis_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderSomfyTelis* instance = context; + free(instance->encoder.upload); + free(instance); +} + +static bool + subghz_protocol_somfy_telis_gen_data(SubGhzProtocolEncoderSomfyTelis* instance, uint8_t btn) { + UNUSED(btn); + uint64_t data = instance->generic.data ^ (instance->generic.data >> 8); + instance->generic.btn = (data >> 44) & 0xF; // ctrl + instance->generic.cnt = (data >> 24) & 0xFFFF; // rolling code + instance->generic.serial = data & 0xFFFFFF; // address + + if(instance->generic.cnt < 0xFFFF) { + instance->generic.cnt++; + } else if(instance->generic.cnt >= 0xFFFF) { + instance->generic.cnt = 0; + } + + uint8_t frame[7]; + frame[0] = data >> 48; + frame[1] = instance->generic.btn << 4; + frame[2] = instance->generic.cnt >> 8; + frame[3] = instance->generic.cnt; + frame[4] = instance->generic.serial >> 16; + frame[5] = instance->generic.serial >> 8; + frame[6] = instance->generic.serial; + + uint8_t checksum = 0; + for(uint8_t i = 0; i < 7; i++) { + checksum = checksum ^ frame[i] ^ (frame[i] >> 4); + } + checksum &= 0xF; + + frame[1] |= checksum; + + for(uint8_t i = 1; i < 7; i++) { + frame[i] ^= frame[i - 1]; + } + data = 0; + for(uint8_t i = 0; i < 7; ++i) { + data <<= 8; + data |= frame[i]; + } + instance->generic.data = data; + return true; +} + +bool subghz_protocol_somfy_telis_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolEncoderSomfyTelis* instance = context; + instance->generic.serial = serial; + instance->generic.cnt = cnt; + instance->generic.data_count_bit = 56; + bool res = subghz_protocol_somfy_telis_gen_data(instance, btn); + if(res) { + res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + } + return res; +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance + * @return true On success + */ +static bool subghz_protocol_encoder_somfy_telis_get_upload( + SubGhzProtocolEncoderSomfyTelis* instance, + uint8_t btn) { + furi_assert(instance); + + //gen new key + if(subghz_protocol_somfy_telis_gen_data(instance, btn)) { + //ToDo if you need to add a callback to automatically update the data on the display + } else { + return false; + } + + size_t index = 0; + + //Send header + //Wake up + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)9415); // 1 + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)89565); // 0 + //Hardware sync + for(uint8_t i = 0; i < 2; ++i) { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short * 4); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short * 4); // 0 + } + //Software sync + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)4550); // 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + + //Send key data MSB manchester + + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + } + } + } + + //Inter-frame silence + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration += (uint32_t)30415; + } else { + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)30415); + } + + //Retransmission + for(uint8_t i = 0; i < 2; i++) { + //Hardware sync + for(uint8_t i = 0; i < 7; ++i) { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short * 4); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short * 4); // 0 + } + //Software sync + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)4550); // 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + + //Send key data MSB manchester + + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration *= 2; // 00 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + } else { + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + } + + } else { + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_HIGH) { + instance->encoder.upload[index - 1].duration *= 2; // 11 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + } else { + instance->encoder.upload[index++] = level_duration_make( + true, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 1 + instance->encoder.upload[index++] = level_duration_make( + false, (uint32_t)subghz_protocol_somfy_telis_const.te_short); // 0 + } + } + } + + //Inter-frame silence + if(instance->encoder.upload[index - 1].level == LEVEL_DURATION_LEVEL_LOW) { + instance->encoder.upload[index - 1].duration += (uint32_t)30415; + } else { + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)30415); + } + } + + size_t size_upload = index; + + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + return true; +} + +bool subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderSomfyTelis* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_somfy_telis_get_upload(instance, instance->generic.btn); + + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; + } + if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to add Key"); + break; + } + + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_somfy_telis_stop(void* context) { + SubGhzProtocolEncoderSomfyTelis* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_somfy_telis_yield(void* context) { + SubGhzProtocolEncoderSomfyTelis* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + void* subghz_protocol_decoder_somfy_telis_alloc(SubGhzEnvironment* environment) { UNUSED(environment); SubGhzProtocolDecoderSomfyTelis* instance = malloc(sizeof(SubGhzProtocolDecoderSomfyTelis)); @@ -299,9 +576,9 @@ static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGener */ uint64_t data = instance->data ^ (instance->data >> 8); - instance->btn = (data >> 44) & 0xF; - instance->cnt = (data >> 24) & 0xFFFF; - instance->serial = data & 0xFFFFFF; + instance->btn = (data >> 44) & 0xF; // ctrl + instance->cnt = (data >> 24) & 0xFFFF; // rolling code + instance->serial = data & 0xFFFFFF; // address } /** @@ -309,7 +586,7 @@ static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGener * @param btn Button number, 4 bit */ static const char* subghz_protocol_somfy_telis_get_name_button(uint8_t btn) { - const char* name_btn[0x10] = { + const char* name_btn[16] = { "Unknown", "My", "Up", @@ -368,7 +645,6 @@ void subghz_protocol_decoder_somfy_telis_get_string(void* context, FuriString* o SubGhzProtocolDecoderSomfyTelis* instance = context; subghz_protocol_somfy_telis_check_remote_controller(&instance->generic); - furi_string_cat_printf( output, "%s %db\r\n" diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index a6a9fa5b2..b5e989866 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -11,6 +11,58 @@ extern const SubGhzProtocolDecoder subghz_protocol_somfy_telis_decoder; extern const SubGhzProtocolEncoder subghz_protocol_somfy_telis_encoder; extern const SubGhzProtocol subghz_protocol_somfy_telis; +/** + * Allocate SubGhzProtocolEncoderSomfyTelis. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderSomfyTelis* pointer to a SubGhzProtocolEncoderSomfyTelis instance + */ +void* subghz_protocol_encoder_somfy_telis_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderSomfyTelis. + * @param context Pointer to a SubGhzProtocolEncoderSomfyTelis instance + */ +void subghz_protocol_encoder_somfy_telis_free(void* context); + +/** + * Key generation from simple data. + * @param context Pointer to a SubGhzProtocolEncoderSomfyTelis instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param serial Serial number, 24 bit + * @param btn Button number, 8 bit + * @param cnt Counter value, 16 bit + * @param preset Modulation, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_somfy_telis_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderSomfyTelis instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderSomfyTelis instance + */ +void subghz_protocol_encoder_somfy_telis_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderSomfyTelis instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_somfy_telis_yield(void* context); + /** * Allocate SubGhzProtocolDecoderSomfyTelis. * @param environment Pointer to a SubGhzEnvironment instance diff --git a/lib/subghz/subghz_setting.c b/lib/subghz/subghz_setting.c index 733fc35b5..35ba54a8a 100644 --- a/lib/subghz/subghz_setting.c +++ b/lib/subghz/subghz_setting.c @@ -39,6 +39,7 @@ static const uint32_t subghz_frequency_list[] = { 330000000, 345000000, 348000000, + 350000000, /* 387 - 464 */ 387000000, @@ -75,10 +76,10 @@ static const uint32_t subghz_frequency_list[] = { }; static const uint32_t subghz_hopper_frequency_list[] = { - 310000000, 315000000, - 318000000, + 330000000, 390000000, + 433420000, 433920000, 868350000, 0, diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 42124bebc..205cc2752 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -70,7 +70,7 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* furi_delay_tick(1); } //waiting for reception to complete - while(furi_hal_gpio_read(&gpio_cc1101_g0)) { + while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) { furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); @@ -104,14 +104,16 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si furi_hal_subghz_write_packet(data, size); furi_hal_subghz_tx(); //start send instance->status = SubGhzTxRxWorkerStatusTx; - while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted + while(!furi_hal_gpio_read( + furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be set -> sync transmitted furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); break; } } - while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet + while(furi_hal_gpio_read( + furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be cleared -> end of packet furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); @@ -134,7 +136,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { furi_hal_subghz_idle(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync); //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_set_frequency_and_path(instance->frequency); furi_hal_subghz_flush_rx(); diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 6c34dc728..1b8ef6a14 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -90,6 +90,7 @@ typedef enum { SubGhzProtocolFlag_Save = (1 << 7), SubGhzProtocolFlag_Load = (1 << 8), SubGhzProtocolFlag_Send = (1 << 9), + SubGhzProtocolFlag_BinRAW = (1 << 10), } SubGhzProtocolFlag; typedef struct { From 17db80794cc6c40c3d8d052049fafe8f75ba6418 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 18:46:40 +0000 Subject: [PATCH 29/34] Better asset pack git ignore --- .gitignore | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index dd487d0ce..bf7addba9 100644 --- a/.gitignore +++ b/.gitignore @@ -68,8 +68,13 @@ PVS-Studio.log # Automate files, etc automate.py deployments/ -assets/dolphin/custom/ -assets/resources/dolphin_custom/ fbt_options.py commitnotes.md lib/STM32CubeWB + +# Asset packs +assets/dolphin/custom/* +!assets/dolphin/custom/WatchDogs/ +!assets/dolphin/custom/ReadMe.md +assets/resources/dolphin_custom/* +!assets/resources/dolphin_custom/WatchDogs/ From dfb6e9daa6d52fa672864dae7733ac337a3081a7 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 19:04:53 +0000 Subject: [PATCH 30/34] Fix spi header --- .../targets/furi_hal_include/furi_hal_spi.h | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/firmware/targets/furi_hal_include/furi_hal_spi.h b/firmware/targets/furi_hal_include/furi_hal_spi.h index 9c54befb4..af15a8838 100644 --- a/firmware/targets/furi_hal_include/furi_hal_spi.h +++ b/firmware/targets/furi_hal_include/furi_hal_spi.h @@ -16,6 +16,9 @@ void furi_hal_spi_config_deinit_early(); /** Initialize SPI HAL */ void furi_hal_spi_config_init(); +/** Initialize SPI DMA HAL */ +void furi_hal_spi_dma_init(); + /** Initialize SPI Bus * * @param handle pointer to FuriHalSpiBus instance @@ -71,6 +74,38 @@ bool furi_hal_spi_bus_rx( size_t size, uint32_t timeout); +/** SPI Transmit + * + * @param handle pointer to FuriHalSpiBusHandle instance + * @param buffer transmit buffer + * @param size transaction size (buffer size) + * @param timeout operation timeout in ms + * + * @return true on success + */ +bool furi_hal_spi_bus_tx( + FuriHalSpiBusHandle* handle, + const uint8_t* buffer, + size_t size, + uint32_t timeout); + +/** SPI Transmit and Receive + * + * @param handle pointer to FuriHalSpiBusHandle instance + * @param tx_buffer pointer to tx buffer + * @param rx_buffer pointer to rx buffer + * @param size transaction size (buffer size) + * @param timeout operation timeout in ms + * + * @return true on success + */ +bool furi_hal_spi_bus_trx( + FuriHalSpiBusHandle* handle, + const uint8_t* tx_buffer, + uint8_t* rx_buffer, + size_t size, + uint32_t timeout); + /** SPI Transmit and Receive with DMA * * @param handle pointer to FuriHalSpiBusHandle instance @@ -90,4 +125,4 @@ bool furi_hal_spi_bus_trx_dma( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif From 7474ac193e863063137da392d533cbd6218b1d65 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 19:15:35 +0000 Subject: [PATCH 31/34] Kinda fix subghz gpio pin shenanigans --- lib/subghz/subghz_tx_rx_worker.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 205cc2752..42124bebc 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -70,7 +70,7 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* furi_delay_tick(1); } //waiting for reception to complete - while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) { + while(furi_hal_gpio_read(&gpio_cc1101_g0)) { furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); @@ -104,16 +104,14 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si furi_hal_subghz_write_packet(data, size); furi_hal_subghz_tx(); //start send instance->status = SubGhzTxRxWorkerStatusTx; - while(!furi_hal_gpio_read( - furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be set -> sync transmitted + while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); break; } } - while(furi_hal_gpio_read( - furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be cleared -> end of packet + while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); @@ -136,7 +134,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { furi_hal_subghz_idle(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync); //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_set_frequency_and_path(instance->frequency); furi_hal_subghz_flush_rx(); From 55d18eb8a4e2c03857b6790c6b30d30c4a7e9337 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 19:37:19 +0000 Subject: [PATCH 32/34] Kinda fix subghz protocols linker issues --- lib/subghz/SConscript | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 8fbec94ad..6d091114b 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -11,7 +11,6 @@ env.Append( File("subghz_tx_rx_worker.h"), File("transmitter.h"), File("registry.h"), - File("protocols/protocol_items.h"), File("protocols/raw.h"), File("blocks/const.h"), File("blocks/decoder.h"), From 5afe51589637fa8b4d227e1a8c3627a93896d53f Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 19:44:34 +0000 Subject: [PATCH 33/34] Fix missing canvas custom font api --- applications/services/gui/canvas.c | 6 ++++++ applications/services/gui/canvas.h | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 6a2bd3537..ee472138e 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -140,6 +140,12 @@ void canvas_set_font(Canvas* canvas, Font font) { } } +void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font) { + furi_assert(canvas); + u8g2_SetFontMode(&canvas->fb, 1); + u8g2_SetFont(&canvas->fb, font); +} + void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { furi_assert(canvas); if(!str) return; diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index 9c03ef59a..9fb554be2 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -147,6 +147,13 @@ void canvas_invert_color(Canvas* canvas); */ void canvas_set_font(Canvas* canvas, Font font); +/** Set custom drawing font + * + * @param canvas Canvas instance + * @param font Pointer to u8g2 const uint8_t* font array + */ +void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font); + /** Draw string at position of baseline defined by x, y. * * @param canvas Canvas instance From 8b1179794916cdf54d3e6a6d8bd1685c014a9ec7 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Thu, 9 Feb 2023 19:53:25 +0000 Subject: [PATCH 34/34] Fix api symbols --- firmware/targets/f7/api_symbols.csv | 640 +--------------------------- 1 file changed, 5 insertions(+), 635 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3a687f32e..a38fe72fe 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,14.0,, +Version,v,15.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -178,7 +178,6 @@ Header,+,lib/subghz/blocks/encoder.h,, Header,+,lib/subghz/blocks/generic.h,, Header,+,lib/subghz/blocks/math.h,, Header,+,lib/subghz/environment.h,, -Header,+,lib/subghz/protocols/protocol_items.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/registry.h,, @@ -535,8 +534,6 @@ Function,-,atoff,float,const char* Function,+,atoi,int,const char* Function,-,atol,long,const char* Function,-,atoll,long long,const char* -Function,-,atomo_decrypt,void,uint8_t* -Function,-,atomo_encrypt,void,uint8_t* Function,-,basename,char*,const char* Function,-,bcmp,int,"const void*, const void*, size_t" Function,-,bcopy,void,"const void*, void*, size_t" @@ -645,6 +642,7 @@ Function,+,canvas_invert_color,void,Canvas* Function,+,canvas_reset,void,Canvas* Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool" Function,+,canvas_set_color,void,"Canvas*, Color" +Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,-,canvas_set_orientation,void,"Canvas*, CanvasOrientation" @@ -1348,10 +1346,13 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus* Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t" Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t" +Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t" Function,-,furi_hal_spi_config_deinit_early,void, Function,-,furi_hal_spi_config_init,void, Function,-,furi_hal_spi_config_init_early,void, +Function,+,furi_hal_spi_dma_init,void, Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* Function,-,furi_hal_subghz_dump_state,void, Function,+,furi_hal_subghz_flush_rx,void, @@ -1745,8 +1746,6 @@ Function,-,j1f,float,float Function,-,jn,double,"int, double" Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] -Function,-,keeloq_reset_kl_type,void, -Function,-,keeloq_reset_mfname,void, Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] @@ -2506,8 +2505,6 @@ Function,+,srand,void,unsigned Function,-,srand48,void,long Function,-,srandom,void,unsigned Function,+,sscanf,int,"const char*, const char*, ..." -Function,-,star_line_reset_kl_type,void, -Function,-,star_line_reset_mfname,void, Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*" Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" @@ -2689,275 +2686,11 @@ Function,+,subghz_protocol_blocks_parity_bytes,uint8_t,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t" Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t" Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t" -Function,+,subghz_protocol_decoder_alutech_at_4n_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_alutech_at_4n_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_decoder_alutech_at_4n_feed,void,"void*, _Bool, uint32_t" -Function,+,subghz_protocol_decoder_alutech_at_4n_free,void,void* -Function,+,subghz_protocol_decoder_alutech_at_4n_get_hash_data,uint8_t,void* -Function,+,subghz_protocol_decoder_alutech_at_4n_get_string,void,"void*, FuriString*" -Function,+,subghz_protocol_decoder_alutech_at_4n_reset,void,void* -Function,+,subghz_protocol_decoder_alutech_at_4n_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_ansonic_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_ansonic_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_ansonic_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_ansonic_free,void,void* -Function,-,subghz_protocol_decoder_ansonic_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_ansonic_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_ansonic_reset,void,void* -Function,-,subghz_protocol_decoder_ansonic_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" -Function,-,subghz_protocol_decoder_bett_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_bett_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_bett_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_bett_free,void,void* -Function,-,subghz_protocol_decoder_bett_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_bett_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_bett_reset,void,void* -Function,-,subghz_protocol_decoder_bett_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_came_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_came_atomo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_came_atomo_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_came_atomo_free,void,void* -Function,-,subghz_protocol_decoder_came_atomo_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_came_atomo_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_came_atomo_reset,void,void* -Function,-,subghz_protocol_decoder_came_atomo_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_came_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_came_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_came_free,void,void* -Function,-,subghz_protocol_decoder_came_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_came_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_came_reset,void,void* -Function,-,subghz_protocol_decoder_came_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_came_twee_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_came_twee_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_came_twee_free,void,void* -Function,-,subghz_protocol_decoder_came_twee_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_came_twee_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_came_twee_reset,void,void* -Function,-,subghz_protocol_decoder_came_twee_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_chamb_code_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_chamb_code_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_chamb_code_free,void,void* -Function,-,subghz_protocol_decoder_chamb_code_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_chamb_code_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_chamb_code_reset,void,void* -Function,-,subghz_protocol_decoder_chamb_code_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_clemsa_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_clemsa_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_clemsa_free,void,void* -Function,-,subghz_protocol_decoder_clemsa_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_clemsa_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_clemsa_reset,void,void* -Function,-,subghz_protocol_decoder_clemsa_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_doitrand_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_doitrand_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_doitrand_free,void,void* -Function,-,subghz_protocol_decoder_doitrand_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_doitrand_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_doitrand_reset,void,void* -Function,-,subghz_protocol_decoder_doitrand_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,+,subghz_protocol_decoder_dooya_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_decoder_dooya_feed,void,"void*, _Bool, uint32_t" -Function,+,subghz_protocol_decoder_dooya_free,void,void* -Function,+,subghz_protocol_decoder_dooya_get_hash_data,uint8_t,void* -Function,+,subghz_protocol_decoder_dooya_get_string,void,"void*, FuriString*" -Function,+,subghz_protocol_decoder_dooya_reset,void,void* -Function,+,subghz_protocol_decoder_dooya_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_faac_slh_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_faac_slh_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_faac_slh_free,void,void* -Function,-,subghz_protocol_decoder_faac_slh_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_faac_slh_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_faac_slh_reset,void,void* -Function,-,subghz_protocol_decoder_faac_slh_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_gate_tx_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_gate_tx_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_gate_tx_free,void,void* -Function,-,subghz_protocol_decoder_gate_tx_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_gate_tx_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_gate_tx_reset,void,void* -Function,-,subghz_protocol_decoder_gate_tx_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_holtek_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_holtek_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_holtek_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_holtek_free,void,void* -Function,-,subghz_protocol_decoder_holtek_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_holtek_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_holtek_reset,void,void* -Function,-,subghz_protocol_decoder_holtek_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_holtek_th12x_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_holtek_th12x_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_holtek_th12x_free,void,void* -Function,-,subghz_protocol_decoder_holtek_th12x_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_holtek_th12x_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_holtek_th12x_reset,void,void* -Function,-,subghz_protocol_decoder_holtek_th12x_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_honeywell_wdb_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_honeywell_wdb_free,void,void* -Function,-,subghz_protocol_decoder_honeywell_wdb_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_honeywell_wdb_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_honeywell_wdb_reset,void,void* -Function,-,subghz_protocol_decoder_honeywell_wdb_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_hormann_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_hormann_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_hormann_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_hormann_free,void,void* -Function,-,subghz_protocol_decoder_hormann_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_hormann_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_hormann_reset,void,void* -Function,-,subghz_protocol_decoder_hormann_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_ido_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_ido_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_ido_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_ido_free,void,void* -Function,-,subghz_protocol_decoder_ido_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_ido_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_ido_reset,void,void* -Function,-,subghz_protocol_decoder_ido_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_intertechno_v3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_intertechno_v3_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_intertechno_v3_free,void,void* -Function,-,subghz_protocol_decoder_intertechno_v3_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_intertechno_v3_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_intertechno_v3_reset,void,void* -Function,-,subghz_protocol_decoder_intertechno_v3_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_keeloq_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_keeloq_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_keeloq_free,void,void* -Function,-,subghz_protocol_decoder_keeloq_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_keeloq_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_keeloq_reset,void,void* -Function,-,subghz_protocol_decoder_keeloq_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_kia_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_kia_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_kia_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_kia_free,void,void* -Function,-,subghz_protocol_decoder_kia_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_kia_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_kia_reset,void,void* -Function,-,subghz_protocol_decoder_kia_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_feed,void,"void*, _Bool, uint32_t" -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_free,void,void* -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data,uint8_t,void* -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_get_string,void,"void*, FuriString*" -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_reset,void,void* -Function,+,subghz_protocol_decoder_kinggates_stylo_4k_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_linear_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_linear_delta3_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_decoder_linear_delta3_feed,void,"void*, _Bool, uint32_t" -Function,+,subghz_protocol_decoder_linear_delta3_free,void,void* -Function,+,subghz_protocol_decoder_linear_delta3_get_hash_data,uint8_t,void* -Function,+,subghz_protocol_decoder_linear_delta3_get_string,void,"void*, FuriString*" -Function,+,subghz_protocol_decoder_linear_delta3_reset,void,void* -Function,+,subghz_protocol_decoder_linear_delta3_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_linear_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_linear_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_linear_free,void,void* -Function,-,subghz_protocol_decoder_linear_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_linear_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_linear_reset,void,void* -Function,-,subghz_protocol_decoder_linear_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_magellan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_magellan_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_magellan_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_magellan_free,void,void* -Function,-,subghz_protocol_decoder_magellan_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_magellan_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_magellan_reset,void,void* -Function,-,subghz_protocol_decoder_magellan_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_marantec_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_marantec_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_marantec_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_marantec_free,void,void* -Function,-,subghz_protocol_decoder_marantec_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_marantec_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_marantec_reset,void,void* -Function,-,subghz_protocol_decoder_marantec_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_megacode_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_megacode_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_megacode_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_megacode_free,void,void* -Function,-,subghz_protocol_decoder_megacode_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_megacode_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_megacode_reset,void,void* -Function,-,subghz_protocol_decoder_megacode_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_nero_radio_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_nero_radio_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_nero_radio_free,void,void* -Function,-,subghz_protocol_decoder_nero_radio_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_nero_radio_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_nero_radio_reset,void,void* -Function,-,subghz_protocol_decoder_nero_radio_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_nero_sketch_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_nero_sketch_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_nero_sketch_free,void,void* -Function,-,subghz_protocol_decoder_nero_sketch_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_nero_sketch_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_nero_sketch_reset,void,void* -Function,-,subghz_protocol_decoder_nero_sketch_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_nice_flo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_nice_flo_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_nice_flo_free,void,void* -Function,-,subghz_protocol_decoder_nice_flo_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_nice_flo_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_nice_flo_reset,void,void* -Function,-,subghz_protocol_decoder_nice_flo_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_nice_flor_s_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_nice_flor_s_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_nice_flor_s_free,void,void* -Function,-,subghz_protocol_decoder_nice_flor_s_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_nice_flor_s_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_nice_flor_s_reset,void,void* -Function,-,subghz_protocol_decoder_nice_flor_s_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_phoenix_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_phoenix_v2_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_phoenix_v2_free,void,void* -Function,-,subghz_protocol_decoder_phoenix_v2_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_phoenix_v2_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_phoenix_v2_reset,void,void* -Function,-,subghz_protocol_decoder_phoenix_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_power_smart_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_power_smart_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_power_smart_free,void,void* -Function,-,subghz_protocol_decoder_power_smart_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_power_smart_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_power_smart_reset,void,void* -Function,-,subghz_protocol_decoder_power_smart_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,+,subghz_protocol_decoder_princeton_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_princeton_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_decoder_princeton_feed,void,"void*, _Bool, uint32_t" -Function,+,subghz_protocol_decoder_princeton_free,void,void* -Function,+,subghz_protocol_decoder_princeton_get_hash_data,uint8_t,void* -Function,+,subghz_protocol_decoder_princeton_get_string,void,"void*, FuriString*" -Function,+,subghz_protocol_decoder_princeton_reset,void,void* -Function,+,subghz_protocol_decoder_princeton_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" @@ -2969,248 +2702,12 @@ Function,+,subghz_protocol_decoder_raw_serialize,_Bool,"void*, FlipperFormat*, S Function,+,subghz_protocol_decoder_raw_set_auto_mode,void,"void*, _Bool" Function,+,subghz_protocol_decoder_raw_set_rssi_threshold,void,"void*, int" Function,+,subghz_protocol_decoder_raw_write_data,_Bool,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_scher_khan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_scher_khan_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_scher_khan_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_scher_khan_free,void,void* -Function,-,subghz_protocol_decoder_scher_khan_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_scher_khan_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_scher_khan_reset,void,void* -Function,-,subghz_protocol_decoder_scher_khan_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_secplus_v1_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_secplus_v1_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_secplus_v1_free,void,void* -Function,-,subghz_protocol_decoder_secplus_v1_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_secplus_v1_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_secplus_v1_reset,void,void* -Function,-,subghz_protocol_decoder_secplus_v1_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_secplus_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_secplus_v2_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_secplus_v2_free,void,void* -Function,-,subghz_protocol_decoder_secplus_v2_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_secplus_v2_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_secplus_v2_reset,void,void* -Function,-,subghz_protocol_decoder_secplus_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_smc5326_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_smc5326_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_smc5326_free,void,void* -Function,-,subghz_protocol_decoder_smc5326_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_smc5326_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_smc5326_reset,void,void* -Function,-,subghz_protocol_decoder_smc5326_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_somfy_keytis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_somfy_keytis_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_somfy_keytis_free,void,void* -Function,-,subghz_protocol_decoder_somfy_keytis_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_somfy_keytis_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_somfy_keytis_reset,void,void* -Function,-,subghz_protocol_decoder_somfy_keytis_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_somfy_telis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_somfy_telis_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_somfy_telis_free,void,void* -Function,-,subghz_protocol_decoder_somfy_telis_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_somfy_telis_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_somfy_telis_reset,void,void* -Function,-,subghz_protocol_decoder_somfy_telis_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_star_line_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_star_line_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_decoder_star_line_feed,void,"void*, _Bool, uint32_t" -Function,-,subghz_protocol_decoder_star_line_free,void,void* -Function,-,subghz_protocol_decoder_star_line_get_hash_data,uint8_t,void* -Function,-,subghz_protocol_decoder_star_line_get_string,void,"void*, FuriString*" -Function,-,subghz_protocol_decoder_star_line_reset,void,void* -Function,-,subghz_protocol_decoder_star_line_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_encoder_ansonic_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_ansonic_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_ansonic_free,void,void* -Function,-,subghz_protocol_encoder_ansonic_stop,void,void* -Function,-,subghz_protocol_encoder_ansonic_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_bett_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_bett_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_bett_free,void,void* -Function,-,subghz_protocol_encoder_bett_stop,void,void* -Function,-,subghz_protocol_encoder_bett_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_came_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_came_atomo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_came_atomo_free,void,void* -Function,-,subghz_protocol_encoder_came_atomo_stop,void,void* -Function,-,subghz_protocol_encoder_came_atomo_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_came_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_came_free,void,void* -Function,-,subghz_protocol_encoder_came_stop,void,void* -Function,-,subghz_protocol_encoder_came_twee_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_came_twee_free,void,void* -Function,-,subghz_protocol_encoder_came_twee_stop,void,void* -Function,-,subghz_protocol_encoder_came_twee_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_came_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_chamb_code_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_chamb_code_free,void,void* -Function,-,subghz_protocol_encoder_chamb_code_stop,void,void* -Function,-,subghz_protocol_encoder_chamb_code_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_clemsa_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_clemsa_free,void,void* -Function,-,subghz_protocol_encoder_clemsa_stop,void,void* -Function,-,subghz_protocol_encoder_clemsa_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_doitrand_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_doitrand_free,void,void* -Function,-,subghz_protocol_encoder_doitrand_stop,void,void* -Function,-,subghz_protocol_encoder_doitrand_yield,LevelDuration,void* -Function,+,subghz_protocol_encoder_dooya_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_encoder_dooya_free,void,void* -Function,+,subghz_protocol_encoder_dooya_stop,void,void* -Function,+,subghz_protocol_encoder_dooya_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_faac_slh_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_faac_slh_free,void,void* -Function,-,subghz_protocol_encoder_faac_slh_stop,void,void* -Function,-,subghz_protocol_encoder_faac_slh_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_gate_tx_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_gate_tx_free,void,void* -Function,-,subghz_protocol_encoder_gate_tx_stop,void,void* -Function,-,subghz_protocol_encoder_gate_tx_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_get_rssi_threshold,int,void* -Function,-,subghz_protocol_encoder_holtek_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_holtek_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_holtek_free,void,void* -Function,-,subghz_protocol_encoder_holtek_stop,void,void* -Function,-,subghz_protocol_encoder_holtek_th12x_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_holtek_th12x_free,void,void* -Function,-,subghz_protocol_encoder_holtek_th12x_stop,void,void* -Function,-,subghz_protocol_encoder_holtek_th12x_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_holtek_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_honeywell_wdb_free,void,void* -Function,-,subghz_protocol_encoder_honeywell_wdb_stop,void,void* -Function,-,subghz_protocol_encoder_honeywell_wdb_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_hormann_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_hormann_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_hormann_free,void,void* -Function,-,subghz_protocol_encoder_hormann_stop,void,void* -Function,-,subghz_protocol_encoder_hormann_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_intertechno_v3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_intertechno_v3_free,void,void* -Function,-,subghz_protocol_encoder_intertechno_v3_stop,void,void* -Function,-,subghz_protocol_encoder_intertechno_v3_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_keeloq_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_keeloq_free,void,void* -Function,-,subghz_protocol_encoder_keeloq_stop,void,void* -Function,-,subghz_protocol_encoder_keeloq_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_linear_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_linear_delta3_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_encoder_linear_delta3_free,void,void* -Function,+,subghz_protocol_encoder_linear_delta3_stop,void,void* -Function,+,subghz_protocol_encoder_linear_delta3_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_linear_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_linear_free,void,void* -Function,-,subghz_protocol_encoder_linear_stop,void,void* -Function,-,subghz_protocol_encoder_linear_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_magellan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_magellan_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_magellan_free,void,void* -Function,-,subghz_protocol_encoder_magellan_stop,void,void* -Function,-,subghz_protocol_encoder_magellan_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_marantec_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_marantec_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_marantec_free,void,void* -Function,-,subghz_protocol_encoder_marantec_stop,void,void* -Function,-,subghz_protocol_encoder_marantec_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_megacode_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_megacode_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_megacode_free,void,void* -Function,-,subghz_protocol_encoder_megacode_stop,void,void* -Function,-,subghz_protocol_encoder_megacode_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_nero_radio_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_nero_radio_free,void,void* -Function,-,subghz_protocol_encoder_nero_radio_stop,void,void* -Function,-,subghz_protocol_encoder_nero_radio_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_nero_sketch_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_nero_sketch_free,void,void* -Function,-,subghz_protocol_encoder_nero_sketch_stop,void,void* -Function,-,subghz_protocol_encoder_nero_sketch_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_nice_flo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_nice_flo_free,void,void* -Function,-,subghz_protocol_encoder_nice_flo_stop,void,void* -Function,-,subghz_protocol_encoder_nice_flo_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_nice_flor_s_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_nice_flor_s_free,void,void* -Function,-,subghz_protocol_encoder_nice_flor_s_stop,void,void* -Function,-,subghz_protocol_encoder_nice_flor_s_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_phoenix_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_phoenix_v2_free,void,void* -Function,-,subghz_protocol_encoder_phoenix_v2_stop,void,void* -Function,-,subghz_protocol_encoder_phoenix_v2_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_power_smart_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_power_smart_free,void,void* -Function,-,subghz_protocol_encoder_power_smart_stop,void,void* -Function,-,subghz_protocol_encoder_power_smart_yield,LevelDuration,void* -Function,+,subghz_protocol_encoder_princeton_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_princeton_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_encoder_princeton_free,void,void* -Function,+,subghz_protocol_encoder_princeton_stop,void,void* -Function,+,subghz_protocol_encoder_princeton_yield,LevelDuration,void* Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" Function,+,subghz_protocol_encoder_raw_free,void,void* Function,+,subghz_protocol_encoder_raw_stop,void,void* Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_secplus_v1_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_secplus_v1_free,void,void* -Function,-,subghz_protocol_encoder_secplus_v1_stop,void,void* -Function,-,subghz_protocol_encoder_secplus_v1_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_secplus_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_secplus_v2_free,void,void* -Function,-,subghz_protocol_encoder_secplus_v2_stop,void,void* -Function,-,subghz_protocol_encoder_secplus_v2_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_smc5326_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_smc5326_free,void,void* -Function,-,subghz_protocol_encoder_smc5326_stop,void,void* -Function,-,subghz_protocol_encoder_smc5326_yield,LevelDuration,void* -Function,+,subghz_protocol_encoder_somfy_keytis_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_encoder_somfy_keytis_free,void,void* -Function,+,subghz_protocol_encoder_somfy_keytis_stop,void,void* -Function,+,subghz_protocol_encoder_somfy_keytis_yield,LevelDuration,void* -Function,+,subghz_protocol_encoder_somfy_telis_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*" -Function,+,subghz_protocol_encoder_somfy_telis_free,void,void* -Function,+,subghz_protocol_encoder_somfy_telis_stop,void,void* -Function,+,subghz_protocol_encoder_somfy_telis_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_star_line_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_star_line_deserialize,_Bool,"void*, FlipperFormat*" -Function,-,subghz_protocol_encoder_star_line_free,void,void* -Function,-,subghz_protocol_encoder_star_line_stop,void,void* -Function,-,subghz_protocol_encoder_star_line_yield,LevelDuration,void* -Function,-,subghz_protocol_faac_slh_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, uint32_t, const char*, SubGhzRadioPreset*" -Function,-,subghz_protocol_keeloq_bft_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, uint32_t, const char*, SubGhzRadioPreset*" -Function,-,subghz_protocol_keeloq_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzRadioPreset*" -Function,-,subghz_protocol_nice_flor_s_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" -Function,-,subghz_protocol_nice_flor_s_encrypt,uint64_t,"uint64_t, const char*" Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* @@ -3220,11 +2717,6 @@ Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* Function,+,subghz_protocol_registry_count,size_t,const SubGhzProtocolRegistry* Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, size_t" Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*" -Function,-,subghz_protocol_secplus_v1_check_fixed,_Bool,uint32_t -Function,-,subghz_protocol_secplus_v2_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzRadioPreset*" -Function,+,subghz_protocol_somfy_keytis_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" -Function,+,subghz_protocol_somfy_telis_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" -Function,-,subghz_protocol_star_line_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzRadioPreset*" Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_free,void,SubGhzReceiver* @@ -4934,131 +4426,9 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence, -Variable,+,subghz_protocol_alutech_at_4n,const SubGhzProtocol, -Variable,+,subghz_protocol_alutech_at_4n_decoder,const SubGhzProtocolDecoder, -Variable,+,subghz_protocol_alutech_at_4n_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_ansonic,const SubGhzProtocol, -Variable,-,subghz_protocol_ansonic_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_ansonic_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_bett,const SubGhzProtocol, -Variable,-,subghz_protocol_bett_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_bett_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_came,const SubGhzProtocol, -Variable,-,subghz_protocol_came_atomo,const SubGhzProtocol, -Variable,-,subghz_protocol_came_atomo_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_came_atomo_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_came_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_came_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_came_twee,const SubGhzProtocol, -Variable,-,subghz_protocol_came_twee_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_came_twee_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_chamb_code,const SubGhzProtocol, -Variable,-,subghz_protocol_chamb_code_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_chamb_code_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_clemsa,const SubGhzProtocol, -Variable,-,subghz_protocol_clemsa_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_clemsa_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_doitrand,const SubGhzProtocol, -Variable,-,subghz_protocol_doitrand_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_doitrand_encoder,const SubGhzProtocolEncoder, -Variable,+,subghz_protocol_dooya,const SubGhzProtocol, -Variable,+,subghz_protocol_dooya_decoder,const SubGhzProtocolDecoder, -Variable,+,subghz_protocol_dooya_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_faac_slh,const SubGhzProtocol, -Variable,-,subghz_protocol_faac_slh_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_faac_slh_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_gate_tx,const SubGhzProtocol, -Variable,-,subghz_protocol_gate_tx_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_gate_tx_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_holtek,const SubGhzProtocol, -Variable,-,subghz_protocol_holtek_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_holtek_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_holtek_th12x,const SubGhzProtocol, -Variable,-,subghz_protocol_holtek_th12x_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_holtek_th12x_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_honeywell_wdb,const SubGhzProtocol, -Variable,-,subghz_protocol_honeywell_wdb_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_honeywell_wdb_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_hormann,const SubGhzProtocol, -Variable,-,subghz_protocol_hormann_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_hormann_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_ido,const SubGhzProtocol, -Variable,-,subghz_protocol_ido_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_ido_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_intertechno_v3,const SubGhzProtocol, -Variable,-,subghz_protocol_intertechno_v3_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_intertechno_v3_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_keeloq,const SubGhzProtocol, -Variable,-,subghz_protocol_keeloq_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_keeloq_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_kia,const SubGhzProtocol, -Variable,-,subghz_protocol_kia_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_kia_encoder,const SubGhzProtocolEncoder, -Variable,+,subghz_protocol_kinggates_stylo_4k,const SubGhzProtocol, -Variable,+,subghz_protocol_kinggates_stylo_4k_decoder,const SubGhzProtocolDecoder, -Variable,+,subghz_protocol_kinggates_stylo_4k_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_linear,const SubGhzProtocol, -Variable,-,subghz_protocol_linear_decoder,const SubGhzProtocolDecoder, -Variable,+,subghz_protocol_linear_delta3,const SubGhzProtocol, -Variable,+,subghz_protocol_linear_delta3_decoder,const SubGhzProtocolDecoder, -Variable,+,subghz_protocol_linear_delta3_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_linear_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_magellan,const SubGhzProtocol, -Variable,-,subghz_protocol_magellan_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_magellan_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_marantec,const SubGhzProtocol, -Variable,-,subghz_protocol_marantec_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_marantec_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_megacode,const SubGhzProtocol, -Variable,-,subghz_protocol_megacode_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_megacode_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_nero_radio,const SubGhzProtocol, -Variable,-,subghz_protocol_nero_radio_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_nero_radio_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_nero_sketch,const SubGhzProtocol, -Variable,-,subghz_protocol_nero_sketch_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_nero_sketch_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_nice_flo,const SubGhzProtocol, -Variable,-,subghz_protocol_nice_flo_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_nice_flo_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_nice_flor_s,const SubGhzProtocol, -Variable,-,subghz_protocol_nice_flor_s_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_nice_flor_s_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_phoenix_v2,const SubGhzProtocol, -Variable,-,subghz_protocol_phoenix_v2_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_phoenix_v2_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_pocsag,const SubGhzProtocol, -Variable,-,subghz_protocol_power_smart,const SubGhzProtocol, -Variable,-,subghz_protocol_power_smart_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_power_smart_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_princeton,const SubGhzProtocol, -Variable,-,subghz_protocol_princeton_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_princeton_encoder,const SubGhzProtocolEncoder, Variable,+,subghz_protocol_raw,const SubGhzProtocol, Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, -Variable,+,subghz_protocol_registry,const SubGhzProtocolRegistry, -Variable,-,subghz_protocol_scher_khan,const SubGhzProtocol, -Variable,-,subghz_protocol_scher_khan_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_scher_khan_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_secplus_v1,const SubGhzProtocol, -Variable,-,subghz_protocol_secplus_v1_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_secplus_v1_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_secplus_v2,const SubGhzProtocol, -Variable,-,subghz_protocol_secplus_v2_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_secplus_v2_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_smc5326,const SubGhzProtocol, -Variable,-,subghz_protocol_smc5326_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_smc5326_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_somfy_keytis,const SubGhzProtocol, -Variable,-,subghz_protocol_somfy_keytis_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_somfy_keytis_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_somfy_telis,const SubGhzProtocol, -Variable,-,subghz_protocol_somfy_telis_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_somfy_telis_encoder,const SubGhzProtocolEncoder, -Variable,-,subghz_protocol_star_line,const SubGhzProtocol, -Variable,-,subghz_protocol_star_line_decoder,const SubGhzProtocolDecoder, -Variable,-,subghz_protocol_star_line_encoder,const SubGhzProtocolEncoder, Variable,-,suboptarg,char*, Variable,-,u8g2_cb_mirror,const u8g2_cb_t, Variable,-,u8g2_cb_r0,const u8g2_cb_t,