From c3532c6d0ed9fadf62ccfb5c89e67c1ba4bd622b Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 9 Mar 2023 21:55:36 +0400 Subject: [PATCH 01/50] [AVR_ISP]: add AVR ISP Programmer FAP --- .../avr_isp_programmer/application.fam | 14 + .../plugins/avr_isp_programmer/avr_isp.png | Bin 0 -> 143 bytes .../plugins/avr_isp_programmer/avr_isp_app.c | 118 ++++ .../avr_isp_programmer/avr_isp_app_i.c | 4 + .../avr_isp_programmer/avr_isp_app_i.h | 44 ++ .../helpers/avr_isp_event.h | 14 + .../avr_isp_programmer/helpers/avr_isp_prog.c | 591 ++++++++++++++++++ .../avr_isp_programmer/helpers/avr_isp_prog.h | 13 + .../helpers/avr_isp_prog_cmd.h | 15 + .../helpers/avr_isp_spi_sw.c | 76 +++ .../helpers/avr_isp_spi_sw.h | 19 + .../helpers/avr_isp_types.h | 48 ++ .../helpers/avr_isp_worker.c | 244 ++++++++ .../helpers/avr_isp_worker.h | 62 ++ .../avr_isp_programmer/images/AvrIspProg.png | Bin 0 -> 1690 bytes .../avr_isp_programmer/scenes/avr_isp_scene.c | 30 + .../avr_isp_programmer/scenes/avr_isp_scene.h | 29 + .../scenes/avr_isp_scene_about.c | 67 ++ .../scenes/avr_isp_scene_config.h | 3 + .../scenes/avr_isp_scene_programmer.c | 38 ++ .../scenes/avr_isp_scene_start.c | 54 ++ .../views/avr_isp_view_programmer.c | 119 ++++ .../views/avr_isp_view_programmer.h | 26 + 23 files changed, 1628 insertions(+) create mode 100644 applications/plugins/avr_isp_programmer/application.fam create mode 100644 applications/plugins/avr_isp_programmer/avr_isp.png create mode 100644 applications/plugins/avr_isp_programmer/avr_isp_app.c create mode 100644 applications/plugins/avr_isp_programmer/avr_isp_app_i.c create mode 100644 applications/plugins/avr_isp_programmer/avr_isp_app_i.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h create mode 100644 applications/plugins/avr_isp_programmer/images/AvrIspProg.png create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h diff --git a/applications/plugins/avr_isp_programmer/application.fam b/applications/plugins/avr_isp_programmer/application.fam new file mode 100644 index 00000000000..2eb8e23761a --- /dev/null +++ b/applications/plugins/avr_isp_programmer/application.fam @@ -0,0 +1,14 @@ +App( + appid="avr_isp", + name="Avr Isp Programmer", + apptype=FlipperAppType.PLUGIN, + targets=["f7"], + entry_point="avr_isp_app", + cdefines=["APP_AVR_ISP"], + requires=["gui"], + stack_size=2 * 1024, + order=20, + fap_icon="avr_isp.png", + fap_category="GPIO", + fap_icon_assets="images", +) diff --git a/applications/plugins/avr_isp_programmer/avr_isp.png b/applications/plugins/avr_isp_programmer/avr_isp.png new file mode 100644 index 0000000000000000000000000000000000000000..2278ce2b61cf97e51720bafb2d07dae48d986560 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>@$__Y43U`H zI>D2R!GMF={pJ7tHnyBWw`O@WO=4vXnQOryxnPsm9sxmyCsV>A?tXRt_DY<&Wq)IO q>DB4a%~XFc{Gk)L^WR4G>Gvdb>|Y;BDpm&?%HZkh=d#Wzp$P!!VJ~6; literal 0 HcmV?d00001 diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app.c b/applications/plugins/avr_isp_programmer/avr_isp_app.c new file mode 100644 index 00000000000..6b9a1e74677 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/avr_isp_app.c @@ -0,0 +1,118 @@ +#include "avr_isp_app_i.h" + +#include +#include + +static bool avr_isp_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + AvrIspApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool avr_isp_app_back_event_callback(void* context) { + furi_assert(context); + AvrIspApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void avr_isp_app_tick_event_callback(void* context) { + furi_assert(context); + AvrIspApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +AvrIspApp* avr_isp_app_alloc() { + AvrIspApp* app = malloc(sizeof(AvrIspApp)); + + // GUI + app->gui = furi_record_open(RECORD_GUI); + + // View Dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&avr_isp_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, avr_isp_app_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, avr_isp_app_back_event_callback); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, avr_isp_app_tick_event_callback, 100); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Open Notification record + app->notifications = furi_record_open(RECORD_NOTIFICATION); + + // // Variable Item List + // app->variable_item_list = variable_item_list_alloc(); + // view_dispatcher_add_view( + // app->view_dispatcher, + // AvrIspViewVariableItemList, + // variable_item_list_get_view(app->variable_item_list)); + + // SubMenu + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, AvrIspViewSubmenu, submenu_get_view(app->submenu)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view(app->view_dispatcher, AvrIspViewWidget, widget_get_view(app->widget)); + + // Programmer view + app->avr_asp_programmer_view = avr_asp_programmer_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + AvrIspViewProgrammer, + avr_asp_programmer_view_get_view(app->avr_asp_programmer_view)); + + scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); + + return app; +} + +void avr_isp_app_free(AvrIspApp* app) { + furi_assert(app); + + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu); + submenu_free(app->submenu); + + // // Variable Item List + // view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewVariableItemList); + // variable_item_list_free(app->variable_item_list); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWidget); + widget_free(app->widget); + + // Programmer view + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer); + avr_asp_programmer_view_free(app->avr_asp_programmer_view); + + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + + // Notifications + furi_record_close(RECORD_NOTIFICATION); + app->notifications = NULL; + + // Close records + furi_record_close(RECORD_GUI); + + free(app); +} + +int32_t avr_isp_app(void* p) { + UNUSED(p); + AvrIspApp* avr_isp_app = avr_isp_app_alloc(); + + view_dispatcher_run(avr_isp_app->view_dispatcher); + + avr_isp_app_free(avr_isp_app); + + return 0; +} diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c new file mode 100644 index 00000000000..2b327f24921 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c @@ -0,0 +1,4 @@ +#include "avr_isp_app_i.h" + +#define TAG "AvrIsp" +#include diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h new file mode 100644 index 00000000000..cf95896a0b6 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h @@ -0,0 +1,44 @@ +#pragma once + +#include "helpers/avr_isp_types.h" + +#include "scenes/avr_isp_scene.h" +#include +#include +#include +#include +#include +#include +//#include + +#include "views/avr_isp_view_programmer.h" + +typedef struct AvrIspApp AvrIspApp; + +// struct AvrIspTxRx { +// SubGhzWorker* worker; + +// SubGhzEnvironment* environment; +// SubGhzReceiver* receiver; +// SubGhzRadioPreset* preset; +// WSHistory* history; +// uint16_t idx_menu_chosen; +// WSTxRxState txrx_state; +// WSHopperState hopper_state; +// uint8_t hopper_timeout; +// uint8_t hopper_idx_frequency; +// WSRxKeyState rx_key_state; +// }; + +//typedef struct AvrIspTxRx AvrIspTxRx; + +struct AvrIspApp { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + NotificationApp* notifications; + //VariableItemList* variable_item_list; + Submenu* submenu; + Widget* widget; + AvrIspProgrammerView* avr_asp_programmer_view; +}; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h new file mode 100644 index 00000000000..71beea7e13c --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h @@ -0,0 +1,14 @@ +#pragma once + +typedef enum { + //AvrIspCustomEvent + AvrIspCustomEventStartId = 100, + + // AvrIspCustomEventSceneSettingLock, + + // AvrIspCustomEventViewReceiverOK, + // AvrIspCustomEventViewReceiverConfig, + // AvrIspCustomEventViewReceiverBack, + // AvrIspCustomEventViewReceiverOffDisplay, + // AvrIspCustomEventViewReceiverUnlock, +} AvrIspCustomEvent; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c new file mode 100644 index 00000000000..26c5c87b148 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c @@ -0,0 +1,591 @@ +#include "avr_isp_prog.h" +#include "avr_isp_prog_cmd.h" + +#include + +#define AVR_ISP_PROG_TX_RX_BUF_SIZE 256 + +struct AvrIspProgParam { + uint8_t devicecode; + uint8_t revision; + uint8_t progtype; + uint8_t parmode; + uint8_t polling; + uint8_t selftimed; + uint8_t lockbytes; + uint8_t fusebytes; + uint8_t flashpoll; + uint16_t eeprompoll; + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; +}; + +typedef struct AvrIspProgParam AvrIspProgParam; + +struct AvrIspProg { + AvrIspSpiSw* spi; + AvrIspProgParam* param; + FuriStreamBuffer* stream_rx; + FuriStreamBuffer* stream_tx; + + uint16_t error; + uint16_t addr; //here + bool pmode; + bool tx_ok; + bool exit; + bool rst_active_high; + uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; + AvrIspSpiSwSpeed spi_speed; +}; + +AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { + AvrIspProg* instance = malloc(sizeof(AvrIspProg)); + instance->param = malloc(sizeof(AvrIspProgParam)); + instance->stream_rx = + furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); + instance->stream_tx = + furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); + instance->spi_speed = spi_speed; + instance->tx_ok = false; + instance->rst_active_high = false; + instance->exit = false; + return instance; +} + +void avr_isp_prog_free(AvrIspProg* instance) { + furi_assert(instance); + + furi_stream_buffer_free(instance->stream_tx); + furi_stream_buffer_free(instance->stream_rx); + free(instance->param); + free(instance); +} + +bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len) { + furi_assert(instance); + furi_assert(data); + furi_assert(len != 0); + size_t ret = furi_stream_buffer_send(instance->stream_rx, data, sizeof(uint8_t) * len, 100); + return ret == sizeof(uint8_t) * len; +} + +size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len) { + furi_assert(instance); + if(!instance->tx_ok) return 0; + size_t len = 0; + if(furi_stream_buffer_bytes_available(instance->stream_tx) > max_len) { + len = furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 100); + } else { + len = furi_stream_buffer_receive( + instance->stream_tx, + data, + sizeof(int8_t) * furi_stream_buffer_bytes_available(instance->stream_tx), + 100); + instance->tx_ok = false; + } + return len; +} + +void avr_isp_prog_exit(AvrIspProg* instance) { + instance->exit = true; +} + +static bool avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) { + furi_assert(instance); + size_t ret = furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), 10); + return ret == sizeof(uint8_t); +} + +static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { + furi_assert(instance); + //ToDo !!!!!!!!!!!!!!! + while(!furi_stream_buffer_bytes_available(instance->stream_rx)) { + furi_delay_ms(5); + if(instance->exit) break; + } + uint8_t data[1] = {0}; + furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 10); + return data[0]; +} + +static void avr_isp_prog_fill(AvrIspProg* instance, size_t len) { + furi_assert(instance); + for(size_t x = 0; x < len; x++) { + instance->buff[x] = avr_isp_prog_getch(instance); + } +} + +static void avr_isp_prog_reset_target(AvrIspProg* instance, bool reset) { + furi_assert(instance); + avr_isp_spi_sw_res_set( + instance->spi, + ((reset && instance->rst_active_high) || (!reset && !instance->rst_active_high)) ? true : + false); +} + +static uint8_t + avr_isp_prog_spi_transaction(AvrIspProg* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + furi_assert(instance); + avr_isp_spi_sw_txrx(instance->spi, a); + avr_isp_spi_sw_txrx(instance->spi, b); + avr_isp_spi_sw_txrx(instance->spi, c); + return avr_isp_spi_sw_txrx(instance->spi, d); +} + +static void avr_isp_prog_empty_reply(AvrIspProg* instance) { + furi_assert(instance); + if(CRC_EOP == avr_isp_prog_getch(instance)) { + avr_isp_prog_tx_ch(instance, STK_INSYNC); + avr_isp_prog_tx_ch(instance, STK_OK); + } else { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } +} + +static void avr_isp_prog_breply(AvrIspProg* instance, uint8_t data) { + furi_assert(instance); + if(CRC_EOP == avr_isp_prog_getch(instance)) { + avr_isp_prog_tx_ch(instance, STK_INSYNC); + avr_isp_prog_tx_ch(instance, data); + avr_isp_prog_tx_ch(instance, STK_OK); + } else { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } +} + +static void avr_isp_prog_get_version(AvrIspProg* instance, uint8_t data) { + furi_assert(instance); + switch(data) { + case 0x80: + avr_isp_prog_breply(instance, HWVER); + break; + case 0x81: + avr_isp_prog_breply(instance, SWMAJ); + break; + case 0x82: + avr_isp_prog_breply(instance, SWMIN); + break; + case 0x93: + avr_isp_prog_breply(instance, 'S'); // serial programmer + break; + default: + avr_isp_prog_breply(instance, 0); + } +} + +static void avr_isp_prog_set_parameters(AvrIspProg* instance) { + furi_assert(instance); + // call this after reading paramter packet into buff[] + instance->param->devicecode = instance->buff[0]; + instance->param->revision = instance->buff[1]; + instance->param->progtype = instance->buff[2]; + instance->param->parmode = instance->buff[3]; + instance->param->polling = instance->buff[4]; + instance->param->selftimed = instance->buff[5]; + instance->param->lockbytes = instance->buff[6]; + instance->param->fusebytes = instance->buff[7]; + instance->param->flashpoll = instance->buff[8]; + // ignore instance->buff[9] (= instance->buff[8]) + // following are 16 bits (big endian) + instance->param->eeprompoll = instance->buff[10] << 8 | + instance->buff[11]; // beget16(&buff[10]); + instance->param->pagesize = instance->buff[12] << 8 | instance->buff[13]; //beget16(&buff[12]); + instance->param->eepromsize = instance->buff[14] << 8 | + instance->buff[15]; //beget16(&buff[14]); + + // 32 bits flashsize (big endian) + instance->param->flashsize = instance->buff[16] << 24 | instance->buff[17] << 16 | + instance->buff[18] << 8 | instance->buff[19]; + //buff[16] * 0x01000000 + buff[17] * 0x00010000 + buff[18] * 0x00000100 + buff[19]; + + // avr devices have active low reset, at89sx are active high + instance->rst_active_high = (instance->param->devicecode >= 0xe0); +} + +static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { + furi_assert(instance); + // Reset target before driving PIN_SCK or PIN_MOSI + + // SPI.begin() will configure SS as output, + // so SPI master mode is selected. + // We have defined RESET as pin 10, + // which for many arduino's is not the SS pin. + // So we have to configure RESET as output here, + // (reset_target() first sets the correct level) + instance->spi = avr_isp_spi_sw_init(instance->spi_speed); + avr_isp_prog_reset_target(instance, true); + + // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": + + // Pulse RESET after PIN_SCK is low: + avr_isp_spi_sw_sck_set(instance->spi, false); + + furi_delay_ms(20); // discharge PIN_SCK, value arbitrally chosen + avr_isp_prog_reset_target(instance, false); + + // Pulse must be minimum 2 target CPU speed cycles + // so 100 usec is ok for CPU speeds above 20KHz + //furi_delay_us(100); + furi_delay_ms(1); + + avr_isp_prog_reset_target(instance, true); + + // Send the enable programming command: + furi_delay_ms(50); // datasheet: must be > 20 msec + avr_isp_prog_spi_transaction(instance, 0xAC, 0x53, 0x00, 0x00); + instance->pmode = true; + return true; +} + +static void avr_isp_prog_end_pmode(AvrIspProg* instance) { + furi_assert(instance); + avr_isp_prog_reset_target(instance, false); + // We're about to take the target out of reset + // so configure SPI pins as input + avr_isp_spi_sw_free(instance->spi); + instance->pmode = false; +} + +static void avr_isp_prog_universal(AvrIspProg* instance) { + furi_assert(instance); + uint8_t data; + + avr_isp_prog_fill(instance, 4); + data = avr_isp_prog_spi_transaction( + instance, instance->buff[0], instance->buff[1], instance->buff[2], instance->buff[3]); + avr_isp_prog_breply(instance, data); +} + +static void avr_isp_prog_flash(AvrIspProg* instance, uint8_t hilo, uint16_t addr, uint8_t data) { + avr_isp_prog_spi_transaction(instance, 0x40 + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data); +} + +static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr) { + // if(PROG_FLICKER) { + // prog_lamp(0); + // } + avr_isp_prog_spi_transaction(instance, 0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); + // if(PROG_FLICKER) { + // delay(PTIME); + // prog_lamp(1); + // } +} + +static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { + if(instance->param->pagesize == 32) { + return instance->addr & 0xFFFFFFF0; + } + if(instance->param->pagesize == 64) { + return instance->addr & 0xFFFFFFE0; + } + if(instance->param->pagesize == 128) { + return instance->addr & 0xFFFFFFC0; + } + if(instance->param->pagesize == 256) { + return instance->addr & 0xFFFFFF80; + } + return instance->addr; +} + +static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t length) { + size_t x = 0; + uint16_t page = avr_isp_prog_current_page(instance); + while(x < length) { + if(page != avr_isp_prog_current_page(instance)) { + avr_isp_prog_commit(instance, page); + page = avr_isp_prog_current_page(instance); + } + avr_isp_prog_flash(instance, 0, instance->addr, instance->buff[x++]); + avr_isp_prog_flash(instance, 1, instance->addr, instance->buff[x++]); + instance->addr++; + } + + avr_isp_prog_commit(instance, page); + + return STK_OK; +} + +static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) { + avr_isp_prog_fill(instance, length); + if(CRC_EOP == avr_isp_prog_getch(instance)) { + avr_isp_prog_tx_ch(instance, STK_INSYNC); + avr_isp_prog_tx_ch(instance, avr_isp_prog_write_flash_pages(instance, length)); + } else { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } +} + +// write (length) bytes, (start) is a byte address +static uint8_t + avr_isp_prog_write_eeprom_chunk(AvrIspProg* instance, uint16_t start, uint16_t length) { + // this writes byte-by-byte, + // page writing may be faster (4 bytes at a time) + avr_isp_prog_fill(instance, length); + //prog_lamp(0); + for(uint16_t x = 0; x < length; x++) { + uint16_t addr = start + x; + avr_isp_prog_spi_transaction( + instance, 0xC0, (addr >> 8) & 0xFF, addr & 0xFF, instance->buff[x]); + furi_delay_ms(45); + } + //prog_lamp(1); + return STK_OK; +} + +static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { + // here is a word address, get the byte address + uint16_t start = instance->addr * 2; + uint16_t remaining = length; + if(length > instance->param->eepromsize) { + instance->error++; + return STK_FAILED; + } + while(remaining > EECHUNK) { + avr_isp_prog_write_eeprom_chunk(instance, start, EECHUNK); + start += EECHUNK; + remaining -= EECHUNK; + } + avr_isp_prog_write_eeprom_chunk(instance, start, remaining); + return STK_OK; +} + +static void avr_isp_prog_program_page(AvrIspProg* instance) { + uint8_t result = STK_FAILED; + unsigned int length = 256 * avr_isp_prog_getch(instance); + length += avr_isp_prog_getch(instance); + uint8_t memtype = avr_isp_prog_getch(instance); + // flash memory @here, (length) bytes + if(memtype == 'F') { //0X46 + avr_isp_prog_write_flash(instance, length); + return; + } + if(memtype == 'E') { //0X45 + result = avr_isp_prog_write_eeprom(instance, length); + if(CRC_EOP == avr_isp_prog_getch(instance)) { + avr_isp_prog_tx_ch(instance, STK_INSYNC); + avr_isp_prog_tx_ch(instance, result); + + } else { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } + return; + } + avr_isp_prog_tx_ch(instance, STK_FAILED); + return; +} + +static uint8_t avr_isp_prog_flash_read(AvrIspProg* instance, uint8_t hilo, uint16_t addr) { + return avr_isp_prog_spi_transaction( + instance, 0x20 + hilo * 8, (addr >> 8) & 0xFF, addr & 0xFF, 0); +} + +static uint8_t avr_isp_prog_flash_read_page(AvrIspProg* instance, uint16_t length) { + for(uint16_t x = 0; x < length; x += 2) { + avr_isp_prog_tx_ch(instance, avr_isp_prog_flash_read(instance, 0, instance->addr)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_flash_read(instance, 1, instance->addr)); + instance->addr++; + } + return STK_OK; +} + +static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t length) { + // here again we have a word address + uint16_t start = instance->addr * 2; + for(uint16_t x = 0; x < length; x++) { + uint16_t addr = start + x; + avr_isp_prog_tx_ch( + instance, + avr_isp_prog_spi_transaction(instance, 0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF)); + } + return STK_OK; +} + +static void avr_isp_prog_read_page(AvrIspProg* instance) { + uint8_t result = (char)STK_FAILED; + int length = 256 * avr_isp_prog_getch(instance); + length += avr_isp_prog_getch(instance); + uint8_t memtype = avr_isp_prog_getch(instance); + if(CRC_EOP != avr_isp_prog_getch(instance)) { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + return; + } + avr_isp_prog_tx_ch(instance, STK_INSYNC); + if(memtype == 'F') result = avr_isp_prog_flash_read_page(instance, length); + if(memtype == 'E') result = avr_isp_prog_eeprom_read_page(instance, length); + avr_isp_prog_tx_ch(instance, result); +} + +static void avr_isp_prog_read_signature(AvrIspProg* instance) { + if(CRC_EOP != avr_isp_prog_getch(instance)) { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + return; + } + avr_isp_prog_tx_ch(instance, STK_INSYNC); + + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x00, 0x00)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x01, 0x00)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x02, 0x00)); + + avr_isp_prog_tx_ch(instance, STK_OK); +} + +void avr_isp_prog_avrisp(AvrIspProg* instance) { + uint8_t ch = avr_isp_prog_getch(instance); + switch(ch) { + case '0': // signon //0x30 + instance->error = 0; + avr_isp_prog_empty_reply(instance); + break; + case '1': //0x31 + if(avr_isp_prog_getch(instance) == CRC_EOP) { + avr_isp_prog_tx_ch(instance, STK_INSYNC); + //SERIAL.print("AVR ISP"); + avr_isp_prog_tx_ch(instance, 'A'); + avr_isp_prog_tx_ch(instance, 'V'); + avr_isp_prog_tx_ch(instance, 'R'); + avr_isp_prog_tx_ch(instance, ' '); + avr_isp_prog_tx_ch(instance, 'I'); + avr_isp_prog_tx_ch(instance, 'S'); + avr_isp_prog_tx_ch(instance, 'P'); + + avr_isp_prog_tx_ch(instance, STK_OK); + } else { + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } + break; + case 'A': //0x41 + avr_isp_prog_get_version(instance, avr_isp_prog_getch(instance)); + break; + case 'B': //0x42 + avr_isp_prog_fill(instance, 20); + avr_isp_prog_set_parameters(instance); + avr_isp_prog_empty_reply(instance); + break; + case 'E': //0x45// extended parameters - ignore for now + avr_isp_prog_fill(instance, 5); + avr_isp_prog_empty_reply(instance); + break; + case 'P': //0X50 + if(!instance->pmode) avr_isp_prog_start_pmode(instance); + avr_isp_prog_empty_reply(instance); + break; + case 'U': //0X55 // set address (word) + instance->addr = avr_isp_prog_getch(instance); + instance->addr += 256 * avr_isp_prog_getch(instance); + avr_isp_prog_empty_reply(instance); + break; + + case 0x60: //STK_PROG_FLASH + avr_isp_prog_getch(instance); // low addr + avr_isp_prog_getch(instance); // high addr + avr_isp_prog_empty_reply(instance); + break; + case 0x61: //STK_PROG_DATA + avr_isp_prog_getch(instance); // data + avr_isp_prog_empty_reply(instance); + break; + + case 0x64: //STK_PROG_PAGE + avr_isp_prog_program_page(instance); + break; + + case 0x74: //STK_READ_PAGE 't' + avr_isp_prog_read_page(instance); + break; + + case 'V': //0x56 + avr_isp_prog_universal(instance); + break; + case 'Q': //0x51 + instance->error = 0; + avr_isp_prog_end_pmode(instance); + avr_isp_prog_empty_reply(instance); + break; + + case 0x75: //STK_READ_SIGN 'U' + avr_isp_prog_read_signature(instance); + break; + + // expecting a command, not CRC_EOP + // this is how we can get back in sync + case CRC_EOP: + instance->error++; + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + break; + + // anything else we will return STK_UNKNOWN + default: + instance->error++; + if(CRC_EOP == avr_isp_prog_getch(instance)) + avr_isp_prog_tx_ch(instance, STK_UNKNOWN); + else + avr_isp_prog_tx_ch(instance, STK_NOSYNC); + } + instance->tx_ok = true; +} + +// // this provides a heartbeat on pin 9, so you can tell the software is running. +// uint8_t hbval = 128; +// int8_t hbdelta = 8; +// void heartbeat() { +// static unsigned long last_time = 0; +// unsigned long now = millis(); +// if ((now - last_time) < 40) +// return; +// last_time = now; +// if (hbval > 192) hbdelta = -hbdelta; +// if (hbval < 32) hbdelta = -hbdelta; +// hbval += hbdelta; +// analogWrite(LED_HB, hbval); +// } + +// static bool rst_active_high; + +// void reset_target(bool reset) { +// digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? 1 : 0); +// } + +// void loop(void) { +// // is pmode active? +// if (pmode) { +// digitalWrite(LED_PMODE, 1); +// } else { +// digitalWrite(LED_PMODE, 0); +// } +// // is there an error? +// if (error) { +// digitalWrite(LED_ERR, 1); +// } else { +// digitalWrite(LED_ERR, 0); +// } + +// // light the heartbeat LED +// heartbeat(); +// if (SERIAL.available()) { +// avrisp(); +// } +// } + +// #define PTIME 30 +// void pulse(int pin, int times) { +// do { +// digitalWrite(pin, 1); +// delay(PTIME); +// digitalWrite(pin, 0); +// delay(PTIME); +// } while(times--); +// } + +// void prog_lamp(int state) { +// if(PROG_FLICKER) { +// digitalWrite(LED_PMODE, state); +// } +// } diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h new file mode 100644 index 00000000000..d44366e7954 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h @@ -0,0 +1,13 @@ +#pragma once + +#include "avr_isp_spi_sw.h" +#include + +typedef struct AvrIspProg AvrIspProg; + +AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed); +void avr_isp_prog_free(AvrIspProg* instance); +bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len); +size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len); +void avr_isp_prog_avrisp(AvrIspProg* instance); +void avr_isp_prog_exit(AvrIspProg* instance); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h new file mode 100644 index 00000000000..4adc5de008b --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h @@ -0,0 +1,15 @@ +#pragma once + +#define HWVER 2 +#define SWMAJ 1 +#define SWMIN 18 + +// STK Definitions +#define STK_OK 0x10 +#define STK_FAILED 0x11 +#define STK_UNKNOWN 0x12 +#define STK_INSYNC 0x14 +#define STK_NOSYNC 0x15 +#define CRC_EOP 0x20 //ok it is a space... + +#define EECHUNK (32) \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c new file mode 100644 index 00000000000..df22550874f --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c @@ -0,0 +1,76 @@ +#include "avr_isp_spi_sw.h" + +#include + +#define AVR_ISP_SPI_SW_MISO &gpio_ext_pa6 +#define AVR_ISP_SPI_SW_MOSI &gpio_ext_pa7 +#define AVR_ISP_SPI_SW_SCK &gpio_ext_pb3 +#define AVR_ISP_RESET &gpio_ext_pa4 + +struct AvrIspSpiSw { + AvrIspSpiSwSpeed speed_wait_time; + const GpioPin* miso; + const GpioPin* mosi; + const GpioPin* sck; + const GpioPin* res; +}; + +AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { + AvrIspSpiSw* instance = malloc(sizeof(AvrIspSpiSw)); + instance->speed_wait_time = speed; + + instance->miso = AVR_ISP_SPI_SW_MISO; + instance->mosi = AVR_ISP_SPI_SW_MOSI; + instance->sck = AVR_ISP_SPI_SW_SCK; + instance->res = AVR_ISP_RESET; + + furi_hal_gpio_init(instance->miso, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_write(instance->mosi, false); + furi_hal_gpio_init(instance->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_write(instance->sck, false); + furi_hal_gpio_init(instance->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + //furi_hal_gpio_write(instance->res, true); + furi_hal_gpio_init(instance->res, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + + return instance; +} + +void avr_isp_spi_sw_free(AvrIspSpiSw* instance) { + furi_assert(instance); + + //furi_hal_gpio_write(instance->res, true); + furi_hal_gpio_init(instance->res, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(instance->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + + free(instance); +} + +uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data) { + furi_assert(instance); + for(uint8_t i = 0; i < 8; ++i) { + furi_hal_gpio_write(instance->mosi, (data & 0x80) ? true : false); + + furi_hal_gpio_write(instance->sck, true); + if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) + furi_delay_us(instance->speed_wait_time - 1); + + data = (data << 1) | furi_hal_gpio_read(instance->miso); + + furi_hal_gpio_write(instance->sck, false); + if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) + furi_delay_us(instance->speed_wait_time - 1); + } + return data; +} + +void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state) { + furi_assert(instance); + furi_hal_gpio_write(instance->res, state); +} + +void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state) { + furi_assert(instance); + furi_hal_gpio_write(instance->sck, state); +} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h new file mode 100644 index 00000000000..fa18999091a --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +typedef enum { + AvrIspSpiSwSpeed1Mhz=0, + AvrIspSpiSwSpeed400Khz=1, + AvrIspSpiSwSpeed250Khz=2, + AvrIspSpiSwSpeed125Khz=4, + AvrIspSpiSwSpeed40Khz=12, +} AvrIspSpiSwSpeed; + +typedef struct AvrIspSpiSw AvrIspSpiSw; + +AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed); +void avr_isp_spi_sw_free(AvrIspSpiSw* instance); +uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data); +void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state); +void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h new file mode 100644 index 00000000000..c0a622e6a57 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#define AVR_ISP_VERSION_APP "0.1" +#define AVR_ISP_DEVELOPED "SkorP" +#define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" + +// #define AVR_ISP_KEY_FILE_VERSION 1 +// #define AVR_ISP_KEY_FILE_TYPE "Flipper Weather Station Key File" + +// /** WSRxKeyState state */ +// typedef enum { +// WSRxKeyStateIDLE, +// WSRxKeyStateBack, +// WSRxKeyStateStart, +// WSRxKeyStateAddKey, +// } WSRxKeyState; + +// /** WSHopperState state */ +// typedef enum { +// WSHopperStateOFF, +// WSHopperStateRunnig, +// WSHopperStatePause, +// WSHopperStateRSSITimeOut, +// } WSHopperState; + +// /** WSLock */ +// typedef enum { +// WSLockOff, +// WSLockOn, +// } WSLock; + +typedef enum { + //AvrIspViewVariableItemList, + AvrIspViewSubmenu, + AvrIspViewProgrammer, + AvrIspViewWidget, +} AvrIspView; + +// /** AvrIspTxRx state */ +// typedef enum { +// WSTxRxStateIDLE, +// WSTxRxStateRx, +// WSTxRxStateTx, +// WSTxRxStateSleep, +// } WSTxRxState; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c new file mode 100644 index 00000000000..65ff149be15 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -0,0 +1,244 @@ +#include "avr_isp_worker.h" +#include "avr_isp_prog.h" +#include "avr_isp_spi_sw.h" + +#include +#include "usb_cdc.h" +#include +#include +#include + +#define TAG "AvrIspWorker" +#define AVR_ISP_VCP_CDC_CH 1 +#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ +#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) + +typedef enum { + WorkerEvtStop = (1 << 0), + WorkerEvtRxDone = (1 << 1), + + WorkerEvtTxStop = (1 << 2), + WorkerEvtCdcRx = (1 << 3), + +} WorkerEvtFlags; + +#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) +#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx) + +typedef enum { + AvrIspWorkerEvtStop = (1 << 0), +} AvrIspWorkerEvt; + +#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) + +struct AvrIspWorker { + //AvrIspProg* prog; + FuriThread* thread; + + AvrIspWorkerUsbConfig cfg; + FuriSemaphore* tx_sem; + + volatile bool worker_running; + // AvrIspWorkerCallback callback; + // void* context; +}; + +// static void vcp_on_cdc_tx_complete(void* context); +// static void vcp_on_cdc_rx(void* context); +// static void vcp_state_callback(void* context, uint8_t state); +// static void vcp_on_cdc_control_line(void* context, uint8_t state); +//static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); + +// static const CdcCallbacks cdc_cb = { +// vcp_on_cdc_tx_complete, +// vcp_on_cdc_rx, +// vcp_state_callback, +// vcp_on_cdc_control_line, +// vcp_on_line_config, +// }; + +// /* VCP callbacks */ + +// static void vcp_on_cdc_tx_complete(void* context) { +// AvrIspWorker* instance = context; +// furi_semaphore_release(instance->tx_sem); +// } + +// static void vcp_on_cdc_rx(void* context) { +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->tx_thread), WorkerEvtCdcRx); +// } + +// static void vcp_state_callback(void* context, uint8_t state) { +// UNUSED(context); +// UNUSED(state); +// } + +// static void vcp_on_cdc_control_line(void* context, uint8_t state) { +// UNUSED(state); +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtCtrlLineSet); +// } + +// static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { +// UNUSED(config); +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtLineCfgSet); +// } + +// +static void avr_isp_worker_vcp_cdc_init(AvrIspWorker* instance) { + UNUSED(instance); + furi_hal_usb_unlock(); + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + //disable callbacks VCP_CDC=0 + furi_hal_cdc_set_callbacks(0, NULL, NULL); + //set 2 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); + + //furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, instance); +} + +static void avr_isp_worker_vcp_cdc_deinit(AvrIspWorker* instance) { + UNUSED(instance); + //disable callbacks AVR_ISP_VCP_CDC_CH + furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); + + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + furi_hal_usb_unlock(); + //set 1 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); +} + +static int32_t avr_isp_worker_prog_thread(void* context) { + AvrIspProg* prog = context; + uint32_t events = 0; + FURI_LOG_I(TAG, "AvrIspProgWorker Start"); + while(1) { + events = furi_thread_flags_get(); + if(events & AvrIspWorkerEvtStop) break; + avr_isp_prog_avrisp(prog); + } + FURI_LOG_I(TAG, "AvrIspProgWorker Stop"); + return 0; +} + +/** Worker thread + * + * @param context + * @return exit code + */ +static int32_t avr_isp_worker_thread(void* context) { + AvrIspWorker* instance = context; + avr_isp_worker_vcp_cdc_init(instance); + + AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed400Khz); + + UNUSED(instance); + uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; + + FuriThread* prog_thread = + furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); + furi_thread_start(prog_thread); + + FURI_LOG_I(TAG, "AvrIspWorker Start"); + while(instance->worker_running) { + furi_delay_ms(1); + + size_t len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + while(len > 0) { + avr_isp_prog_rx(prog, buf, len); + + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "--> %X", buf[i]); + // } + + len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + } + + len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); + while(len > 0) { + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "<-- %X", buf[i]); + // } + + furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); + furi_delay_ms(1); + len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); + } + } + FURI_LOG_I(TAG, "AvrIspWorker Stop"); + furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); + avr_isp_prog_exit(prog); + furi_delay_ms(10); + furi_thread_join(prog_thread); + furi_thread_free(prog_thread); + + avr_isp_prog_free(prog); + avr_isp_worker_vcp_cdc_deinit(instance); + return 0; +} + +AvrIspWorker* avr_isp_worker_alloc(void* context) { + furi_assert(context); + UNUSED(context); + AvrIspWorker* instance = malloc(sizeof(AvrIspWorker)); + + instance->thread = furi_thread_alloc_ex("AvrIspWorker", 2048, avr_isp_worker_thread, instance); + // SubGhz* subghz = context; + // instance->setting = subghz->setting; + return instance; +} + +void avr_isp_worker_free(AvrIspWorker* instance) { + furi_assert(instance); + + furi_thread_free(instance->thread); + free(instance); +} + +// void avr_isp_worker_set_callback( +// AvrIspWorker* instance, +// AvrIspWorkerCallback callback, +// void* context) { +// furi_assert(instance); +// furi_assert(context); +// instance->callback = callback; +// instance->context = context; +// } + +void avr_isp_worker_start(AvrIspWorker* instance) { + furi_assert(instance); + furi_assert(!instance->worker_running); + + instance->worker_running = true; + + furi_thread_start(instance->thread); +} + +void avr_isp_worker_stop(AvrIspWorker* instance) { + furi_assert(instance); + furi_assert(instance->worker_running); + + instance->worker_running = false; + + furi_thread_join(instance->thread); +} + +bool avr_isp_worker_is_running(AvrIspWorker* instance) { + furi_assert(instance); + return instance->worker_running; +} diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h new file mode 100644 index 00000000000..b64d436b884 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include "../avr_isp_app_i.h" + +typedef struct AvrIspWorker AvrIspWorker; + +typedef struct { + uint8_t vcp_ch; + // uint8_t uart_ch; + // uint8_t flow_pins; + // uint8_t baudrate_mode; + uint32_t baudrate; +} AvrIspWorkerUsbConfig; + +// typedef void (*AvrIspWorkerCallback)( +// void* context, +// uint32_t frequency, +// float rssi, +// bool signal); + +/** Allocate AvrIspWorker + * + * @param context AvrIsp* context + * @return AvrIspWorker* + */ +AvrIspWorker* avr_isp_worker_alloc(void* context); + +/** Free AvrIspWorker + * + * @param instance AvrIspWorker instance + */ +void avr_isp_worker_free(AvrIspWorker* instance); + +// /** Callback AvrIspWorker +// * +// * @param instance AvrIspWorker instance +// * @param callback AvrIspWorkerOverrunCallback callback +// * @param context +// */ +// void avr_isp_worker_set_pair_callback( +// AvrIspWorker* instance, +// AvrIspWorkerCallback callback, +// void* context); + +/** Start AvrIspWorker + * + * @param instance AvrIspWorker instance + */ +void avr_isp_worker_start(AvrIspWorker* instance); + +/** Stop AvrIspWorker + * + * @param instance AvrIspWorker instance + */ +void avr_isp_worker_stop(AvrIspWorker* instance); + +/** Check if worker is running + * @param instance AvrIspWorker instance + * @return bool - true if running + */ +bool avr_isp_worker_is_running(AvrIspWorker* instance); diff --git a/applications/plugins/avr_isp_programmer/images/AvrIspProg.png b/applications/plugins/avr_isp_programmer/images/AvrIspProg.png new file mode 100644 index 0000000000000000000000000000000000000000..ec785948d035b717944bc41811f73d190e6fc3bd GIT binary patch literal 1690 zcmaJ?X;2eq7>)>*yJ)S*p|h?~Q6$-f1d>2NNH}5%Lt|z{KrzQc(y-YyStJQ+g^C9Q zSWv-YttjHfh@wyt@GLFhMTjB}M;LSv6%;{^;@J%X_DAW??0&~Q&+|U-`@P@n?x@Hx zJ8Nfa0)b%14d?LjF%^HQmS*_Zy;Prz4^CJ}G`0p!z*2-Nm=GjEMKHicgo!X87D}`~ zG{XJ_!fZF0AR3G2MKHxELKK=XL=B?E*#v@rphhVa%V7)_o@3{?OoMWF~y##kV3^-~Ura#~iQo~#pIF_K28B$0`bDW@qQkN5vj1er#wF+Tj+ z?|%xb1zIIc;=^h*StZ6#E@7!Dl#l0+R;G}k zDeC1D1RjscRj4tcLJV^`ED)C<%48Czw=bJb<4}SjatMt~4q?;jbe~|z8=_EsXfzI; zGR5Vf;$#F?U{hSlXD)k2uBjOiB_5drt7MyCNvH}%fQg)$vYEXwX4ISHN@n&FG$WUU zn<1G__FpGGwS~8jX*%7w_+q;CVFljrD!j4V;}c)t_r;dW2@+`9`eU1O>Hy1H=Z_x? z#)vXQ4`HsunYK6jxY4-M*|zlR`rg;$+V*St8!R`}`J(H(M(Fn4S4n;$pnW-UN$QA` z?fY?KM*pGHedF?8-QC`CtG>sHp2-iZetB?^`cj>4f5g#9o;N06J$3^rWaoX6Zp!iN6AS8ml(v%micb;q2O2KuEfM&;;GfOLnbEbQ;Xh2MB~uUb$O z=Tf34Z;Mngv^s8}xvK?|Q)X5xaeMf&yLz=D);7(;s_;xKaAkeDy_0K?%Yn2|k9C6T z^kdg4x7}!2l%F~e-2N&yKK{I*<bm{PN1M%~EqIS+ z#{g%nih7mt;>v=&E{mA(e4W(c;<>|5`bM6gWBHY@vRSt9LE+^Uhns6zS!2UzZw(cU zoUfWE)n;PLGTwze=xNtR#E5s54 z?u4@P3{ljfm#4cr?==i}&Q~nx+6o_SALMl>7g+8+b*EGr+g0b>QusCdoqSG@XTkT} zJKW>*p7M7!ScsC+I$SWe`PeH**g7LKd+2^e4BT{9(i5Fx*_t#~^L&3q*^<`Bg8SLL zJr^&8Wvz+nlWyNPFyz7qEt>zJmbmY7f19~I|Kz}R|I(kU_SSdG*|X+`TiP_=YR)O9 z%>w2`t#*GaxqGd${KiVYrAK$bi$_|DyT^Fr>F$>+;8w9Tw&Z$d+!FWSfdT)vdK%bz zZxc14Zjp1X%kW^EaVRy?Y1r_3XHB46)J>z~?!08J+0&8}hNJx?^62efuWTu{t@zFL zVZ4jin2pbcGJ}2f!HjR`wC}%p=#A$7DVOR4RjdwPz~ZWrAMHE3V&KiltB9(rl{Yu) zpLzA}yq2xqYW6IxKLj-^F^5Q^3s;lX5 N!3~Mzlm%~0{|8*@s)qmo literal 0 HcmV?d00001 diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c new file mode 100644 index 00000000000..4af125aeeaa --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c @@ -0,0 +1,30 @@ +#include "../avr_isp_app_i.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const avr_isp_scene_on_enter_handlers[])(void*) = { +#include "avr_isp_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const avr_isp_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "avr_isp_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const avr_isp_scene_on_exit_handlers[])(void* context) = { +#include "avr_isp_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers avr_isp_scene_handlers = { + .on_enter_handlers = avr_isp_scene_on_enter_handlers, + .on_event_handlers = avr_isp_scene_on_event_handlers, + .on_exit_handlers = avr_isp_scene_on_exit_handlers, + .scene_num = AvrIspSceneNum, +}; diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h new file mode 100644 index 00000000000..658ee74326f --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) AvrIspScene##id, +typedef enum { +#include "avr_isp_scene_config.h" + AvrIspSceneNum, +} AvrIspScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers avr_isp_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "avr_isp_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "avr_isp_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "avr_isp_scene_config.h" +#undef ADD_SCENE diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c new file mode 100644 index 00000000000..5a175ac3748 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c @@ -0,0 +1,67 @@ +#include "../avr_isp_app_i.h" +#include "../helpers/avr_isp_types.h" + +void avr_isp_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { + AvrIspApp* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void avr_isp_scene_about_on_enter(void* context) { + AvrIspApp* app = context; + + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_printf(temp_str, "\e#%s\n", "Information"); + + furi_string_cat_printf(temp_str, "Version: %s\n", AVR_ISP_VERSION_APP); + furi_string_cat_printf(temp_str, "Developed by: %s\n", AVR_ISP_DEVELOPED); + furi_string_cat_printf(temp_str, "Github: %s\n\n", AVR_ISP_GITHUB); + + furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); + furi_string_cat_printf(temp_str, "Avr Isp Programmer\nBla Bla Bla\nbla bla bla\n\n"); + + furi_string_cat_printf(temp_str, "Supported protocols:\n"); + + widget_add_text_box_element( + app->widget, + 0, + 0, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! \e!\n", + false); + widget_add_text_box_element( + app->widget, + 0, + 2, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! Avr Isp Programmer \e!\n", + false); + widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWidget); +} + +bool avr_isp_scene_about_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + bool consumed = false; + UNUSED(app); + UNUSED(event); + + return consumed; +} + +void avr_isp_scene_about_on_exit(void* context) { + AvrIspApp* app = context; + + // Clear views + widget_reset(app->widget); +} diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h new file mode 100644 index 00000000000..54c5931f18b --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h @@ -0,0 +1,3 @@ +ADD_SCENE(avr_isp, start, Start) +ADD_SCENE(avr_isp, about, About) +ADD_SCENE(avr_isp, programmer, Programmer) diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c new file mode 100644 index 00000000000..10231c56f0b --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c @@ -0,0 +1,38 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_programmer.h" + +void avr_isp_scene_programmer_callback(AvrIspCustomEvent event, void* context) { + furi_assert(context); + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void avr_isp_scene_programmer_on_enter(void* context) { + AvrIspApp* app = context; + + avr_asp_programmer_view_set_callback( + app->avr_asp_programmer_view, avr_isp_scene_programmer_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewProgrammer); +} + +bool avr_isp_scene_programmer_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + UNUSED(app); + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + // case WSCustomEventViewprogrammerBack: + // consumed = true; + // break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + } + return consumed; +} + +void avr_isp_scene_programmer_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c new file mode 100644 index 00000000000..238596ce8f6 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -0,0 +1,54 @@ +#include "../avr_isp_app_i.h" + +typedef enum { + SubmenuIndexAvrIspProgrammer, + SubmenuIndexAvrIspAbout, +} SubmenuIndex; + +void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void avr_isp_scene_start_on_enter(void* context) { + UNUSED(context); + AvrIspApp* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, + "Avr Isp Programmer", + SubmenuIndexAvrIspProgrammer, + avr_isp_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, "About", SubmenuIndexAvrIspAbout, avr_isp_scene_start_submenu_callback, app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, AvrIspSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewSubmenu); +} + +bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexAvrIspAbout) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneAbout); + consumed = true; + } else if(event.event == SubmenuIndexAvrIspProgrammer) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); + } + + return consumed; +} + +void avr_isp_scene_start_on_exit(void* context) { + AvrIspApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c new file mode 100644 index 00000000000..dfa7d658e50 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -0,0 +1,119 @@ +#include "avr_isp_view_programmer.h" +#include "../avr_isp_app_i.h" +#include + +#include "../helpers/avr_isp_worker.h" +//#include + +//#include +//#include + +struct AvrIspProgrammerView { + View* view; + AvrIspWorker* worker; + AvrIspProgrammerViewCallback callback; + void* context; +}; + +typedef struct { + uint16_t idx; +} AvrIspProgrammerViewModel; + +void avr_asp_programmer_view_set_callback( + AvrIspProgrammerView* instance, + AvrIspProgrammerViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { + UNUSED(model); + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + + canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 63, 46, "AvrIspProg"); + canvas_set_font(canvas, FontSecondary); +} + +bool avr_asp_programmer_view_input(InputEvent* event, void* context) { + furi_assert(context); + AvrIspProgrammerView* instance = context; + UNUSED(instance); + if(event->key == InputKeyBack || event->type != InputTypeShort) { + return false; + } + + return true; +} + +void avr_asp_programmer_view_enter(void* context) { + furi_assert(context); + AvrIspProgrammerView* instance = context; + //Start worker + instance->worker = avr_isp_worker_alloc(instance->context); + + // avr_isp_worker_set_callback( + // instance->worker, + // (SubGhzFrequencyAnalyzerWorkerPairCallback)avr_isp_callback, + // instance); + + avr_isp_worker_start(instance->worker); +} + +void avr_asp_programmer_view_exit(void* context) { + furi_assert(context); + AvrIspProgrammerView* instance = context; + //Stop worker + if(avr_isp_worker_is_running(instance->worker)) { + avr_isp_worker_stop(instance->worker); + } + avr_isp_worker_free(instance->worker); +} + +AvrIspProgrammerView* avr_asp_programmer_view_alloc() { + AvrIspProgrammerView* instance = malloc(sizeof(AvrIspProgrammerView)); + + // View allocation and configuration + instance->view = view_alloc(); + + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspProgrammerViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_programmer_view_draw); + view_set_input_callback(instance->view, avr_asp_programmer_view_input); + view_set_enter_callback(instance->view, avr_asp_programmer_view_enter); + view_set_exit_callback(instance->view, avr_asp_programmer_view_exit); + + // with_view_model( + // instance->view, + // AvrIspProgrammerViewModel * model, + // { + // // + // }, + // true); + return instance; +} + +void avr_asp_programmer_view_free(AvrIspProgrammerView* instance) { + furi_assert(instance); + + // with_view_model( + // avr_asp_programmer->view, + // AvrIspProgrammerViewModel * model, + // { + // // + // }, + // false); + view_free(instance->view); + free(instance); +} + +View* avr_asp_programmer_view_get_view(AvrIspProgrammerView* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h new file mode 100644 index 00000000000..6790c668c48 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "../helpers/avr_isp_types.h" +#include "../helpers/avr_isp_event.h" + +typedef struct AvrIspProgrammerView AvrIspProgrammerView; + +typedef void (*AvrIspProgrammerViewCallback)(AvrIspCustomEvent event, void* context); + +// void avr_asp_programmer_view_set_rssi(AvrIspProgrammerView* instance, float rssi); + +// void avr_asp_programmer_view_set_lock(AvrIspProgrammerView* avr_asp_programmer_view, avr_asp_programmerLock keyboard); + +void avr_asp_programmer_view_set_callback( + AvrIspProgrammerView* instance, + AvrIspProgrammerViewCallback callback, + void* context); + +AvrIspProgrammerView* avr_asp_programmer_view_alloc(); + +void avr_asp_programmer_view_free(AvrIspProgrammerView* instance); + +View* avr_asp_programmer_view_get_view(AvrIspProgrammerView* instance); + +void avr_asp_programmer_view_exit(void* context); From 6b4991b8091234b3e26a936edd336752191fbdf8 Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 9 Mar 2023 22:03:08 +0400 Subject: [PATCH 02/50] [AVR_ISP]: fix syntax --- .../avr_isp_programmer/helpers/avr_isp_spi_sw.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h index fa18999091a..9ab63b3b5a9 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h @@ -3,11 +3,11 @@ #include typedef enum { - AvrIspSpiSwSpeed1Mhz=0, - AvrIspSpiSwSpeed400Khz=1, - AvrIspSpiSwSpeed250Khz=2, - AvrIspSpiSwSpeed125Khz=4, - AvrIspSpiSwSpeed40Khz=12, + AvrIspSpiSwSpeed1Mhz = 0, + AvrIspSpiSwSpeed400Khz = 1, + AvrIspSpiSwSpeed250Khz = 2, + AvrIspSpiSwSpeed125Khz = 4, + AvrIspSpiSwSpeed40Khz = 12, } AvrIspSpiSwSpeed; typedef struct AvrIspSpiSw AvrIspSpiSw; From 92288d8147e056c7df1ac426b199f9efc64a5653 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 10 Mar 2023 13:41:04 +0400 Subject: [PATCH 03/50] [AVR_ISP]: refactoring --- .../avr_isp_programmer/application.fam | 2 +- .../avr_isp_programmer/avr_isp_app_i.h | 17 - .../helpers/avr_isp_chip_arr.c | 384 ++++++++++++++++++ .../helpers/avr_isp_chip_arr.h | 32 ++ .../helpers/avr_isp_event.h | 9 - .../avr_isp_programmer/helpers/avr_isp_prog.c | 237 +++++------ .../helpers/avr_isp_prog_cmd.h | 61 ++- .../helpers/avr_isp_spi_sw.c | 2 - .../helpers/avr_isp_types.h | 32 -- .../helpers/avr_isp_worker.c | 22 +- 10 files changed, 581 insertions(+), 217 deletions(-) create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h diff --git a/applications/plugins/avr_isp_programmer/application.fam b/applications/plugins/avr_isp_programmer/application.fam index 2eb8e23761a..f12a9e5fc5b 100644 --- a/applications/plugins/avr_isp_programmer/application.fam +++ b/applications/plugins/avr_isp_programmer/application.fam @@ -1,6 +1,6 @@ App( appid="avr_isp", - name="Avr Isp Programmer", + name="AVR ISP Programmer", apptype=FlipperAppType.PLUGIN, targets=["f7"], entry_point="avr_isp_app", diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h index cf95896a0b6..12c6c2b88dd 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h @@ -15,23 +15,6 @@ typedef struct AvrIspApp AvrIspApp; -// struct AvrIspTxRx { -// SubGhzWorker* worker; - -// SubGhzEnvironment* environment; -// SubGhzReceiver* receiver; -// SubGhzRadioPreset* preset; -// WSHistory* history; -// uint16_t idx_menu_chosen; -// WSTxRxState txrx_state; -// WSHopperState hopper_state; -// uint8_t hopper_timeout; -// uint8_t hopper_idx_frequency; -// WSRxKeyState rx_key_state; -// }; - -//typedef struct AvrIspTxRx AvrIspTxRx; - struct AvrIspApp { Gui* gui; ViewDispatcher* view_dispatcher; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c new file mode 100644 index 00000000000..2c173f5eacd --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c @@ -0,0 +1,384 @@ +#include "avr_isp_chip_arr.h" + +#include + +//https://github.com/avrdudes/avrdude/blob/master/src/avrintel.c + +const AvrIspChipArr avr_isp_chip_arr[] = { // Value of -1 typically means unknown + //{mcu_name, mcuid, family, {sig, na, ture}, flstart, flsize, pgsiz, nb, bootsz, eestart, eesize, ep, rambeg, ramsiz, nf, nl, ni}, // Source + {"ATtiny4", 0, F_AVR8L, {0x1E, 0x8F, 0x0A}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny5", 1, F_AVR8L, {0x1E, 0x8F, 0x09}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny9", 2, F_AVR8L, {0x1E, 0x90, 0x08}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny10", 3, F_AVR8L, {0x1E, 0x90, 0x03}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny20", 4, F_AVR8L, {0x1E, 0x91, 0x0F}, 0, 0x00800, 0x020, 0, 0, 0, 0, 0, 0x0040, 0x0080, 1, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny40", 5, F_AVR8L, {0x1E, 0x92, 0x0E}, 0, 0x01000, 0x040, 0, 0, 0, 0, 0, 0x0040, 0x0100, 1, 1, 18}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATtiny102", 6, F_AVR8L, {0x1E, 0x90, 0x0C}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual) + {"ATtiny104", 7, F_AVR8L, {0x1E, 0x90, 0x0B}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual) + + {"ATtiny11", 8, F_AVR8, {0x1E, 0x90, 0x04}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 5}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny12", 9, F_AVR8, {0x1E, 0x90, 0x05}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny13", 10, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny13A", 11, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny15", 12, F_AVR8, {0x1E, 0x90, 0x06}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 9}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny22", 13, F_AVR8, {0x1E, 0x91, 0x06}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual) + {"ATtiny24", 14, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny24A", 15, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny25", 16, F_AVR8, {0x1E, 0x91, 0x08}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny26", 17, F_AVR8, {0x1E, 0x91, 0x09}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 2, 1, 12}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny28", 18, F_AVR8, {0x1E, 0x91, 0x07}, 0, 0x00800, 0x002, 0, 0, 0, 0, 0, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny43U", 19, F_AVR8, {0x1E, 0x92, 0x0C}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0060, 0x0100, 3, 1, 16}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny44", 20, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny44A", 21, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny45", 22, F_AVR8, {0x1E, 0x92, 0x06}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny48", 23, F_AVR8, {0x1E, 0x92, 0x09}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny84", 24, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny84A", 25, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny85", 26, F_AVR8, {0x1E, 0x93, 0x0B}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny87", 27, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny88", 28, F_AVR8, {0x1E, 0x93, 0x11}, 0, 0x02000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny167", 29, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny261", 30, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny261A", 31, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny441", 32, F_AVR8, {0x1E, 0x92, 0x15}, 0, 0x01000, 0x010, 0, 0, 0, 0x0100, 4, 0x0100, 0x0100, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny461", 33, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny461A", 34, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny828", 35, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny828R", 36, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // avrdude, from ATtiny828 + {"ATtiny841", 37, F_AVR8, {0x1E, 0x93, 0x15}, 0, 0x02000, 0x010, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny861", 38, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny861A", 39, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1634", 40, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1634R", 41, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // avrdude, from ATtiny1634 + {"ATtiny2313", 42, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny2313A", 43, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny4313", 44, F_AVR8, {0x1E, 0x92, 0x0D}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega8", 45, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega8A", 46, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega8HVA", 47, F_AVR8, {0x1E, 0x93, 0x10}, 0, 0x02000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0 + {"ATmega8U2", 48, F_AVR8, {0x1E, 0x93, 0x89}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega16", 49, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega16A", 50, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega16HVA", 51, F_AVR8, {0x1E, 0x94, 0x0C}, 0, 0x04000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0 + {"ATmega16HVB", 52, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0 + {"ATmega16HVBrevB", 53, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0 + {"ATmega16M1", 54, F_AVR8, {0x1E, 0x94, 0x84}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0 + {"ATmega16HVA2", 55, F_AVR8, {0x1E, 0x94, 0x0E}, 0, 0x04000, 0x080, -1, -1, -1, -1, -1, 0x0100, 0x0400, 2, 1, 22}, // avr-gcc 12.2.0 + {"ATmega16U2", 56, F_AVR8, {0x1E, 0x94, 0x89}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega16U4", 57, F_AVR8, {0x1E, 0x94, 0x88}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0500, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32", 58, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32A", 59, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32HVB", 60, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0 + {"ATmega32HVBrevB", 61, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0 + {"ATmega32C1", 62, F_AVR8, {0x1E, 0x95, 0x86}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0 + {"ATmega32M1", 63, F_AVR8, {0x1E, 0x95, 0x84}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32U2", 64, F_AVR8, {0x1E, 0x95, 0x8A}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0400, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32U4", 65, F_AVR8, {0x1E, 0x95, 0x87}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0a00, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega32U6", 66, F_AVR8, {0x1E, 0x95, 0x88}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0100, 0x0a00, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual) + {"ATmega48", 67, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega48A", 68, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega48P", 69, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega48PA", 70, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega48PB", 71, F_AVR8, {0x1E, 0x92, 0x10}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega64", 72, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega64A", 73, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega64HVE", 74, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, -1, -1, -1, 0x0100, 0x1000, 2, 1, 25}, // avr-gcc 12.2.0, boot size (manual) + {"ATmega64C1", 75, F_AVR8, {0x1E, 0x96, 0x86}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0 + {"ATmega64M1", 76, F_AVR8, {0x1E, 0x96, 0x84}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega64HVE2", 77, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, 0, 0x0400, 4, 0x0100, 0x1000, 2, 1, 25}, // atdf, avr-gcc 12.2.0 + {"ATmega64RFR2", 78, F_AVR8, {0x1E, 0xA6, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega88", 79, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega88A", 80, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega88P", 81, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega88PA", 82, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega88PB", 83, F_AVR8, {0x1E, 0x93, 0x16}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega103", 84, F_AVR8, {0x1E, 0x97, 0x01}, 0, 0x20000, 0x100, 0, 0, 0, 0x1000, 1, 0x0060, 0x0fa0, 1, 1, 24}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATmega128", 85, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega128A", 86, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega128RFA1", 87, F_AVR8, {0x1E, 0xA7, 0x01}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 72}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega128RFR2", 88, F_AVR8, {0x1E, 0xA7, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega161", 89, F_AVR8, {0x1E, 0x94, 0x01}, 0, 0x04000, 0x080, 1, 0x0400, 0, 0x0200, 1, 0x0060, 0x0400, 1, 1, 21}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATmega162", 90, F_AVR8, {0x1E, 0x94, 0x04}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega163", 91, F_AVR8, {0x1E, 0x94, 0x02}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 1, 0x0060, 0x0400, 2, 1, 18}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATmega164A", 92, F_AVR8, {0x1E, 0x94, 0x0F}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega164P", 93, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega164PA", 94, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega165", 95, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATmega165A", 96, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega165P", 97, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega165PA", 98, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega168", 99, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega168A", 100, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega168P", 101, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega168PA", 102, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega168PB", 103, F_AVR8, {0x1E, 0x94, 0x15}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 7.3.0, avrdude + {"ATmega169", 104, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"ATmega169A", 105, F_AVR8, {0x1E, 0x94, 0x11}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega169P", 106, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega169PA", 107, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega256RFR2", 108, F_AVR8, {0x1E, 0xA8, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega323", 109, F_AVR8, {0x1E, 0x95, 0x01}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0060, 0x0800, 2, 1, 21}, // avr-gcc 12.2.0, boot size (manual) + {"ATmega324A", 110, F_AVR8, {0x1E, 0x95, 0x15}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega324P", 111, F_AVR8, {0x1E, 0x95, 0x08}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega324PA", 112, F_AVR8, {0x1E, 0x95, 0x11}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega324PB", 113, F_AVR8, {0x1E, 0x95, 0x17}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 51}, // atdf, avrdude + {"ATmega325", 114, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega325A", 115, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega325P", 116, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega325PA", 117, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega328", 118, F_AVR8, {0x1E, 0x95, 0x14}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega328P", 119, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega328PB", 120, F_AVR8, {0x1E, 0x95, 0x16}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 45}, // atdf, avr-gcc 7.3.0, avrdude + {"ATmega329", 121, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega329A", 122, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega329P", 123, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega329PA", 124, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega406", 125, F_AVR8, {0x1E, 0x95, 0x07}, 0, 0x0a000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0800, 2, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega640", 126, F_AVR8, {0x1E, 0x96, 0x08}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega644", 127, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega644A", 128, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega644P", 129, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega644PA", 130, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega644RFR2", 131, F_AVR8, {0x1E, 0xA6, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega645", 132, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega645A", 133, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega645P", 134, F_AVR8, {0x1E, 0x96, 0x0D}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega649", 135, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega649A", 136, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega649P", 137, F_AVR8, {0x1E, 0x96, 0x0B}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1280", 138, F_AVR8, {0x1E, 0x97, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1281", 139, F_AVR8, {0x1E, 0x97, 0x04}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1284", 140, F_AVR8, {0x1E, 0x97, 0x06}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1284P", 141, F_AVR8, {0x1E, 0x97, 0x05}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1284RFR2", 142, F_AVR8, {0x1E, 0xA7, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega2560", 143, F_AVR8, {0x1E, 0x98, 0x01}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega2561", 144, F_AVR8, {0x1E, 0x98, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega2564RFR2", 145, F_AVR8, {0x1E, 0xA8, 0x03}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3250", 146, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3250A", 147, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3250P", 148, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3250PA", 149, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3290", 150, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3290A", 151, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3290P", 152, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3290PA", 153, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6450", 154, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6450A", 155, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6450P", 156, F_AVR8, {0x1E, 0x96, 0x0E}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6490", 157, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6490A", 158, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega6490P", 159, F_AVR8, {0x1E, 0x96, 0x0C}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega8515", 160, F_AVR8, {0x1E, 0x93, 0x06}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega8535", 161, F_AVR8, {0x1E, 0x93, 0x08}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude + {"AT43USB320", 162, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0200, -1, -1, 0}, // avr-gcc 12.2.0 + {"AT43USB355", 163, F_AVR8, {0xff, -1, -1}, 0, 0x06000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0400, -1, -1, 0}, // avr-gcc 12.2.0 + {"AT76C711", 164, F_AVR8, {0xff, -1, -1}, 0, 0x04000, -1, -1, -1, -1, -1, -1, 0x0060, 0x07a0, -1, -1, 0}, // avr-gcc 12.2.0 + {"AT86RF401", 165, F_AVR8, {0x1E, 0x91, 0x81}, 0, 0x00800, -1, -1, -1, -1, -1, -1, 0x0060, 0x0080, 0, 1, 3}, // avr-gcc 12.2.0 + {"AT90PWM1", 166, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0 + {"AT90PWM2", 167, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90PWM2B", 168, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM3", 169, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM3B", 170, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90CAN32", 171, F_AVR8, {0x1E, 0x95, 0x81}, 0, 0x08000, 0x100, 4, 0x0400, 0, 0x0400, 8, 0x0100, 0x0800, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90CAN64", 172, F_AVR8, {0x1E, 0x96, 0x81}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM81", 173, F_AVR8, {0x1E, 0x93, 0x88}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"AT90USB82", 174, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90SCR100", 175, F_AVR8, {0x1E, 0x96, 0xC1}, 0, 0x10000, 0x100, 4, 0x0200, -1, -1, -1, 0x0100, 0x1000, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual) + {"AT90CAN128", 176, F_AVR8, {0x1E, 0x97, 0x81}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM161", 177, F_AVR8, {0x1E, 0x94, 0x8B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"AT90USB162", 178, F_AVR8, {0x1E, 0x94, 0x82}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM216", 179, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90PWM316", 180, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90USB646", 181, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90USB647", 182, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90S1200", 183, F_AVR8, {0x1E, 0x90, 0x01}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 4}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90USB1286", 184, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90USB1287", 185, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude + {"AT90S2313", 186, F_AVR8, {0x1E, 0x91, 0x01}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 11}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S2323", 187, F_AVR8, {0x1E, 0x91, 0x02}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual) + {"AT90S2333", 188, F_AVR8, {0x1E, 0x91, 0x05}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, -1, -1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S2343", 189, F_AVR8, {0x1E, 0x91, 0x03}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S4414", 190, F_AVR8, {0x1E, 0x92, 0x01}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S4433", 191, F_AVR8, {0x1E, 0x92, 0x03}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0080, 1, 1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S4434", 192, F_AVR8, {0x1E, 0x92, 0x02}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90S8515", 193, F_AVR8, {0x1E, 0x93, 0x01}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT90C8534", 194, F_AVR8, {0xff, -1, -1}, 0, 0x02000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0100, -1, -1, 0}, // avr-gcc 12.2.0 + {"AT90S8535", 195, F_AVR8, {0x1E, 0x93, 0x03}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual) + {"AT94K", 196, F_AVR8, {0xff, -1, -1}, 0, 0x08000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0fa0, -1, -1, 0}, // avr-gcc 12.2.0 + {"ATA5272", 197, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 37}, // atdf, avr-gcc 12.2.0 + {"ATA5505", 198, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"ATA5700M322", 199, F_AVR8, {0x1E, 0x95, 0x67}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf + {"ATA5702M322", 200, F_AVR8, {0x1E, 0x95, 0x69}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf, avr-gcc 12.2.0 + {"ATA5781", 201, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA5782", 202, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0 + {"ATA5783", 203, F_AVR8, {0x1E, 0x95, 0x66}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA5787", 204, F_AVR8, {0x1E, 0x94, 0x6C}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf + {"ATA5790", 205, F_AVR8, {0x1E, 0x94, 0x61}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 30}, // atdf, avr-gcc 12.2.0 + {"ATA5790N", 206, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 12.2.0 + {"ATA5791", 207, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 7.3.0 + {"ATA5795", 208, F_AVR8, {0x1E, 0x93, 0x61}, 0, 0x02000, 0x040, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 23}, // atdf, avr-gcc 12.2.0 + {"ATA5831", 209, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0 + {"ATA5832", 210, F_AVR8, {0x1E, 0x95, 0x62}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA5833", 211, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA5835", 212, F_AVR8, {0x1E, 0x94, 0x6B}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf + {"ATA6285", 213, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0 + {"ATA6286", 214, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0 + {"ATA6289", 215, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, -1, -1, -1, 0x0100, 0x0200, 2, 1, 27}, // avr-gcc 12.2.0, boot size (manual) + {"ATA6612C", 216, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0 + {"ATA6613C", 217, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0 + {"ATA6614Q", 218, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0 + {"ATA6616C", 219, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"ATA6617C", 220, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"ATA8210", 221, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0 + {"ATA8215", 222, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA8510", 223, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0 + {"ATA8515", 224, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf + {"ATA664251", 225, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0 + {"M3000", 226, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x1000, 0x1000, -1, -1, 0}, // avr-gcc 12.2.0 + {"LGT8F88P", 227, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega88 + {"LGT8F168P", 228, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega168P + {"LGT8F328P", 229, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // avrdude, from ATmega328P + + {"ATxmega8E5", 230, F_XMEGA, {0x1E, 0x93, 0x41}, 0, 0x02800, 0x080, 1, 0x0800, 0, 0x0200, 32, 0x2000, 0x0400, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega16A4", 231, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega16A4U", 232, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega16C4", 233, F_XMEGA, {0x1E, 0x94, 0x43}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega16D4", 234, F_XMEGA, {0x1E, 0x94, 0x42}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega16E5", 235, F_XMEGA, {0x1E, 0x94, 0x45}, 0, 0x05000, 0x080, 1, 0x1000, 0, 0x0200, 32, 0x2000, 0x0800, 7, 1, 43}, // atdf, avr-gcc 7.3.0, avrdude + {"ATxmega32C3", 236, F_XMEGA, {0x1E, 0x95, 0x49}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0 + {"ATxmega32D3", 237, F_XMEGA, {0x1E, 0x95, 0x4A}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0 + {"ATxmega32A4", 238, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega32A4U", 239, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega32C4", 240, F_XMEGA, {0x1E, 0x95, 0x44}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega32D4", 241, F_XMEGA, {0x1E, 0x95, 0x42}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega32E5", 242, F_XMEGA, {0x1E, 0x95, 0x4C}, 0, 0x09000, 0x080, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64A1", 243, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64A1U", 244, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64B1", 245, F_XMEGA, {0x1E, 0x96, 0x52}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64A3", 246, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64A3U", 247, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64B3", 248, F_XMEGA, {0x1E, 0x96, 0x51}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64C3", 249, F_XMEGA, {0x1E, 0x96, 0x49}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64D3", 250, F_XMEGA, {0x1E, 0x96, 0x4A}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64A4", 251, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude + {"ATxmega64A4U", 252, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega64D4", 253, F_XMEGA, {0x1E, 0x96, 0x47}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128A1", 254, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128A1revD", 255, F_XMEGA, {0x1E, 0x97, 0x41}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude + {"ATxmega128A1U", 256, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128B1", 257, F_XMEGA, {0x1E, 0x97, 0x4D}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128A3", 258, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128A3U", 259, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128B3", 260, F_XMEGA, {0x1E, 0x97, 0x4B}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128C3", 261, F_XMEGA, {0x1E, 0x97, 0x52}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128D3", 262, F_XMEGA, {0x1E, 0x97, 0x48}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128A4", 263, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude + {"ATxmega128A4U", 264, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega128D4", 265, F_XMEGA, {0x1E, 0x97, 0x47}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega192A1", 266, F_XMEGA, {0x1E, 0x97, 0x4E}, 0, 0x32000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude + {"ATxmega192A3", 267, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega192A3U", 268, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega192C3", 269, F_XMEGA, {0x1E, 0x97, 0x51}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega192D3", 270, F_XMEGA, {0x1E, 0x97, 0x49}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256A1", 271, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, -1, -1, 0, 0x1000, 32, -1, -1, -1, -1, 0}, // avrdude + {"ATxmega256A3", 272, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256A3B", 273, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256A3BU", 274, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256A3U", 275, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256C3", 276, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega256D3", 277, F_XMEGA, {0x1E, 0x98, 0x44}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega384C3", 278, F_XMEGA, {0x1E, 0x98, 0x45}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude + {"ATxmega384D3", 279, F_XMEGA, {0x1E, 0x98, 0x47}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude + + {"ATtiny202", 280, F_AVR8X, {0x1E, 0x91, 0x23}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny204", 281, F_AVR8X, {0x1E, 0x91, 0x22}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny212", 282, F_AVR8X, {0x1E, 0x91, 0x21}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny214", 283, F_AVR8X, {0x1E, 0x91, 0x20}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny402", 284, F_AVR8X, {0x1E, 0x92, 0x27}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny404", 285, F_AVR8X, {0x1E, 0x92, 0x26}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny406", 286, F_AVR8X, {0x1E, 0x92, 0x25}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny412", 287, F_AVR8X, {0x1E, 0x92, 0x23}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny414", 288, F_AVR8X, {0x1E, 0x92, 0x22}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny416", 289, F_AVR8X, {0x1E, 0x92, 0x21}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny416auto", 290, F_AVR8X, {0x1E, 0x92, 0x28}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf + {"ATtiny417", 291, F_AVR8X, {0x1E, 0x92, 0x20}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny424", 292, F_AVR8X, {0x1E, 0x92, 0x2C}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude + {"ATtiny426", 293, F_AVR8X, {0x1E, 0x92, 0x2B}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude + {"ATtiny427", 294, F_AVR8X, {0x1E, 0x92, 0x2A}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude + {"ATtiny804", 295, F_AVR8X, {0x1E, 0x93, 0x25}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny806", 296, F_AVR8X, {0x1E, 0x93, 0x24}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny807", 297, F_AVR8X, {0x1E, 0x93, 0x23}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny814", 298, F_AVR8X, {0x1E, 0x93, 0x22}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny816", 299, F_AVR8X, {0x1E, 0x93, 0x21}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny817", 300, F_AVR8X, {0x1E, 0x93, 0x20}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny824", 301, F_AVR8X, {0x1E, 0x93, 0x29}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude + {"ATtiny826", 302, F_AVR8X, {0x1E, 0x93, 0x28}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude + {"ATtiny827", 303, F_AVR8X, {0x1E, 0x93, 0x27}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude + {"ATtiny1604", 304, F_AVR8X, {0x1E, 0x94, 0x25}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1606", 305, F_AVR8X, {0x1E, 0x94, 0x24}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1607", 306, F_AVR8X, {0x1E, 0x94, 0x23}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1614", 307, F_AVR8X, {0x1E, 0x94, 0x22}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1616", 308, F_AVR8X, {0x1E, 0x94, 0x21}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1617", 309, F_AVR8X, {0x1E, 0x94, 0x20}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny1624", 310, F_AVR8X, {0x1E, 0x94, 0x2A}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude + {"ATtiny1626", 311, F_AVR8X, {0x1E, 0x94, 0x29}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude + {"ATtiny1627", 312, F_AVR8X, {0x1E, 0x94, 0x28}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude + {"ATtiny3214", 313, F_AVR8X, {0x1E, 0x95, 0x20}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // avr-gcc 12.2.0 + {"ATtiny3216", 314, F_AVR8X, {0x1E, 0x95, 0x21}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny3217", 315, F_AVR8X, {0x1E, 0x95, 0x22}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude + {"ATtiny3224", 316, F_AVR8X, {0x1E, 0x95, 0x28}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude + {"ATtiny3226", 317, F_AVR8X, {0x1E, 0x95, 0x27}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude + {"ATtiny3227", 318, F_AVR8X, {0x1E, 0x95, 0x26}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude + {"ATmega808", 319, F_AVR8X, {0x1E, 0x93, 0x26}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega809", 320, F_AVR8X, {0x1E, 0x93, 0x2A}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1608", 321, F_AVR8X, {0x1E, 0x94, 0x27}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega1609", 322, F_AVR8X, {0x1E, 0x94, 0x26}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3208", 323, F_AVR8X, {0x1E, 0x95, 0x30}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega3209", 324, F_AVR8X, {0x1E, 0x95, 0x31}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega4808", 325, F_AVR8X, {0x1E, 0x96, 0x50}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude + {"ATmega4809", 326, F_AVR8X, {0x1E, 0x96, 0x51}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude + {"AVR8EA28", 327, F_AVR8X, {0x1E, 0x93, 0x2C}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR8EA32", 328, F_AVR8X, {0x1E, 0x93, 0x2B}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR16DD14", 329, F_AVR8X, {0x1E, 0x94, 0x34}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude + {"AVR16DD20", 330, F_AVR8X, {0x1E, 0x94, 0x33}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude + {"AVR16DD28", 331, F_AVR8X, {0x1E, 0x94, 0x32}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude + {"AVR16EA28", 332, F_AVR8X, {0x1E, 0x94, 0x37}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR16DD32", 333, F_AVR8X, {0x1E, 0x94, 0x31}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude + {"AVR16EA32", 334, F_AVR8X, {0x1E, 0x94, 0x36}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR16EA48", 335, F_AVR8X, {0x1E, 0x94, 0x35}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR32DD14", 336, F_AVR8X, {0x1E, 0x95, 0x3B}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude + {"AVR32DD20", 337, F_AVR8X, {0x1E, 0x95, 0x3A}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude + {"AVR32DA28", 338, F_AVR8X, {0x1E, 0x95, 0x34}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 41}, // atdf, avrdude + {"AVR32DB28", 339, F_AVR8X, {0x1E, 0x95, 0x37}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 42}, // atdf, avrdude + {"AVR32DD28", 340, F_AVR8X, {0x1E, 0x95, 0x39}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude + {"AVR32EA28", 341, F_AVR8X, {0x1E, 0x95, 0x3E}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR32DA32", 342, F_AVR8X, {0x1E, 0x95, 0x33}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude + {"AVR32DB32", 343, F_AVR8X, {0x1E, 0x95, 0x36}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude + {"AVR32DD32", 344, F_AVR8X, {0x1E, 0x95, 0x38}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude + {"AVR32EA32", 345, F_AVR8X, {0x1E, 0x95, 0x3D}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR32DA48", 346, F_AVR8X, {0x1E, 0x95, 0x32}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 58}, // atdf, avrdude + {"AVR32DB48", 347, F_AVR8X, {0x1E, 0x95, 0x35}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 61}, // atdf, avrdude + {"AVR32EA48", 348, F_AVR8X, {0x1E, 0x95, 0x3C}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude + {"AVR64DD14", 349, F_AVR8X, {0x1E, 0x96, 0x1D}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude + {"AVR64DD20", 350, F_AVR8X, {0x1E, 0x96, 0x1C}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude + {"AVR64DA28", 351, F_AVR8X, {0x1E, 0x96, 0x15}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 41}, // atdf, avrdude + {"AVR64DB28", 352, F_AVR8X, {0x1E, 0x96, 0x19}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 42}, // atdf, avrdude + {"AVR64DD28", 353, F_AVR8X, {0x1E, 0x96, 0x1B}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude + {"AVR64EA28", 354, F_AVR8X, {0x1E, 0x96, 0x20}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude + {"AVR64DA32", 355, F_AVR8X, {0x1E, 0x96, 0x14}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude + {"AVR64DB32", 356, F_AVR8X, {0x1E, 0x96, 0x18}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude + {"AVR64DD32", 357, F_AVR8X, {0x1E, 0x96, 0x1A}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude + {"AVR64EA32", 358, F_AVR8X, {0x1E, 0x96, 0x1F}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude + {"AVR64DA48", 359, F_AVR8X, {0x1E, 0x96, 0x13}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 58}, // atdf, avrdude + {"AVR64DB48", 360, F_AVR8X, {0x1E, 0x96, 0x17}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 61}, // atdf, avrdude + {"AVR64EA48", 361, F_AVR8X, {0x1E, 0x96, 0x1E}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 45}, // atdf, avrdude + {"AVR64DA64", 362, F_AVR8X, {0x1E, 0x96, 0x12}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 64}, // atdf, avrdude + {"AVR64DB64", 363, F_AVR8X, {0x1E, 0x96, 0x16}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 65}, // atdf, avrdude + {"AVR128DA28", 364, F_AVR8X, {0x1E, 0x97, 0x0A}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 41}, // atdf, avrdude + {"AVR128DB28", 365, F_AVR8X, {0x1E, 0x97, 0x0E}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 42}, // atdf, avrdude + {"AVR128DA32", 366, F_AVR8X, {0x1E, 0x97, 0x09}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude + {"AVR128DB32", 367, F_AVR8X, {0x1E, 0x97, 0x0D}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude + {"AVR128DA48", 368, F_AVR8X, {0x1E, 0x97, 0x08}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 58}, // atdf, avrdude + {"AVR128DB48", 369, F_AVR8X, {0x1E, 0x97, 0x0C}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 61}, // atdf, avrdude + {"AVR128DA64", 370, F_AVR8X, {0x1E, 0x97, 0x07}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 64}, // atdf, avrdude + {"AVR128DB64", 371, F_AVR8X, {0x1E, 0x97, 0x0B}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 65}, // atdf, avrdude +}; \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h new file mode 100644 index 00000000000..0f4bd344cf3 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#define F_AVR8L 1 // TPI programming, ATtiny(4|5|9|10|20|40|102|104) +#define F_AVR8 2 // ISP programming with SPI, "classic" AVRs +#define F_XMEGA 4 // PDI programming, ATxmega family +#define F_AVR8X 8 // UPDI programming, newer 8-bit MCUs + +struct AvrIspChipArr { // Value of -1 typically means unknown + const char* name; // Name of part + uint16_t mcuid; // ID of MCU in 0..2039 + uint8_t avrarch; // F_AVR8L, F_AVR8, F_XMEGA or F_AVR8X + uint8_t sigs[3]; // Signature bytes + int32_t flashoffset; // Flash offset + int32_t flashsize; // Flash size + int16_t pagesize; // Flash page size + int8_t nboots; // Number of supported boot sectors + int16_t bootsize; // Size of (smallest) boot sector + int32_t eepromoffset; // EEPROM offset + int32_t eepromsize; // EEPROM size + int32_t eeprompagesize; // EEPROM page size + int32_t sramstart; // SRAM offset + int32_t sramsize; // SRAM size + int8_t nfuses; // Number of fuse bytes + int8_t nlocks; // Number of lock bytes + uint8_t ninterrupts; // Number of vectors in interrupt vector table +}; + +typedef struct AvrIspChipArr AvrIspChipArr; + +extern const AvrIspChipArr avr_isp_chip_arr[]; \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h index 71beea7e13c..36c46264181 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h @@ -1,14 +1,5 @@ #pragma once typedef enum { - //AvrIspCustomEvent AvrIspCustomEventStartId = 100, - - // AvrIspCustomEventSceneSettingLock, - - // AvrIspCustomEventViewReceiverOK, - // AvrIspCustomEventViewReceiverConfig, - // AvrIspCustomEventViewReceiverBack, - // AvrIspCustomEventViewReceiverOffDisplay, - // AvrIspCustomEventViewReceiverUnlock, } AvrIspCustomEvent; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c index 26c5c87b148..0707e5b59a9 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c @@ -5,7 +5,7 @@ #define AVR_ISP_PROG_TX_RX_BUF_SIZE 256 -struct AvrIspProgParam { +struct AvrIspProgCfgDevice { uint8_t devicecode; uint8_t revision; uint8_t progtype; @@ -21,16 +21,16 @@ struct AvrIspProgParam { uint32_t flashsize; }; -typedef struct AvrIspProgParam AvrIspProgParam; +typedef struct AvrIspProgCfgDevice AvrIspProgCfgDevice; struct AvrIspProg { AvrIspSpiSw* spi; - AvrIspProgParam* param; + AvrIspProgCfgDevice* cfg; FuriStreamBuffer* stream_rx; FuriStreamBuffer* stream_tx; uint16_t error; - uint16_t addr; //here + uint16_t addr; bool pmode; bool tx_ok; bool exit; @@ -41,7 +41,7 @@ struct AvrIspProg { AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { AvrIspProg* instance = malloc(sizeof(AvrIspProg)); - instance->param = malloc(sizeof(AvrIspProgParam)); + instance->cfg = malloc(sizeof(AvrIspProgCfgDevice)); instance->stream_rx = furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); instance->stream_tx = @@ -58,7 +58,7 @@ void avr_isp_prog_free(AvrIspProg* instance) { furi_stream_buffer_free(instance->stream_tx); furi_stream_buffer_free(instance->stream_rx); - free(instance->param); + free(instance->cfg); free(instance); } @@ -135,7 +135,7 @@ static uint8_t static void avr_isp_prog_empty_reply(AvrIspProg* instance) { furi_assert(instance); - if(CRC_EOP == avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); avr_isp_prog_tx_ch(instance, STK_OK); } else { @@ -146,7 +146,7 @@ static void avr_isp_prog_empty_reply(AvrIspProg* instance) { static void avr_isp_prog_breply(AvrIspProg* instance, uint8_t data) { furi_assert(instance); - if(CRC_EOP == avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); avr_isp_prog_tx_ch(instance, data); avr_isp_prog_tx_ch(instance, STK_OK); @@ -159,52 +159,55 @@ static void avr_isp_prog_breply(AvrIspProg* instance, uint8_t data) { static void avr_isp_prog_get_version(AvrIspProg* instance, uint8_t data) { furi_assert(instance); switch(data) { - case 0x80: - avr_isp_prog_breply(instance, HWVER); + case STK_HW_VER: + avr_isp_prog_breply(instance, AVR_ISP_HWVER); break; - case 0x81: - avr_isp_prog_breply(instance, SWMAJ); + case STK_SW_MAJOR: + avr_isp_prog_breply(instance, AVR_ISP_SWMAJ); break; - case 0x82: - avr_isp_prog_breply(instance, SWMIN); + case STK_SW_MINOR: + avr_isp_prog_breply(instance, AVR_ISP_SWMIN); break; - case 0x93: - avr_isp_prog_breply(instance, 'S'); // serial programmer + case AVP_ISP_GET_CONNECT_TYPE: + avr_isp_prog_breply(instance, AVP_ISP_SERIAL_CONNECT_TYPE); break; default: - avr_isp_prog_breply(instance, 0); + avr_isp_prog_breply(instance, AVR_ISP_RESP_0); } } -static void avr_isp_prog_set_parameters(AvrIspProg* instance) { +static void avr_isp_prog_set_cfg(AvrIspProg* instance) { furi_assert(instance); - // call this after reading paramter packet into buff[] - instance->param->devicecode = instance->buff[0]; - instance->param->revision = instance->buff[1]; - instance->param->progtype = instance->buff[2]; - instance->param->parmode = instance->buff[3]; - instance->param->polling = instance->buff[4]; - instance->param->selftimed = instance->buff[5]; - instance->param->lockbytes = instance->buff[6]; - instance->param->fusebytes = instance->buff[7]; - instance->param->flashpoll = instance->buff[8]; - // ignore instance->buff[9] (= instance->buff[8]) - // following are 16 bits (big endian) - instance->param->eeprompoll = instance->buff[10] << 8 | - instance->buff[11]; // beget16(&buff[10]); - instance->param->pagesize = instance->buff[12] << 8 | instance->buff[13]; //beget16(&buff[12]); - instance->param->eepromsize = instance->buff[14] << 8 | - instance->buff[15]; //beget16(&buff[14]); - - // 32 bits flashsize (big endian) - instance->param->flashsize = instance->buff[16] << 24 | instance->buff[17] << 16 | - instance->buff[18] << 8 | instance->buff[19]; - //buff[16] * 0x01000000 + buff[17] * 0x00010000 + buff[18] * 0x00000100 + buff[19]; + // call this after reading cfg packet into buff[] + instance->cfg->devicecode = instance->buff[0]; + instance->cfg->revision = instance->buff[1]; + instance->cfg->progtype = instance->buff[2]; + instance->cfg->parmode = instance->buff[3]; + instance->cfg->polling = instance->buff[4]; + instance->cfg->selftimed = instance->buff[5]; + instance->cfg->lockbytes = instance->buff[6]; + instance->cfg->fusebytes = instance->buff[7]; + instance->cfg->flashpoll = instance->buff[8]; + // ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as “flashpoll” + instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11]; + instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13]; + instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15]; + instance->cfg->flashsize = instance->buff[16] << 24 | instance->buff[17] << 16 | + instance->buff[18] << 8 | instance->buff[19]; // avr devices have active low reset, at89sx are active high - instance->rst_active_high = (instance->param->devicecode >= 0xe0); + instance->rst_active_high = (instance->cfg->devicecode >= 0xe0); +} +static bool + avr_isp_prog_set_pmode(AvrIspProg* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + furi_assert(instance); + uint8_t res = 0; + avr_isp_spi_sw_txrx(instance->spi, a); + avr_isp_spi_sw_txrx(instance->spi, b); + res = avr_isp_spi_sw_txrx(instance->spi, c); + avr_isp_spi_sw_txrx(instance->spi, d); + return res == 0x53; } - static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { furi_assert(instance); // Reset target before driving PIN_SCK or PIN_MOSI @@ -235,9 +238,12 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { // Send the enable programming command: furi_delay_ms(50); // datasheet: must be > 20 msec - avr_isp_prog_spi_transaction(instance, 0xAC, 0x53, 0x00, 0x00); - instance->pmode = true; - return true; + //if(avr_isp_prog_set_pmode(instance, 0xAC, 0x53, 0x00, 0x00)) { + if(avr_isp_prog_set_pmode(instance, AVR_ISP_SET_PMODE)) { + instance->pmode = true; + return true; + } + return false; } static void avr_isp_prog_end_pmode(AvrIspProg* instance) { @@ -275,16 +281,16 @@ static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr) { } static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { - if(instance->param->pagesize == 32) { + if(instance->cfg->pagesize == 32) { return instance->addr & 0xFFFFFFF0; } - if(instance->param->pagesize == 64) { + if(instance->cfg->pagesize == 64) { return instance->addr & 0xFFFFFFE0; } - if(instance->param->pagesize == 128) { + if(instance->cfg->pagesize == 128) { return instance->addr & 0xFFFFFFC0; } - if(instance->param->pagesize == 256) { + if(instance->cfg->pagesize == 256) { return instance->addr & 0xFFFFFF80; } return instance->addr; @@ -310,7 +316,7 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) { avr_isp_prog_fill(instance, length); - if(CRC_EOP == avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); avr_isp_prog_tx_ch(instance, avr_isp_prog_write_flash_pages(instance, length)); } else { @@ -340,7 +346,7 @@ static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { // here is a word address, get the byte address uint16_t start = instance->addr * 2; uint16_t remaining = length; - if(length > instance->param->eepromsize) { + if(length > instance->cfg->eepromsize) { instance->error++; return STK_FAILED; } @@ -355,17 +361,16 @@ static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { static void avr_isp_prog_program_page(AvrIspProg* instance) { uint8_t result = STK_FAILED; - unsigned int length = 256 * avr_isp_prog_getch(instance); - length += avr_isp_prog_getch(instance); + uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); uint8_t memtype = avr_isp_prog_getch(instance); - // flash memory @here, (length) bytes - if(memtype == 'F') { //0X46 + // flash memory @addr, (length) bytes + if(memtype == STK_SET_FLASH_TYPE) { avr_isp_prog_write_flash(instance, length); return; } - if(memtype == 'E') { //0X45 + if(memtype == STK_SET_EEROM_TYPE) { result = avr_isp_prog_write_eeprom(instance, length); - if(CRC_EOP == avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); avr_isp_prog_tx_ch(instance, result); @@ -406,23 +411,22 @@ static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t leng } static void avr_isp_prog_read_page(AvrIspProg* instance) { - uint8_t result = (char)STK_FAILED; - int length = 256 * avr_isp_prog_getch(instance); - length += avr_isp_prog_getch(instance); + uint8_t result = STK_FAILED; + uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); uint8_t memtype = avr_isp_prog_getch(instance); - if(CRC_EOP != avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) != CRC_EOP) { instance->error++; avr_isp_prog_tx_ch(instance, STK_NOSYNC); return; } avr_isp_prog_tx_ch(instance, STK_INSYNC); - if(memtype == 'F') result = avr_isp_prog_flash_read_page(instance, length); - if(memtype == 'E') result = avr_isp_prog_eeprom_read_page(instance, length); + if(memtype == STK_SET_FLASH_TYPE) result = avr_isp_prog_flash_read_page(instance, length); + if(memtype == STK_SET_EEROM_TYPE) result = avr_isp_prog_eeprom_read_page(instance, length); avr_isp_prog_tx_ch(instance, result); } static void avr_isp_prog_read_signature(AvrIspProg* instance) { - if(CRC_EOP != avr_isp_prog_getch(instance)) { + if(avr_isp_prog_getch(instance) != CRC_EOP) { instance->error++; avr_isp_prog_tx_ch(instance, STK_NOSYNC); return; @@ -439,14 +443,14 @@ static void avr_isp_prog_read_signature(AvrIspProg* instance) { void avr_isp_prog_avrisp(AvrIspProg* instance) { uint8_t ch = avr_isp_prog_getch(instance); switch(ch) { - case '0': // signon //0x30 + case STK_GET_SYNC: instance->error = 0; avr_isp_prog_empty_reply(instance); break; - case '1': //0x31 + case STK_GET_SIGN_ON: if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); - //SERIAL.print("AVR ISP"); + avr_isp_prog_tx_ch(instance, 'A'); avr_isp_prog_tx_ch(instance, 'V'); avr_isp_prog_tx_ch(instance, 'R'); @@ -461,56 +465,57 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { avr_isp_prog_tx_ch(instance, STK_NOSYNC); } break; - case 'A': //0x41 + case STK_GET_PARAMETER: avr_isp_prog_get_version(instance, avr_isp_prog_getch(instance)); break; - case 'B': //0x42 + case STK_SET_DEVICE: avr_isp_prog_fill(instance, 20); - avr_isp_prog_set_parameters(instance); + avr_isp_prog_set_cfg(instance); avr_isp_prog_empty_reply(instance); break; - case 'E': //0x45// extended parameters - ignore for now + case STK_SET_DEVICE_EXT: // ignore for now avr_isp_prog_fill(instance, 5); avr_isp_prog_empty_reply(instance); break; - case 'P': //0X50 + case STK_ENTER_PROGMODE: if(!instance->pmode) avr_isp_prog_start_pmode(instance); avr_isp_prog_empty_reply(instance); break; - case 'U': //0X55 // set address (word) - instance->addr = avr_isp_prog_getch(instance); - instance->addr += 256 * avr_isp_prog_getch(instance); + case STK_LOAD_ADDRESS: + instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8; + // instance->addr = avr_isp_prog_getch(instance); + // instance->addr += 256 * avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; - case 0x60: //STK_PROG_FLASH - avr_isp_prog_getch(instance); // low addr - avr_isp_prog_getch(instance); // high addr + case STK_PROG_FLASH: // ignore for now + avr_isp_prog_getch(instance); + avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; - case 0x61: //STK_PROG_DATA - avr_isp_prog_getch(instance); // data + case STK_PROG_DATA: // ignore for now + avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; - case 0x64: //STK_PROG_PAGE + case STK_PROG_PAGE: avr_isp_prog_program_page(instance); break; - case 0x74: //STK_READ_PAGE 't' + case STK_READ_PAGE: avr_isp_prog_read_page(instance); break; - case 'V': //0x56 + case STK_UNIVERSAL: avr_isp_prog_universal(instance); break; - case 'Q': //0x51 + case STK_LEAVE_PROGMODE: instance->error = 0; - avr_isp_prog_end_pmode(instance); + if(instance->pmode) avr_isp_prog_end_pmode(instance); avr_isp_prog_empty_reply(instance); break; - case 0x75: //STK_READ_SIGN 'U' + case STK_READ_SIGN: avr_isp_prog_read_signature(instance); break; @@ -524,68 +529,10 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { // anything else we will return STK_UNKNOWN default: instance->error++; - if(CRC_EOP == avr_isp_prog_getch(instance)) + if(avr_isp_prog_getch(instance) == CRC_EOP) avr_isp_prog_tx_ch(instance, STK_UNKNOWN); else avr_isp_prog_tx_ch(instance, STK_NOSYNC); } instance->tx_ok = true; } - -// // this provides a heartbeat on pin 9, so you can tell the software is running. -// uint8_t hbval = 128; -// int8_t hbdelta = 8; -// void heartbeat() { -// static unsigned long last_time = 0; -// unsigned long now = millis(); -// if ((now - last_time) < 40) -// return; -// last_time = now; -// if (hbval > 192) hbdelta = -hbdelta; -// if (hbval < 32) hbdelta = -hbdelta; -// hbval += hbdelta; -// analogWrite(LED_HB, hbval); -// } - -// static bool rst_active_high; - -// void reset_target(bool reset) { -// digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? 1 : 0); -// } - -// void loop(void) { -// // is pmode active? -// if (pmode) { -// digitalWrite(LED_PMODE, 1); -// } else { -// digitalWrite(LED_PMODE, 0); -// } -// // is there an error? -// if (error) { -// digitalWrite(LED_ERR, 1); -// } else { -// digitalWrite(LED_ERR, 0); -// } - -// // light the heartbeat LED -// heartbeat(); -// if (SERIAL.available()) { -// avrisp(); -// } -// } - -// #define PTIME 30 -// void pulse(int pin, int times) { -// do { -// digitalWrite(pin, 1); -// delay(PTIME); -// digitalWrite(pin, 0); -// delay(PTIME); -// } while(times--); -// } - -// void prog_lamp(int state) { -// if(PROG_FLICKER) { -// digitalWrite(LED_PMODE, state); -// } -// } diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h index 4adc5de008b..9de508825a2 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h @@ -1,8 +1,13 @@ #pragma once -#define HWVER 2 -#define SWMAJ 1 -#define SWMIN 18 +// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf + +#define AVR_ISP_HWVER 0X02 +#define AVR_ISP_SWMAJ 0X01 +#define AVR_ISP_SWMIN 0X12 +#define AVP_ISP_SERIAL_CONNECT_TYPE 0X53 +#define AVP_ISP_GET_CONNECT_TYPE 0x93 +#define AVR_ISP_RESP_0 0X00 // STK Definitions #define STK_OK 0x10 @@ -10,6 +15,52 @@ #define STK_UNKNOWN 0x12 #define STK_INSYNC 0x14 #define STK_NOSYNC 0x15 -#define CRC_EOP 0x20 //ok it is a space... +#define CRC_EOP 0x20 + +#define STK_GET_SYNC 0x30 +#define STK_GET_SIGN_ON 0x31 +#define STK_SET_PARAMETER 0x40 +#define STK_GET_PARAMETER 0x41 +#define STK_SET_DEVICE 0x42 +#define STK_SET_DEVICE_EXT 0x45 +#define STK_ENTER_PROGMODE 0x50 +#define STK_LEAVE_PROGMODE 0x51 +#define STK_CHIP_ERASE 0x52 +#define STK_CHECK_AUTOINC 0x53 +#define STK_LOAD_ADDRESS 0x55 +#define STK_UNIVERSAL 0x56 +#define STK_UNIVERSAL_MULTI 0x57 +#define STK_PROG_FLASH 0x60 +#define STK_PROG_DATA 0x61 +#define STK_PROG_FUSE 0x62 +#define STK_PROG_FUSE_EXT 0x65 +#define STK_PROG_LOCK 0x63 +#define STK_PROG_PAGE 0x64 +#define STK_READ_FLASH 0x70 +#define STK_READ_DATA 0x71 +#define STK_READ_FUSE 0x72 +#define STK_READ_LOCK 0x73 +#define STK_READ_PAGE 0x74 +#define STK_READ_SIGN 0x75 +#define STK_READ_OSCCAL 0x76 +#define STK_READ_FUSE_EXT 0x77 +#define STK_READ_OSCCAL_EXT 0x78 +#define STK_HW_VER 0x80 +#define STK_SW_MAJOR 0x81 +#define STK_SW_MINOR 0x82 +#define STK_LEDS 0x83 +#define STK_VTARGET 0x84 +#define STK_VADJUST 0x85 +#define STK_OSC_PSCALE 0x86 +#define STK_OSC_CMATCH 0x87 +#define STK_SCK_DURATION 0x89 +#define STK_BUFSIZEL 0x90 +#define STK_BUFSIZEH 0x91 +#define STK_STK500_TOPCARD_DETECT 0x98 + +#define STK_SET_EEROM_TYPE 0X45 +#define STK_SET_FLASH_TYPE 0X46 + +#define EECHUNK (32) -#define EECHUNK (32) \ No newline at end of file +#define AVR_ISP_SET_PMODE 0xAC, 0x53, 0x00, 0x00 \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c index df22550874f..60a203a87bd 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c @@ -29,7 +29,6 @@ AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { furi_hal_gpio_init(instance->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); furi_hal_gpio_write(instance->sck, false); furi_hal_gpio_init(instance->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - //furi_hal_gpio_write(instance->res, true); furi_hal_gpio_init(instance->res, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); return instance; @@ -38,7 +37,6 @@ AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { void avr_isp_spi_sw_free(AvrIspSpiSw* instance) { furi_assert(instance); - //furi_hal_gpio_write(instance->res, true); furi_hal_gpio_init(instance->res, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h index c0a622e6a57..7e0db53f649 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -7,31 +7,6 @@ #define AVR_ISP_DEVELOPED "SkorP" #define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" -// #define AVR_ISP_KEY_FILE_VERSION 1 -// #define AVR_ISP_KEY_FILE_TYPE "Flipper Weather Station Key File" - -// /** WSRxKeyState state */ -// typedef enum { -// WSRxKeyStateIDLE, -// WSRxKeyStateBack, -// WSRxKeyStateStart, -// WSRxKeyStateAddKey, -// } WSRxKeyState; - -// /** WSHopperState state */ -// typedef enum { -// WSHopperStateOFF, -// WSHopperStateRunnig, -// WSHopperStatePause, -// WSHopperStateRSSITimeOut, -// } WSHopperState; - -// /** WSLock */ -// typedef enum { -// WSLockOff, -// WSLockOn, -// } WSLock; - typedef enum { //AvrIspViewVariableItemList, AvrIspViewSubmenu, @@ -39,10 +14,3 @@ typedef enum { AvrIspViewWidget, } AvrIspView; -// /** AvrIspTxRx state */ -// typedef enum { -// WSTxRxStateIDLE, -// WSTxRxStateRx, -// WSTxRxStateTx, -// WSTxRxStateSleep, -// } WSTxRxState; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index 65ff149be15..54b92c15e4e 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -1,6 +1,7 @@ #include "avr_isp_worker.h" #include "avr_isp_prog.h" #include "avr_isp_spi_sw.h" +#include "avr_isp_chip_arr.h" #include #include "usb_cdc.h" @@ -150,6 +151,15 @@ static int32_t avr_isp_worker_thread(void* context) { UNUSED(instance); uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; + // for(size_t i = 0; i < 372; i++) { + // if(avr_isp_chip_arr[i].sigs[1] == 0x97) { + // if(avr_isp_chip_arr[i].sigs[2] == 0x0B) { + // FURI_LOG_I(TAG, "name %s", avr_isp_chip_arr[i].name); + // break; + // } + // } + // } + FuriThread* prog_thread = furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); furi_thread_start(prog_thread); @@ -162,18 +172,18 @@ static int32_t avr_isp_worker_thread(void* context) { while(len > 0) { avr_isp_prog_rx(prog, buf, len); - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "--> %X", buf[i]); - // } + for(uint8_t i = 0; i < len; i++) { + FURI_LOG_I(TAG, "--> %X", buf[i]); + } len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); } len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); while(len > 0) { - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "<-- %X", buf[i]); - // } + for(uint8_t i = 0; i < len; i++) { + FURI_LOG_I(TAG, "<-- %X", buf[i]); + } furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); furi_delay_ms(1); From d660f1f186d7befc75f91c8302b179cd1618e5d9 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 10 Mar 2023 20:00:51 +0400 Subject: [PATCH 04/50] [AVR_ISP]: refactoring --- .../avr_isp_programmer/application.fam | 5 + .../helpers/avr_isp_worker.c | 137 ++-------------- .../helpers/avr_isp_worker.h | 14 -- .../driver}/avr_isp_chip_arr.c | 0 .../driver}/avr_isp_chip_arr.h | 0 .../{helpers => lib/driver}/avr_isp_prog.c | 152 ++++++++++-------- .../{helpers => lib/driver}/avr_isp_prog.h | 0 .../driver}/avr_isp_prog_cmd.h | 28 +++- .../{helpers => lib/driver}/avr_isp_spi_sw.c | 0 .../{helpers => lib/driver}/avr_isp_spi_sw.h | 0 .../lib/driver/avr_isp_vcp_cdc.c | 115 +++++++++++++ .../lib/driver/avr_isp_vcp_cdc.h | 18 +++ .../scenes/avr_isp_scene_about.c | 4 +- .../scenes/avr_isp_scene_start.c | 2 +- .../views/avr_isp_view_programmer.c | 2 +- .../views/avr_isp_view_programmer.h | 4 - 16 files changed, 262 insertions(+), 219 deletions(-) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_chip_arr.c (100%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_chip_arr.h (100%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_prog.c (85%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_prog.h (100%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_prog_cmd.h (63%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_spi_sw.c (100%) rename applications/plugins/avr_isp_programmer/{helpers => lib/driver}/avr_isp_spi_sw.h (100%) create mode 100644 applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c create mode 100644 applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h diff --git a/applications/plugins/avr_isp_programmer/application.fam b/applications/plugins/avr_isp_programmer/application.fam index f12a9e5fc5b..1b0e931e91e 100644 --- a/applications/plugins/avr_isp_programmer/application.fam +++ b/applications/plugins/avr_isp_programmer/application.fam @@ -11,4 +11,9 @@ App( fap_icon="avr_isp.png", fap_category="GPIO", fap_icon_assets="images", + fap_private_libs=[ + Lib( + name="driver", + ), + ], ) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index 54b92c15e4e..749e3b10f16 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -1,30 +1,12 @@ #include "avr_isp_worker.h" -#include "avr_isp_prog.h" -#include "avr_isp_spi_sw.h" -#include "avr_isp_chip_arr.h" +#include "../lib/driver/avr_isp_prog.h" +#include "../lib/driver/avr_isp_spi_sw.h" +#include "../lib/driver/avr_isp_chip_arr.h" +#include "../lib/driver/avr_isp_vcp_cdc.h" #include -#include "usb_cdc.h" -#include -#include -#include #define TAG "AvrIspWorker" -#define AVR_ISP_VCP_CDC_CH 1 -#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ -#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), - - WorkerEvtTxStop = (1 << 2), - WorkerEvtCdcRx = (1 << 3), - -} WorkerEvtFlags; - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) -#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx) typedef enum { AvrIspWorkerEvtStop = (1 << 0), @@ -33,97 +15,12 @@ typedef enum { #define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) struct AvrIspWorker { - //AvrIspProg* prog; FuriThread* thread; - - AvrIspWorkerUsbConfig cfg; - FuriSemaphore* tx_sem; - volatile bool worker_running; // AvrIspWorkerCallback callback; // void* context; }; -// static void vcp_on_cdc_tx_complete(void* context); -// static void vcp_on_cdc_rx(void* context); -// static void vcp_state_callback(void* context, uint8_t state); -// static void vcp_on_cdc_control_line(void* context, uint8_t state); -//static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); - -// static const CdcCallbacks cdc_cb = { -// vcp_on_cdc_tx_complete, -// vcp_on_cdc_rx, -// vcp_state_callback, -// vcp_on_cdc_control_line, -// vcp_on_line_config, -// }; - -// /* VCP callbacks */ - -// static void vcp_on_cdc_tx_complete(void* context) { -// AvrIspWorker* instance = context; -// furi_semaphore_release(instance->tx_sem); -// } - -// static void vcp_on_cdc_rx(void* context) { -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->tx_thread), WorkerEvtCdcRx); -// } - -// static void vcp_state_callback(void* context, uint8_t state) { -// UNUSED(context); -// UNUSED(state); -// } - -// static void vcp_on_cdc_control_line(void* context, uint8_t state) { -// UNUSED(state); -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtCtrlLineSet); -// } - -// static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { -// UNUSED(config); -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtLineCfgSet); -// } - -// -static void avr_isp_worker_vcp_cdc_init(AvrIspWorker* instance) { - UNUSED(instance); - furi_hal_usb_unlock(); - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - //disable callbacks VCP_CDC=0 - furi_hal_cdc_set_callbacks(0, NULL, NULL); - //set 2 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - - //furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, instance); -} - -static void avr_isp_worker_vcp_cdc_deinit(AvrIspWorker* instance) { - UNUSED(instance); - //disable callbacks AVR_ISP_VCP_CDC_CH - furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); - - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - furi_hal_usb_unlock(); - //set 1 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); -} - static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; uint32_t events = 0; @@ -144,7 +41,7 @@ static int32_t avr_isp_worker_prog_thread(void* context) { */ static int32_t avr_isp_worker_thread(void* context) { AvrIspWorker* instance = context; - avr_isp_worker_vcp_cdc_init(instance); + avr_isp_vcp_cdc_init(); AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed400Khz); @@ -164,33 +61,33 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); furi_thread_start(prog_thread); - FURI_LOG_I(TAG, "AvrIspWorker Start"); + FURI_LOG_D(TAG, "AvrIspWorker Start"); while(instance->worker_running) { furi_delay_ms(1); - size_t len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + size_t len = avr_isp_vcp_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); while(len > 0) { avr_isp_prog_rx(prog, buf, len); - for(uint8_t i = 0; i < len; i++) { - FURI_LOG_I(TAG, "--> %X", buf[i]); - } + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "--> %X", buf[i]); + // } - len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + len = avr_isp_vcp_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); } len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); while(len > 0) { - for(uint8_t i = 0; i < len; i++) { - FURI_LOG_I(TAG, "<-- %X", buf[i]); - } + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "<-- %X", buf[i]); + // } - furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); + avr_isp_vcp_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); furi_delay_ms(1); len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); } } - FURI_LOG_I(TAG, "AvrIspWorker Stop"); + FURI_LOG_D(TAG, "AvrIspWorker Stop"); furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); avr_isp_prog_exit(prog); furi_delay_ms(10); @@ -198,7 +95,7 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_free(prog_thread); avr_isp_prog_free(prog); - avr_isp_worker_vcp_cdc_deinit(instance); + avr_isp_vcp_cdc_deinit(); return 0; } diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h index b64d436b884..d0c6bcdbe76 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h @@ -5,20 +5,6 @@ typedef struct AvrIspWorker AvrIspWorker; -typedef struct { - uint8_t vcp_ch; - // uint8_t uart_ch; - // uint8_t flow_pins; - // uint8_t baudrate_mode; - uint32_t baudrate; -} AvrIspWorkerUsbConfig; - -// typedef void (*AvrIspWorkerCallback)( -// void* context, -// uint32_t frequency, -// float rssi, -// bool signal); - /** Allocate AvrIspWorker * * @param context AvrIsp* context diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.c rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_chip_arr.h rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c similarity index 85% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index 0707e5b59a9..9cb87b54178 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -55,7 +55,6 @@ AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { void avr_isp_prog_free(AvrIspProg* instance) { furi_assert(instance); - furi_stream_buffer_free(instance->stream_tx); furi_stream_buffer_free(instance->stream_rx); free(instance->cfg); @@ -88,6 +87,7 @@ size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len) { } void avr_isp_prog_exit(AvrIspProg* instance) { + furi_assert(instance); instance->exit = true; } @@ -99,7 +99,7 @@ static bool avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) { static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { furi_assert(instance); - //ToDo !!!!!!!!!!!!!!! + //ToDo can be optimized while(!furi_stream_buffer_bytes_available(instance->stream_rx)) { furi_delay_ms(5); if(instance->exit) break; @@ -124,13 +124,17 @@ static void avr_isp_prog_reset_target(AvrIspProg* instance, bool reset) { false); } -static uint8_t - avr_isp_prog_spi_transaction(AvrIspProg* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { +static uint8_t avr_isp_prog_spi_transaction( + AvrIspProg* instance, + uint8_t cmd, + uint8_t addr_hi, + uint8_t addr_lo, + uint8_t data) { furi_assert(instance); - avr_isp_spi_sw_txrx(instance->spi, a); - avr_isp_spi_sw_txrx(instance->spi, b); - avr_isp_spi_sw_txrx(instance->spi, c); - return avr_isp_spi_sw_txrx(instance->spi, d); + avr_isp_spi_sw_txrx(instance->spi, cmd); + avr_isp_spi_sw_txrx(instance->spi, addr_hi); + avr_isp_spi_sw_txrx(instance->spi, addr_lo); + return avr_isp_spi_sw_txrx(instance->spi, data); } static void avr_isp_prog_empty_reply(AvrIspProg* instance) { @@ -168,7 +172,7 @@ static void avr_isp_prog_get_version(AvrIspProg* instance, uint8_t data) { case STK_SW_MINOR: avr_isp_prog_breply(instance, AVR_ISP_SWMIN); break; - case AVP_ISP_GET_CONNECT_TYPE: + case AVP_ISP_CONNECT_TYPE: avr_isp_prog_breply(instance, AVP_ISP_SERIAL_CONNECT_TYPE); break; default: @@ -208,6 +212,16 @@ static bool avr_isp_spi_sw_txrx(instance->spi, d); return res == 0x53; } + +static void avr_isp_prog_end_pmode(AvrIspProg* instance) { + furi_assert(instance); + avr_isp_prog_reset_target(instance, false); + // We're about to take the target out of reset + // so configure SPI pins as input + if(instance->spi) avr_isp_spi_sw_free(instance->spi); + instance->pmode = false; +} + static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { furi_assert(instance); // Reset target before driving PIN_SCK or PIN_MOSI @@ -226,35 +240,28 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { // Pulse RESET after PIN_SCK is low: avr_isp_spi_sw_sck_set(instance->spi, false); - furi_delay_ms(20); // discharge PIN_SCK, value arbitrally chosen + // discharge PIN_SCK, value arbitrally chosen + furi_delay_ms(20); avr_isp_prog_reset_target(instance, false); // Pulse must be minimum 2 target CPU speed cycles // so 100 usec is ok for CPU speeds above 20KHz - //furi_delay_us(100); furi_delay_ms(1); avr_isp_prog_reset_target(instance, true); // Send the enable programming command: - furi_delay_ms(50); // datasheet: must be > 20 msec - //if(avr_isp_prog_set_pmode(instance, 0xAC, 0x53, 0x00, 0x00)) { + // datasheet: must be > 20 msec + furi_delay_ms(50); if(avr_isp_prog_set_pmode(instance, AVR_ISP_SET_PMODE)) { instance->pmode = true; return true; + } else { + avr_isp_prog_end_pmode(instance); } return false; } -static void avr_isp_prog_end_pmode(AvrIspProg* instance) { - furi_assert(instance); - avr_isp_prog_reset_target(instance, false); - // We're about to take the target out of reset - // so configure SPI pins as input - avr_isp_spi_sw_free(instance->spi); - instance->pmode = false; -} - static void avr_isp_prog_universal(AvrIspProg* instance) { furi_assert(instance); uint8_t data; @@ -265,38 +272,38 @@ static void avr_isp_prog_universal(AvrIspProg* instance) { avr_isp_prog_breply(instance, data); } -static void avr_isp_prog_flash(AvrIspProg* instance, uint8_t hilo, uint16_t addr, uint8_t data) { - avr_isp_prog_spi_transaction(instance, 0x40 + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data); -} - static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr) { - // if(PROG_FLICKER) { - // prog_lamp(0); - // } - avr_isp_prog_spi_transaction(instance, 0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); - // if(PROG_FLICKER) { - // delay(PTIME); - // prog_lamp(1); - // } + furi_assert(instance); + avr_isp_prog_spi_transaction(instance, AVR_ISP_COMMIT(addr)); } static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { - if(instance->cfg->pagesize == 32) { - return instance->addr & 0xFFFFFFF0; - } - if(instance->cfg->pagesize == 64) { - return instance->addr & 0xFFFFFFE0; - } - if(instance->cfg->pagesize == 128) { - return instance->addr & 0xFFFFFFC0; - } - if(instance->cfg->pagesize == 256) { - return instance->addr & 0xFFFFFF80; + furi_assert(instance); + uint16_t page = 0; + switch(instance->cfg->pagesize) { + case 32: + page = instance->addr & 0xFFFFFFF0; + break; + case 64: + page = instance->addr & 0xFFFFFFE0; + break; + case 128: + page = instance->addr & 0xFFFFFFC0; + break; + case 256: + page = instance->addr & 0xFFFFFF80; + break; + + default: + page = instance->addr; + break; } - return instance->addr; + + return page; } static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t length) { + furi_assert(instance); size_t x = 0; uint16_t page = avr_isp_prog_current_page(instance); while(x < length) { @@ -304,8 +311,11 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt avr_isp_prog_commit(instance, page); page = avr_isp_prog_current_page(instance); } - avr_isp_prog_flash(instance, 0, instance->addr, instance->buff[x++]); - avr_isp_prog_flash(instance, 1, instance->addr, instance->buff[x++]); + avr_isp_prog_spi_transaction( + instance, AVR_ISP_WRITE_FLASH_LO(instance->addr, instance->buff[x++])); + + avr_isp_prog_spi_transaction( + instance, AVR_ISP_WRITE_FLASH_HI(instance->addr, instance->buff[x++])); instance->addr++; } @@ -315,6 +325,7 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt } static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) { + furi_assert(instance); avr_isp_prog_fill(instance, length); if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); @@ -328,21 +339,20 @@ static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) { // write (length) bytes, (start) is a byte address static uint8_t avr_isp_prog_write_eeprom_chunk(AvrIspProg* instance, uint16_t start, uint16_t length) { + furi_assert(instance); // this writes byte-by-byte, // page writing may be faster (4 bytes at a time) avr_isp_prog_fill(instance, length); - //prog_lamp(0); for(uint16_t x = 0; x < length; x++) { uint16_t addr = start + x; - avr_isp_prog_spi_transaction( - instance, 0xC0, (addr >> 8) & 0xFF, addr & 0xFF, instance->buff[x]); + avr_isp_prog_spi_transaction(instance, AVR_ISP_WRITE_EEROM(addr, instance->buff[x])); furi_delay_ms(45); } - //prog_lamp(1); return STK_OK; } static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { + furi_assert(instance); // here is a word address, get the byte address uint16_t start = instance->addr * 2; uint16_t remaining = length; @@ -350,16 +360,17 @@ static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) { instance->error++; return STK_FAILED; } - while(remaining > EECHUNK) { - avr_isp_prog_write_eeprom_chunk(instance, start, EECHUNK); - start += EECHUNK; - remaining -= EECHUNK; + while(remaining > AVR_ISP_EECHUNK) { + avr_isp_prog_write_eeprom_chunk(instance, start, AVR_ISP_EECHUNK); + start += AVR_ISP_EECHUNK; + remaining -= AVR_ISP_EECHUNK; } avr_isp_prog_write_eeprom_chunk(instance, start, remaining); return STK_OK; } static void avr_isp_prog_program_page(AvrIspProg* instance) { + furi_assert(instance); uint8_t result = STK_FAILED; uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); uint8_t memtype = avr_isp_prog_getch(instance); @@ -384,33 +395,34 @@ static void avr_isp_prog_program_page(AvrIspProg* instance) { return; } -static uint8_t avr_isp_prog_flash_read(AvrIspProg* instance, uint8_t hilo, uint16_t addr) { - return avr_isp_prog_spi_transaction( - instance, 0x20 + hilo * 8, (addr >> 8) & 0xFF, addr & 0xFF, 0); -} - static uint8_t avr_isp_prog_flash_read_page(AvrIspProg* instance, uint16_t length) { + furi_assert(instance); for(uint16_t x = 0; x < length; x += 2) { - avr_isp_prog_tx_ch(instance, avr_isp_prog_flash_read(instance, 0, instance->addr)); - avr_isp_prog_tx_ch(instance, avr_isp_prog_flash_read(instance, 1, instance->addr)); + avr_isp_prog_tx_ch( + instance, + avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(instance->addr))); + avr_isp_prog_tx_ch( + instance, + avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(instance->addr))); instance->addr++; } return STK_OK; } static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t length) { + furi_assert(instance); // here again we have a word address uint16_t start = instance->addr * 2; for(uint16_t x = 0; x < length; x++) { uint16_t addr = start + x; avr_isp_prog_tx_ch( - instance, - avr_isp_prog_spi_transaction(instance, 0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF)); + instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_EEROM(addr))); } return STK_OK; } static void avr_isp_prog_read_page(AvrIspProg* instance) { + furi_assert(instance); uint8_t result = STK_FAILED; uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance); uint8_t memtype = avr_isp_prog_getch(instance); @@ -426,6 +438,7 @@ static void avr_isp_prog_read_page(AvrIspProg* instance) { } static void avr_isp_prog_read_signature(AvrIspProg* instance) { + furi_assert(instance); if(avr_isp_prog_getch(instance) != CRC_EOP) { instance->error++; avr_isp_prog_tx_ch(instance, STK_NOSYNC); @@ -433,14 +446,15 @@ static void avr_isp_prog_read_signature(AvrIspProg* instance) { } avr_isp_prog_tx_ch(instance, STK_INSYNC); - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x00, 0x00)); - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x01, 0x00)); - avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, 0x30, 0x00, 0x02, 0x00)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY)); + avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER)); avr_isp_prog_tx_ch(instance, STK_OK); } void avr_isp_prog_avrisp(AvrIspProg* instance) { + furi_assert(instance); uint8_t ch = avr_isp_prog_getch(instance); switch(ch) { case STK_GET_SYNC: @@ -483,8 +497,6 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { break; case STK_LOAD_ADDRESS: instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8; - // instance->addr = avr_isp_prog_getch(instance); - // instance->addr += 256 * avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_prog.h rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h similarity index 63% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h index 9de508825a2..20f37399814 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_prog_cmd.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h @@ -1,14 +1,32 @@ #pragma once -// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf - +// http://ww1.microchip.com/downloads/en/appnotes/atmel-0943-in-system-programming_applicationnote_avr910.pdf +// AVR ISP Definitions #define AVR_ISP_HWVER 0X02 #define AVR_ISP_SWMAJ 0X01 #define AVR_ISP_SWMIN 0X12 #define AVP_ISP_SERIAL_CONNECT_TYPE 0X53 -#define AVP_ISP_GET_CONNECT_TYPE 0x93 +#define AVP_ISP_CONNECT_TYPE 0x93 #define AVR_ISP_RESP_0 0X00 +#define AVR_ISP_SET_PMODE 0xAC, 0x53, 0x00, 0x00 +#define AVR_ISP_READ_VENDOR 0x30, 0x00, 0x00, 0x00 +#define AVR_ISP_READ_PART_FAMILY 0x30, 0x00, 0x01, 0x00 +#define AVR_ISP_READ_PART_NUMBER 0x30, 0x00, 0x02, 0x00 + +#define AVR_ISP_WRITE_FLASH_LO(add, data) 0x40, (add >> 8) & 0xFF, add & 0xFF, data +#define AVR_ISP_WRITE_FLASH_HI(add, data) 0x48, (add >> 8) & 0xFF, add & 0xFF, data +#define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00 +#define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00 + +#define AVR_ISP_WRITE_EEROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data +#define AVR_ISP_READ_EEROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF + +#define AVR_ISP_COMMIT(add) 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 + +#define AVR_ISP_EECHUNK 0x20 + +// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf // STK Definitions #define STK_OK 0x10 #define STK_FAILED 0x11 @@ -60,7 +78,3 @@ #define STK_SET_EEROM_TYPE 0X45 #define STK_SET_FLASH_TYPE 0X46 - -#define EECHUNK (32) - -#define AVR_ISP_SET_PMODE 0xAC, 0x53, 0x00, 0x00 \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.c rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_spi_sw.h rename to applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c new file mode 100644 index 00000000000..e01546ebaa0 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c @@ -0,0 +1,115 @@ +#include "avr_isp_vcp_cdc.h" + +#include + +typedef enum { + WorkerEvtStop = (1 << 0), + WorkerEvtRxDone = (1 << 1), + + WorkerEvtTxStop = (1 << 2), + WorkerEvtCdcRx = (1 << 3), + +} WorkerEvtFlags; + +#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) +#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx) + +// typedef struct { +// uint8_t vcp_ch; +// // uint8_t uart_ch; +// // uint8_t flow_pins; +// // uint8_t baudrate_mode; +// uint32_t baudrate; +// } AvrIspWorkerUsbConfig; + +// struct AvrIspVcpCdc { +// AvrIspWorkerUsbConfig cfg; +// FuriSemaphore* tx_sem; +// }; + +// static void vcp_on_cdc_tx_complete(void* context); +// static void vcp_on_cdc_rx(void* context); +// static void vcp_state_callback(void* context, uint8_t state); +// static void vcp_on_cdc_control_line(void* context, uint8_t state); +//static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); + +// static const CdcCallbacks cdc_cb = { +// vcp_on_cdc_tx_complete, +// vcp_on_cdc_rx, +// vcp_state_callback, +// vcp_on_cdc_control_line, +// vcp_on_line_config, +// }; + +// /* VCP callbacks */ + +// static void vcp_on_cdc_tx_complete(void* context) { +// AvrIspWorker* instance = context; +// furi_semaphore_release(instance->tx_sem); +// } + +// static void vcp_on_cdc_rx(void* context) { +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->tx_thread), WorkerEvtCdcRx); +// } + +// static void vcp_state_callback(void* context, uint8_t state) { +// UNUSED(context); +// UNUSED(state); +// } + +// static void vcp_on_cdc_control_line(void* context, uint8_t state) { +// UNUSED(state); +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtCtrlLineSet); +// } + +// static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { +// UNUSED(config); +// AvrIspWorker* instance = context; +// UNUSED (instance); +// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtLineCfgSet); +// } + +// + +void avr_isp_vcp_cdc_init(void) { + furi_hal_usb_unlock(); + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + //disable callbacks VCP_CDC=0 + furi_hal_cdc_set_callbacks(0, NULL, NULL); + //set 2 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); + + //furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, instance); +} + +void avr_isp_vcp_cdc_deinit(void) { + //disable callbacks AVR_ISP_VCP_CDC_CH + furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); + + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + furi_hal_usb_unlock(); + //set 1 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); +} + +inline int32_t avr_isp_vcp_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { + return furi_hal_cdc_receive(if_num, buf, max_len); +} + +inline void avr_isp_vcp_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { + furi_hal_cdc_send(if_num, buf, len); +} diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h new file mode 100644 index 00000000000..46159a16f75 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include "usb_cdc.h" +#include +#include +#include + +typedef struct AvrIspVcpCdc AvrIspVcpCdc; + +#define AVR_ISP_VCP_CDC_CH 1 +#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ +#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) + +void avr_isp_vcp_cdc_init(void); +void avr_isp_vcp_cdc_deinit(void); +int32_t avr_isp_vcp_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); +void avr_isp_vcp_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c index 5a175ac3748..54d74d6bd0e 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c @@ -20,7 +20,7 @@ void avr_isp_scene_about_on_enter(void* context) { furi_string_cat_printf(temp_str, "Github: %s\n\n", AVR_ISP_GITHUB); furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf(temp_str, "Avr Isp Programmer\nBla Bla Bla\nbla bla bla\n\n"); + furi_string_cat_printf(temp_str, "AVR ISP Programmer\nBla Bla Bla\nbla bla bla\n\n"); furi_string_cat_printf(temp_str, "Supported protocols:\n"); @@ -42,7 +42,7 @@ void avr_isp_scene_about_on_enter(void* context) { 14, AlignCenter, AlignBottom, - "\e#\e! Avr Isp Programmer \e!\n", + "\e#\e! AVR ISP Programmer \e!\n", false); widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); furi_string_free(temp_str); diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c index 238596ce8f6..fc290c3e9d8 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -17,7 +17,7 @@ void avr_isp_scene_start_on_enter(void* context) { submenu_add_item( submenu, - "Avr Isp Programmer", + "AVR ISP Programmer", SubmenuIndexAvrIspProgrammer, avr_isp_scene_start_submenu_callback, app); diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c index dfa7d658e50..0ca0bfd7893 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -37,7 +37,7 @@ void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "AvrIspProg"); + canvas_draw_str(canvas, 63, 46, "AVRISPProg"); canvas_set_font(canvas, FontSecondary); } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h index 6790c668c48..0cbdc793172 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h @@ -8,10 +8,6 @@ typedef struct AvrIspProgrammerView AvrIspProgrammerView; typedef void (*AvrIspProgrammerViewCallback)(AvrIspCustomEvent event, void* context); -// void avr_asp_programmer_view_set_rssi(AvrIspProgrammerView* instance, float rssi); - -// void avr_asp_programmer_view_set_lock(AvrIspProgrammerView* avr_asp_programmer_view, avr_asp_programmerLock keyboard); - void avr_asp_programmer_view_set_callback( AvrIspProgrammerView* instance, AvrIspProgrammerViewCallback callback, From 85ad336d1c009b84b817ef026915f2d5d2e2c2d1 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 10 Mar 2023 21:38:41 +0400 Subject: [PATCH 05/50] [AVR_ISP]: add auto detect AVR chip --- .../helpers/avr_isp_worker.c | 77 ++++++++++----- .../helpers/avr_isp_worker.h | 24 +++-- .../images/ChipLooking_64x64/frame_01.png | Bin 0 -> 7231 bytes .../images/ChipLooking_64x64/frame_02.png | Bin 0 -> 6909 bytes .../images/ChipLooking_64x64/frame_03.png | Bin 0 -> 7308 bytes .../images/ChipLooking_64x64/frame_rate | 1 + .../lib/driver/avr_isp_chip_arr.c | 4 +- .../lib/driver/avr_isp_chip_arr.h | 3 +- .../views/avr_isp_view_programmer.c | 88 +++++++++++++----- 9 files changed, 140 insertions(+), 57 deletions(-) create mode 100644 applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png create mode 100644 applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png create mode 100644 applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png create mode 100644 applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index 749e3b10f16..b338e5dc38e 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -1,5 +1,6 @@ #include "avr_isp_worker.h" #include "../lib/driver/avr_isp_prog.h" +#include "../lib/driver/avr_isp_prog_cmd.h" #include "../lib/driver/avr_isp_spi_sw.h" #include "../lib/driver/avr_isp_chip_arr.h" #include "../lib/driver/avr_isp_vcp_cdc.h" @@ -17,20 +18,52 @@ typedef enum { struct AvrIspWorker { FuriThread* thread; volatile bool worker_running; - // AvrIspWorkerCallback callback; - // void* context; + AvrIspWorkerCallback callback; + void* context; }; +void avr_isp_worker_detect_chip(AvrIspWorker* instance) { + uint8_t buf_cmd[] = { + STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; + uint8_t buf_data[256] = {0}; + size_t ind = 0; + + FURI_LOG_D(TAG, "Detecting AVR chip"); + AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed400Khz); + + avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); + + for(uint8_t i = 0; i < 3; i++) { + avr_isp_prog_avrisp(prog); + } + + size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); + UNUSED(len); + if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { + for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { + if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { + if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { + FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); + break; + } + } + } + } + avr_isp_prog_free(prog); + + if(instance->callback) instance->callback(instance->context, avr_isp_chip_arr[ind].name); +} + static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; uint32_t events = 0; - FURI_LOG_I(TAG, "AvrIspProgWorker Start"); + FURI_LOG_D(TAG, "AvrIspProgWorker Start"); while(1) { events = furi_thread_flags_get(); if(events & AvrIspWorkerEvtStop) break; avr_isp_prog_avrisp(prog); } - FURI_LOG_I(TAG, "AvrIspProgWorker Stop"); + FURI_LOG_D(TAG, "AvrIspProgWorker Stop"); return 0; } @@ -48,7 +81,7 @@ static int32_t avr_isp_worker_thread(void* context) { UNUSED(instance); uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; - // for(size_t i = 0; i < 372; i++) { + // for(size_t i = 0; i < avr_isp_chip_arr_size; i++) { // if(avr_isp_chip_arr[i].sigs[1] == 0x97) { // if(avr_isp_chip_arr[i].sigs[2] == 0x0B) { // FURI_LOG_I(TAG, "name %s", avr_isp_chip_arr[i].name); @@ -61,7 +94,7 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); furi_thread_start(prog_thread); - FURI_LOG_D(TAG, "AvrIspWorker Start"); + FURI_LOG_D(TAG, "Start"); while(instance->worker_running) { furi_delay_ms(1); @@ -69,25 +102,25 @@ static int32_t avr_isp_worker_thread(void* context) { while(len > 0) { avr_isp_prog_rx(prog, buf, len); - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "--> %X", buf[i]); - // } + for(uint8_t i = 0; i < len; i++) { + FURI_LOG_I(TAG, "--> %X", buf[i]); + } len = avr_isp_vcp_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); } len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); while(len > 0) { - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "<-- %X", buf[i]); - // } + for(uint8_t i = 0; i < len; i++) { + FURI_LOG_I(TAG, "<-- %X", buf[i]); + } avr_isp_vcp_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); furi_delay_ms(1); len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); } } - FURI_LOG_D(TAG, "AvrIspWorker Stop"); + FURI_LOG_D(TAG, "Stop"); furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); avr_isp_prog_exit(prog); furi_delay_ms(10); @@ -117,15 +150,15 @@ void avr_isp_worker_free(AvrIspWorker* instance) { free(instance); } -// void avr_isp_worker_set_callback( -// AvrIspWorker* instance, -// AvrIspWorkerCallback callback, -// void* context) { -// furi_assert(instance); -// furi_assert(context); -// instance->callback = callback; -// instance->context = context; -// } +void avr_isp_worker_set_callback( + AvrIspWorker* instance, + AvrIspWorkerCallback callback, + void* context) { + furi_assert(instance); + furi_assert(context); + instance->callback = callback; + instance->context = context; +} void avr_isp_worker_start(AvrIspWorker* instance) { furi_assert(instance); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h index d0c6bcdbe76..b23dbe412ef 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h @@ -5,6 +5,8 @@ typedef struct AvrIspWorker AvrIspWorker; +typedef void (*AvrIspWorkerCallback)(void* context, const char* name); + /** Allocate AvrIspWorker * * @param context AvrIsp* context @@ -18,16 +20,16 @@ AvrIspWorker* avr_isp_worker_alloc(void* context); */ void avr_isp_worker_free(AvrIspWorker* instance); -// /** Callback AvrIspWorker -// * -// * @param instance AvrIspWorker instance -// * @param callback AvrIspWorkerOverrunCallback callback -// * @param context -// */ -// void avr_isp_worker_set_pair_callback( -// AvrIspWorker* instance, -// AvrIspWorkerCallback callback, -// void* context); +/** Callback AvrIspWorker + * + * @param instance AvrIspWorker instance + * @param callback AvrIspWorkerOverrunCallback callback + * @param context + */ +void avr_isp_worker_set_callback( + AvrIspWorker* instance, + AvrIspWorkerCallback callback, + void* context); /** Start AvrIspWorker * @@ -46,3 +48,5 @@ void avr_isp_worker_stop(AvrIspWorker* instance); * @return bool - true if running */ bool avr_isp_worker_is_running(AvrIspWorker* instance); + +void avr_isp_worker_detect_chip(AvrIspWorker* instance); diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png b/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff2e3042e540d8b499118e9edf4ecd180b39511 GIT binary patch literal 7231 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 NY%KPgSDX4C`yZHc9FG71 literal 0 HcmV?d00001 diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png b/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png new file mode 100644 index 0000000000000000000000000000000000000000..1342dc7bf95265db5d0ab2924e1ef03fe4df9943 GIT binary patch literal 7308 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 literal 0 HcmV?d00001 diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate b/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate new file mode 100644 index 00000000000..d8263ee9860 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c index 2c173f5eacd..2be54de6a59 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c @@ -381,4 +381,6 @@ const AvrIspChipArr avr_isp_chip_arr[] = { // Value of -1 typically means unkn {"AVR128DB48", 369, F_AVR8X, {0x1E, 0x97, 0x0C}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 61}, // atdf, avrdude {"AVR128DA64", 370, F_AVR8X, {0x1E, 0x97, 0x07}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 64}, // atdf, avrdude {"AVR128DB64", 371, F_AVR8X, {0x1E, 0x97, 0x0B}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 65}, // atdf, avrdude -}; \ No newline at end of file +}; + +const size_t avr_isp_chip_arr_size = COUNT_OF(avr_isp_chip_arr); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h index 0f4bd344cf3..66f16a7b96a 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h @@ -29,4 +29,5 @@ struct AvrIspChipArr { // Value of -1 typically means unknown typedef struct AvrIspChipArr AvrIspChipArr; -extern const AvrIspChipArr avr_isp_chip_arr[]; \ No newline at end of file +extern const AvrIspChipArr avr_isp_chip_arr[]; +extern const size_t avr_isp_chip_arr_size; \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c index 0ca0bfd7893..bb9cebcaf85 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -17,6 +17,9 @@ struct AvrIspProgrammerView { typedef struct { uint16_t idx; + IconAnimation* icon; + const char* name_chip; + bool detect_chip; } AvrIspProgrammerViewModel; void avr_asp_programmer_view_set_callback( @@ -32,13 +35,22 @@ void avr_asp_programmer_view_set_callback( void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { UNUSED(model); canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); + // canvas_set_color(canvas, ColorBlack); + // canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + // canvas_set_font(canvas, FontPrimary); + // canvas_draw_str(canvas, 63, 46, "AVRISPProg"); + // canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 63, 46, "AVRISPProg"); - canvas_set_font(canvas, FontSecondary); + if(!model->detect_chip) { + canvas_draw_icon_animation(canvas, 0, 0, model->icon); + canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); + canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); + } else { + canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); + canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + } } bool avr_asp_programmer_view_input(InputEvent* event, void* context) { @@ -52,16 +64,40 @@ bool avr_asp_programmer_view_input(InputEvent* event, void* context) { return true; } +static void avr_asp_programmer_detect_chip_callback(void* context, const char* name) { + furi_assert(context); + AvrIspProgrammerView* instance = context; + FURI_LOG_D("ssss", "%s", name); + with_view_model( + instance->view, + AvrIspProgrammerViewModel * model, + { + model->name_chip = name; + model->detect_chip = true; + icon_animation_stop(model->icon); + }, + true); +} void avr_asp_programmer_view_enter(void* context) { furi_assert(context); AvrIspProgrammerView* instance = context; + + with_view_model( + instance->view, + AvrIspProgrammerViewModel * model, + { + icon_animation_start(model->icon); + model->detect_chip = false; + }, + false); + //Start worker instance->worker = avr_isp_worker_alloc(instance->context); - // avr_isp_worker_set_callback( - // instance->worker, - // (SubGhzFrequencyAnalyzerWorkerPairCallback)avr_isp_callback, - // instance); + avr_isp_worker_set_callback( + instance->worker, avr_asp_programmer_detect_chip_callback, instance); + + avr_isp_worker_detect_chip(instance->worker); avr_isp_worker_start(instance->worker); } @@ -74,6 +110,12 @@ void avr_asp_programmer_view_exit(void* context) { avr_isp_worker_stop(instance->worker); } avr_isp_worker_free(instance->worker); + + with_view_model( + instance->view, + AvrIspProgrammerViewModel * model, + { icon_animation_stop(model->icon); }, + false); } AvrIspProgrammerView* avr_asp_programmer_view_alloc() { @@ -89,26 +131,26 @@ AvrIspProgrammerView* avr_asp_programmer_view_alloc() { view_set_enter_callback(instance->view, avr_asp_programmer_view_enter); view_set_exit_callback(instance->view, avr_asp_programmer_view_exit); - // with_view_model( - // instance->view, - // AvrIspProgrammerViewModel * model, - // { - // // - // }, - // true); + with_view_model( + instance->view, + AvrIspProgrammerViewModel * model, + { + model->icon = icon_animation_alloc(&A_ChipLooking_64x64); + view_tie_icon_animation(instance->view, model->icon); + model->detect_chip = false; + }, + false); return instance; } void avr_asp_programmer_view_free(AvrIspProgrammerView* instance) { furi_assert(instance); - // with_view_model( - // avr_asp_programmer->view, - // AvrIspProgrammerViewModel * model, - // { - // // - // }, - // false); + with_view_model( + instance->view, + AvrIspProgrammerViewModel * model, + { icon_animation_free(model->icon); }, + false); view_free(instance->view); free(instance); } From e3b6c234d3ba64ddafb615a4367b8930a724feb2 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 10 Mar 2023 22:11:38 +0400 Subject: [PATCH 06/50] [AVR_ISP]: fix auto detect chip --- .../helpers/avr_isp_worker.c | 33 ++++++++++++++----- .../lib/driver/avr_isp_prog.c | 3 +- .../views/avr_isp_view_programmer.c | 1 - 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index b338e5dc38e..63292aa2577 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -36,22 +36,39 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { for(uint8_t i = 0; i < 3; i++) { avr_isp_prog_avrisp(prog); } - size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); UNUSED(len); + + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "<-- %X", buf_data[i]); + // } + if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { - for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { - if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { - if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { - FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); - break; + if(buf_data[3] == 0x00) { + ind = avr_isp_chip_arr_size + 1; //No detect chip + } else { + for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { + if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { + if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { + FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); + break; + } } } } } avr_isp_prog_free(prog); - - if(instance->callback) instance->callback(instance->context, avr_isp_chip_arr[ind].name); + if(instance->callback) { + if(ind > avr_isp_chip_arr_size) { + //ToDo add output ID chip + instance->callback(instance->context, "No detect"); + } else if(ind < avr_isp_chip_arr_size) { + instance->callback(instance->context, avr_isp_chip_arr[ind].name); + } else { + //ToDo add output ID chip + instance->callback(instance->context, "unknown"); + } + } } static int32_t avr_isp_worker_prog_thread(void* context) { diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index 9cb87b54178..a31423317d4 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -131,6 +131,7 @@ static uint8_t avr_isp_prog_spi_transaction( uint8_t addr_lo, uint8_t data) { furi_assert(instance); + avr_isp_spi_sw_txrx(instance->spi, cmd); avr_isp_spi_sw_txrx(instance->spi, addr_hi); avr_isp_spi_sw_txrx(instance->spi, addr_lo); @@ -256,8 +257,6 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { if(avr_isp_prog_set_pmode(instance, AVR_ISP_SET_PMODE)) { instance->pmode = true; return true; - } else { - avr_isp_prog_end_pmode(instance); } return false; } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c index bb9cebcaf85..99c705abf71 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -67,7 +67,6 @@ bool avr_asp_programmer_view_input(InputEvent* event, void* context) { static void avr_asp_programmer_detect_chip_callback(void* context, const char* name) { furi_assert(context); AvrIspProgrammerView* instance = context; - FURI_LOG_D("ssss", "%s", name); with_view_model( instance->view, AvrIspProgrammerViewModel * model, From 327fdcd667329cf8f6efbb61c187b7867930b76c Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 10 Mar 2023 22:14:39 +0400 Subject: [PATCH 07/50] [AVR_ISP]: fix syntax --- applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h index 7e0db53f649..3dcd8c45f03 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -13,4 +13,3 @@ typedef enum { AvrIspViewProgrammer, AvrIspViewWidget, } AvrIspView; - From 1319dbd79fbe078ed2b198b40e2c87f12d860422 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 14 Mar 2023 00:17:10 +0400 Subject: [PATCH 08/50] [AVR_ISP]: refactoring --- .../helpers/avr_isp_worker.c | 179 ++++++++++++++---- .../lib/driver/avr_isp_prog.c | 55 +++--- .../lib/driver/avr_isp_prog.h | 2 + .../lib/driver/avr_isp_vcp_cdc.c | 115 ----------- .../lib/driver/avr_isp_vcp_cdc.h | 18 -- 5 files changed, 170 insertions(+), 199 deletions(-) delete mode 100644 applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c delete mode 100644 applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index 63292aa2577..e26a387386b 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -3,7 +3,7 @@ #include "../lib/driver/avr_isp_prog_cmd.h" #include "../lib/driver/avr_isp_spi_sw.h" #include "../lib/driver/avr_isp_chip_arr.h" -#include "../lib/driver/avr_isp_vcp_cdc.h" +//#include "../lib/driver/avr_isp_vcp_cdc.h" #include @@ -11,9 +11,15 @@ typedef enum { AvrIspWorkerEvtStop = (1 << 0), -} AvrIspWorkerEvt; + AvrIspWorkerEvtProgRun = (1 << 1), + + AvrIspWorkerEvtRx = (1 << 2), + AvrIspWorkerEvtTxCoplete = (1 << 3), + AvrIspWorkerEvtTx = (1 << 4), + + //AvrIspWorkerEvtCfg = (1 << 5), -#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) +} AvrIspWorkerEvt; struct AvrIspWorker { FuriThread* thread; @@ -22,6 +28,98 @@ struct AvrIspWorker { void* context; }; +#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop | AvrIspWorkerEvtProgRun) +#define AVR_ISP_WORKER_ALL_EVENTS \ + (AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop) + +//########################/* VCP CDC */############################################# +#include "usb_cdc.h" +#include +#include +#include + +#define AVR_ISP_VCP_CDC_CH 1 +#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ +#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) + +static void vcp_on_cdc_tx_complete(void* context); +static void vcp_on_cdc_rx(void* context); +static void vcp_state_callback(void* context, uint8_t state); +static void vcp_on_cdc_control_line(void* context, uint8_t state); +static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); + +static const CdcCallbacks cdc_cb = { + vcp_on_cdc_tx_complete, + vcp_on_cdc_rx, + vcp_state_callback, + vcp_on_cdc_control_line, + vcp_on_line_config, +}; + +/* VCP callbacks */ + +static void vcp_on_cdc_tx_complete(void* context) { + furi_assert(context); + AvrIspWorker* instance = context; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTxCoplete); +} + +static void vcp_on_cdc_rx(void* context) { + furi_assert(context); + AvrIspWorker* instance = context; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx); +} + +static void vcp_state_callback(void* context, uint8_t state) { + UNUSED(context); + UNUSED(state); +} + +static void vcp_on_cdc_control_line(void* context, uint8_t state) { + UNUSED(state); + UNUSED(context); +} + +static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { + UNUSED(config); + UNUSED(context); + //AvrIspWorker* instance = context; + //furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtCfg); +} + +static void avr_isp_worker_vcp_cdc_init(void* context) { + furi_hal_usb_unlock(); + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + //disable callbacks VCP_CDC=0 + furi_hal_cdc_set_callbacks(0, NULL, NULL); + //set 2 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); + + furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, context); +} + +static void avr_isp_worker_vcp_cdc_deinit(void) { + //disable callbacks AVR_ISP_VCP_CDC_CH + furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); + + Cli* cli = furi_record_open(RECORD_CLI); + //close cli + cli_session_close(cli); + furi_hal_usb_unlock(); + //set 1 cdc + furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); + //open cli VCP_CDC=0 + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); +} + +//################################################################################# + void avr_isp_worker_detect_chip(AvrIspWorker* instance) { uint8_t buf_cmd[] = { STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; @@ -29,7 +127,7 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { size_t ind = 0; FURI_LOG_D(TAG, "Detecting AVR chip"); - AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed400Khz); + AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed1Mhz); avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); @@ -73,17 +171,27 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; - uint32_t events = 0; FURI_LOG_D(TAG, "AvrIspProgWorker Start"); while(1) { - events = furi_thread_flags_get(); - if(events & AvrIspWorkerEvtStop) break; - avr_isp_prog_avrisp(prog); + // uint32_t events = furi_thread_flags_wait( + // AVR_ISP_WORKER_PROG_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); + + if(furi_thread_flags_get() & AvrIspWorkerEvtStop) break; + // if(events & AvrIspWorkerEvtProgRun) { + // FURI_LOG_D(TAG, "events RUN"); + avr_isp_prog_avrisp(prog); + // } } FURI_LOG_D(TAG, "AvrIspProgWorker Stop"); return 0; } +static void avr_isp_worker_prog_tx_data(void* context) { + furi_assert(context); + AvrIspWorker* instance = context; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTx); +} + /** Worker thread * * @param context @@ -91,21 +199,13 @@ static int32_t avr_isp_worker_prog_thread(void* context) { */ static int32_t avr_isp_worker_thread(void* context) { AvrIspWorker* instance = context; - avr_isp_vcp_cdc_init(); + avr_isp_worker_vcp_cdc_init(instance); - AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed400Khz); + AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed1Mhz); + avr_isp_prog_set_tx_callback(prog, avr_isp_worker_prog_tx_data, instance); - UNUSED(instance); uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; - - // for(size_t i = 0; i < avr_isp_chip_arr_size; i++) { - // if(avr_isp_chip_arr[i].sigs[1] == 0x97) { - // if(avr_isp_chip_arr[i].sigs[2] == 0x0B) { - // FURI_LOG_I(TAG, "name %s", avr_isp_chip_arr[i].name); - // break; - // } - // } - // } + size_t len = 0; FuriThread* prog_thread = furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog); @@ -113,28 +213,30 @@ static int32_t avr_isp_worker_thread(void* context) { FURI_LOG_D(TAG, "Start"); while(instance->worker_running) { - furi_delay_ms(1); - - size_t len = avr_isp_vcp_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); - while(len > 0) { + uint32_t events = + furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); + + if(events & AvrIspWorkerEvtRx) { + len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "--> %X", buf[i]); + // } avr_isp_prog_rx(prog, buf, len); + + } - for(uint8_t i = 0; i < len; i++) { - FURI_LOG_I(TAG, "--> %X", buf[i]); - } + if((events & AvrIspWorkerEvtTxCoplete) || (events & AvrIspWorkerEvtTx)) { + len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); - len = avr_isp_vcp_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); - } + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "<-- %X", buf[i]); + // } - len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); - while(len > 0) { - for(uint8_t i = 0; i < len; i++) { - FURI_LOG_I(TAG, "<-- %X", buf[i]); - } + if(len > 0) furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); + } - avr_isp_vcp_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len); - furi_delay_ms(1); - len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN); + if(events & AvrIspWorkerEvtStop) { + break; } } FURI_LOG_D(TAG, "Stop"); @@ -145,7 +247,7 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_free(prog_thread); avr_isp_prog_free(prog); - avr_isp_vcp_cdc_deinit(); + avr_isp_worker_vcp_cdc_deinit(); return 0; } @@ -191,6 +293,7 @@ void avr_isp_worker_stop(AvrIspWorker* instance) { furi_assert(instance->worker_running); instance->worker_running = false; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtStop); furi_thread_join(instance->thread); } diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index a31423317d4..03643cfbe2b 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -32,11 +32,13 @@ struct AvrIspProg { uint16_t error; uint16_t addr; bool pmode; - bool tx_ok; bool exit; bool rst_active_high; uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; AvrIspSpiSwSpeed spi_speed; + + AvrIspProgCallback callback; + void* context; }; AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { @@ -47,7 +49,6 @@ AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { instance->stream_tx = furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); instance->spi_speed = spi_speed; - instance->tx_ok = false; instance->rst_active_high = false; instance->exit = false; return instance; @@ -65,25 +66,13 @@ bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len) { furi_assert(instance); furi_assert(data); furi_assert(len != 0); - size_t ret = furi_stream_buffer_send(instance->stream_rx, data, sizeof(uint8_t) * len, 100); + size_t ret = furi_stream_buffer_send(instance->stream_rx, data, sizeof(uint8_t) * len, 0); return ret == sizeof(uint8_t) * len; } size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len) { furi_assert(instance); - if(!instance->tx_ok) return 0; - size_t len = 0; - if(furi_stream_buffer_bytes_available(instance->stream_tx) > max_len) { - len = furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 100); - } else { - len = furi_stream_buffer_receive( - instance->stream_tx, - data, - sizeof(int8_t) * furi_stream_buffer_bytes_available(instance->stream_tx), - 100); - instance->tx_ok = false; - } - return len; + return furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 0); } void avr_isp_prog_exit(AvrIspProg* instance) { @@ -91,21 +80,24 @@ void avr_isp_prog_exit(AvrIspProg* instance) { instance->exit = true; } -static bool avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) { +void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context) { + furi_assert(instance); + furi_assert(context); + instance->callback = callback; + instance->context = context; +} + +static void avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) { furi_assert(instance); - size_t ret = furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), 10); - return ret == sizeof(uint8_t); + furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), FuriWaitForever); } static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { furi_assert(instance); - //ToDo can be optimized - while(!furi_stream_buffer_bytes_available(instance->stream_rx)) { - furi_delay_ms(5); - if(instance->exit) break; - } uint8_t data[1] = {0}; - furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 10); + while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) { + if(instance->exit) break; + }; return data[0]; } @@ -246,7 +238,7 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { avr_isp_prog_reset_target(instance, false); // Pulse must be minimum 2 target CPU speed cycles - // so 100 usec is ok for CPU speeds above 20KHz + // so 0 usec is ok for CPU speeds above 20KHz furi_delay_ms(1); avr_isp_prog_reset_target(instance, true); @@ -273,7 +265,9 @@ static void avr_isp_prog_universal(AvrIspProg* instance) { static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr) { furi_assert(instance); + furi_delay_ms(2); avr_isp_prog_spi_transaction(instance, AVR_ISP_COMMIT(addr)); + furi_delay_ms(2); } static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { @@ -319,7 +313,6 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt } avr_isp_prog_commit(instance, page); - return STK_OK; } @@ -545,5 +538,11 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { else avr_isp_prog_tx_ch(instance, STK_NOSYNC); } - instance->tx_ok = true; + + // if(!instance->tx_ok) { + // instance->tx_ok = true; + if(instance->callback) { + instance->callback(instance->context); + } + // } } diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h index d44366e7954..777eec5ccaf 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h @@ -4,6 +4,7 @@ #include typedef struct AvrIspProg AvrIspProg; +typedef void (*AvrIspProgCallback)(void* context); AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed); void avr_isp_prog_free(AvrIspProg* instance); @@ -11,3 +12,4 @@ bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len); size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len); void avr_isp_prog_avrisp(AvrIspProg* instance); void avr_isp_prog_exit(AvrIspProg* instance); +void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context); diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c deleted file mode 100644 index e01546ebaa0..00000000000 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "avr_isp_vcp_cdc.h" - -#include - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), - - WorkerEvtTxStop = (1 << 2), - WorkerEvtCdcRx = (1 << 3), - -} WorkerEvtFlags; - -#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone) -#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx) - -// typedef struct { -// uint8_t vcp_ch; -// // uint8_t uart_ch; -// // uint8_t flow_pins; -// // uint8_t baudrate_mode; -// uint32_t baudrate; -// } AvrIspWorkerUsbConfig; - -// struct AvrIspVcpCdc { -// AvrIspWorkerUsbConfig cfg; -// FuriSemaphore* tx_sem; -// }; - -// static void vcp_on_cdc_tx_complete(void* context); -// static void vcp_on_cdc_rx(void* context); -// static void vcp_state_callback(void* context, uint8_t state); -// static void vcp_on_cdc_control_line(void* context, uint8_t state); -//static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config); - -// static const CdcCallbacks cdc_cb = { -// vcp_on_cdc_tx_complete, -// vcp_on_cdc_rx, -// vcp_state_callback, -// vcp_on_cdc_control_line, -// vcp_on_line_config, -// }; - -// /* VCP callbacks */ - -// static void vcp_on_cdc_tx_complete(void* context) { -// AvrIspWorker* instance = context; -// furi_semaphore_release(instance->tx_sem); -// } - -// static void vcp_on_cdc_rx(void* context) { -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->tx_thread), WorkerEvtCdcRx); -// } - -// static void vcp_state_callback(void* context, uint8_t state) { -// UNUSED(context); -// UNUSED(state); -// } - -// static void vcp_on_cdc_control_line(void* context, uint8_t state) { -// UNUSED(state); -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtCtrlLineSet); -// } - -// static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { -// UNUSED(config); -// AvrIspWorker* instance = context; -// UNUSED (instance); -// //furi_thread_flags_set(furi_thread_get_id(instance->thread), WorkerEvtLineCfgSet); -// } - -// - -void avr_isp_vcp_cdc_init(void) { - furi_hal_usb_unlock(); - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - //disable callbacks VCP_CDC=0 - furi_hal_cdc_set_callbacks(0, NULL, NULL); - //set 2 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - - //furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, instance); -} - -void avr_isp_vcp_cdc_deinit(void) { - //disable callbacks AVR_ISP_VCP_CDC_CH - furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL); - - Cli* cli = furi_record_open(RECORD_CLI); - //close cli - cli_session_close(cli); - furi_hal_usb_unlock(); - //set 1 cdc - furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - //open cli VCP_CDC=0 - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); -} - -inline int32_t avr_isp_vcp_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len) { - return furi_hal_cdc_receive(if_num, buf, max_len); -} - -inline void avr_isp_vcp_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len) { - furi_hal_cdc_send(if_num, buf, len); -} diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h deleted file mode 100644 index 46159a16f75..00000000000 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_vcp_cdc.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include "usb_cdc.h" -#include -#include -#include - -typedef struct AvrIspVcpCdc AvrIspVcpCdc; - -#define AVR_ISP_VCP_CDC_CH 1 -#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ -#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5) - -void avr_isp_vcp_cdc_init(void); -void avr_isp_vcp_cdc_deinit(void); -int32_t avr_isp_vcp_cdc_receive(uint8_t if_num, uint8_t* buf, uint16_t max_len); -void avr_isp_vcp_cdc_send(uint8_t if_num, uint8_t* buf, uint16_t len); \ No newline at end of file From 0160d7032e5b7182aa6a95022ca776add61b04dc Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 14 Mar 2023 14:28:56 +0400 Subject: [PATCH 09/50] [AVR_ISP]: fix fast write flash --- .../lib/driver/avr_isp_prog.c | 42 ++++++++++++------- .../lib/driver/avr_isp_prog_cmd.h | 6 +-- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index 03643cfbe2b..118909922d5 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -238,7 +238,7 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { avr_isp_prog_reset_target(instance, false); // Pulse must be minimum 2 target CPU speed cycles - // so 0 usec is ok for CPU speeds above 20KHz + // so 100 usec is ok for CPU speeds above 20KHz furi_delay_ms(1); avr_isp_prog_reset_target(instance, true); @@ -263,11 +263,21 @@ static void avr_isp_prog_universal(AvrIspProg* instance) { avr_isp_prog_breply(instance, data); } -static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr) { +static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t data) { furi_assert(instance); - furi_delay_ms(2); avr_isp_prog_spi_transaction(instance, AVR_ISP_COMMIT(addr)); - furi_delay_ms(2); + /* polling flash */ + if(data == 0xFF) { + furi_delay_ms(5); + } else { + /* polling flash */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { + break; + }; + } + } } static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) { @@ -301,7 +311,8 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt uint16_t page = avr_isp_prog_current_page(instance); while(x < length) { if(page != avr_isp_prog_current_page(instance)) { - avr_isp_prog_commit(instance, page); + --x; + avr_isp_prog_commit(instance, page, instance->buff[x++]); page = avr_isp_prog_current_page(instance); } avr_isp_prog_spi_transaction( @@ -312,7 +323,7 @@ static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t lengt instance->addr++; } - avr_isp_prog_commit(instance, page); + avr_isp_prog_commit(instance, page, instance->buff[--x]); return STK_OK; } @@ -337,8 +348,8 @@ static uint8_t avr_isp_prog_fill(instance, length); for(uint16_t x = 0; x < length; x++) { uint16_t addr = start + x; - avr_isp_prog_spi_transaction(instance, AVR_ISP_WRITE_EEROM(addr, instance->buff[x])); - furi_delay_ms(45); + avr_isp_prog_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, instance->buff[x])); + furi_delay_ms(10); } return STK_OK; } @@ -371,7 +382,7 @@ static void avr_isp_prog_program_page(AvrIspProg* instance) { avr_isp_prog_write_flash(instance, length); return; } - if(memtype == STK_SET_EEROM_TYPE) { + if(memtype == STK_SET_EEPROM_TYPE) { result = avr_isp_prog_write_eeprom(instance, length); if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); @@ -408,7 +419,7 @@ static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t leng for(uint16_t x = 0; x < length; x++) { uint16_t addr = start + x; avr_isp_prog_tx_ch( - instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_EEROM(addr))); + instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr))); } return STK_OK; } @@ -425,7 +436,7 @@ static void avr_isp_prog_read_page(AvrIspProg* instance) { } avr_isp_prog_tx_ch(instance, STK_INSYNC); if(memtype == STK_SET_FLASH_TYPE) result = avr_isp_prog_flash_read_page(instance, length); - if(memtype == STK_SET_EEROM_TYPE) result = avr_isp_prog_eeprom_read_page(instance, length); + if(memtype == STK_SET_EEPROM_TYPE) result = avr_isp_prog_eeprom_read_page(instance, length); avr_isp_prog_tx_ch(instance, result); } @@ -484,7 +495,11 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { avr_isp_prog_empty_reply(instance); break; case STK_ENTER_PROGMODE: - if(!instance->pmode) avr_isp_prog_start_pmode(instance); + if(!instance->pmode) { + for(uint8_t i = 0; i < 16; i++) { + if(avr_isp_prog_start_pmode(instance)) break; + } + } avr_isp_prog_empty_reply(instance); break; case STK_LOAD_ADDRESS: @@ -539,10 +554,7 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { avr_isp_prog_tx_ch(instance, STK_NOSYNC); } - // if(!instance->tx_ok) { - // instance->tx_ok = true; if(instance->callback) { instance->callback(instance->context); } - // } } diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h index 20f37399814..9ca83818148 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h @@ -19,8 +19,8 @@ #define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00 #define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00 -#define AVR_ISP_WRITE_EEROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data -#define AVR_ISP_READ_EEROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF +#define AVR_ISP_WRITE_EEPROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data +#define AVR_ISP_READ_EEPROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF #define AVR_ISP_COMMIT(add) 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 @@ -76,5 +76,5 @@ #define STK_BUFSIZEH 0x91 #define STK_STK500_TOPCARD_DETECT 0x98 -#define STK_SET_EEROM_TYPE 0X45 +#define STK_SET_EEPROM_TYPE 0X45 #define STK_SET_FLASH_TYPE 0X46 From afebd2a7c1c4a385e4c5989839c1ad51b5923e7d Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 14 Mar 2023 17:27:50 +0400 Subject: [PATCH 10/50] AVR_ISP: auto set SPI speed --- .../helpers/avr_isp_worker.c | 60 ++++++++----------- .../helpers/avr_isp_worker.h | 5 +- .../lib/driver/avr_isp_prog.c | 54 ++++++++++------- .../lib/driver/avr_isp_prog.h | 3 +- .../lib/driver/avr_isp_spi_sw.h | 1 + 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index e26a387386b..cc0401a3169 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -3,7 +3,6 @@ #include "../lib/driver/avr_isp_prog_cmd.h" #include "../lib/driver/avr_isp_spi_sw.h" #include "../lib/driver/avr_isp_chip_arr.h" -//#include "../lib/driver/avr_isp_vcp_cdc.h" #include @@ -11,24 +10,24 @@ typedef enum { AvrIspWorkerEvtStop = (1 << 0), - AvrIspWorkerEvtProgRun = (1 << 1), - AvrIspWorkerEvtRx = (1 << 2), - AvrIspWorkerEvtTxCoplete = (1 << 3), - AvrIspWorkerEvtTx = (1 << 4), + AvrIspWorkerEvtRx = (1 << 1), + AvrIspWorkerEvtTxCoplete = (1 << 2), + AvrIspWorkerEvtTx = (1 << 3), - //AvrIspWorkerEvtCfg = (1 << 5), + //AvrIspWorkerEvtCfg = (1 << 4), } AvrIspWorkerEvt; struct AvrIspWorker { FuriThread* thread; + AvrIspSpiSwSpeed spi_speed; volatile bool worker_running; AvrIspWorkerCallback callback; void* context; }; -#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop | AvrIspWorkerEvtProgRun) +#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) #define AVR_ISP_WORKER_ALL_EVENTS \ (AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop) @@ -76,15 +75,13 @@ static void vcp_state_callback(void* context, uint8_t state) { } static void vcp_on_cdc_control_line(void* context, uint8_t state) { - UNUSED(state); UNUSED(context); + UNUSED(state); } static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { - UNUSED(config); UNUSED(context); - //AvrIspWorker* instance = context; - //furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtCfg); + UNUSED(config); } static void avr_isp_worker_vcp_cdc_init(void* context) { @@ -123,24 +120,20 @@ static void avr_isp_worker_vcp_cdc_deinit(void) { void avr_isp_worker_detect_chip(AvrIspWorker* instance) { uint8_t buf_cmd[] = { STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; - uint8_t buf_data[256] = {0}; + + uint8_t buf_data[64] = {0}; size_t ind = 0; FURI_LOG_D(TAG, "Detecting AVR chip"); - AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed1Mhz); - + AvrIspProg* prog = avr_isp_prog_init(); avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); - for(uint8_t i = 0; i < 3; i++) { + for(uint8_t i = 0; i < 2; i++) { avr_isp_prog_avrisp(prog); } size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); UNUSED(len); - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "<-- %X", buf_data[i]); - // } - if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { if(buf_data[3] == 0x00) { ind = avr_isp_chip_arr_size + 1; //No detect chip @@ -164,7 +157,7 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { instance->callback(instance->context, avr_isp_chip_arr[ind].name); } else { //ToDo add output ID chip - instance->callback(instance->context, "unknown"); + instance->callback(instance->context, "Unknown"); } } } @@ -173,14 +166,8 @@ static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; FURI_LOG_D(TAG, "AvrIspProgWorker Start"); while(1) { - // uint32_t events = furi_thread_flags_wait( - // AVR_ISP_WORKER_PROG_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); - if(furi_thread_flags_get() & AvrIspWorkerEvtStop) break; - // if(events & AvrIspWorkerEvtProgRun) { - // FURI_LOG_D(TAG, "events RUN"); - avr_isp_prog_avrisp(prog); - // } + avr_isp_prog_avrisp(prog); } FURI_LOG_D(TAG, "AvrIspProgWorker Stop"); return 0; @@ -201,7 +188,7 @@ static int32_t avr_isp_worker_thread(void* context) { AvrIspWorker* instance = context; avr_isp_worker_vcp_cdc_init(instance); - AvrIspProg* prog = avr_isp_prog_init(AvrIspSpiSwSpeed1Mhz); + AvrIspProg* prog = avr_isp_prog_init(); avr_isp_prog_set_tx_callback(prog, avr_isp_worker_prog_tx_data, instance); uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE]; @@ -217,12 +204,15 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); if(events & AvrIspWorkerEvtRx) { - len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); - // for(uint8_t i = 0; i < len; i++) { - // FURI_LOG_I(TAG, "--> %X", buf[i]); - // } - avr_isp_prog_rx(prog, buf, len); - + if(avr_isp_prog_spaces_rx(prog) >= AVR_ISP_VCP_CDC_PKT_LEN) { + len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN); + // for(uint8_t i = 0; i < len; i++) { + // FURI_LOG_I(TAG, "--> %X", buf[i]); + // } + avr_isp_prog_rx(prog, buf, len); + } else { + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx); + } } if((events & AvrIspWorkerEvtTxCoplete) || (events & AvrIspWorkerEvtTx)) { @@ -257,8 +247,6 @@ AvrIspWorker* avr_isp_worker_alloc(void* context) { AvrIspWorker* instance = malloc(sizeof(AvrIspWorker)); instance->thread = furi_thread_alloc_ex("AvrIspWorker", 2048, avr_isp_worker_thread, instance); - // SubGhz* subghz = context; - // instance->setting = subghz->setting; return instance; } diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h index b23dbe412ef..82f56c22061 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h @@ -1,7 +1,6 @@ #pragma once #include -#include "../avr_isp_app_i.h" typedef struct AvrIspWorker AvrIspWorker; @@ -49,4 +48,8 @@ void avr_isp_worker_stop(AvrIspWorker* instance); */ bool avr_isp_worker_is_running(AvrIspWorker* instance); +/** Detect chip + * + * @param instance AvrIspWorker instance + */ void avr_isp_worker_detect_chip(AvrIspWorker* instance); diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index 118909922d5..c709592343c 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -35,20 +35,18 @@ struct AvrIspProg { bool exit; bool rst_active_high; uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; - AvrIspSpiSwSpeed spi_speed; AvrIspProgCallback callback; void* context; }; -AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed) { +AvrIspProg* avr_isp_prog_init(void) { AvrIspProg* instance = malloc(sizeof(AvrIspProg)); instance->cfg = malloc(sizeof(AvrIspProgCfgDevice)); instance->stream_rx = furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); instance->stream_tx = furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t)); - instance->spi_speed = spi_speed; instance->rst_active_high = false; instance->exit = false; return instance; @@ -62,6 +60,10 @@ void avr_isp_prog_free(AvrIspProg* instance) { free(instance); } +size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) { + return furi_stream_buffer_spaces_available(instance->stream_rx); +} + bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len) { furi_assert(instance); furi_assert(data); @@ -208,14 +210,17 @@ static bool static void avr_isp_prog_end_pmode(AvrIspProg* instance) { furi_assert(instance); - avr_isp_prog_reset_target(instance, false); - // We're about to take the target out of reset - // so configure SPI pins as input - if(instance->spi) avr_isp_spi_sw_free(instance->spi); + if(instance->pmode) { + avr_isp_prog_reset_target(instance, false); + // We're about to take the target out of reset + // so configure SPI pins as input + if(instance->spi) avr_isp_spi_sw_free(instance->spi); + } + instance->pmode = false; } -static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { +static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_speed) { furi_assert(instance); // Reset target before driving PIN_SCK or PIN_MOSI @@ -225,7 +230,7 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { // which for many arduino's is not the SS pin. // So we have to configure RESET as output here, // (reset_target() first sets the correct level) - instance->spi = avr_isp_spi_sw_init(instance->spi_speed); + instance->spi = avr_isp_spi_sw_init(spi_speed); avr_isp_prog_reset_target(instance, true); // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": @@ -253,6 +258,24 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance) { return false; } +static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { + AvrIspSpiSwSpeed spi_speed[] = { + AvrIspSpiSwSpeed1Mhz, + AvrIspSpiSwSpeed400Khz, + AvrIspSpiSwSpeed250Khz, + AvrIspSpiSwSpeed125Khz, + AvrIspSpiSwSpeed40Khz, + AvrIspSpiSwSpeed20Khz, + }; + + for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { + if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { + return true; + } + } + return false; +} + static void avr_isp_prog_universal(AvrIspProg* instance) { furi_assert(instance); uint8_t data; @@ -495,18 +518,13 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { avr_isp_prog_empty_reply(instance); break; case STK_ENTER_PROGMODE: - if(!instance->pmode) { - for(uint8_t i = 0; i < 16; i++) { - if(avr_isp_prog_start_pmode(instance)) break; - } - } + if(!instance->pmode) avr_isp_prog_auto_set_spi_speed_start_pmode(instance); avr_isp_prog_empty_reply(instance); break; case STK_LOAD_ADDRESS: instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8; avr_isp_prog_empty_reply(instance); break; - case STK_PROG_FLASH: // ignore for now avr_isp_prog_getch(instance); avr_isp_prog_getch(instance); @@ -516,15 +534,12 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; - case STK_PROG_PAGE: avr_isp_prog_program_page(instance); break; - case STK_READ_PAGE: avr_isp_prog_read_page(instance); break; - case STK_UNIVERSAL: avr_isp_prog_universal(instance); break; @@ -533,18 +548,15 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { if(instance->pmode) avr_isp_prog_end_pmode(instance); avr_isp_prog_empty_reply(instance); break; - case STK_READ_SIGN: avr_isp_prog_read_signature(instance); break; - // expecting a command, not CRC_EOP // this is how we can get back in sync case CRC_EOP: instance->error++; avr_isp_prog_tx_ch(instance, STK_NOSYNC); break; - // anything else we will return STK_UNKNOWN default: instance->error++; diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h index 777eec5ccaf..2c15ab06636 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h @@ -6,8 +6,9 @@ typedef struct AvrIspProg AvrIspProg; typedef void (*AvrIspProgCallback)(void* context); -AvrIspProg* avr_isp_prog_init(AvrIspSpiSwSpeed spi_speed); +AvrIspProg* avr_isp_prog_init(void); void avr_isp_prog_free(AvrIspProg* instance); +size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) ; bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len); size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len); void avr_isp_prog_avrisp(AvrIspProg* instance); diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h index 9ab63b3b5a9..c65e851b191 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h @@ -8,6 +8,7 @@ typedef enum { AvrIspSpiSwSpeed250Khz = 2, AvrIspSpiSwSpeed125Khz = 4, AvrIspSpiSwSpeed40Khz = 12, + AvrIspSpiSwSpeed20Khz = 24, } AvrIspSpiSwSpeed; typedef struct AvrIspSpiSw AvrIspSpiSw; From d4a0643b85cfa729c4e08e097a314d5b02c383f4 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 14 Mar 2023 18:15:30 +0400 Subject: [PATCH 11/50] AVR_ISP: add clock 4Mhz on &gpio_ext_pa4 --- .../plugins/avr_isp_programmer/helpers/avr_isp_worker.c | 9 +++++++-- .../plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c | 4 ++++ .../avr_isp_programmer/lib/driver/avr_isp_spi_sw.c | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index cc0401a3169..80a6f2e6a9c 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -1,4 +1,5 @@ #include "avr_isp_worker.h" +#include #include "../lib/driver/avr_isp_prog.h" #include "../lib/driver/avr_isp_prog_cmd.h" #include "../lib/driver/avr_isp_spi_sw.h" @@ -128,14 +129,14 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { AvrIspProg* prog = avr_isp_prog_init(); avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); - for(uint8_t i = 0; i < 2; i++) { + for(uint8_t i = 0; i < 3; i++) { avr_isp_prog_avrisp(prog); } size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); UNUSED(len); if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { - if(buf_data[3] == 0x00) { + if(buf_data[3] != 0x1E) { ind = avr_isp_chip_arr_size + 1; //No detect chip } else { for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { @@ -188,6 +189,9 @@ static int32_t avr_isp_worker_thread(void* context) { AvrIspWorker* instance = context; avr_isp_worker_vcp_cdc_init(instance); + /* start PWM on &gpio_ext_pa4 */ + furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); + AvrIspProg* prog = avr_isp_prog_init(); avr_isp_prog_set_tx_callback(prog, avr_isp_worker_prog_tx_data, instance); @@ -237,6 +241,7 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_free(prog_thread); avr_isp_prog_free(prog); + furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); avr_isp_worker_vcp_cdc_deinit(); return 0; } diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index c709592343c..b7b3bee3940 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -40,6 +40,8 @@ struct AvrIspProg { void* context; }; +static void avr_isp_prog_end_pmode(AvrIspProg* instance); + AvrIspProg* avr_isp_prog_init(void) { AvrIspProg* instance = malloc(sizeof(AvrIspProg)); instance->cfg = malloc(sizeof(AvrIspProgCfgDevice)); @@ -54,6 +56,7 @@ AvrIspProg* avr_isp_prog_init(void) { void avr_isp_prog_free(AvrIspProg* instance) { furi_assert(instance); + if(instance->pmode) avr_isp_prog_end_pmode(instance); furi_stream_buffer_free(instance->stream_tx); furi_stream_buffer_free(instance->stream_rx); free(instance->cfg); @@ -255,6 +258,7 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_ instance->pmode = true; return true; } + if(instance->spi) avr_isp_spi_sw_free(instance->spi); return false; } diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c index 60a203a87bd..30c018d0c78 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c @@ -5,7 +5,7 @@ #define AVR_ISP_SPI_SW_MISO &gpio_ext_pa6 #define AVR_ISP_SPI_SW_MOSI &gpio_ext_pa7 #define AVR_ISP_SPI_SW_SCK &gpio_ext_pb3 -#define AVR_ISP_RESET &gpio_ext_pa4 +#define AVR_ISP_RESET &gpio_ext_pb2 struct AvrIspSpiSw { AvrIspSpiSwSpeed speed_wait_time; @@ -36,7 +36,6 @@ AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) { void avr_isp_spi_sw_free(AvrIspSpiSw* instance) { furi_assert(instance); - furi_hal_gpio_init(instance->res, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); From 29413f88d690a8f06f7b66bfe6de29ae15c18b85 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 14 Mar 2023 20:42:20 +0400 Subject: [PATCH 12/50] AVR_ISP: fix PVS --- .../plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c | 5 +---- .../plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index b7b3bee3940..c71252df340 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -115,10 +115,7 @@ static void avr_isp_prog_fill(AvrIspProg* instance, size_t len) { static void avr_isp_prog_reset_target(AvrIspProg* instance, bool reset) { furi_assert(instance); - avr_isp_spi_sw_res_set( - instance->spi, - ((reset && instance->rst_active_high) || (!reset && !instance->rst_active_high)) ? true : - false); + avr_isp_spi_sw_res_set(instance->spi, (reset == instance->rst_active_high) ? true : false); } static uint8_t avr_isp_prog_spi_transaction( diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c index 30c018d0c78..f60850c841a 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c @@ -53,7 +53,7 @@ uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data) { if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) furi_delay_us(instance->speed_wait_time - 1); - data = (data << 1) | furi_hal_gpio_read(instance->miso); + data = (data << 1) | furi_hal_gpio_read(instance->miso); //-V792 furi_hal_gpio_write(instance->sck, false); if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz) From 9c98444878cb0ddd1eafbc8933e26d137c621512 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 15 Mar 2023 12:02:40 +0400 Subject: [PATCH 13/50] AVR_ISP: fix "[CRASH][ISR 4] NULL pointer dereference" with no AVR chip connected --- .../avr_isp_programmer/lib/driver/avr_isp_prog.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index c71252df340..bef39a335b4 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -56,7 +56,7 @@ AvrIspProg* avr_isp_prog_init(void) { void avr_isp_prog_free(AvrIspProg* instance) { furi_assert(instance); - if(instance->pmode) avr_isp_prog_end_pmode(instance); + if(instance->spi) avr_isp_prog_end_pmode(instance); furi_stream_buffer_free(instance->stream_tx); furi_stream_buffer_free(instance->stream_rx); free(instance->cfg); @@ -214,7 +214,9 @@ static void avr_isp_prog_end_pmode(AvrIspProg* instance) { avr_isp_prog_reset_target(instance, false); // We're about to take the target out of reset // so configure SPI pins as input + if(instance->spi) avr_isp_spi_sw_free(instance->spi); + instance->spi = NULL; } instance->pmode = false; @@ -230,9 +232,10 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_ // which for many arduino's is not the SS pin. // So we have to configure RESET as output here, // (reset_target() first sets the correct level) + if(instance->spi) avr_isp_spi_sw_free(instance->spi); instance->spi = avr_isp_spi_sw_init(spi_speed); - avr_isp_prog_reset_target(instance, true); + avr_isp_prog_reset_target(instance, true); // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": // Pulse RESET after PIN_SCK is low: @@ -255,7 +258,6 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_ instance->pmode = true; return true; } - if(instance->spi) avr_isp_spi_sw_free(instance->spi); return false; } @@ -268,7 +270,6 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { AvrIspSpiSwSpeed40Khz, AvrIspSpiSwSpeed20Khz, }; - for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { return true; @@ -483,6 +484,7 @@ static void avr_isp_prog_read_signature(AvrIspProg* instance) { void avr_isp_prog_avrisp(AvrIspProg* instance) { furi_assert(instance); uint8_t ch = avr_isp_prog_getch(instance); + switch(ch) { case STK_GET_SYNC: instance->error = 0; From c79c70a299fe59801394b1bb6fcc58044b3e30de Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 16 Mar 2023 22:49:16 +0400 Subject: [PATCH 14/50] AVR_ISP: add AVR ISP Reader --- .../plugins/avr_isp_programmer/avr_isp_app.c | 11 + .../avr_isp_programmer/avr_isp_app_i.h | 2 + .../avr_isp_programmer/helpers/avr_isp.c | 444 ++++++++++++++++++ .../avr_isp_programmer/helpers/avr_isp.h | 26 + .../helpers/avr_isp_rw_worker.c | 288 ++++++++++++ .../helpers/avr_isp_rw_worker.h | 58 +++ .../helpers/avr_isp_rw_worker_cmd.h | 8 + .../helpers/avr_isp_types.h | 1 + .../helpers/avr_isp_worker.c | 3 +- .../helpers/flipper_hex_file.c | 95 ++++ .../helpers/flipper_hex_file.h | 11 + .../lib/driver/avr_isp_prog.c | 19 +- .../lib/driver/avr_isp_prog_cmd.h | 18 +- .../scenes/avr_isp_scene_config.h | 1 + .../scenes/avr_isp_scene_reader.c | 38 ++ .../scenes/avr_isp_scene_start.c | 10 + .../views/avr_isp_view_reader.c | 160 +++++++ .../views/avr_isp_view_reader.h | 22 + 18 files changed, 1210 insertions(+), 5 deletions(-) create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app.c b/applications/plugins/avr_isp_programmer/avr_isp_app.c index 6b9a1e74677..98d45b1cf83 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app.c +++ b/applications/plugins/avr_isp_programmer/avr_isp_app.c @@ -67,6 +67,13 @@ AvrIspApp* avr_isp_app_alloc() { app->view_dispatcher, AvrIspViewProgrammer, avr_asp_programmer_view_get_view(app->avr_asp_programmer_view)); + + // Reader view + app->avr_asp_reader_view = avr_asp_reader_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + AvrIspViewReader, + avr_asp_reader_view_get_view(app->avr_asp_reader_view)); scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); @@ -92,6 +99,10 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer); avr_asp_programmer_view_free(app->avr_asp_programmer_view); + // Reader view + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader); + avr_asp_reader_view_free(app->avr_asp_reader_view); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h index 12c6c2b88dd..cf8ad2168d6 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h @@ -12,6 +12,7 @@ //#include #include "views/avr_isp_view_programmer.h" +#include "views/avr_isp_view_reader.h" typedef struct AvrIspApp AvrIspApp; @@ -24,4 +25,5 @@ struct AvrIspApp { Submenu* submenu; Widget* widget; AvrIspProgrammerView* avr_asp_programmer_view; + AvrIspReaderView* avr_asp_reader_view; }; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c new file mode 100644 index 00000000000..6f95a5a57b9 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c @@ -0,0 +1,444 @@ +#include "avr_isp.h" +#include "../lib/driver/avr_isp_prog_cmd.h" +#include "../lib/driver/avr_isp_spi_sw.h" + +#include + +#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320 +#define TAG "AvrIsp" + +struct AvrIsp { + AvrIspSpiSw* spi; + + uint16_t error; + uint16_t addr; + bool pmode; + //uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; + + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; + + AvrIspCallback callback; + void* context; +}; + +AvrIsp* avr_isp_alloc(void) { + AvrIsp* instance = malloc(sizeof(AvrIsp)); + return instance; +} + +void avr_isp_free(AvrIsp* instance) { + furi_assert(instance); + if(instance->spi) avr_isp_end_pmode(instance); + free(instance); +} + +void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context) { + furi_assert(instance); + furi_assert(context); + instance->callback = callback; + instance->context = context; +} + +uint8_t avr_isp_spi_transaction( + AvrIsp* instance, + uint8_t cmd, + uint8_t addr_hi, + uint8_t addr_lo, + uint8_t data) { + furi_assert(instance); + + avr_isp_spi_sw_txrx(instance->spi, cmd); + avr_isp_spi_sw_txrx(instance->spi, addr_hi); + avr_isp_spi_sw_txrx(instance->spi, addr_lo); + return avr_isp_spi_sw_txrx(instance->spi, data); +} + +static bool avr_isp_set_pmode(AvrIsp* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + furi_assert(instance); + uint8_t res = 0; + avr_isp_spi_sw_txrx(instance->spi, a); + avr_isp_spi_sw_txrx(instance->spi, b); + res = avr_isp_spi_sw_txrx(instance->spi, c); + avr_isp_spi_sw_txrx(instance->spi, d); + return res == 0x53; +} + +void avr_isp_end_pmode(AvrIsp* instance) { + furi_assert(instance); + if(instance->pmode) { + avr_isp_spi_sw_res_set(instance->spi, true); + // We're about to take the target out of reset + // so configure SPI pins as input + if(instance->spi) avr_isp_spi_sw_free(instance->spi); + instance->spi = NULL; + } + + instance->pmode = false; +} + +static bool avr_isp_start_pmode(AvrIsp* instance, AvrIspSpiSwSpeed spi_speed) { + furi_assert(instance); + // Reset target before driving PIN_SCK or PIN_MOSI + + // SPI.begin() will configure SS as output, + // so SPI master mode is selected. + // We have defined RESET as pin 10, + // which for many arduino's is not the SS pin. + // So we have to configure RESET as output here, + // (reset_target() first sets the correct level) + if(instance->spi) avr_isp_spi_sw_free(instance->spi); + instance->spi = avr_isp_spi_sw_init(spi_speed); + + avr_isp_spi_sw_res_set(instance->spi, false); + // See avr datasheets, chapter "SERIAL_PRG Programming Algorithm": + + // Pulse RESET after PIN_SCK is low: + avr_isp_spi_sw_sck_set(instance->spi, false); + + // discharge PIN_SCK, value arbitrally chosen + furi_delay_ms(20); + avr_isp_spi_sw_res_set(instance->spi, true); + + // Pulse must be minimum 2 target CPU speed cycles + // so 100 usec is ok for CPU speeds above 20KHz + furi_delay_ms(1); + + avr_isp_spi_sw_res_set(instance->spi, false); + + // Send the enable programming command: + // datasheet: must be > 20 msec + furi_delay_ms(50); + if(avr_isp_set_pmode(instance, AVR_ISP_SET_PMODE)) { + instance->pmode = true; + return true; + } + return false; +} + +bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { + AvrIspSpiSwSpeed spi_speed[] = { + AvrIspSpiSwSpeed1Mhz, + AvrIspSpiSwSpeed400Khz, + AvrIspSpiSwSpeed250Khz, + AvrIspSpiSwSpeed125Khz, + AvrIspSpiSwSpeed40Khz, + AvrIspSpiSwSpeed20Khz, + }; + for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { + if(avr_isp_start_pmode(instance, spi_speed[i])) { + return true; + } + } + return false; +} + +// static void avr_isp_universal(AvrIsp* instance) { +// furi_assert(instance); +// uint8_t data; + +// avr_isp_fill(instance, 4); +// data = avr_isp_spi_transaction( +// instance, instance->buff[0], instance->buff[1], instance->buff[2], instance->buff[3]); +// avr_isp_breply(instance, data); +// } + +// static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { +// furi_assert(instance); +// avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr)); +// /* polling flash */ +// if(data == 0xFF) { +// furi_delay_ms(5); +// } else { +// /* polling flash */ +// uint32_t starttime = furi_get_tick(); +// while((furi_get_tick() - starttime) < 30) { +// if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { +// break; +// }; +// } +// } +// } + +// static uint16_t avr_isp_current_page(AvrIsp* instance) { +// furi_assert(instance); +// uint16_t page = 0; +// switch(instance->cfg->pagesize) { +// case 32: +// page = instance->addr & 0xFFFFFFF0; +// break; +// case 64: +// page = instance->addr & 0xFFFFFFE0; +// break; +// case 128: +// page = instance->addr & 0xFFFFFFC0; +// break; +// case 256: +// page = instance->addr & 0xFFFFFF80; +// break; + +// default: +// page = instance->addr; +// break; +// } + +// return page; +// } + +// static uint8_t avr_isp_write_flash_pages(AvrIsp* instance, size_t length) { +// furi_assert(instance); +// size_t x = 0; +// uint16_t page = avr_isp_current_page(instance); +// while(x < length) { +// if(page != avr_isp_current_page(instance)) { +// --x; +// avr_isp_commit(instance, page, instance->buff[x++]); +// page = avr_isp_current_page(instance); +// } +// avr_isp_spi_transaction( +// instance, AVR_ISP_WRITE_FLASH_LO(instance->addr, instance->buff[x++])); + +// avr_isp_spi_transaction( +// instance, AVR_ISP_WRITE_FLASH_HI(instance->addr, instance->buff[x++])); +// instance->addr++; +// } + +// avr_isp_commit(instance, page, instance->buff[--x]); +// return STK_OK; +// } + +// static void avr_isp_write_flash(AvrIsp* instance, size_t length) { +// furi_assert(instance); +// avr_isp_fill(instance, length); +// if(avr_isp_getch(instance) == CRC_EOP) { +// avr_isp_tx_ch(instance, STK_INSYNC); +// avr_isp_tx_ch(instance, avr_isp_write_flash_pages(instance, length)); +// } else { +// instance->error++; +// avr_isp_tx_ch(instance, STK_NOSYNC); +// } +// } + +// // write (length) bytes, (start) is a byte address +// static uint8_t +// avr_isp_write_eeprom_chunk(AvrIsp* instance, uint16_t start, uint16_t length) { +// furi_assert(instance); +// // this writes byte-by-byte, +// // page writing may be faster (4 bytes at a time) +// avr_isp_fill(instance, length); +// for(uint16_t x = 0; x < length; x++) { +// uint16_t addr = start + x; +// avr_isp_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, instance->buff[x])); +// furi_delay_ms(10); +// } +// return STK_OK; +// } + +// static uint8_t avr_isp_write_eeprom(AvrIsp* instance, size_t length) { +// furi_assert(instance); +// // here is a word address, get the byte address +// uint16_t start = instance->addr * 2; +// uint16_t remaining = length; +// if(length > instance->cfg->eepromsize) { +// instance->error++; +// return STK_FAILED; +// } +// while(remaining > AVR_ISP_EECHUNK) { +// avr_isp_write_eeprom_chunk(instance, start, AVR_ISP_EECHUNK); +// start += AVR_ISP_EECHUNK; +// remaining -= AVR_ISP_EECHUNK; +// } +// avr_isp_write_eeprom_chunk(instance, start, remaining); +// return STK_OK; +// } + +// static void avr_isp_program_page(AvrIsp* instance) { +// furi_assert(instance); +// uint8_t result = STK_FAILED; +// uint16_t length = avr_isp_getch(instance) << 8 | avr_isp_getch(instance); +// uint8_t memtype = avr_isp_getch(instance); +// // flash memory @addr, (length) bytes +// if(memtype == STK_SET_FLASH_TYPE) { +// avr_isp_write_flash(instance, length); +// return; +// } +// if(memtype == STK_SET_EEPROM_TYPE) { +// result = avr_isp_write_eeprom(instance, length); +// if(avr_isp_getch(instance) == CRC_EOP) { +// avr_isp_tx_ch(instance, STK_INSYNC); +// avr_isp_tx_ch(instance, result); + +// } else { +// instance->error++; +// avr_isp_tx_ch(instance, STK_NOSYNC); +// } +// return; +// } +// avr_isp_tx_ch(instance, STK_FAILED); +// return; +// } + +static bool avr_isp_flash_read_page( + AvrIsp* instance, + uint16_t addr, + uint16_t size_page, + uint8_t* data, + uint32_t size_data) { + furi_assert(instance); + if(size_page > size_data) return false; + for(uint16_t i = 0; i < size_page; i += 2) { + data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(addr)); + data[i + 1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)); + addr++; + } + return true; +} + +static bool avr_isp_eeprom_read_page( + AvrIsp* instance, + uint16_t addr, + uint16_t size_page, + uint8_t* data, + uint32_t size_data) { + furi_assert(instance); + if(size_page > size_data) return false; + for(uint16_t i = 0; i < size_page; i++) { + data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr)); + addr++; + } + return true; +} + +bool avr_isp_read_page( + AvrIsp* instance, + uint32_t memtype, + uint16_t addr, + uint16_t size_page, + uint8_t* data, + uint32_t size_data) { + furi_assert(instance); + bool res = false; + if(memtype == STK_SET_FLASH_TYPE) + res = avr_isp_flash_read_page(instance, addr, size_page, data, size_data); + if(memtype == STK_SET_EEPROM_TYPE) + res = avr_isp_eeprom_read_page(instance, addr, size_page, data, size_data); + + return res; +} + +void avr_isp_read_signature(AvrIsp* instance, uint8_t* data) { + furi_assert(instance); + data[0] = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR); + data[1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); + data[2] = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); +} + +// void avr_isp_avrisp(AvrIsp* instance) { +// furi_assert(instance); +// uint8_t ch = avr_isp_getch(instance); + +// switch(ch) { +// case STK_GET_SYNC: +// FURI_LOG_D(TAG, "cmd STK_GET_SYNC"); +// instance->error = 0; +// avr_isp_empty_reply(instance); +// break; +// case STK_GET_SIGN_ON: +// FURI_LOG_D(TAG, "cmd STK_GET_SIGN_ON"); +// if(avr_isp_getch(instance) == CRC_EOP) { +// avr_isp_tx_ch(instance, STK_INSYNC); + +// avr_isp_tx_ch(instance, 'A'); +// avr_isp_tx_ch(instance, 'V'); +// avr_isp_tx_ch(instance, 'R'); +// avr_isp_tx_ch(instance, ' '); +// avr_isp_tx_ch(instance, 'I'); +// avr_isp_tx_ch(instance, 'S'); +// avr_isp_tx_ch(instance, 'P'); + +// avr_isp_tx_ch(instance, STK_OK); +// } else { +// instance->error++; +// avr_isp_tx_ch(instance, STK_NOSYNC); +// } +// break; +// case STK_GET_PARAMETER: +// FURI_LOG_D(TAG, "cmd STK_GET_PARAMETER"); +// avr_isp_get_version(instance, avr_isp_getch(instance)); +// break; +// case STK_SET_DEVICE: +// FURI_LOG_D(TAG, "cmd STK_SET_DEVICE"); +// avr_isp_fill(instance, 20); +// avr_isp_set_cfg(instance); +// avr_isp_empty_reply(instance); +// break; +// case STK_SET_DEVICE_EXT: // ignore for now +// FURI_LOG_D(TAG, "cmd STK_SET_DEVICE_EXT"); +// avr_isp_fill(instance, 5); +// avr_isp_empty_reply(instance); +// break; +// case STK_ENTER_PROGMODE: +// FURI_LOG_D(TAG, "cmd STK_ENTER_PROGMODE"); +// if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance); +// avr_isp_empty_reply(instance); +// break; +// case STK_LOAD_ADDRESS: +// FURI_LOG_D(TAG, "cmd STK_LOAD_ADDRESS"); +// instance->addr = avr_isp_getch(instance) | avr_isp_getch(instance) << 8; +// avr_isp_empty_reply(instance); +// break; +// case STK_PROG_FLASH: // ignore for now +// FURI_LOG_D(TAG, "cmd STK_PROG_FLASH"); +// avr_isp_getch(instance); +// avr_isp_getch(instance); +// avr_isp_empty_reply(instance); +// break; +// case STK_PROG_DATA: // ignore for now +// FURI_LOG_D(TAG, "cmd STK_PROG_DATA"); +// avr_isp_getch(instance); +// avr_isp_empty_reply(instance); +// break; +// case STK_PROG_PAGE: +// FURI_LOG_D(TAG, "cmd STK_PROG_PAGE"); +// avr_isp_program_page(instance); +// break; +// case STK_READ_PAGE: +// FURI_LOG_D(TAG, "cmd STK_READ_PAGE"); +// avr_isp_read_page(instance); +// break; +// case STK_UNIVERSAL: +// FURI_LOG_D(TAG, "cmd STK_UNIVERSAL"); +// avr_isp_universal(instance); +// break; +// case STK_LEAVE_PROGMODE: +// FURI_LOG_D(TAG, "cmd STK_LEAVE_PROGMODE"); +// instance->error = 0; +// if(instance->pmode) avr_isp_end_pmode(instance); +// avr_isp_empty_reply(instance); +// break; +// case STK_READ_SIGN: +// FURI_LOG_D(TAG, "cmd STK_READ_SIGN"); +// avr_isp_read_signature(instance); +// break; +// // expecting a command, not CRC_EOP +// // this is how we can get back in sync +// case CRC_EOP: +// FURI_LOG_D(TAG, "cmd CRC_EOP"); +// instance->error++; +// avr_isp_tx_ch(instance, STK_NOSYNC); +// break; +// // anything else we will return STK_UNKNOWN +// default: +// FURI_LOG_D(TAG, "cmd STK_ERROR_CMD"); +// instance->error++; +// if(avr_isp_getch(instance) == CRC_EOP) +// avr_isp_tx_ch(instance, STK_UNKNOWN); +// else +// avr_isp_tx_ch(instance, STK_NOSYNC); +// } + +// if(instance->callback) { +// instance->callback(instance->context); +// } +// } diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h new file mode 100644 index 00000000000..ac9c243f3aa --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +typedef struct AvrIsp AvrIsp; +typedef void (*AvrIspCallback)(void* context); + +AvrIsp* avr_isp_alloc(void); +void avr_isp_free(AvrIsp* instance); +void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context); +bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance); +void avr_isp_read_signature(AvrIsp* instance, uint8_t* data); +void avr_isp_end_pmode(AvrIsp* instance); +uint8_t avr_isp_spi_transaction( + AvrIsp* instance, + uint8_t cmd, + uint8_t addr_hi, + uint8_t addr_lo, + uint8_t data); +bool avr_isp_read_page( + AvrIsp* instance, + uint32_t memtype, + uint16_t addr, + uint16_t size_page, + uint8_t* data, + uint32_t size_data); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c new file mode 100644 index 00000000000..cc908e50e15 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c @@ -0,0 +1,288 @@ +#include "avr_isp_rw_worker.h" +#include "avr_isp_rw_worker_cmd.h" +#include "avr_isp.h" +#include "../lib/driver/avr_isp_prog_cmd.h" +#include "../lib/driver/avr_isp_chip_arr.h" + +#include "flipper_hex_file.h" +#include + +#include + +#define TAG "AvrIspRWWorker" + +struct AvrIspRWWorker { + FuriThread* thread; + AvrIsp* avr_isp; + + uint32_t chip_arr_ind; + bool chip_detect; + volatile bool worker_running; + AvrIspRWWorkerCallback callback; + void* context; +}; + +void avr_isp_rw_worker_detect_chip(AvrIspRWWorker* instance) { + furi_assert(instance); + FURI_LOG_D(TAG, "Detecting AVR chip"); + uint8_t data[10]; + size_t ind = avr_isp_chip_arr_size + 1; + do { + if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + break; + } + avr_isp_read_signature(instance->avr_isp, data); + avr_isp_end_pmode(instance->avr_isp); + + if(data[0] != 0x1E) { + ind = avr_isp_chip_arr_size + 1; //No detect chip + } else { + for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { + if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; + if(avr_isp_chip_arr[ind].sigs[1] == data[1]) { + if(avr_isp_chip_arr[ind].sigs[2] == data[2]) { + FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); + break; + } + } + } + } + + } while(0); + + if(instance->callback) { + if(ind > avr_isp_chip_arr_size) { + //ToDo add output ID chip + instance->callback(instance->context, "No detect"); + instance->chip_detect = false; + instance->chip_arr_ind = ind; + } else if(ind < avr_isp_chip_arr_size) { + instance->callback(instance->context, avr_isp_chip_arr[ind].name); + instance->chip_detect = true; + instance->chip_arr_ind = ind; + } else { + //ToDo add output ID chip + instance->callback(instance->context, "Unknown"); + instance->chip_detect = false; + instance->chip_arr_ind = ind; + } + } + avr_isp_rw_worker_rx(instance); +} + +/** Worker thread + * + * @param context + * @return exit code + */ +static int32_t avr_isp_rw_worker_thread(void* context) { + AvrIspRWWorker* instance = context; + + FURI_LOG_D(TAG, "Start"); + while(instance->worker_running) { + furi_delay_ms(100); + } + FURI_LOG_D(TAG, "Stop"); + return 0; +} + +AvrIspRWWorker* avr_isp_rw_worker_alloc(void* context) { + furi_assert(context); + UNUSED(context); + AvrIspRWWorker* instance = malloc(sizeof(AvrIspRWWorker)); + instance->avr_isp = avr_isp_alloc(); + + instance->chip_detect = false; + + instance->thread = + furi_thread_alloc_ex("AvrIspRWWorker", 2048, avr_isp_rw_worker_thread, instance); + return instance; +} + +void avr_isp_rw_worker_free(AvrIspRWWorker* instance) { + furi_assert(instance); + + avr_isp_free(instance->avr_isp); + furi_thread_free(instance->thread); + free(instance); +} + +void avr_isp_rw_worker_set_callback( + AvrIspRWWorker* instance, + AvrIspRWWorkerCallback callback, + void* context) { + furi_assert(instance); + furi_assert(context); + instance->callback = callback; + instance->context = context; +} + +void avr_isp_rw_worker_start(AvrIspRWWorker* instance) { + furi_assert(instance); + furi_assert(!instance->worker_running); + + instance->worker_running = true; + + furi_thread_start(instance->thread); +} + +void avr_isp_rw_worker_stop(AvrIspRWWorker* instance) { + furi_assert(instance); + furi_assert(instance->worker_running); + + instance->worker_running = false; + + furi_thread_join(instance->thread); +} + +bool avr_isp_rw_worker_is_running(AvrIspRWWorker* instance) { + furi_assert(instance); + return instance->worker_running; +} + +bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { + furi_assert(instance); + uint8_t data[256]; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + FURI_LOG_D(TAG, "Read chip"); + do { + if(!instance->chip_detect) { + FURI_LOG_E(TAG, "No detect AVR chip"); + break; + } + + // if(!storage_simply_mkdir(storage, "/any/avr_isp/")) { + // FURI_LOG_E(TAG, "storage_simply_mkdir"); + // break; + // } + + // if(!storage_simply_remove(storage, "dump.avr")) { + // break; + // } + + if(!flipper_format_file_open_always(flipper_format, "/any/avr_isp/dump.avr")) { + FURI_LOG_E(TAG, "flipper_format_file_open_always"); + break; + } + if(!flipper_format_write_header_cstr(flipper_format, "Flipper dump AVR", 1)) { + FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); + break; + } + if(!flipper_format_write_comment_cstr(flipper_format, "This is comment")) { + FURI_LOG_E(TAG, "flipper_format_write_comment_cstr"); + break; + } + //if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break; + + if(!flipper_format_write_string_cstr( + flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { + FURI_LOG_E(TAG, "Chip name"); + break; + } + + if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + break; + } + + avr_isp_read_signature(instance->avr_isp, data); + + if(!flipper_format_write_hex(flipper_format, "ID", data, 3)) { + FURI_LOG_E(TAG, "Unable to add ID"); + break; + } + FURI_LOG_D(TAG, "ID = 0x%02X 0x%02X 0x%02X", data[0], data[1], data[2]); + + data[0] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_HIGH); + data[1] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_LOW); + data[2] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_EXTENDED); + data[3] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_LOCK_BYTE); + + if(!flipper_format_write_hex(flipper_format, "Hfuse", data, 1)) { + FURI_LOG_E(TAG, "Unable to add Hfuse"); + break; + } + + if(!flipper_format_write_hex(flipper_format, "Lfuse", data + 1, 1)) { + FURI_LOG_E(TAG, "Unable to add Lfuse"); + break; + } + + if(!flipper_format_write_hex(flipper_format, "Efuse", data + 2, 1)) { + FURI_LOG_E(TAG, "Unable to add Efuse"); + break; + } + + if(!flipper_format_write_hex(flipper_format, "Lock", data + 3, 1)) { + FURI_LOG_E(TAG, "Unable to add Lock"); + break; + } + + FURI_LOG_D( + TAG, + "hfuse = 0x%02X lfuse = 0x%02X efuse = 0x%02X lock = 0x%02X", + data[0], + data[1], + data[2], + data[3]); + + if(!flipper_format_write_string_cstr(flipper_format, "Dump_flash", "flash.hex")) { + FURI_LOG_E(TAG, "Unable to add Dump_flash"); + break; + } + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + if(!flipper_format_write_string_cstr(flipper_format, "Dump_eeprom", "eeprom.hex")) { + FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); + break; + } + } + + FURI_LOG_D(TAG, "EEPROM"); + + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + FlipperHexFile* flipper_hex_eeprom = + flipper_hex_file_open("/any/avr_isp/eeprom.hex", 0); + int32_t size_data = 32; + if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) + size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + + for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + i += size_data) { + avr_isp_read_page( + instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); + flipper_hex_file_bin_to_hex_add_data(flipper_hex_eeprom, data, size_data); + printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_eeprom)); + } + flipper_hex_file_bin_to_hex_add_end_line(flipper_hex_eeprom); + printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_eeprom)); + flipper_hex_file_close(flipper_hex_eeprom); + } + + FURI_LOG_D(TAG, "FLASH"); + FlipperHexFile* flipper_hex_flash = flipper_hex_file_open("/any/avr_isp/flash.hex", 0); + for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; + i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { + avr_isp_read_page( + instance->avr_isp, + STK_SET_FLASH_TYPE, + i, + avr_isp_chip_arr[instance->chip_arr_ind].pagesize, + data, + sizeof(data)); + flipper_hex_file_bin_to_hex_add_data( + flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); + printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_flash)); + } + flipper_hex_file_bin_to_hex_add_end_line(flipper_hex_flash); + printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_flash)); + flipper_hex_file_close(flipper_hex_flash); + + avr_isp_end_pmode(instance->avr_isp); + } while(0); + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + return true; +} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h new file mode 100644 index 00000000000..5af29e35f03 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +typedef struct AvrIspRWWorker AvrIspRWWorker; + +typedef void (*AvrIspRWWorkerCallback)(void* context, const char* name); + +/** Allocate AvrIspRWWorker + * + * @param context AvrIsp* context + * @return AvrIspRWWorker* + */ +AvrIspRWWorker* avr_isp_rw_worker_alloc(void* context); + +/** Free AvrIspRWWorker + * + * @param instance AvrIspRWWorker instance + */ +void avr_isp_rw_worker_free(AvrIspRWWorker* instance); + +/** Callback AvrIspRWWorker + * + * @param instance AvrIspRWWorker instance + * @param callback AvrIspRWWorkerOverrunCallback callback + * @param context + */ +void avr_isp_rw_worker_set_callback( + AvrIspRWWorker* instance, + AvrIspRWWorkerCallback callback, + void* context); + +/** Start AvrIspRWWorker + * + * @param instance AvrIspRWWorker instance + */ +void avr_isp_rw_worker_start(AvrIspRWWorker* instance); + +/** Stop AvrIspRWWorker + * + * @param instance AvrIspRWWorker instance + */ +void avr_isp_rw_worker_stop(AvrIspRWWorker* instance); + +/** Check if worker is running + * @param instance AvrIspRWWorker instance + * @return bool - true if running + */ +bool avr_isp_rw_worker_is_running(AvrIspRWWorker* instance); + +/** Detect chip + * + * @param instance AvrIspRWWorker instance + */ +void avr_isp_rw_worker_detect_chip(AvrIspRWWorker* instance); + + +bool avr_isp_rw_worker_rx (AvrIspRWWorker* instance); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h new file mode 100644 index 00000000000..31ba24a0539 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../lib/driver/avr_isp_prog_cmd.h" + +#define AVR_ISP_RW_GET_SYNC STK_GET_SYNC,CRC_EOP +#define AVR_ISP_RW_ENTER_PROGMODE STK_ENTER_PROGMODE,CRC_EOP +#define AVR_ISP_RW_READ_SIGN STK_READ_SIGN,CRC_EOP +#define AVR_ISP_RW_LEAVE_PROGMODE STK_LEAVE_PROGMODE,CRC_EOP diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h index 3dcd8c45f03..6b465884beb 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -11,5 +11,6 @@ typedef enum { //AvrIspViewVariableItemList, AvrIspViewSubmenu, AvrIspViewProgrammer, + AvrIspViewReader, AvrIspViewWidget, } AvrIspView; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c index 80a6f2e6a9c..f01b112939b 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c @@ -2,7 +2,6 @@ #include #include "../lib/driver/avr_isp_prog.h" #include "../lib/driver/avr_isp_prog_cmd.h" -#include "../lib/driver/avr_isp_spi_sw.h" #include "../lib/driver/avr_isp_chip_arr.h" #include @@ -22,7 +21,6 @@ typedef enum { struct AvrIspWorker { FuriThread* thread; - AvrIspSpiSwSpeed spi_speed; volatile bool worker_running; AvrIspWorkerCallback callback; void* context; @@ -140,6 +138,7 @@ void avr_isp_worker_detect_chip(AvrIspWorker* instance) { ind = avr_isp_chip_arr_size + 1; //No detect chip } else { for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { + if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c new file mode 100644 index 00000000000..33353e4471b --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c @@ -0,0 +1,95 @@ +#include "flipper_hex_file.h" +#include +#include +#include +#include + +//https://ru.wikipedia.org/wiki/Intel_HEX + +#define COUNT_BYTE_PAYLOAD 32 //how much payload will be used + +struct FlipperHexFile { + uint32_t addr; + Storage* storage; + FlipperFormat* flipper_format; + Stream* stream; + FuriString* str_data; +}; + +FlipperHexFile* flipper_hex_file_open(const char* name, uint32_t start_addr) { + furi_assert(name); + + FlipperHexFile* instance = malloc(sizeof(FlipperHexFile)); + instance->addr = start_addr; + instance->storage = furi_record_open(RECORD_STORAGE); + instance->flipper_format = flipper_format_file_alloc(instance->storage); + flipper_format_file_open_always(instance->flipper_format, name); + instance->stream = flipper_format_get_raw_stream(instance->flipper_format); + + instance->str_data = furi_string_alloc(); + + return instance; +} + +void flipper_hex_file_close(FlipperHexFile* instance) { + furi_assert(instance); + furi_string_free(instance->str_data); + flipper_format_free(instance->flipper_format); + furi_record_close(RECORD_STORAGE); +} + +void flipper_hex_file_bin_to_hex_add_data( + FlipperHexFile* instance, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + + uint32_t cur_addr = instance->addr; + uint8_t count_byte = 0; + uint32_t ind = 0; + uint8_t crc = 0; + + furi_string_reset(instance->str_data); + + while(ind < data_size) { + if((ind + COUNT_BYTE_PAYLOAD) > data_size) { + count_byte = data_size - ind; + } else { + count_byte = COUNT_BYTE_PAYLOAD; + } + furi_string_cat_printf( + instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF)); + crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF); + + for(uint32_t i = 0; i < count_byte; i++) { + furi_string_cat_printf(instance->str_data, "%02X", *data); + crc += *data++; + } + crc = 0x01 + ~crc; + furi_string_cat_printf(instance->str_data, "%02X\r\n", crc); + + ind += count_byte; + instance->addr += count_byte; + + if((cur_addr & 0xFF0000) > (instance->addr & 0xFF0000)) { + crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF); + crc = 0x01 + ~crc; + furi_string_cat_printf( + instance->str_data, ":02000004%04lX\r\n", (instance->addr >> 16)); + cur_addr = instance->addr; + } + } + stream_write_string(instance->stream, instance->str_data); +} + +void flipper_hex_file_bin_to_hex_add_end_line(FlipperHexFile* instance) { + furi_assert(instance); + furi_string_reset(instance->str_data); + furi_string_cat_printf(instance->str_data, ":00000001FF\r\n"); + stream_write_string(instance->stream, instance->str_data); +} + +const char* flipper_hex_file_get_string(FlipperHexFile* instance) { + furi_assert(instance); + return furi_string_get_cstr(instance->str_data); +} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h new file mode 100644 index 00000000000..26111419be2 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct FlipperHexFile FlipperHexFile; + +FlipperHexFile* flipper_hex_file_open(const char* name, uint32_t start_addr); +void flipper_hex_file_close(FlipperHexFile* instance); +void flipper_hex_file_bin_to_hex_add_data(FlipperHexFile* instance, uint8_t* data, uint32_t data_size); +void flipper_hex_file_bin_to_hex_add_end_line(FlipperHexFile* instance); +const char* flipper_hex_file_get_string(FlipperHexFile* instance); diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c index bef39a335b4..4d6d263f058 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -3,7 +3,8 @@ #include -#define AVR_ISP_PROG_TX_RX_BUF_SIZE 256 +#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320 +#define TAG "AvrIspProg" struct AvrIspProgCfgDevice { uint8_t devicecode; @@ -487,10 +488,12 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { switch(ch) { case STK_GET_SYNC: + FURI_LOG_D(TAG, "cmd STK_GET_SYNC"); instance->error = 0; avr_isp_prog_empty_reply(instance); break; case STK_GET_SIGN_ON: + FURI_LOG_D(TAG, "cmd STK_GET_SIGN_ON"); if(avr_isp_prog_getch(instance) == CRC_EOP) { avr_isp_prog_tx_ch(instance, STK_INSYNC); @@ -509,59 +512,73 @@ void avr_isp_prog_avrisp(AvrIspProg* instance) { } break; case STK_GET_PARAMETER: + FURI_LOG_D(TAG, "cmd STK_GET_PARAMETER"); avr_isp_prog_get_version(instance, avr_isp_prog_getch(instance)); break; case STK_SET_DEVICE: + FURI_LOG_D(TAG, "cmd STK_SET_DEVICE"); avr_isp_prog_fill(instance, 20); avr_isp_prog_set_cfg(instance); avr_isp_prog_empty_reply(instance); break; case STK_SET_DEVICE_EXT: // ignore for now + FURI_LOG_D(TAG, "cmd STK_SET_DEVICE_EXT"); avr_isp_prog_fill(instance, 5); avr_isp_prog_empty_reply(instance); break; case STK_ENTER_PROGMODE: + FURI_LOG_D(TAG, "cmd STK_ENTER_PROGMODE"); if(!instance->pmode) avr_isp_prog_auto_set_spi_speed_start_pmode(instance); avr_isp_prog_empty_reply(instance); break; case STK_LOAD_ADDRESS: + FURI_LOG_D(TAG, "cmd STK_LOAD_ADDRESS"); instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8; avr_isp_prog_empty_reply(instance); break; case STK_PROG_FLASH: // ignore for now + FURI_LOG_D(TAG, "cmd STK_PROG_FLASH"); avr_isp_prog_getch(instance); avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; case STK_PROG_DATA: // ignore for now + FURI_LOG_D(TAG, "cmd STK_PROG_DATA"); avr_isp_prog_getch(instance); avr_isp_prog_empty_reply(instance); break; case STK_PROG_PAGE: + FURI_LOG_D(TAG, "cmd STK_PROG_PAGE"); avr_isp_prog_program_page(instance); break; case STK_READ_PAGE: + FURI_LOG_D(TAG, "cmd STK_READ_PAGE"); avr_isp_prog_read_page(instance); break; case STK_UNIVERSAL: + FURI_LOG_D(TAG, "cmd STK_UNIVERSAL"); avr_isp_prog_universal(instance); break; case STK_LEAVE_PROGMODE: + FURI_LOG_D(TAG, "cmd STK_LEAVE_PROGMODE"); instance->error = 0; if(instance->pmode) avr_isp_prog_end_pmode(instance); avr_isp_prog_empty_reply(instance); break; case STK_READ_SIGN: + FURI_LOG_D(TAG, "cmd STK_READ_SIGN"); avr_isp_prog_read_signature(instance); break; // expecting a command, not CRC_EOP // this is how we can get back in sync case CRC_EOP: + FURI_LOG_D(TAG, "cmd CRC_EOP"); instance->error++; avr_isp_prog_tx_ch(instance, STK_NOSYNC); break; // anything else we will return STK_UNKNOWN default: + FURI_LOG_D(TAG, "cmd STK_ERROR_CMD"); instance->error++; if(avr_isp_prog_getch(instance) == CRC_EOP) avr_isp_prog_tx_ch(instance, STK_UNKNOWN); diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h index 9ca83818148..bc8ccb9a3be 100644 --- a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h +++ b/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h @@ -13,16 +13,30 @@ #define AVR_ISP_READ_VENDOR 0x30, 0x00, 0x00, 0x00 #define AVR_ISP_READ_PART_FAMILY 0x30, 0x00, 0x01, 0x00 #define AVR_ISP_READ_PART_NUMBER 0x30, 0x00, 0x02, 0x00 +#define AVR_ISP_ERASE_CHIP 0xAC, 0x80, 0x00, 0x00 //Erase Chip, Wait N ms, Release RESET to end the erase. +//The only way to end a Chip Erase cycle is by temporarily releasing the Reset line #define AVR_ISP_WRITE_FLASH_LO(add, data) 0x40, (add >> 8) & 0xFF, add & 0xFF, data #define AVR_ISP_WRITE_FLASH_HI(add, data) 0x48, (add >> 8) & 0xFF, add & 0xFF, data #define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00 #define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00 -#define AVR_ISP_WRITE_EEPROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data +#define AVR_ISP_WRITE_EEPROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data //Send cmd, Wait N ms #define AVR_ISP_READ_EEPROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF -#define AVR_ISP_COMMIT(add) 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 +#define AVR_ISP_COMMIT(add) 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 //Send cmd, polling read last addr page + +#define AVR_ISP_OSCCAL(add) 0x38, 0x00, add, 0x00 + +#define AVR_ISP_WRITE_LOCK_BYTE(data) 0xAC, 0xE0, 0x00, data //Send cmd, Wait N ms +#define AVR_ISP_READ_LOCK_BYTE 0x58, 0x00, 0x00, 0x00 +#define AVR_ISP_WRITE_FUSE_LOW(data) 0xAC, 0xA0, 0x00, data //Send cmd, Wait N ms +#define AVR_ISP_READ_FUSE_LOW 0x50, 0x00, 0x00, 0x00 +#define AVR_ISP_WRITE_FUSE_HIGH(data) 0xAC, 0xA8, 0x00, data //Send cmd, Wait N ms +#define AVR_ISP_READ_FUSE_HIGH 0x58, 0x08, 0x00, 0x00 +#define AVR_ISP_WRITE_FUSE_EXTENDED(data) 0xAC, 0xA4, 0x00, data //Send cmd, Wait N ms (~write) +#define AVR_ISP_READ_FUSE_EXTENDED 0x50, 0x08, 0x00, 0x00 + #define AVR_ISP_EECHUNK 0x20 diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h index 54c5931f18b..a107029a75a 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h @@ -1,3 +1,4 @@ ADD_SCENE(avr_isp, start, Start) ADD_SCENE(avr_isp, about, About) ADD_SCENE(avr_isp, programmer, Programmer) +ADD_SCENE(avr_isp, reader, Reader) \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c new file mode 100644 index 00000000000..0184819edfe --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -0,0 +1,38 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_reader.h" + +void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { + furi_assert(context); + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void avr_isp_scene_reader_on_enter(void* context) { + AvrIspApp* app = context; + + avr_asp_reader_view_set_callback( + app->avr_asp_reader_view, avr_isp_scene_reader_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); +} + +bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + UNUSED(app); + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + // case WSCustomEventViewreaderBack: + // consumed = true; + // break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + } + return consumed; +} + +void avr_isp_scene_reader_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c index fc290c3e9d8..a77b3b2c88c 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -2,6 +2,7 @@ typedef enum { SubmenuIndexAvrIspProgrammer, + SubmenuIndexAvrIspReader, SubmenuIndexAvrIspAbout, } SubmenuIndex; @@ -21,6 +22,12 @@ void avr_isp_scene_start_on_enter(void* context) { SubmenuIndexAvrIspProgrammer, avr_isp_scene_start_submenu_callback, app); + submenu_add_item( + submenu, + "AVR ISP Reader", + SubmenuIndexAvrIspReader, + avr_isp_scene_start_submenu_callback, + app); submenu_add_item( submenu, "About", SubmenuIndexAvrIspAbout, avr_isp_scene_start_submenu_callback, app); @@ -41,6 +48,9 @@ bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubmenuIndexAvrIspProgrammer) { scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); consumed = true; + }else if(event.event == SubmenuIndexAvrIspReader) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneReader); + consumed = true; } scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c new file mode 100644 index 00000000000..cadc8da8186 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c @@ -0,0 +1,160 @@ +#include "avr_isp_view_reader.h" +#include "../avr_isp_app_i.h" +#include + +#include "../helpers/avr_isp_rw_worker.h" +//#include + +//#include +//#include + +struct AvrIspReaderView { + View* view; + AvrIspRWWorker* worker; + AvrIspReaderViewCallback callback; + void* context; +}; + +typedef struct { + uint16_t idx; + IconAnimation* icon; + const char* name_chip; + bool detect_chip; +} AvrIspReaderViewModel; + +void avr_asp_reader_view_set_callback( + AvrIspReaderView* instance, + AvrIspReaderViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +void avr_asp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { + UNUSED(model); + canvas_clear(canvas); + // canvas_set_color(canvas, ColorBlack); + // canvas_set_font(canvas, FontSecondary); + + // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 20, 10, "AVRISPReader"); + // canvas_set_font(canvas, FontSecondary); + canvas_set_font(canvas, FontPrimary); + if(!model->detect_chip) { + canvas_draw_icon_animation(canvas, 0, 0, model->icon); + canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); + canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); + } else { + canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); + canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + } +} + +bool avr_asp_reader_view_input(InputEvent* event, void* context) { + furi_assert(context); + AvrIspReaderView* instance = context; + UNUSED(instance); + if(event->key == InputKeyBack || event->type != InputTypeShort) { + return false; + } + + return true; +} + +static void avr_asp_reader_detect_chip_callback(void* context, const char* name) { + furi_assert(context); + AvrIspReaderView* instance = context; + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + model->name_chip = name; + model->detect_chip = true; + icon_animation_stop(model->icon); + }, + true); +} +void avr_asp_reader_view_enter(void* context) { + furi_assert(context); + AvrIspReaderView* instance = context; + + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + icon_animation_start(model->icon); + model->detect_chip = false; + }, + false); + + //Start worker + instance->worker = avr_isp_rw_worker_alloc(instance->context); + + avr_isp_rw_worker_set_callback( + instance->worker, avr_asp_reader_detect_chip_callback, instance); + + avr_isp_rw_worker_detect_chip(instance->worker); + + //avr_isp_rw_worker_start(instance->worker); +} + +void avr_asp_reader_view_exit(void* context) { + furi_assert(context); + AvrIspReaderView* instance = context; + // //Stop worker + // if(avr_isp_worker_is_running(instance->worker)) { + // avr_isp_worker_stop(instance->worker); + // } + avr_isp_rw_worker_free(instance->worker); + + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { icon_animation_stop(model->icon); }, + false); +} + +AvrIspReaderView* avr_asp_reader_view_alloc() { + AvrIspReaderView* instance = malloc(sizeof(AvrIspReaderView)); + + // View allocation and configuration + instance->view = view_alloc(); + + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspReaderViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_reader_view_draw); + view_set_input_callback(instance->view, avr_asp_reader_view_input); + view_set_enter_callback(instance->view, avr_asp_reader_view_enter); + view_set_exit_callback(instance->view, avr_asp_reader_view_exit); + + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + model->icon = icon_animation_alloc(&A_ChipLooking_64x64); + view_tie_icon_animation(instance->view, model->icon); + model->detect_chip = false; + }, + false); + return instance; +} + +void avr_asp_reader_view_free(AvrIspReaderView* instance) { + furi_assert(instance); + + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { icon_animation_free(model->icon); }, + false); + view_free(instance->view); + free(instance); +} + +View* avr_asp_reader_view_get_view(AvrIspReaderView* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h new file mode 100644 index 00000000000..e06a5a597d5 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "../helpers/avr_isp_types.h" +#include "../helpers/avr_isp_event.h" + +typedef struct AvrIspReaderView AvrIspReaderView; + +typedef void (*AvrIspReaderViewCallback)(AvrIspCustomEvent event, void* context); + +void avr_asp_reader_view_set_callback( + AvrIspReaderView* instance, + AvrIspReaderViewCallback callback, + void* context); + +AvrIspReaderView* avr_asp_reader_view_alloc(); + +void avr_asp_reader_view_free(AvrIspReaderView* instance); + +View* avr_asp_reader_view_get_view(AvrIspReaderView* instance); + +void avr_asp_reader_view_exit(void* context); From c0a728dbd1ac128b5a3bda9fee1969890e3fbfe4 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 17 Mar 2023 14:01:00 +0400 Subject: [PATCH 15/50] AVR_ISP: add read and check I32HEX file --- .../helpers/avr_isp_rw_worker.c | 65 ++-- .../helpers/flipper_hex_file.c | 95 ------ .../helpers/flipper_hex_file.h | 11 - .../helpers/flipper_i32hex_file.c | 306 ++++++++++++++++++ .../helpers/flipper_i32hex_file.h | 18 ++ firmware/targets/f7/api_symbols.csv | 8 +- lib/toolbox/SConscript | 1 + 7 files changed, 371 insertions(+), 133 deletions(-) delete mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c delete mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h create mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c index cc908e50e15..88dc655ae3e 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c @@ -4,7 +4,7 @@ #include "../lib/driver/avr_isp_prog_cmd.h" #include "../lib/driver/avr_isp_chip_arr.h" -#include "flipper_hex_file.h" +#include "flipper_i32hex_file.h" #include #include @@ -243,8 +243,8 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { FURI_LOG_D(TAG, "EEPROM"); if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - FlipperHexFile* flipper_hex_eeprom = - flipper_hex_file_open("/any/avr_isp/eeprom.hex", 0); + FlipperI32HexFile* flipper_hex_eeprom = + flipper_i32hex_file_open_write("/any/avr_isp/eeprom.hex", 0); int32_t size_data = 32; if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; @@ -253,34 +253,47 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { i += size_data) { avr_isp_read_page( instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); - flipper_hex_file_bin_to_hex_add_data(flipper_hex_eeprom, data, size_data); - printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_eeprom)); + flipper_i32hex_file_bin_to_i32hex_add_data(flipper_hex_eeprom, data, size_data); + printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); } - flipper_hex_file_bin_to_hex_add_end_line(flipper_hex_eeprom); - printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_eeprom)); - flipper_hex_file_close(flipper_hex_eeprom); + flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_eeprom); + printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); + flipper_i32hex_file_close(flipper_hex_eeprom); } - FURI_LOG_D(TAG, "FLASH"); - FlipperHexFile* flipper_hex_flash = flipper_hex_file_open("/any/avr_isp/flash.hex", 0); - for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; - i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { - avr_isp_read_page( - instance->avr_isp, - STK_SET_FLASH_TYPE, - i, - avr_isp_chip_arr[instance->chip_arr_ind].pagesize, - data, - sizeof(data)); - flipper_hex_file_bin_to_hex_add_data( - flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_flash)); - } - flipper_hex_file_bin_to_hex_add_end_line(flipper_hex_flash); - printf("%s\r\n", flipper_hex_file_get_string(flipper_hex_flash)); - flipper_hex_file_close(flipper_hex_flash); + // FURI_LOG_D(TAG, "FLASH"); + // FlipperI32HexFile* flipper_hex_flash = + // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", 0); + // for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; + // i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { + // avr_isp_read_page( + // instance->avr_isp, + // STK_SET_FLASH_TYPE, + // i, + // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, + // data, + // sizeof(data)); + // flipper_i32hex_file_bin_to_i32hex_add_data( + // flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); + // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); + // } + // flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_flash); + // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); + // flipper_i32hex_file_close(flipper_hex_flash); avr_isp_end_pmode(instance->avr_isp); + + FURI_LOG_D(TAG, "EEPROM READ"); + FlipperI32HexFile* flipper_hex_eeprom_read = + flipper_i32hex_file_open_read("/any/avr_isp/eeprom.hex"); + FURI_LOG_D(TAG, "EEPROM READ1"); + if(flipper_i32hex_file_check(flipper_hex_eeprom_read)){ + FURI_LOG_D(TAG, "Check OK"); + } else { + FURI_LOG_E(TAG, "Check ERROR"); + } + flipper_i32hex_file_close(flipper_hex_eeprom_read); + } while(0); flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c deleted file mode 100644 index 33353e4471b..00000000000 --- a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "flipper_hex_file.h" -#include -#include -#include -#include - -//https://ru.wikipedia.org/wiki/Intel_HEX - -#define COUNT_BYTE_PAYLOAD 32 //how much payload will be used - -struct FlipperHexFile { - uint32_t addr; - Storage* storage; - FlipperFormat* flipper_format; - Stream* stream; - FuriString* str_data; -}; - -FlipperHexFile* flipper_hex_file_open(const char* name, uint32_t start_addr) { - furi_assert(name); - - FlipperHexFile* instance = malloc(sizeof(FlipperHexFile)); - instance->addr = start_addr; - instance->storage = furi_record_open(RECORD_STORAGE); - instance->flipper_format = flipper_format_file_alloc(instance->storage); - flipper_format_file_open_always(instance->flipper_format, name); - instance->stream = flipper_format_get_raw_stream(instance->flipper_format); - - instance->str_data = furi_string_alloc(); - - return instance; -} - -void flipper_hex_file_close(FlipperHexFile* instance) { - furi_assert(instance); - furi_string_free(instance->str_data); - flipper_format_free(instance->flipper_format); - furi_record_close(RECORD_STORAGE); -} - -void flipper_hex_file_bin_to_hex_add_data( - FlipperHexFile* instance, - uint8_t* data, - uint32_t data_size) { - furi_assert(instance); - - uint32_t cur_addr = instance->addr; - uint8_t count_byte = 0; - uint32_t ind = 0; - uint8_t crc = 0; - - furi_string_reset(instance->str_data); - - while(ind < data_size) { - if((ind + COUNT_BYTE_PAYLOAD) > data_size) { - count_byte = data_size - ind; - } else { - count_byte = COUNT_BYTE_PAYLOAD; - } - furi_string_cat_printf( - instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF)); - crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF); - - for(uint32_t i = 0; i < count_byte; i++) { - furi_string_cat_printf(instance->str_data, "%02X", *data); - crc += *data++; - } - crc = 0x01 + ~crc; - furi_string_cat_printf(instance->str_data, "%02X\r\n", crc); - - ind += count_byte; - instance->addr += count_byte; - - if((cur_addr & 0xFF0000) > (instance->addr & 0xFF0000)) { - crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF); - crc = 0x01 + ~crc; - furi_string_cat_printf( - instance->str_data, ":02000004%04lX\r\n", (instance->addr >> 16)); - cur_addr = instance->addr; - } - } - stream_write_string(instance->stream, instance->str_data); -} - -void flipper_hex_file_bin_to_hex_add_end_line(FlipperHexFile* instance) { - furi_assert(instance); - furi_string_reset(instance->str_data); - furi_string_cat_printf(instance->str_data, ":00000001FF\r\n"); - stream_write_string(instance->stream, instance->str_data); -} - -const char* flipper_hex_file_get_string(FlipperHexFile* instance) { - furi_assert(instance); - return furi_string_get_cstr(instance->str_data); -} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h b/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h deleted file mode 100644 index 26111419be2..00000000000 --- a/applications/plugins/avr_isp_programmer/helpers/flipper_hex_file.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -typedef struct FlipperHexFile FlipperHexFile; - -FlipperHexFile* flipper_hex_file_open(const char* name, uint32_t start_addr); -void flipper_hex_file_close(FlipperHexFile* instance); -void flipper_hex_file_bin_to_hex_add_data(FlipperHexFile* instance, uint8_t* data, uint32_t data_size); -void flipper_hex_file_bin_to_hex_add_end_line(FlipperHexFile* instance); -const char* flipper_hex_file_get_string(FlipperHexFile* instance); diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c new file mode 100644 index 00000000000..4aa5caa747e --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -0,0 +1,306 @@ +#include "flipper_i32hex_file.h" +#include +#include +#include +#include +#include + +//https://en.wikipedia.org/wiki/Intel_HEX + +#define TAG "FlipperI32HexFile" + +#define COUNT_BYTE_PAYLOAD 32 //how much payload will be used + +#define I32HEX_TYPE_DATA 0x00 +#define I32HEX_TYPE_END_OF_FILE 0x01 +#define I32HEX_TYPE_EXT_LINEAR_ADDR 0x04 +#define I32HEX_TYPE_START_LINEAR_ADDR 0x05 + +struct FlipperI32HexFile { + uint32_t addr; + uint32_t addr_last; + Storage* storage; + Stream* stream; + FuriString* str_data; + bool file_open; +}; + +typedef enum { + FlipperI32HexFileStatusOK = 0, + FlipperI32HexFileStatusData = 2, + FlipperI32HexFileStatusUdateAddr = 3, + FlipperI32HexFileStatusEofFile = 4, + + // Errors + FlipperI32HexFileStatusErrorCrc = (-1), + FlipperI32HexFileStatusErrorOverflow = (-2), + FlipperI32HexFileStatusErrorData = (-3), + FlipperI32HexFileStatusErrorUnsupportedCommand = (-4), + + FlipperI32HexFileStatusReserved = + 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. +} FlipperI32HexFileStatus; + +typedef struct { + FlipperI32HexFileStatus status; + uint32_t data_size; +} FlipperI32HexFileRet; + +FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr) { + furi_assert(name); + + FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile)); + instance->addr = start_addr; + instance->addr_last = 0; + instance->storage = furi_record_open(RECORD_STORAGE); + instance->stream = file_stream_alloc(instance->storage); + + if(!file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + FURI_LOG_E(TAG, "Failed to open file"); + instance->file_open = false; + } else { + instance->file_open = true; + } + instance->str_data = furi_string_alloc(instance->storage); + + return instance; +} + +FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { + furi_assert(name); + + FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile)); + instance->addr = 0; + instance->addr_last = 0; + instance->storage = furi_record_open(RECORD_STORAGE); + instance->stream = file_stream_alloc(instance->storage); + + if(!file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E(TAG, "Failed to open file"); + instance->file_open = false; + } else { + instance->file_open = true; + } + instance->str_data = furi_string_alloc(instance->storage); + + return instance; +} + +void flipper_i32hex_file_close(FlipperI32HexFile* instance) { + furi_assert(instance); + furi_string_free(instance->str_data); + file_stream_close(instance->stream); + stream_free(instance->stream); + furi_record_close(RECORD_STORAGE); +} + +void flipper_i32hex_file_bin_to_i32hex_add_data( + FlipperI32HexFile* instance, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + furi_assert(data); + + uint8_t count_byte = 0; + uint32_t ind = 0; + uint8_t crc = 0; + + furi_string_reset(instance->str_data); + + if((instance->addr_last & 0xFF0000) > (instance->addr & 0xFF0000)) { + crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF); + crc = 0x01 + ~crc; + //I32HEX_TYPE_EXT_LINEAR_ADDR + furi_string_cat_printf(instance->str_data, ":02000004%04lX\r\n", (instance->addr >> 16)); + instance->addr_last = instance->addr; + } + + while(ind < data_size) { + if((ind + COUNT_BYTE_PAYLOAD) > data_size) { + count_byte = data_size - ind; + } else { + count_byte = COUNT_BYTE_PAYLOAD; + } + //I32HEX_TYPE_DATA + furi_string_cat_printf( + instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF)); + crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF); + + for(uint32_t i = 0; i < count_byte; i++) { + furi_string_cat_printf(instance->str_data, "%02X", *data); + crc += *data++; + } + crc = 0x01 + ~crc; + furi_string_cat_printf(instance->str_data, "%02X\r\n", crc); + + ind += count_byte; + instance->addr += count_byte; + } + if(instance->file_open) stream_write_string(instance->stream, instance->str_data); +} + +void flipper_i32hex_file_bin_to_i32hex_add_end_line(FlipperI32HexFile* instance) { + furi_assert(instance); + furi_string_reset(instance->str_data); + //I32HEX_TYPE_END_OF_FILE + furi_string_cat_printf(instance->str_data, ":00000001FF\r\n"); + if(instance->file_open) stream_write_string(instance->stream, instance->str_data); +} + +void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) { + furi_assert(instance); + instance->addr = addr; +} + +const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance) { + furi_assert(instance); + return furi_string_get_cstr(instance->str_data); +} + +static FlipperI32HexFileRet flipper_i32hex_file_parse_line( + FlipperI32HexFile* instance, + const char* str, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + furi_assert(data); + + char* str1; + uint32_t data_wrire_ind = 0; + uint32_t data_len = 0; + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusErrorData, .data_size = 0}; + + //Search for start of data I32HEX + str1 = strstr(str, ":"); + do { + if(str1 == NULL) { + ret.status = FlipperI32HexFileStatusErrorData; + break; + } + str1++; + if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) { + ret.status = FlipperI32HexFileStatusErrorData; + break; + } + str1++; + if(++data_wrire_ind > data_size) { + ret.status = FlipperI32HexFileStatusErrorOverflow; + break; + } + data_len = 5 + data[0]; // +5 bytes per header and crc + while(data_len > data_wrire_ind) { + str1++; + if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) { + ret.status = FlipperI32HexFileStatusErrorData; + break; + } + str1++; + if(++data_wrire_ind > data_size) { + ret.status = FlipperI32HexFileStatusErrorOverflow; + break; + } + } + ret.status = FlipperI32HexFileStatusOK; + ret.data_size = data_wrire_ind; + + } while(0); + return ret; +} + +static bool flipper_i32hex_file_check_data(uint8_t* data, uint32_t data_size) { + furi_assert(data); + uint8_t crc = 0; + uint32_t data_read_ind = 0; + if(data[0] > data_size) return false; + while(data_read_ind < data_size - 1) { + crc += data[data_read_ind++]; + } + return data[data_size - 1] == ((1 + ~crc) & 0xFF); +} + +static FlipperI32HexFileRet flipper_i32hex_file_parse( + FlipperI32HexFile* instance, + const char* str, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + furi_assert(data); + + FlipperI32HexFileRet ret = flipper_i32hex_file_parse_line(instance, str, data, data_size); + + if((ret.status == FlipperI32HexFileStatusOK) && (ret.data_size > 4)) { + switch(data[3]) { + case I32HEX_TYPE_DATA: + if(flipper_i32hex_file_check_data(data, ret.data_size)) { + ret.data_size -= 5; + memcpy(data, data + 4, ret.data_size); + } else { + ret.status = FlipperI32HexFileStatusErrorCrc; + ret.data_size = 0; + } + break; + case I32HEX_TYPE_END_OF_FILE: + if(flipper_i32hex_file_check_data(data, ret.data_size)) { + ret.status = FlipperI32HexFileStatusEofFile; + ret.data_size = 0; + } else { + ret.status = FlipperI32HexFileStatusErrorCrc; + ret.data_size = 0; + } + break; + case I32HEX_TYPE_EXT_LINEAR_ADDR: + if(flipper_i32hex_file_check_data(data, ret.data_size)) { + data[0] = data[1]; + data[1] = data[2]; + data[3] = 0; + data[4] = 0; + ret.status = FlipperI32HexFileStatusUdateAddr; + ret.data_size = 4; + } else { + ret.status = FlipperI32HexFileStatusErrorCrc; + ret.data_size = 0; + } + break; + case I32HEX_TYPE_START_LINEAR_ADDR: + ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand; + ret.data_size = 0; + break; + default: + ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand; + ret.data_size = 0; + break; + } + } else { + ret.status = FlipperI32HexFileStatusErrorData; + ret.data_size = 0; + } + return ret; +} + +bool flipper_i32hex_file_check(FlipperI32HexFile* instance) { + furi_assert(instance); + + furi_delay_ms(100); + uint32_t data_size = 280; + uint8_t data[280] = {0}; + FuriString* line = furi_string_alloc(); + bool ret = true; + + if(!instance->file_open) { + FURI_LOG_E(TAG, "File is not open"); + } else { + stream_rewind(instance->stream); + + while(stream_read_line(instance->stream, line)) { + FlipperI32HexFileRet parse_ret = + flipper_i32hex_file_parse(instance, furi_string_get_cstr(line), data, data_size); + + if(parse_ret.status < 0) { + ret = false; + } + } + } + + furi_string_free(line); + return ret; +} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h new file mode 100644 index 00000000000..153168aff81 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +typedef struct FlipperI32HexFile FlipperI32HexFile; + +FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr); +FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name); +void flipper_i32hex_file_close(FlipperI32HexFile* instance); +void flipper_i32hex_file_bin_to_i32hex_add_data( + FlipperI32HexFile* instance, + uint8_t* data, + uint32_t data_size); +void flipper_i32hex_file_bin_to_i32hex_add_end_line(FlipperI32HexFile* instance); +const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance); +void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr); +bool flipper_i32hex_file_check(FlipperI32HexFile* instance); + diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index fcacaeee939..4cfb653cb7e 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,+,18.1,, +Version,+,18.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -187,6 +187,7 @@ Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, +Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/hmac_sha256.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, @@ -1592,6 +1593,10 @@ Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*" Function,+,hal_sd_detect,_Bool, Function,+,hal_sd_detect_init,void, Function,+,hal_sd_detect_set_low,void, +Function,+,hex_char_to_hex_nibble,_Bool,"char, uint8_t*" +Function,+,hex_char_to_uint8,_Bool,"char, char, uint8_t*" +Function,+,hex_chars_to_uint64,_Bool,"const char*, uint64_t*" +Function,+,hex_chars_to_uint8,_Bool,"const char*, uint8_t*" Function,+,hmac_sha256_finish,void,"const hmac_sha256_context*, const uint8_t*, uint8_t*" Function,+,hmac_sha256_init,void,"hmac_sha256_context*, const uint8_t*" Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, unsigned" @@ -2791,6 +2796,7 @@ Function,+,uECC_sign,int,"const uint8_t*, const uint8_t*, unsigned, uint8_t*, uE Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned, const uECC_HashContext*, uint8_t*, uECC_Curve" Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" +Function,+,uint8_to_hex_chars,void,"const uint8_t*, uint8_t*, int" Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" Function,-,ulTaskGetIdleRunTimeCounter,uint32_t, diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index d7b0e7bbc0c..4f83b7a23f5 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -28,6 +28,7 @@ env.Append( File("stream/buffered_file_stream.h"), File("protocols/protocol_dict.h"), File("pretty_format.h"), + File("hex.h"), ], ) From 5de80da3483abee94b8e2b1824a7645c81a66500 Mon Sep 17 00:00:00 2001 From: SkorP Date: Mon, 20 Mar 2023 00:09:23 +0400 Subject: [PATCH 16/50] AVR_ISP: add write eerom, flash, fuse, lock byte --- .../avr_isp_programmer/helpers/avr_isp.c | 545 +++++++++--------- .../avr_isp_programmer/helpers/avr_isp.h | 34 +- .../helpers/avr_isp_rw_worker.c | 170 +++++- .../helpers/flipper_i32hex_file.c | 84 +-- .../helpers/flipper_i32hex_file.h | 35 +- 5 files changed, 529 insertions(+), 339 deletions(-) diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c index 6f95a5a57b9..6234f7b177d 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c @@ -9,16 +9,7 @@ struct AvrIsp { AvrIspSpiSw* spi; - - uint16_t error; - uint16_t addr; bool pmode; - //uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE]; - - uint16_t pagesize; - uint16_t eepromsize; - uint32_t flashsize; - AvrIspCallback callback; void* context; }; @@ -134,160 +125,139 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { return false; } -// static void avr_isp_universal(AvrIsp* instance) { -// furi_assert(instance); -// uint8_t data; - -// avr_isp_fill(instance, 4); -// data = avr_isp_spi_transaction( -// instance, instance->buff[0], instance->buff[1], instance->buff[2], instance->buff[3]); -// avr_isp_breply(instance, data); -// } - -// static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { -// furi_assert(instance); -// avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr)); -// /* polling flash */ -// if(data == 0xFF) { -// furi_delay_ms(5); -// } else { -// /* polling flash */ -// uint32_t starttime = furi_get_tick(); -// while((furi_get_tick() - starttime) < 30) { -// if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { -// break; -// }; -// } -// } -// } - -// static uint16_t avr_isp_current_page(AvrIsp* instance) { -// furi_assert(instance); -// uint16_t page = 0; -// switch(instance->cfg->pagesize) { -// case 32: -// page = instance->addr & 0xFFFFFFF0; -// break; -// case 64: -// page = instance->addr & 0xFFFFFFE0; -// break; -// case 128: -// page = instance->addr & 0xFFFFFFC0; -// break; -// case 256: -// page = instance->addr & 0xFFFFFF80; -// break; - -// default: -// page = instance->addr; -// break; -// } - -// return page; -// } - -// static uint8_t avr_isp_write_flash_pages(AvrIsp* instance, size_t length) { -// furi_assert(instance); -// size_t x = 0; -// uint16_t page = avr_isp_current_page(instance); -// while(x < length) { -// if(page != avr_isp_current_page(instance)) { -// --x; -// avr_isp_commit(instance, page, instance->buff[x++]); -// page = avr_isp_current_page(instance); -// } -// avr_isp_spi_transaction( -// instance, AVR_ISP_WRITE_FLASH_LO(instance->addr, instance->buff[x++])); - -// avr_isp_spi_transaction( -// instance, AVR_ISP_WRITE_FLASH_HI(instance->addr, instance->buff[x++])); -// instance->addr++; -// } - -// avr_isp_commit(instance, page, instance->buff[--x]); -// return STK_OK; -// } - -// static void avr_isp_write_flash(AvrIsp* instance, size_t length) { -// furi_assert(instance); -// avr_isp_fill(instance, length); -// if(avr_isp_getch(instance) == CRC_EOP) { -// avr_isp_tx_ch(instance, STK_INSYNC); -// avr_isp_tx_ch(instance, avr_isp_write_flash_pages(instance, length)); -// } else { -// instance->error++; -// avr_isp_tx_ch(instance, STK_NOSYNC); -// } -// } - -// // write (length) bytes, (start) is a byte address -// static uint8_t -// avr_isp_write_eeprom_chunk(AvrIsp* instance, uint16_t start, uint16_t length) { -// furi_assert(instance); -// // this writes byte-by-byte, -// // page writing may be faster (4 bytes at a time) -// avr_isp_fill(instance, length); -// for(uint16_t x = 0; x < length; x++) { -// uint16_t addr = start + x; -// avr_isp_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, instance->buff[x])); -// furi_delay_ms(10); -// } -// return STK_OK; -// } - -// static uint8_t avr_isp_write_eeprom(AvrIsp* instance, size_t length) { -// furi_assert(instance); -// // here is a word address, get the byte address -// uint16_t start = instance->addr * 2; -// uint16_t remaining = length; -// if(length > instance->cfg->eepromsize) { -// instance->error++; -// return STK_FAILED; -// } -// while(remaining > AVR_ISP_EECHUNK) { -// avr_isp_write_eeprom_chunk(instance, start, AVR_ISP_EECHUNK); -// start += AVR_ISP_EECHUNK; -// remaining -= AVR_ISP_EECHUNK; -// } -// avr_isp_write_eeprom_chunk(instance, start, remaining); -// return STK_OK; -// } - -// static void avr_isp_program_page(AvrIsp* instance) { -// furi_assert(instance); -// uint8_t result = STK_FAILED; -// uint16_t length = avr_isp_getch(instance) << 8 | avr_isp_getch(instance); -// uint8_t memtype = avr_isp_getch(instance); -// // flash memory @addr, (length) bytes -// if(memtype == STK_SET_FLASH_TYPE) { -// avr_isp_write_flash(instance, length); -// return; -// } -// if(memtype == STK_SET_EEPROM_TYPE) { -// result = avr_isp_write_eeprom(instance, length); -// if(avr_isp_getch(instance) == CRC_EOP) { -// avr_isp_tx_ch(instance, STK_INSYNC); -// avr_isp_tx_ch(instance, result); - -// } else { -// instance->error++; -// avr_isp_tx_ch(instance, STK_NOSYNC); -// } -// return; -// } -// avr_isp_tx_ch(instance, STK_FAILED); -// return; -// } +static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { + furi_assert(instance); + avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr)); + /* polling flash */ + if(data == 0xFF) { + furi_delay_ms(5); + } else { + /* polling flash */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { + break; + }; + } + } +} + +static uint16_t avr_isp_current_page(AvrIsp* instance, uint32_t addr, uint16_t page_size) { + furi_assert(instance); + uint16_t page = 0; + switch(page_size) { + case 32: + page = addr & 0xFFFFFFF0; + break; + case 64: + page = addr & 0xFFFFFFE0; + break; + case 128: + page = addr & 0xFFFFFFC0; + break; + case 256: + page = addr & 0xFFFFFF80; + break; + + default: + page = addr; + break; + } + + return page; +} + +static bool avr_isp_flash_write_pages( + AvrIsp* instance, + uint16_t addr, + uint16_t page_size, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + + size_t x = 0; + uint16_t page = avr_isp_current_page(instance, addr, page_size); + + while(x < data_size) { + if(page != avr_isp_current_page(instance, addr, page_size)) { + avr_isp_commit(instance, page, data[x - 1]); + page = avr_isp_current_page(instance, addr, page_size); + } + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_LO(addr, data[x++])); + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_HI(addr, data[x++])); + addr++; + } + avr_isp_commit(instance, page, data[x - 1]); + return true; +} + +bool avr_isp_erase_chip(AvrIsp* instance) { + furi_assert(instance); + bool ret = false; + + if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance); + if(instance->pmode) { + avr_isp_spi_transaction(instance, AVR_ISP_ERASE_CHIP); + furi_delay_ms(100); + avr_isp_end_pmode(instance); + ret = true; + } + return ret; +} + +static bool + avr_isp_eeprom_write(AvrIsp* instance, uint16_t addr, uint8_t* data, uint32_t data_size) { + furi_assert(instance); + + for(uint16_t i = 0; i < data_size; i++) { + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, data[i])); + furi_delay_ms(10); + addr++; + } + return true; +} + +bool avr_isp_write_page( + AvrIsp* instance, + uint32_t mem_type, + uint32_t mem_size, + uint16_t addr, + uint16_t page_size, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + bool ret = false; + + switch(mem_type) { + case STK_SET_FLASH_TYPE: + if((addr + data_size / 2) <= mem_size) { + ret = avr_isp_flash_write_pages(instance, addr, page_size, data, data_size); + } + break; + + case STK_SET_EEPROM_TYPE: + if((addr + data_size) <= mem_size) { + ret = avr_isp_eeprom_write(instance, addr, data, data_size); + } + break; + + default: + furi_crash(TAG " Incorrect mem type."); + break; + } + + return ret; +} static bool avr_isp_flash_read_page( AvrIsp* instance, uint16_t addr, - uint16_t size_page, + uint16_t page_size, uint8_t* data, - uint32_t size_data) { + uint32_t data_size) { furi_assert(instance); - if(size_page > size_data) return false; - for(uint16_t i = 0; i < size_page; i += 2) { + if(page_size > data_size) return false; + for(uint16_t i = 0; i < page_size; i += 2) { data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(addr)); data[i + 1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)); addr++; @@ -298,12 +268,12 @@ static bool avr_isp_flash_read_page( static bool avr_isp_eeprom_read_page( AvrIsp* instance, uint16_t addr, - uint16_t size_page, + uint16_t page_size, uint8_t* data, - uint32_t size_data) { + uint32_t data_size) { furi_assert(instance); - if(size_page > size_data) return false; - for(uint16_t i = 0; i < size_page; i++) { + if(page_size > data_size) return false; + for(uint16_t i = 0; i < page_size; i++) { data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr)); addr++; } @@ -312,17 +282,17 @@ static bool avr_isp_eeprom_read_page( bool avr_isp_read_page( AvrIsp* instance, - uint32_t memtype, + uint32_t mem_type, uint16_t addr, - uint16_t size_page, + uint16_t page_size, uint8_t* data, - uint32_t size_data) { + uint32_t data_size) { furi_assert(instance); bool res = false; - if(memtype == STK_SET_FLASH_TYPE) - res = avr_isp_flash_read_page(instance, addr, size_page, data, size_data); - if(memtype == STK_SET_EEPROM_TYPE) - res = avr_isp_eeprom_read_page(instance, addr, size_page, data, size_data); + if(mem_type == STK_SET_FLASH_TYPE) + res = avr_isp_flash_read_page(instance, addr, page_size, data, data_size); + if(mem_type == STK_SET_EEPROM_TYPE) + res = avr_isp_eeprom_read_page(instance, addr, page_size, data, data_size); return res; } @@ -334,111 +304,134 @@ void avr_isp_read_signature(AvrIsp* instance, uint8_t* data) { data[2] = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); } -// void avr_isp_avrisp(AvrIsp* instance) { -// furi_assert(instance); -// uint8_t ch = avr_isp_getch(instance); - -// switch(ch) { -// case STK_GET_SYNC: -// FURI_LOG_D(TAG, "cmd STK_GET_SYNC"); -// instance->error = 0; -// avr_isp_empty_reply(instance); -// break; -// case STK_GET_SIGN_ON: -// FURI_LOG_D(TAG, "cmd STK_GET_SIGN_ON"); -// if(avr_isp_getch(instance) == CRC_EOP) { -// avr_isp_tx_ch(instance, STK_INSYNC); - -// avr_isp_tx_ch(instance, 'A'); -// avr_isp_tx_ch(instance, 'V'); -// avr_isp_tx_ch(instance, 'R'); -// avr_isp_tx_ch(instance, ' '); -// avr_isp_tx_ch(instance, 'I'); -// avr_isp_tx_ch(instance, 'S'); -// avr_isp_tx_ch(instance, 'P'); - -// avr_isp_tx_ch(instance, STK_OK); -// } else { -// instance->error++; -// avr_isp_tx_ch(instance, STK_NOSYNC); -// } -// break; -// case STK_GET_PARAMETER: -// FURI_LOG_D(TAG, "cmd STK_GET_PARAMETER"); -// avr_isp_get_version(instance, avr_isp_getch(instance)); -// break; -// case STK_SET_DEVICE: -// FURI_LOG_D(TAG, "cmd STK_SET_DEVICE"); -// avr_isp_fill(instance, 20); -// avr_isp_set_cfg(instance); -// avr_isp_empty_reply(instance); -// break; -// case STK_SET_DEVICE_EXT: // ignore for now -// FURI_LOG_D(TAG, "cmd STK_SET_DEVICE_EXT"); -// avr_isp_fill(instance, 5); -// avr_isp_empty_reply(instance); -// break; -// case STK_ENTER_PROGMODE: -// FURI_LOG_D(TAG, "cmd STK_ENTER_PROGMODE"); -// if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance); -// avr_isp_empty_reply(instance); -// break; -// case STK_LOAD_ADDRESS: -// FURI_LOG_D(TAG, "cmd STK_LOAD_ADDRESS"); -// instance->addr = avr_isp_getch(instance) | avr_isp_getch(instance) << 8; -// avr_isp_empty_reply(instance); -// break; -// case STK_PROG_FLASH: // ignore for now -// FURI_LOG_D(TAG, "cmd STK_PROG_FLASH"); -// avr_isp_getch(instance); -// avr_isp_getch(instance); -// avr_isp_empty_reply(instance); -// break; -// case STK_PROG_DATA: // ignore for now -// FURI_LOG_D(TAG, "cmd STK_PROG_DATA"); -// avr_isp_getch(instance); -// avr_isp_empty_reply(instance); -// break; -// case STK_PROG_PAGE: -// FURI_LOG_D(TAG, "cmd STK_PROG_PAGE"); -// avr_isp_program_page(instance); -// break; -// case STK_READ_PAGE: -// FURI_LOG_D(TAG, "cmd STK_READ_PAGE"); -// avr_isp_read_page(instance); -// break; -// case STK_UNIVERSAL: -// FURI_LOG_D(TAG, "cmd STK_UNIVERSAL"); -// avr_isp_universal(instance); -// break; -// case STK_LEAVE_PROGMODE: -// FURI_LOG_D(TAG, "cmd STK_LEAVE_PROGMODE"); -// instance->error = 0; -// if(instance->pmode) avr_isp_end_pmode(instance); -// avr_isp_empty_reply(instance); -// break; -// case STK_READ_SIGN: -// FURI_LOG_D(TAG, "cmd STK_READ_SIGN"); -// avr_isp_read_signature(instance); -// break; -// // expecting a command, not CRC_EOP -// // this is how we can get back in sync -// case CRC_EOP: -// FURI_LOG_D(TAG, "cmd CRC_EOP"); -// instance->error++; -// avr_isp_tx_ch(instance, STK_NOSYNC); -// break; -// // anything else we will return STK_UNKNOWN -// default: -// FURI_LOG_D(TAG, "cmd STK_ERROR_CMD"); -// instance->error++; -// if(avr_isp_getch(instance) == CRC_EOP) -// avr_isp_tx_ch(instance, STK_UNKNOWN); -// else -// avr_isp_tx_ch(instance, STK_NOSYNC); -// } - -// if(instance->callback) { -// instance->callback(instance->context); -// } -// } +uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { + furi_assert(instance); + uint8_t data = 0; + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 300) { + data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE); + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) { + break; + }; + data = 0x00; + } + return data; +} + +bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { + furi_assert(instance); + bool ret = false; + if(avr_isp_read_lock_byte(instance) == lock) { + ret = true; + } else { + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_LOCK_BYTE(lock)); + /* polling lock byte */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) { + ret = true; + break; + }; + } + } + return ret; +} + +uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { + furi_assert(instance); + uint8_t data = 0; + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 300) { + data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW); + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) { + break; + }; + data = 0x00; + } + return data; +} + +bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { + furi_assert(instance); + bool ret = false; + if(avr_isp_read_fuse_low(instance) == lfuse) { + ret = true; + } else { + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_LOW(lfuse)); + /* polling fuse */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) { + ret = true; + break; + }; + } + } + return ret; +} + +uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { + furi_assert(instance); + uint8_t data = 0; + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 300) { + data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH); + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) { + break; + }; + data = 0x00; + } + return data; +} + +bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { + furi_assert(instance); + bool ret = false; + if(avr_isp_read_fuse_high(instance) == hfuse) { + ret = true; + } else { + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_HIGH(hfuse)); + /* polling fuse */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) { + ret = true; + break; + }; + } + } + return ret; +} + +uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { + furi_assert(instance); + uint8_t data = 0; + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 300) { + data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED); + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) { + break; + }; + data = 0x00; + } + return data; +} + +bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { + furi_assert(instance); + bool ret = false; + if(avr_isp_read_fuse_extended(instance) == efuse) { + ret = true; + } else { + avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_EXTENDED(efuse)); + /* polling fuse */ + uint32_t starttime = furi_get_tick(); + while((furi_get_tick() - starttime) < 30) { + if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) { + ret = true; + break; + }; + } + } + return ret; +} diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h index ac9c243f3aa..391a682cd00 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h @@ -6,21 +6,51 @@ typedef struct AvrIsp AvrIsp; typedef void (*AvrIspCallback)(void* context); AvrIsp* avr_isp_alloc(void); + void avr_isp_free(AvrIsp* instance); + void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context); + bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance); + void avr_isp_read_signature(AvrIsp* instance, uint8_t* data); + void avr_isp_end_pmode(AvrIsp* instance); + +bool avr_isp_erase_chip(AvrIsp* instance); + uint8_t avr_isp_spi_transaction( AvrIsp* instance, uint8_t cmd, uint8_t addr_hi, uint8_t addr_lo, uint8_t data); + bool avr_isp_read_page( AvrIsp* instance, uint32_t memtype, uint16_t addr, - uint16_t size_page, + uint16_t page_size, uint8_t* data, - uint32_t size_data); \ No newline at end of file + uint32_t data_size); + +bool avr_isp_write_page( + AvrIsp* instance, + uint32_t mem_type, + uint32_t mem_size, + uint16_t addr, + uint16_t page_size, + uint8_t* data, + uint32_t data_size); + +uint8_t avr_isp_read_lock_byte(AvrIsp* instance); +bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock); + +uint8_t avr_isp_read_fuse_low(AvrIsp* instance); +bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse); + +uint8_t avr_isp_read_fuse_high(AvrIsp* instance); +bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse); + +uint8_t avr_isp_read_fuse_extended(AvrIsp* instance); +bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c index 88dc655ae3e..27bceb64a74 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c @@ -196,10 +196,10 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { } FURI_LOG_D(TAG, "ID = 0x%02X 0x%02X 0x%02X", data[0], data[1], data[2]); - data[0] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_HIGH); - data[1] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_LOW); - data[2] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_FUSE_EXTENDED); - data[3] = avr_isp_spi_transaction(instance->avr_isp, AVR_ISP_READ_LOCK_BYTE); + data[0] = avr_isp_read_fuse_high(instance->avr_isp); + data[1] = avr_isp_read_fuse_low(instance->avr_isp); + data[2] = avr_isp_read_fuse_extended(instance->avr_isp); + data[3] = avr_isp_read_lock_byte(instance->avr_isp); if(!flipper_format_write_hex(flipper_format, "Hfuse", data, 1)) { FURI_LOG_E(TAG, "Unable to add Hfuse"); @@ -243,8 +243,8 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { FURI_LOG_D(TAG, "EEPROM"); if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - FlipperI32HexFile* flipper_hex_eeprom = - flipper_i32hex_file_open_write("/any/avr_isp/eeprom.hex", 0); + FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( + "/any/avr_isp/eeprom.hex", avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); int32_t size_data = 32; if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; @@ -253,17 +253,17 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { i += size_data) { avr_isp_read_page( instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); - flipper_i32hex_file_bin_to_i32hex_add_data(flipper_hex_eeprom, data, size_data); + flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); } - flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_eeprom); + flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); flipper_i32hex_file_close(flipper_hex_eeprom); } // FURI_LOG_D(TAG, "FLASH"); // FlipperI32HexFile* flipper_hex_flash = - // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", 0); + // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", avr_isp_chip_arr[instance->chip_arr_ind].flashoffset;); // for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; // i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { // avr_isp_read_page( @@ -283,17 +283,149 @@ bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { avr_isp_end_pmode(instance->avr_isp); - FURI_LOG_D(TAG, "EEPROM READ"); - FlipperI32HexFile* flipper_hex_eeprom_read = - flipper_i32hex_file_open_read("/any/avr_isp/eeprom.hex"); - FURI_LOG_D(TAG, "EEPROM READ1"); - if(flipper_i32hex_file_check(flipper_hex_eeprom_read)){ - FURI_LOG_D(TAG, "Check OK"); - } else { - FURI_LOG_E(TAG, "Check ERROR"); - } - flipper_i32hex_file_close(flipper_hex_eeprom_read); + // // //################################################################ + // FURI_LOG_D(TAG, "FUSE Write"); + // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + // break; + // } + // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_low(instance->avr_isp, 0xFF)); + // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_extended(instance->avr_isp, 0xFD)); + // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_high(instance->avr_isp, 0xDA)); + // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_lock_byte(instance->avr_isp, 0xFF)); + + + // avr_isp_end_pmode(instance->avr_isp); + // //################################################################## + + // //################################################################ + // FURI_LOG_D(TAG, "ERASE CHIP"); + // avr_isp_erase_chip(instance->avr_isp); + // //################################################################## + + // //########################################################## + // FURI_LOG_D(TAG, "FLASH WRITE"); + // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + // break; + // } + // avr_isp_read_signature(instance->avr_isp, data); + + // FlipperI32HexFile* flipper_hex_flash = + // flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); + + // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + // FlipperI32HexFileRet flipper_hex_ret = + // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); + // FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); + // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { + // // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); + // // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // // printf("%02X ", data[i]); + // // } + // // printf("\r\n"); + + // switch(flipper_hex_ret.status) { + // case FlipperI32HexFileStatusData: + // if(!avr_isp_write_page( + // instance->avr_isp, + // STK_SET_FLASH_TYPE, + // avr_isp_chip_arr[instance->chip_arr_ind].flashsize, + // addr, + // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, + // data, + // flipper_hex_ret.data_size)) { + // break; + // } + // addr += flipper_hex_ret.data_size/2; + // break; + + // case FlipperI32HexFileStatusUdateAddr: + // addr = data[0] << 24 | data[1] << 16; + // break; + + // default: + // furi_crash(TAG " Incorrect status."); + // break; + // } + + // flipper_hex_ret = + // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); + // } + + // flipper_i32hex_file_close(flipper_hex_flash); + // avr_isp_end_pmode(instance->avr_isp); + //########################################################## + + // FURI_LOG_D(TAG, "CHECK HEX"); + // FlipperI32HexFile* flipper_hex_eeprom_read = + // flipper_i32hex_file_open_read("/any/avr_isp/a.hex"); + // if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { + // FURI_LOG_D(TAG, "Check OK"); + // } else { + // FURI_LOG_E(TAG, "Check ERROR"); + // } + // // flipper_i32hex_file_close(flipper_hex_eeprom_read); + + // //########################################################## + // FURI_LOG_D(TAG, "EEPROM WRITE"); + + // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + // break; + // } + // avr_isp_read_signature(instance->avr_isp, data); + // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; + // FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + // flipper_hex_eeprom_read, data, sizeof(data)); + + // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { + // FURI_LOG_D(TAG, "EEPROM WRITE Page"); + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data[i]); + // } + // printf("\r\n"); + + // switch(flipper_hex_ret.status) { + // case FlipperI32HexFileStatusData: + // if(!avr_isp_write_page( + // instance->avr_isp, + // STK_SET_EEPROM_TYPE, + // avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, + // addr, + // avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, + // data, + // flipper_hex_ret.data_size)) { + // break; + // } + // addr += flipper_hex_ret.data_size; + // break; + + // case FlipperI32HexFileStatusUdateAddr: + // addr = data[0] << 24 | data[1] << 16; + // break; + + // default: + // furi_crash(TAG " Incorrect status."); + // break; + // } + + // flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + // flipper_hex_eeprom_read, data, sizeof(data)); + // } + + // flipper_i32hex_file_close(flipper_hex_eeprom_read); + // avr_isp_end_pmode(instance->avr_isp); + // //########################################################## + + // //################################################################ + // FURI_LOG_D(TAG, "ERASE CHIP"); + // avr_isp_erase_chip(instance->avr_isp); + // //################################################################## + FURI_LOG_D(TAG, "___END___"); } while(0); flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c index 4aa5caa747e..6f98cbf733b 100644 --- a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -22,30 +22,9 @@ struct FlipperI32HexFile { Storage* storage; Stream* stream; FuriString* str_data; - bool file_open; + FlipperI32HexFileStatus file_open; }; -typedef enum { - FlipperI32HexFileStatusOK = 0, - FlipperI32HexFileStatusData = 2, - FlipperI32HexFileStatusUdateAddr = 3, - FlipperI32HexFileStatusEofFile = 4, - - // Errors - FlipperI32HexFileStatusErrorCrc = (-1), - FlipperI32HexFileStatusErrorOverflow = (-2), - FlipperI32HexFileStatusErrorData = (-3), - FlipperI32HexFileStatusErrorUnsupportedCommand = (-4), - - FlipperI32HexFileStatusReserved = - 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. -} FlipperI32HexFileStatus; - -typedef struct { - FlipperI32HexFileStatus status; - uint32_t data_size; -} FlipperI32HexFileRet; - FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr) { furi_assert(name); @@ -55,11 +34,11 @@ FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t sta instance->storage = furi_record_open(RECORD_STORAGE); instance->stream = file_stream_alloc(instance->storage); - if(!file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - FURI_LOG_E(TAG, "Failed to open file"); - instance->file_open = false; + if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + instance->file_open = FlipperI32HexFileStatusOpenFileWrite; } else { - instance->file_open = true; + FURI_LOG_E(TAG, "Failed to open file"); + instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; } instance->str_data = furi_string_alloc(instance->storage); @@ -75,11 +54,11 @@ FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { instance->storage = furi_record_open(RECORD_STORAGE); instance->stream = file_stream_alloc(instance->storage); - if(!file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Failed to open file"); - instance->file_open = false; + if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { + instance->file_open = FlipperI32HexFileStatusOpenFileRead; } else { - instance->file_open = true; + FURI_LOG_E(TAG, "Failed to open file"); + instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; } instance->str_data = furi_string_alloc(instance->storage); @@ -94,13 +73,17 @@ void flipper_i32hex_file_close(FlipperI32HexFile* instance) { furi_record_close(RECORD_STORAGE); } -void flipper_i32hex_file_bin_to_i32hex_add_data( +FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( FlipperI32HexFile* instance, uint8_t* data, uint32_t data_size) { furi_assert(instance); furi_assert(data); + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; + if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) { + ret.status = FlipperI32HexFileStatusErrorFileWrite; + } uint8_t count_byte = 0; uint32_t ind = 0; uint8_t crc = 0; @@ -137,14 +120,20 @@ void flipper_i32hex_file_bin_to_i32hex_add_data( instance->addr += count_byte; } if(instance->file_open) stream_write_string(instance->stream, instance->str_data); + return ret; } -void flipper_i32hex_file_bin_to_i32hex_add_end_line(FlipperI32HexFile* instance) { +FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance) { furi_assert(instance); + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; + if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) { + ret.status = FlipperI32HexFileStatusErrorFileWrite; + } furi_string_reset(instance->str_data); //I32HEX_TYPE_END_OF_FILE furi_string_cat_printf(instance->str_data, ":00000001FF\r\n"); if(instance->file_open) stream_write_string(instance->stream, instance->str_data); + return ret; } void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) { @@ -234,6 +223,7 @@ static FlipperI32HexFileRet flipper_i32hex_file_parse( if(flipper_i32hex_file_check_data(data, ret.data_size)) { ret.data_size -= 5; memcpy(data, data + 4, ret.data_size); + ret.status =FlipperI32HexFileStatusData; } else { ret.status = FlipperI32HexFileStatusErrorCrc; ret.data_size = 0; @@ -280,27 +270,43 @@ static FlipperI32HexFileRet flipper_i32hex_file_parse( bool flipper_i32hex_file_check(FlipperI32HexFile* instance) { furi_assert(instance); - furi_delay_ms(100); uint32_t data_size = 280; uint8_t data[280] = {0}; - FuriString* line = furi_string_alloc(); bool ret = true; - if(!instance->file_open) { + if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) { FURI_LOG_E(TAG, "File is not open"); + ret = false; } else { stream_rewind(instance->stream); - while(stream_read_line(instance->stream, line)) { - FlipperI32HexFileRet parse_ret = - flipper_i32hex_file_parse(instance, furi_string_get_cstr(line), data, data_size); + while(stream_read_line(instance->stream, instance->str_data)) { + FlipperI32HexFileRet parse_ret = flipper_i32hex_file_parse( + instance, furi_string_get_cstr(instance->str_data), data, data_size); if(parse_ret.status < 0) { ret = false; } } + stream_rewind(instance->stream); + } + return ret; +} + +FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( + FlipperI32HexFile* instance, + uint8_t* data, + uint32_t data_size) { + furi_assert(instance); + furi_assert(data); + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; + if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) { + ret.status = FlipperI32HexFileStatusErrorFileRead; + } else { + stream_read_line(instance->stream, instance->str_data); + ret = flipper_i32hex_file_parse( + instance, furi_string_get_cstr(instance->str_data), data, data_size); } - furi_string_free(line); return ret; } \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h index 153168aff81..3d81c5deb0e 100644 --- a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h @@ -4,15 +4,44 @@ typedef struct FlipperI32HexFile FlipperI32HexFile; +typedef enum { + FlipperI32HexFileStatusOK = 0, + FlipperI32HexFileStatusData = 2, + FlipperI32HexFileStatusUdateAddr = 3, + FlipperI32HexFileStatusEofFile = 4, + FlipperI32HexFileStatusOpenFileWrite = 5, + FlipperI32HexFileStatusOpenFileRead = 6, + + // Errors + FlipperI32HexFileStatusErrorCrc = (-1), + FlipperI32HexFileStatusErrorOverflow = (-2), + FlipperI32HexFileStatusErrorData = (-3), + FlipperI32HexFileStatusErrorUnsupportedCommand = (-4), + FlipperI32HexFileStatusErrorNoOpenFile = (-5), + FlipperI32HexFileStatusErrorFileWrite = (-6), + FlipperI32HexFileStatusErrorFileRead = (-7), + + FlipperI32HexFileStatusReserved = + 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. +} FlipperI32HexFileStatus; + +typedef struct { + FlipperI32HexFileStatus status; + uint32_t data_size; +} FlipperI32HexFileRet; + FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr); FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name); void flipper_i32hex_file_close(FlipperI32HexFile* instance); -void flipper_i32hex_file_bin_to_i32hex_add_data( +FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( FlipperI32HexFile* instance, uint8_t* data, uint32_t data_size); -void flipper_i32hex_file_bin_to_i32hex_add_end_line(FlipperI32HexFile* instance); +FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance); const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance); void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr); bool flipper_i32hex_file_check(FlipperI32HexFile* instance); - +FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( + FlipperI32HexFile* instance, + uint8_t* data, + uint32_t data_size); \ No newline at end of file From 2280dc40a1188c93afce6aa00759e7b2b3126e49 Mon Sep 17 00:00:00 2001 From: SkorP Date: Mon, 20 Mar 2023 23:22:57 +0400 Subject: [PATCH 17/50] AVR_ISP: add gui Reader, Writer --- applications/external/dap_link/lib/free-dap | 1 + .../plugins/avr_isp_programmer/avr_isp_app.c | 33 +++- .../avr_isp_programmer/avr_isp_app_i.c | 24 +++ .../avr_isp_programmer/avr_isp_app_i.h | 17 ++ .../helpers/avr_isp_event.h | 1 + .../helpers/avr_isp_rw_worker.c | 2 +- .../helpers/avr_isp_types.h | 4 + .../avr_isp_programmer/images/avr_isp.png | Bin 0 -> 143 bytes .../scenes/avr_isp_scene_config.h | 5 +- .../scenes/avr_isp_scene_input_name.c | 113 ++++++++++++ .../scenes/avr_isp_scene_load.c | 31 ++++ .../scenes/avr_isp_scene_reader.c | 16 +- .../scenes/avr_isp_scene_start.c | 12 +- .../scenes/avr_isp_scene_writer.c | 38 ++++ .../views/avr_isp_view_programmer.c | 2 +- .../views/avr_isp_view_reader.c | 10 ++ .../views/avr_isp_view_writer.c | 170 ++++++++++++++++++ .../views/avr_isp_view_writer.h | 22 +++ 18 files changed, 488 insertions(+), 13 deletions(-) create mode 160000 applications/external/dap_link/lib/free-dap create mode 100644 applications/plugins/avr_isp_programmer/images/avr_isp.png create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c create mode 100644 applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c create mode 100644 applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h diff --git a/applications/external/dap_link/lib/free-dap b/applications/external/dap_link/lib/free-dap new file mode 160000 index 00000000000..e7752beb5e8 --- /dev/null +++ b/applications/external/dap_link/lib/free-dap @@ -0,0 +1 @@ +Subproject commit e7752beb5e8a69119af67b70b9179cb3c90f3ac5 diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app.c b/applications/plugins/avr_isp_programmer/avr_isp_app.c index 98d45b1cf83..679840f253a 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app.c +++ b/applications/plugins/avr_isp_programmer/avr_isp_app.c @@ -24,6 +24,8 @@ static void avr_isp_app_tick_event_callback(void* context) { AvrIspApp* avr_isp_app_alloc() { AvrIspApp* app = malloc(sizeof(AvrIspApp)); + app->file_path = furi_string_alloc(); + // GUI app->gui = furi_record_open(RECORD_GUI); @@ -61,13 +63,21 @@ AvrIspApp* avr_isp_app_alloc() { app->widget = widget_alloc(); view_dispatcher_add_view(app->view_dispatcher, AvrIspViewWidget, widget_get_view(app->widget)); + // Text Input + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, AvrIspViewTextInput, text_input_get_view(app->text_input)); + + //Dialog + app->dialogs = furi_record_open(RECORD_DIALOGS); + // Programmer view app->avr_asp_programmer_view = avr_asp_programmer_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, AvrIspViewProgrammer, avr_asp_programmer_view_get_view(app->avr_asp_programmer_view)); - + // Reader view app->avr_asp_reader_view = avr_asp_reader_view_alloc(); view_dispatcher_add_view( @@ -75,6 +85,13 @@ AvrIspApp* avr_isp_app_alloc() { AvrIspViewReader, avr_asp_reader_view_get_view(app->avr_asp_reader_view)); + // Reader view + app->avr_asp_writer_view = avr_asp_writer_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + AvrIspViewWriter, + avr_asp_writer_view_get_view(app->avr_asp_writer_view)); + scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); return app; @@ -95,6 +112,13 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWidget); widget_free(app->widget); + // TextInput + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewTextInput); + text_input_free(app->text_input); + + //Dialog + furi_record_close(RECORD_DIALOGS); + // Programmer view view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer); avr_asp_programmer_view_free(app->avr_asp_programmer_view); @@ -103,6 +127,10 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader); avr_asp_reader_view_free(app->avr_asp_reader_view); + // Reader view + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWriter); + avr_asp_writer_view_free(app->avr_asp_writer_view); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); @@ -114,6 +142,9 @@ void avr_isp_app_free(AvrIspApp* app) { // Close records furi_record_close(RECORD_GUI); + // Path strings + furi_string_free(app->file_path); + free(app); } diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c index 2b327f24921..b196624dc39 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c @@ -2,3 +2,27 @@ #define TAG "AvrIsp" #include + + +bool avr_isp_load_from_file(AvrIspApp* app) { + furi_assert(app); + + FuriString* file_path; + file_path = furi_string_alloc(); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, AVR_ISP_APP_EXTENSION, &I_avr_isp); + browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; + + // Input events and views are managed by file_select + bool res = dialog_file_browser_show( + app->dialogs, app->file_path, app->file_path, &browser_options); + + // if(res) { + // res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); + // } + + furi_string_free(file_path); + + return res; +} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h index cf8ad2168d6..6f82b75518f 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h @@ -1,6 +1,7 @@ #pragma once #include "helpers/avr_isp_types.h" +#include #include "scenes/avr_isp_scene.h" #include @@ -9,10 +10,17 @@ #include #include #include +#include +#include +#include //#include #include "views/avr_isp_view_programmer.h" #include "views/avr_isp_view_reader.h" +#include "views/avr_isp_view_writer.h" + +#define AVR_ISP_MAX_LEN_NAME 64 + typedef struct AvrIspApp AvrIspApp; @@ -21,9 +29,18 @@ struct AvrIspApp { ViewDispatcher* view_dispatcher; SceneManager* scene_manager; NotificationApp* notifications; + DialogsApp* dialogs; //VariableItemList* variable_item_list; Submenu* submenu; Widget* widget; + TextInput* text_input; + FuriString* file_path; + //FuriString* file_name; + char file_name_tmp[AVR_ISP_MAX_LEN_NAME]; AvrIspProgrammerView* avr_asp_programmer_view; AvrIspReaderView* avr_asp_reader_view; + AvrIspWriterView* avr_asp_writer_view; }; + + +bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h index 36c46264181..f0bd02f7867 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h @@ -2,4 +2,5 @@ typedef enum { AvrIspCustomEventStartId = 100, + AvrIspCustomEventSceneInputName, } AvrIspCustomEvent; diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c index 27bceb64a74..00d32543488 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c @@ -68,7 +68,7 @@ void avr_isp_rw_worker_detect_chip(AvrIspRWWorker* instance) { instance->chip_arr_ind = ind; } } - avr_isp_rw_worker_rx(instance); + // avr_isp_rw_worker_rx(instance); } /** Worker thread diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h index 6b465884beb..6e5f13b89b1 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -7,10 +7,14 @@ #define AVR_ISP_DEVELOPED "SkorP" #define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" +#define AVR_ISP_APP_EXTENSION ".avr" + typedef enum { //AvrIspViewVariableItemList, AvrIspViewSubmenu, AvrIspViewProgrammer, AvrIspViewReader, + AvrIspViewWriter, AvrIspViewWidget, + AvrIspViewTextInput, } AvrIspView; diff --git a/applications/plugins/avr_isp_programmer/images/avr_isp.png b/applications/plugins/avr_isp_programmer/images/avr_isp.png new file mode 100644 index 0000000000000000000000000000000000000000..2278ce2b61cf97e51720bafb2d07dae48d986560 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>@$__Y43U`H zI>D2R!GMF={pJ7tHnyBWw`O@WO=4vXnQOryxnPsm9sxmyCsV>A?tXRt_DY<&Wq)IO q>DB4a%~XFc{Gk)L^WR4G>Gvdb>|Y;BDpm&?%HZkh=d#Wzp$P!!VJ~6; literal 0 HcmV?d00001 diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h index a107029a75a..6c829afd0ef 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h @@ -1,4 +1,7 @@ ADD_SCENE(avr_isp, start, Start) ADD_SCENE(avr_isp, about, About) ADD_SCENE(avr_isp, programmer, Programmer) -ADD_SCENE(avr_isp, reader, Reader) \ No newline at end of file +ADD_SCENE(avr_isp, reader, Reader) +ADD_SCENE(avr_isp, input_name, InputName) +ADD_SCENE(avr_isp, load, Load) +ADD_SCENE(avr_isp, writer, Writer) diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c new file mode 100644 index 00000000000..5ba1e7eeeda --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c @@ -0,0 +1,113 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_programmer.h" +#include +#include + +#define MAX_TEXT_INPUT_LEN 22 + +void avr_isp_scene_input_name_text_callback(void* context) { + furi_assert(context); + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneInputName); +} + +void avr_isp_scene_input_name_get_timefilename(FuriString* name) { + FuriHalRtcDateTime datetime = {0}; + furi_hal_rtc_get_datetime(&datetime); + furi_string_printf( + name, + "AVR_dump-%.4d%.2d%.2d-%.2d%.2d%.2d", + datetime.year, + datetime.month, + datetime.day, + datetime.hour, + datetime.minute, + datetime.second); +} + +void avr_isp_scene_input_name_on_enter(void* context) { + AvrIspApp* app = context; + + // Setup view + TextInput* text_input = app->text_input; + bool dev_name_empty = false; + + FuriString* file_name; + FuriString* dir_name; + file_name = furi_string_alloc(); + dir_name = furi_string_alloc(); + + //if(!app_path_is_file(app->file_path)) { + char file_name_buf[AVR_ISP_MAX_LEN_NAME] = {0}; + set_random_name(file_name_buf, AVR_ISP_MAX_LEN_NAME); + furi_string_set(file_name, file_name_buf); + //furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); + //highlighting the entire filename by default + dev_name_empty = true; + //} + //else { + // furi_string_set(app->file_path_tmp, app->file_path); + // path_extract_dirname(furi_string_get_cstr(app->file_path), dir_name); + // path_extract_filename(app->file_path, file_name, true); + // if(scene_manager_get_scene_state(app->scene_manager, SubGhzSceneReadRAW) != + // SubGhzCustomEventManagerNoSet) { + // if(scene_manager_get_scene_state(app->scene_manager, SubGhzSceneReadRAW) == + // SubGhzCustomEventManagerSetRAW) { + // dev_name_empty = true; + // avr_isp_scene_input_name_get_timefilename(file_name); + // } + // } + // furi_string_set(app->file_path, dir_name); + // } + + strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); + text_input_set_header_text(text_input, "Name dump"); + text_input_set_result_callback( + text_input, + avr_isp_scene_input_name_text_callback, + app, + app->file_name_tmp, + MAX_TEXT_INPUT_LEN, // buffer size + dev_name_empty); + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(STORAGE_APP_DATA_PATH_PREFIX, AVR_ISP_APP_EXTENSION, ""); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + furi_string_free(file_name); + furi_string_free(dir_name); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewTextInput); +} + +bool avr_isp_scene_input_name_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + if(event.type == SceneManagerEventTypeBack) { + scene_manager_previous_scene(app->scene_manager); + return true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == AvrIspCustomEventSceneInputName) { + if(strcmp(app->file_name_tmp, "") != 0) { + //furi_string_set(file_name, app->file_name_tmp); + scene_manager_next_scene(app->scene_manager, AvrIspSceneReader); + } else { + // furi_string_set(app->error_str, "No name file"); + // scene_manager_next_scene(app->scene_manager, SubGhzSceneShowErrorSub); + // return true; + } + } + } + return false; +} + +void avr_isp_scene_input_name_on_exit(void* context) { + AvrIspApp* app = context; + + // Clear validator + void* validator_context = text_input_get_validator_callback_context(app->text_input); + text_input_set_validator(app->text_input, NULL, NULL); + validator_is_file_free(validator_context); + + // Clear view + text_input_reset(app->text_input); +} diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c new file mode 100644 index 00000000000..9c0741314f6 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c @@ -0,0 +1,31 @@ +#include "../avr_isp_app_i.h" + +void avr_isp_scene_load_on_enter(void* context) { + AvrIspApp* app = context; + + if(avr_isp_load_from_file(app)) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneWriter); + } else { + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, AvrIspSceneStart); + } + // if(avr_isp_load_protocol_from_file(subghz)) { + // if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { + // subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; + // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); + // } else { + // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); + // } + // } else { + // scene_manager_search_and_switch_to_previous_scene(subghz->scene_manager, SubGhzSceneStart); + // } +} + +bool avr_isp_scene_load_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void avr_isp_scene_load_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c index 0184819edfe..50b416cf191 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -1,22 +1,22 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_reader.h" +#include "../views/avr_isp_view_writer.h" -void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { +void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } -void avr_isp_scene_reader_on_enter(void* context) { +void avr_isp_scene_writer_on_enter(void* context) { AvrIspApp* app = context; - avr_asp_reader_view_set_callback( - app->avr_asp_reader_view, avr_isp_scene_reader_callback, app); + avr_asp_writer_view_set_callback( + app->avr_asp_writer_view, avr_isp_scene_writer_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter); } -bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { +bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; UNUSED(app); bool consumed = false; @@ -33,6 +33,6 @@ bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { return consumed; } -void avr_isp_scene_reader_on_exit(void* context) { +void avr_isp_scene_writer_on_exit(void* context) { UNUSED(context); } diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c index a77b3b2c88c..63086156108 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -3,6 +3,7 @@ typedef enum { SubmenuIndexAvrIspProgrammer, SubmenuIndexAvrIspReader, + SubmenuIndexAvrIspWriter, SubmenuIndexAvrIspAbout, } SubmenuIndex; @@ -28,6 +29,12 @@ void avr_isp_scene_start_on_enter(void* context) { SubmenuIndexAvrIspReader, avr_isp_scene_start_submenu_callback, app); + submenu_add_item( + submenu, + "AVR ISP Writer", + SubmenuIndexAvrIspWriter, + avr_isp_scene_start_submenu_callback, + app); submenu_add_item( submenu, "About", SubmenuIndexAvrIspAbout, avr_isp_scene_start_submenu_callback, app); @@ -49,7 +56,10 @@ bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); consumed = true; }else if(event.event == SubmenuIndexAvrIspReader) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneReader); + scene_manager_next_scene(app->scene_manager, AvrIspSceneInputName); + consumed = true; + }else if(event.event == SubmenuIndexAvrIspWriter) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); consumed = true; } scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c new file mode 100644 index 00000000000..0184819edfe --- /dev/null +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -0,0 +1,38 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_reader.h" + +void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { + furi_assert(context); + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void avr_isp_scene_reader_on_enter(void* context) { + AvrIspApp* app = context; + + avr_asp_reader_view_set_callback( + app->avr_asp_reader_view, avr_isp_scene_reader_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); +} + +bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + UNUSED(app); + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + // case WSCustomEventViewreaderBack: + // consumed = true; + // break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + } + return consumed; +} + +void avr_isp_scene_reader_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c index 99c705abf71..30513b6c7f7 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -38,7 +38,7 @@ void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod // canvas_set_color(canvas, ColorBlack); // canvas_set_font(canvas, FontSecondary); - // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + //canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); // canvas_set_font(canvas, FontPrimary); // canvas_draw_str(canvas, 63, 46, "AVRISPProg"); // canvas_set_font(canvas, FontSecondary); diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c index cadc8da8186..7ed36030a3b 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c @@ -1,6 +1,7 @@ #include "avr_isp_view_reader.h" #include "../avr_isp_app_i.h" #include +#include #include "../helpers/avr_isp_rw_worker.h" //#include @@ -39,10 +40,15 @@ void avr_asp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { // canvas_set_font(canvas, FontSecondary); // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 20, 10, "AVRISPReader"); // canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontPrimary); + + elements_button_left(canvas, "ReDetect"); + elements_button_center(canvas, "Dump"); + if(!model->detect_chip) { canvas_draw_icon_animation(canvas, 0, 0, model->icon); canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); @@ -59,6 +65,10 @@ bool avr_asp_reader_view_input(InputEvent* event, void* context) { UNUSED(instance); if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; + } else if(event->key == InputKeyOk && event->type == InputTypePress) { + } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + FURI_LOG_D("s", "--Detecting--"); + avr_isp_rw_worker_detect_chip(instance->worker); } return true; diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c new file mode 100644 index 00000000000..e50597d1d73 --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c @@ -0,0 +1,170 @@ +#include "avr_isp_view_reader.h" +#include "../avr_isp_app_i.h" +#include +#include + +#include "../helpers/avr_isp_rw_worker.h" +//#include + +//#include +//#include + +struct AvrIspWriterView { + View* view; + AvrIspRWWorker* worker; + AvrIspWriterViewCallback callback; + void* context; +}; + +typedef struct { + uint16_t idx; + IconAnimation* icon; + const char* name_chip; + bool detect_chip; +} AvrIspWriterViewModel; + +void avr_asp_writer_view_set_callback( + AvrIspWriterView* instance, + AvrIspWriterViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +void avr_asp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { + UNUSED(model); + canvas_clear(canvas); + // canvas_set_color(canvas, ColorBlack); + // canvas_set_font(canvas, FontSecondary); + + // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 20, 10, "AVRISPWriter"); + // canvas_set_font(canvas, FontSecondary); + canvas_set_font(canvas, FontPrimary); + + elements_button_left(canvas, "ReDetect"); + elements_button_center(canvas, "Dump"); + + if(!model->detect_chip) { + canvas_draw_icon_animation(canvas, 0, 0, model->icon); + canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); + canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); + } else { + canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); + canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + } +} + +bool avr_asp_writer_view_input(InputEvent* event, void* context) { + furi_assert(context); + AvrIspWriterView* instance = context; + UNUSED(instance); + if(event->key == InputKeyBack || event->type != InputTypeShort) { + return false; + } else if(event->key == InputKeyOk && event->type == InputTypePress) { + } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + FURI_LOG_D("s", "--Detecting--"); + avr_isp_rw_worker_detect_chip(instance->worker); + } + + return true; +} + +static void avr_asp_writer_detect_chip_callback(void* context, const char* name) { + furi_assert(context); + AvrIspWriterView* instance = context; + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + model->name_chip = name; + model->detect_chip = true; + icon_animation_stop(model->icon); + }, + true); +} +void avr_asp_writer_view_enter(void* context) { + furi_assert(context); + AvrIspWriterView* instance = context; + + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + icon_animation_start(model->icon); + model->detect_chip = false; + }, + false); + + //Start worker + instance->worker = avr_isp_rw_worker_alloc(instance->context); + + avr_isp_rw_worker_set_callback( + instance->worker, avr_asp_writer_detect_chip_callback, instance); + + avr_isp_rw_worker_detect_chip(instance->worker); + + //avr_isp_rw_worker_start(instance->worker); +} + +void avr_asp_writer_view_exit(void* context) { + furi_assert(context); + AvrIspWriterView* instance = context; + // //Stop worker + // if(avr_isp_worker_is_running(instance->worker)) { + // avr_isp_worker_stop(instance->worker); + // } + avr_isp_rw_worker_free(instance->worker); + + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { icon_animation_stop(model->icon); }, + false); +} + +AvrIspWriterView* avr_asp_writer_view_alloc() { + AvrIspWriterView* instance = malloc(sizeof(AvrIspWriterView)); + + // View allocation and configuration + instance->view = view_alloc(); + + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspWriterViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_writer_view_draw); + view_set_input_callback(instance->view, avr_asp_writer_view_input); + view_set_enter_callback(instance->view, avr_asp_writer_view_enter); + view_set_exit_callback(instance->view, avr_asp_writer_view_exit); + + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + model->icon = icon_animation_alloc(&A_ChipLooking_64x64); + view_tie_icon_animation(instance->view, model->icon); + model->detect_chip = false; + }, + false); + return instance; +} + +void avr_asp_writer_view_free(AvrIspWriterView* instance) { + furi_assert(instance); + + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { icon_animation_free(model->icon); }, + false); + view_free(instance->view); + free(instance); +} + +View* avr_asp_writer_view_get_view(AvrIspWriterView* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h new file mode 100644 index 00000000000..d6d10baeeae --- /dev/null +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "../helpers/avr_isp_types.h" +#include "../helpers/avr_isp_event.h" + +typedef struct AvrIspWriterView AvrIspWriterView; + +typedef void (*AvrIspWriterViewCallback)(AvrIspCustomEvent event, void* context); + +void avr_asp_writer_view_set_callback( + AvrIspWriterView* instance, + AvrIspWriterViewCallback callback, + void* context); + +AvrIspWriterView* avr_asp_writer_view_alloc(); + +void avr_asp_writer_view_free(AvrIspWriterView* instance); + +View* avr_asp_writer_view_get_view(AvrIspWriterView* instance); + +void avr_asp_writer_view_exit(void* context); From 980ba867b8913ea2259da66eb8c99a17455a4b0d Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Tue, 21 Mar 2023 18:14:43 +0900 Subject: [PATCH 18/50] Github: unshallow on decontamination --- .github/workflows/unit_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index bed5a470d5c..74b0dcb9004 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -15,7 +15,7 @@ jobs: - 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)" + git submodule status || (git fetch --unshallow; git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1))" fi - name: Checkout code @@ -32,7 +32,7 @@ jobs: - name: 'Flash unit tests firmware' id: flashing if: success() - run: | + run: | ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 - name: 'Wait for flipper and format ext' From 3335cc94925e527858254ae713d0d1878dc2a706 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 21 Mar 2023 18:22:46 +0400 Subject: [PATCH 19/50] AVR_ISP: refactoring --- .../plugins/avr_isp_programmer/avr_isp_app.c | 18 +- .../avr_isp_programmer/avr_isp_app_i.c | 5 +- .../avr_isp_programmer/avr_isp_app_i.h | 14 +- .../avr_isp_programmer/helpers/avr_isp.c | 10 +- .../avr_isp_programmer/helpers/avr_isp.h | 12 +- .../avr_isp_programmer/helpers/avr_isp_rw.c | 596 ++++++++++++++++++ .../avr_isp_programmer/helpers/avr_isp_rw.h | 37 ++ .../helpers/avr_isp_rw_worker.c | 433 ------------- .../helpers/avr_isp_rw_worker.h | 58 -- .../helpers/avr_isp_rw_worker_cmd.h | 8 - .../helpers/avr_isp_types.h | 2 + .../helpers/flipper_i32hex_file.c | 6 +- .../scenes/avr_isp_scene_input_name.c | 8 +- .../scenes/avr_isp_scene_programmer.c | 4 +- .../scenes/avr_isp_scene_reader.c | 18 +- .../scenes/avr_isp_scene_writer.c | 16 +- .../views/avr_isp_view_programmer.c | 28 +- .../views/avr_isp_view_programmer.h | 10 +- .../views/avr_isp_view_reader.c | 85 ++- .../views/avr_isp_view_reader.h | 15 +- .../views/avr_isp_view_writer.c | 59 +- .../views/avr_isp_view_writer.h | 10 +- 22 files changed, 811 insertions(+), 641 deletions(-) create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c create mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h delete mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c delete mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h delete mode 100644 applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app.c b/applications/plugins/avr_isp_programmer/avr_isp_app.c index 679840f253a..65cb6df0ce5 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app.c +++ b/applications/plugins/avr_isp_programmer/avr_isp_app.c @@ -72,25 +72,25 @@ AvrIspApp* avr_isp_app_alloc() { app->dialogs = furi_record_open(RECORD_DIALOGS); // Programmer view - app->avr_asp_programmer_view = avr_asp_programmer_view_alloc(); + app->avr_isp_programmer_view = avr_isp_programmer_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, AvrIspViewProgrammer, - avr_asp_programmer_view_get_view(app->avr_asp_programmer_view)); + avr_isp_programmer_view_get_view(app->avr_isp_programmer_view)); // Reader view - app->avr_asp_reader_view = avr_asp_reader_view_alloc(); + app->avr_isp_reader_view = avr_isp_reader_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, AvrIspViewReader, - avr_asp_reader_view_get_view(app->avr_asp_reader_view)); + avr_isp_reader_view_get_view(app->avr_isp_reader_view)); // Reader view - app->avr_asp_writer_view = avr_asp_writer_view_alloc(); + app->avr_isp_writer_view = avr_isp_writer_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, AvrIspViewWriter, - avr_asp_writer_view_get_view(app->avr_asp_writer_view)); + avr_isp_writer_view_get_view(app->avr_isp_writer_view)); scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); @@ -121,15 +121,15 @@ void avr_isp_app_free(AvrIspApp* app) { // Programmer view view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer); - avr_asp_programmer_view_free(app->avr_asp_programmer_view); + avr_isp_programmer_view_free(app->avr_isp_programmer_view); // Reader view view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader); - avr_asp_reader_view_free(app->avr_asp_reader_view); + avr_isp_reader_view_free(app->avr_isp_reader_view); // Reader view view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWriter); - avr_asp_writer_view_free(app->avr_asp_writer_view); + avr_isp_writer_view_free(app->avr_isp_writer_view); // View dispatcher view_dispatcher_free(app->view_dispatcher); diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c index b196624dc39..7c92a03d9e8 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.c @@ -25,4 +25,7 @@ bool avr_isp_load_from_file(AvrIspApp* app) { furi_string_free(file_path); return res; -} \ No newline at end of file +} + + + diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h index 6f82b75518f..63a02bcc046 100644 --- a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/plugins/avr_isp_programmer/avr_isp_app_i.h @@ -21,10 +21,7 @@ #define AVR_ISP_MAX_LEN_NAME 64 - -typedef struct AvrIspApp AvrIspApp; - -struct AvrIspApp { +typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; SceneManager* scene_manager; @@ -37,10 +34,9 @@ struct AvrIspApp { FuriString* file_path; //FuriString* file_name; char file_name_tmp[AVR_ISP_MAX_LEN_NAME]; - AvrIspProgrammerView* avr_asp_programmer_view; - AvrIspReaderView* avr_asp_reader_view; - AvrIspWriterView* avr_asp_writer_view; -}; - + AvrIspProgrammerView* avr_isp_programmer_view; + AvrIspReaderView* avr_isp_reader_view; + AvrIspWriterView* avr_isp_writer_view; +} AvrIspApp; bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c index 6234f7b177d..5766dc92037 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.c @@ -297,11 +297,13 @@ bool avr_isp_read_page( return res; } -void avr_isp_read_signature(AvrIsp* instance, uint8_t* data) { +AvrIspSignature avr_isp_read_signature(AvrIsp* instance) { furi_assert(instance); - data[0] = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR); - data[1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); - data[2] = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); + AvrIspSignature signature; + signature.vendor = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR); + signature.part_family = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); + signature.part_number = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); + return signature; } uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h index 391a682cd00..7041d6c469b 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp.h @@ -5,6 +5,14 @@ typedef struct AvrIsp AvrIsp; typedef void (*AvrIspCallback)(void* context); +struct AvrIspSignature { + uint8_t vendor; + uint8_t part_family; + uint8_t part_number; +}; + +typedef struct AvrIspSignature AvrIspSignature; + AvrIsp* avr_isp_alloc(void); void avr_isp_free(AvrIsp* instance); @@ -13,7 +21,7 @@ void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* co bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance); -void avr_isp_read_signature(AvrIsp* instance, uint8_t* data); +AvrIspSignature avr_isp_read_signature(AvrIsp* instance); void avr_isp_end_pmode(AvrIsp* instance); @@ -42,7 +50,7 @@ bool avr_isp_write_page( uint16_t page_size, uint8_t* data, uint32_t data_size); - + uint8_t avr_isp_read_lock_byte(AvrIsp* instance); bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c new file mode 100644 index 00000000000..9314f65037c --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c @@ -0,0 +1,596 @@ +#include "avr_isp_rw.h" +#include "avr_isp_types.h" +#include "avr_isp.h" +#include "../lib/driver/avr_isp_prog_cmd.h" +#include "../lib/driver/avr_isp_chip_arr.h" + +#include "flipper_i32hex_file.h" +#include + +#include + +#define TAG "AvrIspRW" + +struct AvrIspRW { + AvrIsp* avr_isp; + + uint32_t chip_arr_ind; + bool chip_detect; + uint8_t lfuse; + uint8_t hfuse; + uint8_t efuse; + uint8_t lock; + AvrIspSignature signature; + AvrIspRWCallback callback; + void* context; +}; + +bool avr_isp_rw_detect_chip(AvrIspRW* instance) { + furi_assert(instance); + FURI_LOG_D(TAG, "Detecting AVR chip"); + instance->chip_detect = false; + instance->chip_arr_ind = avr_isp_chip_arr_size + 1; + //uint8_t data[10]; + + do { + if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + break; + } + instance->signature = avr_isp_read_signature(instance->avr_isp); + + if(instance->signature.vendor != 0x1E) { + //No detect chip + } else { + for(uint32_t ind = 0; ind < avr_isp_chip_arr_size; ind++) { + if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; + if(avr_isp_chip_arr[ind].sigs[1] == instance->signature.part_family) { + if(avr_isp_chip_arr[ind].sigs[2] == instance->signature.part_number) { + FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); + FURI_LOG_D( + TAG, + "Signature = 0x%02X 0x%02X 0x%02X", + instance->signature.vendor, + instance->signature.part_family, + instance->signature.part_number); + + switch(avr_isp_chip_arr[ind].nfuses) { + case 1: + instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); + FURI_LOG_D(TAG, "Lfuse = %02X", instance->lfuse); + break; + case 2: + instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); + instance->hfuse = avr_isp_read_fuse_high(instance->avr_isp); + FURI_LOG_D( + TAG, "Lfuse = %02X Hfuse = %02X", instance->lfuse, instance->hfuse); + break; + case 3: + instance->lfuse = avr_isp_read_fuse_low(instance->avr_isp); + instance->hfuse = avr_isp_read_fuse_high(instance->avr_isp); + instance->efuse = avr_isp_read_fuse_extended(instance->avr_isp); + FURI_LOG_D( + TAG, + "Lfuse = %02X Hfuse = %02X Efuse = %02X", + instance->lfuse, + instance->hfuse, + instance->efuse); + break; + default: + break; + } + if(avr_isp_chip_arr[ind].nlocks == 1) { + instance->lock = avr_isp_read_lock_byte(instance->avr_isp); + FURI_LOG_D(TAG, "Lock = %02X", instance->lock); + } + instance->chip_detect = true; + instance->chip_arr_ind = ind; + break; + } + } + } + } + avr_isp_end_pmode(instance->avr_isp); + + } while(0); + if(instance->callback) { + if(instance->chip_arr_ind > avr_isp_chip_arr_size) { + //ToDo add output ID chip + instance->callback(instance->context, "No detect", instance->chip_detect); + + } else if(instance->chip_arr_ind < avr_isp_chip_arr_size) { + instance->callback( + instance->context, + avr_isp_chip_arr[instance->chip_arr_ind].name, + instance->chip_detect); + } else { + //ToDo add output ID chip + instance->callback(instance->context, "Unknown", instance->chip_detect); + } + } + + return instance->chip_detect; +} + +AvrIspRW* avr_isp_rw_alloc(void* context) { + furi_assert(context); + UNUSED(context); + AvrIspRW* instance = malloc(sizeof(AvrIspRW)); + instance->avr_isp = avr_isp_alloc(); + + instance->chip_detect = false; + instance->lfuse = 0; + instance->hfuse = 0; + instance->efuse = 0; + instance->lock = 0; + + return instance; +} + +void avr_isp_rw_free(AvrIspRW* instance) { + furi_assert(instance); + + avr_isp_free(instance->avr_isp); + + free(instance); +} + +void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context) { + furi_assert(instance); + furi_assert(context); + instance->callback = callback; + instance->context = context; +} + +void avr_isp_rw_get_dump_flash(AvrIspRW* instance, const char* file_path) { + furi_assert(instance); + furi_check(instance->avr_isp); + + FURI_LOG_D(TAG, "Dump FLASH"); + + FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_write( + file_path, avr_isp_chip_arr[instance->chip_arr_ind].flashoffset); + + uint8_t data[272] = {0}; + + for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; + i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { + avr_isp_read_page( + instance->avr_isp, + STK_SET_FLASH_TYPE, + i, + avr_isp_chip_arr[instance->chip_arr_ind].pagesize, + data, + sizeof(data)); + flipper_i32hex_file_bin_to_i32hex_set_data( + flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + } + flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + flipper_i32hex_file_close(flipper_hex_flash); +} + +void avr_isp_rw_get_dump_eeprom(AvrIspRW* instance, const char* file_path) { + furi_assert(instance); + furi_check(instance->avr_isp); + + FURI_LOG_D(TAG, "Dump EEPROM"); + + FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( + file_path, avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); + + int32_t size_data = 32; + uint8_t data[256] = {0}; + + if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) + size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + + for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; i += size_data) { + avr_isp_read_page( + instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); + flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); + } + flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); + flipper_i32hex_file_close(flipper_hex_eeprom); +} + +bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* file_name) { + furi_assert(instance); + furi_assert(file_path); + furi_assert(file_name); + + FURI_LOG_D(TAG, "Read dump chip"); + bool ret = false; + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + FuriString* file_path_name = furi_string_alloc(); + + if(!avr_isp_rw_detect_chip(instance)) { + FURI_LOG_E(TAG, "No detect AVR chip"); + } else { + do { + furi_string_printf( + file_path_name, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); + if(!flipper_format_file_open_always( + flipper_format, furi_string_get_cstr(file_path_name))) { + FURI_LOG_E(TAG, "flipper_format_file_open_always"); + break; + } + if(!flipper_format_write_header_cstr( + flipper_format, AVR_ISP_APP_FILE_TYPE, AVR_ISP_APP_FILE_VERSION)) { + FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); + break; + } + if(!flipper_format_write_string_cstr( + flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { + FURI_LOG_E(TAG, "Chip name"); + break; + } + if(!flipper_format_write_hex( + flipper_format, + "Signature", + (uint8_t*)&instance->signature, + sizeof(AvrIspSignature))) { + FURI_LOG_E(TAG, "Unable to add Signature"); + break; + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + if(!flipper_format_write_hex(flipper_format, "Lfuse", &instance->lfuse, 1)) { + FURI_LOG_E(TAG, "Unable to add Lfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + if(!flipper_format_write_hex(flipper_format, "Hfuse", &instance->hfuse, 1)) { + FURI_LOG_E(TAG, "Unable to add Hfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + if(!flipper_format_write_hex(flipper_format, "Efuse", &instance->efuse, 1)) { + FURI_LOG_E(TAG, "Unable to add Efuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + if(!flipper_format_write_hex(flipper_format, "Lock", &instance->lock, 1)) { + FURI_LOG_E(TAG, "Unable to add Lock"); + break; + } + } + furi_string_printf(file_path_name, "%s_flash.hex", file_name); + if(!flipper_format_write_string_cstr( + flipper_format, "Dump_flash", furi_string_get_cstr(file_path_name))) { + FURI_LOG_E(TAG, "Unable to add Dump_flash"); + break; + } + + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + furi_string_printf(file_path_name, "%s_eeprom.hex", file_name); + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + if(!flipper_format_write_string_cstr( + flipper_format, "Dump_eeprom", furi_string_get_cstr(file_path_name))) { + FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); + break; + } + } + } + ret = true; + } while(false); + } + + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + + if(ret) { + if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + //Dump flash + furi_string_printf(file_path_name, "%s/%s_flash.hex", file_path, file_name); + avr_isp_rw_get_dump_flash(instance, furi_string_get_cstr(file_path_name)); + //Dump eeprom + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + furi_string_printf(file_path_name, "%s/%s_eeprom.hex", file_path, file_name); + avr_isp_rw_get_dump_eeprom(instance, furi_string_get_cstr(file_path_name)); + } + + avr_isp_end_pmode(instance->avr_isp); + } + } + + furi_string_free(file_path_name); + + return true; +} + +// bool avr_isp_rw_rx1(AvrIspRW* instance) { +// furi_assert(instance); +// uint8_t data[256]; + +// Storage* storage = furi_record_open(RECORD_STORAGE); +// FlipperFormat* flipper_format = flipper_format_file_alloc(storage); +// FURI_LOG_D(TAG, "Read chip"); +// do { +// if(!instance->chip_detect) { +// FURI_LOG_E(TAG, "No detect AVR chip"); +// break; +// } + +// // if(!storage_simply_mkdir(storage, "/any/avr_isp/")) { +// // FURI_LOG_E(TAG, "storage_simply_mkdir"); +// // break; +// // } + +// // if(!storage_simply_remove(storage, "dump.avr")) { +// // break; +// // } + +// if(!flipper_format_file_open_always(flipper_format, "/any/avr_isp/dump.avr")) { +// FURI_LOG_E(TAG, "flipper_format_file_open_always"); +// break; +// } +// if(!flipper_format_write_header_cstr(flipper_format, "Flipper dump AVR", 1)) { +// FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); +// break; +// } +// if(!flipper_format_write_comment_cstr(flipper_format, "This is comment")) { +// FURI_LOG_E(TAG, "flipper_format_write_comment_cstr"); +// break; +// } +// //if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break; + +// if(!flipper_format_write_string_cstr( +// flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { +// FURI_LOG_E(TAG, "Chip name"); +// break; +// } + +// if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { +// FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); +// break; +// } + +// // avr_isp_read_signature(instance->avr_isp, data); + +// if(!flipper_format_write_hex(flipper_format, "ID", data, 3)) { +// FURI_LOG_E(TAG, "Unable to add ID"); +// break; +// } +// FURI_LOG_D(TAG, "ID = 0x%02X 0x%02X 0x%02X", data[0], data[1], data[2]); + +// data[0] = avr_isp_read_fuse_high(instance->avr_isp); +// data[1] = avr_isp_read_fuse_low(instance->avr_isp); +// data[2] = avr_isp_read_fuse_extended(instance->avr_isp); +// data[3] = avr_isp_read_lock_byte(instance->avr_isp); + +// if(!flipper_format_write_hex(flipper_format, "Hfuse", data, 1)) { +// FURI_LOG_E(TAG, "Unable to add Hfuse"); +// break; +// } + +// if(!flipper_format_write_hex(flipper_format, "Lfuse", data + 1, 1)) { +// FURI_LOG_E(TAG, "Unable to add Lfuse"); +// break; +// } + +// if(!flipper_format_write_hex(flipper_format, "Efuse", data + 2, 1)) { +// FURI_LOG_E(TAG, "Unable to add Efuse"); +// break; +// } + +// if(!flipper_format_write_hex(flipper_format, "Lock", data + 3, 1)) { +// FURI_LOG_E(TAG, "Unable to add Lock"); +// break; +// } + +// FURI_LOG_D( +// TAG, +// "hfuse = 0x%02X lfuse = 0x%02X efuse = 0x%02X lock = 0x%02X", +// data[0], +// data[1], +// data[2], +// data[3]); + +// if(!flipper_format_write_string_cstr(flipper_format, "Dump_flash", "flash.hex")) { +// FURI_LOG_E(TAG, "Unable to add Dump_flash"); +// break; +// } +// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { +// if(!flipper_format_write_string_cstr(flipper_format, "Dump_eeprom", "eeprom.hex")) { +// FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); +// break; +// } +// } + +// FURI_LOG_D(TAG, "EEPROM"); + +// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { +// FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( +// "/any/avr_isp/eeprom.hex", avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); +// int32_t size_data = 32; +// if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) +// size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + +// for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; +// i += size_data) { +// avr_isp_read_page( +// instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); +// flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); +// printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); +// } +// flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); +// printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); +// flipper_i32hex_file_close(flipper_hex_eeprom); +// } + +// // FURI_LOG_D(TAG, "FLASH"); +// // FlipperI32HexFile* flipper_hex_flash = +// // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", avr_isp_chip_arr[instance->chip_arr_ind].flashoffset;); +// // for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; +// // i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { +// // avr_isp_read_page( +// // instance->avr_isp, +// // STK_SET_FLASH_TYPE, +// // i, +// // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, +// // data, +// // sizeof(data)); +// // flipper_i32hex_file_bin_to_i32hex_add_data( +// // flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); +// // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); +// // } +// // flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_flash); +// // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); +// // flipper_i32hex_file_close(flipper_hex_flash); + +// avr_isp_end_pmode(instance->avr_isp); + +// // // //################################################################ +// // FURI_LOG_D(TAG, "FUSE Write"); +// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { +// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); +// // break; +// // } +// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_low(instance->avr_isp, 0xFF)); +// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_extended(instance->avr_isp, 0xFD)); +// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_high(instance->avr_isp, 0xDA)); +// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_lock_byte(instance->avr_isp, 0xFF)); + +// // avr_isp_end_pmode(instance->avr_isp); +// // //################################################################## + +// // //################################################################ +// // FURI_LOG_D(TAG, "ERASE CHIP"); +// // avr_isp_erase_chip(instance->avr_isp); +// // //################################################################## + +// // //########################################################## +// // FURI_LOG_D(TAG, "FLASH WRITE"); + +// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { +// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); +// // break; +// // } +// // avr_isp_read_signature(instance->avr_isp, data); + +// // FlipperI32HexFile* flipper_hex_flash = +// // flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); + +// // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; +// // FlipperI32HexFileRet flipper_hex_ret = +// // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); +// // FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); +// // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || +// // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { +// // // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); +// // // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { +// // // printf("%02X ", data[i]); +// // // } +// // // printf("\r\n"); + +// // switch(flipper_hex_ret.status) { +// // case FlipperI32HexFileStatusData: +// // if(!avr_isp_write_page( +// // instance->avr_isp, +// // STK_SET_FLASH_TYPE, +// // avr_isp_chip_arr[instance->chip_arr_ind].flashsize, +// // addr, +// // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, +// // data, +// // flipper_hex_ret.data_size)) { +// // break; +// // } +// // addr += flipper_hex_ret.data_size/2; +// // break; + +// // case FlipperI32HexFileStatusUdateAddr: +// // addr = data[0] << 24 | data[1] << 16; +// // break; + +// // default: +// // furi_crash(TAG " Incorrect status."); +// // break; +// // } + +// // flipper_hex_ret = +// // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); +// // } + +// // flipper_i32hex_file_close(flipper_hex_flash); +// // avr_isp_end_pmode(instance->avr_isp); +// //########################################################## + +// // FURI_LOG_D(TAG, "CHECK HEX"); +// // FlipperI32HexFile* flipper_hex_eeprom_read = +// // flipper_i32hex_file_open_read("/any/avr_isp/a.hex"); +// // if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { +// // FURI_LOG_D(TAG, "Check OK"); +// // } else { +// // FURI_LOG_E(TAG, "Check ERROR"); +// // } +// // // flipper_i32hex_file_close(flipper_hex_eeprom_read); + +// // //########################################################## +// // FURI_LOG_D(TAG, "EEPROM WRITE"); + +// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { +// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); +// // break; +// // } +// // avr_isp_read_signature(instance->avr_isp, data); +// // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; +// // FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( +// // flipper_hex_eeprom_read, data, sizeof(data)); + +// // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || +// // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { +// // FURI_LOG_D(TAG, "EEPROM WRITE Page"); +// // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { +// // printf("%02X ", data[i]); +// // } +// // printf("\r\n"); + +// // switch(flipper_hex_ret.status) { +// // case FlipperI32HexFileStatusData: +// // if(!avr_isp_write_page( +// // instance->avr_isp, +// // STK_SET_EEPROM_TYPE, +// // avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, +// // addr, +// // avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, +// // data, +// // flipper_hex_ret.data_size)) { +// // break; +// // } +// // addr += flipper_hex_ret.data_size; +// // break; + +// // case FlipperI32HexFileStatusUdateAddr: +// // addr = data[0] << 24 | data[1] << 16; +// // break; + +// // default: +// // furi_crash(TAG " Incorrect status."); +// // break; +// // } + +// // flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( +// // flipper_hex_eeprom_read, data, sizeof(data)); +// // } + +// // flipper_i32hex_file_close(flipper_hex_eeprom_read); +// // avr_isp_end_pmode(instance->avr_isp); +// // //########################################################## + +// // //################################################################ +// // FURI_LOG_D(TAG, "ERASE CHIP"); +// // avr_isp_erase_chip(instance->avr_isp); +// // //################################################################## +// FURI_LOG_D(TAG, "___END___"); +// } while(0); +// flipper_format_free(flipper_format); +// furi_record_close(RECORD_STORAGE); +// return true; +// } \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h new file mode 100644 index 00000000000..b1f1c1f109e --- /dev/null +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +typedef struct AvrIspRW AvrIspRW; + +typedef void (*AvrIspRWCallback)(void* context, const char* name, bool detect_chip); + +/** Allocate AvrIspRW + * + * @param context AvrIsp* context + * @return AvrIspRW* + */ +AvrIspRW* avr_isp_rw_alloc(void* context); + +/** Free AvrIspRW + * + * @param instance AvrIspRW instance + */ +void avr_isp_rw_free(AvrIspRW* instance); + +/** Callback AvrIspRW + * + * @param instance AvrIspRW instance + * @param callback AvrIspRWOverrunCallback callback + * @param context + */ +void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context); + +/** Detect chip + * + * @param instance AvrIspRW instance + * @return bool + */ +bool avr_isp_rw_detect_chip(AvrIspRW* instance); + +bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* file_name); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c deleted file mode 100644 index 00d32543488..00000000000 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.c +++ /dev/null @@ -1,433 +0,0 @@ -#include "avr_isp_rw_worker.h" -#include "avr_isp_rw_worker_cmd.h" -#include "avr_isp.h" -#include "../lib/driver/avr_isp_prog_cmd.h" -#include "../lib/driver/avr_isp_chip_arr.h" - -#include "flipper_i32hex_file.h" -#include - -#include - -#define TAG "AvrIspRWWorker" - -struct AvrIspRWWorker { - FuriThread* thread; - AvrIsp* avr_isp; - - uint32_t chip_arr_ind; - bool chip_detect; - volatile bool worker_running; - AvrIspRWWorkerCallback callback; - void* context; -}; - -void avr_isp_rw_worker_detect_chip(AvrIspRWWorker* instance) { - furi_assert(instance); - FURI_LOG_D(TAG, "Detecting AVR chip"); - uint8_t data[10]; - size_t ind = avr_isp_chip_arr_size + 1; - do { - if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - break; - } - avr_isp_read_signature(instance->avr_isp, data); - avr_isp_end_pmode(instance->avr_isp); - - if(data[0] != 0x1E) { - ind = avr_isp_chip_arr_size + 1; //No detect chip - } else { - for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { - if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; - if(avr_isp_chip_arr[ind].sigs[1] == data[1]) { - if(avr_isp_chip_arr[ind].sigs[2] == data[2]) { - FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); - break; - } - } - } - } - - } while(0); - - if(instance->callback) { - if(ind > avr_isp_chip_arr_size) { - //ToDo add output ID chip - instance->callback(instance->context, "No detect"); - instance->chip_detect = false; - instance->chip_arr_ind = ind; - } else if(ind < avr_isp_chip_arr_size) { - instance->callback(instance->context, avr_isp_chip_arr[ind].name); - instance->chip_detect = true; - instance->chip_arr_ind = ind; - } else { - //ToDo add output ID chip - instance->callback(instance->context, "Unknown"); - instance->chip_detect = false; - instance->chip_arr_ind = ind; - } - } - // avr_isp_rw_worker_rx(instance); -} - -/** Worker thread - * - * @param context - * @return exit code - */ -static int32_t avr_isp_rw_worker_thread(void* context) { - AvrIspRWWorker* instance = context; - - FURI_LOG_D(TAG, "Start"); - while(instance->worker_running) { - furi_delay_ms(100); - } - FURI_LOG_D(TAG, "Stop"); - return 0; -} - -AvrIspRWWorker* avr_isp_rw_worker_alloc(void* context) { - furi_assert(context); - UNUSED(context); - AvrIspRWWorker* instance = malloc(sizeof(AvrIspRWWorker)); - instance->avr_isp = avr_isp_alloc(); - - instance->chip_detect = false; - - instance->thread = - furi_thread_alloc_ex("AvrIspRWWorker", 2048, avr_isp_rw_worker_thread, instance); - return instance; -} - -void avr_isp_rw_worker_free(AvrIspRWWorker* instance) { - furi_assert(instance); - - avr_isp_free(instance->avr_isp); - furi_thread_free(instance->thread); - free(instance); -} - -void avr_isp_rw_worker_set_callback( - AvrIspRWWorker* instance, - AvrIspRWWorkerCallback callback, - void* context) { - furi_assert(instance); - furi_assert(context); - instance->callback = callback; - instance->context = context; -} - -void avr_isp_rw_worker_start(AvrIspRWWorker* instance) { - furi_assert(instance); - furi_assert(!instance->worker_running); - - instance->worker_running = true; - - furi_thread_start(instance->thread); -} - -void avr_isp_rw_worker_stop(AvrIspRWWorker* instance) { - furi_assert(instance); - furi_assert(instance->worker_running); - - instance->worker_running = false; - - furi_thread_join(instance->thread); -} - -bool avr_isp_rw_worker_is_running(AvrIspRWWorker* instance) { - furi_assert(instance); - return instance->worker_running; -} - -bool avr_isp_rw_worker_rx(AvrIspRWWorker* instance) { - furi_assert(instance); - uint8_t data[256]; - - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* flipper_format = flipper_format_file_alloc(storage); - FURI_LOG_D(TAG, "Read chip"); - do { - if(!instance->chip_detect) { - FURI_LOG_E(TAG, "No detect AVR chip"); - break; - } - - // if(!storage_simply_mkdir(storage, "/any/avr_isp/")) { - // FURI_LOG_E(TAG, "storage_simply_mkdir"); - // break; - // } - - // if(!storage_simply_remove(storage, "dump.avr")) { - // break; - // } - - if(!flipper_format_file_open_always(flipper_format, "/any/avr_isp/dump.avr")) { - FURI_LOG_E(TAG, "flipper_format_file_open_always"); - break; - } - if(!flipper_format_write_header_cstr(flipper_format, "Flipper dump AVR", 1)) { - FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); - break; - } - if(!flipper_format_write_comment_cstr(flipper_format, "This is comment")) { - FURI_LOG_E(TAG, "flipper_format_write_comment_cstr"); - break; - } - //if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break; - - if(!flipper_format_write_string_cstr( - flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { - FURI_LOG_E(TAG, "Chip name"); - break; - } - - if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - break; - } - - avr_isp_read_signature(instance->avr_isp, data); - - if(!flipper_format_write_hex(flipper_format, "ID", data, 3)) { - FURI_LOG_E(TAG, "Unable to add ID"); - break; - } - FURI_LOG_D(TAG, "ID = 0x%02X 0x%02X 0x%02X", data[0], data[1], data[2]); - - data[0] = avr_isp_read_fuse_high(instance->avr_isp); - data[1] = avr_isp_read_fuse_low(instance->avr_isp); - data[2] = avr_isp_read_fuse_extended(instance->avr_isp); - data[3] = avr_isp_read_lock_byte(instance->avr_isp); - - if(!flipper_format_write_hex(flipper_format, "Hfuse", data, 1)) { - FURI_LOG_E(TAG, "Unable to add Hfuse"); - break; - } - - if(!flipper_format_write_hex(flipper_format, "Lfuse", data + 1, 1)) { - FURI_LOG_E(TAG, "Unable to add Lfuse"); - break; - } - - if(!flipper_format_write_hex(flipper_format, "Efuse", data + 2, 1)) { - FURI_LOG_E(TAG, "Unable to add Efuse"); - break; - } - - if(!flipper_format_write_hex(flipper_format, "Lock", data + 3, 1)) { - FURI_LOG_E(TAG, "Unable to add Lock"); - break; - } - - FURI_LOG_D( - TAG, - "hfuse = 0x%02X lfuse = 0x%02X efuse = 0x%02X lock = 0x%02X", - data[0], - data[1], - data[2], - data[3]); - - if(!flipper_format_write_string_cstr(flipper_format, "Dump_flash", "flash.hex")) { - FURI_LOG_E(TAG, "Unable to add Dump_flash"); - break; - } - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - if(!flipper_format_write_string_cstr(flipper_format, "Dump_eeprom", "eeprom.hex")) { - FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); - break; - } - } - - FURI_LOG_D(TAG, "EEPROM"); - - if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( - "/any/avr_isp/eeprom.hex", avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); - int32_t size_data = 32; - if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) - size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - - for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - i += size_data) { - avr_isp_read_page( - instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); - flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); - printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); - } - flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); - printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); - flipper_i32hex_file_close(flipper_hex_eeprom); - } - - // FURI_LOG_D(TAG, "FLASH"); - // FlipperI32HexFile* flipper_hex_flash = - // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", avr_isp_chip_arr[instance->chip_arr_ind].flashoffset;); - // for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; - // i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { - // avr_isp_read_page( - // instance->avr_isp, - // STK_SET_FLASH_TYPE, - // i, - // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, - // data, - // sizeof(data)); - // flipper_i32hex_file_bin_to_i32hex_add_data( - // flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); - // } - // flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_flash); - // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); - // flipper_i32hex_file_close(flipper_hex_flash); - - avr_isp_end_pmode(instance->avr_isp); - - // // //################################################################ - // FURI_LOG_D(TAG, "FUSE Write"); - // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - // break; - // } - // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_low(instance->avr_isp, 0xFF)); - // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_extended(instance->avr_isp, 0xFD)); - // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_high(instance->avr_isp, 0xDA)); - // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_lock_byte(instance->avr_isp, 0xFF)); - - - // avr_isp_end_pmode(instance->avr_isp); - // //################################################################## - - // //################################################################ - // FURI_LOG_D(TAG, "ERASE CHIP"); - // avr_isp_erase_chip(instance->avr_isp); - // //################################################################## - - // //########################################################## - // FURI_LOG_D(TAG, "FLASH WRITE"); - - // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - // break; - // } - // avr_isp_read_signature(instance->avr_isp, data); - - // FlipperI32HexFile* flipper_hex_flash = - // flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); - - // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; - // FlipperI32HexFileRet flipper_hex_ret = - // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); - // FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); - // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - // // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); - // // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // // printf("%02X ", data[i]); - // // } - // // printf("\r\n"); - - // switch(flipper_hex_ret.status) { - // case FlipperI32HexFileStatusData: - // if(!avr_isp_write_page( - // instance->avr_isp, - // STK_SET_FLASH_TYPE, - // avr_isp_chip_arr[instance->chip_arr_ind].flashsize, - // addr, - // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, - // data, - // flipper_hex_ret.data_size)) { - // break; - // } - // addr += flipper_hex_ret.data_size/2; - // break; - - // case FlipperI32HexFileStatusUdateAddr: - // addr = data[0] << 24 | data[1] << 16; - // break; - - // default: - // furi_crash(TAG " Incorrect status."); - // break; - // } - - // flipper_hex_ret = - // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); - // } - - // flipper_i32hex_file_close(flipper_hex_flash); - // avr_isp_end_pmode(instance->avr_isp); - //########################################################## - - // FURI_LOG_D(TAG, "CHECK HEX"); - // FlipperI32HexFile* flipper_hex_eeprom_read = - // flipper_i32hex_file_open_read("/any/avr_isp/a.hex"); - // if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { - // FURI_LOG_D(TAG, "Check OK"); - // } else { - // FURI_LOG_E(TAG, "Check ERROR"); - // } - // // flipper_i32hex_file_close(flipper_hex_eeprom_read); - - // //########################################################## - // FURI_LOG_D(TAG, "EEPROM WRITE"); - - // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); - // break; - // } - // avr_isp_read_signature(instance->avr_isp, data); - // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; - // FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - // flipper_hex_eeprom_read, data, sizeof(data)); - - // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - // FURI_LOG_D(TAG, "EEPROM WRITE Page"); - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data[i]); - // } - // printf("\r\n"); - - // switch(flipper_hex_ret.status) { - // case FlipperI32HexFileStatusData: - // if(!avr_isp_write_page( - // instance->avr_isp, - // STK_SET_EEPROM_TYPE, - // avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, - // addr, - // avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, - // data, - // flipper_hex_ret.data_size)) { - // break; - // } - // addr += flipper_hex_ret.data_size; - // break; - - // case FlipperI32HexFileStatusUdateAddr: - // addr = data[0] << 24 | data[1] << 16; - // break; - - // default: - // furi_crash(TAG " Incorrect status."); - // break; - // } - - // flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - // flipper_hex_eeprom_read, data, sizeof(data)); - // } - - // flipper_i32hex_file_close(flipper_hex_eeprom_read); - // avr_isp_end_pmode(instance->avr_isp); - // //########################################################## - - // //################################################################ - // FURI_LOG_D(TAG, "ERASE CHIP"); - // avr_isp_erase_chip(instance->avr_isp); - // //################################################################## - FURI_LOG_D(TAG, "___END___"); - } while(0); - flipper_format_free(flipper_format); - furi_record_close(RECORD_STORAGE); - return true; -} \ No newline at end of file diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h deleted file mode 100644 index 5af29e35f03..00000000000 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include - -typedef struct AvrIspRWWorker AvrIspRWWorker; - -typedef void (*AvrIspRWWorkerCallback)(void* context, const char* name); - -/** Allocate AvrIspRWWorker - * - * @param context AvrIsp* context - * @return AvrIspRWWorker* - */ -AvrIspRWWorker* avr_isp_rw_worker_alloc(void* context); - -/** Free AvrIspRWWorker - * - * @param instance AvrIspRWWorker instance - */ -void avr_isp_rw_worker_free(AvrIspRWWorker* instance); - -/** Callback AvrIspRWWorker - * - * @param instance AvrIspRWWorker instance - * @param callback AvrIspRWWorkerOverrunCallback callback - * @param context - */ -void avr_isp_rw_worker_set_callback( - AvrIspRWWorker* instance, - AvrIspRWWorkerCallback callback, - void* context); - -/** Start AvrIspRWWorker - * - * @param instance AvrIspRWWorker instance - */ -void avr_isp_rw_worker_start(AvrIspRWWorker* instance); - -/** Stop AvrIspRWWorker - * - * @param instance AvrIspRWWorker instance - */ -void avr_isp_rw_worker_stop(AvrIspRWWorker* instance); - -/** Check if worker is running - * @param instance AvrIspRWWorker instance - * @return bool - true if running - */ -bool avr_isp_rw_worker_is_running(AvrIspRWWorker* instance); - -/** Detect chip - * - * @param instance AvrIspRWWorker instance - */ -void avr_isp_rw_worker_detect_chip(AvrIspRWWorker* instance); - - -bool avr_isp_rw_worker_rx (AvrIspRWWorker* instance); diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h deleted file mode 100644 index 31ba24a0539..00000000000 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw_worker_cmd.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "../lib/driver/avr_isp_prog_cmd.h" - -#define AVR_ISP_RW_GET_SYNC STK_GET_SYNC,CRC_EOP -#define AVR_ISP_RW_ENTER_PROGMODE STK_ENTER_PROGMODE,CRC_EOP -#define AVR_ISP_RW_READ_SIGN STK_READ_SIGN,CRC_EOP -#define AVR_ISP_RW_LEAVE_PROGMODE STK_LEAVE_PROGMODE,CRC_EOP diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h index 6e5f13b89b1..c540d05db32 100644 --- a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h @@ -7,6 +7,8 @@ #define AVR_ISP_DEVELOPED "SkorP" #define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" +#define AVR_ISP_APP_FILE_VERSION 1 +#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR" #define AVR_ISP_APP_EXTENSION ".avr" typedef enum { diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c index 6f98cbf733b..8ead2fbf3b0 100644 --- a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ b/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -37,7 +37,7 @@ FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t sta if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { instance->file_open = FlipperI32HexFileStatusOpenFileWrite; } else { - FURI_LOG_E(TAG, "Failed to open file"); + FURI_LOG_E(TAG, "Failed to open file %s", name); instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; } instance->str_data = furi_string_alloc(instance->storage); @@ -57,7 +57,7 @@ FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { instance->file_open = FlipperI32HexFileStatusOpenFileRead; } else { - FURI_LOG_E(TAG, "Failed to open file"); + FURI_LOG_E(TAG, "Failed to open file %s", name); instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; } instance->str_data = furi_string_alloc(instance->storage); @@ -223,7 +223,7 @@ static FlipperI32HexFileRet flipper_i32hex_file_parse( if(flipper_i32hex_file_check_data(data, ret.data_size)) { ret.data_size -= 5; memcpy(data, data + 4, ret.data_size); - ret.status =FlipperI32HexFileStatusData; + ret.status = FlipperI32HexFileStatusData; } else { ret.status = FlipperI32HexFileStatusErrorCrc; ret.data_size = 0; diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c index 5ba1e7eeeda..2264a787ea4 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c @@ -33,15 +33,15 @@ void avr_isp_scene_input_name_on_enter(void* context) { bool dev_name_empty = false; FuriString* file_name; - FuriString* dir_name; + //FuriString* dir_name; file_name = furi_string_alloc(); - dir_name = furi_string_alloc(); + //dir_name = furi_string_alloc(); //if(!app_path_is_file(app->file_path)) { char file_name_buf[AVR_ISP_MAX_LEN_NAME] = {0}; set_random_name(file_name_buf, AVR_ISP_MAX_LEN_NAME); furi_string_set(file_name, file_name_buf); - //furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); + furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); //highlighting the entire filename by default dev_name_empty = true; //} @@ -75,7 +75,7 @@ void avr_isp_scene_input_name_on_enter(void* context) { text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); furi_string_free(file_name); - furi_string_free(dir_name); + //furi_string_free(dir_name); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewTextInput); } diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c index 10231c56f0b..3e6b530f78c 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c @@ -10,8 +10,8 @@ void avr_isp_scene_programmer_callback(AvrIspCustomEvent event, void* context) { void avr_isp_scene_programmer_on_enter(void* context) { AvrIspApp* app = context; - avr_asp_programmer_view_set_callback( - app->avr_asp_programmer_view, avr_isp_scene_programmer_callback, app); + avr_isp_programmer_view_set_callback( + app->avr_isp_programmer_view, avr_isp_scene_programmer_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewProgrammer); } diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c index 50b416cf191..9d9eb35721f 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -1,22 +1,24 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_writer.h" +#include "../views/avr_isp_view_reader.h" -void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { +void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } -void avr_isp_scene_writer_on_enter(void* context) { +void avr_isp_scene_reader_on_enter(void* context) { AvrIspApp* app = context; - avr_asp_writer_view_set_callback( - app->avr_asp_writer_view, avr_isp_scene_writer_callback, app); + avr_isp_reader_set_file_path( + app->avr_isp_reader_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); + avr_isp_reader_view_set_callback( + app->avr_isp_reader_view, avr_isp_scene_reader_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter); + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); } -bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { +bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; UNUSED(app); bool consumed = false; @@ -33,6 +35,6 @@ bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { return consumed; } -void avr_isp_scene_writer_on_exit(void* context) { +void avr_isp_scene_reader_on_exit(void* context) { UNUSED(context); } diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c index 0184819edfe..59dd7ba3fab 100644 --- a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ b/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -1,22 +1,20 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_reader.h" +#include "../views/avr_isp_view_writer.h" -void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { +void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } -void avr_isp_scene_reader_on_enter(void* context) { +void avr_isp_scene_writer_on_enter(void* context) { AvrIspApp* app = context; - avr_asp_reader_view_set_callback( - app->avr_asp_reader_view, avr_isp_scene_reader_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); + avr_isp_writer_view_set_callback(app->avr_isp_writer_view, avr_isp_scene_writer_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter); } -bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { +bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; UNUSED(app); bool consumed = false; @@ -33,6 +31,6 @@ bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { return consumed; } -void avr_isp_scene_reader_on_exit(void* context) { +void avr_isp_scene_writer_on_exit(void* context) { UNUSED(context); } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c index 30513b6c7f7..b8ff0ca4548 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -22,7 +22,7 @@ typedef struct { bool detect_chip; } AvrIspProgrammerViewModel; -void avr_asp_programmer_view_set_callback( +void avr_isp_programmer_view_set_callback( AvrIspProgrammerView* instance, AvrIspProgrammerViewCallback callback, void* context) { @@ -32,7 +32,7 @@ void avr_asp_programmer_view_set_callback( instance->context = context; } -void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { +void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { UNUSED(model); canvas_clear(canvas); // canvas_set_color(canvas, ColorBlack); @@ -53,7 +53,7 @@ void avr_asp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod } } -bool avr_asp_programmer_view_input(InputEvent* event, void* context) { +bool avr_isp_programmer_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspProgrammerView* instance = context; UNUSED(instance); @@ -64,7 +64,7 @@ bool avr_asp_programmer_view_input(InputEvent* event, void* context) { return true; } -static void avr_asp_programmer_detect_chip_callback(void* context, const char* name) { +static void avr_isp_programmer_detect_chip_callback(void* context, const char* name) { furi_assert(context); AvrIspProgrammerView* instance = context; with_view_model( @@ -77,7 +77,7 @@ static void avr_asp_programmer_detect_chip_callback(void* context, const char* n }, true); } -void avr_asp_programmer_view_enter(void* context) { +void avr_isp_programmer_view_enter(void* context) { furi_assert(context); AvrIspProgrammerView* instance = context; @@ -94,14 +94,14 @@ void avr_asp_programmer_view_enter(void* context) { instance->worker = avr_isp_worker_alloc(instance->context); avr_isp_worker_set_callback( - instance->worker, avr_asp_programmer_detect_chip_callback, instance); + instance->worker, avr_isp_programmer_detect_chip_callback, instance); avr_isp_worker_detect_chip(instance->worker); avr_isp_worker_start(instance->worker); } -void avr_asp_programmer_view_exit(void* context) { +void avr_isp_programmer_view_exit(void* context) { furi_assert(context); AvrIspProgrammerView* instance = context; //Stop worker @@ -117,7 +117,7 @@ void avr_asp_programmer_view_exit(void* context) { false); } -AvrIspProgrammerView* avr_asp_programmer_view_alloc() { +AvrIspProgrammerView* avr_isp_programmer_view_alloc() { AvrIspProgrammerView* instance = malloc(sizeof(AvrIspProgrammerView)); // View allocation and configuration @@ -125,10 +125,10 @@ AvrIspProgrammerView* avr_asp_programmer_view_alloc() { view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspProgrammerViewModel)); view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_programmer_view_draw); - view_set_input_callback(instance->view, avr_asp_programmer_view_input); - view_set_enter_callback(instance->view, avr_asp_programmer_view_enter); - view_set_exit_callback(instance->view, avr_asp_programmer_view_exit); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_programmer_view_draw); + view_set_input_callback(instance->view, avr_isp_programmer_view_input); + view_set_enter_callback(instance->view, avr_isp_programmer_view_enter); + view_set_exit_callback(instance->view, avr_isp_programmer_view_exit); with_view_model( instance->view, @@ -142,7 +142,7 @@ AvrIspProgrammerView* avr_asp_programmer_view_alloc() { return instance; } -void avr_asp_programmer_view_free(AvrIspProgrammerView* instance) { +void avr_isp_programmer_view_free(AvrIspProgrammerView* instance) { furi_assert(instance); with_view_model( @@ -154,7 +154,7 @@ void avr_asp_programmer_view_free(AvrIspProgrammerView* instance) { free(instance); } -View* avr_asp_programmer_view_get_view(AvrIspProgrammerView* instance) { +View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance) { furi_assert(instance); return instance->view; } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h index 0cbdc793172..b467f0a2300 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h @@ -8,15 +8,15 @@ typedef struct AvrIspProgrammerView AvrIspProgrammerView; typedef void (*AvrIspProgrammerViewCallback)(AvrIspCustomEvent event, void* context); -void avr_asp_programmer_view_set_callback( +void avr_isp_programmer_view_set_callback( AvrIspProgrammerView* instance, AvrIspProgrammerViewCallback callback, void* context); -AvrIspProgrammerView* avr_asp_programmer_view_alloc(); +AvrIspProgrammerView* avr_isp_programmer_view_alloc(); -void avr_asp_programmer_view_free(AvrIspProgrammerView* instance); +void avr_isp_programmer_view_free(AvrIspProgrammerView* instance); -View* avr_asp_programmer_view_get_view(AvrIspProgrammerView* instance); +View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance); -void avr_asp_programmer_view_exit(void* context); +void avr_isp_programmer_view_exit(void* context); diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c index 7ed36030a3b..23eddc2e32f 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c @@ -3,7 +3,7 @@ #include #include -#include "../helpers/avr_isp_rw_worker.h" +#include "../helpers/avr_isp_rw.h" //#include //#include @@ -11,7 +11,9 @@ struct AvrIspReaderView { View* view; - AvrIspRWWorker* worker; + AvrIspRW* avr_isp_rw; + const char* file_path; + const char* file_name; AvrIspReaderViewCallback callback; void* context; }; @@ -23,7 +25,7 @@ typedef struct { bool detect_chip; } AvrIspReaderViewModel; -void avr_asp_reader_view_set_callback( +void avr_isp_reader_view_set_callback( AvrIspReaderView* instance, AvrIspReaderViewCallback callback, void* context) { @@ -33,7 +35,16 @@ void avr_asp_reader_view_set_callback( instance->context = context; } -void avr_asp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { +void avr_isp_reader_set_file_path( + AvrIspReaderView* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; +} + +void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { UNUSED(model); canvas_clear(canvas); // canvas_set_color(canvas, ColorBlack); @@ -46,9 +57,6 @@ void avr_asp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { // canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontPrimary); - elements_button_left(canvas, "ReDetect"); - elements_button_center(canvas, "Dump"); - if(!model->detect_chip) { canvas_draw_icon_animation(canvas, 0, 0, model->icon); canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); @@ -57,24 +65,36 @@ void avr_asp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); } + elements_button_left(canvas, "ReDetect"); + elements_button_center(canvas, "Dump"); } -bool avr_asp_reader_view_input(InputEvent* event, void* context) { +bool avr_isp_reader_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspReaderView* instance = context; UNUSED(instance); if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; - } else if(event->key == InputKeyOk && event->type == InputTypePress) { + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + FURI_LOG_D("d", "Read dump chip 1"); + avr_isp_rw_get_dump(instance->avr_isp_rw, instance->file_path, instance->file_name); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - FURI_LOG_D("s", "--Detecting--"); - avr_isp_rw_worker_detect_chip(instance->worker); + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + icon_animation_start(model->icon); + model->detect_chip = false; + }, + false); + avr_isp_rw_detect_chip(instance->avr_isp_rw); } return true; } -static void avr_asp_reader_detect_chip_callback(void* context, const char* name) { +static void + avr_isp_reader_detect_chip_callback(void* context, const char* name, bool detect_chip) { furi_assert(context); AvrIspReaderView* instance = context; with_view_model( @@ -82,12 +102,12 @@ static void avr_asp_reader_detect_chip_callback(void* context, const char* name) AvrIspReaderViewModel * model, { model->name_chip = name; - model->detect_chip = true; - icon_animation_stop(model->icon); + model->detect_chip = detect_chip; + if(detect_chip) icon_animation_stop(model->icon); }, true); } -void avr_asp_reader_view_enter(void* context) { +void avr_isp_reader_view_enter(void* context) { furi_assert(context); AvrIspReaderView* instance = context; @@ -100,25 +120,24 @@ void avr_asp_reader_view_enter(void* context) { }, false); - //Start worker - instance->worker = avr_isp_rw_worker_alloc(instance->context); + //Start avr_isp_rw + instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); - avr_isp_rw_worker_set_callback( - instance->worker, avr_asp_reader_detect_chip_callback, instance); + avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_reader_detect_chip_callback, instance); - avr_isp_rw_worker_detect_chip(instance->worker); + avr_isp_rw_detect_chip(instance->avr_isp_rw); - //avr_isp_rw_worker_start(instance->worker); + //avr_isp_rw_start(instance->avr_isp_rw); } -void avr_asp_reader_view_exit(void* context) { +void avr_isp_reader_view_exit(void* context) { furi_assert(context); AvrIspReaderView* instance = context; - // //Stop worker - // if(avr_isp_worker_is_running(instance->worker)) { - // avr_isp_worker_stop(instance->worker); + // //Stop avr_isp_rw + // if(avr_isp_avr_isp_rw_is_running(instance->avr_isp_rw)) { + // avr_isp_avr_isp_rw_stop(instance->avr_isp_rw); // } - avr_isp_rw_worker_free(instance->worker); + avr_isp_rw_free(instance->avr_isp_rw); with_view_model( instance->view, @@ -127,7 +146,7 @@ void avr_asp_reader_view_exit(void* context) { false); } -AvrIspReaderView* avr_asp_reader_view_alloc() { +AvrIspReaderView* avr_isp_reader_view_alloc() { AvrIspReaderView* instance = malloc(sizeof(AvrIspReaderView)); // View allocation and configuration @@ -135,10 +154,10 @@ AvrIspReaderView* avr_asp_reader_view_alloc() { view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspReaderViewModel)); view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_reader_view_draw); - view_set_input_callback(instance->view, avr_asp_reader_view_input); - view_set_enter_callback(instance->view, avr_asp_reader_view_enter); - view_set_exit_callback(instance->view, avr_asp_reader_view_exit); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_reader_view_draw); + view_set_input_callback(instance->view, avr_isp_reader_view_input); + view_set_enter_callback(instance->view, avr_isp_reader_view_enter); + view_set_exit_callback(instance->view, avr_isp_reader_view_exit); with_view_model( instance->view, @@ -152,7 +171,7 @@ AvrIspReaderView* avr_asp_reader_view_alloc() { return instance; } -void avr_asp_reader_view_free(AvrIspReaderView* instance) { +void avr_isp_reader_view_free(AvrIspReaderView* instance) { furi_assert(instance); with_view_model( @@ -164,7 +183,7 @@ void avr_asp_reader_view_free(AvrIspReaderView* instance) { free(instance); } -View* avr_asp_reader_view_get_view(AvrIspReaderView* instance) { +View* avr_isp_reader_view_get_view(AvrIspReaderView* instance) { furi_assert(instance); return instance->view; } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h index e06a5a597d5..39282888480 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h @@ -8,15 +8,20 @@ typedef struct AvrIspReaderView AvrIspReaderView; typedef void (*AvrIspReaderViewCallback)(AvrIspCustomEvent event, void* context); -void avr_asp_reader_view_set_callback( +void avr_isp_reader_set_file_path( + AvrIspReaderView* instance, + const char* file_path, + const char* file_name); + +void avr_isp_reader_view_set_callback( AvrIspReaderView* instance, AvrIspReaderViewCallback callback, void* context); -AvrIspReaderView* avr_asp_reader_view_alloc(); +AvrIspReaderView* avr_isp_reader_view_alloc(); -void avr_asp_reader_view_free(AvrIspReaderView* instance); +void avr_isp_reader_view_free(AvrIspReaderView* instance); -View* avr_asp_reader_view_get_view(AvrIspReaderView* instance); +View* avr_isp_reader_view_get_view(AvrIspReaderView* instance); -void avr_asp_reader_view_exit(void* context); +void avr_isp_reader_view_exit(void* context); diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c index e50597d1d73..01f425ef2a3 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c @@ -3,7 +3,7 @@ #include #include -#include "../helpers/avr_isp_rw_worker.h" +#include "../helpers/avr_isp_rw.h" //#include //#include @@ -11,7 +11,7 @@ struct AvrIspWriterView { View* view; - AvrIspRWWorker* worker; + AvrIspRW* avr_isp_rw; AvrIspWriterViewCallback callback; void* context; }; @@ -23,7 +23,7 @@ typedef struct { bool detect_chip; } AvrIspWriterViewModel; -void avr_asp_writer_view_set_callback( +void avr_isp_writer_view_set_callback( AvrIspWriterView* instance, AvrIspWriterViewCallback callback, void* context) { @@ -33,7 +33,7 @@ void avr_asp_writer_view_set_callback( instance->context = context; } -void avr_asp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { +void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { UNUSED(model); canvas_clear(canvas); // canvas_set_color(canvas, ColorBlack); @@ -46,8 +46,7 @@ void avr_asp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { // canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontPrimary); - elements_button_left(canvas, "ReDetect"); - elements_button_center(canvas, "Dump"); + if(!model->detect_chip) { canvas_draw_icon_animation(canvas, 0, 0, model->icon); @@ -57,9 +56,11 @@ void avr_asp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); } + elements_button_left(canvas, "ReDetect"); + elements_button_center(canvas, "Dump"); } -bool avr_asp_writer_view_input(InputEvent* event, void* context) { +bool avr_isp_writer_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspWriterView* instance = context; UNUSED(instance); @@ -68,13 +69,14 @@ bool avr_asp_writer_view_input(InputEvent* event, void* context) { } else if(event->key == InputKeyOk && event->type == InputTypePress) { } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { FURI_LOG_D("s", "--Detecting--"); - avr_isp_rw_worker_detect_chip(instance->worker); + avr_isp_rw_detect_chip(instance->avr_isp_rw); } return true; } -static void avr_asp_writer_detect_chip_callback(void* context, const char* name) { +static void + avr_isp_writer_detect_chip_callback(void* context, const char* name, bool detect_chip) { furi_assert(context); AvrIspWriterView* instance = context; with_view_model( @@ -82,12 +84,12 @@ static void avr_asp_writer_detect_chip_callback(void* context, const char* name) AvrIspWriterViewModel * model, { model->name_chip = name; - model->detect_chip = true; + model->detect_chip = detect_chip; icon_animation_stop(model->icon); }, true); } -void avr_asp_writer_view_enter(void* context) { +void avr_isp_writer_view_enter(void* context) { furi_assert(context); AvrIspWriterView* instance = context; @@ -100,25 +102,24 @@ void avr_asp_writer_view_enter(void* context) { }, false); - //Start worker - instance->worker = avr_isp_rw_worker_alloc(instance->context); + //Start avr_isp_rw + instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); - avr_isp_rw_worker_set_callback( - instance->worker, avr_asp_writer_detect_chip_callback, instance); + avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_writer_detect_chip_callback, instance); - avr_isp_rw_worker_detect_chip(instance->worker); + avr_isp_rw_detect_chip(instance->avr_isp_rw); - //avr_isp_rw_worker_start(instance->worker); + //avr_isp_rw_start(instance->avr_isp_rw); } -void avr_asp_writer_view_exit(void* context) { +void avr_isp_writer_view_exit(void* context) { furi_assert(context); AvrIspWriterView* instance = context; - // //Stop worker - // if(avr_isp_worker_is_running(instance->worker)) { - // avr_isp_worker_stop(instance->worker); + // //Stop avr_isp_rw + // if(avr_isp_avr_isp_rw_is_running(instance->avr_isp_rw)) { + // avr_isp_avr_isp_rw_stop(instance->avr_isp_rw); // } - avr_isp_rw_worker_free(instance->worker); + avr_isp_rw_free(instance->avr_isp_rw); with_view_model( instance->view, @@ -127,7 +128,7 @@ void avr_asp_writer_view_exit(void* context) { false); } -AvrIspWriterView* avr_asp_writer_view_alloc() { +AvrIspWriterView* avr_isp_writer_view_alloc() { AvrIspWriterView* instance = malloc(sizeof(AvrIspWriterView)); // View allocation and configuration @@ -135,10 +136,10 @@ AvrIspWriterView* avr_asp_writer_view_alloc() { view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspWriterViewModel)); view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)avr_asp_writer_view_draw); - view_set_input_callback(instance->view, avr_asp_writer_view_input); - view_set_enter_callback(instance->view, avr_asp_writer_view_enter); - view_set_exit_callback(instance->view, avr_asp_writer_view_exit); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_writer_view_draw); + view_set_input_callback(instance->view, avr_isp_writer_view_input); + view_set_enter_callback(instance->view, avr_isp_writer_view_enter); + view_set_exit_callback(instance->view, avr_isp_writer_view_exit); with_view_model( instance->view, @@ -152,7 +153,7 @@ AvrIspWriterView* avr_asp_writer_view_alloc() { return instance; } -void avr_asp_writer_view_free(AvrIspWriterView* instance) { +void avr_isp_writer_view_free(AvrIspWriterView* instance) { furi_assert(instance); with_view_model( @@ -164,7 +165,7 @@ void avr_asp_writer_view_free(AvrIspWriterView* instance) { free(instance); } -View* avr_asp_writer_view_get_view(AvrIspWriterView* instance) { +View* avr_isp_writer_view_get_view(AvrIspWriterView* instance) { furi_assert(instance); return instance->view; } diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h index d6d10baeeae..aabeb93868d 100644 --- a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h +++ b/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h @@ -8,15 +8,15 @@ typedef struct AvrIspWriterView AvrIspWriterView; typedef void (*AvrIspWriterViewCallback)(AvrIspCustomEvent event, void* context); -void avr_asp_writer_view_set_callback( +void avr_isp_writer_view_set_callback( AvrIspWriterView* instance, AvrIspWriterViewCallback callback, void* context); -AvrIspWriterView* avr_asp_writer_view_alloc(); +AvrIspWriterView* avr_isp_writer_view_alloc(); -void avr_asp_writer_view_free(AvrIspWriterView* instance); +void avr_isp_writer_view_free(AvrIspWriterView* instance); -View* avr_asp_writer_view_get_view(AvrIspWriterView* instance); +View* avr_isp_writer_view_get_view(AvrIspWriterView* instance); -void avr_asp_writer_view_exit(void* context); +void avr_isp_writer_view_exit(void* context); From 831f917b6ec8b8fbf523b65b904c25f3993913ef Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 21 Mar 2023 18:45:43 +0400 Subject: [PATCH 20/50] AVR_ISP: move to externel --- .../avr_isp_programmer/application.fam | 4 +--- .../avr_isp_programmer/avr_isp.png | Bin .../avr_isp_programmer/avr_isp_app.c | 0 .../avr_isp_programmer/avr_isp_app_i.c | 0 .../avr_isp_programmer/avr_isp_app_i.h | 0 .../avr_isp_programmer/helpers/avr_isp.c | 0 .../avr_isp_programmer/helpers/avr_isp.h | 0 .../avr_isp_programmer/helpers/avr_isp_event.h | 0 .../avr_isp_programmer/helpers/avr_isp_rw.c | 0 .../avr_isp_programmer/helpers/avr_isp_rw.h | 0 .../avr_isp_programmer/helpers/avr_isp_types.h | 0 .../avr_isp_programmer/helpers/avr_isp_worker.c | 0 .../avr_isp_programmer/helpers/avr_isp_worker.h | 0 .../helpers/flipper_i32hex_file.c | 0 .../helpers/flipper_i32hex_file.h | 0 .../avr_isp_programmer/images/AvrIspProg.png | Bin .../images/ChipLooking_64x64/frame_01.png | Bin .../images/ChipLooking_64x64/frame_02.png | Bin .../images/ChipLooking_64x64/frame_03.png | Bin .../images/ChipLooking_64x64/frame_rate | 0 .../avr_isp_programmer/images/avr_isp.png | Bin .../lib/driver/avr_isp_chip_arr.c | 0 .../lib/driver/avr_isp_chip_arr.h | 0 .../avr_isp_programmer/lib/driver/avr_isp_prog.c | 0 .../avr_isp_programmer/lib/driver/avr_isp_prog.h | 0 .../lib/driver/avr_isp_prog_cmd.h | 0 .../avr_isp_programmer/lib/driver/avr_isp_spi_sw.c | 0 .../avr_isp_programmer/lib/driver/avr_isp_spi_sw.h | 0 .../avr_isp_programmer/scenes/avr_isp_scene.c | 0 .../avr_isp_programmer/scenes/avr_isp_scene.h | 0 .../avr_isp_programmer/scenes/avr_isp_scene_about.c | 0 .../scenes/avr_isp_scene_config.h | 0 .../scenes/avr_isp_scene_input_name.c | 0 .../avr_isp_programmer/scenes/avr_isp_scene_load.c | 0 .../scenes/avr_isp_scene_programmer.c | 0 .../scenes/avr_isp_scene_reader.c | 0 .../avr_isp_programmer/scenes/avr_isp_scene_start.c | 0 .../scenes/avr_isp_scene_writer.c | 0 .../views/avr_isp_view_programmer.c | 0 .../views/avr_isp_view_programmer.h | 0 .../avr_isp_programmer/views/avr_isp_view_reader.c | 0 .../avr_isp_programmer/views/avr_isp_view_reader.h | 0 .../avr_isp_programmer/views/avr_isp_view_writer.c | 0 .../avr_isp_programmer/views/avr_isp_view_writer.h | 0 44 files changed, 1 insertion(+), 3 deletions(-) rename applications/{plugins => external}/avr_isp_programmer/application.fam (78%) rename applications/{plugins => external}/avr_isp_programmer/avr_isp.png (100%) rename applications/{plugins => external}/avr_isp_programmer/avr_isp_app.c (100%) rename applications/{plugins => external}/avr_isp_programmer/avr_isp_app_i.c (100%) rename applications/{plugins => external}/avr_isp_programmer/avr_isp_app_i.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp.c (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_event.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_rw.c (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_rw.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_types.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_worker.c (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/avr_isp_worker.h (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/flipper_i32hex_file.c (100%) rename applications/{plugins => external}/avr_isp_programmer/helpers/flipper_i32hex_file.h (100%) rename applications/{plugins => external}/avr_isp_programmer/images/AvrIspProg.png (100%) rename applications/{plugins => external}/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png (100%) rename applications/{plugins => external}/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png (100%) rename applications/{plugins => external}/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png (100%) rename applications/{plugins => external}/avr_isp_programmer/images/ChipLooking_64x64/frame_rate (100%) rename applications/{plugins => external}/avr_isp_programmer/images/avr_isp.png (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_prog.c (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_prog.h (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c (100%) rename applications/{plugins => external}/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene.h (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_about.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_config.h (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_input_name.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_load.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_programmer.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_reader.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_start.c (100%) rename applications/{plugins => external}/avr_isp_programmer/scenes/avr_isp_scene_writer.c (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_programmer.c (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_programmer.h (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_reader.c (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_reader.h (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_writer.c (100%) rename applications/{plugins => external}/avr_isp_programmer/views/avr_isp_view_writer.h (100%) diff --git a/applications/plugins/avr_isp_programmer/application.fam b/applications/external/avr_isp_programmer/application.fam similarity index 78% rename from applications/plugins/avr_isp_programmer/application.fam rename to applications/external/avr_isp_programmer/application.fam index 1b0e931e91e..a7a0e67e904 100644 --- a/applications/plugins/avr_isp_programmer/application.fam +++ b/applications/external/avr_isp_programmer/application.fam @@ -1,10 +1,8 @@ App( appid="avr_isp", name="AVR ISP Programmer", - apptype=FlipperAppType.PLUGIN, - targets=["f7"], + apptype=FlipperAppType.EXTERNAL, entry_point="avr_isp_app", - cdefines=["APP_AVR_ISP"], requires=["gui"], stack_size=2 * 1024, order=20, diff --git a/applications/plugins/avr_isp_programmer/avr_isp.png b/applications/external/avr_isp_programmer/avr_isp.png similarity index 100% rename from applications/plugins/avr_isp_programmer/avr_isp.png rename to applications/external/avr_isp_programmer/avr_isp.png diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c similarity index 100% rename from applications/plugins/avr_isp_programmer/avr_isp_app.c rename to applications/external/avr_isp_programmer/avr_isp_app.c diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c similarity index 100% rename from applications/plugins/avr_isp_programmer/avr_isp_app_i.c rename to applications/external/avr_isp_programmer/avr_isp_app_i.c diff --git a/applications/plugins/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h similarity index 100% rename from applications/plugins/avr_isp_programmer/avr_isp_app_i.h rename to applications/external/avr_isp_programmer/avr_isp_app_i.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp.c rename to applications/external/avr_isp_programmer/helpers/avr_isp.c diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp.h b/applications/external/avr_isp_programmer/helpers/avr_isp.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp.h rename to applications/external/avr_isp_programmer/helpers/avr_isp.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_event.h rename to applications/external/avr_isp_programmer/helpers/avr_isp_event.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.c rename to applications/external/avr_isp_programmer/helpers/avr_isp_rw.c diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_rw.h rename to applications/external/avr_isp_programmer/helpers/avr_isp_rw.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_types.h rename to applications/external/avr_isp_programmer/helpers/avr_isp_types.h diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.c rename to applications/external/avr_isp_programmer/helpers/avr_isp_worker.c diff --git a/applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/avr_isp_worker.h rename to applications/external/avr_isp_programmer/helpers/avr_isp_worker.h diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.c rename to applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c diff --git a/applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h similarity index 100% rename from applications/plugins/avr_isp_programmer/helpers/flipper_i32hex_file.h rename to applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h diff --git a/applications/plugins/avr_isp_programmer/images/AvrIspProg.png b/applications/external/avr_isp_programmer/images/AvrIspProg.png similarity index 100% rename from applications/plugins/avr_isp_programmer/images/AvrIspProg.png rename to applications/external/avr_isp_programmer/images/AvrIspProg.png diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png similarity index 100% rename from applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png rename to applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png similarity index 100% rename from applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png rename to applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png similarity index 100% rename from applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png rename to applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png diff --git a/applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate similarity index 100% rename from applications/plugins/avr_isp_programmer/images/ChipLooking_64x64/frame_rate rename to applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate diff --git a/applications/plugins/avr_isp_programmer/images/avr_isp.png b/applications/external/avr_isp_programmer/images/avr_isp.png similarity index 100% rename from applications/plugins/avr_isp_programmer/images/avr_isp.png rename to applications/external/avr_isp_programmer/images/avr_isp.png diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.c rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog.h rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c diff --git a/applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h similarity index 100% rename from applications/plugins/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h rename to applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene.h similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene.h rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene.h diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_about.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_config.h rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_input_name.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_load.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_programmer.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_reader.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_start.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c diff --git a/applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c similarity index 100% rename from applications/plugins/avr_isp_programmer/scenes/avr_isp_scene_writer.c rename to applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.c rename to applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_programmer.h rename to applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.c rename to applications/external/avr_isp_programmer/views/avr_isp_view_reader.c diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_reader.h rename to applications/external/avr_isp_programmer/views/avr_isp_view_reader.h diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.c rename to applications/external/avr_isp_programmer/views/avr_isp_view_writer.c diff --git a/applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h similarity index 100% rename from applications/plugins/avr_isp_programmer/views/avr_isp_view_writer.h rename to applications/external/avr_isp_programmer/views/avr_isp_view_writer.h From 31c9365a962ee7b3452072550181075c990945b0 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 21 Mar 2023 18:54:51 +0400 Subject: [PATCH 21/50] API: fix api_symbols --- firmware/targets/f18/api_symbols.csv | 8 +++++++- firmware/targets/f7/api_symbols.csv | 6 +----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index b6be56f60d1..91e394487a9 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,+,19.0,, +Version,v,19.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -160,6 +160,7 @@ Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, +Header,+,lib/toolbox/hex.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, @@ -1316,6 +1317,10 @@ Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*" Function,+,hal_sd_detect,_Bool, Function,+,hal_sd_detect_init,void, Function,+,hal_sd_detect_set_low,void, +Function,+,hex_char_to_hex_nibble,_Bool,"char, uint8_t*" +Function,+,hex_char_to_uint8,_Bool,"char, char, uint8_t*" +Function,+,hex_chars_to_uint64,_Bool,"const char*, uint64_t*" +Function,+,hex_chars_to_uint8,_Bool,"const char*, uint8_t*" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* Function,+,icon_animation_get_height,uint8_t,const IconAnimation* @@ -1876,6 +1881,7 @@ Function,+,uECC_sign,int,"const uint8_t*, const uint8_t*, unsigned, uint8_t*, uE Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned, const uECC_HashContext*, uint8_t*, uECC_Curve" Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" +Function,+,uint8_to_hex_chars,void,"const uint8_t*, uint8_t*, int" Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" Function,-,ulTaskGetIdleRunTimeCounter,uint32_t, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 4d01b37231d..a4a75de3946 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,+,19.0,, +Version,+,19.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -193,7 +193,6 @@ Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, Header,+,lib/toolbox/hex.h,, -Header,+,lib/toolbox/hmac_sha256.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, @@ -1610,9 +1609,6 @@ Function,+,hex_char_to_hex_nibble,_Bool,"char, uint8_t*" Function,+,hex_char_to_uint8,_Bool,"char, char, uint8_t*" Function,+,hex_chars_to_uint64,_Bool,"const char*, uint64_t*" Function,+,hex_chars_to_uint8,_Bool,"const char*, uint8_t*" -Function,+,hmac_sha256_finish,void,"const hmac_sha256_context*, const uint8_t*, uint8_t*" -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,-,hypot,double,"double, double" Function,-,hypotf,float,"float, float" Function,-,hypotl,long double,"long double, long double" From b279bb78ff1dcd4c2b834086be5682a1a1fe1c01 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 21 Mar 2023 21:07:07 +0400 Subject: [PATCH 22/50] AVR_ISP: add wiring scene --- .../avr_isp_programmer/avr_isp_app_i.c | 2 +- .../images/AVR_app_icon_10x10.png | Bin 0 -> 3614 bytes .../avr_isp_programmer/images/AvrIspProg.png | Bin 1690 -> 0 bytes .../images/Link_waiting_77x56.png | Bin 0 -> 3883 bytes .../avr_isp_programmer/images/avr_isp.png | Bin 143 -> 0 bytes .../avr_isp_programmer/images/avr_wiring.png | Bin 0 -> 4513 bytes .../images/chif_not_found_83x37.png | Bin 0 -> 3742 bytes .../images/chip_error_70x22.png | Bin 0 -> 3673 bytes .../images/chip_long_70x22.png | Bin 0 -> 3649 bytes .../scenes/avr_isp_scene_config.h | 2 ++ .../scenes/avr_isp_scene_start.c | 10 +++++-- .../scenes/avr_isp_scene_wiring.c | 18 +++++++++++++ .../views/avr_isp_view_programmer.c | 25 +++++++++--------- 13 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png delete mode 100644 applications/external/avr_isp_programmer/images/AvrIspProg.png create mode 100644 applications/external/avr_isp_programmer/images/Link_waiting_77x56.png delete mode 100644 applications/external/avr_isp_programmer/images/avr_isp.png create mode 100644 applications/external/avr_isp_programmer/images/avr_wiring.png create mode 100644 applications/external/avr_isp_programmer/images/chif_not_found_83x37.png create mode 100644 applications/external/avr_isp_programmer/images/chip_error_70x22.png create mode 100644 applications/external/avr_isp_programmer/images/chip_long_70x22.png create mode 100644 applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c index 7c92a03d9e8..4dd2e5b703e 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.c @@ -11,7 +11,7 @@ bool avr_isp_load_from_file(AvrIspApp* app) { file_path = furi_string_alloc(); DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, AVR_ISP_APP_EXTENSION, &I_avr_isp); + dialog_file_browser_set_basic_options(&browser_options, AVR_ISP_APP_EXTENSION, &I_AVR_app_icon_10x10); browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; // Input events and views are managed by file_select diff --git a/applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png b/applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png new file mode 100644 index 0000000000000000000000000000000000000000..533787fe3569f70196d3f71e8373102dfd3967a0 GIT binary patch literal 3614 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 Vpqb^9w@m;7?5&;gRaoD1{{|C}E&c!i literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/AvrIspProg.png b/applications/external/avr_isp_programmer/images/AvrIspProg.png deleted file mode 100644 index ec785948d035b717944bc41811f73d190e6fc3bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1690 zcmaJ?X;2eq7>)>*yJ)S*p|h?~Q6$-f1d>2NNH}5%Lt|z{KrzQc(y-YyStJQ+g^C9Q zSWv-YttjHfh@wyt@GLFhMTjB}M;LSv6%;{^;@J%X_DAW??0&~Q&+|U-`@P@n?x@Hx zJ8Nfa0)b%14d?LjF%^HQmS*_Zy;Prz4^CJ}G`0p!z*2-Nm=GjEMKHicgo!X87D}`~ zG{XJ_!fZF0AR3G2MKHxELKK=XL=B?E*#v@rphhVa%V7)_o@3{?OoMWF~y##kV3^-~Ura#~iQo~#pIF_K28B$0`bDW@qQkN5vj1er#wF+Tj+ z?|%xb1zIIc;=^h*StZ6#E@7!Dl#l0+R;G}k zDeC1D1RjscRj4tcLJV^`ED)C<%48Czw=bJb<4}SjatMt~4q?;jbe~|z8=_EsXfzI; zGR5Vf;$#F?U{hSlXD)k2uBjOiB_5drt7MyCNvH}%fQg)$vYEXwX4ISHN@n&FG$WUU zn<1G__FpGGwS~8jX*%7w_+q;CVFljrD!j4V;}c)t_r;dW2@+`9`eU1O>Hy1H=Z_x? z#)vXQ4`HsunYK6jxY4-M*|zlR`rg;$+V*St8!R`}`J(H(M(Fn4S4n;$pnW-UN$QA` z?fY?KM*pGHedF?8-QC`CtG>sHp2-iZetB?^`cj>4f5g#9o;N06J$3^rWaoX6Zp!iN6AS8ml(v%micb;q2O2KuEfM&;;GfOLnbEbQ;Xh2MB~uUb$O z=Tf34Z;Mngv^s8}xvK?|Q)X5xaeMf&yLz=D);7(;s_;xKaAkeDy_0K?%Yn2|k9C6T z^kdg4x7}!2l%F~e-2N&yKK{I*<bm{PN1M%~EqIS+ z#{g%nih7mt;>v=&E{mA(e4W(c;<>|5`bM6gWBHY@vRSt9LE+^Uhns6zS!2UzZw(cU zoUfWE)n;PLGTwze=xNtR#E5s54 z?u4@P3{ljfm#4cr?==i}&Q~nx+6o_SALMl>7g+8+b*EGr+g0b>QusCdoqSG@XTkT} zJKW>*p7M7!ScsC+I$SWe`PeH**g7LKd+2^e4BT{9(i5Fx*_t#~^L&3q*^<`Bg8SLL zJr^&8Wvz+nlWyNPFyz7qEt>zJmbmY7f19~I|Kz}R|I(kU_SSdG*|X+`TiP_=YR)O9 z%>w2`t#*GaxqGd${KiVYrAK$bi$_|DyT^Fr>F$>+;8w9Tw&Z$d+!FWSfdT)vdK%bz zZxc14Zjp1X%kW^EaVRy?Y1r_3XHB46)J>z~?!08J+0&8}hNJx?^62efuWTu{t@zFL zVZ4jin2pbcGJ}2f!HjR`wC}%p=#A$7DVOR4RjdwPz~ZWrAMHE3V&KiltB9(rl{Yu) zpLzA}yq2xqYW6IxKLj-^F^5Q^3s;lX5 N!3~Mzlm%~0{|8*@s)qmo diff --git a/applications/external/avr_isp_programmer/images/Link_waiting_77x56.png b/applications/external/avr_isp_programmer/images/Link_waiting_77x56.png new file mode 100644 index 0000000000000000000000000000000000000000..d7d32aed59a19e24a7e1f2216c806872610a0af5 GIT binary patch literal 3883 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 diff --git a/applications/external/avr_isp_programmer/images/avr_wiring.png b/applications/external/avr_isp_programmer/images/avr_wiring.png new file mode 100644 index 0000000000000000000000000000000000000000..957012405127ce4504ef8cd4e805b1fc31963026 GIT binary patch literal 4513 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 literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png b/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png new file mode 100644 index 0000000000000000000000000000000000000000..b03bf3567ade9b2e4ce2d29328032ebd40c89401 GIT binary patch literal 3742 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 literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/chip_error_70x22.png b/applications/external/avr_isp_programmer/images/chip_error_70x22.png new file mode 100644 index 0000000000000000000000000000000000000000..cb07199cd1b6cbbad0786129a1104ad2a3e0cf8a GIT binary patch literal 3673 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, AvrIspSceneProgrammer); consumed = true; - }else if(event.event == SubmenuIndexAvrIspReader) { + } else if(event.event == SubmenuIndexAvrIspReader) { scene_manager_next_scene(app->scene_manager, AvrIspSceneInputName); consumed = true; - }else if(event.event == SubmenuIndexAvrIspWriter) { + } else if(event.event == SubmenuIndexAvrIspWriter) { scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); consumed = true; + } else if(event.event == SubmenuIndexAvrIsWiring) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); + consumed = true; } scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c new file mode 100644 index 00000000000..cda42bd9653 --- /dev/null +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c @@ -0,0 +1,18 @@ +#include "../avr_isp_app_i.h" +#include "../helpers/avr_isp_types.h" + +void avr_isp_scene_wiring_on_enter(void* context) { + AvrIspApp* app = context; + widget_add_icon_element(app->widget, 0, 0, &I_avr_wiring); + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWidget); +} + +bool avr_isp_scene_wiring_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void avr_isp_scene_wiring_on_exit(void* context) { + AvrIspApp* app = context; + widget_reset(app->widget); +} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index b8ff0ca4548..08dca9ce512 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -6,7 +6,7 @@ //#include //#include -//#include +#include struct AvrIspProgrammerView { View* view; @@ -37,20 +37,21 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod canvas_clear(canvas); // canvas_set_color(canvas, ColorBlack); // canvas_set_font(canvas, FontSecondary); - - //canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + canvas_set_font(canvas, FontPrimary); + canvas_draw_icon(canvas, 20, 8, &I_Link_waiting_77x56); + elements_multiline_text(canvas, 20, 10, "Waiting for software\nconnection"); // canvas_set_font(canvas, FontPrimary); // canvas_draw_str(canvas, 63, 46, "AVRISPProg"); // canvas_set_font(canvas, FontSecondary); - canvas_set_font(canvas, FontPrimary); - if(!model->detect_chip) { - canvas_draw_icon_animation(canvas, 0, 0, model->icon); - canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); - canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); - } else { - canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); - canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); - } + + // if(!model->detect_chip) { + // canvas_draw_icon_animation(canvas, 0, 0, model->icon); + // canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); + // canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); + // } else { + // canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); + // canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + // } } bool avr_isp_programmer_view_input(InputEvent* event, void* context) { From e8b6ee12b03f5139eb1096a3918ee8389f092816 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 21 Mar 2023 23:05:59 +0400 Subject: [PATCH 23/50] AVR_ISP: refactoring --- .../avr_isp_programmer/application.fam | 2 +- .../external/avr_isp_programmer/avr_isp_app.c | 15 +- .../avr_isp_programmer/avr_isp_app_i.h | 2 + .../helpers/avr_isp_event.h | 12 +- .../avr_isp_programmer/helpers/avr_isp_rw.c | 7 +- .../avr_isp_programmer/helpers/avr_isp_rw.h | 2 +- .../helpers/avr_isp_types.h | 3 +- .../scenes/avr_isp_scene_chip_detect.c | 41 ++++ .../scenes/avr_isp_scene_config.h | 1 + .../scenes/avr_isp_scene_start.c | 11 +- .../views/avr_isp_view_chip_detect.c | 197 ++++++++++++++++++ .../views/avr_isp_view_chip_detect.h | 38 ++++ .../views/avr_isp_view_reader.c | 30 +-- .../views/avr_isp_view_writer.c | 31 +-- 14 files changed, 344 insertions(+), 48 deletions(-) create mode 100644 applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c create mode 100644 applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c create mode 100644 applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h diff --git a/applications/external/avr_isp_programmer/application.fam b/applications/external/avr_isp_programmer/application.fam index a7a0e67e904..87ccb4cfb01 100644 --- a/applications/external/avr_isp_programmer/application.fam +++ b/applications/external/avr_isp_programmer/application.fam @@ -4,7 +4,7 @@ App( apptype=FlipperAppType.EXTERNAL, entry_point="avr_isp_app", requires=["gui"], - stack_size=2 * 1024, + stack_size=4 * 1024, order=20, fap_icon="avr_isp.png", fap_category="GPIO", diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index 65cb6df0ce5..e3254949c4a 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -85,12 +85,19 @@ AvrIspApp* avr_isp_app_alloc() { AvrIspViewReader, avr_isp_reader_view_get_view(app->avr_isp_reader_view)); - // Reader view + // Writer view app->avr_isp_writer_view = avr_isp_writer_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, AvrIspViewWriter, avr_isp_writer_view_get_view(app->avr_isp_writer_view)); + + // Chip detect view + app->avr_isp_chip_detect_view = avr_isp_chip_detect_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + AvrIspViewChipDetect, + avr_isp_chip_detect_view_get_view(app->avr_isp_chip_detect_view)); scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); @@ -127,10 +134,14 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader); avr_isp_reader_view_free(app->avr_isp_reader_view); - // Reader view + // Writer view view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWriter); avr_isp_writer_view_free(app->avr_isp_writer_view); + // Chip detect view + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewChipDetect); + avr_isp_chip_detect_view_free(app->avr_isp_chip_detect_view); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h index 63a02bcc046..edc2c7c6978 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.h @@ -18,6 +18,7 @@ #include "views/avr_isp_view_programmer.h" #include "views/avr_isp_view_reader.h" #include "views/avr_isp_view_writer.h" +#include "views/avr_isp_view_chip_detect.h" #define AVR_ISP_MAX_LEN_NAME 64 @@ -37,6 +38,7 @@ typedef struct { AvrIspProgrammerView* avr_isp_programmer_view; AvrIspReaderView* avr_isp_reader_view; AvrIspWriterView* avr_isp_writer_view; + AvrIspChipDetectView* avr_isp_chip_detect_view; } AvrIspApp; bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index f0bd02f7867..dd0bf997376 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -1,6 +1,16 @@ #pragma once typedef enum { - AvrIspCustomEventStartId = 100, + //SubmenuIndex + SubmenuIndexAvrIspProgrammer = 10, + SubmenuIndexAvrIspReader, + SubmenuIndexAvrIspWriter, + SubmenuIndexAvrIsWiring, + SubmenuIndexAvrIspAbout, + + //AvrIspCustomEventStartId = 100, + + //AvrIspCustomEvent + AvrIspCustomEventSceneChipDetectOk = 100, AvrIspCustomEventSceneInputName, } AvrIspCustomEvent; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c index 9314f65037c..7ce09cd3c75 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c @@ -96,16 +96,17 @@ bool avr_isp_rw_detect_chip(AvrIspRW* instance) { if(instance->callback) { if(instance->chip_arr_ind > avr_isp_chip_arr_size) { //ToDo add output ID chip - instance->callback(instance->context, "No detect", instance->chip_detect); + instance->callback(instance->context, "No detect", instance->chip_detect, 0); } else if(instance->chip_arr_ind < avr_isp_chip_arr_size) { instance->callback( instance->context, avr_isp_chip_arr[instance->chip_arr_ind].name, - instance->chip_detect); + instance->chip_detect, + avr_isp_chip_arr[instance->chip_arr_ind].flashsize); } else { //ToDo add output ID chip - instance->callback(instance->context, "Unknown", instance->chip_detect); + instance->callback(instance->context, "Unknown", instance->chip_detect, 0); } } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h index b1f1c1f109e..9b45d302468 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h @@ -4,7 +4,7 @@ typedef struct AvrIspRW AvrIspRW; -typedef void (*AvrIspRWCallback)(void* context, const char* name, bool detect_chip); +typedef void (*AvrIspRWCallback)(void* context, const char* name, bool detect_chip, uint32_t flash_size); /** Allocate AvrIspRW * diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h index c540d05db32..8c9e9c4404d 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h @@ -19,4 +19,5 @@ typedef enum { AvrIspViewWriter, AvrIspViewWidget, AvrIspViewTextInput, -} AvrIspView; + AvrIspViewChipDetect, +} AvrIspView; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c new file mode 100644 index 00000000000..01e42c2abf4 --- /dev/null +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -0,0 +1,41 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_chip_detect.h" + +void avr_isp_scene_chip_detect_callback(AvrIspCustomEvent event, void* context) { + furi_assert(context); + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void avr_isp_scene_chip_detect_on_enter(void* context) { + AvrIspApp* app = context; + + // avr_isp_chip_detect_set_file_path( + // app->avr_isp_chip_detect_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); + avr_isp_chip_detect_view_set_callback( + app->avr_isp_chip_detect_view, avr_isp_scene_chip_detect_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewChipDetect); +} + +bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + UNUSED(app); + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case AvrIspCustomEventSceneChipDetectOk: + FURI_LOG_E("FF","DETECL OK"); + consumed = true; + break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + } + return consumed; +} + +void avr_isp_scene_chip_detect_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h index f14d96265b8..338a7f1e37a 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h @@ -6,4 +6,5 @@ ADD_SCENE(avr_isp, input_name, InputName) ADD_SCENE(avr_isp, load, Load) ADD_SCENE(avr_isp, writer, Writer) ADD_SCENE(avr_isp, wiring, Wiring) +ADD_SCENE(avr_isp, chip_detect, ChipDetect) diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c index 023cdeb2c5d..25e5852d7b2 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -1,13 +1,5 @@ #include "../avr_isp_app_i.h" -typedef enum { - SubmenuIndexAvrIspProgrammer, - SubmenuIndexAvrIspReader, - SubmenuIndexAvrIspWriter, - SubmenuIndexAvrIsWiring, - SubmenuIndexAvrIspAbout, -} SubmenuIndex; - void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); @@ -65,7 +57,8 @@ bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); consumed = true; } else if(event.event == SubmenuIndexAvrIsWiring) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); + //scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); + scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); consumed = true; } scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c new file mode 100644 index 00000000000..8809888bd47 --- /dev/null +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -0,0 +1,197 @@ +#include "avr_isp_view_chip_detect.h" +#include "../avr_isp_app_i.h" +#include +#include + +#include "../helpers/avr_isp_rw.h" + +struct AvrIspChipDetectView { + View* view; + AvrIspRW* avr_isp_rw; + const char* file_path; + const char* file_name; + AvrIspChipDetectViewCallback callback; + void* context; +}; + +typedef struct { + uint16_t idx; + const char* name_chip; + uint32_t flash_size; + AvrIspChipDetectViewStatus status; +} AvrIspChipDetectViewModel; + +void avr_isp_chip_detect_view_set_callback( + AvrIspChipDetectView* instance, + AvrIspChipDetectViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +void avr_isp_chip_detect_set_file_path( + AvrIspChipDetectView* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; +} + +void avr_isp_chip_detect_set_status( + AvrIspChipDetectView* instance, + AvrIspChipDetectViewStatus status) { + furi_assert(instance); + + with_view_model( + instance->view, AvrIspChipDetectViewModel * model, { model->status = status; }, true); +} + +void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* model) { + canvas_clear(canvas); + char str_buf[64] = {0}; + canvas_set_font(canvas, FontPrimary); + + switch(model->status) { + case AvrIspChipDetectViewStatusDetected: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip detected!"); + canvas_draw_icon(canvas, 29, 14, &I_chip_long_70x22); + canvas_set_font(canvas, FontSecondary); + snprintf(str_buf, sizeof(str_buf), "%ld Kb", model->flash_size / 1024); + canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignCenter, str_buf); + canvas_draw_str_aligned(canvas, 64, 45, AlignCenter, AlignCenter, model->name_chip); + elements_button_right(canvas, "Next"); + break; + case AvrIspChipDetectViewStatusErrorOccured: + canvas_draw_str_aligned( + canvas, 64, 5, AlignCenter, AlignCenter, "Error occured, try again!"); + canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); + break; + case AvrIspChipDetectViewStatusErrorVerification: + canvas_draw_str_aligned( + canvas, 64, 5, AlignCenter, AlignCenter, "Data verification failed"); + canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); + break; + + default: + //AvrIspChipDetectViewStatusNoDetect + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip not found!"); + canvas_draw_icon(canvas, 29, 12, &I_chif_not_found_83x37); + + break; + } + canvas_set_font(canvas, FontSecondary); + elements_button_left(canvas, "Retry"); +} + +bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { + furi_assert(context); + AvrIspChipDetectView* instance = context; + if(event->key == InputKeyBack || event->type != InputTypeShort) { + return false; + } else if(event->key == InputKeyRight && event->type == InputTypeShort) { + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + if(model->status == AvrIspChipDetectViewStatusDetected) { + if(instance->callback) + instance->callback(AvrIspCustomEventSceneChipDetectOk, instance->context); + } + }, + false); + + } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + avr_isp_rw_detect_chip(instance->avr_isp_rw); + } + + return true; +} + +static void avr_isp_chip_detect_detect_chip_callback( + void* context, + const char* name, + bool detect_chip, + uint32_t flash_size) { + furi_assert(context); + AvrIspChipDetectView* instance = context; + + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + model->name_chip = name; + model->flash_size = flash_size; + if(detect_chip) { + model->status = AvrIspChipDetectViewStatusDetected; + } else { + model->status = AvrIspChipDetectViewStatusNoDetect; + } + }, + true); +} +void avr_isp_chip_detect_view_enter(void* context) { + furi_assert(context); + AvrIspChipDetectView* instance = context; + FURI_LOG_E("FF","1"); + //Start avr_isp_rw + instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); +FURI_LOG_E("FF","2"); + avr_isp_rw_set_callback( + instance->avr_isp_rw, avr_isp_chip_detect_detect_chip_callback, instance); +FURI_LOG_E("FF","3"); + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + if(model->status == AvrIspChipDetectViewStatusNoDetect) { + avr_isp_rw_detect_chip(instance->avr_isp_rw); + } + }, + false); + //avr_isp_rw_detect_chip(instance->avr_isp_rw); + FURI_LOG_E("FF","4"); +} + +void avr_isp_chip_detect_view_exit(void* context) { + furi_assert(context); + AvrIspChipDetectView* instance = context; + + avr_isp_rw_set_callback(instance->avr_isp_rw, NULL, NULL); + avr_isp_rw_free(instance->avr_isp_rw); +} + +AvrIspChipDetectView* avr_isp_chip_detect_view_alloc() { + AvrIspChipDetectView* instance = malloc(sizeof(AvrIspChipDetectView)); + + // View allocation and configuration + instance->view = view_alloc(); + + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(AvrIspChipDetectViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)avr_isp_chip_detect_view_draw); + view_set_input_callback(instance->view, avr_isp_chip_detect_view_input); + view_set_enter_callback(instance->view, avr_isp_chip_detect_view_enter); + view_set_exit_callback(instance->view, avr_isp_chip_detect_view_exit); + + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { model->status = AvrIspChipDetectViewStatusNoDetect; }, + false); + return instance; +} + +void avr_isp_chip_detect_view_free(AvrIspChipDetectView* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* avr_isp_chip_detect_view_get_view(AvrIspChipDetectView* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h new file mode 100644 index 00000000000..d52ff1d1dee --- /dev/null +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include "../helpers/avr_isp_types.h" +#include "../helpers/avr_isp_event.h" + +typedef struct AvrIspChipDetectView AvrIspChipDetectView; + +typedef void (*AvrIspChipDetectViewCallback)(AvrIspCustomEvent event, void* context); + +typedef enum { + AvrIspChipDetectViewStatusNoDetect, + AvrIspChipDetectViewStatusDetected, + AvrIspChipDetectViewStatusErrorOccured, + AvrIspChipDetectViewStatusErrorVerification, +} AvrIspChipDetectViewStatus; + +void avr_isp_chip_detect_set_file_path( + AvrIspChipDetectView* instance, + const char* file_path, + const char* file_name); + +void avr_isp_chip_detect_view_set_callback( + AvrIspChipDetectView* instance, + AvrIspChipDetectViewCallback callback, + void* context); + +void avr_isp_chip_detect_set_status( + AvrIspChipDetectView* instance, + AvrIspChipDetectViewStatus status); + +AvrIspChipDetectView* avr_isp_chip_detect_view_alloc(); + +void avr_isp_chip_detect_view_free(AvrIspChipDetectView* instance); + +View* avr_isp_chip_detect_view_get_view(AvrIspChipDetectView* instance); + +void avr_isp_chip_detect_view_exit(void* context); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 23eddc2e32f..8d655bf4afd 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -93,20 +93,20 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { return true; } -static void - avr_isp_reader_detect_chip_callback(void* context, const char* name, bool detect_chip) { - furi_assert(context); - AvrIspReaderView* instance = context; - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - model->name_chip = name; - model->detect_chip = detect_chip; - if(detect_chip) icon_animation_stop(model->icon); - }, - true); -} +// static void +// avr_isp_reader_detect_chip_callback(void* context, const char* name, bool detect_chip) { +// furi_assert(context); +// AvrIspReaderView* instance = context; +// with_view_model( +// instance->view, +// AvrIspReaderViewModel * model, +// { +// model->name_chip = name; +// model->detect_chip = detect_chip; +// if(detect_chip) icon_animation_stop(model->icon); +// }, +// true); +// } void avr_isp_reader_view_enter(void* context) { furi_assert(context); AvrIspReaderView* instance = context; @@ -123,7 +123,7 @@ void avr_isp_reader_view_enter(void* context) { //Start avr_isp_rw instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); - avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_reader_detect_chip_callback, instance); + //avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_reader_detect_chip_callback, instance); avr_isp_rw_detect_chip(instance->avr_isp_rw); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 01f425ef2a3..85e69d8184d 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -75,20 +75,21 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { return true; } -static void - avr_isp_writer_detect_chip_callback(void* context, const char* name, bool detect_chip) { - furi_assert(context); - AvrIspWriterView* instance = context; - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - model->name_chip = name; - model->detect_chip = detect_chip; - icon_animation_stop(model->icon); - }, - true); -} +// static void +// avr_isp_writer_detect_chip_callback(void* context, const char* name, bool detect_chip) { +// furi_assert(context); +// AvrIspWriterView* instance = context; +// with_view_model( +// instance->view, +// AvrIspWriterViewModel * model, +// { +// model->name_chip = name; +// model->detect_chip = detect_chip; +// icon_animation_stop(model->icon); +// }, +// true); +// } + void avr_isp_writer_view_enter(void* context) { furi_assert(context); AvrIspWriterView* instance = context; @@ -105,7 +106,7 @@ void avr_isp_writer_view_enter(void* context) { //Start avr_isp_rw instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); - avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_writer_detect_chip_callback, instance); + //avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_writer_detect_chip_callback, instance); avr_isp_rw_detect_chip(instance->avr_isp_rw); From 9dc022927eee3ff6bc134f1df9c1a0406f7f1ef8 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 22 Mar 2023 00:13:29 +0400 Subject: [PATCH 24/50] GUI: model mutex FuriMutexTypeNormal -> FuriMutexTypeRecursive --- applications/services/gui/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/services/gui/view.c b/applications/services/gui/view.c index 50c05a406fa..4d84cac507d 100644 --- a/applications/services/gui/view.c +++ b/applications/services/gui/view.c @@ -81,7 +81,7 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) { view->model = malloc(size); } else if(view->model_type == ViewModelTypeLocking) { ViewModelLocking* model = malloc(sizeof(ViewModelLocking)); - model->mutex = furi_mutex_alloc(FuriMutexTypeNormal); + model->mutex = furi_mutex_alloc(FuriMutexTypeRecursive); furi_check(model->mutex); model->data = malloc(size); view->model = model; From 53d5395e03f28f5e55750e09c1aa2577d724f15e Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 22 Mar 2023 00:14:23 +0400 Subject: [PATCH 25/50] AVR_ISP: add chip_detect view --- .../helpers/avr_isp_event.h | 2 -- .../avr_isp_programmer/helpers/avr_isp_rw.c | 2 -- .../scenes/avr_isp_scene_chip_detect.c | 19 ++++++++--- .../scenes/avr_isp_scene_start.c | 16 ++++++---- .../views/avr_isp_view_chip_detect.c | 32 ++++++++----------- .../views/avr_isp_view_chip_detect.h | 6 +--- 6 files changed, 40 insertions(+), 37 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index dd0bf997376..3554ea3b5bb 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -8,8 +8,6 @@ typedef enum { SubmenuIndexAvrIsWiring, SubmenuIndexAvrIspAbout, - //AvrIspCustomEventStartId = 100, - //AvrIspCustomEvent AvrIspCustomEventSceneChipDetectOk = 100, AvrIspCustomEventSceneInputName, diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c index 7ce09cd3c75..4d0d3bb76df 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c @@ -137,8 +137,6 @@ void avr_isp_rw_free(AvrIspRW* instance) { } void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context) { - furi_assert(instance); - furi_assert(context); instance->callback = callback; instance->context = context; } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index 01e42c2abf4..3e456381b59 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -10,8 +10,6 @@ void avr_isp_scene_chip_detect_callback(AvrIspCustomEvent event, void* context) void avr_isp_scene_chip_detect_on_enter(void* context) { AvrIspApp* app = context; - // avr_isp_chip_detect_set_file_path( - // app->avr_isp_chip_detect_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); avr_isp_chip_detect_view_set_callback( app->avr_isp_chip_detect_view, avr_isp_scene_chip_detect_callback, app); @@ -20,12 +18,25 @@ void avr_isp_scene_chip_detect_on_enter(void* context) { bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; - UNUSED(app); bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case AvrIspCustomEventSceneChipDetectOk: - FURI_LOG_E("FF","DETECL OK"); + FURI_LOG_E("FF", "DETECL OK"); + + if(scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == + AvrIspViewProgrammer) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); + } else if( + scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == + AvrIspViewReader) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneInputName); + } else if( + scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == + AvrIspViewWriter) { + scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); + } + consumed = true; break; default: diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c index 25e5852d7b2..242f9eb13cd 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -6,7 +6,6 @@ void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { } void avr_isp_scene_start_on_enter(void* context) { - UNUSED(context); AvrIspApp* app = context; Submenu* submenu = app->submenu; @@ -48,17 +47,22 @@ bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(app->scene_manager, AvrIspSceneAbout); consumed = true; } else if(event.event == SubmenuIndexAvrIspProgrammer) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneProgrammer); + scene_manager_set_scene_state( + app->scene_manager, AvrIspSceneChipDetect, AvrIspViewProgrammer); + scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); consumed = true; } else if(event.event == SubmenuIndexAvrIspReader) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneInputName); + scene_manager_set_scene_state( + app->scene_manager, AvrIspSceneChipDetect, AvrIspViewReader); + scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); consumed = true; } else if(event.event == SubmenuIndexAvrIspWriter) { - scene_manager_next_scene(app->scene_manager, AvrIspSceneLoad); + scene_manager_set_scene_state( + app->scene_manager, AvrIspSceneChipDetect, AvrIspViewWriter); + scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); consumed = true; } else if(event.event == SubmenuIndexAvrIsWiring) { - //scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); - scene_manager_next_scene(app->scene_manager, AvrIspSceneChipDetect); + scene_manager_next_scene(app->scene_manager, AvrIspSceneWiring); consumed = true; } scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 8809888bd47..0d7a396dc3c 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -8,8 +8,6 @@ struct AvrIspChipDetectView { View* view; AvrIspRW* avr_isp_rw; - const char* file_path; - const char* file_name; AvrIspChipDetectViewCallback callback; void* context; }; @@ -31,15 +29,6 @@ void avr_isp_chip_detect_view_set_callback( instance->context = context; } -void avr_isp_chip_detect_set_file_path( - AvrIspChipDetectView* instance, - const char* file_path, - const char* file_name) { - furi_assert(instance); - instance->file_path = file_path; - instance->file_name = file_name; -} - void avr_isp_chip_detect_set_status( AvrIspChipDetectView* instance, AvrIspChipDetectViewStatus status) { @@ -104,7 +93,17 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { false); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - avr_isp_rw_detect_chip(instance->avr_isp_rw); + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + if(model->status != AvrIspChipDetectViewStatusDetecting) { + model->status = AvrIspChipDetectViewStatusDetecting; + avr_isp_rw_detect_chip(instance->avr_isp_rw); + } + }, + false); + } return true; @@ -117,7 +116,6 @@ static void avr_isp_chip_detect_detect_chip_callback( uint32_t flash_size) { furi_assert(context); AvrIspChipDetectView* instance = context; - with_view_model( instance->view, AvrIspChipDetectViewModel * model, @@ -135,13 +133,13 @@ static void avr_isp_chip_detect_detect_chip_callback( void avr_isp_chip_detect_view_enter(void* context) { furi_assert(context); AvrIspChipDetectView* instance = context; - FURI_LOG_E("FF","1"); + //Start avr_isp_rw instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); -FURI_LOG_E("FF","2"); + avr_isp_rw_set_callback( instance->avr_isp_rw, avr_isp_chip_detect_detect_chip_callback, instance); -FURI_LOG_E("FF","3"); + with_view_model( instance->view, AvrIspChipDetectViewModel * model, @@ -151,8 +149,6 @@ FURI_LOG_E("FF","3"); } }, false); - //avr_isp_rw_detect_chip(instance->avr_isp_rw); - FURI_LOG_E("FF","4"); } void avr_isp_chip_detect_view_exit(void* context) { diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h index d52ff1d1dee..1f1fcd5e21d 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h @@ -10,16 +10,12 @@ typedef void (*AvrIspChipDetectViewCallback)(AvrIspCustomEvent event, void* cont typedef enum { AvrIspChipDetectViewStatusNoDetect, + AvrIspChipDetectViewStatusDetecting, AvrIspChipDetectViewStatusDetected, AvrIspChipDetectViewStatusErrorOccured, AvrIspChipDetectViewStatusErrorVerification, } AvrIspChipDetectViewStatus; -void avr_isp_chip_detect_set_file_path( - AvrIspChipDetectView* instance, - const char* file_path, - const char* file_name); - void avr_isp_chip_detect_view_set_callback( AvrIspChipDetectView* instance, AvrIspChipDetectViewCallback callback, From 793de2bbb65f525be25c951ff73ded28b08e1aa8 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 22 Mar 2023 14:04:06 +0400 Subject: [PATCH 26/50] AVR_ISP: refactoring gui ISP Programmer --- .../avr_isp_programmer/application.fam | 4 +- .../avr_isp_programmer/avr_app_icon_10x10.png | Bin 0 -> 3614 bytes .../external/avr_isp_programmer/avr_isp.png | Bin 143 -> 0 bytes .../avr_isp_programmer/avr_isp_app_i.c | 11 +- .../avr_isp_programmer/helpers/avr_isp_rw.c | 1 + .../helpers/avr_isp_worker.c | 110 ++++++++++-------- .../helpers/avr_isp_worker.h | 12 +- .../images/isp_active_128x64.png | Bin 0 -> 4028 bytes .../scenes/avr_isp_scene_start.c | 17 +-- .../views/avr_isp_view_chip_detect.c | 4 +- .../views/avr_isp_view_programmer.c | 76 ++++-------- .../views/avr_isp_view_programmer.h | 5 + 12 files changed, 106 insertions(+), 134 deletions(-) create mode 100644 applications/external/avr_isp_programmer/avr_app_icon_10x10.png delete mode 100644 applications/external/avr_isp_programmer/avr_isp.png create mode 100644 applications/external/avr_isp_programmer/images/isp_active_128x64.png diff --git a/applications/external/avr_isp_programmer/application.fam b/applications/external/avr_isp_programmer/application.fam index 87ccb4cfb01..19556d03d3a 100644 --- a/applications/external/avr_isp_programmer/application.fam +++ b/applications/external/avr_isp_programmer/application.fam @@ -1,12 +1,12 @@ App( appid="avr_isp", - name="AVR ISP Programmer", + name="AVR Flasher", apptype=FlipperAppType.EXTERNAL, entry_point="avr_isp_app", requires=["gui"], stack_size=4 * 1024, order=20, - fap_icon="avr_isp.png", + fap_icon="avr_app_icon_10x10.png", fap_category="GPIO", fap_icon_assets="images", fap_private_libs=[ diff --git a/applications/external/avr_isp_programmer/avr_app_icon_10x10.png b/applications/external/avr_isp_programmer/avr_app_icon_10x10.png new file mode 100644 index 0000000000000000000000000000000000000000..533787fe3569f70196d3f71e8373102dfd3967a0 GIT binary patch literal 3614 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 Vpqb^9w@m;7?5&;gRaoD1{{|C}E&c!i literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/avr_isp.png b/applications/external/avr_isp_programmer/avr_isp.png deleted file mode 100644 index 2278ce2b61cf97e51720bafb2d07dae48d986560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>@$__Y43U`H zI>D2R!GMF={pJ7tHnyBWw`O@WO=4vXnQOryxnPsm9sxmyCsV>A?tXRt_DY<&Wq)IO q>DB4a%~XFc{Gk)L^WR4G>Gvdb>|Y;BDpm&?%HZkh=d#Wzp$P!!VJ~6; diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c index 4dd2e5b703e..2475ec59a6f 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.c @@ -3,7 +3,6 @@ #define TAG "AvrIsp" #include - bool avr_isp_load_from_file(AvrIspApp* app) { furi_assert(app); @@ -11,12 +10,13 @@ bool avr_isp_load_from_file(AvrIspApp* app) { file_path = furi_string_alloc(); DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, AVR_ISP_APP_EXTENSION, &I_AVR_app_icon_10x10); + dialog_file_browser_set_basic_options( + &browser_options, AVR_ISP_APP_EXTENSION, &I_avr_app_icon_10x10); browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; // Input events and views are managed by file_select - bool res = dialog_file_browser_show( - app->dialogs, app->file_path, app->file_path, &browser_options); + bool res = + dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); // if(res) { // res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); @@ -26,6 +26,3 @@ bool avr_isp_load_from_file(AvrIspApp* app) { return res; } - - - diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c index 4d0d3bb76df..1866800baed 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c @@ -137,6 +137,7 @@ void avr_isp_rw_free(AvrIspRW* instance) { } void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context) { + furi_assert(instance); instance->callback = callback; instance->context = context; } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c index f01b112939b..3438a8d2801 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c @@ -14,21 +14,24 @@ typedef enum { AvrIspWorkerEvtRx = (1 << 1), AvrIspWorkerEvtTxCoplete = (1 << 2), AvrIspWorkerEvtTx = (1 << 3), + AvrIspWorkerEvtState = (1 << 4), - //AvrIspWorkerEvtCfg = (1 << 4), + //AvrIspWorkerEvtCfg = (1 << 5), } AvrIspWorkerEvt; struct AvrIspWorker { FuriThread* thread; volatile bool worker_running; + uint8_t connect_usb; AvrIspWorkerCallback callback; void* context; }; #define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop) -#define AVR_ISP_WORKER_ALL_EVENTS \ - (AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop) +#define AVR_ISP_WORKER_ALL_EVENTS \ + (AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop | \ + AvrIspWorkerEvtState) //########################/* VCP CDC */############################################# #include "usb_cdc.h" @@ -70,7 +73,10 @@ static void vcp_on_cdc_rx(void* context) { static void vcp_state_callback(void* context, uint8_t state) { UNUSED(context); - UNUSED(state); + + AvrIspWorker* instance = context; + instance->connect_usb = state; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtState); } static void vcp_on_cdc_control_line(void* context, uint8_t state) { @@ -116,51 +122,51 @@ static void avr_isp_worker_vcp_cdc_deinit(void) { //################################################################################# -void avr_isp_worker_detect_chip(AvrIspWorker* instance) { - uint8_t buf_cmd[] = { - STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; - - uint8_t buf_data[64] = {0}; - size_t ind = 0; - - FURI_LOG_D(TAG, "Detecting AVR chip"); - AvrIspProg* prog = avr_isp_prog_init(); - avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); - - for(uint8_t i = 0; i < 3; i++) { - avr_isp_prog_avrisp(prog); - } - size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); - UNUSED(len); - - if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { - if(buf_data[3] != 0x1E) { - ind = avr_isp_chip_arr_size + 1; //No detect chip - } else { - for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { - if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; - if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { - if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { - FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); - break; - } - } - } - } - } - avr_isp_prog_free(prog); - if(instance->callback) { - if(ind > avr_isp_chip_arr_size) { - //ToDo add output ID chip - instance->callback(instance->context, "No detect"); - } else if(ind < avr_isp_chip_arr_size) { - instance->callback(instance->context, avr_isp_chip_arr[ind].name); - } else { - //ToDo add output ID chip - instance->callback(instance->context, "Unknown"); - } - } -} +// void avr_isp_worker_detect_chip(AvrIspWorker* instance) { +// uint8_t buf_cmd[] = { +// STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; + +// uint8_t buf_data[64] = {0}; +// size_t ind = 0; + +// FURI_LOG_D(TAG, "Detecting AVR chip"); +// AvrIspProg* prog = avr_isp_prog_init(); +// avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); + +// for(uint8_t i = 0; i < 3; i++) { +// avr_isp_prog_avrisp(prog); +// } +// size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); +// UNUSED(len); + +// if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { +// if(buf_data[3] != 0x1E) { +// ind = avr_isp_chip_arr_size + 1; //No detect chip +// } else { +// for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { +// if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; +// if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { +// if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { +// FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); +// break; +// } +// } +// } +// } +// } +// avr_isp_prog_free(prog); +// if(instance->callback) { +// if(ind > avr_isp_chip_arr_size) { +// //ToDo add output ID chip +// instance->callback(instance->context, "No detect"); +// } else if(ind < avr_isp_chip_arr_size) { +// instance->callback(instance->context, avr_isp_chip_arr[ind].name); +// } else { +// //ToDo add output ID chip +// instance->callback(instance->context, "Unknown"); +// } +// } +// } static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; @@ -231,6 +237,11 @@ static int32_t avr_isp_worker_thread(void* context) { if(events & AvrIspWorkerEvtStop) { break; } + + if(events & AvrIspWorkerEvtState) { + if(instance->callback) + instance->callback(instance->context, (bool)instance->connect_usb); + } } FURI_LOG_D(TAG, "Stop"); furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); @@ -266,7 +277,6 @@ void avr_isp_worker_set_callback( AvrIspWorkerCallback callback, void* context) { furi_assert(instance); - furi_assert(context); instance->callback = callback; instance->context = context; } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h index 82f56c22061..d92e14c44b8 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h @@ -4,7 +4,7 @@ typedef struct AvrIspWorker AvrIspWorker; -typedef void (*AvrIspWorkerCallback)(void* context, const char* name); +typedef void (*AvrIspWorkerCallback)(void* context, bool connect_usb); /** Allocate AvrIspWorker * @@ -48,8 +48,8 @@ void avr_isp_worker_stop(AvrIspWorker* instance); */ bool avr_isp_worker_is_running(AvrIspWorker* instance); -/** Detect chip - * - * @param instance AvrIspWorker instance - */ -void avr_isp_worker_detect_chip(AvrIspWorker* instance); +// /** Detect chip +// * +// * @param instance AvrIspWorker instance +// */ +// void avr_isp_worker_detect_chip(AvrIspWorker* instance); diff --git a/applications/external/avr_isp_programmer/images/isp_active_128x64.png b/applications/external/avr_isp_programmer/images/isp_active_128x64.png new file mode 100644 index 0000000000000000000000000000000000000000..5751f4a0d2ddb8718f03ded87446ee6d9ec14e9f GIT binary patch literal 4028 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 S;`?py^JisdXIg>rjQSs966<0B literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c index 242f9eb13cd..4db8fc42686 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -8,23 +8,14 @@ void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { void avr_isp_scene_start_on_enter(void* context) { AvrIspApp* app = context; Submenu* submenu = app->submenu; - submenu_add_item( - submenu, - "AVR ISP Programmer", - SubmenuIndexAvrIspProgrammer, - avr_isp_scene_start_submenu_callback, - app); + submenu, "Dump AVR", SubmenuIndexAvrIspReader, avr_isp_scene_start_submenu_callback, app); submenu_add_item( - submenu, - "AVR ISP Reader", - SubmenuIndexAvrIspReader, - avr_isp_scene_start_submenu_callback, - app); + submenu, "Flash AVR", SubmenuIndexAvrIspWriter, avr_isp_scene_start_submenu_callback, app); submenu_add_item( submenu, - "AVR ISP Writer", - SubmenuIndexAvrIspWriter, + "ISP Programmer", + SubmenuIndexAvrIspProgrammer, avr_isp_scene_start_submenu_callback, app); submenu_add_item( diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 0d7a396dc3c..bc9604ebd4a 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -103,7 +103,6 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { } }, false); - } return true; @@ -144,7 +143,8 @@ void avr_isp_chip_detect_view_enter(void* context) { instance->view, AvrIspChipDetectViewModel * model, { - if(model->status == AvrIspChipDetectViewStatusNoDetect) { + if(model->status == AvrIspChipDetectViewStatusNoDetect || + model->status == AvrIspChipDetectViewStatusDetected) { avr_isp_rw_detect_chip(instance->avr_isp_rw); } }, diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 08dca9ce512..6fea8e89664 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -1,11 +1,7 @@ #include "avr_isp_view_programmer.h" #include "../avr_isp_app_i.h" -#include #include "../helpers/avr_isp_worker.h" -//#include - -//#include #include struct AvrIspProgrammerView { @@ -16,10 +12,7 @@ struct AvrIspProgrammerView { }; typedef struct { - uint16_t idx; - IconAnimation* icon; - const char* name_chip; - bool detect_chip; + AvrIspProgrammerViewStatus status; } AvrIspProgrammerViewModel; void avr_isp_programmer_view_set_callback( @@ -33,25 +26,16 @@ void avr_isp_programmer_view_set_callback( } void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { - UNUSED(model); canvas_clear(canvas); - // canvas_set_color(canvas, ColorBlack); - // canvas_set_font(canvas, FontSecondary); - canvas_set_font(canvas, FontPrimary); - canvas_draw_icon(canvas, 20, 8, &I_Link_waiting_77x56); - elements_multiline_text(canvas, 20, 10, "Waiting for software\nconnection"); - // canvas_set_font(canvas, FontPrimary); - // canvas_draw_str(canvas, 63, 46, "AVRISPProg"); - // canvas_set_font(canvas, FontSecondary); - - // if(!model->detect_chip) { - // canvas_draw_icon_animation(canvas, 0, 0, model->icon); - // canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); - // canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); - // } else { - // canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); - // canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); - // } + if(model->status == AvrIspProgrammerViewStatusUSBConnect) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_icon(canvas, 0, 0, &I_isp_active_128x64); + elements_multiline_text(canvas, 40, 10, "ISP mode active"); + } else { + canvas_set_font(canvas, FontSecondary); + canvas_draw_icon(canvas, 51, 6, &I_link_waiting_77x56); + elements_multiline_text(canvas, 0, 25, "Waiting for\nsoftware\nconnection"); + } } bool avr_isp_programmer_view_input(InputEvent* event, void* context) { @@ -65,19 +49,22 @@ bool avr_isp_programmer_view_input(InputEvent* event, void* context) { return true; } -static void avr_isp_programmer_detect_chip_callback(void* context, const char* name) { +static void avr_isp_programmer_usb_connect_callback(void* context, bool status_connect) { furi_assert(context); AvrIspProgrammerView* instance = context; with_view_model( instance->view, AvrIspProgrammerViewModel * model, { - model->name_chip = name; - model->detect_chip = true; - icon_animation_stop(model->icon); + if(status_connect) { + model->status = AvrIspProgrammerViewStatusUSBConnect; + } else { + model->status = AvrIspProgrammerViewStatusNoUSBConnect; + } }, true); } + void avr_isp_programmer_view_enter(void* context) { furi_assert(context); AvrIspProgrammerView* instance = context; @@ -85,19 +72,14 @@ void avr_isp_programmer_view_enter(void* context) { with_view_model( instance->view, AvrIspProgrammerViewModel * model, - { - icon_animation_start(model->icon); - model->detect_chip = false; - }, - false); + { model->status = AvrIspProgrammerViewStatusNoUSBConnect; }, + true); //Start worker instance->worker = avr_isp_worker_alloc(instance->context); avr_isp_worker_set_callback( - instance->worker, avr_isp_programmer_detect_chip_callback, instance); - - avr_isp_worker_detect_chip(instance->worker); + instance->worker, avr_isp_programmer_usb_connect_callback, instance); avr_isp_worker_start(instance->worker); } @@ -109,13 +91,8 @@ void avr_isp_programmer_view_exit(void* context) { if(avr_isp_worker_is_running(instance->worker)) { avr_isp_worker_stop(instance->worker); } + avr_isp_worker_set_callback(instance->worker, NULL, NULL); avr_isp_worker_free(instance->worker); - - with_view_model( - instance->view, - AvrIspProgrammerViewModel * model, - { icon_animation_stop(model->icon); }, - false); } AvrIspProgrammerView* avr_isp_programmer_view_alloc() { @@ -134,11 +111,7 @@ AvrIspProgrammerView* avr_isp_programmer_view_alloc() { with_view_model( instance->view, AvrIspProgrammerViewModel * model, - { - model->icon = icon_animation_alloc(&A_ChipLooking_64x64); - view_tie_icon_animation(instance->view, model->icon); - model->detect_chip = false; - }, + { model->status = AvrIspProgrammerViewStatusNoUSBConnect; }, false); return instance; } @@ -146,11 +119,6 @@ AvrIspProgrammerView* avr_isp_programmer_view_alloc() { void avr_isp_programmer_view_free(AvrIspProgrammerView* instance) { furi_assert(instance); - with_view_model( - instance->view, - AvrIspProgrammerViewModel * model, - { icon_animation_free(model->icon); }, - false); view_free(instance->view); free(instance); } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h index b467f0a2300..9f005b026a2 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h @@ -8,6 +8,11 @@ typedef struct AvrIspProgrammerView AvrIspProgrammerView; typedef void (*AvrIspProgrammerViewCallback)(AvrIspCustomEvent event, void* context); +typedef enum { + AvrIspProgrammerViewStatusNoUSBConnect, + AvrIspProgrammerViewStatusUSBConnect, +} AvrIspProgrammerViewStatus; + void avr_isp_programmer_view_set_callback( AvrIspProgrammerView* instance, AvrIspProgrammerViewCallback callback, From 9c95bb1a64914042c903dc8c99e1a4c5c0d67c80 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 22 Mar 2023 23:38:52 +0400 Subject: [PATCH 27/50] AVR_ISP: add gui "Dump AVR" --- .../external/avr_isp_programmer/avr_isp_app.c | 10 +- .../avr_isp_programmer/avr_isp_app_i.h | 2 + .../helpers/avr_isp_event.h | 5 + .../avr_isp_programmer/helpers/avr_isp_rw.h | 37 -- .../helpers/avr_isp_types.h | 1 + .../helpers/avr_isp_worker.c | 3 +- .../{avr_isp_rw.c => avr_isp_worker_rw.c} | 483 +++++++++++++++--- .../helpers/avr_isp_worker_rw.h | 92 ++++ .../helpers/flipper_i32hex_file.c | 2 + .../images/DolphinNice_96x59.png | Bin 0 -> 2459 bytes .../images/chip_error_70x22.png | Bin 3673 -> 3688 bytes .../images/chip_long_70x22.png | Bin 3649 -> 3656 bytes ...ve_128x64.png => chip_not_found_83x37.png} | Bin 4028 -> 3779 bytes .../images/isp_active_128x53.png | Bin 0 -> 3961 bytes .../scenes/avr_isp_scene_chip_detect.c | 1 - .../scenes/avr_isp_scene_config.h | 2 +- .../scenes/avr_isp_scene_reader.c | 11 +- .../scenes/avr_isp_scene_success.c | 52 ++ .../views/avr_isp_view_chip_detect.c | 20 +- .../views/avr_isp_view_programmer.c | 2 +- .../views/avr_isp_view_reader.c | 195 ++++--- .../views/avr_isp_view_reader.h | 8 + .../views/avr_isp_view_writer.c | 24 +- 23 files changed, 754 insertions(+), 196 deletions(-) delete mode 100644 applications/external/avr_isp_programmer/helpers/avr_isp_rw.h rename applications/external/avr_isp_programmer/helpers/{avr_isp_rw.c => avr_isp_worker_rw.c} (59%) create mode 100644 applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h create mode 100644 applications/external/avr_isp_programmer/images/DolphinNice_96x59.png rename applications/external/avr_isp_programmer/images/{isp_active_128x64.png => chip_not_found_83x37.png} (71%) create mode 100644 applications/external/avr_isp_programmer/images/isp_active_128x53.png create mode 100644 applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index e3254949c4a..2ab154b9933 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -68,6 +68,10 @@ AvrIspApp* avr_isp_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, AvrIspViewTextInput, text_input_get_view(app->text_input)); + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view(app->view_dispatcher, AvrIspViewPopup, popup_get_view(app->popup)); + //Dialog app->dialogs = furi_record_open(RECORD_DIALOGS); @@ -91,7 +95,7 @@ AvrIspApp* avr_isp_app_alloc() { app->view_dispatcher, AvrIspViewWriter, avr_isp_writer_view_get_view(app->avr_isp_writer_view)); - + // Chip detect view app->avr_isp_chip_detect_view = avr_isp_chip_detect_view_alloc(); view_dispatcher_add_view( @@ -123,6 +127,10 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewTextInput); text_input_free(app->text_input); + // Popup + view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewPopup); + popup_free(app->popup); + //Dialog furi_record_close(RECORD_DIALOGS); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h index edc2c7c6978..474b1fa46a0 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.h @@ -13,6 +13,7 @@ #include #include #include +#include //#include #include "views/avr_isp_view_programmer.h" @@ -28,6 +29,7 @@ typedef struct { SceneManager* scene_manager; NotificationApp* notifications; DialogsApp* dialogs; + Popup* popup; //VariableItemList* variable_item_list; Submenu* submenu; Widget* widget; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index 3554ea3b5bb..365c1a3ccad 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -10,5 +10,10 @@ typedef enum { //AvrIspCustomEvent AvrIspCustomEventSceneChipDetectOk = 100, + AvrIspCustomEventSceneReadingOk, + AvrIspCustomEventSceneErrorVerification, + AvrIspCustomEventSceneErrorReading, + AvrIspCustomEventSceneErrorWriting, AvrIspCustomEventSceneInputName, + AvrIspCustomEventSceneSuccess, } AvrIspCustomEvent; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h deleted file mode 100644 index 9b45d302468..00000000000 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include - -typedef struct AvrIspRW AvrIspRW; - -typedef void (*AvrIspRWCallback)(void* context, const char* name, bool detect_chip, uint32_t flash_size); - -/** Allocate AvrIspRW - * - * @param context AvrIsp* context - * @return AvrIspRW* - */ -AvrIspRW* avr_isp_rw_alloc(void* context); - -/** Free AvrIspRW - * - * @param instance AvrIspRW instance - */ -void avr_isp_rw_free(AvrIspRW* instance); - -/** Callback AvrIspRW - * - * @param instance AvrIspRW instance - * @param callback AvrIspRWOverrunCallback callback - * @param context - */ -void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context); - -/** Detect chip - * - * @param instance AvrIspRW instance - * @return bool - */ -bool avr_isp_rw_detect_chip(AvrIspRW* instance); - -bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* file_name); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h index 8c9e9c4404d..5853239ba8e 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h @@ -18,6 +18,7 @@ typedef enum { AvrIspViewReader, AvrIspViewWriter, AvrIspViewWidget, + AvrIspViewPopup, AvrIspViewTextInput, AvrIspViewChipDetect, } AvrIspView; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c index 3438a8d2801..238e225b472 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c @@ -267,7 +267,8 @@ AvrIspWorker* avr_isp_worker_alloc(void* context) { void avr_isp_worker_free(AvrIspWorker* instance) { furi_assert(instance); - + + furi_check(!instance->worker_running); furi_thread_free(instance->thread); free(instance); } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c similarity index 59% rename from applications/external/avr_isp_programmer/helpers/avr_isp_rw.c rename to applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 1866800baed..346c79ffce2 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -1,4 +1,5 @@ -#include "avr_isp_rw.h" +#include "avr_isp_worker_rw.h" +#include #include "avr_isp_types.h" #include "avr_isp.h" #include "../lib/driver/avr_isp_prog_cmd.h" @@ -9,10 +10,12 @@ #include -#define TAG "AvrIspRW" +#define TAG "AvrIspWorkerRW" -struct AvrIspRW { +struct AvrIspWorkerRW { AvrIsp* avr_isp; + FuriThread* thread; + volatile bool worker_running; uint32_t chip_arr_ind; bool chip_detect; @@ -20,17 +23,99 @@ struct AvrIspRW { uint8_t hfuse; uint8_t efuse; uint8_t lock; + float progress_flash; + float progress_eeprom; + const char* file_path; + const char* file_name; AvrIspSignature signature; - AvrIspRWCallback callback; + AvrIspWorkerRWCallback callback; void* context; + + AvrIspWorkerRWStatusCallback callback_status; + void* context_status; }; -bool avr_isp_rw_detect_chip(AvrIspRW* instance) { +typedef enum { + AvrIspWorkerRWEvtStop = (1 << 0), + + AvrIspWorkerRWEvtReading = (1 << 1), + AvrIspWorkerRWEvtVerification = (1 << 2), + AvrIspWorkerRWEvtWriting = (1 << 3), + +} AvrIspWorkerRWEvt; +#define AVR_ISP_WORKER_ALL_EVENTS \ + (AvrIspWorkerRWEvtWriting | AvrIspWorkerRWEvtVerification | AvrIspWorkerRWEvtReading | \ + AvrIspWorkerRWEvtStop) + +/** Worker thread + * + * @param context + * @return exit code + */ +static int32_t avr_isp_worker_rw_thread(void* context) { + AvrIspWorkerRW* instance = context; + + /* start PWM on &gpio_ext_pa4 */ + furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); + + FURI_LOG_D(TAG, "Start"); + while(1) { + uint32_t events = + furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); + + if(events & AvrIspWorkerRWEvtStop) { + break; + } + + if(events & AvrIspWorkerRWEvtWriting) { + // if(avr_isp_worker_rw_get_dump(instance, instance->file_path, instance->file_name)) { + // if(instance->callback_status) + // instance->callback_status( + // instance->context_status, AvrIspWorkerRWStatusEndWriting); + // } else { + // if(instance->callback_status) + // instance->callback_status( + // instance->context_status, AvrIspWorkerRWStatusErrorWriting); + // } + } + + if(events & AvrIspWorkerRWEvtVerification) { + if(avr_isp_worker_rw_verification(instance, instance->file_path, instance->file_name)) { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusEndVerification); + } else { + if(instance->callback_status) + instance->callback_status(instance->context_status, AvrIspWorkerRWStatusErrorVerification); + } + } + + if(events & AvrIspWorkerRWEvtReading) { + if(avr_isp_worker_rw_get_dump(instance, instance->file_path, instance->file_name)) { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusEndReading); + } else { + if(instance->callback_status) + instance->callback_status(instance->context_status, AvrIspWorkerRWStatusErrorReading); + } + } + } + FURI_LOG_D(TAG, "Stop"); + + furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); + + return 0; +} + +bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { furi_assert(instance); FURI_LOG_D(TAG, "Detecting AVR chip"); instance->chip_detect = false; instance->chip_arr_ind = avr_isp_chip_arr_size + 1; - //uint8_t data[10]; + + /* start PWM on &gpio_ext_pa4 */ + furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); do { if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { @@ -92,6 +177,8 @@ bool avr_isp_rw_detect_chip(AvrIspRW* instance) { } avr_isp_end_pmode(instance->avr_isp); + furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); + } while(0); if(instance->callback) { if(instance->chip_arr_ind > avr_isp_chip_arr_size) { @@ -113,40 +200,94 @@ bool avr_isp_rw_detect_chip(AvrIspRW* instance) { return instance->chip_detect; } -AvrIspRW* avr_isp_rw_alloc(void* context) { +AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context) { furi_assert(context); UNUSED(context); - AvrIspRW* instance = malloc(sizeof(AvrIspRW)); + AvrIspWorkerRW* instance = malloc(sizeof(AvrIspWorkerRW)); instance->avr_isp = avr_isp_alloc(); + instance->thread = + furi_thread_alloc_ex("AvrIspWorkerRW", 4096, avr_isp_worker_rw_thread, instance); + instance->chip_detect = false; instance->lfuse = 0; instance->hfuse = 0; instance->efuse = 0; instance->lock = 0; + instance->progress_flash = 0.0f; + instance->progress_eeprom = 0.0f; return instance; } -void avr_isp_rw_free(AvrIspRW* instance) { +void avr_isp_worker_rw_free(AvrIspWorkerRW* instance) { furi_assert(instance); avr_isp_free(instance->avr_isp); + furi_check(!instance->worker_running); + furi_thread_free(instance->thread); + free(instance); } -void avr_isp_rw_set_callback(AvrIspRW* instance, AvrIspRWCallback callback, void* context) { +void avr_isp_worker_rw_start(AvrIspWorkerRW* instance) { + furi_assert(instance); + furi_assert(!instance->worker_running); + + instance->worker_running = true; + + furi_thread_start(instance->thread); +} + +void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance) { + furi_assert(instance); + furi_assert(instance->worker_running); + + instance->worker_running = false; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtStop); + + furi_thread_join(instance->thread); +} + +bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance) { + furi_assert(instance); + return instance->worker_running; +} + +void avr_isp_worker_rw_set_callback( + AvrIspWorkerRW* instance, + AvrIspWorkerRWCallback callback, + void* context) { furi_assert(instance); instance->callback = callback; instance->context = context; } -void avr_isp_rw_get_dump_flash(AvrIspRW* instance, const char* file_path) { +void avr_isp_worker_rw_set_callback_status( + AvrIspWorkerRW* instance, + AvrIspWorkerRWStatusCallback callback_status, + void* context_status) { + furi_assert(instance); + instance->callback_status = callback_status; + instance->context_status = context_status; +} + +float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance) { + furi_assert(instance); + return instance->progress_flash; +} + +float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance) { + furi_assert(instance); + return instance->progress_eeprom; +} + +void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); - FURI_LOG_D(TAG, "Dump FLASH"); + FURI_LOG_D(TAG, "Dump FLASH %s", file_path); FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_write( file_path, avr_isp_chip_arr[instance->chip_arr_ind].flashoffset); @@ -165,17 +306,20 @@ void avr_isp_rw_get_dump_flash(AvrIspRW* instance, const char* file_path) { flipper_i32hex_file_bin_to_i32hex_set_data( flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + instance->progress_flash = + (float)i / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); flipper_i32hex_file_close(flipper_hex_flash); + instance->progress_flash = 1.0f; } -void avr_isp_rw_get_dump_eeprom(AvrIspRW* instance, const char* file_path) { +void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); - FURI_LOG_D(TAG, "Dump EEPROM"); + FURI_LOG_D(TAG, "Dump EEPROM %s", file_path); FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( file_path, avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); @@ -191,24 +335,31 @@ void avr_isp_rw_get_dump_eeprom(AvrIspRW* instance, const char* file_path) { instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); + instance->progress_eeprom = (float)i / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); flipper_i32hex_file_close(flipper_hex_eeprom); + instance->progress_eeprom = 1.0f; } -bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* file_name) { +bool avr_isp_worker_rw_get_dump( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { furi_assert(instance); furi_assert(file_path); furi_assert(file_name); FURI_LOG_D(TAG, "Read dump chip"); + instance->progress_flash = 0.0f; + instance->progress_eeprom = 0.0f; bool ret = false; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); FuriString* file_path_name = furi_string_alloc(); - if(!avr_isp_rw_detect_chip(instance)) { + if(!avr_isp_worker_rw_detect_chip(instance)) { FURI_LOG_E(TAG, "No detect AVR chip"); } else { do { @@ -289,11 +440,11 @@ bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { //Dump flash furi_string_printf(file_path_name, "%s/%s_flash.hex", file_path, file_name); - avr_isp_rw_get_dump_flash(instance, furi_string_get_cstr(file_path_name)); + avr_isp_worker_rw_get_dump_flash(instance, furi_string_get_cstr(file_path_name)); //Dump eeprom if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { furi_string_printf(file_path_name, "%s/%s_eeprom.hex", file_path, file_name); - avr_isp_rw_get_dump_eeprom(instance, furi_string_get_cstr(file_path_name)); + avr_isp_worker_rw_get_dump_eeprom(instance, furi_string_get_cstr(file_path_name)); } avr_isp_end_pmode(instance->avr_isp); @@ -305,7 +456,200 @@ bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* return true; } -// bool avr_isp_rw_rx1(AvrIspRW* instance) { +void avr_isp_worker_rw_get_dump_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtReading); +} + +bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* file_path) { + furi_assert(instance); + furi_assert(file_path); + + FURI_LOG_D(TAG, "Verification flash %s", file_path); + instance->progress_flash = 0.0; + bool ret = true; + + FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); + + uint8_t data_read_flash[272] = {0}; + uint8_t data_read_hex[272] = {0}; + + uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + + FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); + + if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && + ret) { + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_hex[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + avr_isp_read_page( + instance->avr_isp, + STK_SET_FLASH_TYPE, + addr, + flipper_hex_ret.data_size, + data_read_flash, + sizeof(data_read_flash)); + + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_flash[i]); + // } + // printf("\r\n"); + + if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { + ret = false; + FURI_LOG_E(TAG, "Verification flash error"); + } + + addr += flipper_hex_ret.data_size / 2; + instance->progress_flash = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + break; + + case FlipperI32HexFileStatusUdateAddr: + addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16) / 2; + break; + + default: + furi_crash(TAG " Incorrect status."); + break; + } + + flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); + } + + avr_isp_end_pmode(instance->avr_isp); + } + flipper_i32hex_file_close(flipper_hex_flash); + instance->progress_flash = 1.0f; + + return ret; +} + +bool avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* file_path) { + furi_assert(instance); + furi_assert(file_path); + + FURI_LOG_D(TAG, "Verification eeprom %s", file_path); + instance->progress_eeprom = 0.0; + bool ret = true; + + FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_read(file_path); + + uint8_t data_read_eeprom[272] = {0}; + uint8_t data_read_hex[272] = {0}; + + uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; + + FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); + + if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && + ret) { + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_hex[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + avr_isp_read_page( + instance->avr_isp, + STK_SET_EEPROM_TYPE, + addr, + flipper_hex_ret.data_size, + data_read_eeprom, + sizeof(data_read_eeprom)); + + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_eeprom[i]); + // } + // printf("\r\n"); + + if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { + ret = false; + FURI_LOG_E(TAG, "Verification eeprom error"); + } + + addr += flipper_hex_ret.data_size; + instance->progress_flash = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + break; + + case FlipperI32HexFileStatusUdateAddr: + addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16); + break; + + default: + furi_crash(TAG " Incorrect status."); + break; + } + + flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); + } + + avr_isp_end_pmode(instance->avr_isp); + } + flipper_i32hex_file_close(flipper_hex_eeprom); + instance->progress_eeprom = 1.0f; + + return ret; +} + +bool avr_isp_worker_rw_verification( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + furi_assert(file_path); + furi_assert(file_name); + + instance->progress_flash = 0.0f; + instance->progress_eeprom = 0.0f; + char str_buf[64] = {0}; + bool ret = false; + + do { + snprintf( + str_buf, sizeof(str_buf), "%s/%s_flash.hex", instance->file_path, instance->file_name); + if(!avr_isp_worker_rw_verification_flash(instance, str_buf)) break; + snprintf( + str_buf, sizeof(str_buf), "%s/%s_eeprom.hex", instance->file_path, instance->file_name); + + if(!avr_isp_worker_rw_verification_eeprom(instance, str_buf)) break; + ret = true; + } while(false); + + return ret; +} + +void avr_isp_worker_rw_verification_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtVerification); +} + +// bool avr_isp_worker_rw_rx1(AvrIspWorkerRW* instance) { // furi_assert(instance); // uint8_t data[256]; @@ -466,61 +810,60 @@ bool avr_isp_rw_get_dump(AvrIspRW* instance, const char* file_path, const char* // // avr_isp_erase_chip(instance->avr_isp); // // //################################################################## -// // //########################################################## -// // FURI_LOG_D(TAG, "FLASH WRITE"); - -// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { -// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); -// // break; -// // } -// // avr_isp_read_signature(instance->avr_isp, data); - -// // FlipperI32HexFile* flipper_hex_flash = -// // flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); - -// // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; -// // FlipperI32HexFileRet flipper_hex_ret = -// // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); -// // FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); -// // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || -// // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { -// // // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); -// // // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { -// // // printf("%02X ", data[i]); -// // // } -// // // printf("\r\n"); - -// // switch(flipper_hex_ret.status) { -// // case FlipperI32HexFileStatusData: -// // if(!avr_isp_write_page( -// // instance->avr_isp, -// // STK_SET_FLASH_TYPE, -// // avr_isp_chip_arr[instance->chip_arr_ind].flashsize, -// // addr, -// // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, -// // data, -// // flipper_hex_ret.data_size)) { -// // break; -// // } -// // addr += flipper_hex_ret.data_size/2; -// // break; +// //########################################################## +// FURI_LOG_D(TAG, "FLASH WRITE"); + +// if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { +// FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); +// break; +// } +// avr_isp_read_signature(instance->avr_isp, data); + +// FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); + +// uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; +// FlipperI32HexFileRet flipper_hex_ret = +// flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); +// FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); +// while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || +// (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { +// // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); +// // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { +// // printf("%02X ", data[i]); +// // } +// // printf("\r\n"); + +// switch(flipper_hex_ret.status) { +// case FlipperI32HexFileStatusData: +// if(!avr_isp_write_page( +// instance->avr_isp, +// STK_SET_FLASH_TYPE, +// avr_isp_chip_arr[instance->chip_arr_ind].flashsize, +// addr, +// avr_isp_chip_arr[instance->chip_arr_ind].pagesize, +// data, +// flipper_hex_ret.data_size)) { +// break; +// } +// addr += flipper_hex_ret.data_size / 2; +// break; -// // case FlipperI32HexFileStatusUdateAddr: -// // addr = data[0] << 24 | data[1] << 16; -// // break; +// case FlipperI32HexFileStatusUdateAddr: +// addr = data[0] << 24 | data[1] << 16; +// break; -// // default: -// // furi_crash(TAG " Incorrect status."); -// // break; -// // } +// default: +// furi_crash(TAG " Incorrect status."); +// break; +// } -// // flipper_hex_ret = -// // flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); -// // } +// flipper_hex_ret = +// flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); +// } -// // flipper_i32hex_file_close(flipper_hex_flash); -// // avr_isp_end_pmode(instance->avr_isp); -// //########################################################## +// flipper_i32hex_file_close(flipper_hex_flash); +// avr_isp_end_pmode(instance->avr_isp); +// ########################################################## // // FURI_LOG_D(TAG, "CHECK HEX"); // // FlipperI32HexFile* flipper_hex_eeprom_read = diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h new file mode 100644 index 00000000000..7a4348d4ee0 --- /dev/null +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h @@ -0,0 +1,92 @@ +#pragma once + +#include + +typedef struct AvrIspWorkerRW AvrIspWorkerRW; + +typedef void (*AvrIspWorkerRWCallback)( + void* context, + const char* name, + bool detect_chip, + uint32_t flash_size); + +typedef enum { + AvrIspWorkerRWStatusILDE = 0, + AvrIspWorkerRWStatusEndReading = 1, + AvrIspWorkerRWStatusEndVerification = 2, + AvrIspWorkerRWStatusEndWritin = 3, + + AvrIspWorkerRWStatusErrorReading = (-1), + AvrIspWorkerRWStatusErrorVerification = (-2), + AvrIspWorkerRWStatusErrorWritin = (-3), + + AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. +} AvrIspWorkerRWStatus; + +typedef void (*AvrIspWorkerRWStatusCallback)(void* context, AvrIspWorkerRWStatus status); + +/** Allocate AvrIspWorkerRW + * + * @param context AvrIsp* context + * @return AvrIspWorkerRW* + */ +AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context); + +/** Free AvrIspWorkerRW + * + * @param instance AvrIspWorkerRW instance + */ +void avr_isp_worker_rw_free(AvrIspWorkerRW* instance); + +void avr_isp_worker_rw_start(AvrIspWorkerRW* instance); + +void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance); + +bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance); + +/** Callback AvrIspWorkerRW + * + * @param instance AvrIspWorkerRW instance + * @param callback AvrIspWorkerRWOverrunCallback callback + * @param context + */ +void avr_isp_worker_rw_set_callback( + AvrIspWorkerRW* instance, + AvrIspWorkerRWCallback callback, + void* context); + +void avr_isp_worker_rw_set_callback_status( + AvrIspWorkerRW* instance, + AvrIspWorkerRWStatusCallback callback_status, + void* context_status); + +/** Detect chip + * + * @param instance AvrIspWorkerRW instance + * @return bool + */ +bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance); + +float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance); + +float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance); + +bool avr_isp_worker_rw_get_dump( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +void avr_isp_worker_rw_get_dump_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +bool avr_isp_worker_rw_verification( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +void avr_isp_worker_rw_verification_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c index 8ead2fbf3b0..69f2782ea2e 100644 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -36,6 +36,7 @@ FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t sta if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { instance->file_open = FlipperI32HexFileStatusOpenFileWrite; + FURI_LOG_D(TAG, "Open write file %s", name); } else { FURI_LOG_E(TAG, "Failed to open file %s", name); instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; @@ -56,6 +57,7 @@ FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) { instance->file_open = FlipperI32HexFileStatusOpenFileRead; + FURI_LOG_D(TAG, "Open read file %s", name); } else { FURI_LOG_E(TAG, "Failed to open file %s", name); instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile; diff --git a/applications/external/avr_isp_programmer/images/DolphinNice_96x59.png b/applications/external/avr_isp_programmer/images/DolphinNice_96x59.png new file mode 100644 index 0000000000000000000000000000000000000000..a299d3630239b4486e249cc501872bed5996df3b GIT binary patch literal 2459 zcmbVO3s4i+8V(M(gEFORwSrA`4O0uPn|M|5y* zB*aMDxC&7(gP9JN;POOi-9khrC>Z9YJs2U!LnVcQEEC0fDtKo&ILlzb30%M}3J^;~ zv7RzcsilOs4Mq@tD*&R;!LMSk2A~{(`HK9|hQBqEX)3sQr9Je6SZU*F-^fD-p+~Hs; zHLkO%v?>ZoxEv+F#whudr%615FkA0DYR0tMEo}3OOY#xecLWe>xV?u5KtSmC^ z7)Fmj6gjfKstiEV-*Cxbbb+&rRWuI_rBJ)ybs_f1Rn&f2>q3pYwI^|J(hdn{j{0EZIm_F zpIyIWLsRUgOItR-dUbVd|6Zo=_BU_Tj4|{{jxO#=JH4o8er(5{!nZD_j4}MH&zh~9 zVLC~y(0-D6GO0ghZD8BYzP?o{>22~lT6^d@X{SwQ8vrNY-PPIMajIwC)`s14Ep72@ zeq7YOzM`?U{+W)ocXBr`eSOcpk?Rxc=ou5&)fWW|pD};-Z0mvk9}=&`Rb&y<77W~a z(>6YM;6Y5aIU~JKZ}mQZynKHiSTQ#Bczn@&jTiN^?vPJ(jhm7cXLx0oum5P$`TceG zU+wR;OO^)8CVlnM)5p$CO&e94KJt>HccCaHGusmW_b`T6m| z-R6V6Db1pErTot?^d22ojm+2>_)FbD`_+WbDGMx9f@hO27maS2`csiV(D&Fs`PS2& zvrq18du_&zXID(!KIxsU$)iuTYuZ?zmYiP&n&i@Be{IdbS-jA2c0QAlu5NXQv_0K< z3Hvs4eeu6B7yD&CNT~gIkMV&UkRU=V!iQ(+_(O&u^ah$+s{_yn(yBYeD40HeU{xGsIT6W Zfq!wOp!Qwb z?FL>zUaF^yV@SoVJ0Yj}4k++6{r{i2`RohcSyOb5$-Qb-s12B)aGSIJBE$L1J|3*h ziLAans#&7y0=ru$xqYrV+z_68s%q+mkaw90TmP(Bc2D~5qgPALxIf*?DWRm8-ZsJ5 hxc$*FWh)j528V-8v6CYX-vrvo;OXk;vd$@?2>=b0YOMeO delta 303 zcmaDMb5mx+Tpk5O6GvwYCo>CY0|Ns?Lsu6k6LU9LQ$r&|S3@^fLs#R;dwFDFiY##| z`pILUU~XybV(Dz|=H%w)hSelbUKyw&3j>^rT6vx7{fdO=GB7Z(1^9%x0_p$%|1Z5c z|1OY~;_2cTQgQ1{$Z0+X1&*fw|6g89E@j>xak@EHW?_edW1RYugob}H%S3#%Bsjb? zt_Fm?edcmB(CJXdoRyk3(wDC#I9=Y^-uU#>1m9Y-sw1IG&$vI`%PFCl-ZsH_|1R_R eyN}ckFiaJ`#iSZDX+kT|LIzJ)KbLh*2~7a&UuHc3 diff --git a/applications/external/avr_isp_programmer/images/chip_long_70x22.png b/applications/external/avr_isp_programmer/images/chip_long_70x22.png index bd6bb920ae4e213876a141042c655d9d4c624dae..3edfff82de952d6f49a012154a23104e3fd935fa 100644 GIT binary patch delta 286 zcmX>ob3$grTpk5yLjx0IOH(6f150N^Lsu6^11A$FH$xXwS7SpbH)DgzdwFDFii~k8 z`pIJeQ)GZsktZ+QBtx8vT6vx7HO$NIGB7Z(1^9%x0_p$%|1Z5cA0)z5666>BpW*3t z11})Y)zif>q~camLP|q}JIN7oo-Lx7U(|MS!x=Z%E wPjvDM;UkBQe+H_j2Q6P9(buZs(7?#hslk%}j>$I$Xdr{9tDnm{C#HlZ0A!m}yZ`_I delta 278 zcmX>hb5Lf(Tpk5;OJf&HXLA=PH#av!Lsu6k6LU9LQ$r&|S3@^fLs#R;dwFDFid=Cj z`pIJeQ{;qGktZ+QBxjt8T6vwSHb436$-uzC7T^=&`v3obAT#vP~ijTaH&LbgW|`P2Obw)3O@BV sQCm&;ndS0*dHmW~Nv<8yc7xTbepL8(2C|-p3FxipUfCp-l z1=J)ltKyQN)HJIUEapL#T7r~fHSa2~Q@z>2DQAHGVhivIaRt)<|NmclbN*c*i>V~Y zFZe&h)9nUcK;8jQ7srr_TYIiPQM)`T)^<+bxrHlnOoYf7G1hks`e!9*VQ|BmG93#$Ft?na~tO89lmqyX0yMWAY6WTqIKk_ zGKNRy>*lU}q`OV2{p_;4vb*xlY`s?;`?BIh$%<1cA!$OZjJ35)xL29P2W3gEG<_@Q glk`PQpOKA0*NM~g-=q6$fu3RTboFyt=akR{0Hsd3RsaA1 delta 687 zcmX>syGLHJGr-TCmrII^fq{Y7)59eQNH+kn0|zsZe9F=9yHT-{i?L$!Y%VRv$?v#R zChz0cbSd!lwel~@OwY_q%yG$2F3nBNEAe!(RjSA>&`Zfou`;nVOf^qQwA8h*G&9mQ zF*8ZkO|&qv&`mM7OioTUO*TnQN}9ZvM~273)zQh^%+1Kzz|3rNA+PAvfD)!)34b2r$-j8?RT2#ijM5AY&2^Jf%q?_HObyd?6U~y$bQ2BIj7$^F zEt5=>%_e*D%BT?KhE`su`ry#T%|O4h1^9%x{{R0U$P7JnxsHK>vE0+eF{I+wn;EbB zjwo=nTE72(X}0h3$8Qt3h0dlG{=4Bhh5yMSj#B~?zh$3Z!D1R@&LlGTb|sSx!vtl9 zTLP9{3ZMEJ?B)gh>r3=F3um=>@cvpvhP_TP-X^$KtE{iGRG8xrT=cjrCB zviDzv3Bw+SISg{^x2=`>dR(f(bWZ2L(`UK(8=N+rWU@M_#{GgtkKw?>EprZhjWBzb z;rnYZS0I~#@P`@iep{ygt6(x?(h%G6Z!zyVzJv`{N1PT!JeYQ0rb2xk!xkRlHghA;k<{R>|XhJ)&prhm4)ATt7fY^oN?BcI^ZgB>-i56(Flzg>undC o7PD_y?EJ_-cQxmG_Xb9WetVXzXuhm(z{p_mboFyt=akR{0KSU?*#H0l diff --git a/applications/external/avr_isp_programmer/images/isp_active_128x53.png b/applications/external/avr_isp_programmer/images/isp_active_128x53.png new file mode 100644 index 0000000000000000000000000000000000000000..843792123c844788cf84662284cfb0d6b65eff14 GIT binary patch literal 3961 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 B&F}yK literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index 3e456381b59..f96ecca8dcc 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -22,7 +22,6 @@ bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case AvrIspCustomEventSceneChipDetectOk: - FURI_LOG_E("FF", "DETECL OK"); if(scene_manager_get_scene_state(app->scene_manager, AvrIspSceneChipDetect) == AvrIspViewProgrammer) { diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h index 338a7f1e37a..6f22511dbe2 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h @@ -7,4 +7,4 @@ ADD_SCENE(avr_isp, load, Load) ADD_SCENE(avr_isp, writer, Writer) ADD_SCENE(avr_isp, wiring, Wiring) ADD_SCENE(avr_isp, chip_detect, ChipDetect) - +ADD_SCENE(avr_isp, success, Success) diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c index 9d9eb35721f..1b57cbeb82a 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -12,8 +12,7 @@ void avr_isp_scene_reader_on_enter(void* context) { avr_isp_reader_set_file_path( app->avr_isp_reader_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); - avr_isp_reader_view_set_callback( - app->avr_isp_reader_view, avr_isp_scene_reader_callback, app); + avr_isp_reader_view_set_callback(app->avr_isp_reader_view, avr_isp_scene_reader_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader); } @@ -24,13 +23,15 @@ bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - // case WSCustomEventViewreaderBack: - // consumed = true; - // break; + case AvrIspCustomEventSceneReadingOk: + scene_manager_next_scene(app->scene_manager, AvrIspSceneSuccess); + consumed = true; + break; default: break; } } else if(event.type == SceneManagerEventTypeTick) { + avr_isp_reader_update_progress(app->avr_isp_reader_view); } return consumed; } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c new file mode 100644 index 00000000000..392ed1e9f19 --- /dev/null +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c @@ -0,0 +1,52 @@ +#include "../avr_isp_app_i.h" +#include "../views/avr_isp_view_programmer.h" + +void avr_isp_scene_success_popup_callback(void* context) { + AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneSuccess); +} + +void avr_isp_scene_success_on_enter(void* context) { + AvrIspApp* app = context; + + // Setup view + Popup* popup = app->popup; + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, app); + popup_set_callback(popup, avr_isp_scene_success_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewPopup); +} + +bool avr_isp_scene_success_on_event(void* context, SceneManagerEvent event) { + AvrIspApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == AvrIspCustomEventSceneSuccess) { + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneStart); + // if(!scene_manager_search_and_switch_to_previous_scene( + // app -> scene_manager, AvrIspSceneReceiver)) { + // app -> txrx->rx_key_state = AvrIspRxKeyStateRAWSave; + // if(!scene_manager_search_and_switch_to_previous_scene( + // app -> scene_manager, AvrIspSceneReadRAW)) { + // app -> txrx->rx_key_state = AvrIspRxKeyStateIDLE; + // if(!scene_manager_search_and_switch_to_previous_scene( + // app -> scene_manager, AvrIspSceneSaved)) { + // scene_manager_next_scene(app -> scene_manager, AvrIspSceneSaved); + // } + // } + // } + return true; + } + } + return false; +} + +void avr_isp_scene_success_on_exit(void* context) { + AvrIspApp* app = context; + Popup* popup = app->popup; + + popup_reset(popup); +} diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index bc9604ebd4a..4efc2b59b90 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -3,11 +3,11 @@ #include #include -#include "../helpers/avr_isp_rw.h" +#include "../helpers/avr_isp_worker_rw.h" struct AvrIspChipDetectView { View* view; - AvrIspRW* avr_isp_rw; + AvrIspWorkerRW* avr_isp_worker_rw; AvrIspChipDetectViewCallback callback; void* context; }; @@ -99,7 +99,7 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { { if(model->status != AvrIspChipDetectViewStatusDetecting) { model->status = AvrIspChipDetectViewStatusDetecting; - avr_isp_rw_detect_chip(instance->avr_isp_rw); + avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } }, false); @@ -133,11 +133,11 @@ void avr_isp_chip_detect_view_enter(void* context) { furi_assert(context); AvrIspChipDetectView* instance = context; - //Start avr_isp_rw - instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); + //Start avr_isp_worker_rw + instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - avr_isp_rw_set_callback( - instance->avr_isp_rw, avr_isp_chip_detect_detect_chip_callback, instance); + avr_isp_worker_rw_set_callback( + instance->avr_isp_worker_rw, avr_isp_chip_detect_detect_chip_callback, instance); with_view_model( instance->view, @@ -145,7 +145,7 @@ void avr_isp_chip_detect_view_enter(void* context) { { if(model->status == AvrIspChipDetectViewStatusNoDetect || model->status == AvrIspChipDetectViewStatusDetected) { - avr_isp_rw_detect_chip(instance->avr_isp_rw); + avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } }, false); @@ -155,8 +155,8 @@ void avr_isp_chip_detect_view_exit(void* context) { furi_assert(context); AvrIspChipDetectView* instance = context; - avr_isp_rw_set_callback(instance->avr_isp_rw, NULL, NULL); - avr_isp_rw_free(instance->avr_isp_rw); + avr_isp_worker_rw_set_callback(instance->avr_isp_worker_rw, NULL, NULL); + avr_isp_worker_rw_free(instance->avr_isp_worker_rw); } AvrIspChipDetectView* avr_isp_chip_detect_view_alloc() { diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 6fea8e89664..12daf94c456 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -29,7 +29,7 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod canvas_clear(canvas); if(model->status == AvrIspProgrammerViewStatusUSBConnect) { canvas_set_font(canvas, FontPrimary); - canvas_draw_icon(canvas, 0, 0, &I_isp_active_128x64); + canvas_draw_icon(canvas, 0, 11, &I_isp_active_128x53); elements_multiline_text(canvas, 40, 10, "ISP mode active"); } else { canvas_set_font(canvas, FontSecondary); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 8d655bf4afd..24c464b8f0b 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -1,9 +1,9 @@ #include "avr_isp_view_reader.h" #include "../avr_isp_app_i.h" -#include +//#include #include -#include "../helpers/avr_isp_rw.h" +#include "../helpers/avr_isp_worker_rw.h" //#include //#include @@ -11,7 +11,7 @@ struct AvrIspReaderView { View* view; - AvrIspRW* avr_isp_rw; + AvrIspWorkerRW* avr_isp_worker_rw; const char* file_path; const char* file_name; AvrIspReaderViewCallback callback; @@ -19,12 +19,27 @@ struct AvrIspReaderView { }; typedef struct { - uint16_t idx; - IconAnimation* icon; - const char* name_chip; - bool detect_chip; + AvrIspReaderViewStatus status; + float progress_flash; + float progress_eeprom; + // IconAnimation* icon; + // const char* name_chip; + // bool detect_chip; } AvrIspReaderViewModel; +void avr_isp_reader_update_progress(AvrIspReaderView* instance) { + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + model->progress_flash = + avr_isp_worker_rw_get_progress_flash(instance->avr_isp_worker_rw); + model->progress_eeprom = + avr_isp_worker_rw_get_progress_eeprom(instance->avr_isp_worker_rw); + }, + true); +} + void avr_isp_reader_view_set_callback( AvrIspReaderView* instance, AvrIspReaderViewCallback callback, @@ -53,20 +68,41 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 20, 10, "AVRISPReader"); - // canvas_set_font(canvas, FontSecondary); + canvas_set_font(canvas, FontSecondary); + //canvas_draw_str(canvas, 20, 10, "Reding dump"); + canvas_set_font(canvas, FontSecondary); + //canvas_set_font(canvas, FontPrimary); + canvas_set_font(canvas, FontPrimary); + switch(model->status) { + case AvrIspReaderViewStatusIDLE: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reding dump"); + canvas_set_font(canvas, FontSecondary); + elements_button_center(canvas, "Start"); + break; + case AvrIspReaderViewStatusReading: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reding dump"); + //elements_button_left(canvas, "Cancel"); + break; + case AvrIspReaderViewStatusVerification: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); + canvas_set_font(canvas, FontSecondary); + //elements_button_left(canvas, "Cancel"); + break; - if(!model->detect_chip) { - canvas_draw_icon_animation(canvas, 0, 0, model->icon); - canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); - canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); - } else { - canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); - canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + default: + break; } - elements_button_left(canvas, "ReDetect"); - elements_button_center(canvas, "Dump"); + + char str_buf[64] = {0}; + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 27, "Flash"); + snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); + elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_buf); + canvas_draw_str(canvas, 0, 43, "EEPROM"); + snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); + elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_buf); } bool avr_isp_reader_view_input(InputEvent* event, void* context) { @@ -76,19 +112,29 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - FURI_LOG_D("d", "Read dump chip 1"); - avr_isp_rw_get_dump(instance->avr_isp_rw, instance->file_path, instance->file_name); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { with_view_model( instance->view, AvrIspReaderViewModel * model, { - icon_animation_start(model->icon); - model->detect_chip = false; + if(model->status == AvrIspReaderViewStatusIDLE) { + model->status = AvrIspReaderViewStatusReading; + avr_isp_worker_rw_get_dump_start( + instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + } }, false); - avr_isp_rw_detect_chip(instance->avr_isp_rw); } + // else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + // // with_view_model( + // // instance->view, + // // AvrIspReaderViewModel * model, + // // { + // // icon_animation_start(model->icon); + // // model->detect_chip = false; + // // }, + // // false); + // // avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); + // } return true; } @@ -107,6 +153,39 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { // }, // true); // } + +static void avr_isp_reader_callback_status(void* context, AvrIspWorkerRWStatus status) { + furi_assert(context); + AvrIspReaderView* instance = context; + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + switch(status) { + case AvrIspWorkerRWStatusEndReading: + model->status = AvrIspReaderViewStatusVerification; + avr_isp_worker_rw_verification_start( + instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + break; + case AvrIspWorkerRWStatusEndVerification: + if(instance->callback) + instance->callback(AvrIspCustomEventSceneReadingOk, instance->context); + break; + case AvrIspWorkerRWStatusErrorVerification: + if(instance->callback) + instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); + break; + + default: + //AvrIspWorkerRWStatusErrorReading; + if(instance->callback) + instance->callback(AvrIspCustomEventSceneErrorReading, instance->context); + break; + } + }, + true); +} + void avr_isp_reader_view_enter(void* context) { furi_assert(context); AvrIspReaderView* instance = context; @@ -115,35 +194,37 @@ void avr_isp_reader_view_enter(void* context) { instance->view, AvrIspReaderViewModel * model, { - icon_animation_start(model->icon); - model->detect_chip = false; + model->status = AvrIspReaderViewStatusIDLE; + model->progress_flash = 0.0f; + model->progress_eeprom = 0.0f; }, - false); + true); - //Start avr_isp_rw - instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); + //Start avr_isp_worker_rw + instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - //avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_reader_detect_chip_callback, instance); + avr_isp_worker_rw_set_callback_status( + instance->avr_isp_worker_rw, avr_isp_reader_callback_status, instance); - avr_isp_rw_detect_chip(instance->avr_isp_rw); - - //avr_isp_rw_start(instance->avr_isp_rw); + avr_isp_worker_rw_start(instance->avr_isp_worker_rw); } void avr_isp_reader_view_exit(void* context) { furi_assert(context); AvrIspReaderView* instance = context; - // //Stop avr_isp_rw - // if(avr_isp_avr_isp_rw_is_running(instance->avr_isp_rw)) { - // avr_isp_avr_isp_rw_stop(instance->avr_isp_rw); - // } - avr_isp_rw_free(instance->avr_isp_rw); + UNUSED(instance); + // //Stop avr_isp_worker_rw + if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { + avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); + } - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { icon_animation_stop(model->icon); }, - false); + avr_isp_worker_rw_free(instance->avr_isp_worker_rw); + + // with_view_model( + // instance->view, + // AvrIspReaderViewModel * model, + // { icon_animation_stop(model->icon); }, + // false); } AvrIspReaderView* avr_isp_reader_view_alloc() { @@ -159,26 +240,26 @@ AvrIspReaderView* avr_isp_reader_view_alloc() { view_set_enter_callback(instance->view, avr_isp_reader_view_enter); view_set_exit_callback(instance->view, avr_isp_reader_view_exit); - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { - model->icon = icon_animation_alloc(&A_ChipLooking_64x64); - view_tie_icon_animation(instance->view, model->icon); - model->detect_chip = false; - }, - false); + // with_view_model( + // instance->view, + // AvrIspReaderViewModel * model, + // { + // model->icon = icon_animation_alloc(&A_ChipLooking_64x64); + // view_tie_icon_animation(instance->view, model->icon); + // model->detect_chip = false; + // }, + // false); return instance; } void avr_isp_reader_view_free(AvrIspReaderView* instance) { furi_assert(instance); - with_view_model( - instance->view, - AvrIspReaderViewModel * model, - { icon_animation_free(model->icon); }, - false); + // with_view_model( + // instance->view, + // AvrIspReaderViewModel * model, + // { icon_animation_free(model->icon); }, + // false); view_free(instance->view); free(instance); } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h index 39282888480..94856fb26dc 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h @@ -8,6 +8,14 @@ typedef struct AvrIspReaderView AvrIspReaderView; typedef void (*AvrIspReaderViewCallback)(AvrIspCustomEvent event, void* context); +typedef enum { + AvrIspReaderViewStatusIDLE, + AvrIspReaderViewStatusReading, + AvrIspReaderViewStatusVerification, +} AvrIspReaderViewStatus; + +void avr_isp_reader_update_progress(AvrIspReaderView* instance); + void avr_isp_reader_set_file_path( AvrIspReaderView* instance, const char* file_path, diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 85e69d8184d..35f81610bbf 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -3,7 +3,7 @@ #include #include -#include "../helpers/avr_isp_rw.h" +#include "../helpers/avr_isp_worker_rw.h" //#include //#include @@ -11,7 +11,7 @@ struct AvrIspWriterView { View* view; - AvrIspRW* avr_isp_rw; + AvrIspWorkerRW* avr_isp_worker_rw; AvrIspWriterViewCallback callback; void* context; }; @@ -69,7 +69,7 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { } else if(event->key == InputKeyOk && event->type == InputTypePress) { } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { FURI_LOG_D("s", "--Detecting--"); - avr_isp_rw_detect_chip(instance->avr_isp_rw); + avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } return true; @@ -103,24 +103,24 @@ void avr_isp_writer_view_enter(void* context) { }, false); - //Start avr_isp_rw - instance->avr_isp_rw = avr_isp_rw_alloc(instance->context); + //Start avr_isp_worker_rw + instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - //avr_isp_rw_set_callback(instance->avr_isp_rw, avr_isp_writer_detect_chip_callback, instance); + //avr_isp_worker_rw_set_callback(instance->avr_isp_worker_rw, avr_isp_writer_detect_chip_callback, instance); - avr_isp_rw_detect_chip(instance->avr_isp_rw); + avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); - //avr_isp_rw_start(instance->avr_isp_rw); + //avr_isp_worker_rw_start(instance->avr_isp_worker_rw); } void avr_isp_writer_view_exit(void* context) { furi_assert(context); AvrIspWriterView* instance = context; - // //Stop avr_isp_rw - // if(avr_isp_avr_isp_rw_is_running(instance->avr_isp_rw)) { - // avr_isp_avr_isp_rw_stop(instance->avr_isp_rw); + // //Stop avr_isp_worker_rw + // if(avr_isp_avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { + // avr_isp_avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); // } - avr_isp_rw_free(instance->avr_isp_rw); + avr_isp_worker_rw_free(instance->avr_isp_worker_rw); with_view_model( instance->view, From daa3c0f6cdef85741e50462b0f8308e907cd2eea Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 23 Mar 2023 14:44:30 +0400 Subject: [PATCH 28/50] AVR_ISP: add gui "Flash AVR" --- .../external/avr_isp_programmer/avr_isp_app.c | 1 + .../avr_isp_programmer/avr_isp_app_i.c | 17 +- .../helpers/avr_isp_event.h | 1 + .../helpers/avr_isp_worker_rw.c | 842 ++++++++++-------- .../helpers/avr_isp_worker_rw.h | 23 +- .../scenes/avr_isp_scene_writer.c | 12 +- .../views/avr_isp_view_reader.c | 90 +- .../views/avr_isp_view_writer.c | 203 +++-- .../views/avr_isp_view_writer.h | 13 + applications/main/subghz/subghz_i.c | 2 +- 10 files changed, 661 insertions(+), 543 deletions(-) diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index 2ab154b9933..a86d7a209de 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -25,6 +25,7 @@ AvrIspApp* avr_isp_app_alloc() { AvrIspApp* app = malloc(sizeof(AvrIspApp)); app->file_path = furi_string_alloc(); + furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); // GUI app->gui = furi_record_open(RECORD_GUI); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c index 2475ec59a6f..92b90cecafe 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.c @@ -1,13 +1,14 @@ #include "avr_isp_app_i.h" +#include +#include #define TAG "AvrIsp" -#include bool avr_isp_load_from_file(AvrIspApp* app) { furi_assert(app); - FuriString* file_path; - file_path = furi_string_alloc(); + FuriString* file_path = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options( @@ -15,13 +16,13 @@ bool avr_isp_load_from_file(AvrIspApp* app) { browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; // Input events and views are managed by file_select - bool res = - dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); + bool res = dialog_file_browser_show(app->dialogs, file_path, app->file_path, &browser_options); - // if(res) { - // res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); - // } + path_extract_dirname(furi_string_get_cstr(file_path), app->file_path); + path_extract_filename(file_path, file_name, true); + strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); + furi_string_free(file_name); furi_string_free(file_path); return res; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index 365c1a3ccad..78537628617 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -11,6 +11,7 @@ typedef enum { //AvrIspCustomEvent AvrIspCustomEventSceneChipDetectOk = 100, AvrIspCustomEventSceneReadingOk, + AvrIspCustomEventSceneWritingOk, AvrIspCustomEventSceneErrorVerification, AvrIspCustomEventSceneErrorReading, AvrIspCustomEventSceneErrorWriting, diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 346c79ffce2..7b5db71a996 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -12,6 +12,9 @@ #define TAG "AvrIspWorkerRW" +#define NAME_PATERN_FLASH_FILE "flash.hex" +#define NAME_PATERN_EEPROM_FILE "eeprom.hex" + struct AvrIspWorkerRW { AvrIsp* avr_isp; FuriThread* thread; @@ -68,15 +71,15 @@ static int32_t avr_isp_worker_rw_thread(void* context) { } if(events & AvrIspWorkerRWEvtWriting) { - // if(avr_isp_worker_rw_get_dump(instance, instance->file_path, instance->file_name)) { - // if(instance->callback_status) - // instance->callback_status( - // instance->context_status, AvrIspWorkerRWStatusEndWriting); - // } else { - // if(instance->callback_status) - // instance->callback_status( - // instance->context_status, AvrIspWorkerRWStatusErrorWriting); - // } + if(avr_isp_worker_rw_write_dump(instance, instance->file_path, instance->file_name)) { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusEndWriting); + } else { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusEndWriting); + } } if(events & AvrIspWorkerRWEvtVerification) { @@ -86,18 +89,20 @@ static int32_t avr_isp_worker_rw_thread(void* context) { instance->context_status, AvrIspWorkerRWStatusEndVerification); } else { if(instance->callback_status) - instance->callback_status(instance->context_status, AvrIspWorkerRWStatusErrorVerification); + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusErrorVerification); } } if(events & AvrIspWorkerRWEvtReading) { - if(avr_isp_worker_rw_get_dump(instance, instance->file_path, instance->file_name)) { + if(avr_isp_worker_rw_read_dump(instance, instance->file_path, instance->file_name)) { if(instance->callback_status) instance->callback_status( instance->context_status, AvrIspWorkerRWStatusEndReading); } else { if(instance->callback_status) - instance->callback_status(instance->context_status, AvrIspWorkerRWStatusErrorReading); + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusErrorReading); } } } @@ -343,7 +348,7 @@ void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const char* fil instance->progress_eeprom = 1.0f; } -bool avr_isp_worker_rw_get_dump( +bool avr_isp_worker_rw_read_dump( AvrIspWorkerRW* instance, const char* file_path, const char* file_name) { @@ -412,7 +417,7 @@ bool avr_isp_worker_rw_get_dump( break; } } - furi_string_printf(file_path_name, "%s_flash.hex", file_name); + furi_string_printf(file_path_name, "%s_%s", file_name, NAME_PATERN_FLASH_FILE); if(!flipper_format_write_string_cstr( flipper_format, "Dump_flash", furi_string_get_cstr(file_path_name))) { FURI_LOG_E(TAG, "Unable to add Dump_flash"); @@ -420,7 +425,7 @@ bool avr_isp_worker_rw_get_dump( } if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - furi_string_printf(file_path_name, "%s_eeprom.hex", file_name); + furi_string_printf(file_path_name, "%s_%s", file_name, NAME_PATERN_EEPROM_FILE); if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { if(!flipper_format_write_string_cstr( flipper_format, "Dump_eeprom", furi_string_get_cstr(file_path_name))) { @@ -439,11 +444,13 @@ bool avr_isp_worker_rw_get_dump( if(ret) { if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { //Dump flash - furi_string_printf(file_path_name, "%s/%s_flash.hex", file_path, file_name); + furi_string_printf( + file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); avr_isp_worker_rw_get_dump_flash(instance, furi_string_get_cstr(file_path_name)); //Dump eeprom if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { - furi_string_printf(file_path_name, "%s/%s_eeprom.hex", file_path, file_name); + furi_string_printf( + file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); avr_isp_worker_rw_get_dump_eeprom(instance, furi_string_get_cstr(file_path_name)); } @@ -456,7 +463,7 @@ bool avr_isp_worker_rw_get_dump( return true; } -void avr_isp_worker_rw_get_dump_start( +void avr_isp_worker_rw_read_dump_start( AvrIspWorkerRW* instance, const char* file_path, const char* file_name) { @@ -484,55 +491,52 @@ bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); - if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && - ret) { + while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && + ret) { + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_hex[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + avr_isp_read_page( + instance->avr_isp, + STK_SET_FLASH_TYPE, + addr, + flipper_hex_ret.data_size, + data_read_flash, + sizeof(data_read_flash)); + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_hex[i]); + // printf("%02X ", data_read_flash[i]); // } // printf("\r\n"); - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - avr_isp_read_page( - instance->avr_isp, - STK_SET_FLASH_TYPE, - addr, - flipper_hex_ret.data_size, - data_read_flash, - sizeof(data_read_flash)); - - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_flash[i]); - // } - // printf("\r\n"); - - if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { - ret = false; - FURI_LOG_E(TAG, "Verification flash error"); - } - - addr += flipper_hex_ret.data_size / 2; - instance->progress_flash = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); - break; + if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { + ret = false; + FURI_LOG_E(TAG, "Verification flash error"); + } - case FlipperI32HexFileStatusUdateAddr: - addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16) / 2; - break; + addr += flipper_hex_ret.data_size / 2; + instance->progress_flash = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + break; - default: - furi_crash(TAG " Incorrect status."); - break; - } + case FlipperI32HexFileStatusUdateAddr: + addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16) / 2; + break; - flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); + default: + furi_crash(TAG " Incorrect status."); + break; } - avr_isp_end_pmode(instance->avr_isp); + flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); } + flipper_i32hex_file_close(flipper_hex_flash); instance->progress_flash = 1.0f; @@ -557,55 +561,52 @@ bool avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); - if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { - while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || - (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && - ret) { + while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && + ret) { + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data_read_hex[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + avr_isp_read_page( + instance->avr_isp, + STK_SET_EEPROM_TYPE, + addr, + flipper_hex_ret.data_size, + data_read_eeprom, + sizeof(data_read_eeprom)); + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_hex[i]); + // printf("%02X ", data_read_eeprom[i]); // } // printf("\r\n"); - switch(flipper_hex_ret.status) { - case FlipperI32HexFileStatusData: - avr_isp_read_page( - instance->avr_isp, - STK_SET_EEPROM_TYPE, - addr, - flipper_hex_ret.data_size, - data_read_eeprom, - sizeof(data_read_eeprom)); - - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_eeprom[i]); - // } - // printf("\r\n"); - - if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { - ret = false; - FURI_LOG_E(TAG, "Verification eeprom error"); - } - - addr += flipper_hex_ret.data_size; - instance->progress_flash = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); - break; + if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { + ret = false; + FURI_LOG_E(TAG, "Verification eeprom error"); + } - case FlipperI32HexFileStatusUdateAddr: - addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16); - break; + addr += flipper_hex_ret.data_size; + instance->progress_eeprom = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + break; - default: - furi_crash(TAG " Incorrect status."); - break; - } + case FlipperI32HexFileStatusUdateAddr: + addr = (data_read_hex[0] << 24 | data_read_hex[1] << 16); + break; - flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( - flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); + default: + furi_crash(TAG " Incorrect status."); + break; } - avr_isp_end_pmode(instance->avr_isp); + flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_eeprom, data_read_hex, sizeof(data_read_hex)); } + flipper_i32hex_file_close(flipper_hex_eeprom); instance->progress_eeprom = 1.0f; @@ -622,20 +623,31 @@ bool avr_isp_worker_rw_verification( instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; - char str_buf[64] = {0}; + FuriString* file_path_name = furi_string_alloc(); + bool ret = false; - do { - snprintf( - str_buf, sizeof(str_buf), "%s/%s_flash.hex", instance->file_path, instance->file_name); - if(!avr_isp_worker_rw_verification_flash(instance, str_buf)) break; - snprintf( - str_buf, sizeof(str_buf), "%s/%s_eeprom.hex", instance->file_path, instance->file_name); + if(avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + do { + furi_string_printf( + file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); + if(!avr_isp_worker_rw_verification_flash( + instance, furi_string_get_cstr(file_path_name))) + break; - if(!avr_isp_worker_rw_verification_eeprom(instance, str_buf)) break; - ret = true; - } while(false); + if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { + furi_string_printf( + file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); + if(!avr_isp_worker_rw_verification_eeprom( + instance, furi_string_get_cstr(file_path_name))) + break; + } + ret = true; + } while(false); + avr_isp_end_pmode(instance->avr_isp); + furi_string_free(file_path_name); + } return ret; } @@ -649,291 +661,381 @@ void avr_isp_worker_rw_verification_start( furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtVerification); } -// bool avr_isp_worker_rw_rx1(AvrIspWorkerRW* instance) { +// bool avr_isp_worker_rw_check_hex( +// AvrIspWorkerRW* instance, +// const char* file_path, +// const char* file_name) { // furi_assert(instance); -// uint8_t data[256]; +// furi_assert(file_path); +// furi_assert(file_name); + +// FuriString* file_path_name = furi_string_alloc(); +// bool ret = false; +// bool check_flash = true; +// bool check_eeprom = true; -// Storage* storage = furi_record_open(RECORD_STORAGE); -// FlipperFormat* flipper_format = flipper_format_file_alloc(storage); -// FURI_LOG_D(TAG, "Read chip"); // do { -// if(!instance->chip_detect) { -// FURI_LOG_E(TAG, "No detect AVR chip"); -// break; +// furi_string_printf( +// file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); + +// FURI_LOG_D(TAG, "Check flash file"); +// FlipperI32HexFile* flipper_hex_flash_read = +// flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); +// if(flipper_i32hex_file_check(flipper_hex_flash_read)) { +// FURI_LOG_D(TAG, "Check flash file: OK"); +// } else { +// FURI_LOG_D(TAG, "Check flash file: Error"); +// check_flash = false; // } +// flipper_i32hex_file_close(flipper_hex_flash_read); -// // if(!storage_simply_mkdir(storage, "/any/avr_isp/")) { -// // FURI_LOG_E(TAG, "storage_simply_mkdir"); -// // break; -// // } +// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { +// furi_string_printf( +// file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); + +// FURI_LOG_D(TAG, "Check eeprom file"); +// FlipperI32HexFile* flipper_hex_eeprom_read = +// flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); +// if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { +// FURI_LOG_D(TAG, "Check eeprom file: OK"); +// } else { +// FURI_LOG_D(TAG, "Check eeprom file: Error"); +// check_eeprom = false; +// } +// flipper_i32hex_file_close(flipper_hex_eeprom_read); +// } -// // if(!storage_simply_remove(storage, "dump.avr")) { -// // break; -// // } +// if(check_flash && check_eeprom) ret = true; +// } while(false); +// furi_string_free(file_path_name); +// return ret; +// } -// if(!flipper_format_file_open_always(flipper_format, "/any/avr_isp/dump.avr")) { -// FURI_LOG_E(TAG, "flipper_format_file_open_always"); -// break; -// } -// if(!flipper_format_write_header_cstr(flipper_format, "Flipper dump AVR", 1)) { -// FURI_LOG_E(TAG, "flipper_format_write_header_cstr"); -// break; -// } -// if(!flipper_format_write_comment_cstr(flipper_format, "This is comment")) { -// FURI_LOG_E(TAG, "flipper_format_write_comment_cstr"); -// break; -// } -// //if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break; +void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_path) { + furi_assert(instance); + furi_check(instance->avr_isp); + instance->progress_flash = 0.0; -// if(!flipper_format_write_string_cstr( -// flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { -// FURI_LOG_E(TAG, "Chip name"); -// break; -// } + FURI_LOG_D(TAG, "Write Flash %s", file_path); + uint8_t data[288] = {0}; -// if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { -// FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); -// break; -// } + FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); -// // avr_isp_read_signature(instance->avr_isp, data); + uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + FlipperI32HexFileRet flipper_hex_ret = + flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); + + while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { + // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + if(!avr_isp_write_page( + instance->avr_isp, + STK_SET_FLASH_TYPE, + avr_isp_chip_arr[instance->chip_arr_ind].flashsize, + addr, + avr_isp_chip_arr[instance->chip_arr_ind].pagesize, + data, + flipper_hex_ret.data_size)) { + break; + } + addr += flipper_hex_ret.data_size / 2; + instance->progress_flash = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + break; -// if(!flipper_format_write_hex(flipper_format, "ID", data, 3)) { -// FURI_LOG_E(TAG, "Unable to add ID"); -// break; -// } -// FURI_LOG_D(TAG, "ID = 0x%02X 0x%02X 0x%02X", data[0], data[1], data[2]); + case FlipperI32HexFileStatusUdateAddr: + addr = (data[0] << 24 | data[1] << 16) / 2; + break; -// data[0] = avr_isp_read_fuse_high(instance->avr_isp); -// data[1] = avr_isp_read_fuse_low(instance->avr_isp); -// data[2] = avr_isp_read_fuse_extended(instance->avr_isp); -// data[3] = avr_isp_read_lock_byte(instance->avr_isp); + default: + furi_crash(TAG " Incorrect status."); + break; + } -// if(!flipper_format_write_hex(flipper_format, "Hfuse", data, 1)) { -// FURI_LOG_E(TAG, "Unable to add Hfuse"); -// break; -// } + flipper_hex_ret = + flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); + } -// if(!flipper_format_write_hex(flipper_format, "Lfuse", data + 1, 1)) { -// FURI_LOG_E(TAG, "Unable to add Lfuse"); -// break; -// } + flipper_i32hex_file_close(flipper_hex_flash); + instance->progress_flash = 1.0f; +} -// if(!flipper_format_write_hex(flipper_format, "Efuse", data + 2, 1)) { -// FURI_LOG_E(TAG, "Unable to add Efuse"); -// break; -// } +void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* file_path) { + furi_assert(instance); + furi_check(instance->avr_isp); + instance->progress_eeprom = 0.0; + uint8_t data[288] = {0}; + FURI_LOG_D(TAG, "Write EEPROM %s", file_path); -// if(!flipper_format_write_hex(flipper_format, "Lock", data + 3, 1)) { -// FURI_LOG_E(TAG, "Unable to add Lock"); -// break; -// } + FlipperI32HexFile* flipper_hex_eeprom_read = flipper_i32hex_file_open_read(file_path); -// FURI_LOG_D( -// TAG, -// "hfuse = 0x%02X lfuse = 0x%02X efuse = 0x%02X lock = 0x%02X", -// data[0], -// data[1], -// data[2], -// data[3]); - -// if(!flipper_format_write_string_cstr(flipper_format, "Dump_flash", "flash.hex")) { -// FURI_LOG_E(TAG, "Unable to add Dump_flash"); -// break; -// } -// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { -// if(!flipper_format_write_string_cstr(flipper_format, "Dump_eeprom", "eeprom.hex")) { -// FURI_LOG_E(TAG, "Unable to add Dump_eeprom"); -// break; -// } -// } + uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; + FlipperI32HexFileRet flipper_hex_ret = + flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_eeprom_read, data, sizeof(data)); + + while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || + (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { + // FURI_LOG_D(TAG, "EEPROM WRITE Page"); + // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { + // printf("%02X ", data[i]); + // } + // printf("\r\n"); + + switch(flipper_hex_ret.status) { + case FlipperI32HexFileStatusData: + if(!avr_isp_write_page( + instance->avr_isp, + STK_SET_EEPROM_TYPE, + avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, + addr, + avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, + data, + flipper_hex_ret.data_size)) { + break; + } + addr += flipper_hex_ret.data_size; + instance->progress_eeprom = + (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + break; + break; -// FURI_LOG_D(TAG, "EEPROM"); + case FlipperI32HexFileStatusUdateAddr: + addr = data[0] << 24 | data[1] << 16; + break; -// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { -// FlipperI32HexFile* flipper_hex_eeprom = flipper_i32hex_file_open_write( -// "/any/avr_isp/eeprom.hex", avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset); -// int32_t size_data = 32; -// if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) -// size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - -// for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; -// i += size_data) { -// avr_isp_read_page( -// instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); -// flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); -// printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); -// } -// flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); -// printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_eeprom)); -// flipper_i32hex_file_close(flipper_hex_eeprom); -// } + default: + furi_crash(TAG " Incorrect status."); + break; + } -// // FURI_LOG_D(TAG, "FLASH"); -// // FlipperI32HexFile* flipper_hex_flash = -// // flipper_i32hex_file_open_write("/any/avr_isp/flash.hex", avr_isp_chip_arr[instance->chip_arr_ind].flashoffset;); -// // for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; -// // i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { -// // avr_isp_read_page( -// // instance->avr_isp, -// // STK_SET_FLASH_TYPE, -// // i, -// // avr_isp_chip_arr[instance->chip_arr_ind].pagesize, -// // data, -// // sizeof(data)); -// // flipper_i32hex_file_bin_to_i32hex_add_data( -// // flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); -// // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); -// // } -// // flipper_i32hex_file_bin_to_i32hex_add_end_line(flipper_hex_flash); -// // printf("%s\r\n", flipper_i32hex_file_get_string(flipper_hex_flash)); -// // flipper_i32hex_file_close(flipper_hex_flash); - -// avr_isp_end_pmode(instance->avr_isp); - -// // // //################################################################ -// // FURI_LOG_D(TAG, "FUSE Write"); -// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { -// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); -// // break; -// // } -// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_low(instance->avr_isp, 0xFF)); -// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_extended(instance->avr_isp, 0xFD)); -// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_fuse_high(instance->avr_isp, 0xDA)); -// // FURI_LOG_E(TAG, "fuse %d", avr_isp_write_lock_byte(instance->avr_isp, 0xFF)); - -// // avr_isp_end_pmode(instance->avr_isp); -// // //################################################################## - -// // //################################################################ -// // FURI_LOG_D(TAG, "ERASE CHIP"); -// // avr_isp_erase_chip(instance->avr_isp); -// // //################################################################## - -// //########################################################## -// FURI_LOG_D(TAG, "FLASH WRITE"); - -// if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { -// FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); -// break; -// } -// avr_isp_read_signature(instance->avr_isp, data); - -// FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read("/any/avr_isp/flash.hex"); - -// uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; -// FlipperI32HexFileRet flipper_hex_ret = -// flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); -// FURI_LOG_D(TAG, "FLASH WRITE Page ---%ld", addr); -// while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || -// (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { -// // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); -// // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { -// // printf("%02X ", data[i]); -// // } -// // printf("\r\n"); - -// switch(flipper_hex_ret.status) { -// case FlipperI32HexFileStatusData: -// if(!avr_isp_write_page( -// instance->avr_isp, -// STK_SET_FLASH_TYPE, -// avr_isp_chip_arr[instance->chip_arr_ind].flashsize, -// addr, -// avr_isp_chip_arr[instance->chip_arr_ind].pagesize, -// data, -// flipper_hex_ret.data_size)) { -// break; -// } -// addr += flipper_hex_ret.data_size / 2; -// break; + flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( + flipper_hex_eeprom_read, data, sizeof(data)); + } -// case FlipperI32HexFileStatusUdateAddr: -// addr = data[0] << 24 | data[1] << 16; -// break; + flipper_i32hex_file_close(flipper_hex_eeprom_read); + instance->progress_eeprom = 1.0f; +} -// default: -// furi_crash(TAG " Incorrect status."); -// break; -// } +bool avr_isp_worker_rw_write_dump( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + furi_assert(file_path); + furi_assert(file_name); -// flipper_hex_ret = -// flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); -// } + FURI_LOG_D(TAG, "Write dump chip"); + instance->progress_flash = 0.0f; + instance->progress_eeprom = 0.0f; + bool ret = false; + uint8_t lfuse; + uint8_t hfuse; + uint8_t efuse; + uint8_t lock; -// flipper_i32hex_file_close(flipper_hex_flash); -// avr_isp_end_pmode(instance->avr_isp); -// ########################################################## - -// // FURI_LOG_D(TAG, "CHECK HEX"); -// // FlipperI32HexFile* flipper_hex_eeprom_read = -// // flipper_i32hex_file_open_read("/any/avr_isp/a.hex"); -// // if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { -// // FURI_LOG_D(TAG, "Check OK"); -// // } else { -// // FURI_LOG_E(TAG, "Check ERROR"); -// // } -// // // flipper_i32hex_file_close(flipper_hex_eeprom_read); - -// // //########################################################## -// // FURI_LOG_D(TAG, "EEPROM WRITE"); - -// // if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { -// // FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); -// // break; -// // } -// // avr_isp_read_signature(instance->avr_isp, data); -// // uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; -// // FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( -// // flipper_hex_eeprom_read, data, sizeof(data)); - -// // while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || -// // (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { -// // FURI_LOG_D(TAG, "EEPROM WRITE Page"); -// // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { -// // printf("%02X ", data[i]); -// // } -// // printf("\r\n"); - -// // switch(flipper_hex_ret.status) { -// // case FlipperI32HexFileStatusData: -// // if(!avr_isp_write_page( -// // instance->avr_isp, -// // STK_SET_EEPROM_TYPE, -// // avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, -// // addr, -// // avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, -// // data, -// // flipper_hex_ret.data_size)) { -// // break; -// // } -// // addr += flipper_hex_ret.data_size; -// // break; - -// // case FlipperI32HexFileStatusUdateAddr: -// // addr = data[0] << 24 | data[1] << 16; -// // break; - -// // default: -// // furi_crash(TAG " Incorrect status."); -// // break; -// // } - -// // flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( -// // flipper_hex_eeprom_read, data, sizeof(data)); -// // } - -// // flipper_i32hex_file_close(flipper_hex_eeprom_read); -// // avr_isp_end_pmode(instance->avr_isp); -// // //########################################################## - -// // //################################################################ -// // FURI_LOG_D(TAG, "ERASE CHIP"); -// // avr_isp_erase_chip(instance->avr_isp); -// // //################################################################## -// FURI_LOG_D(TAG, "___END___"); -// } while(0); -// flipper_format_free(flipper_format); -// furi_record_close(RECORD_STORAGE); -// return true; -// } \ No newline at end of file + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + FuriString* file_path_name = furi_string_alloc(); + + FuriString* temp_str_1 = furi_string_alloc(); + FuriString* temp_str_2 = furi_string_alloc(); + uint32_t temp_data32; + + if(!avr_isp_worker_rw_detect_chip(instance)) { + FURI_LOG_E(TAG, "No detect AVR chip"); + } else { + //upload file with description + do { + furi_string_printf( + file_path_name, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); + if(!flipper_format_file_open_existing( + flipper_format, furi_string_get_cstr(file_path_name))) { + FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(file_path_name)); + break; + } + + if(!flipper_format_read_header(flipper_format, temp_str_1, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + break; + } + + if((!strcmp(furi_string_get_cstr(temp_str_1), AVR_ISP_APP_FILE_TYPE)) && + temp_data32 == AVR_ISP_APP_FILE_VERSION) { + } else { + FURI_LOG_E(TAG, "Type or version mismatch"); + break; + } + + // if(!flipper_format_write_string_cstr( + // flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { + // FURI_LOG_E(TAG, "Chip name"); + // break; + // } + + AvrIspSignature sig_read = {0}; + + if(!flipper_format_read_hex( + flipper_format, "Signature", (uint8_t*)&sig_read, sizeof(AvrIspSignature))) { + FURI_LOG_E(TAG, "Missing Signature"); + break; + } + + if(memcmp( + (uint8_t*)&instance->signature, (uint8_t*)&sig_read, sizeof(AvrIspSignature)) != + 0) { + FURI_LOG_E( + TAG, + "Wrong chip. Connected (%02X %02X %02X), read from file (%02X %02X %02X)", + instance->signature.vendor, + instance->signature.part_family, + instance->signature.part_number, + sig_read.vendor, + sig_read.part_family, + sig_read.part_number); + break; + } + + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { + FURI_LOG_E(TAG, "Missing Lfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { + FURI_LOG_E(TAG, "Missing Hfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { + FURI_LOG_E(TAG, "Missing Efuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { + FURI_LOG_E(TAG, "Missing Lock"); + break; + } + } + + if(!flipper_format_read_string(flipper_format, "Dump_flash", temp_str_1)) { + FURI_LOG_E(TAG, "Missing Dump_flash"); + break; + } + + //may not be + flipper_format_read_string(flipper_format, "Dump_eeprom", temp_str_2); + ret = true; + } while(false); + } + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + + if(ret) { + do { + //checking .hex files for errors + + furi_string_printf( + file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_1)); + + FURI_LOG_D(TAG, "Check flash file"); + FlipperI32HexFile* flipper_hex_flash_read = + flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); + if(flipper_i32hex_file_check(flipper_hex_flash_read)) { + FURI_LOG_D(TAG, "Check flash file: OK"); + } else { + FURI_LOG_E(TAG, "Check flash file: Error"); + ret = false; + } + flipper_i32hex_file_close(flipper_hex_flash_read); + + if(furi_string_size(temp_str_2) > 4) { + furi_string_printf( + file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); + + FURI_LOG_D(TAG, "Check eeprom file"); + FlipperI32HexFile* flipper_hex_eeprom_read = + flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); + if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { + FURI_LOG_D(TAG, "Check eeprom file: OK"); + } else { + FURI_LOG_E(TAG, "Check eeprom file: Error"); + ret = false; + } + flipper_i32hex_file_close(flipper_hex_eeprom_read); + } + + if(!ret) break; + ret = false; + + //erase chip + FURI_LOG_D(TAG, "Erase chip"); + if(!avr_isp_erase_chip(instance->avr_isp)) { + FURI_LOG_E(TAG, "Erase chip: Error"); + break; + } + + if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + break; + } + + //write flash + furi_string_printf( + file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_1)); + avr_isp_worker_rw_write_flash(instance, furi_string_get_cstr(file_path_name)); + + //write eeprom + if(furi_string_size(temp_str_2) > 4) { + furi_string_printf( + file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); + avr_isp_worker_rw_write_eeprom(instance, furi_string_get_cstr(file_path_name)); + } + + //write fuse and lock + FURI_LOG_D(TAG, "Write fuse"); + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + if(instance->lfuse != lfuse) avr_isp_write_fuse_low(instance->avr_isp, lfuse); + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + if(instance->hfuse != hfuse) avr_isp_write_fuse_high(instance->avr_isp, hfuse); + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + if(instance->efuse != efuse) avr_isp_write_fuse_extended(instance->avr_isp, efuse); + } + + if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + FURI_LOG_D(TAG, "Write lock byte"); + if(instance->lock != lock) avr_isp_write_lock_byte(instance->avr_isp, lock); + } + + avr_isp_end_pmode(instance->avr_isp); + ret = true; + } while(false); + } + + furi_string_free(file_path_name); + furi_string_free(temp_str_1); + furi_string_free(temp_str_2); + + return true; +} + +void avr_isp_worker_rw_write_dump_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWriting); +} diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h index 7a4348d4ee0..22f8a2052d9 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h @@ -14,11 +14,11 @@ typedef enum { AvrIspWorkerRWStatusILDE = 0, AvrIspWorkerRWStatusEndReading = 1, AvrIspWorkerRWStatusEndVerification = 2, - AvrIspWorkerRWStatusEndWritin = 3, + AvrIspWorkerRWStatusEndWriting = 3, AvrIspWorkerRWStatusErrorReading = (-1), AvrIspWorkerRWStatusErrorVerification = (-2), - AvrIspWorkerRWStatusErrorWritin = (-3), + AvrIspWorkerRWStatusErrorWriting = (-3), AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. } AvrIspWorkerRWStatus; @@ -71,12 +71,12 @@ float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance); float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance); -bool avr_isp_worker_rw_get_dump( +bool avr_isp_worker_rw_read_dump( AvrIspWorkerRW* instance, const char* file_path, const char* file_name); -void avr_isp_worker_rw_get_dump_start( +void avr_isp_worker_rw_read_dump_start( AvrIspWorkerRW* instance, const char* file_path, const char* file_name); @@ -90,3 +90,18 @@ void avr_isp_worker_rw_verification_start( AvrIspWorkerRW* instance, const char* file_path, const char* file_name); + +bool avr_isp_worker_rw_check_hex( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +bool avr_isp_worker_rw_write_dump( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +void avr_isp_worker_rw_write_dump_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c index 59dd7ba3fab..999d262bc08 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -10,6 +10,10 @@ void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { void avr_isp_scene_writer_on_enter(void* context) { AvrIspApp* app = context; + + + avr_isp_writer_set_file_path( + app->avr_isp_writer_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); avr_isp_writer_view_set_callback(app->avr_isp_writer_view, avr_isp_scene_writer_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter); } @@ -20,13 +24,15 @@ bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - // case WSCustomEventViewreaderBack: - // consumed = true; - // break; + case AvrIspCustomEventSceneWritingOk: + scene_manager_next_scene(app->scene_manager, AvrIspSceneSuccess); + consumed = true; + break; default: break; } } else if(event.type == SceneManagerEventTypeTick) { + avr_isp_writer_update_progress(app->avr_isp_writer_view); } return consumed; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 24c464b8f0b..1fc22a8761e 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -1,13 +1,8 @@ #include "avr_isp_view_reader.h" #include "../avr_isp_app_i.h" -//#include #include #include "../helpers/avr_isp_worker_rw.h" -//#include - -//#include -//#include struct AvrIspReaderView { View* view; @@ -22,9 +17,6 @@ typedef struct { AvrIspReaderViewStatus status; float progress_flash; float progress_eeprom; - // IconAnimation* icon; - // const char* name_chip; - // bool detect_chip; } AvrIspReaderViewModel; void avr_isp_reader_update_progress(AvrIspReaderView* instance) { @@ -60,18 +52,8 @@ void avr_isp_reader_set_file_path( } void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { - UNUSED(model); canvas_clear(canvas); - // canvas_set_color(canvas, ColorBlack); - // canvas_set_font(canvas, FontSecondary); - - // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); - - canvas_set_font(canvas, FontPrimary); - canvas_set_font(canvas, FontSecondary); - //canvas_draw_str(canvas, 20, 10, "Reding dump"); - canvas_set_font(canvas, FontSecondary); - //canvas_set_font(canvas, FontPrimary); + char str_buf[64] = {0}; canvas_set_font(canvas, FontPrimary); switch(model->status) { @@ -82,20 +64,15 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { break; case AvrIspReaderViewStatusReading: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reding dump"); - //elements_button_left(canvas, "Cancel"); break; case AvrIspReaderViewStatusVerification: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); - canvas_set_font(canvas, FontSecondary); - //elements_button_left(canvas, "Cancel"); break; default: break; } - char str_buf[64] = {0}; - canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 0, 27, "Flash"); snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); @@ -108,52 +85,35 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { bool avr_isp_reader_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspReaderView* instance = context; - UNUSED(instance); + bool ret = true; + if(event->key == InputKeyBack || event->type != InputTypeShort) { - return false; + with_view_model( + instance->view, + AvrIspReaderViewModel * model, + { + if(model->status == AvrIspReaderViewStatusIDLE) { + ret = false; + } + }, + false); } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + FURI_LOG_E("Read", "Start %s %s", instance->file_path, instance->file_name); with_view_model( instance->view, AvrIspReaderViewModel * model, { if(model->status == AvrIspReaderViewStatusIDLE) { model->status = AvrIspReaderViewStatusReading; - avr_isp_worker_rw_get_dump_start( + avr_isp_worker_rw_read_dump_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); } }, false); } - // else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - // // with_view_model( - // // instance->view, - // // AvrIspReaderViewModel * model, - // // { - // // icon_animation_start(model->icon); - // // model->detect_chip = false; - // // }, - // // false); - // // avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); - // } - - return true; + return ret; } -// static void -// avr_isp_reader_detect_chip_callback(void* context, const char* name, bool detect_chip) { -// furi_assert(context); -// AvrIspReaderView* instance = context; -// with_view_model( -// instance->view, -// AvrIspReaderViewModel * model, -// { -// model->name_chip = name; -// model->detect_chip = detect_chip; -// if(detect_chip) icon_animation_stop(model->icon); -// }, -// true); -// } - static void avr_isp_reader_callback_status(void* context, AvrIspWorkerRWStatus status) { furi_assert(context); AvrIspReaderView* instance = context; @@ -219,12 +179,6 @@ void avr_isp_reader_view_exit(void* context) { } avr_isp_worker_rw_free(instance->avr_isp_worker_rw); - - // with_view_model( - // instance->view, - // AvrIspReaderViewModel * model, - // { icon_animation_stop(model->icon); }, - // false); } AvrIspReaderView* avr_isp_reader_view_alloc() { @@ -240,26 +194,12 @@ AvrIspReaderView* avr_isp_reader_view_alloc() { view_set_enter_callback(instance->view, avr_isp_reader_view_enter); view_set_exit_callback(instance->view, avr_isp_reader_view_exit); - // with_view_model( - // instance->view, - // AvrIspReaderViewModel * model, - // { - // model->icon = icon_animation_alloc(&A_ChipLooking_64x64); - // view_tie_icon_animation(instance->view, model->icon); - // model->detect_chip = false; - // }, - // false); return instance; } void avr_isp_reader_view_free(AvrIspReaderView* instance) { furi_assert(instance); - // with_view_model( - // instance->view, - // AvrIspReaderViewModel * model, - // { icon_animation_free(model->icon); }, - // false); view_free(instance->view); free(instance); } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 35f81610bbf..aa3f93f350f 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -1,28 +1,37 @@ -#include "avr_isp_view_reader.h" +#include "avr_isp_view_writer.h" #include "../avr_isp_app_i.h" -#include #include #include "../helpers/avr_isp_worker_rw.h" -//#include - -//#include -//#include struct AvrIspWriterView { View* view; AvrIspWorkerRW* avr_isp_worker_rw; + const char* file_path; + const char* file_name; AvrIspWriterViewCallback callback; void* context; }; typedef struct { - uint16_t idx; - IconAnimation* icon; - const char* name_chip; - bool detect_chip; + AvrIspWriterViewStatus status; + float progress_flash; + float progress_eeprom; } AvrIspWriterViewModel; +void avr_isp_writer_update_progress(AvrIspWriterView* instance) { + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + model->progress_flash = + avr_isp_worker_rw_get_progress_flash(instance->avr_isp_worker_rw); + model->progress_eeprom = + avr_isp_worker_rw_get_progress_eeprom(instance->avr_isp_worker_rw); + }, + true); +} + void avr_isp_writer_view_set_callback( AvrIspWriterView* instance, AvrIspWriterViewCallback callback, @@ -33,62 +42,110 @@ void avr_isp_writer_view_set_callback( instance->context = context; } +void avr_isp_writer_set_file_path( + AvrIspWriterView* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + instance->file_path = file_path; + instance->file_name = file_name; +} + void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { - UNUSED(model); canvas_clear(canvas); - // canvas_set_color(canvas, ColorBlack); - // canvas_set_font(canvas, FontSecondary); - - // canvas_draw_icon(canvas, 0, 0, &I_AvrIspProg); + char str_buf[64] = {0}; canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 20, 10, "AVRISPWriter"); - // canvas_set_font(canvas, FontSecondary); - canvas_set_font(canvas, FontPrimary); - - - - if(!model->detect_chip) { - canvas_draw_icon_animation(canvas, 0, 0, model->icon); - canvas_draw_str_aligned(canvas, 64, 26, AlignLeft, AlignCenter, "Detecting"); - canvas_draw_str_aligned(canvas, 64, 36, AlignLeft, AlignCenter, "AVR chip..."); - } else { - canvas_draw_str_aligned(canvas, 20, 26, AlignLeft, AlignCenter, "AVR chip"); - canvas_draw_str_aligned(canvas, 20, 36, AlignLeft, AlignCenter, model->name_chip); + switch(model->status) { + case AvrIspWriterViewStatusIDLE: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); + canvas_set_font(canvas, FontSecondary); + elements_button_center(canvas, "Start"); + break; + case AvrIspWriterViewStatusWriting: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); + break; + case AvrIspWriterViewStatusVerification: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); + break; + + default: + break; } - elements_button_left(canvas, "ReDetect"); - elements_button_center(canvas, "Dump"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 27, "Flash"); + snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); + elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_buf); + canvas_draw_str(canvas, 0, 43, "EEPROM"); + snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); + elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_buf); } bool avr_isp_writer_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspWriterView* instance = context; - UNUSED(instance); + bool ret = true; + if(event->key == InputKeyBack || event->type != InputTypeShort) { - return false; - } else if(event->key == InputKeyOk && event->type == InputTypePress) { - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - FURI_LOG_D("s", "--Detecting--"); - avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + if(model->status == AvrIspWriterViewStatusIDLE) { + ret = false; + } + }, + false); + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + FURI_LOG_E("WRITE", "Start %s %s", instance->file_path, instance->file_name); + + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + if(model->status == AvrIspWriterViewStatusIDLE) { + model->status = AvrIspWriterViewStatusWriting; + avr_isp_worker_rw_write_dump_start( + instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + } + }, + false); } - - return true; + return ret; } -// static void -// avr_isp_writer_detect_chip_callback(void* context, const char* name, bool detect_chip) { -// furi_assert(context); -// AvrIspWriterView* instance = context; -// with_view_model( -// instance->view, -// AvrIspWriterViewModel * model, -// { -// model->name_chip = name; -// model->detect_chip = detect_chip; -// icon_animation_stop(model->icon); -// }, -// true); -// } +static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus status) { + furi_assert(context); + AvrIspWriterView* instance = context; + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + switch(status) { + case AvrIspWorkerRWStatusEndWriting: + model->status = AvrIspWriterViewStatusVerification; + avr_isp_worker_rw_verification_start( + instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + break; + case AvrIspWorkerRWStatusEndVerification: + if(instance->callback) + instance->callback(AvrIspCustomEventSceneWritingOk, instance->context); + break; + case AvrIspWorkerRWStatusErrorVerification: + if(instance->callback) + instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); + break; + + default: + //AvrIspWorkerRWStatusErrorWriting; + if(instance->callback) + instance->callback(AvrIspCustomEventSceneErrorWriting, instance->context); + break; + } + }, + true); +} void avr_isp_writer_view_enter(void* context) { furi_assert(context); @@ -98,35 +155,31 @@ void avr_isp_writer_view_enter(void* context) { instance->view, AvrIspWriterViewModel * model, { - icon_animation_start(model->icon); - model->detect_chip = false; + model->status = AvrIspWriterViewStatusIDLE; + model->progress_flash = 0.0f; + model->progress_eeprom = 0.0f; }, - false); + true); //Start avr_isp_worker_rw instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - //avr_isp_worker_rw_set_callback(instance->avr_isp_worker_rw, avr_isp_writer_detect_chip_callback, instance); + avr_isp_worker_rw_set_callback_status( + instance->avr_isp_worker_rw, avr_isp_writer_callback_status, instance); - avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); - - //avr_isp_worker_rw_start(instance->avr_isp_worker_rw); + avr_isp_worker_rw_start(instance->avr_isp_worker_rw); } void avr_isp_writer_view_exit(void* context) { furi_assert(context); AvrIspWriterView* instance = context; + UNUSED(instance); // //Stop avr_isp_worker_rw - // if(avr_isp_avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { - // avr_isp_avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); - // } - avr_isp_worker_rw_free(instance->avr_isp_worker_rw); + if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { + avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); + } - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { icon_animation_stop(model->icon); }, - false); + avr_isp_worker_rw_free(instance->avr_isp_worker_rw); } AvrIspWriterView* avr_isp_writer_view_alloc() { @@ -142,26 +195,12 @@ AvrIspWriterView* avr_isp_writer_view_alloc() { view_set_enter_callback(instance->view, avr_isp_writer_view_enter); view_set_exit_callback(instance->view, avr_isp_writer_view_exit); - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { - model->icon = icon_animation_alloc(&A_ChipLooking_64x64); - view_tie_icon_animation(instance->view, model->icon); - model->detect_chip = false; - }, - false); return instance; } void avr_isp_writer_view_free(AvrIspWriterView* instance) { furi_assert(instance); - with_view_model( - instance->view, - AvrIspWriterViewModel * model, - { icon_animation_free(model->icon); }, - false); view_free(instance->view); free(instance); } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h index aabeb93868d..ba847b78f41 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h @@ -8,6 +8,19 @@ typedef struct AvrIspWriterView AvrIspWriterView; typedef void (*AvrIspWriterViewCallback)(AvrIspCustomEvent event, void* context); +typedef enum { + AvrIspWriterViewStatusIDLE, + AvrIspWriterViewStatusWriting, + AvrIspWriterViewStatusVerification, +} AvrIspWriterViewStatus; + +void avr_isp_writer_update_progress(AvrIspWriterView* instance); + +void avr_isp_writer_set_file_path( + AvrIspWriterView* instance, + const char* file_path, + const char* file_name); + void avr_isp_writer_view_set_callback( AvrIspWriterView* instance, AvrIspWriterViewCallback callback, diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 94713ddba6e..3691c940e57 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -483,7 +483,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { } furi_string_free(file_path); - +path_extract_filename return res; } From 918d1cac7449901dd7a72da9edd0b63fe15ff31a Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 23 Mar 2023 16:14:52 +0400 Subject: [PATCH 29/50] SubGhz: fix --- applications/main/subghz/subghz_i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 3691c940e57..94713ddba6e 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -483,7 +483,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { } furi_string_free(file_path); -path_extract_filename + return res; } From efccf0bd993e9a85bd66936a612fb6941368399b Mon Sep 17 00:00:00 2001 From: SkorP Date: Thu, 23 Mar 2023 22:31:19 +0400 Subject: [PATCH 30/50] AVR_ISP: fix navigation gui --- .../external/avr_isp_programmer/avr_isp_app.c | 1 + .../avr_isp_programmer/avr_isp_app_i.c | 8 ++-- .../avr_isp_programmer/avr_isp_app_i.h | 1 + .../helpers/avr_isp_event.h | 2 + .../helpers/avr_isp_types.h | 9 ++++- .../helpers/avr_isp_worker.c | 2 +- .../helpers/avr_isp_worker_rw.c | 30 ++++++++++++--- .../avr_isp_programmer/lib/driver/clock.png | Bin 0 -> 3649 bytes .../scenes/avr_isp_scene_chip_detect.c | 17 +++++++++ .../scenes/avr_isp_scene_reader.c | 22 ++++++++++- .../scenes/avr_isp_scene_writer.c | 29 ++++++++++++--- .../views/avr_isp_view_chip_detect.c | 6 +++ .../views/avr_isp_view_programmer.c | 4 +- .../views/avr_isp_view_reader.c | 4 +- .../views/avr_isp_view_writer.c | 35 ++++++++++++++---- .../views/avr_isp_view_writer.h | 1 + 16 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 applications/external/avr_isp_programmer/lib/driver/clock.png diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index a86d7a209de..5430a16947a 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -26,6 +26,7 @@ AvrIspApp* avr_isp_app_alloc() { app->file_path = furi_string_alloc(); furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); + app->error = AvrIspErrorNoError; // GUI app->gui = furi_record_open(RECORD_GUI); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.c b/applications/external/avr_isp_programmer/avr_isp_app_i.c index 92b90cecafe..7a7fa6d7f18 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.c +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.c @@ -18,9 +18,11 @@ bool avr_isp_load_from_file(AvrIspApp* app) { // Input events and views are managed by file_select bool res = dialog_file_browser_show(app->dialogs, file_path, app->file_path, &browser_options); - path_extract_dirname(furi_string_get_cstr(file_path), app->file_path); - path_extract_filename(file_path, file_name, true); - strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); + if(res) { + path_extract_dirname(furi_string_get_cstr(file_path), app->file_path); + path_extract_filename(file_path, file_name, true); + strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); + } furi_string_free(file_name); furi_string_free(file_path); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h index 474b1fa46a0..cea0ed50b2a 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.h @@ -41,6 +41,7 @@ typedef struct { AvrIspReaderView* avr_isp_reader_view; AvrIspWriterView* avr_isp_writer_view; AvrIspChipDetectView* avr_isp_chip_detect_view; + AvrIspError error; } AvrIspApp; bool avr_isp_load_from_file(AvrIspApp* app); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index 78537628617..90c2f2a95fe 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -17,4 +17,6 @@ typedef enum { AvrIspCustomEventSceneErrorWriting, AvrIspCustomEventSceneInputName, AvrIspCustomEventSceneSuccess, + AvrIspCustomEventSceneExit, + AvrIspCustomEventSceneExitStartMenu, } AvrIspCustomEvent; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h index 5853239ba8e..c4813e5140c 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h @@ -21,4 +21,11 @@ typedef enum { AvrIspViewPopup, AvrIspViewTextInput, AvrIspViewChipDetect, -} AvrIspView; \ No newline at end of file +} AvrIspView; + +typedef enum { + AvrIspErrorNoError, + AvrIspErrorReading, + AvrIspErrorWriting, + AvrIspErrorVerification, +} AvrIspError; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c index 238e225b472..cefb34b22d8 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c @@ -267,7 +267,7 @@ AvrIspWorker* avr_isp_worker_alloc(void* context) { void avr_isp_worker_free(AvrIspWorker* instance) { furi_assert(instance); - + furi_check(!instance->worker_running); furi_thread_free(instance->thread); free(instance); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 7b5db71a996..e9bd2dbfcc2 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -1003,23 +1003,43 @@ bool avr_isp_worker_rw_write_dump( //write fuse and lock FURI_LOG_D(TAG, "Write fuse"); + ret = true; if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - if(instance->lfuse != lfuse) avr_isp_write_fuse_low(instance->avr_isp, lfuse); + if(instance->lfuse != lfuse) { + if(!avr_isp_write_fuse_low(instance->avr_isp, lfuse)) { + FURI_LOG_E(TAG, "Write Lfuse: error"); + ret = false; + } + } } if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - if(instance->hfuse != hfuse) avr_isp_write_fuse_high(instance->avr_isp, hfuse); + if(instance->hfuse != hfuse) { + if(!avr_isp_write_fuse_high(instance->avr_isp, hfuse)) { + FURI_LOG_E(TAG, "Write Hfuse: error"); + ret = false; + } + } } if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - if(instance->efuse != efuse) avr_isp_write_fuse_extended(instance->avr_isp, efuse); + if(instance->efuse != efuse) { + if(!avr_isp_write_fuse_extended(instance->avr_isp, efuse)) { + FURI_LOG_E(TAG, "Write Efuse: error"); + ret = false; + } + } } if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { FURI_LOG_D(TAG, "Write lock byte"); - if(instance->lock != lock) avr_isp_write_lock_byte(instance->avr_isp, lock); + if(instance->lock != lock) { + if(!avr_isp_write_lock_byte(instance->avr_isp, lock)) { + FURI_LOG_E(TAG, "Write Lock byte: error"); + ret = false; + } + } } avr_isp_end_pmode(instance->avr_isp); - ret = true; } while(false); } diff --git a/applications/external/avr_isp_programmer/lib/driver/clock.png b/applications/external/avr_isp_programmer/lib/driver/clock.png new file mode 100644 index 0000000000000000000000000000000000000000..93a59fe681d26795d0db342a0c55ba42fc2c7529 GIT binary patch literal 3649 zcmaJ@c{r3^8-FYniewGR7?BDy24yB=8_Oum7~4q77=ytqjlm2hDWzn~mNi>R4Q+~K zs}!Vu|T0fG&^kldAlcBl>S5JG204rZ&Cc^O@cJQ3w^Qg>RR zx8UiyV9wOk>ZjF;v5c{`7FO%duw7y*@uRsu02~{khv-s>wL#Z5REF_NqWk$lqN9zk zytcdnfEhj(GnDbrV2$Si72pME9UA+@>IQyYEXSxg0ibxGA1pSuohJ?p)N9z+O91t| zfroZaJcNKm0Ptg-H3kFsgn`K)7W!L&uEK;~X`m~2PoV%1%>$&Wn(yN^d;z#QT)?XF z*1Q6;*@j>Z{+eQ*Fz075bKbDZEkIxlE^eox8xWRitkwj8ba?^PUh!r=kR@L>w7t5& z@H8!=49x@7G$u8t9BC`)=T8#Fi5Kd3nP%I}deUiyHjr{FL+BPCr)96iQo*|Gxw zWS84sZs;1sjg1ZujCzjwaelnX-SC~Eg7p<=`!*`B^YR0t)~%fG(<39De6%{AhXK{T zg)Tt1BjDY)?5foxn0-R%eeiM=OLxt1Z&nVbUQd3H(Dv<9%I-Op(4i>(Us?my{;1GJ z?(RlU@Cl;(z*(Pd0m3+JI=uOHEzjv3{|W7ba-Z zTiteNz1m%IS&-kTUO*hLh=|>6`(r_iNryc~mwsx(;Tr=^)V_UwDya9&K?<&Y%dzv6_Jb4d+LR~!ZNE zNW`rZ7Ub+e48-nAp}2NHnsRfx6sj>_J+I?^8p(^a z6H7uQIVOcBjoq_%@OLoiVBOnpf8Sx}{Zo$T?wC0|!3-4&ew4c3Q7G^5qVRBW3pNNF zi)pnzomX{wJ$!{A{P=Q&S@vago;{)TtxU9{)LR&F7H8Z^cjTK;^Sx>1?(%qf(lT(% zs$3u>#L^Dsf6tTc8Sj}ndZw92F=CQPMg9JsJ6i2I2k`pUBXOL9O0YqO;TCg%%y?5yBfXA<7>V1+AQ++m#Iu& z@fy-$O6z;Fse9bn+FyyizIu3f609e`Hvi3V)q&Q(#uliikvlbn3+ce|Nv8cmQb;;eyXB)R9TO}{CZ#wEbvK$v2Kd~)3Pfn;!kUO3H zFmg`mJJJ#9jnD2Dr5Du(rjz?51|?z-v>#ZoqjYOdu1yL}rcG|0f-mA1l^4m2t@2HK z#N<1VGLD|5GXk0d{b&^v`2*Uo3u_Bsk2`tEdFA+L&g)3uIUd(2mJ*mEZAUJ+RzSHG z+?X^XJ6+!X^ut14`iu15qR-@yUz(6_&fQ#;wp2Uv4bv({VOcwX|1@Kj!qz3_z3mrsE|mH+lOoh{K@UTlTz z(3dpcAt>yuKu@67NYBYF6SR80)Y94{-w9+&o{(FCHmO+d?c5b}xmBP~G?aR0*>b$; znLuQ}xnE?N0!b!Sdik8hfrGGn8sBY8>=M!t2kE_V_%b2YRu6 z{IGt6$@H?YvU_D0m{)$9&ZdYl#PWw&h?FJd?jfejZWm@5x)Ocj zqgJ2i#`k5V?cq{qE8`ww${s%HDq}j&_JgZUUq~rM*+~a!Xu4v{J(#4K_H&KijgOPp zF@rd)!<-MRcP<8dvHkXK)S+-E?WDrQhDJ*9j}y-clK3PK2aZolhl}I+gVIT-*);au z;-3%A%0>sBtWS5GU0{*ByT2YQeK$3Mp2(k|u$P>x9~`UnG3t1Kc}BQMZZ>*E?lk$> zS4K{-&q7RdN%OmAJ{`QyluOeycF$bS;k?D*%=4~|j_XDDORGMsbaz&N2@07PxhOAr z^eZQEvf}9>rju`_>A3|;`*ir1SXp{-d09!qeoQ=$>xS13nwh!9Yx6YG?fovDhPT^Z^Wi45*rTV(sx>kCjTC)tK8Pk@fr;6aM$d`ql?mkGJC1x@NX7N3~WLvkK?w zoco0j5Oqp*3KcCZoH9;%UtOg_s_L5I24=o(g-}=U-eyUE?Ci!GWa-lU zY8YI37x%AHhGB|h*ik(hL3lb5F!G?f6G0YaycZEm#Cx#LG!XRwfKQcVk7MAhED;1M zSp&c6qroK8xM%>-Ghov21YaTp+3>pFg2?`3*2-4D^(!C&>a5x+Sg+X92b*_iHKa0Y^Gu0{nO1~LQi2ejR ziN+vNDWFY8ygN03fdq4t{r4%zw0~$R{(o1BTQdj~PlIS`KsQhI+tJGE|GSdO|9JZ| zu*Co5`#*{O?O8M;1WWX%2G9xI-gzo*hN2-*bRwQXrQ1`fe!mNe@uo7U{@zp?2&Sc> z1yZ%b6G)Uz%YnZjR#pfLia!HSArLK0kYFx}28rZ>(AGYzWd?^Do9aN1Xlk0GjEr@( zOwCY7bYYq>xRw_DH`ato2p|(FjNe#~|6oyn#BK_LOyfp2A<{{KL=Q7Ml??jp)Ckg_ zbAkVn?{BQfpK~$#BNoC<2C~`P|LXN`6IVc+(|^RvUHl_|B897YI#=9}_AkY9FUD4k zrM>B|@Xb4NEn;?-J6Kzo7}+zs^RX^M07#%``usTPM&dJQT7TW0pZvvcreZ!fk89eR zxb$l$y&OrR&%MN0k$&Et1-(znrXGup@9h&S%{ikQa$ LTALIbyM_M?u*zuP literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index f96ecca8dcc..851f4a6fc70 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -10,6 +10,23 @@ void avr_isp_scene_chip_detect_callback(AvrIspCustomEvent event, void* context) void avr_isp_scene_chip_detect_on_enter(void* context) { AvrIspApp* app = context; + switch(app->error) { + case AvrIspErrorReading: + case AvrIspErrorWriting: + avr_isp_chip_detect_set_status( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusErrorOccured); + break; + case AvrIspErrorVerification: + avr_isp_chip_detect_set_status( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusErrorVerification); + break; + + default: + avr_isp_chip_detect_set_status( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusNoDetect); + break; + } + app->error = AvrIspErrorNoError; avr_isp_chip_detect_view_set_callback( app->avr_isp_chip_detect_view, avr_isp_scene_chip_detect_callback, app); diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c index 1b57cbeb82a..52f12e7ba20 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -21,12 +21,32 @@ bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; UNUSED(app); bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { + if(event.type == SceneManagerEventTypeBack) { + //do not handle exit on "Back" + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case AvrIspCustomEventSceneReadingOk: scene_manager_next_scene(app->scene_manager, AvrIspSceneSuccess); consumed = true; break; + case AvrIspCustomEventSceneExit: + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; + case AvrIspCustomEventSceneErrorVerification: + app->error = AvrIspErrorVerification; + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; + case AvrIspCustomEventSceneErrorReading: + app->error = AvrIspErrorReading; + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; default: break; } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c index 999d262bc08..ff288d4b87f 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -10,8 +10,6 @@ void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { void avr_isp_scene_writer_on_enter(void* context) { AvrIspApp* app = context; - - avr_isp_writer_set_file_path( app->avr_isp_writer_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); avr_isp_writer_view_set_callback(app->avr_isp_writer_view, avr_isp_scene_writer_callback, app); @@ -22,10 +20,31 @@ bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { AvrIspApp* app = context; UNUSED(app); bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { + if(event.type == SceneManagerEventTypeBack) { + //do not handle exit on "Back" + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case AvrIspCustomEventSceneWritingOk: - scene_manager_next_scene(app->scene_manager, AvrIspSceneSuccess); + case AvrIspCustomEventSceneExitStartMenu: + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneStart); + consumed = true; + break; + case AvrIspCustomEventSceneExit: + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; + case AvrIspCustomEventSceneErrorVerification: + app->error = AvrIspErrorVerification; + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; + case AvrIspCustomEventSceneErrorWriting: + app->error = AvrIspErrorWriting; + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); consumed = true; break; default: diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 4efc2b59b90..70dff5eee81 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -57,11 +57,17 @@ void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* mo canvas_draw_str_aligned( canvas, 64, 5, AlignCenter, AlignCenter, "Error occured, try again!"); canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 45, AlignCenter, AlignCenter, "Check the wiring and retry"); break; case AvrIspChipDetectViewStatusErrorVerification: canvas_draw_str_aligned( canvas, 64, 5, AlignCenter, AlignCenter, "Data verification failed"); canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 45, AlignCenter, AlignCenter, "Try to restart the process"); break; default: diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 12daf94c456..1276d5f175b 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -29,8 +29,8 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod canvas_clear(canvas); if(model->status == AvrIspProgrammerViewStatusUSBConnect) { canvas_set_font(canvas, FontPrimary); - canvas_draw_icon(canvas, 0, 11, &I_isp_active_128x53); - elements_multiline_text(canvas, 40, 10, "ISP mode active"); + canvas_draw_icon(canvas, 0, 0, &I_isp_active_128x53); + elements_multiline_text(canvas, 45, 10, "ISP mode active"); } else { canvas_set_font(canvas, FontSecondary); canvas_draw_icon(canvas, 51, 6, &I_link_waiting_77x56); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 1fc22a8761e..0bf8317f629 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -87,12 +87,14 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { AvrIspReaderView* instance = context; bool ret = true; - if(event->key == InputKeyBack || event->type != InputTypeShort) { + if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( instance->view, AvrIspReaderViewModel * model, { if(model->status == AvrIspReaderViewStatusIDLE) { + if(instance->callback) + instance->callback(AvrIspCustomEventSceneExit, instance->context); ret = false; } }, diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index aa3f93f350f..5fad21fe341 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -68,6 +68,11 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { case AvrIspWriterViewStatusVerification: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); break; + case AvrIspWriterViewStatusVerificationOk: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); + elements_button_center(canvas, "Reflash"); + elements_button_right(canvas, "Exit"); + break; default: break; @@ -87,30 +92,45 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { AvrIspWriterView* instance = context; bool ret = true; - if(event->key == InputKeyBack || event->type != InputTypeShort) { + if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( instance->view, AvrIspWriterViewModel * model, { - if(model->status == AvrIspWriterViewStatusIDLE) { + if((model->status == AvrIspWriterViewStatusIDLE) || + (model->status == AvrIspWriterViewStatusVerificationOk)) { + if(instance->callback) + instance->callback(AvrIspCustomEventSceneExit, instance->context); ret = false; } }, false); } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - FURI_LOG_E("WRITE", "Start %s %s", instance->file_path, instance->file_name); - with_view_model( instance->view, AvrIspWriterViewModel * model, { - if(model->status == AvrIspWriterViewStatusIDLE) { + if((model->status == AvrIspWriterViewStatusIDLE) || + (model->status == AvrIspWriterViewStatusVerificationOk)) { model->status = AvrIspWriterViewStatusWriting; avr_isp_worker_rw_write_dump_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); } }, false); + } else if(event->key == InputKeyRight && event->type == InputTypeShort) { + with_view_model( + instance->view, + AvrIspWriterViewModel * model, + { + if((model->status == AvrIspWriterViewStatusIDLE) || + (model->status == AvrIspWriterViewStatusVerificationOk)) { + if(instance->callback) + instance->callback(AvrIspCustomEventSceneExitStartMenu, instance->context); + ret = false; + } + }, + false); } return ret; } @@ -129,8 +149,9 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s instance->avr_isp_worker_rw, instance->file_path, instance->file_name); break; case AvrIspWorkerRWStatusEndVerification: - if(instance->callback) - instance->callback(AvrIspCustomEventSceneWritingOk, instance->context); + // if(instance->callback) + // instance->callback(AvrIspCustomEventSceneWritingOk, instance->context); + model->status = AvrIspWriterViewStatusVerificationOk; break; case AvrIspWorkerRWStatusErrorVerification: if(instance->callback) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h index ba847b78f41..917b401db7f 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h @@ -12,6 +12,7 @@ typedef enum { AvrIspWriterViewStatusIDLE, AvrIspWriterViewStatusWriting, AvrIspWriterViewStatusVerification, + AvrIspWriterViewStatusVerificationOk, } AvrIspWriterViewStatus; void avr_isp_writer_update_progress(AvrIspWriterView* instance); From 21019fc7330d841f679ca3168849e04b653c1e41 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 11:12:39 +0400 Subject: [PATCH 31/50] AVR_ISP: refactoring --- .../external/avr_isp_programmer/avr_isp_app.c | 14 -- .../avr_isp_programmer/avr_isp_app_i.h | 3 - .../avr_isp_programmer/helpers/avr_isp.c | 25 +++- .../avr_isp_programmer/helpers/avr_isp.h | 4 + .../helpers/avr_isp_worker.c | 51 +------ .../helpers/avr_isp_worker.h | 6 - .../helpers/avr_isp_worker_rw.c | 124 ++++-------------- .../helpers/avr_isp_worker_rw.h | 20 --- .../helpers/flipper_i32hex_file.c | 6 + .../helpers/flipper_i32hex_file.h | 8 ++ .../scenes/avr_isp_scene_about.c | 56 ++++++-- .../scenes/avr_isp_scene_chip_detect.c | 19 +-- .../scenes/avr_isp_scene_input_name.c | 42 ++---- .../scenes/avr_isp_scene_load.c | 15 +-- .../scenes/avr_isp_scene_programmer.c | 22 +--- .../scenes/avr_isp_scene_reader.c | 7 +- .../scenes/avr_isp_scene_start.c | 9 +- .../scenes/avr_isp_scene_success.c | 26 ++-- .../scenes/avr_isp_scene_wiring.c | 5 +- .../scenes/avr_isp_scene_writer.c | 8 +- .../views/avr_isp_view_chip_detect.c | 42 +++--- .../views/avr_isp_view_chip_detect.h | 16 +-- .../views/avr_isp_view_programmer.c | 13 +- .../views/avr_isp_view_reader.c | 12 +- .../views/avr_isp_view_writer.c | 15 ++- 25 files changed, 231 insertions(+), 337 deletions(-) diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index 5430a16947a..36212de8592 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -1,8 +1,5 @@ #include "avr_isp_app_i.h" -#include -#include - static bool avr_isp_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); AvrIspApp* app = context; @@ -49,13 +46,6 @@ AvrIspApp* avr_isp_app_alloc() { // Open Notification record app->notifications = furi_record_open(RECORD_NOTIFICATION); - // // Variable Item List - // app->variable_item_list = variable_item_list_alloc(); - // view_dispatcher_add_view( - // app->view_dispatcher, - // AvrIspViewVariableItemList, - // variable_item_list_get_view(app->variable_item_list)); - // SubMenu app->submenu = submenu_alloc(); view_dispatcher_add_view( @@ -117,10 +107,6 @@ void avr_isp_app_free(AvrIspApp* app) { view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu); submenu_free(app->submenu); - // // Variable Item List - // view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewVariableItemList); - // variable_item_list_free(app->variable_item_list); - // Widget view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWidget); widget_free(app->widget); diff --git a/applications/external/avr_isp_programmer/avr_isp_app_i.h b/applications/external/avr_isp_programmer/avr_isp_app_i.h index cea0ed50b2a..17c69f8f2e2 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app_i.h +++ b/applications/external/avr_isp_programmer/avr_isp_app_i.h @@ -14,7 +14,6 @@ #include #include #include -//#include #include "views/avr_isp_view_programmer.h" #include "views/avr_isp_view_reader.h" @@ -30,12 +29,10 @@ typedef struct { NotificationApp* notifications; DialogsApp* dialogs; Popup* popup; - //VariableItemList* variable_item_list; Submenu* submenu; Widget* widget; TextInput* text_input; FuriString* file_path; - //FuriString* file_name; char file_name_tmp[AVR_ISP_MAX_LEN_NAME]; AvrIspProgrammerView* avr_isp_programmer_view; AvrIspReaderView* avr_isp_reader_view; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 5766dc92037..2cdb230277e 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -21,6 +21,7 @@ AvrIsp* avr_isp_alloc(void) { void avr_isp_free(AvrIsp* instance) { furi_assert(instance); + if(instance->spi) avr_isp_end_pmode(instance); free(instance); } @@ -28,6 +29,7 @@ void avr_isp_free(AvrIsp* instance) { void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context) { furi_assert(instance); furi_assert(context); + instance->callback = callback; instance->context = context; } @@ -48,6 +50,7 @@ uint8_t avr_isp_spi_transaction( static bool avr_isp_set_pmode(AvrIsp* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) { furi_assert(instance); + uint8_t res = 0; avr_isp_spi_sw_txrx(instance->spi, a); avr_isp_spi_sw_txrx(instance->spi, b); @@ -58,6 +61,7 @@ static bool avr_isp_set_pmode(AvrIsp* instance, uint8_t a, uint8_t b, uint8_t c, void avr_isp_end_pmode(AvrIsp* instance) { furi_assert(instance); + if(instance->pmode) { avr_isp_spi_sw_res_set(instance->spi, true); // We're about to take the target out of reset @@ -71,6 +75,7 @@ void avr_isp_end_pmode(AvrIsp* instance) { static bool avr_isp_start_pmode(AvrIsp* instance, AvrIspSpiSwSpeed spi_speed) { furi_assert(instance); + // Reset target before driving PIN_SCK or PIN_MOSI // SPI.begin() will configure SS as output, @@ -109,6 +114,8 @@ static bool avr_isp_start_pmode(AvrIsp* instance, AvrIspSpiSwSpeed spi_speed) { } bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { + furi_assert(instance); + AvrIspSpiSwSpeed spi_speed[] = { AvrIspSpiSwSpeed1Mhz, AvrIspSpiSwSpeed400Khz, @@ -127,6 +134,7 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { furi_assert(instance); + avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr)); /* polling flash */ if(data == 0xFF) { @@ -144,6 +152,7 @@ static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { static uint16_t avr_isp_current_page(AvrIsp* instance, uint32_t addr, uint16_t page_size) { furi_assert(instance); + uint16_t page = 0; switch(page_size) { case 32: @@ -193,8 +202,8 @@ static bool avr_isp_flash_write_pages( bool avr_isp_erase_chip(AvrIsp* instance) { furi_assert(instance); - bool ret = false; + bool ret = false; if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance); if(instance->pmode) { avr_isp_spi_transaction(instance, AVR_ISP_ERASE_CHIP); @@ -226,8 +235,8 @@ bool avr_isp_write_page( uint8_t* data, uint32_t data_size) { furi_assert(instance); - bool ret = false; + bool ret = false; switch(mem_type) { case STK_SET_FLASH_TYPE: if((addr + data_size / 2) <= mem_size) { @@ -256,6 +265,7 @@ static bool avr_isp_flash_read_page( uint8_t* data, uint32_t data_size) { furi_assert(instance); + if(page_size > data_size) return false; for(uint16_t i = 0; i < page_size; i += 2) { data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(addr)); @@ -272,6 +282,7 @@ static bool avr_isp_eeprom_read_page( uint8_t* data, uint32_t data_size) { furi_assert(instance); + if(page_size > data_size) return false; for(uint16_t i = 0; i < page_size; i++) { data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr)); @@ -288,6 +299,7 @@ bool avr_isp_read_page( uint8_t* data, uint32_t data_size) { furi_assert(instance); + bool res = false; if(mem_type == STK_SET_FLASH_TYPE) res = avr_isp_flash_read_page(instance, addr, page_size, data, data_size); @@ -299,6 +311,7 @@ bool avr_isp_read_page( AvrIspSignature avr_isp_read_signature(AvrIsp* instance) { furi_assert(instance); + AvrIspSignature signature; signature.vendor = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR); signature.part_family = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); @@ -308,6 +321,7 @@ AvrIspSignature avr_isp_read_signature(AvrIsp* instance) { uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { furi_assert(instance); + uint8_t data = 0; uint32_t starttime = furi_get_tick(); while((furi_get_tick() - starttime) < 300) { @@ -322,6 +336,7 @@ uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { furi_assert(instance); + bool ret = false; if(avr_isp_read_lock_byte(instance) == lock) { ret = true; @@ -341,6 +356,7 @@ bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { furi_assert(instance); + uint8_t data = 0; uint32_t starttime = furi_get_tick(); while((furi_get_tick() - starttime) < 300) { @@ -355,6 +371,7 @@ uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { furi_assert(instance); + bool ret = false; if(avr_isp_read_fuse_low(instance) == lfuse) { ret = true; @@ -374,6 +391,7 @@ bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { furi_assert(instance); + uint8_t data = 0; uint32_t starttime = furi_get_tick(); while((furi_get_tick() - starttime) < 300) { @@ -388,6 +406,7 @@ uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { furi_assert(instance); + bool ret = false; if(avr_isp_read_fuse_high(instance) == hfuse) { ret = true; @@ -407,6 +426,7 @@ bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { furi_assert(instance); + uint8_t data = 0; uint32_t starttime = furi_get_tick(); while((furi_get_tick() - starttime) < 300) { @@ -421,6 +441,7 @@ uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { furi_assert(instance); + bool ret = false; if(avr_isp_read_fuse_extended(instance) == efuse) { ret = true; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.h b/applications/external/avr_isp_programmer/helpers/avr_isp.h index 7041d6c469b..bb029f6ada3 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.h @@ -52,13 +52,17 @@ bool avr_isp_write_page( uint32_t data_size); uint8_t avr_isp_read_lock_byte(AvrIsp* instance); + bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock); uint8_t avr_isp_read_fuse_low(AvrIsp* instance); + bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse); uint8_t avr_isp_read_fuse_high(AvrIsp* instance); + bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse); uint8_t avr_isp_read_fuse_extended(AvrIsp* instance); + bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c index cefb34b22d8..dfe1f43c2c3 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.c @@ -122,52 +122,6 @@ static void avr_isp_worker_vcp_cdc_deinit(void) { //################################################################################# -// void avr_isp_worker_detect_chip(AvrIspWorker* instance) { -// uint8_t buf_cmd[] = { -// STK_ENTER_PROGMODE, CRC_EOP, STK_READ_SIGN, CRC_EOP, STK_LEAVE_PROGMODE, CRC_EOP}; - -// uint8_t buf_data[64] = {0}; -// size_t ind = 0; - -// FURI_LOG_D(TAG, "Detecting AVR chip"); -// AvrIspProg* prog = avr_isp_prog_init(); -// avr_isp_prog_rx(prog, buf_cmd, sizeof(buf_cmd)); - -// for(uint8_t i = 0; i < 3; i++) { -// avr_isp_prog_avrisp(prog); -// } -// size_t len = avr_isp_prog_tx(prog, buf_data, sizeof(buf_data)); -// UNUSED(len); - -// if(buf_data[2] == STK_INSYNC && buf_data[6] == STK_OK) { -// if(buf_data[3] != 0x1E) { -// ind = avr_isp_chip_arr_size + 1; //No detect chip -// } else { -// for(ind = 0; ind < avr_isp_chip_arr_size; ind++) { -// if(avr_isp_chip_arr[ind].avrarch != F_AVR8) continue; -// if(avr_isp_chip_arr[ind].sigs[1] == buf_data[4]) { -// if(avr_isp_chip_arr[ind].sigs[2] == buf_data[5]) { -// FURI_LOG_D(TAG, "Detect AVR chip = \"%s\"", avr_isp_chip_arr[ind].name); -// break; -// } -// } -// } -// } -// } -// avr_isp_prog_free(prog); -// if(instance->callback) { -// if(ind > avr_isp_chip_arr_size) { -// //ToDo add output ID chip -// instance->callback(instance->context, "No detect"); -// } else if(ind < avr_isp_chip_arr_size) { -// instance->callback(instance->context, avr_isp_chip_arr[ind].name); -// } else { -// //ToDo add output ID chip -// instance->callback(instance->context, "Unknown"); -// } -// } -// } - static int32_t avr_isp_worker_prog_thread(void* context) { AvrIspProg* prog = context; FURI_LOG_D(TAG, "AvrIspProgWorker Start"); @@ -208,6 +162,7 @@ static int32_t avr_isp_worker_thread(void* context) { furi_thread_start(prog_thread); FURI_LOG_D(TAG, "Start"); + while(instance->worker_running) { uint32_t events = furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); @@ -243,7 +198,9 @@ static int32_t avr_isp_worker_thread(void* context) { instance->callback(instance->context, (bool)instance->connect_usb); } } + FURI_LOG_D(TAG, "Stop"); + furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop); avr_isp_prog_exit(prog); furi_delay_ms(10); @@ -278,6 +235,7 @@ void avr_isp_worker_set_callback( AvrIspWorkerCallback callback, void* context) { furi_assert(instance); + instance->callback = callback; instance->context = context; } @@ -303,5 +261,6 @@ void avr_isp_worker_stop(AvrIspWorker* instance) { bool avr_isp_worker_is_running(AvrIspWorker* instance) { furi_assert(instance); + return instance->worker_running; } diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h index d92e14c44b8..cd9897dff3f 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker.h @@ -47,9 +47,3 @@ void avr_isp_worker_stop(AvrIspWorker* instance); * @return bool - true if running */ bool avr_isp_worker_is_running(AvrIspWorker* instance); - -// /** Detect chip -// * -// * @param instance AvrIspWorker instance -// */ -// void avr_isp_worker_detect_chip(AvrIspWorker* instance); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index e9bd2dbfcc2..8a5f2cf4b01 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -62,6 +62,7 @@ static int32_t avr_isp_worker_rw_thread(void* context) { furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50); FURI_LOG_D(TAG, "Start"); + while(1) { uint32_t events = furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); @@ -115,7 +116,9 @@ static int32_t avr_isp_worker_rw_thread(void* context) { bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { furi_assert(instance); + FURI_LOG_D(TAG, "Detecting AVR chip"); + instance->chip_detect = false; instance->chip_arr_ind = avr_isp_chip_arr_size + 1; @@ -187,9 +190,7 @@ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { } while(0); if(instance->callback) { if(instance->chip_arr_ind > avr_isp_chip_arr_size) { - //ToDo add output ID chip instance->callback(instance->context, "No detect", instance->chip_detect, 0); - } else if(instance->chip_arr_ind < avr_isp_chip_arr_size) { instance->callback( instance->context, @@ -197,7 +198,6 @@ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { instance->chip_detect, avr_isp_chip_arr[instance->chip_arr_ind].flashsize); } else { - //ToDo add output ID chip instance->callback(instance->context, "Unknown", instance->chip_detect, 0); } } @@ -208,6 +208,7 @@ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance) { AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context) { furi_assert(context); UNUSED(context); + AvrIspWorkerRW* instance = malloc(sizeof(AvrIspWorkerRW)); instance->avr_isp = avr_isp_alloc(); @@ -257,6 +258,7 @@ void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance) { bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance) { furi_assert(instance); + return instance->worker_running; } @@ -265,6 +267,7 @@ void avr_isp_worker_rw_set_callback( AvrIspWorkerRWCallback callback, void* context) { furi_assert(instance); + instance->callback = callback; instance->context = context; } @@ -274,21 +277,24 @@ void avr_isp_worker_rw_set_callback_status( AvrIspWorkerRWStatusCallback callback_status, void* context_status) { furi_assert(instance); + instance->callback_status = callback_status; instance->context_status = context_status; } float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance) { furi_assert(instance); + return instance->progress_flash; } float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance) { furi_assert(instance); + return instance->progress_eeprom; } -void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const char* file_path) { +static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); @@ -320,7 +326,7 @@ void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const char* file instance->progress_flash = 1.0f; } -void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const char* file_path) { +static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); @@ -357,6 +363,7 @@ bool avr_isp_worker_rw_read_dump( furi_assert(file_name); FURI_LOG_D(TAG, "Read dump chip"); + instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; bool ret = false; @@ -468,16 +475,18 @@ void avr_isp_worker_rw_read_dump_start( const char* file_path, const char* file_name) { furi_assert(instance); + instance->file_path = file_path; instance->file_name = file_name; furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtReading); } -bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* file_path) { +static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_assert(file_path); FURI_LOG_D(TAG, "Verification flash %s", file_path); + instance->progress_flash = 0.0; bool ret = true; @@ -494,11 +503,6 @@ bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && ret) { - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_hex[i]); - // } - // printf("\r\n"); - switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: avr_isp_read_page( @@ -509,11 +513,6 @@ bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* data_read_flash, sizeof(data_read_flash)); - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_flash[i]); - // } - // printf("\r\n"); - if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { ret = false; FURI_LOG_E(TAG, "Verification flash error"); @@ -543,11 +542,13 @@ bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const char* return ret; } -bool avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* file_path) { +static bool + avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_assert(file_path); FURI_LOG_D(TAG, "Verification eeprom %s", file_path); + instance->progress_eeprom = 0.0; bool ret = true; @@ -564,11 +565,6 @@ bool avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* while(((flipper_hex_ret.status == FlipperI32HexFileStatusData) || (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) && ret) { - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_hex[i]); - // } - // printf("\r\n"); - switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: avr_isp_read_page( @@ -579,11 +575,6 @@ bool avr_isp_worker_rw_verification_eeprom(AvrIspWorkerRW* instance, const char* data_read_eeprom, sizeof(data_read_eeprom)); - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data_read_eeprom[i]); - // } - // printf("\r\n"); - if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { ret = false; FURI_LOG_E(TAG, "Verification eeprom error"); @@ -656,67 +647,20 @@ void avr_isp_worker_rw_verification_start( const char* file_path, const char* file_name) { furi_assert(instance); + instance->file_path = file_path; instance->file_name = file_name; furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtVerification); } -// bool avr_isp_worker_rw_check_hex( -// AvrIspWorkerRW* instance, -// const char* file_path, -// const char* file_name) { -// furi_assert(instance); -// furi_assert(file_path); -// furi_assert(file_name); - -// FuriString* file_path_name = furi_string_alloc(); -// bool ret = false; -// bool check_flash = true; -// bool check_eeprom = true; - -// do { -// furi_string_printf( -// file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_FLASH_FILE); - -// FURI_LOG_D(TAG, "Check flash file"); -// FlipperI32HexFile* flipper_hex_flash_read = -// flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); -// if(flipper_i32hex_file_check(flipper_hex_flash_read)) { -// FURI_LOG_D(TAG, "Check flash file: OK"); -// } else { -// FURI_LOG_D(TAG, "Check flash file: Error"); -// check_flash = false; -// } -// flipper_i32hex_file_close(flipper_hex_flash_read); - -// if(avr_isp_chip_arr[instance->chip_arr_ind].eepromsize > 0) { -// furi_string_printf( -// file_path_name, "%s/%s_%s", file_path, file_name, NAME_PATERN_EEPROM_FILE); - -// FURI_LOG_D(TAG, "Check eeprom file"); -// FlipperI32HexFile* flipper_hex_eeprom_read = -// flipper_i32hex_file_open_read(furi_string_get_cstr(file_path_name)); -// if(flipper_i32hex_file_check(flipper_hex_eeprom_read)) { -// FURI_LOG_D(TAG, "Check eeprom file: OK"); -// } else { -// FURI_LOG_D(TAG, "Check eeprom file: Error"); -// check_eeprom = false; -// } -// flipper_i32hex_file_close(flipper_hex_eeprom_read); -// } - -// if(check_flash && check_eeprom) ret = true; -// } while(false); -// furi_string_free(file_path_name); -// return ret; -// } - -void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_path) { +static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); + instance->progress_flash = 0.0; FURI_LOG_D(TAG, "Write Flash %s", file_path); + uint8_t data[288] = {0}; FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); @@ -727,12 +671,6 @@ void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_pa while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - // FURI_LOG_D(TAG, "EEPROM WRITE Page1"); - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data[i]); - // } - // printf("\r\n"); - switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: if(!avr_isp_write_page( @@ -767,11 +705,13 @@ void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* file_pa instance->progress_flash = 1.0f; } -void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* file_path) { +static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* file_path) { furi_assert(instance); furi_check(instance->avr_isp); + instance->progress_eeprom = 0.0; uint8_t data[288] = {0}; + FURI_LOG_D(TAG, "Write EEPROM %s", file_path); FlipperI32HexFile* flipper_hex_eeprom_read = flipper_i32hex_file_open_read(file_path); @@ -782,12 +722,6 @@ void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* file_p while((flipper_hex_ret.status == FlipperI32HexFileStatusData) || (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { - // FURI_LOG_D(TAG, "EEPROM WRITE Page"); - // for(size_t i = 0; i < flipper_hex_ret.data_size; i++) { - // printf("%02X ", data[i]); - // } - // printf("\r\n"); - switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: if(!avr_isp_write_page( @@ -832,6 +766,7 @@ bool avr_isp_worker_rw_write_dump( furi_assert(file_name); FURI_LOG_D(TAG, "Write dump chip"); + instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; bool ret = false; @@ -873,12 +808,6 @@ bool avr_isp_worker_rw_write_dump( break; } - // if(!flipper_format_write_string_cstr( - // flipper_format, "Chip name", avr_isp_chip_arr[instance->chip_arr_ind].name)) { - // FURI_LOG_E(TAG, "Chip name"); - // break; - // } - AvrIspSignature sig_read = {0}; if(!flipper_format_read_hex( @@ -1055,6 +984,7 @@ void avr_isp_worker_rw_write_dump_start( const char* file_path, const char* file_name) { furi_assert(instance); + instance->file_path = file_path; instance->file_name = file_name; furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWriting); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h index 22f8a2052d9..26dc02a6e7d 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h @@ -25,17 +25,8 @@ typedef enum { typedef void (*AvrIspWorkerRWStatusCallback)(void* context, AvrIspWorkerRWStatus status); -/** Allocate AvrIspWorkerRW - * - * @param context AvrIsp* context - * @return AvrIspWorkerRW* - */ AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context); -/** Free AvrIspWorkerRW - * - * @param instance AvrIspWorkerRW instance - */ void avr_isp_worker_rw_free(AvrIspWorkerRW* instance); void avr_isp_worker_rw_start(AvrIspWorkerRW* instance); @@ -44,12 +35,6 @@ void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance); bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance); -/** Callback AvrIspWorkerRW - * - * @param instance AvrIspWorkerRW instance - * @param callback AvrIspWorkerRWOverrunCallback callback - * @param context - */ void avr_isp_worker_rw_set_callback( AvrIspWorkerRW* instance, AvrIspWorkerRWCallback callback, @@ -60,11 +45,6 @@ void avr_isp_worker_rw_set_callback_status( AvrIspWorkerRWStatusCallback callback_status, void* context_status); -/** Detect chip - * - * @param instance AvrIspWorkerRW instance - * @return bool - */ bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance); float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance); diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c index 69f2782ea2e..5584a977e69 100644 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -69,6 +69,7 @@ FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) { void flipper_i32hex_file_close(FlipperI32HexFile* instance) { furi_assert(instance); + furi_string_free(instance->str_data); file_stream_close(instance->stream); stream_free(instance->stream); @@ -127,6 +128,7 @@ FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance) { furi_assert(instance); + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) { ret.status = FlipperI32HexFileStatusErrorFileWrite; @@ -140,11 +142,13 @@ FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32He void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) { furi_assert(instance); + instance->addr = addr; } const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance) { furi_assert(instance); + return furi_string_get_cstr(instance->str_data); } @@ -200,6 +204,7 @@ static FlipperI32HexFileRet flipper_i32hex_file_parse_line( static bool flipper_i32hex_file_check_data(uint8_t* data, uint32_t data_size) { furi_assert(data); + uint8_t crc = 0; uint32_t data_read_ind = 0; if(data[0] > data_size) return false; @@ -301,6 +306,7 @@ FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( uint32_t data_size) { furi_assert(instance); furi_assert(data); + FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0}; if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) { ret.status = FlipperI32HexFileStatusErrorFileRead; diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h index 3d81c5deb0e..765b94beb59 100644 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h +++ b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h @@ -31,16 +31,24 @@ typedef struct { } FlipperI32HexFileRet; FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr); + FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name); + void flipper_i32hex_file_close(FlipperI32HexFile* instance); + FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( FlipperI32HexFile* instance, uint8_t* data, uint32_t data_size); + FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance); + const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance); + void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr); + bool flipper_i32hex_file_check(FlipperI32HexFile* instance); + FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data( FlipperI32HexFile* instance, uint8_t* data, diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c index 54d74d6bd0e..e5f530fec89 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c @@ -2,6 +2,8 @@ #include "../helpers/avr_isp_types.h" void avr_isp_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + AvrIspApp* app = context; if(type == InputTypeShort) { view_dispatcher_send_custom_event(app->view_dispatcher, result); @@ -9,10 +11,10 @@ void avr_isp_scene_about_widget_callback(GuiButtonType result, InputType type, v } void avr_isp_scene_about_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); - FuriString* temp_str; - temp_str = furi_string_alloc(); + AvrIspApp* app = context; + FuriString* temp_str = furi_string_alloc(); furi_string_printf(temp_str, "\e#%s\n", "Information"); furi_string_cat_printf(temp_str, "Version: %s\n", AVR_ISP_VERSION_APP); @@ -20,9 +22,41 @@ void avr_isp_scene_about_on_enter(void* context) { furi_string_cat_printf(temp_str, "Github: %s\n\n", AVR_ISP_GITHUB); furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); - furi_string_cat_printf(temp_str, "AVR ISP Programmer\nBla Bla Bla\nbla bla bla\n\n"); + furi_string_cat_printf( + temp_str, + "This application is an AVR in-system programmer based on stk500mk1. It is compatible with AVR-based" + " microcontrollers including Arduino. You can also use it to repair the chip if you accidentally" + " corrupt the bootloader.\n\n"); + + furi_string_cat_printf(temp_str, "\e#%s\n", "What it can do:"); + furi_string_cat_printf(temp_str, "- Create a dump of your chip on an SD card\n"); + furi_string_cat_printf(temp_str, "- Flash your chip firmware from the SD card\n"); + furi_string_cat_printf(temp_str, "- Act as a wired USB ISP using avrdude software\n\n"); + + furi_string_cat_printf(temp_str, "\e#%s\n", "Supported chip series:"); + furi_string_cat_printf( + temp_str, + "Example command for avrdude flashing: avrdude.exe -p m328p -c stk500v1 -P COMxx -U flash:r:" + "X:\\sketch_sample.hex" + ":i\n"); + furi_string_cat_printf( + temp_str, + "Where: " + "-p m328p" + " brand of your chip, " + "-P COMxx" + " com port number in the system when " + "ISP Programmer" + " is enabled\n\n"); - furi_string_cat_printf(temp_str, "Supported protocols:\n"); + furi_string_cat_printf(temp_str, "\e#%s\n", "Info"); + furi_string_cat_printf( + temp_str, + "ATtinyXXXX\nATmegaXXXX\nAT43Uxxx\nAT76C711\nAT86RF401\nAT90xxxxx\nAT94K\n" + "ATAxxxxx\nATA664251\nM3000\nLGT8F88P\nLGT8F168P\nLGT8F328P\n"); + + furi_string_cat_printf( + temp_str, "For a more detailed list of supported chips, see AVRDude help\n"); widget_add_text_box_element( app->widget, @@ -42,7 +76,7 @@ void avr_isp_scene_about_on_enter(void* context) { 14, AlignCenter, AlignBottom, - "\e#\e! AVR ISP Programmer \e!\n", + "\e#\e! ISP Programmer \e!\n", false); widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); furi_string_free(temp_str); @@ -51,17 +85,15 @@ void avr_isp_scene_about_on_enter(void* context) { } bool avr_isp_scene_about_on_event(void* context, SceneManagerEvent event) { - AvrIspApp* app = context; - bool consumed = false; - UNUSED(app); + UNUSED(context); UNUSED(event); - - return consumed; + return false; } void avr_isp_scene_about_on_exit(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; // Clear views widget_reset(app->widget); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index 851f4a6fc70..c43803ffe03 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -1,29 +1,30 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_chip_detect.h" void avr_isp_scene_chip_detect_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } void avr_isp_scene_chip_detect_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; switch(app->error) { case AvrIspErrorReading: case AvrIspErrorWriting: - avr_isp_chip_detect_set_status( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusErrorOccured); + avr_isp_chip_detect_set_state( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorOccured); break; case AvrIspErrorVerification: - avr_isp_chip_detect_set_status( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusErrorVerification); + avr_isp_chip_detect_set_state( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorVerification); break; default: - avr_isp_chip_detect_set_status( - app->avr_isp_chip_detect_view, AvrIspChipDetectViewStatusNoDetect); + avr_isp_chip_detect_set_state( + app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateNoDetect); break; } app->error = AvrIspErrorNoError; @@ -34,6 +35,8 @@ void avr_isp_scene_chip_detect_on_enter(void* context) { } bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c index 2264a787ea4..3394f4362a6 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c @@ -1,12 +1,11 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_programmer.h" -#include #include #define MAX_TEXT_INPUT_LEN 22 void avr_isp_scene_input_name_text_callback(void* context) { furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneInputName); } @@ -26,39 +25,19 @@ void avr_isp_scene_input_name_get_timefilename(FuriString* name) { } void avr_isp_scene_input_name_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; // Setup view TextInput* text_input = app->text_input; bool dev_name_empty = false; - FuriString* file_name; - //FuriString* dir_name; - file_name = furi_string_alloc(); - //dir_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); - //if(!app_path_is_file(app->file_path)) { - char file_name_buf[AVR_ISP_MAX_LEN_NAME] = {0}; - set_random_name(file_name_buf, AVR_ISP_MAX_LEN_NAME); - furi_string_set(file_name, file_name_buf); + avr_isp_scene_input_name_get_timefilename(file_name); furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); //highlighting the entire filename by default dev_name_empty = true; - //} - //else { - // furi_string_set(app->file_path_tmp, app->file_path); - // path_extract_dirname(furi_string_get_cstr(app->file_path), dir_name); - // path_extract_filename(app->file_path, file_name, true); - // if(scene_manager_get_scene_state(app->scene_manager, SubGhzSceneReadRAW) != - // SubGhzCustomEventManagerNoSet) { - // if(scene_manager_get_scene_state(app->scene_manager, SubGhzSceneReadRAW) == - // SubGhzCustomEventManagerSetRAW) { - // dev_name_empty = true; - // avr_isp_scene_input_name_get_timefilename(file_name); - // } - // } - // furi_string_set(app->file_path, dir_name); - // } strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME); text_input_set_header_text(text_input, "Name dump"); @@ -75,12 +54,13 @@ void avr_isp_scene_input_name_on_enter(void* context) { text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); furi_string_free(file_name); - //furi_string_free(dir_name); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewTextInput); } bool avr_isp_scene_input_name_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; if(event.type == SceneManagerEventTypeBack) { scene_manager_previous_scene(app->scene_manager); @@ -88,12 +68,8 @@ bool avr_isp_scene_input_name_on_event(void* context, SceneManagerEvent event) { } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == AvrIspCustomEventSceneInputName) { if(strcmp(app->file_name_tmp, "") != 0) { - //furi_string_set(file_name, app->file_name_tmp); scene_manager_next_scene(app->scene_manager, AvrIspSceneReader); } else { - // furi_string_set(app->error_str, "No name file"); - // scene_manager_next_scene(app->scene_manager, SubGhzSceneShowErrorSub); - // return true; } } } @@ -101,13 +77,13 @@ bool avr_isp_scene_input_name_on_event(void* context, SceneManagerEvent event) { } void avr_isp_scene_input_name_on_exit(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; // Clear validator void* validator_context = text_input_get_validator_callback_context(app->text_input); text_input_set_validator(app->text_input, NULL, NULL); validator_is_file_free(validator_context); - // Clear view text_input_reset(app->text_input); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c index 9c0741314f6..e8890e37381 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c @@ -1,23 +1,14 @@ #include "../avr_isp_app_i.h" void avr_isp_scene_load_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; if(avr_isp_load_from_file(app)) { scene_manager_next_scene(app->scene_manager, AvrIspSceneWriter); } else { - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, AvrIspSceneStart); + scene_manager_previous_scene(app->scene_manager); } - // if(avr_isp_load_protocol_from_file(subghz)) { - // if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { - // subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; - // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); - // } else { - // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); - // } - // } else { - // scene_manager_search_and_switch_to_previous_scene(subghz->scene_manager, SubGhzSceneStart); - // } } bool avr_isp_scene_load_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c index 3e6b530f78c..0915e1e8a2a 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c @@ -1,15 +1,16 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_programmer.h" void avr_isp_scene_programmer_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } void avr_isp_scene_programmer_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; avr_isp_programmer_view_set_callback( app->avr_isp_programmer_view, avr_isp_scene_programmer_callback, app); @@ -17,20 +18,9 @@ void avr_isp_scene_programmer_on_enter(void* context) { } bool avr_isp_scene_programmer_on_event(void* context, SceneManagerEvent event) { - AvrIspApp* app = context; - UNUSED(app); - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - // case WSCustomEventViewprogrammerBack: - // consumed = true; - // break; - default: - break; - } - } else if(event.type == SceneManagerEventTypeTick) { - } - return consumed; + UNUSED(context); + UNUSED(event); + return false; } void avr_isp_scene_programmer_on_exit(void* context) { diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c index 52f12e7ba20..8dcb4759700 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c @@ -1,15 +1,16 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_reader.h" void avr_isp_scene_reader_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } void avr_isp_scene_reader_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; avr_isp_reader_set_file_path( app->avr_isp_reader_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); avr_isp_reader_view_set_callback(app->avr_isp_reader_view, avr_isp_scene_reader_callback, app); @@ -18,6 +19,8 @@ void avr_isp_scene_reader_on_enter(void* context) { } bool avr_isp_scene_reader_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; UNUSED(app); bool consumed = false; diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c index 4db8fc42686..b00bfefce2f 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c @@ -1,11 +1,15 @@ #include "../avr_isp_app_i.h" void avr_isp_scene_start_submenu_callback(void* context, uint32_t index) { + furi_assert(context); AvrIspApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); } void avr_isp_scene_start_on_enter(void* context) { + furi_assert(context); + AvrIspApp* app = context; Submenu* submenu = app->submenu; submenu_add_item( @@ -30,9 +34,10 @@ void avr_isp_scene_start_on_enter(void* context) { } bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexAvrIspAbout) { scene_manager_next_scene(app->scene_manager, AvrIspSceneAbout); @@ -63,6 +68,8 @@ bool avr_isp_scene_start_on_event(void* context, SceneManagerEvent event) { } void avr_isp_scene_start_on_exit(void* context) { + furi_assert(context); + AvrIspApp* app = context; submenu_reset(app->submenu); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c index 392ed1e9f19..b17d207f979 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c @@ -1,18 +1,19 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_programmer.h" void avr_isp_scene_success_popup_callback(void* context) { + furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, AvrIspCustomEventSceneSuccess); } void avr_isp_scene_success_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); - // Setup view + AvrIspApp* app = context; Popup* popup = app->popup; popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); + popup_set_header(popup, "Success!", 8, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, app); popup_set_callback(popup, avr_isp_scene_success_popup_callback); @@ -21,23 +22,13 @@ void avr_isp_scene_success_on_enter(void* context) { } bool avr_isp_scene_success_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == AvrIspCustomEventSceneSuccess) { scene_manager_search_and_switch_to_previous_scene( app->scene_manager, AvrIspSceneStart); - // if(!scene_manager_search_and_switch_to_previous_scene( - // app -> scene_manager, AvrIspSceneReceiver)) { - // app -> txrx->rx_key_state = AvrIspRxKeyStateRAWSave; - // if(!scene_manager_search_and_switch_to_previous_scene( - // app -> scene_manager, AvrIspSceneReadRAW)) { - // app -> txrx->rx_key_state = AvrIspRxKeyStateIDLE; - // if(!scene_manager_search_and_switch_to_previous_scene( - // app -> scene_manager, AvrIspSceneSaved)) { - // scene_manager_next_scene(app -> scene_manager, AvrIspSceneSaved); - // } - // } - // } return true; } } @@ -45,8 +36,9 @@ bool avr_isp_scene_success_on_event(void* context, SceneManagerEvent event) { } void avr_isp_scene_success_on_exit(void* context) { + furi_assert(context); + AvrIspApp* app = context; Popup* popup = app->popup; - popup_reset(popup); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c index cda42bd9653..787ed56732e 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c @@ -1,7 +1,8 @@ #include "../avr_isp_app_i.h" -#include "../helpers/avr_isp_types.h" void avr_isp_scene_wiring_on_enter(void* context) { + furi_assert(context); + AvrIspApp* app = context; widget_add_icon_element(app->widget, 0, 0, &I_avr_wiring); view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWidget); @@ -13,6 +14,8 @@ bool avr_isp_scene_wiring_on_event(void* context, SceneManagerEvent event) { return false; } void avr_isp_scene_wiring_on_exit(void* context) { + furi_assert(context); + AvrIspApp* app = context; widget_reset(app->widget); } diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c index ff288d4b87f..4e333bd959d 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -1,15 +1,16 @@ #include "../avr_isp_app_i.h" -#include "../views/avr_isp_view_writer.h" void avr_isp_scene_writer_callback(AvrIspCustomEvent event, void* context) { furi_assert(context); + AvrIspApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, event); } void avr_isp_scene_writer_on_enter(void* context) { - AvrIspApp* app = context; + furi_assert(context); + AvrIspApp* app = context; avr_isp_writer_set_file_path( app->avr_isp_writer_view, furi_string_get_cstr(app->file_path), app->file_name_tmp); avr_isp_writer_view_set_callback(app->avr_isp_writer_view, avr_isp_scene_writer_callback, app); @@ -17,8 +18,9 @@ void avr_isp_scene_writer_on_enter(void* context) { } bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + AvrIspApp* app = context; - UNUSED(app); bool consumed = false; if(event.type == SceneManagerEventTypeBack) { //do not handle exit on "Back" diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 70dff5eee81..72ba38d24bf 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -1,5 +1,4 @@ #include "avr_isp_view_chip_detect.h" -#include "../avr_isp_app_i.h" #include #include @@ -16,7 +15,7 @@ typedef struct { uint16_t idx; const char* name_chip; uint32_t flash_size; - AvrIspChipDetectViewStatus status; + AvrIspChipDetectViewState state; } AvrIspChipDetectViewModel; void avr_isp_chip_detect_view_set_callback( @@ -25,26 +24,26 @@ void avr_isp_chip_detect_view_set_callback( void* context) { furi_assert(instance); furi_assert(callback); + instance->callback = callback; instance->context = context; } -void avr_isp_chip_detect_set_status( - AvrIspChipDetectView* instance, - AvrIspChipDetectViewStatus status) { +void avr_isp_chip_detect_set_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state) { furi_assert(instance); with_view_model( - instance->view, AvrIspChipDetectViewModel * model, { model->status = status; }, true); + instance->view, AvrIspChipDetectViewModel * model, { model->state = state; }, true); } void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* model) { canvas_clear(canvas); + char str_buf[64] = {0}; canvas_set_font(canvas, FontPrimary); - switch(model->status) { - case AvrIspChipDetectViewStatusDetected: + switch(model->state) { + case AvrIspChipDetectViewStateDetected: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip detected!"); canvas_draw_icon(canvas, 29, 14, &I_chip_long_70x22); canvas_set_font(canvas, FontSecondary); @@ -53,7 +52,7 @@ void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* mo canvas_draw_str_aligned(canvas, 64, 45, AlignCenter, AlignCenter, model->name_chip); elements_button_right(canvas, "Next"); break; - case AvrIspChipDetectViewStatusErrorOccured: + case AvrIspChipDetectViewStateErrorOccured: canvas_draw_str_aligned( canvas, 64, 5, AlignCenter, AlignCenter, "Error occured, try again!"); canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); @@ -61,7 +60,7 @@ void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* mo canvas_draw_str_aligned( canvas, 64, 45, AlignCenter, AlignCenter, "Check the wiring and retry"); break; - case AvrIspChipDetectViewStatusErrorVerification: + case AvrIspChipDetectViewStateErrorVerification: canvas_draw_str_aligned( canvas, 64, 5, AlignCenter, AlignCenter, "Data verification failed"); canvas_draw_icon(canvas, 29, 14, &I_chip_error_70x22); @@ -71,7 +70,7 @@ void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* mo break; default: - //AvrIspChipDetectViewStatusNoDetect + //AvrIspChipDetectViewStateNoDetect canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "AVR chip not found!"); canvas_draw_icon(canvas, 29, 12, &I_chif_not_found_83x37); @@ -83,6 +82,7 @@ void avr_isp_chip_detect_view_draw(Canvas* canvas, AvrIspChipDetectViewModel* mo bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { furi_assert(context); + AvrIspChipDetectView* instance = context; if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; @@ -91,7 +91,7 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { instance->view, AvrIspChipDetectViewModel * model, { - if(model->status == AvrIspChipDetectViewStatusDetected) { + if(model->state == AvrIspChipDetectViewStateDetected) { if(instance->callback) instance->callback(AvrIspCustomEventSceneChipDetectOk, instance->context); } @@ -103,8 +103,8 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { instance->view, AvrIspChipDetectViewModel * model, { - if(model->status != AvrIspChipDetectViewStatusDetecting) { - model->status = AvrIspChipDetectViewStatusDetecting; + if(model->state != AvrIspChipDetectViewStateDetecting) { + model->state = AvrIspChipDetectViewStateDetecting; avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } }, @@ -120,6 +120,7 @@ static void avr_isp_chip_detect_detect_chip_callback( bool detect_chip, uint32_t flash_size) { furi_assert(context); + AvrIspChipDetectView* instance = context; with_view_model( instance->view, @@ -128,15 +129,16 @@ static void avr_isp_chip_detect_detect_chip_callback( model->name_chip = name; model->flash_size = flash_size; if(detect_chip) { - model->status = AvrIspChipDetectViewStatusDetected; + model->state = AvrIspChipDetectViewStateDetected; } else { - model->status = AvrIspChipDetectViewStatusNoDetect; + model->state = AvrIspChipDetectViewStateNoDetect; } }, true); } void avr_isp_chip_detect_view_enter(void* context) { furi_assert(context); + AvrIspChipDetectView* instance = context; //Start avr_isp_worker_rw @@ -149,8 +151,8 @@ void avr_isp_chip_detect_view_enter(void* context) { instance->view, AvrIspChipDetectViewModel * model, { - if(model->status == AvrIspChipDetectViewStatusNoDetect || - model->status == AvrIspChipDetectViewStatusDetected) { + if(model->state == AvrIspChipDetectViewStateNoDetect || + model->state == AvrIspChipDetectViewStateDetected) { avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } }, @@ -159,6 +161,7 @@ void avr_isp_chip_detect_view_enter(void* context) { void avr_isp_chip_detect_view_exit(void* context) { furi_assert(context); + AvrIspChipDetectView* instance = context; avr_isp_worker_rw_set_callback(instance->avr_isp_worker_rw, NULL, NULL); @@ -181,7 +184,7 @@ AvrIspChipDetectView* avr_isp_chip_detect_view_alloc() { with_view_model( instance->view, AvrIspChipDetectViewModel * model, - { model->status = AvrIspChipDetectViewStatusNoDetect; }, + { model->state = AvrIspChipDetectViewStateNoDetect; }, false); return instance; } @@ -195,5 +198,6 @@ void avr_isp_chip_detect_view_free(AvrIspChipDetectView* instance) { View* avr_isp_chip_detect_view_get_view(AvrIspChipDetectView* instance) { furi_assert(instance); + return instance->view; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h index 1f1fcd5e21d..37f2ae23369 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h @@ -9,21 +9,19 @@ typedef struct AvrIspChipDetectView AvrIspChipDetectView; typedef void (*AvrIspChipDetectViewCallback)(AvrIspCustomEvent event, void* context); typedef enum { - AvrIspChipDetectViewStatusNoDetect, - AvrIspChipDetectViewStatusDetecting, - AvrIspChipDetectViewStatusDetected, - AvrIspChipDetectViewStatusErrorOccured, - AvrIspChipDetectViewStatusErrorVerification, -} AvrIspChipDetectViewStatus; + AvrIspChipDetectViewStateNoDetect, + AvrIspChipDetectViewStateDetecting, + AvrIspChipDetectViewStateDetected, + AvrIspChipDetectViewStateErrorOccured, + AvrIspChipDetectViewStateErrorVerification, +} AvrIspChipDetectViewState; void avr_isp_chip_detect_view_set_callback( AvrIspChipDetectView* instance, AvrIspChipDetectViewCallback callback, void* context); -void avr_isp_chip_detect_set_status( - AvrIspChipDetectView* instance, - AvrIspChipDetectViewStatus status); +void avr_isp_chip_detect_set_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state); AvrIspChipDetectView* avr_isp_chip_detect_view_alloc(); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 1276d5f175b..34e18770b2f 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -1,5 +1,5 @@ #include "avr_isp_view_programmer.h" -#include "../avr_isp_app_i.h" +#include #include "../helpers/avr_isp_worker.h" #include @@ -21,12 +21,14 @@ void avr_isp_programmer_view_set_callback( void* context) { furi_assert(instance); furi_assert(callback); + instance->callback = callback; instance->context = context; } void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* model) { canvas_clear(canvas); + if(model->status == AvrIspProgrammerViewStatusUSBConnect) { canvas_set_font(canvas, FontPrimary); canvas_draw_icon(canvas, 0, 0, &I_isp_active_128x53); @@ -40,8 +42,8 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod bool avr_isp_programmer_view_input(InputEvent* event, void* context) { furi_assert(context); - AvrIspProgrammerView* instance = context; - UNUSED(instance); + UNUSED(context); + if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; } @@ -52,6 +54,7 @@ bool avr_isp_programmer_view_input(InputEvent* event, void* context) { static void avr_isp_programmer_usb_connect_callback(void* context, bool status_connect) { furi_assert(context); AvrIspProgrammerView* instance = context; + with_view_model( instance->view, AvrIspProgrammerViewModel * model, @@ -67,8 +70,8 @@ static void avr_isp_programmer_usb_connect_callback(void* context, bool status_c void avr_isp_programmer_view_enter(void* context) { furi_assert(context); - AvrIspProgrammerView* instance = context; + AvrIspProgrammerView* instance = context; with_view_model( instance->view, AvrIspProgrammerViewModel * model, @@ -86,6 +89,7 @@ void avr_isp_programmer_view_enter(void* context) { void avr_isp_programmer_view_exit(void* context) { furi_assert(context); + AvrIspProgrammerView* instance = context; //Stop worker if(avr_isp_worker_is_running(instance->worker)) { @@ -125,5 +129,6 @@ void avr_isp_programmer_view_free(AvrIspProgrammerView* instance) { View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance) { furi_assert(instance); + return instance->view; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 0bf8317f629..92f8ef27847 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -1,5 +1,4 @@ #include "avr_isp_view_reader.h" -#include "../avr_isp_app_i.h" #include #include "../helpers/avr_isp_worker_rw.h" @@ -38,6 +37,7 @@ void avr_isp_reader_view_set_callback( void* context) { furi_assert(instance); furi_assert(callback); + instance->callback = callback; instance->context = context; } @@ -47,6 +47,7 @@ void avr_isp_reader_set_file_path( const char* file_path, const char* file_name) { furi_assert(instance); + instance->file_path = file_path; instance->file_name = file_name; } @@ -85,8 +86,8 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { bool avr_isp_reader_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspReaderView* instance = context; - bool ret = true; + bool ret = true; if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( instance->view, @@ -100,7 +101,6 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { }, false); } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - FURI_LOG_E("Read", "Start %s %s", instance->file_path, instance->file_name); with_view_model( instance->view, AvrIspReaderViewModel * model, @@ -119,6 +119,7 @@ bool avr_isp_reader_view_input(InputEvent* event, void* context) { static void avr_isp_reader_callback_status(void* context, AvrIspWorkerRWStatus status) { furi_assert(context); AvrIspReaderView* instance = context; + with_view_model( instance->view, AvrIspReaderViewModel * model, @@ -173,9 +174,9 @@ void avr_isp_reader_view_enter(void* context) { void avr_isp_reader_view_exit(void* context) { furi_assert(context); + AvrIspReaderView* instance = context; - UNUSED(instance); - // //Stop avr_isp_worker_rw + //Stop avr_isp_worker_rw if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); } @@ -208,5 +209,6 @@ void avr_isp_reader_view_free(AvrIspReaderView* instance) { View* avr_isp_reader_view_get_view(AvrIspReaderView* instance) { furi_assert(instance); + return instance->view; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 5fad21fe341..05970f44990 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -1,5 +1,4 @@ #include "avr_isp_view_writer.h" -#include "../avr_isp_app_i.h" #include #include "../helpers/avr_isp_worker_rw.h" @@ -38,6 +37,7 @@ void avr_isp_writer_view_set_callback( void* context) { furi_assert(instance); furi_assert(callback); + instance->callback = callback; instance->context = context; } @@ -47,6 +47,7 @@ void avr_isp_writer_set_file_path( const char* file_path, const char* file_name) { furi_assert(instance); + instance->file_path = file_path; instance->file_name = file_name; } @@ -90,8 +91,8 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { bool avr_isp_writer_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspWriterView* instance = context; - bool ret = true; + bool ret = true; if(event->key == InputKeyBack && event->type == InputTypeShort) { with_view_model( instance->view, @@ -137,6 +138,7 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus status) { furi_assert(context); + AvrIspWriterView* instance = context; with_view_model( instance->view, @@ -149,8 +151,6 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s instance->avr_isp_worker_rw, instance->file_path, instance->file_name); break; case AvrIspWorkerRWStatusEndVerification: - // if(instance->callback) - // instance->callback(AvrIspCustomEventSceneWritingOk, instance->context); model->status = AvrIspWriterViewStatusVerificationOk; break; case AvrIspWorkerRWStatusErrorVerification: @@ -170,8 +170,8 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s void avr_isp_writer_view_enter(void* context) { furi_assert(context); - AvrIspWriterView* instance = context; + AvrIspWriterView* instance = context; with_view_model( instance->view, AvrIspWriterViewModel * model, @@ -194,8 +194,8 @@ void avr_isp_writer_view_enter(void* context) { void avr_isp_writer_view_exit(void* context) { furi_assert(context); AvrIspWriterView* instance = context; - UNUSED(instance); - // //Stop avr_isp_worker_rw + + //Stop avr_isp_worker_rw if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) { avr_isp_worker_rw_stop(instance->avr_isp_worker_rw); } @@ -228,5 +228,6 @@ void avr_isp_writer_view_free(AvrIspWriterView* instance) { View* avr_isp_writer_view_get_view(AvrIspWriterView* instance) { furi_assert(instance); + return instance->view; } From aaeab83686975b036f10b16cfe0417bac7f6a3f7 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 11:35:26 +0400 Subject: [PATCH 32/50] GUI: model mutex FuriMutexTypeRecursive -> FuriMutexTypeNormal --- .../views/avr_isp_view_chip_detect.c | 18 ++++++++++-------- applications/services/gui/view.c | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 72ba38d24bf..90a22008ef0 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -140,23 +140,25 @@ void avr_isp_chip_detect_view_enter(void* context) { furi_assert(context); AvrIspChipDetectView* instance = context; - - //Start avr_isp_worker_rw - instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); - - avr_isp_worker_rw_set_callback( - instance->avr_isp_worker_rw, avr_isp_chip_detect_detect_chip_callback, instance); - + bool detect_chip = false; with_view_model( instance->view, AvrIspChipDetectViewModel * model, { if(model->state == AvrIspChipDetectViewStateNoDetect || model->state == AvrIspChipDetectViewStateDetected) { - avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); + detect_chip = true; } }, false); + + //Start avr_isp_worker_rw + instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context); + + avr_isp_worker_rw_set_callback( + instance->avr_isp_worker_rw, avr_isp_chip_detect_detect_chip_callback, instance); + + if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } void avr_isp_chip_detect_view_exit(void* context) { diff --git a/applications/services/gui/view.c b/applications/services/gui/view.c index 4d84cac507d..50c05a406fa 100644 --- a/applications/services/gui/view.c +++ b/applications/services/gui/view.c @@ -81,7 +81,7 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) { view->model = malloc(size); } else if(view->model_type == ViewModelTypeLocking) { ViewModelLocking* model = malloc(sizeof(ViewModelLocking)); - model->mutex = furi_mutex_alloc(FuriMutexTypeRecursive); + model->mutex = furi_mutex_alloc(FuriMutexTypeNormal); furi_check(model->mutex); model->data = malloc(size); view->model = model; From 9ac53114e2e4a4b58db07da041da4f960420080d Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 11:55:23 +0400 Subject: [PATCH 33/50] AVR_ISP: fix conflicts --- firmware/targets/f18/api_symbols.csv | 2 +- firmware/targets/f7/api_symbols.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 91e394487a9..a554082aea3 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,v,19.1,, +Version,+,20.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a4a75de3946..88f8683bf51 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,+,19.1,, +Version,+,20.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, From 8382efe34699799139a05fc339b7476780d5671d Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 12:03:35 +0400 Subject: [PATCH 34/50] AVR_ISP: fix build --- .../external/avr_isp_programmer/views/avr_isp_view_programmer.c | 2 +- .../external/avr_isp_programmer/views/avr_isp_view_writer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index 34e18770b2f..ee1647dd11b 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -35,7 +35,7 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod elements_multiline_text(canvas, 45, 10, "ISP mode active"); } else { canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 51, 6, &I_link_waiting_77x56); + canvas_draw_icon(canvas, 51, 6, &I_Link_waiting_77x56); elements_multiline_text(canvas, 0, 25, "Waiting for\nsoftware\nconnection"); } } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 05970f44990..86c1e7a5c41 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -228,6 +228,6 @@ void avr_isp_writer_view_free(AvrIspWriterView* instance) { View* avr_isp_writer_view_get_view(AvrIspWriterView* instance) { furi_assert(instance); - + return instance->view; } From 822e6be4642aa2c0b3e1bab18d72cf3c3ba3b93a Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 12:11:12 +0400 Subject: [PATCH 35/50] AVR_ISP: delete images --- .../images/AVR_app_icon_10x10.png | Bin 3614 -> 0 bytes .../images/ChipLooking_64x64/frame_01.png | Bin 7231 -> 0 bytes .../images/ChipLooking_64x64/frame_02.png | Bin 6909 -> 0 bytes .../images/ChipLooking_64x64/frame_03.png | Bin 7308 -> 0 bytes .../images/ChipLooking_64x64/frame_rate | 1 - .../images/DolphinNice_96x59.png | Bin 2459 -> 0 bytes .../images/Link_waiting_77x56.png | Bin 3883 -> 0 bytes .../avr_isp_programmer/images/avr_wiring.png | Bin 4513 -> 0 bytes .../images/chif_not_found_83x37.png | Bin 3742 -> 0 bytes .../images/chip_error_70x22.png | Bin 3688 -> 0 bytes .../images/chip_long_70x22.png | Bin 3656 -> 0 bytes .../images/chip_not_found_83x37.png | Bin 3779 -> 0 bytes .../images/isp_active_128x53.png | Bin 3961 -> 0 bytes 13 files changed, 1 deletion(-) delete mode 100644 applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png delete mode 100644 applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png delete mode 100644 applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_02.png delete mode 100644 applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png delete mode 100644 applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate delete mode 100644 applications/external/avr_isp_programmer/images/DolphinNice_96x59.png delete mode 100644 applications/external/avr_isp_programmer/images/Link_waiting_77x56.png delete mode 100644 applications/external/avr_isp_programmer/images/avr_wiring.png delete mode 100644 applications/external/avr_isp_programmer/images/chif_not_found_83x37.png delete mode 100644 applications/external/avr_isp_programmer/images/chip_error_70x22.png delete mode 100644 applications/external/avr_isp_programmer/images/chip_long_70x22.png delete mode 100644 applications/external/avr_isp_programmer/images/chip_not_found_83x37.png delete mode 100644 applications/external/avr_isp_programmer/images/isp_active_128x53.png diff --git a/applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png b/applications/external/avr_isp_programmer/images/AVR_app_icon_10x10.png deleted file mode 100644 index 533787fe3569f70196d3f71e8373102dfd3967a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3614 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 Vpqb^9w@m;7?5&;gRaoD1{{|C}E&c!i diff --git a/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_01.png deleted file mode 100644 index 4ff2e3042e540d8b499118e9edf4ecd180b39511..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7231 zcmeHMdoEn$MdVgUZYLx{p`@Z* z5=qFBa!ZuRNt8&rOMYMKoYPtFyMFIFYrXG(XJ)?NneTq~{ycks_I{rA>^1SW)@IxJ zr1;p_*tT1k8{325`WqJy7kDov2Mx2a@x2OjbY2M`Byg}q zdditUP#58HOC|7r1H~oe0_oV1h2XiPZ*3RSD?Ykq-%_5SOb`1{+$2vyuL;!B7!E_u zzX_}%{q0OK^*Y|$y`*W)GjXA=-S#66!AfzrlUA>&^-udbIVtuzrTN=&La*17lgs*J zZl^wCQ!w$|rq%qI+E;bj$Z_Y0j7d02JuK6t{ia>Ue&qw{8KqC1_FEM{Z2$HNcQIrt zmtb*KajG`z&@Vc&_6PXJ-|^QrK}&6l-0eOsM21&-Za+XW>13C-I#{e~QvIH$q7bVw zK?;(!s|e5Csc+&sXea?3IoYB_NRKx5@~;pPkvx*W^;wl$a4hHfs#-(yds1UZWQ@7{ zA4ybPE~^ex+v3z|$>Z#+O^Hs4sqF82aQv&(h*7&#ox6YTyv6`24Ruzb3o|2;m!=sx z->)?j0g;Q~+f&}eB_7TrA1e~9c7iG`T%!6=!r?&yFKTa+^+bw&|BK($ho)|J$(udC z+8FWJof6cNY3ps_g+!f= z%sU=kO@MLnU&oP$`U307nC{7$fivMkb(62%&kiu<+^1gzR+Kwq4vJI`@EAG2_ZEtH zwRm~Ux0J}4iaCeVHWlmEb2G;4Haq1rgm%l1Ur(CBy?F3C_ifkBJw0Fi+&^{(zgNuM z6`=9tjJ5KGII}80?Gdr9rKd8}yIU6U&5mkL=EsG6lv)6;u@EQ_T%WRjN=-HhxPs@Y? z$IKnSmNM#IAnpy%eu)+DLEez|Zx4a)aGl{z-+s!s(_USXdFJYky_B0rFQ(Sl!p%SC zq}zRT{kp~~veAN$((6C@5P}+>tGnDF^NN)ZwJAu)*GknFL_KyU9WW~0H@*&e94kBt zoR3M<6%-eGuBF8;Qme%t?2 zr~9r%6udXDRItOBWTHvqTyRvq!|E#Df70s2Lh*h(y(4L|{oSz_QUZ-|T(~Ljm%U-L z@~5g!L@M=Ju{GV)2>6Bn+}Vs*oa=MS*AHGSzHpk-tR+?z-#wQ#aal9}j^3#DOsMko zo4fYhk9C1et0kqFNW%ePvj{U+1z_s2u8i5!>V)zy9AT5f$K)<$&N_*xo?GM;kvMUu z-VknQaAd*!)%>YGaVAz#A}kf3C!tSx$Ypq+|IiNCqr!I&F*>vMN%5t|Nz4j`cjh*; zt8$n0Nw&F?cOM#PC0bYYzaCU~p}0eZr9$6&~+{m$l6rYIeM?=T7WOGPt0g z;@7diTT%Wq`~9NU-eb+w(Lq}`NhCKv`-gljWPm3Y*nOO*z#~9RfDdOVEDZUiL!66Y8tAJjJ}he%27KBS`v%PtzX>|=e#=bFen^slAFFW28X zdkK(Glr&z~B(8L(Kk7_6E;f87_?jE5Ss}d8aD2-c`|CDI>7W*;%b$EC_)ZgqhDID+ z20BMP@bXRdqGE3w&J{R#KFFSS%sAhWu4r$W+i_0*exib+e1FzT=h;i2$>k9xl#@kT z3%H8OMgD~S4H3OHQ!h%e;#F-mPd!5(YxLj_8)M6WY@g@aNP(eumIadzT{>wKG)K$W zcBbeRAlR)qtB)?uTcI$hyoD;Hsw5gI?W7Q(%C0W+lh90 z!C95=0E*|-K3>yq{=(jjBLfMa*bK1PcQGPeNAU%(BtNK_-$|;aMPY-yZmh|}lML}C zw3qKxV3coGp?mplfG(05I42(U+*qLeVnk%#gc4qZH+Xqt**23PAv zWExD5{g!#Uf%|!pp7mMi%OGvzi+O^wm92JPay-n>b%1nR&R4&U5WNB*Y_ zRhkF?)~i`&F-y#%I_}qA$?*+XW@N~=!J=;fM?ReWH?B-yr4{nM*(W*^RmbZ&#uo() zlb?nkRv500>2>}MK6)eF#SGocKtJ4XitMIxhtJU-+{sD>?)zZo{KM1^!mz1@{?>Yy z*Us#El~ULgJSqA@w)M;Fc5^ymsnrkNx6bAYJc}N`Zs)n-yYlG+Oa5C0SA}ha%$#r~;qqgZkB=taaxT5` zNN1V98540d{(~BKY9oi3yuqm`J`LNbGZNRZN@Di6i@R2wf-_qhIBkACs`hHo4>d0?3ais^!!f9(zZjBxZ^ckRuSjC0{osSa^UCtu9&>-k0+~LBGsNZtDaak}xvZc(~%Mumoy=3Z6*y22@x9G_WyYW7F1S(eMO+ zfC=#ie93`2(3!gXPzaf*19efyA#gM!fJ8PAqXQ0M){cZQe*%UG)zjtEW??~q0Dy^y zumUK73@l3rx`~Sge{YE4P{^hV(_aVbinE0nQRx6gO+`%w0W)EdLy%BiK8QA*=!3O4 zHvItsKIuS7OePHrhlhrSs)V9csB~YrDh7jrBam<;5(a9(7)Jw{cor;>p|An*9m5!4 z5a?tYlS~bSY+&NOsliMgC=?ur{O(@>4Tt*!K9KQ)1&|Lo3r~ZqsvzJ20q~zK7)+B8 z5afqL|JH)x2=;Gqdw@X=rV{{@5Fn7L@G}IF@P|Dum`>RYhe&_}6d(XpWq`A){$)xt z3!LpA78?}!k^^X)Rv_7b(PWZ+{v_)!zHN+bhV!!{p!pxTf6@Lu_Dy9_3x~rRQwhNv z?pYY?KsV;c5~&0-5xe;lO+*7I3<`j$5)s}oHM}|+hDUh&z|_zhnwoe`O$4Ck^AnUs zAcKhyBmf&wAh-${#8Jm0;~O5K~FiHD&y)ippU6cL6|1H57C>IffA4Ctv3`a2YnfHkGk1Mpxv z$pLs@08R_^-JD~CaIAr?g$@*{g7{NnOTjaJKm#2p4o`sCIQ%){NDcrTnD`AkRW&p) z7)^CmO|-fiMqLB>r;;;3XMm-+0ji2nL464~f2d*a~o{2ZcGXW43fka|ekyr%M5xlEouqgC?1PY7zNuNq2`yBmG z+8e6}qWwMR=41vq|Itm+_a)^31bu({{zxHjt|bU$b5&sRgzq6R@F4(k(@zlV`w)SI z5A+4V?c+zi{w^o~n_57kQEEg4+8gGBR7Jzodo-_66>S@ISW0AEa$;JpaSjk7WE0X8@u9ndEQr`ww0J(Dk<%_*=^VRM$Ur z{VfLmmhwN<^Z@0Fy15?-3Q8-tBa zMPcJ&XBFv%fI@Dj1aR^)}AP@J?o%Il4;_~G@=GtvO{j9&J>Z|v_y@r;oY$NuW*w}&jJwZ6>l)cF`M4k$gots`r2--j245+u&^v5QIX zCEb)coOsFotYi-NF}rlgy*F3X{pah32PjNlHXQHa?a`$xOYWpsX0d<#9lb|*S;sW<6s~8XZ zwVqMzuWn;T#Sd3EBnd)0Vk=Y@W~j};=fM0DW$?Y4-W&~$X0)xIzNaYyqE=K&*2 zZplDiS7nk#?UeNLR<(V1LW}SDi?3~M+n(<=HvF-CaU1(L{omln(e%KS`p?IqA6K*< zcBTw*pGRSSX~{zwzZ9_Pb^e&J9|B8J048FVTw2!OF7Ljf2NL8C$-5zpRw zx}SZG5&hJ?Ygw>RE!}MG0SJRDH>9v*iXe{=RZMoCQPB($3Pmwi-fc*@wps$m+uaQQ=P z{%1?zMe~A5U*NSD-FGF+$J|Zqc#7WK*}q>))5KCM_3WQvwAap1{UI-Jjpw@3{c(?Y z-(GNUAASBOocChrwk0ahTu|j?IW7sN&xPk-9$s@1xxmuD6SS&l=>Qj5A5taf-k48D z?js)i)YhmiwJK8078=m0I`RH+d}P;~&dIJ}HEOU2W%2f=kGnr;(9`xTk&XqQye4ItbyIoI@E~$1Lc=!jo9@FXXky#}m8>?{jSLN_*cX^A* zyJJ#%4!*&iB5{(2hwkp@D|_Z9LE~Gop{>TMSDe2SP>y(fX}3##%XECjqpbSOc0skB z-Xf>l-&=_&*`x274-^U|R1PK}Y|j#|9B@4pSg(8HH!qWH$zMLdN-(^D;qR7&qzSkU z*l7Pxync|rTkL1NBV7MB+mz!)$1Ii|l zS1#4EkxQy=`nM^VyIul+@hY|#%%s%yVP}seBbsMYCwdkPBlh-Vvwe>X8?wcB6=xJB z>9tIfjb$BBY8RmQ8|@N@q@8WC(pEFcwmRS8>O)r_vsB%O zFId_lTrZCZ!y6tj+?8DZY-oKKJy~0pCs3}}Thk$8#GQ({-;?n8?EYS{9K*b=CUjq6n4E~N5jWwW^HD7FI`i$ zEJ(BxM`p2VL^f~3c?~_E%$v2ab5B_@D3duoSFD>+8Y-rzzA3yqakRt$&*O5BSu_9c zwfE_S9?cyZ0{qgtfOD8|rKk$FA>}uV*=*mFn+uiJx~?9R=32nNSv^}Wlz(0Av3X-a zkZ{pc&BPtW)*d4-8ifZcWcv6r=$jk+5iXtq{{5B(!56f7-*K;~J$!XkFCegFB*rIZ zS|u#WIAlI&Z1~{RP}1}45Qz!3RWaEWtYoH{zSGFW8}3jASmToeVKyVGTf}qV)?-!1 zKJA*t1<8JAiTu7uzWV;jtX&kAY)IzYQ}rWI%u!bQsU+2kHl>!Ra`MhQl%3ZkZ@ak3 z2SSV^P4}1^1H{U%4}kHhqIr^OZr@!H+yT9CuxoOGHN=wTDZybHHGH`YvF$^<6PN{*S#3)A>^Zaz^l_dZq`wKwH&y`yzKfSwMujP zjHgfBt`r}YG-}WMEs~T;T-46%kqW8_+|c>Qo!d(yg{Sc?H<}`L^!P-uNugG?X;KzD z)g?RRwL-*AlYc#tkUVgpSkzRQh#)wdTpXU7conJAF}U^q>9fFz7xlAHY{RT%XiW&; zmg(-btKKHO&sv*ewq8xhWYI+EsdHVu(I(M@3cox!9WFCnpwAYS^PA}_K9nrzwpf6- zzr6OgPP;gvdR}11HAcpx6Px-YM*r9F**@Q&G6! zX1%_&oS4Q{7m8gt{(yX|B*yW<)XUJn_C3nOuGs^_y0JZj6~DiDZa7lExfi;%WW+u0 zc8I1`+^&1$UgO6PScn-s9U2dCEQ1jPv~`FLYfS zm3M&NUkSt`cD^^?94{9+AgDZC%`a=6B1rc8bTN`7m( zYzA$~BiZxB9X!>yTlwny*hlk2MWS~q+@6I%%a;2T8x*3cl~5g16N=h#f=5T5{lg|3 zjU66{b3&Hs2gldn)_#g=SxR=EMOhf7^~t&87=3%fd3+;vw(V&B#paN{L-1u^Y{Hpdd#Ii^K-1m2*MJkQGjhmIM^R};Uw!Z=ByqxUk;Um@uE#8YQ9s$Z6 z%otvV4IhWz>~kKUlKpse?MfN@?1F-P>M>sDXULL#^_}c3pEFL4opnV(i~DzB>?YV} z79J_Nj2?Rrb*^rx?F)$R&Jru@=BbokykvY%XZam+{Gq21fxR#rwB0bquIP*mS3 z0jC3-k50VK*PlTe74W}(f$8IKRGE>T6u`dZ-}<{>HeV+Sa5@;(OcmKCt0T{F6Vrs2BT2|C-FGIe5|a_2@hO*}I;t ztX@B<#vz0IRc)`Mcjw5gkc7kUY317AFfWSZ`>ZjUphXg6BlFj}gv$^0Url|O4S{g6 zX=Y}QHfCmj_k3Wdmm8Cbx9%|B(&gh^vRg(#BN0O>-z#fw!5Z2vU0_-+;}wQ%UNrN+ zpHbX|5vt}BFp{khMfA1cnuLyx2qYGrK3$l6X7xt#fby;5W3ks-SDK;)1g}aCRW|H1 z9tzgZN=(j~IVB%uA{*|f@l7U?4;LHRN&0mBA2zZ z`)$RM5pj8h%gJcj~0Sgo^8FM45Lx-%I>-ZBq7uc@TXZvF#zYNy)NXaKr)u1 zY-A{85P<^$f&ms077-j2!o)@3l{av4;5|pIr3~9JVFluqJqV64Gdcr+=^%6vNVr7= z?J!!|PzYwgpips6=9XU}z$d)2KZ_NL)6xnL4@ZP+Bj^l2Eff}u)k31R&}cYl0cS>r zu!s@x5T*(T;tPg3z$7zhp)49b1jfN6lIUS9ys|Q=hy5L2a43QB4L*eVl?9Lwtq5YM z77BsX3J%u#-h;`qI1GY(4d}mmFkQe`87(J(Ne^R?0gJ;x2utOA2nzX|e`pvZXd@j8 zSqlgPfPsm3zw21JDg%Fu_vffTEBH?JpY6yx_oWKxT=YLInXf zV8LW?W(xn{S5zUD#00c#%(Kr+uheW%ew81M*7pZ{+ zZ@#mqQ)tx4|IM1SdSC`$=G>ab1jmou5Pexv&cLBBPhTE`Xd7z@2HRK_I3oE=3QXc* z;0whd))y7opBUl?fZNB{di`5Y`!BVC(j^0AG#Lfg)uy80I=Vz6SWenlxDJ+z!~zr| zQXh@kVBs4&lTKxY6B&SsAIKxf6{iN$(G4QX9e^%H38C^pEyifrlU>g(;zAhC;?ghVuK=?^^R_2g(&M*J> zveTesQ>e8k69Pe~a89m>5~IVQP=IAaun>3y>AsgKy zK!JtRSpG0hx9EOUR1SRU-fv@W;^P1E?fG`e<1nasYRCFIBg*#{aR+Z==gGr(p{y8o z2)AwTk(nbGy5E2fkobF-U*jPXNh|J8!{48MDS4@JZ^~$9Pqk;inB4KU-o}u95HCiU zXYD_*|04@V1Lu1xX9FZ#|MVzojME#5z{?L0Exq2Rw3M zW>MoVO;2#**@;-i=z$Z3lu?67?}W(Fk7!1>W1-nk>cfG)vy$E2<3O;}qXwUnil-;kax^cc-{dmlkLAJFDp0vqzHD2Us NY%KPgSDX4C`yZHc9FG71 diff --git a/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_03.png deleted file mode 100644 index 1342dc7bf95265db5d0ab2924e1ef03fe4df9943..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7308 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 diff --git a/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate b/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate deleted file mode 100644 index d8263ee9860..00000000000 --- a/applications/external/avr_isp_programmer/images/ChipLooking_64x64/frame_rate +++ /dev/null @@ -1 +0,0 @@ -2 \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/images/DolphinNice_96x59.png b/applications/external/avr_isp_programmer/images/DolphinNice_96x59.png deleted file mode 100644 index a299d3630239b4486e249cc501872bed5996df3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2459 zcmbVO3s4i+8V(M(gEFORwSrA`4O0uPn|M|5y* zB*aMDxC&7(gP9JN;POOi-9khrC>Z9YJs2U!LnVcQEEC0fDtKo&ILlzb30%M}3J^;~ zv7RzcsilOs4Mq@tD*&R;!LMSk2A~{(`HK9|hQBqEX)3sQr9Je6SZU*F-^fD-p+~Hs; zHLkO%v?>ZoxEv+F#whudr%615FkA0DYR0tMEo}3OOY#xecLWe>xV?u5KtSmC^ z7)Fmj6gjfKstiEV-*Cxbbb+&rRWuI_rBJ)ybs_f1Rn&f2>q3pYwI^|J(hdn{j{0EZIm_F zpIyIWLsRUgOItR-dUbVd|6Zo=_BU_Tj4|{{jxO#=JH4o8er(5{!nZD_j4}MH&zh~9 zVLC~y(0-D6GO0ghZD8BYzP?o{>22~lT6^d@X{SwQ8vrNY-PPIMajIwC)`s14Ep72@ zeq7YOzM`?U{+W)ocXBr`eSOcpk?Rxc=ou5&)fWW|pD};-Z0mvk9}=&`Rb&y<77W~a z(>6YM;6Y5aIU~JKZ}mQZynKHiSTQ#Bczn@&jTiN^?vPJ(jhm7cXLx0oum5P$`TceG zU+wR;OO^)8CVlnM)5p$CO&e94KJt>HccCaHGusmW_b`T6m| z-R6V6Db1pErTot?^d22ojm+2>_)FbD`_+WbDGMx9f@hO27maS2`csiV(D&Fs`PS2& zvrq18du_&zXID(!KIxsU$)iuTYuZ?zmYiP&n&i@Be{IdbS-jA2c0QAlu5NXQv_0K< z3Hvs4eeu6B7yD&CNT~gIkMV&UkRU=V!iQ(+_(O&u^ah$+s{_yn(yBYeD40HeU{xGsIT6W Zfq!wOp!QIU@?5-8X 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 diff --git a/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png b/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png deleted file mode 100644 index b03bf3567ade9b2e4ce2d29328032ebd40c89401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3742 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 diff --git a/applications/external/avr_isp_programmer/images/chip_error_70x22.png b/applications/external/avr_isp_programmer/images/chip_error_70x22.png deleted file mode 100644 index 16f81178c0ec857591db3fe40830a5955db54e73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3688 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 diff --git a/applications/external/avr_isp_programmer/images/chip_long_70x22.png b/applications/external/avr_isp_programmer/images/chip_long_70x22.png deleted file mode 100644 index 3edfff82de952d6f49a012154a23104e3fd935fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3656 zcmaJ@c{o&iA3q}dR#`&2V+e^^Eq5kknHjqwjEuAxGh<8|Gse_dB9bj#lCnlxWLHrn zlr5AHrR=gLb@5(HlHizZSI7I`1!2T>3I?-iX0kb^3h_#CiziP*F zmKOy%W8=f+k~DSH#AIz_)o%95JJs*7un|q@1!evQM^}VLhV*UTjnvQs+zN~M<>S81RuB0NO({6*Z{AbYhtY!na38Ire=Gt3|jLFr0}2z{9k z3$FkmCrO^4?ZSFshjeL2hhaj6^a;Js&xAL@US8uHlbuCuGXNOnhIMV|Ld%uI4+@7f zH*W2l74kVQk#l-E-n&f3>=BSN-S4)*-l~no&C6ANeUlRty|ztQ5AsX5&<%RSi8{CS zQ{Tdj*Or$)JRQ@BKpcy(5?cAt@M_UMcTeXPu?t><9}}(CDkV18RNsJ`Y`m&SI&$Mq zJN*;z8J89ix!^eLmHp56b#GF~Ms!yNO-2lW`zK8VLX!0Ik5L4_+G)v>xOHR805D(8 zs(-63Dj4n)IoiqFoHJdw%Gn2md)r*`2Y};v4G8gNxoL|i0N`^Xbnct0EY|PVtrOl; zzkRS?V$IX=0#>7`0V|6Yr-tw0c>$Phl#DvUSMR$?a`eOyWE|Sy}L>1GcR@CaPg?7ekfL_GPIf3nx46NbK7l|NO zYt?xSXB#T!sO6KSgRKDK{91I475r*MnG@!%_AJ{Gy-gTPA|K zstY>M8a0tM(KvyeP?=Dh_YlwWGV{N);xeY~{PLu&(xmL9{-iK14PowjJHvS>|0Z#V zLE;f?$;}GqdrmR=yYx?IpxPr9Z0vGNZe4q$?4#(j%((Z7`(($^wY?6huid)arma4u zeiB^dNlHb_N4CV$wUsh=i|nQ=@pj)!v%jnKCSIw92s46zNt;TSNoTo|bSiYt$|t=P zzh-+)^O}kdlvq%Bw{W;n!gay5jhI+)+$FTs(iQ14ULf{1rO34~>(Cb$6&HHJ!Tgv) zdOnM2dMC_%Jx>4%uSQ6lx7cbO)v}@|c5Kg@a_Ms!$`j91AYjl-rI143 zT$P*Ec-}L=yxFwur^myy?OA!lLA6ug_k=>%iR;Yoc}rH3B;j&N4dDUFj@`!34g6Wg zs?e5!Kb&yK8qILIXo=b8)a;)64B&%fKyXunayd8N}4#^Hh+3)C$_y4GPQBhE-bbqo}c%Za`SrJO6 zdnwW@pO-eyCf6p1J_-G89U~$Y(Xhy5 zMUGeOYTMt$$a2YiV?|e_R|P~a#KyMgxyO**u%QG8h z@(1qC8qP9iV+L=$(!a4k+Z`G3y0I1a!D+I~RN}@pnD0n&m?O?Hg8pbq9ZG>Fxs|-X zUzy7*Tqe&cntV0k+!!|*H#QnZ47;CrWmH$$TG{5<$jUwuHG(^*zDeB--s}SM!uJW# z1>+*jBRsaPt^}V|dzN5|9-w_K>zgsZlv8CcZ=QI*k~$dD zQHR1ly?ZS}{z#5*43pG~iivWIHcep1l9apPsRq2RL0rHH{yRPeKb%R2JEHFC*&67W z6hclK_ZvOYe`4AU@pgaJL&_rAoU+@4g6NbQ`ki_@vNp32GnO?bF&?6r25mjY4!YUV zuo#u6PypGfi%v1Kk9GL<>c7lob@CN1?VI1l+m|37)S%ix2Sd9IyJCBBM|Ji(%vtKf2ty_Ee>COTUo;|z$2z@Tg4kynx~`(q2$2+0-n&-9Pp zXWEKsQDqy?{o*U3d#{PS@GZYwyxm<-yaIdo6Y+@ldmWK7I?c`dS$o_|R7z3yf%chK zBH$7F-$J*kPs4`>!paJo5`Rxay4+|F?KfYL@!|ZV^ znsG}l4Xf1*Ciq4iuYY;I{*i$17YSGK$*9mTgYRdKIg+66Bag`6qq9^@YY$XMR^X~`KQn$@L(6;7(SFdBc!#)1{7y8S?H+nWe!t?^HLDU*^Hu-%o&k@V z<#m%6PX}BDTnRniJ+xJu)$(Q2(zwFum6TQHu@VQS|4fTux8S;nx^%_+s<%C=-58>C z;=2Q1tfX6hdAgA`$J3KClyd#;dh?h%8y_?=y(~7eyjKd{f96t1@uWA`B21>y@v|MdAc$@KZoOIg>lLc<{6 z20aIERfJ4YIz~>)u;!k~a!0!@Hshxb)*S3OI{%nEUp6qg%k8mS#y#{2=4b9_3c@m`)*$u{a3TC5HFLt*n>Pc{lORJ#z&T7JH~G@>vR#?e~u zXshnyY0Z|@IM$q4G@CK+!wtpsn0jms_RbBSJ6XreS?C(HS{9Cq?A%CNN|eEEPfSm2 zicRS)X3Z!*xNOfsG3Oe0f+{9n+F0YFfjK_qcW1bZ}v z#e|TzFpxkdo6iOSW79x3nc_?1g1l&Sh93qzSN#kOVo)()HvQY3q^PIEC}ez1RK!DRm<>lg5MrT8_229nuOI0Uwp)ej(n@c*Gq=0E5Ft~2dF z@%~TY0AdiE26d(duugL*{N8!1Z@FTlaU2?%%i<7OtW!S0{(xN-(9(Sx95Xm>NsTk}XA2)`-f!R1^ti z%NnATUACkyzSj~r+i%=^yT9)r_kPdoob!2}&+B==pZD{8ocpU1bMk{A-O~I03dAUg~cAT!eT*87K7?_o&o^=gBeaVg43)ldUbReV-p>6 z+lJvNBM5TD#D+*GsA?z)Nm@rMWe>3&@J zgXnAR>*GNWyg$^ee(v0Q_R(mjcqya2TcA!*G|5uOK`%tK0CRB9r|_1h=J6?rNvN<2 z6Oa@vCoB1FD)Rtq!6?)baGk(QfXDxxh#*jhPp^X=h}xF;ib*}m6LOWOj-7DSMleJg zFbRyqV0_fKQU{)?vOW<)OP}e0XQU(Z$0x*Z@h{FJ15OB6tS=k@B znhHppFS?+9J5nk+qrvS|Y8k3Z1z{HICaC2r;Nk)~sNQ8IcSKsBw2PEx0%-_HmDdi{ zmH4#u1^}`WWVqEXZTfeKmv(jO$5n`*(fay|e;e%XKDjmBUBom2fN^$k&z2^%e1C`` ze+Yf+{-Jq3&(k7V7gl4bWfCUOfUMa;mnG&-Z_Ki9Rt*eHPfhh(H(}gJ?Jk$MXborT zTsF`D9*o*pUHSBKLM2rDRHy~t+NXv$%eFZOx^D?xbszp5Z?RD+vb~}B4%}qrUPaW9 zo^+7%jl-o~U((J2$6#(9etoESn>;b5xz1}erUyJeXT%efpp}2hgZI0Qnk123H?ax; zi`9(!_v(VYA)evm-JIXt76oW`j@2<_#@ErI}m%L>(aY^tzazfZG{ z|3Llj;d+scv-(#tDoqU-NsKT#lidSvHgMUAu2_a=(Ebq=19iA-@wgY$E7 zG*jXSNiefsy(UzM&$Lx=FG*=In#cVbQ8`XfE;V9Jsos)LDpm#57A@@nwn@;lggag% zfSfHA7tyR;h^Uk1FA@w}0qwAj$Qldy?a(p@^n1}~*s6Sk{a4NJi@YVX;c4-*S?Ou1lrE%KBYj5orz!0Nv26VPco4}&x}VxAn;6iW2ycmggKEo$EX_;@jIbj>@x|1?jq$`;`;h2Fc!K z0*Kq1pd+mjQyEi@Q#w-$Q%Z|&!Wr%+z7N-&Ce$6<&sob)OHS)f^HWl^O`RX4IgaFK z6ZYuEpTLx4S2#X$h|1rqdm#>0Up&@TC{OK-=l z#h2tSyvrO>u}GQlmS~!~eEL3teKdK_zDFsxx$^H~pQA<6f~fOg2LRw(LxdDCFc%8e8Fj_%cbVdI!==XLhqA`oC`CKeREQ9q7@kC zM-|fY83f~p!LFMz{H~3*jrQ1w4p~pmOx84mL_Fln{WX=m#fl;?gz7b^KIt5|bWx)^ zWmB;_7F}47jlk+y>$sFVF5RXY3rwc?uH9wZ3C*bIB`*bE8{|U{C{EFuktFoyRxvujS zH9iq15Ux2y=M$&O%}X*$4t=ODsm|MzS7n!ISCsjI*7*3hinfY^O8Ljr{rp3v74(YB zB$~S%t@3qg<9uRm;^h~YZ)~Ck#G(eoixf{N2Kzl_Nh6OVN7K6Q&KqBTy__@)r4hR& zyZdz}EB1CAZt}`-N`GfTlcQDng)c?N#@K{)K$49h=?cvwt+i9u>=oZr^8R_Ne z4RiTJkLLB~z2>8a@4eBzcR15k$M0=pEB2GabdRyfy*n`PvEpERtbHi$*^DyO1DfDc z^6_zH4ySOHv><2n-H3H>(r6N8FseQ3dghHmU1e)!hkYX>^Gw7T_KNa0c{^~s2gnOK z#6#na2{jFM+qJ$HcuDD1oH25U^1W4p1%LVQR)F-G6x$dqsumFy;Sy;a$BZWK?|~=lae9Waeq*>FxFps@lt`>w-hyzF(EP;B$onhJ;e;j z?rK<$$dfIANNFOIOl+g=j^6%{sia1}?Da#7dpU>VgaaBB8)#r?kA6>dKlY@?LAymu z4Se9OUlVHd0#sh>Y6(|ha=#ExsDIQDD5FtasINL>+7U@bnMXS3 z-jufw-88tnaBq7~szGY}Rz*&vjf<8d@pEnQIYb%CH(*G3QfBv&$m9IQsOQ%zH0XWy zMRP96rNOnTfq3uG)Aj9P_0M>`zlk^tPe)w-HvDn!lsysZI`)k8BQit5NG9f5sq~Os zvdoo!^Mg(yb*tJLA!PYa5gs>t2cUh3@UQLRij@ub4!&&lFGVgrLu#m0_5om=^C zHUv%XR3EAiufSG4c!hdiL&NGSaJR~d=eh~EMdqn2ZLcHadms=SN94#?@G3Oh1n7#b9Z}T|Hi22!`IQk4U3^)B<|{>Tm!6^2yI@2vtjQNX^Y+0Gwx(u4u0LD+Son=h%cuQ{`9GG{t~9f|5QcH0{6Ul_h}u8xzn)H7_c${!Kly_K*MFM-`1pBmp0 zDHi!H^QaL5F=5QwoZZO7c9XkRGv&7KZ*`Q)$wGtI`o4Ya>PhLzPF_q-d_}*Mv-!2| zoBX4p=7#2jFWdZe;HQ_5ug}$UhB=B055^?yr!Il6sBe4z{$$1JZQgpKd}87@A8*Ri z#)97MFz$DyJll-Oc4AQ391@EHn35Up6p$62M58!TNaO(DHVO&=c-6fKL^cs`i}Ya7 zA*7uch(DdlMFRlJ*q=%A@TRaq?i8Ar4;s8s{R#~7BBQ}BdUzO~iKTdYSq8EwPJwm= zk3eq^1Q~2>1VZ^Exde0yn*{QwpZD=Y`lG>r@FKbP&NdVb`XhwxjRyZIiikf3!ZKJC zkO2g)jHBVvdC1VBhLJ< zbX*S&_GGh}NGO!U;XpV#5C)3|g(DCMC`=owt*yn4(DDoLVUzr|eEgJuGTNQGcK^vV6NCdtDrOgruFgrt5e*bLH$WgC>#RYsp@AS9{;~X>GZ#&{n(C_ z|JVDE#D0VTCI#w9@nc+Id2r8;s=SkmiNvxfBsPOZU@*@AY~(Rd2AkpM$zX!Cbs%t% zI-ca=<+HPM_zwskkF@gfW0QP5C{{Q$m`eij@**R#aG0(RLeCTnLtx=>Gn^?5ql+Gkhgj{durKe6P0(DGLuh=0XGxniI@XZv4g{d0>uKs)B&!^?I49)F4tcjj5# z;nuIe&HaG@_>b8V%((0J_IA#|y%Dapi|uIVv<*yG!mPPoofXcM;6GT?H!fZ$Da!Y0 zX$xBW8d*vV%UrQ2w_S|TxOtIRHavm;WE;HqbtZlw`-)`BDNO$x^HQ?ae{z4hYpFiu z)R;}Yp)`=zVQ8c)ec zcxR&Vca72o=5Oxhj3gMkE?xvC3`#Q!CbTNRQJuLXiZ2-YXq)`z<@{E5emj{!l`7OZ tqM<8NsC&lo-2MW+xr4Uu%d$`&en1N&q_;IOR>G|Xurjm5m153@{U2Vwjb;D< diff --git a/applications/external/avr_isp_programmer/images/isp_active_128x53.png b/applications/external/avr_isp_programmer/images/isp_active_128x53.png deleted file mode 100644 index 843792123c844788cf84662284cfb0d6b65eff14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3961 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 B&F}yK From d1e18fcb99ebcc5d614b9f94d0d0620ea214c7b0 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 12:13:35 +0400 Subject: [PATCH 36/50] AVR_ISP: add images --- .../images/avr_app_icon_10x10.png | Bin 0 -> 3614 bytes .../avr_isp_programmer/images/avr_wiring.png | Bin 0 -> 4513 bytes .../images/chif_not_found_83x37.png | Bin 0 -> 3742 bytes .../images/chip_error_70x22.png | Bin 0 -> 3688 bytes .../images/chip_long_70x22.png | Bin 0 -> 3656 bytes .../images/chip_not_found_83x37.png | Bin 0 -> 3779 bytes .../images/dolphin_nice_96x59.png | Bin 0 -> 2459 bytes .../images/isp_active_128x53.png | Bin 0 -> 3961 bytes .../images/link_waiting_77x56.png | Bin 0 -> 3883 bytes .../scenes/avr_isp_scene_success.c | 2 +- .../views/avr_isp_view_programmer.c | 2 +- 11 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png create mode 100644 applications/external/avr_isp_programmer/images/avr_wiring.png create mode 100644 applications/external/avr_isp_programmer/images/chif_not_found_83x37.png create mode 100644 applications/external/avr_isp_programmer/images/chip_error_70x22.png create mode 100644 applications/external/avr_isp_programmer/images/chip_long_70x22.png create mode 100644 applications/external/avr_isp_programmer/images/chip_not_found_83x37.png create mode 100644 applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png create mode 100644 applications/external/avr_isp_programmer/images/isp_active_128x53.png create mode 100644 applications/external/avr_isp_programmer/images/link_waiting_77x56.png diff --git a/applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png b/applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png new file mode 100644 index 0000000000000000000000000000000000000000..533787fe3569f70196d3f71e8373102dfd3967a0 GIT binary patch literal 3614 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 Vpqb^9w@m;7?5&;gRaoD1{{|C}E&c!i literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/avr_wiring.png b/applications/external/avr_isp_programmer/images/avr_wiring.png new file mode 100644 index 0000000000000000000000000000000000000000..957012405127ce4504ef8cd4e805b1fc31963026 GIT binary patch literal 4513 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 literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png b/applications/external/avr_isp_programmer/images/chif_not_found_83x37.png new file mode 100644 index 0000000000000000000000000000000000000000..b03bf3567ade9b2e4ce2d29328032ebd40c89401 GIT binary patch literal 3742 zcmaJ@c{r4N`+r3CEm@K{W62gXW^B!vvCLx07Dh%=4Kv21F=I@Pr9`q-hor0#mFy}? z31!Qg5mMR9k`UfwiIbS$IPdAazdzpI=X##!`~BY6{rTLVdwH(wNjU6eBO$t16aWAT zJ6o(PZ*}86`-S;=ZxMz43jiRBqhc_J?JyV+gGu+Jo+bl8$Y8b`1@AT^k6IgDLEFbi z-ms^;$_ay9(N`j6lQnf!MWheKtL6>Jxisv;;RKZ0a^v|E6Cs7X2VJsd^_d z`fmK?j*U;@cLUzlu6^#>dh*_Ux^y|avRkNLSUlC%(8V}Xya=tb>tl3lbIYemuw|5} z1_O{5t|X}jZ>sYF>k&xg0kwLe7XV*KpO`RE@0e9@urH1)HH*$T#us^sub!2B&|WxF z7O)IUMBfK2t@$Fe(>2|ITmj%@r?1Zha9AHWsdeFV9}tHyOD43{~3Y&v9|j0#kfWk%sa|PVEtp`>lKImecjhZF8K_9PO|y&RE+yWxlgUx&ZnB7 zD?8yL6O@R}yt)j_S4%)&*Lk(SmrEKS)7#)TA2S9Xo-*ePPu4H=_T~R(uO&@j)sL?M zz)}sp;jOkXf24o(r*1ZP(PGmkcRvv6XLmga0FGld!1#_zi&kL(z~)BjKD1I=Y1pGz zFSxH^=Wv7AkCP^s&>GE+Xlb-4DRLk4q)zEYw03OQLuK8Qkhhk~M)fZKu_+8maHIP( zNfblsJ5e~NLAy3eM8K*|csEgXFrLrnGC@62SRo^3UA4hhK<0`Ds6AfRMa@3h*cR$~ z84q%|RbE0dcfjM0SwBxUYXe{xf5g_>KyO4f8N@Eg%zxs~0g5V531q6)RhU1HtKoZ6Ro%hS9D;5mOQVOD>ICYAJ>Gk2Rm~`m=eD z4-6Vdu+>w4CzG@rA{`!&X*Si6Nx;Cgs;}*^dvp)qE7NP;8|bP&qgRw=WV=^ArG1bT zP$2}rp$9t97BiVW*)(Z5sWhp&!< zVIF>$anezASzeXv1DCkM-9~3J;a$=4cJ}#YcW(CW^;hs;qdxe;dcJGqrixSA8;{=3 z8JjO@U-(zp;u5iP(XH_mZN;oTLVGBR>^%?C9qudkT~Tbs8<;}p(x)?|GU)CE-74L4 za>*T{HxJ#^ys4xM!507wsOc3;Ja%ghK+;ho&bYh~m1tjLHSQ(;dnU@bS@TiXz`3)! zHR+qmHCIr@MR{u@!m8&Q&0t%tOZY1vScI6Jea-3Hu73PcO!9Z`tY za&U1#zEWNdmi;oYU?Dx{#qr1-2YSJ1Xx;Spedi&Y_)XgPf>j%Ff?%b%hTxDmXAkm~ zaS$D;3~3$u!v*8rWQoZq-Xx}dx|CeqgS^{s{kyf)Rcgzz35^L_3$5j@rl6*(roH2= z<3gsZWA%NV`(_Si4y|3UyY6(o%P`JDLEposv!=7&XN^5Qc{JpxUR7b$GqPR9?){sN^vU5c}Hn__(xTHRnb$$hf^N}hsvvH zRp*Hm9|g+OSLIC$DRn95pP&DI6D1@OHy~M}d{j9i_%Tx!aRf1%$+@*)asJgx>I{TJ z=$7vOU^r2=yHlr`n(da=XG2k-R0l^d$6raXzt{;*GY4lWwT!gYO&(&c26=x9>s`&x zs?2JfFC2QXV6s46h#S8B+UT}Uj;CSpo2E9*N0+G{3$fcb4FbkWBb+hLQIsds>JVQ@ zvPaqbhfnj_#cRYx1@mv_%-a*@6G+oh*r?};*QWJP+n#nhH_>xW#EfAssB=l&Fm4Y} z5V@a^!k-Xj73H;KV?FGg>dQn6#1Q#g#lXDP)!b?;Ijf|LWf!L!%2fT^zFsR+U7Jql zBy*^eF^40*yn7=={7k&k6d|q^6BpwVYmvx^C+zKkrWvz)hB3io*zed>>}VDR>I{FN zf5=$Zycm26IcWOa=($A;*w6EIKOvi7ciMg*9IRVz5_tN>*pK<;xbf_9v59bnbV!>w zBQ%fGxDrz!Uj&xXL!??d#5*0l@h>ZB-9q`R`)f#t~CzTcx9NcH&uN}tLR#-gM`CK79vMJ^DKx4Lm}#*(bto&1)+;o9aE|( zvy{(%XFE&DF%?^{0~fVZ zt>3w1-XpC%qE0i+F(B%AL&wF2Cwu{OV(y|-G3V!o-_LtH6Cj>rPl(@Rvz5%{5-yj^ z4k@I`UHG6q95SU8NAGxj)wiP8Tw7?mJ!l3^w2WCojN#ku`h+P)O|JkX7>3A z@SnpchwfB`Py2GlPD#-hpG&ho_2Rf!rp;>2ILDTrv6d=^rgnQg^T>RFI6<3b%_6r_ z`kY&9Zq;O#S04+gUI?pu67IJ)qm*OH8Cj_d{X?Gnu0IEk8mU_jqp!VMTOE@hiC}7N zayn}U*jfu^wa&FCRxIbO1~4OW{T5zZ!yguhFPy4p=PvgQ+pG!3M0al`uO>-hb|z&c zb;e4>&gC35hr`D$n42>{3NYQIZp|Eptvg$td03hFTh1R9>`)7($P)9NCy}U=OpE7w?WqIZvJgUC`$G|M_Uu?M=Z(iegF%SAai# z`NyL1jf=ehN<|iqz;dJevDic=8L%SJeaIj?8j(VFB@;=ZLG5HD0Pt&5@dOsZ(E;I0 zr-6yvKHv}(0fqcjmY9LB&vF4>3h)P1Kc^EqyI5IF~f2wU5lk67e zg!c^#@P(7qEX+a35Co5aMrIK~A+*zh!H5u)+F!f~-hSH*Q3L(u!U{mC{aX~l@h}KO zXOcmtV5q*Yfq?enh%g^RKccT52xb6-LZH0cR3B=JfEgm7aM0hE8ZRJ|4z6!T3-H8RAL~rk`Q@@_Of|z8#8zz%a=~7M+Qw(@*~_Mf`iUj|2aEkBc6%Ub3|?d`nMplMCRsD-G|*pJBdEXD zV)aYDzpjS`{dS`D2EscJb2lO0{+PQx=-(}3(8oy0uhgTX+fL`k zyt(6*cX@@0I3*>}r~j|T>)y@tdH&;DIV$ov7@BF+XQ7hWqLV(GY3!CV9|KV_4;@Qw zHgg+M-MBTofZWY;GdHGi+ddaS#dNqK9JDfZcS%67m6T`CT6nRQe wIH}{3#|#He;{>wqaxL5a-a2W^9f$+?fvxTxD_~Z-3{Ny*hjYS~qfcJ^KPy3ZW&i*H literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/chip_error_70x22.png b/applications/external/avr_isp_programmer/images/chip_error_70x22.png new file mode 100644 index 0000000000000000000000000000000000000000..16f81178c0ec857591db3fe40830a5955db54e73 GIT binary patch literal 3688 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 literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/chip_long_70x22.png b/applications/external/avr_isp_programmer/images/chip_long_70x22.png new file mode 100644 index 0000000000000000000000000000000000000000..3edfff82de952d6f49a012154a23104e3fd935fa GIT binary patch literal 3656 zcmaJ@c{o&iA3q}dR#`&2V+e^^Eq5kknHjqwjEuAxGh<8|Gse_dB9bj#lCnlxWLHrn zlr5AHrR=gLb@5(HlHizZSI7I`1!2T>3I?-iX0kb^3h_#CiziP*F zmKOy%W8=f+k~DSH#AIz_)o%95JJs*7un|q@1!evQM^}VLhV*UTjnvQs+zN~M<>S81RuB0NO({6*Z{AbYhtY!na38Ire=Gt3|jLFr0}2z{9k z3$FkmCrO^4?ZSFshjeL2hhaj6^a;Js&xAL@US8uHlbuCuGXNOnhIMV|Ld%uI4+@7f zH*W2l74kVQk#l-E-n&f3>=BSN-S4)*-l~no&C6ANeUlRty|ztQ5AsX5&<%RSi8{CS zQ{Tdj*Or$)JRQ@BKpcy(5?cAt@M_UMcTeXPu?t><9}}(CDkV18RNsJ`Y`m&SI&$Mq zJN*;z8J89ix!^eLmHp56b#GF~Ms!yNO-2lW`zK8VLX!0Ik5L4_+G)v>xOHR805D(8 zs(-63Dj4n)IoiqFoHJdw%Gn2md)r*`2Y};v4G8gNxoL|i0N`^Xbnct0EY|PVtrOl; zzkRS?V$IX=0#>7`0V|6Yr-tw0c>$Phl#DvUSMR$?a`eOyWE|Sy}L>1GcR@CaPg?7ekfL_GPIf3nx46NbK7l|NO zYt?xSXB#T!sO6KSgRKDK{91I475r*MnG@!%_AJ{Gy-gTPA|K zstY>M8a0tM(KvyeP?=Dh_YlwWGV{N);xeY~{PLu&(xmL9{-iK14PowjJHvS>|0Z#V zLE;f?$;}GqdrmR=yYx?IpxPr9Z0vGNZe4q$?4#(j%((Z7`(($^wY?6huid)arma4u zeiB^dNlHb_N4CV$wUsh=i|nQ=@pj)!v%jnKCSIw92s46zNt;TSNoTo|bSiYt$|t=P zzh-+)^O}kdlvq%Bw{W;n!gay5jhI+)+$FTs(iQ14ULf{1rO34~>(Cb$6&HHJ!Tgv) zdOnM2dMC_%Jx>4%uSQ6lx7cbO)v}@|c5Kg@a_Ms!$`j91AYjl-rI143 zT$P*Ec-}L=yxFwur^myy?OA!lLA6ug_k=>%iR;Yoc}rH3B;j&N4dDUFj@`!34g6Wg zs?e5!Kb&yK8qILIXo=b8)a;)64B&%fKyXunayd8N}4#^Hh+3)C$_y4GPQBhE-bbqo}c%Za`SrJO6 zdnwW@pO-eyCf6p1J_-G89U~$Y(Xhy5 zMUGeOYTMt$$a2YiV?|e_R|P~a#KyMgxyO**u%QG8h z@(1qC8qP9iV+L=$(!a4k+Z`G3y0I1a!D+I~RN}@pnD0n&m?O?Hg8pbq9ZG>Fxs|-X zUzy7*Tqe&cntV0k+!!|*H#QnZ47;CrWmH$$TG{5<$jUwuHG(^*zDeB--s}SM!uJW# z1>+*jBRsaPt^}V|dzN5|9-w_K>zgsZlv8CcZ=QI*k~$dD zQHR1ly?ZS}{z#5*43pG~iivWIHcep1l9apPsRq2RL0rHH{yRPeKb%R2JEHFC*&67W z6hclK_ZvOYe`4AU@pgaJL&_rAoU+@4g6NbQ`ki_@vNp32GnO?bF&?6r25mjY4!YUV zuo#u6PypGfi%v1Kk9GL<>c7lob@CN1?VI1l+m|37)S%ix2Sd9IyJCBBM|Ji(%vtKf2ty_Ee>COTUo;|z$2z@Tg4kynx~`(q2$2+0-n&-9Pp zXWEKsQDqy?{o*U3d#{PS@GZYwyxm<-yaIdo6Y+@ldmWK7I?c`dS$o_|R7z3yf%chK zBH$7F-$J*kPs4`>!paJo5`Rxay4+|F?KfYL@!|ZV^ znsG}l4Xf1*Ciq4iuYY;I{*i$17YSGK$*9mTgYRdKIg+66Bag`6qq9^@YY$XMR^X~`KQn$@L(6;7(SFdBc!#)1{7y8S?H+nWe!t?^HLDU*^Hu-%o&k@V z<#m%6PX}BDTnRniJ+xJu)$(Q2(zwFum6TQHu@VQS|4fTux8S;nx^%_+s<%C=-58>C z;=2Q1tfX6hdAgA`$J3KClyd#;dh?h%8y_?=y(~7eyjKd{f96t1@uWA`B21>y@v|MdAc$@KZoOIg>lLc<{6 z20aIERfJ4YIz~>)u;!k~a!0!@Hshxb)*S3OI{%nEUp6qg%k8mS#y#{2=4b9_3c@m`)*$u{a3TC5HFLt*n>Pc{lORJ#z&T7JH~G@>vR#?e~u zXshnyY0Z|@IM$q4G@CK+!wtpsn0jms_RbBSJ6XreS?C(HS{9Cq?A%CNN|eEEPfSm2 zicRS)X3Z!*xNOfsG3Oe0f+{9n+F0YFfjK_qcW1bZ}v z#e|TzFpxkdo6iOSW79x3nc_?1g1l&Sh93qzSN#kOVo)()HvQY3q^PIEC}ez1RK!DRm<>lg5MrT8_229nuOI0Uwp)ej(n@c*Gq=0E5Ft~2dF z@%~TY0AdiE26d(duugL*{N8!1Z@FTlaU2?%%i<7OtW!S0{(xN-(9(Sx95Xm>NsTk}XA2)`-f!R1^ti z%NnATUACkyzSj~r+i%=^yT9)r_kPdoob!2}&+B==pZD{8ocpU1bMk{A-O~I03dAUg~cAT!eT*87K7?_o&o^=gBeaVg43)ldUbReV-p>6 z+lJvNBM5TD#D+*GsA?z)Nm@rMWe>3&@J zgXnAR>*GNWyg$^ee(v0Q_R(mjcqya2TcA!*G|5uOK`%tK0CRB9r|_1h=J6?rNvN<2 z6Oa@vCoB1FD)Rtq!6?)baGk(QfXDxxh#*jhPp^X=h}xF;ib*}m6LOWOj-7DSMleJg zFbRyqV0_fKQU{)?vOW<)OP}e0XQU(Z$0x*Z@h{FJ15OB6tS=k@B znhHppFS?+9J5nk+qrvS|Y8k3Z1z{HICaC2r;Nk)~sNQ8IcSKsBw2PEx0%-_HmDdi{ zmH4#u1^}`WWVqEXZTfeKmv(jO$5n`*(fay|e;e%XKDjmBUBom2fN^$k&z2^%e1C`` ze+Yf+{-Jq3&(k7V7gl4bWfCUOfUMa;mnG&-Z_Ki9Rt*eHPfhh(H(}gJ?Jk$MXborT zTsF`D9*o*pUHSBKLM2rDRHy~t+NXv$%eFZOx^D?xbszp5Z?RD+vb~}B4%}qrUPaW9 zo^+7%jl-o~U((J2$6#(9etoESn>;b5xz1}erUyJeXT%efpp}2hgZI0Qnk123H?ax; zi`9(!_v(VYA)evm-JIXt76oW`j@2<_#@ErI}m%L>(aY^tzazfZG{ z|3Llj;d+scv-(#tDoqU-NsKT#lidSvHgMUAu2_a=(Ebq=19iA-@wgY$E7 zG*jXSNiefsy(UzM&$Lx=FG*=In#cVbQ8`XfE;V9Jsos)LDpm#57A@@nwn@;lggag% zfSfHA7tyR;h^Uk1FA@w}0qwAj$Qldy?a(p@^n1}~*s6Sk{a4NJi@YVX;c4-*S?Ou1lrE%KBYj5orz!0Nv26VPco4}&x}VxAn;6iW2ycmggKEo$EX_;@jIbj>@x|1?jq$`;`;h2Fc!K z0*Kq1pd+mjQyEi@Q#w-$Q%Z|&!Wr%+z7N-&Ce$6<&sob)OHS)f^HWl^O`RX4IgaFK z6ZYuEpTLx4S2#X$h|1rqdm#>0Up&@TC{OK-=l z#h2tSyvrO>u}GQlmS~!~eEL3teKdK_zDFsxx$^H~pQA<6f~fOg2LRw(LxdDCFc%8e8Fj_%cbVdI!==XLhqA`oC`CKeREQ9q7@kC zM-|fY83f~p!LFMz{H~3*jrQ1w4p~pmOx84mL_Fln{WX=m#fl;?gz7b^KIt5|bWx)^ zWmB;_7F}47jlk+y>$sFVF5RXY3rwc?uH9wZ3C*bIB`*bE8{|U{C{EFuktFoyRxvujS zH9iq15Ux2y=M$&O%}X*$4t=ODsm|MzS7n!ISCsjI*7*3hinfY^O8Ljr{rp3v74(YB zB$~S%t@3qg<9uRm;^h~YZ)~Ck#G(eoixf{N2Kzl_Nh6OVN7K6Q&KqBTy__@)r4hR& zyZdz}EB1CAZt}`-N`GfTlcQDng)c?N#@K{)K$49h=?cvwt+i9u>=oZr^8R_Ne z4RiTJkLLB~z2>8a@4eBzcR15k$M0=pEB2GabdRyfy*n`PvEpERtbHi$*^DyO1DfDc z^6_zH4ySOHv><2n-H3H>(r6N8FseQ3dghHmU1e)!hkYX>^Gw7T_KNa0c{^~s2gnOK z#6#na2{jFM+qJ$HcuDD1oH25U^1W4p1%LVQR)F-G6x$dqsumFy;Sy;a$BZWK?|~=lae9Waeq*>FxFps@lt`>w-hyzF(EP;B$onhJ;e;j z?rK<$$dfIANNFOIOl+g=j^6%{sia1}?Da#7dpU>VgaaBB8)#r?kA6>dKlY@?LAymu z4Se9OUlVHd0#sh>Y6(|ha=#ExsDIQDD5FtasINL>+7U@bnMXS3 z-jufw-88tnaBq7~szGY}Rz*&vjf<8d@pEnQIYb%CH(*G3QfBv&$m9IQsOQ%zH0XWy zMRP96rNOnTfq3uG)Aj9P_0M>`zlk^tPe)w-HvDn!lsysZI`)k8BQit5NG9f5sq~Os zvdoo!^Mg(yb*tJLA!PYa5gs>t2cUh3@UQLRij@ub4!&&lFGVgrLu#m0_5om=^C zHUv%XR3EAiufSG4c!hdiL&NGSaJR~d=eh~EMdqn2ZLcHadms=SN94#?@G3Oh1n7#b9Z}T|Hi22!`IQk4U3^)B<|{>Tm!6^2yI@2vtjQNX^Y+0Gwx(u4u0LD+Son=h%cuQ{`9GG{t~9f|5QcH0{6Ul_h}u8xzn)H7_c${!Kly_K*MFM-`1pBmp0 zDHi!H^QaL5F=5QwoZZO7c9XkRGv&7KZ*`Q)$wGtI`o4Ya>PhLzPF_q-d_}*Mv-!2| zoBX4p=7#2jFWdZe;HQ_5ug}$UhB=B055^?yr!Il6sBe4z{$$1JZQgpKd}87@A8*Ri z#)97MFz$DyJll-Oc4AQ391@EHn35Up6p$62M58!TNaO(DHVO&=c-6fKL^cs`i}Ya7 zA*7uch(DdlMFRlJ*q=%A@TRaq?i8Ar4;s8s{R#~7BBQ}BdUzO~iKTdYSq8EwPJwm= zk3eq^1Q~2>1VZ^Exde0yn*{QwpZD=Y`lG>r@FKbP&NdVb`XhwxjRyZIiikf3!ZKJC zkO2g)jHBVvdC1VBhLJ< zbX*S&_GGh}NGO!U;XpV#5C)3|g(DCMC`=owt*yn4(DDoLVUzr|eEgJuGTNQGcK^vV6NCdtDrOgruFgrt5e*bLH$WgC>#RYsp@AS9{;~X>GZ#&{n(C_ z|JVDE#D0VTCI#w9@nc+Id2r8;s=SkmiNvxfBsPOZU@*@AY~(Rd2AkpM$zX!Cbs%t% zI-ca=<+HPM_zwskkF@gfW0QP5C{{Q$m`eij@**R#aG0(RLeCTnLtx=>Gn^?5ql+Gkhgj{durKe6P0(DGLuh=0XGxniI@XZv4g{d0>uKs)B&!^?I49)F4tcjj5# z;nuIe&HaG@_>b8V%((0J_IA#|y%Dapi|uIVv<*yG!mPPoofXcM;6GT?H!fZ$Da!Y0 zX$xBW8d*vV%UrQ2w_S|TxOtIRHavm;WE;HqbtZlw`-)`BDNO$x^HQ?ae{z4hYpFiu z)R;}Yp)`=zVQ8c)ec zcxR&Vca72o=5Oxhj3gMkE?xvC3`#Q!CbTNRQJuLXiZ2-YXq)`z<@{E5emj{!l`7OZ tqM<8NsC&lo-2MW+xr4Uu%d$`&en1N&q_;IOR>G|Xurjm5m153@{U2Vwjb;D< literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png b/applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png new file mode 100644 index 0000000000000000000000000000000000000000..a299d3630239b4486e249cc501872bed5996df3b GIT binary patch literal 2459 zcmbVO3s4i+8V(M(gEFORwSrA`4O0uPn|M|5y* zB*aMDxC&7(gP9JN;POOi-9khrC>Z9YJs2U!LnVcQEEC0fDtKo&ILlzb30%M}3J^;~ zv7RzcsilOs4Mq@tD*&R;!LMSk2A~{(`HK9|hQBqEX)3sQr9Je6SZU*F-^fD-p+~Hs; zHLkO%v?>ZoxEv+F#whudr%615FkA0DYR0tMEo}3OOY#xecLWe>xV?u5KtSmC^ z7)Fmj6gjfKstiEV-*Cxbbb+&rRWuI_rBJ)ybs_f1Rn&f2>q3pYwI^|J(hdn{j{0EZIm_F zpIyIWLsRUgOItR-dUbVd|6Zo=_BU_Tj4|{{jxO#=JH4o8er(5{!nZD_j4}MH&zh~9 zVLC~y(0-D6GO0ghZD8BYzP?o{>22~lT6^d@X{SwQ8vrNY-PPIMajIwC)`s14Ep72@ zeq7YOzM`?U{+W)ocXBr`eSOcpk?Rxc=ou5&)fWW|pD};-Z0mvk9}=&`Rb&y<77W~a z(>6YM;6Y5aIU~JKZ}mQZynKHiSTQ#Bczn@&jTiN^?vPJ(jhm7cXLx0oum5P$`TceG zU+wR;OO^)8CVlnM)5p$CO&e94KJt>HccCaHGusmW_b`T6m| z-R6V6Db1pErTot?^d22ojm+2>_)FbD`_+WbDGMx9f@hO27maS2`csiV(D&Fs`PS2& zvrq18du_&zXID(!KIxsU$)iuTYuZ?zmYiP&n&i@Be{IdbS-jA2c0QAlu5NXQv_0K< z3Hvs4eeu6B7yD&CNT~gIkMV&UkRU=V!iQ(+_(O&u^ah$+s{_yn(yBYeD40HeU{xGsIT6W Zfq!wOp!QjS=r55&&8K)tZJ>! zX9!|urpns_+3bLGhpWpJa7G1iR=7U<4q#?(qy>Qh$3$rnPo_4eDBe*|l7 zt*?E0IVl%{I3HrfzVWH??Kkt>Bi(nnZ@7%i#u{xs%!_xbh~O&bT^Ien|%u6t7Zn-j(gUnSv0WUO%}G04p`rhWCnG zY)p@^iEhU3vhKD~_HlseZgR&P04`wVAh`BQ-BvCDz-EUimFr7>YdEZ2&vB$-|40Mx zmb1nUv|Mu|S_sYK#ysNVe4->2tr*c+E~VrQeXl2_R&VVQkw6oGG}=8E(54CgByeRl zDAtB>v+K8U9U@2%MS)yy;bmjE#L~hyq#KOc58jpozljpImNAQ0H-_8X!h!9KrB<|k z_8}vk3}3{bZUYdZTM@NJ@WhY`Ywh=ZPchX6ni4k*@ALM!(c$T_qS+ZeK2IdHqcw8o zdWt;+hhlXwt+4vfhdEW7FT)@$P3Xs`l(`dJJ08oF@D;a6l%FkOtGT)6+WnZpelWzK zo?C;Rfd&(f>Ko(D@s=Nr3&2O@)D8@BYjU&Qux?b4NhmOTBLCvRkLJTJ2zVskSXp-9 zVC*5NP*4=6SyS%dO$_I(}mMxRqYvwdUm z@kfY+wMLN?#WN0b9wv!14nImY&l7)lTf7wq(}XXi&ZP;aQSI7?>s5sq+ z!4BIuIUJhIo2)Pot+O9roT_aB^SX*x`YTI&@fSy22~lsBf805E)laD=bz7?Dwsuir z4ickks%l?pvzq9x%Q=XXr$vvl-pRyW!YfO0g#N-LdJT>!bIMKar%|?;pP5%@P~)%}BB0-Ds^FwxM2hX&pE+kcXgiwElP_wajan;%6nW)J=G0&r zuPFITsaY>CFtg05`C|cfb3czzm3(p>!+c$bwO*@xQ?;a^t;1if zG3T4~Fu8;zLdwLA`08G*2mOYB7z##vwm416O_5v3Ef3^5)T*ilt@n_EG{Ld*@6;wSZnp8}m%X3(&s-=XVLptQ* z?arOAG%U?5Jw8xVT9bbuzuGdvvN&si)Kvbp>P=PQGx747j~v5gRphE`1d@vw>DlYD zrlo|sgljLZ{jsgh$sai=P%L#$D%kglk1*;iYAn6$?vn1c*WZ%op(K2_Q1?gGsj5RA zCz?GoZ8P2(k;F*VzG16Tw{Mz-c0f{eAQ_S^qiuE5rt~%M^Amx6Ynd698I6kt!;h9U zmOPgtNAA5ESBr8$NebGZ0cv;JAzvkt2!YSzW@am;nuUANu9-CiJ{c^pJyyBVS% z;<#^fBk-#9s~BC>F!6iE;G%wXcD25Uer#xI=uAVYv`5>Yai!AhbE#eNU7iBrXM#Tu z^l%bp3AdYq`4qwPk9AkV{%a znlIE|=(a%I9p3iiGw~*u&5j@;N@W_9%P+^b7FQ!DGbeecg2YmxZRcqLIbDt4!t+H7 zAqSOF$$I8dmZuW`r7xsZAR2vqH%`ERdbbRs&6P1#?_khn~!FovP9GUz+{9rstz7@CqB*_T_kOhP(}JensxW?oZ<&1&I%II-u+eQ&30sRan{Ms#kZC1!*QB- zm+$Q^9&9`~ai=Ob!pvSp3O`#{atT?Xh0V8(#3zNt&DCz*?tSj_vtue*jsnR=DYGd86#l`XC;a1QpDeC@HyDPdbSe(l zgjHdxAH33fUQ5h>)75!e7xxhN4fhkLvD7#El<;AL(z_%XRQp}+&;DV@+VyRnH!p|n zKz0`W?)}6~lg-L?-LjiS^Bc*VMPG3nk%&<-0 zbaZiiVf9w0ci_ud;Fi(wF~PfPS`GoGtGG9wL-V2U5=blE(V0n^*McEGMx2N5R|Ua?u5HlLtuj{xo@^N|O`lWhC_G<5l(K<(XSoco+TC5;ue{5Q8M+ASwLe?oA zByv*MXM27tAJgsDEuST}bAP9!OiUCSywSh#p{qBwHz#E!CE*qMYVP)z`UUYv!!3<1 zM_<12SA}2rc6M{Ific36T7EDtXf=Hmd|h$ZUH$OID6hDdM=@P0$o0suBePaK|(w=hS!Qppg)o(;sG zOk<$|Kug!3MsW2a(!nl7k|#x5X1V5-4A|36TgG190%k$O5IsDN1AU0LftEPeKrdIM zn~bgwSj!*9A|Mm#1h7B(GQ}6=uPyTzFN!7asi899zf9;}+A{wM3U6@+jG_7v!I}`b ziYp8T18X87L^lG$Mb(|)stiWJ5O64*b!)1?HBksv6dVcu`;uWf^l@`X*eMIcmI7An306gt6Qh2kswivdgYb@lP2(LJdY z@E#+9|u4GM?A_OkkAXkqccP08ectbOS=#Q(qt3hN`e%SS;1`3Ykcu|H8Wc7klcr*u8-u(^#IdL?2H-qMM-)l??tXYn12jV^RMt z-``lb-^ZfyTP&0n40Nxz|EJf#RICBo6aN`r*5;q_CsJ55@535yKkHgm)`!7y#vEtB zT6cGMa|iE@vZQ@<8%x_=VCEUj6aYYeCRlx(|InYQ3j$4GuJG99-9E$yK6D9-^!kkir((8ExON>}J~Ocpw}BbH6#MyjJ@7P6)WtmSMmDP-fQf-6whZkY`fn1t B&F}yK literal 0 HcmV?d00001 diff --git a/applications/external/avr_isp_programmer/images/link_waiting_77x56.png b/applications/external/avr_isp_programmer/images/link_waiting_77x56.png new file mode 100644 index 0000000000000000000000000000000000000000..d7d32aed59a19e24a7e1f2216c806872610a0af5 GIT binary patch literal 3883 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 - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_icon(popup, 32, 5, &I_dolphin_nice_96x59); popup_set_header(popup, "Success!", 8, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, app); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c index ee1647dd11b..34e18770b2f 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c @@ -35,7 +35,7 @@ void avr_isp_programmer_view_draw(Canvas* canvas, AvrIspProgrammerViewModel* mod elements_multiline_text(canvas, 45, 10, "ISP mode active"); } else { canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 51, 6, &I_Link_waiting_77x56); + canvas_draw_icon(canvas, 51, 6, &I_link_waiting_77x56); elements_multiline_text(canvas, 0, 25, "Waiting for\nsoftware\nconnection"); } } From 9f78caec6699193e04598a5b7cb9925704d7a95d Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 12:41:19 +0400 Subject: [PATCH 37/50] AVR_ISP: fix PVS --- .../helpers/avr_isp_worker_rw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 8a5f2cf4b01..ebdb7e01a07 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -79,7 +79,7 @@ static int32_t avr_isp_worker_rw_thread(void* context) { } else { if(instance->callback_status) instance->callback_status( - instance->context_status, AvrIspWorkerRWStatusEndWriting); + instance->context_status, AvrIspWorkerRWStatusErrorWriting); } } @@ -318,7 +318,7 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = - (float)i / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(i) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); @@ -346,7 +346,8 @@ static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const ch instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); - instance->progress_eeprom = (float)i / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + instance->progress_eeprom = + (float)(i) / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); @@ -520,7 +521,7 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); break; case FlipperI32HexFileStatusUdateAddr: @@ -582,7 +583,7 @@ static bool addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: @@ -685,7 +686,7 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); break; case FlipperI32HexFileStatusUdateAddr: @@ -736,8 +737,7 @@ static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (float)addr / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); - break; + (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: From 04cca7a3a762a2fa35f1d4d183d832a31e5456ca Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 13:45:03 +0400 Subject: [PATCH 38/50] AVR_ISP: fix PVS --- .../avr_isp_programmer/helpers/avr_isp_worker_rw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index ebdb7e01a07..b4d9856a230 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -318,7 +318,7 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = - (float)(i) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (double)(i) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); @@ -347,7 +347,7 @@ static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const ch flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); instance->progress_eeprom = - (float)(i) / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + (double)(i) / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); @@ -521,7 +521,7 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); break; case FlipperI32HexFileStatusUdateAddr: @@ -583,7 +583,7 @@ static bool addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: @@ -686,7 +686,7 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); break; case FlipperI32HexFileStatusUdateAddr: @@ -737,7 +737,7 @@ static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (float)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: From b7730ef5af403924d07f5dbcf5ebeaf614b4891e Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 14:48:14 +0400 Subject: [PATCH 39/50] AVR_ISP: fix gui --- .../external/avr_isp_programmer/views/avr_isp_view_reader.c | 2 +- .../external/avr_isp_programmer/views/avr_isp_view_writer.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 92f8ef27847..fd19d48e0c4 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -59,7 +59,7 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { canvas_set_font(canvas, FontPrimary); switch(model->status) { case AvrIspReaderViewStatusIDLE: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reding dump"); + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to dump"); canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Start"); break; diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 86c1e7a5c41..b6ee7213d81 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -59,7 +59,7 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_set_font(canvas, FontPrimary); switch(model->status) { case AvrIspWriterViewStatusIDLE: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to write"); canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Start"); break; @@ -67,10 +67,11 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); break; case AvrIspWriterViewStatusVerification: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); break; case AvrIspWriterViewStatusVerificationOk: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); + canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Reflash"); elements_button_right(canvas, "Exit"); break; From f15a567b26c3ebf761f4f1b1d20a7f89ceed8839 Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 16:24:25 +0400 Subject: [PATCH 40/50] AVR_ISP: fix stuck in navigation --- .../avr_isp_programmer/views/avr_isp_view_chip_detect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 90a22008ef0..0d3229c38e4 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -99,16 +99,18 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { false); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + bool detect_chip = false; with_view_model( instance->view, AvrIspChipDetectViewModel * model, { if(model->state != AvrIspChipDetectViewStateDetecting) { model->state = AvrIspChipDetectViewStateDetecting; - avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); + detect_chip = true; } }, false); + if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } return true; From 9b88e20355c429d4385eff2a5ba64f0052f6efba Mon Sep 17 00:00:00 2001 From: SkorP Date: Fri, 24 Mar 2023 16:35:34 +0400 Subject: [PATCH 41/50] AVR_ISP: fix PVS --- .../external/avr_isp_programmer/avr_isp_app.c | 2 +- .../helpers/avr_isp_worker_rw.c | 12 ++-- .../views/avr_isp_view_chip_detect.c | 58 ++++++++++--------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index 36212de8592..e582834c6a7 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -98,7 +98,7 @@ AvrIspApp* avr_isp_app_alloc() { scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); return app; -} +} //-V773 void avr_isp_app_free(AvrIspApp* app) { furi_assert(app); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index b4d9856a230..67693ad6719 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -318,7 +318,7 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = - (double)(i) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); @@ -347,7 +347,7 @@ static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const ch flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); instance->progress_eeprom = - (double)(i) / avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + (float)(i) /((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); @@ -521,7 +521,7 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); break; case FlipperI32HexFileStatusUdateAddr: @@ -583,7 +583,7 @@ static bool addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: @@ -686,7 +686,7 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size / 2; instance->progress_flash = - (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2); + (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); break; case FlipperI32HexFileStatusUdateAddr: @@ -737,7 +737,7 @@ static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* } addr += flipper_hex_ret.data_size; instance->progress_eeprom = - (double)(addr) / (avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (float)(addr) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); break; case FlipperI32HexFileStatusUdateAddr: diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c index 0d3229c38e4..fdcf71c36c1 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c @@ -84,33 +84,39 @@ bool avr_isp_chip_detect_view_input(InputEvent* event, void* context) { furi_assert(context); AvrIspChipDetectView* instance = context; - if(event->key == InputKeyBack || event->type != InputTypeShort) { + + if(event->type == InputTypeShort) { + if(event->key == InputKeyBack) { + return false; + } else if(event->key == InputKeyRight) { + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + if(model->state == AvrIspChipDetectViewStateDetected) { + if(instance->callback) + instance->callback( + AvrIspCustomEventSceneChipDetectOk, instance->context); + } + }, + false); + + } else if(event->key == InputKeyLeft) { + bool detect_chip = false; + with_view_model( + instance->view, + AvrIspChipDetectViewModel * model, + { + if(model->state != AvrIspChipDetectViewStateDetecting) { + model->state = AvrIspChipDetectViewStateDetecting; + detect_chip = true; + } + }, + false); + if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); + } + } else { return false; - } else if(event->key == InputKeyRight && event->type == InputTypeShort) { - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - if(model->state == AvrIspChipDetectViewStateDetected) { - if(instance->callback) - instance->callback(AvrIspCustomEventSceneChipDetectOk, instance->context); - } - }, - false); - - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - bool detect_chip = false; - with_view_model( - instance->view, - AvrIspChipDetectViewModel * model, - { - if(model->state != AvrIspChipDetectViewStateDetecting) { - model->state = AvrIspChipDetectViewStateDetecting; - detect_chip = true; - } - }, - false); - if(detect_chip) avr_isp_worker_rw_detect_chip(instance->avr_isp_worker_rw); } return true; From 4ccb164f142b591d049ef9836f795b9e661e5f40 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 12:07:30 +0400 Subject: [PATCH 42/50] AVR_ISP: changing the Fuse bit recording logic --- .../avr_isp_programmer/helpers/avr_isp.c | 20 +- .../helpers/avr_isp_event.h | 1 + .../helpers/avr_isp_types.h | 1 + .../helpers/avr_isp_worker_rw.c | 256 +++++++++++++++--- .../helpers/avr_isp_worker_rw.h | 12 + .../lib/driver/avr_isp_prog.c | 30 +- .../scenes/avr_isp_scene_chip_detect.c | 3 +- .../scenes/avr_isp_scene_writer.c | 8 +- .../views/avr_isp_view_writer.c | 27 +- .../views/avr_isp_view_writer.h | 3 +- 10 files changed, 302 insertions(+), 59 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 2cdb230277e..6a429eabac3 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -117,16 +117,26 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { furi_assert(instance); AvrIspSpiSwSpeed spi_speed[] = { - AvrIspSpiSwSpeed1Mhz, - AvrIspSpiSwSpeed400Khz, - AvrIspSpiSwSpeed250Khz, - AvrIspSpiSwSpeed125Khz, + //AvrIspSpiSwSpeed1Mhz, + // AvrIspSpiSwSpeed400Khz, + // AvrIspSpiSwSpeed250Khz, + // AvrIspSpiSwSpeed125Khz, AvrIspSpiSwSpeed40Khz, AvrIspSpiSwSpeed20Khz, }; for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_start_pmode(instance, spi_speed[i])) { - return true; + AvrIspSignature sig = avr_isp_read_signature(instance); + AvrIspSignature sig_examination = avr_isp_read_signature(instance); + uint8_t y = 0; + while(y < 16) { + if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) != + 0) + break; + sig_examination = avr_isp_read_signature(instance); + y++; + } + if(y == 16) return true; } } return false; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h index 90c2f2a95fe..c704b5b356a 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_event.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_event.h @@ -15,6 +15,7 @@ typedef enum { AvrIspCustomEventSceneErrorVerification, AvrIspCustomEventSceneErrorReading, AvrIspCustomEventSceneErrorWriting, + AvrIspCustomEventSceneErrorWritingFuse, AvrIspCustomEventSceneInputName, AvrIspCustomEventSceneSuccess, AvrIspCustomEventSceneExit, diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h index c4813e5140c..5e174ec3b9c 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_types.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_types.h @@ -28,4 +28,5 @@ typedef enum { AvrIspErrorReading, AvrIspErrorWriting, AvrIspErrorVerification, + AvrIspErrorWritingFuse, } AvrIspError; \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 67693ad6719..92490021ee7 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -44,11 +44,12 @@ typedef enum { AvrIspWorkerRWEvtReading = (1 << 1), AvrIspWorkerRWEvtVerification = (1 << 2), AvrIspWorkerRWEvtWriting = (1 << 3), + AvrIspWorkerRWEvtWritingFuse = (1 << 4), } AvrIspWorkerRWEvt; -#define AVR_ISP_WORKER_ALL_EVENTS \ - (AvrIspWorkerRWEvtWriting | AvrIspWorkerRWEvtVerification | AvrIspWorkerRWEvtReading | \ - AvrIspWorkerRWEvtStop) +#define AVR_ISP_WORKER_ALL_EVENTS \ + (AvrIspWorkerRWEvtWritingFuse | AvrIspWorkerRWEvtWriting | AvrIspWorkerRWEvtVerification | \ + AvrIspWorkerRWEvtReading | AvrIspWorkerRWEvtStop) /** Worker thread * @@ -71,6 +72,18 @@ static int32_t avr_isp_worker_rw_thread(void* context) { break; } + if(events & AvrIspWorkerRWEvtWritingFuse) { + if(avr_isp_worker_rw_write_fuse(instance, instance->file_path, instance->file_name)) { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusEndWritingFuse); + } else { + if(instance->callback_status) + instance->callback_status( + instance->context_status, AvrIspWorkerRWStatusErrorWritingFuse); + } + } + if(events & AvrIspWorkerRWEvtWriting) { if(avr_isp_worker_rw_write_dump(instance, instance->file_path, instance->file_name)) { if(instance->callback_status) @@ -347,7 +360,7 @@ static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const ch flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); instance->progress_eeprom = - (float)(i) /((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); + (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].eepromsize); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_eeprom); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); @@ -613,6 +626,8 @@ bool avr_isp_worker_rw_verification( furi_assert(file_path); furi_assert(file_name); + FURI_LOG_D(TAG, "Verification chip"); + instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; FuriString* file_path_name = furi_string_alloc(); @@ -770,10 +785,10 @@ bool avr_isp_worker_rw_write_dump( instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; bool ret = false; - uint8_t lfuse; - uint8_t hfuse; - uint8_t efuse; - uint8_t lock; + // uint8_t lfuse; + // uint8_t hfuse; + // uint8_t efuse; + // uint8_t lock; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -831,30 +846,30 @@ bool avr_isp_worker_rw_write_dump( break; } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { - FURI_LOG_E(TAG, "Missing Lfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { - FURI_LOG_E(TAG, "Missing Hfuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { - FURI_LOG_E(TAG, "Missing Efuse"); - break; - } - } - if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { - FURI_LOG_E(TAG, "Missing Lock"); - break; - } - } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + // if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { + // FURI_LOG_E(TAG, "Missing Lfuse"); + // break; + // } + // } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + // if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { + // FURI_LOG_E(TAG, "Missing Hfuse"); + // break; + // } + // } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + // if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { + // FURI_LOG_E(TAG, "Missing Efuse"); + // break; + // } + // } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + // if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { + // FURI_LOG_E(TAG, "Missing Lock"); + // break; + // } + // } if(!flipper_format_read_string(flipper_format, "Dump_flash", temp_str_1)) { FURI_LOG_E(TAG, "Missing Dump_flash"); @@ -929,10 +944,167 @@ bool avr_isp_worker_rw_write_dump( file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); avr_isp_worker_rw_write_eeprom(instance, furi_string_get_cstr(file_path_name)); } + ret = true; + // //write fuse and lock + // FURI_LOG_D(TAG, "Write fuse"); + // ret = true; + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + // if(instance->lfuse != lfuse) { + // if(!avr_isp_write_fuse_low(instance->avr_isp, lfuse)) { + // FURI_LOG_E(TAG, "Write Lfuse: error"); + // ret = false; + // } + // } + // } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + // if(instance->hfuse != hfuse) { + // if(!avr_isp_write_fuse_high(instance->avr_isp, hfuse)) { + // FURI_LOG_E(TAG, "Write Hfuse: error"); + // ret = false; + // } + // } + // } + // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + // if(instance->efuse != efuse) { + // if(!avr_isp_write_fuse_extended(instance->avr_isp, efuse)) { + // FURI_LOG_E(TAG, "Write Efuse: error"); + // ret = false; + // } + // } + // } + + // if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + // FURI_LOG_D(TAG, "Write lock byte"); + // if(instance->lock != lock) { + // if(!avr_isp_write_lock_byte(instance->avr_isp, lock)) { + // FURI_LOG_E(TAG, "Write Lock byte: error"); + // ret = false; + // } + // } + // } + + avr_isp_end_pmode(instance->avr_isp); + } while(false); + } + + furi_string_free(file_path_name); + furi_string_free(temp_str_1); + furi_string_free(temp_str_2); + + return ret; +} + +void avr_isp_worker_rw_write_dump_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + + instance->file_path = file_path; + instance->file_name = file_name; + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWriting); +} + +bool avr_isp_worker_rw_write_fuse( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name) { + furi_assert(instance); + furi_assert(file_path); + furi_assert(file_name); + + FURI_LOG_D(TAG, "Write fuse chip"); + + bool ret = false; + uint8_t lfuse; + uint8_t hfuse; + uint8_t efuse; + uint8_t lock; + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + FuriString* temp_str = furi_string_alloc(); + + uint32_t temp_data32; + + if(!avr_isp_worker_rw_detect_chip(instance)) { + FURI_LOG_E(TAG, "No detect AVR chip"); + } else { + //upload file with description + do { + furi_string_printf(temp_str, "%s/%s%s", file_path, file_name, AVR_ISP_APP_EXTENSION); + if(!flipper_format_file_open_existing(flipper_format, furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(temp_str)); + break; + } + + if(!flipper_format_read_header(flipper_format, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + break; + } + + if((!strcmp(furi_string_get_cstr(temp_str), AVR_ISP_APP_FILE_TYPE)) && + temp_data32 == AVR_ISP_APP_FILE_VERSION) { + } else { + FURI_LOG_E(TAG, "Type or version mismatch"); + break; + } + + AvrIspSignature sig_read = {0}; + + if(!flipper_format_read_hex( + flipper_format, "Signature", (uint8_t*)&sig_read, sizeof(AvrIspSignature))) { + FURI_LOG_E(TAG, "Missing Signature"); + break; + } + + if(memcmp( + (uint8_t*)&instance->signature, (uint8_t*)&sig_read, sizeof(AvrIspSignature)) != + 0) { + FURI_LOG_E( + TAG, + "Wrong chip. Connected (%02X %02X %02X), read from file (%02X %02X %02X)", + instance->signature.vendor, + instance->signature.part_family, + instance->signature.part_number, + sig_read.vendor, + sig_read.part_family, + sig_read.part_number); + break; + } + + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { + if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { + FURI_LOG_E(TAG, "Missing Lfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { + if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { + FURI_LOG_E(TAG, "Missing Hfuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { + if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { + FURI_LOG_E(TAG, "Missing Efuse"); + break; + } + } + if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { + if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { + FURI_LOG_E(TAG, "Missing Lock"); + break; + } + } + + if(!avr_isp_auto_set_spi_speed_start_pmode(instance->avr_isp)) { + FURI_LOG_E(TAG, "Well, I managed to enter the mod program"); + break; + } - //write fuse and lock - FURI_LOG_D(TAG, "Write fuse"); ret = true; + if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { if(instance->lfuse != lfuse) { if(!avr_isp_write_fuse_low(instance->avr_isp, lfuse)) { @@ -967,19 +1139,17 @@ bool avr_isp_worker_rw_write_dump( } } } - avr_isp_end_pmode(instance->avr_isp); } while(false); } - furi_string_free(file_path_name); - furi_string_free(temp_str_1); - furi_string_free(temp_str_2); - - return true; + flipper_format_free(flipper_format); + furi_record_close(RECORD_STORAGE); + furi_string_free(temp_str); + return ret; } -void avr_isp_worker_rw_write_dump_start( +void avr_isp_worker_rw_write_fuse_start( AvrIspWorkerRW* instance, const char* file_path, const char* file_name) { @@ -987,5 +1157,5 @@ void avr_isp_worker_rw_write_dump_start( instance->file_path = file_path; instance->file_name = file_name; - furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWriting); -} + furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerRWEvtWritingFuse); +} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h index 26dc02a6e7d..2c52a8700d5 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h @@ -15,10 +15,12 @@ typedef enum { AvrIspWorkerRWStatusEndReading = 1, AvrIspWorkerRWStatusEndVerification = 2, AvrIspWorkerRWStatusEndWriting = 3, + AvrIspWorkerRWStatusEndWritingFuse = 4, AvrIspWorkerRWStatusErrorReading = (-1), AvrIspWorkerRWStatusErrorVerification = (-2), AvrIspWorkerRWStatusErrorWriting = (-3), + AvrIspWorkerRWStatusErrorWritingFuse = (-4), AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. } AvrIspWorkerRWStatus; @@ -85,3 +87,13 @@ void avr_isp_worker_rw_write_dump_start( AvrIspWorkerRW* instance, const char* file_path, const char* file_name); + +bool avr_isp_worker_rw_write_fuse( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); + +void avr_isp_worker_rw_write_fuse_start( + AvrIspWorkerRW* instance, + const char* file_path, + const char* file_name); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index 4d6d263f058..fd59788c859 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -6,6 +6,14 @@ #define AVR_ISP_PROG_TX_RX_BUF_SIZE 320 #define TAG "AvrIspProg" +struct AvrIspProgSignature { + uint8_t vendor; + uint8_t part_family; + uint8_t part_number; +}; + +typedef struct AvrIspProgSignature AvrIspProgSignature; + struct AvrIspProgCfgDevice { uint8_t devicecode; uint8_t revision; @@ -262,6 +270,15 @@ static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_ return false; } +static AvrIspProgSignature avr_isp_prog_check_signature(AvrIspProg* instance) { + furi_assert(instance); + AvrIspProgSignature signature; + signature.vendor = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR); + signature.part_family = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY); + signature.part_number = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER); + return signature; +} + static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { AvrIspSpiSwSpeed spi_speed[] = { AvrIspSpiSwSpeed1Mhz, @@ -273,7 +290,18 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { }; for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { - return true; + AvrIspProgSignature sig = avr_isp_prog_check_signature(instance); + AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); + uint8_t y = 0; + while(y < 16) { + if(memcmp( + (uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspProgSignature)) != + 0) + break; + sig_examination = avr_isp_prog_check_signature(instance); + y++; + } + if(y == 16) return true; } } return false; diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index c43803ffe03..7bb0055af1d 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -14,6 +14,7 @@ void avr_isp_scene_chip_detect_on_enter(void* context) { switch(app->error) { case AvrIspErrorReading: case AvrIspErrorWriting: + case AvrIspErrorWritingFuse: avr_isp_chip_detect_set_state( app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorOccured); break; @@ -36,7 +37,7 @@ void avr_isp_scene_chip_detect_on_enter(void* context) { bool avr_isp_scene_chip_detect_on_event(void* context, SceneManagerEvent event) { furi_assert(context); - + AvrIspApp* app = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c index 4e333bd959d..39c944fd5fc 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c @@ -19,7 +19,7 @@ void avr_isp_scene_writer_on_enter(void* context) { bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { furi_assert(context); - + AvrIspApp* app = context; bool consumed = false; if(event.type == SceneManagerEventTypeBack) { @@ -49,6 +49,12 @@ bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) { app->scene_manager, AvrIspSceneChipDetect); consumed = true; break; + case AvrIspCustomEventSceneErrorWritingFuse: + app->error = AvrIspErrorWritingFuse; + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, AvrIspSceneChipDetect); + consumed = true; + break; default: break; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index b6ee7213d81..980ff4452eb 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -69,7 +69,10 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { case AvrIspWriterViewStatusVerification: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); break; - case AvrIspWriterViewStatusVerificationOk: + case AvrIspWriterViewStatusWritingFuse: + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); + break; + case AvrIspWriterViewStatusWritingFuseOk: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Reflash"); @@ -100,7 +103,7 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { AvrIspWriterViewModel * model, { if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusVerificationOk)) { + (model->status == AvrIspWriterViewStatusWritingFuseOk)) { if(instance->callback) instance->callback(AvrIspCustomEventSceneExit, instance->context); ret = false; @@ -113,8 +116,9 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { AvrIspWriterViewModel * model, { if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusVerificationOk)) { + (model->status == AvrIspWriterViewStatusWritingFuseOk)) { model->status = AvrIspWriterViewStatusWriting; + avr_isp_worker_rw_write_dump_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); } @@ -126,7 +130,7 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { AvrIspWriterViewModel * model, { if((model->status == AvrIspWriterViewStatusIDLE) || - (model->status == AvrIspWriterViewStatusVerificationOk)) { + (model->status == AvrIspWriterViewStatusWritingFuseOk)) { if(instance->callback) instance->callback(AvrIspCustomEventSceneExitStartMenu, instance->context); ret = false; @@ -150,13 +154,22 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s model->status = AvrIspWriterViewStatusVerification; avr_isp_worker_rw_verification_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + break; + case AvrIspWorkerRWStatusErrorVerification: + if(instance->callback) + instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); break; case AvrIspWorkerRWStatusEndVerification: - model->status = AvrIspWriterViewStatusVerificationOk; + avr_isp_worker_rw_write_fuse_start( + instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + model->status = AvrIspWriterViewStatusVerification; break; - case AvrIspWorkerRWStatusErrorVerification: + case AvrIspWorkerRWStatusErrorWritingFuse: if(instance->callback) - instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); + instance->callback(AvrIspCustomEventSceneErrorWritingFuse, instance->context); + break; + case AvrIspWorkerRWStatusEndWritingFuse: + model->status = AvrIspWriterViewStatusWritingFuseOk; break; default: diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h index 917b401db7f..a2a3b7b85ca 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h @@ -12,7 +12,8 @@ typedef enum { AvrIspWriterViewStatusIDLE, AvrIspWriterViewStatusWriting, AvrIspWriterViewStatusVerification, - AvrIspWriterViewStatusVerificationOk, + AvrIspWriterViewStatusWritingFuse, + AvrIspWriterViewStatusWritingFuseOk, } AvrIspWriterViewStatus; void avr_isp_writer_update_progress(AvrIspWriterView* instance); From 25452bfdc11f3dcc8b57c912f85380089f3a39b0 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 12:23:40 +0400 Subject: [PATCH 43/50] AVR_ISP: fix PVS --- .../avr_isp_programmer/helpers/avr_isp.c | 2 +- .../helpers/avr_isp_worker_rw.c | 69 +------------------ .../lib/driver/avr_isp_prog.c | 2 +- .../views/avr_isp_view_reader.c | 1 + .../views/avr_isp_view_writer.c | 9 +-- 5 files changed, 9 insertions(+), 74 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 6a429eabac3..aaf5eaf429b 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -127,7 +127,7 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_start_pmode(instance, spi_speed[i])) { AvrIspSignature sig = avr_isp_read_signature(instance); - AvrIspSignature sig_examination = avr_isp_read_signature(instance); + AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V654 uint8_t y = 0; while(y < 16) { if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) != diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 92490021ee7..217edb0f1d7 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -785,10 +785,6 @@ bool avr_isp_worker_rw_write_dump( instance->progress_flash = 0.0f; instance->progress_eeprom = 0.0f; bool ret = false; - // uint8_t lfuse; - // uint8_t hfuse; - // uint8_t efuse; - // uint8_t lock; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* flipper_format = flipper_format_file_alloc(storage); @@ -846,31 +842,6 @@ bool avr_isp_worker_rw_write_dump( break; } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - // if(!flipper_format_read_hex(flipper_format, "Lfuse", &lfuse, 1)) { - // FURI_LOG_E(TAG, "Missing Lfuse"); - // break; - // } - // } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - // if(!flipper_format_read_hex(flipper_format, "Hfuse", &hfuse, 1)) { - // FURI_LOG_E(TAG, "Missing Hfuse"); - // break; - // } - // } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - // if(!flipper_format_read_hex(flipper_format, "Efuse", &efuse, 1)) { - // FURI_LOG_E(TAG, "Missing Efuse"); - // break; - // } - // } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - // if(!flipper_format_read_hex(flipper_format, "Lock", &lock, 1)) { - // FURI_LOG_E(TAG, "Missing Lock"); - // break; - // } - // } - if(!flipper_format_read_string(flipper_format, "Dump_flash", temp_str_1)) { FURI_LOG_E(TAG, "Missing Dump_flash"); break; @@ -944,45 +915,7 @@ bool avr_isp_worker_rw_write_dump( file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); avr_isp_worker_rw_write_eeprom(instance, furi_string_get_cstr(file_path_name)); } - ret = true; - // //write fuse and lock - // FURI_LOG_D(TAG, "Write fuse"); - // ret = true; - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 0) { - // if(instance->lfuse != lfuse) { - // if(!avr_isp_write_fuse_low(instance->avr_isp, lfuse)) { - // FURI_LOG_E(TAG, "Write Lfuse: error"); - // ret = false; - // } - // } - // } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 1) { - // if(instance->hfuse != hfuse) { - // if(!avr_isp_write_fuse_high(instance->avr_isp, hfuse)) { - // FURI_LOG_E(TAG, "Write Hfuse: error"); - // ret = false; - // } - // } - // } - // if(avr_isp_chip_arr[instance->chip_arr_ind].nfuses > 2) { - // if(instance->efuse != efuse) { - // if(!avr_isp_write_fuse_extended(instance->avr_isp, efuse)) { - // FURI_LOG_E(TAG, "Write Efuse: error"); - // ret = false; - // } - // } - // } - - // if(avr_isp_chip_arr[instance->chip_arr_ind].nlocks == 1) { - // FURI_LOG_D(TAG, "Write lock byte"); - // if(instance->lock != lock) { - // if(!avr_isp_write_lock_byte(instance->avr_isp, lock)) { - // FURI_LOG_E(TAG, "Write Lock byte: error"); - // ret = false; - // } - // } - // } - + ret = true; avr_isp_end_pmode(instance->avr_isp); } while(false); } diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index fd59788c859..e61505790f0 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -291,7 +291,7 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { AvrIspProgSignature sig = avr_isp_prog_check_signature(instance); - AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); + AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V654 uint8_t y = 0; while(y < 16) { if(memcmp( diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index fd19d48e0c4..7beeacfcdfb 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -129,6 +129,7 @@ static void avr_isp_reader_callback_status(void* context, AvrIspWorkerRWStatus s model->status = AvrIspReaderViewStatusVerification; avr_isp_worker_rw_verification_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); + model->status = AvrIspReaderViewStatusVerification; break; case AvrIspWorkerRWStatusEndVerification: if(instance->callback) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 980ff4452eb..bdc9ee392ff 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -70,7 +70,7 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); break; case AvrIspWriterViewStatusWritingFuse: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing fuse"); break; case AvrIspWriterViewStatusWritingFuseOk: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); @@ -118,7 +118,7 @@ bool avr_isp_writer_view_input(InputEvent* event, void* context) { if((model->status == AvrIspWriterViewStatusIDLE) || (model->status == AvrIspWriterViewStatusWritingFuseOk)) { model->status = AvrIspWriterViewStatusWriting; - + avr_isp_worker_rw_write_dump_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); } @@ -154,7 +154,8 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s model->status = AvrIspWriterViewStatusVerification; avr_isp_worker_rw_verification_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - break; + model->status = AvrIspWriterViewStatusVerification; + break; case AvrIspWorkerRWStatusErrorVerification: if(instance->callback) instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context); @@ -162,7 +163,7 @@ static void avr_isp_writer_callback_status(void* context, AvrIspWorkerRWStatus s case AvrIspWorkerRWStatusEndVerification: avr_isp_worker_rw_write_fuse_start( instance->avr_isp_worker_rw, instance->file_path, instance->file_name); - model->status = AvrIspWriterViewStatusVerification; + model->status = AvrIspWriterViewStatusWritingFuse; break; case AvrIspWorkerRWStatusErrorWritingFuse: if(instance->callback) From 4bbe9ec856b0151e566b03ca56eb8bf644e1f288 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 19:13:31 +0400 Subject: [PATCH 44/50] AVR_ISP: fix read/write chips with memory greater than 64Kb --- .../avr_isp_programmer/helpers/avr_isp.c | 15 +++- .../avr_isp_programmer/helpers/avr_isp.h | 4 +- .../helpers/avr_isp_worker_rw.c | 73 ++++++++++++++++--- .../helpers/flipper_i32hex_file.c | 9 ++- .../lib/driver/avr_isp_prog_cmd.h | 15 ++-- 5 files changed, 90 insertions(+), 26 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index aaf5eaf429b..d8b610e9b3b 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -117,10 +117,10 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { furi_assert(instance); AvrIspSpiSwSpeed spi_speed[] = { - //AvrIspSpiSwSpeed1Mhz, - // AvrIspSpiSwSpeed400Khz, - // AvrIspSpiSwSpeed250Khz, - // AvrIspSpiSwSpeed125Khz, + AvrIspSpiSwSpeed1Mhz, + AvrIspSpiSwSpeed400Khz, + AvrIspSpiSwSpeed250Khz, + AvrIspSpiSwSpeed125Khz, AvrIspSpiSwSpeed40Khz, AvrIspSpiSwSpeed20Khz, }; @@ -468,3 +468,10 @@ bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { } return ret; } + +void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr) { + furi_assert(instance); + + avr_isp_spi_transaction(instance, AVR_ISP_EXTENDED_ADDR(extended_addr)); + furi_delay_ms(10); +} \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.h b/applications/external/avr_isp_programmer/helpers/avr_isp.h index bb029f6ada3..476fc3d6427 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.h +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.h @@ -65,4 +65,6 @@ bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse); uint8_t avr_isp_read_fuse_extended(AvrIsp* instance); -bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse); \ No newline at end of file +bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse); + +void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr); \ No newline at end of file diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 217edb0f1d7..5380aa2d3c0 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -317,24 +317,33 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha file_path, avr_isp_chip_arr[instance->chip_arr_ind].flashoffset); uint8_t data[272] = {0}; + bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); + uint8_t extended_addr = 0; - for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; + for(int32_t i = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { + if(send_extended_addr) { + if(extended_addr == ((i >> 16) & 0xFF)) { + avr_isp_write_extended_addr(instance->avr_isp, extended_addr); + extended_addr = ((i >> 16) & 0xFF) + 1; + } + } avr_isp_read_page( instance->avr_isp, STK_SET_FLASH_TYPE, - i, + (uint16_t)i, avr_isp_chip_arr[instance->chip_arr_ind].pagesize, data, sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data( flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); - FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); flipper_i32hex_file_close(flipper_hex_flash); instance->progress_flash = 1.0f; } @@ -354,9 +363,11 @@ static void avr_isp_worker_rw_get_dump_eeprom(AvrIspWorkerRW* instance, const ch if(size_data > avr_isp_chip_arr[instance->chip_arr_ind].eepromsize) size_data = avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; - for(uint16_t i = 0; i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; i += size_data) { + for(int32_t i = avr_isp_chip_arr[instance->chip_arr_ind].eepromoffset; + i < avr_isp_chip_arr[instance->chip_arr_ind].eepromsize; + i += size_data) { avr_isp_read_page( - instance->avr_isp, STK_SET_EEPROM_TYPE, i, size_data, data, sizeof(data)); + instance->avr_isp, STK_SET_EEPROM_TYPE, (uint16_t)i, size_data, data, sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data(flipper_hex_eeprom, data, size_data); FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_eeprom)); instance->progress_eeprom = @@ -510,6 +521,8 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const uint8_t data_read_hex[272] = {0}; uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); + uint8_t extended_addr = 0; FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data( flipper_hex_flash, data_read_hex, sizeof(data_read_hex)); @@ -519,17 +532,35 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const ret) { switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: + + if(send_extended_addr) { + if(extended_addr == ((addr >> 16) & 0xFF)) { + avr_isp_write_extended_addr(instance->avr_isp, extended_addr); + extended_addr = ((addr >> 16) & 0xFF) + 1; + } + } + avr_isp_read_page( instance->avr_isp, STK_SET_FLASH_TYPE, - addr, + (uint16_t)addr, flipper_hex_ret.data_size, data_read_flash, sizeof(data_read_flash)); if(memcmp(data_read_hex, data_read_flash, flipper_hex_ret.data_size) != 0) { ret = false; + FURI_LOG_E(TAG, "Verification flash error"); + FURI_LOG_E(TAG, "Addr: 0x%04lX", addr); + for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { + FURI_LOG_RAW_E("%02X ", data_read_hex[i]); + } + FURI_LOG_RAW_E("\r\n"); + for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { + FURI_LOG_RAW_E("%02X ", data_read_flash[i]); + } + FURI_LOG_RAW_E("\r\n"); } addr += flipper_hex_ret.data_size / 2; @@ -584,7 +615,7 @@ static bool avr_isp_read_page( instance->avr_isp, STK_SET_EEPROM_TYPE, - addr, + (uint16_t)addr, flipper_hex_ret.data_size, data_read_eeprom, sizeof(data_read_eeprom)); @@ -592,6 +623,15 @@ static bool if(memcmp(data_read_hex, data_read_eeprom, flipper_hex_ret.data_size) != 0) { ret = false; FURI_LOG_E(TAG, "Verification eeprom error"); + FURI_LOG_E(TAG, "Addr: 0x%04lX", addr); + for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { + FURI_LOG_RAW_E("%02X ", data_read_hex[i]); + } + FURI_LOG_RAW_E("\r\n"); + for(uint32_t i = 0; i < flipper_hex_ret.data_size; i++) { + FURI_LOG_RAW_E("%02X ", data_read_eeprom[i]); + } + FURI_LOG_RAW_E("\r\n"); } addr += flipper_hex_ret.data_size; @@ -682,6 +722,9 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* FlipperI32HexFile* flipper_hex_flash = flipper_i32hex_file_open_read(file_path); uint32_t addr = avr_isp_chip_arr[instance->chip_arr_ind].flashoffset; + bool send_extended_addr = ((avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2) > 0x10000); + uint8_t extended_addr = 0; + FlipperI32HexFileRet flipper_hex_ret = flipper_i32hex_file_i32hex_to_bin_get_data(flipper_hex_flash, data, sizeof(data)); @@ -689,11 +732,19 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* (flipper_hex_ret.status == FlipperI32HexFileStatusUdateAddr)) { switch(flipper_hex_ret.status) { case FlipperI32HexFileStatusData: + + if(send_extended_addr) { + if(extended_addr == ((addr >> 16) & 0xFF)) { + avr_isp_write_extended_addr(instance->avr_isp, extended_addr); + extended_addr = ((addr >> 16) & 0xFF) + 1; + } + } + if(!avr_isp_write_page( instance->avr_isp, STK_SET_FLASH_TYPE, avr_isp_chip_arr[instance->chip_arr_ind].flashsize, - addr, + (uint16_t)addr, avr_isp_chip_arr[instance->chip_arr_ind].pagesize, data, flipper_hex_ret.data_size)) { @@ -744,7 +795,7 @@ static void avr_isp_worker_rw_write_eeprom(AvrIspWorkerRW* instance, const char* instance->avr_isp, STK_SET_EEPROM_TYPE, avr_isp_chip_arr[instance->chip_arr_ind].eepromsize, - addr, + (uint16_t)addr, avr_isp_chip_arr[instance->chip_arr_ind].eeprompagesize, data, flipper_hex_ret.data_size)) { @@ -915,7 +966,7 @@ bool avr_isp_worker_rw_write_dump( file_path_name, "%s/%s", file_path, furi_string_get_cstr(temp_str_2)); avr_isp_worker_rw_write_eeprom(instance, furi_string_get_cstr(file_path_name)); } - ret = true; + ret = true; avr_isp_end_pmode(instance->avr_isp); } while(false); } diff --git a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c index 5584a977e69..a8c20a0bd94 100644 --- a/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c +++ b/applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c @@ -93,11 +93,12 @@ FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data( furi_string_reset(instance->str_data); - if((instance->addr_last & 0xFF0000) > (instance->addr & 0xFF0000)) { + if((instance->addr_last & 0xFF0000) < (instance->addr & 0xFF0000)) { crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF); crc = 0x01 + ~crc; //I32HEX_TYPE_EXT_LINEAR_ADDR - furi_string_cat_printf(instance->str_data, ":02000004%04lX\r\n", (instance->addr >> 16)); + furi_string_cat_printf( + instance->str_data, ":02000004%04lX%02X\r\n", (instance->addr >> 16), crc); instance->addr_last = instance->addr; } @@ -247,8 +248,8 @@ static FlipperI32HexFileRet flipper_i32hex_file_parse( break; case I32HEX_TYPE_EXT_LINEAR_ADDR: if(flipper_i32hex_file_check_data(data, ret.data_size)) { - data[0] = data[1]; - data[1] = data[2]; + data[0] = data[4]; + data[1] = data[5]; data[3] = 0; data[4] = 0; ret.status = FlipperI32HexFileStatusUdateAddr; diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h index bc8ccb9a3be..f8b07203e66 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h @@ -13,18 +13,22 @@ #define AVR_ISP_READ_VENDOR 0x30, 0x00, 0x00, 0x00 #define AVR_ISP_READ_PART_FAMILY 0x30, 0x00, 0x01, 0x00 #define AVR_ISP_READ_PART_NUMBER 0x30, 0x00, 0x02, 0x00 -#define AVR_ISP_ERASE_CHIP 0xAC, 0x80, 0x00, 0x00 //Erase Chip, Wait N ms, Release RESET to end the erase. +#define AVR_ISP_ERASE_CHIP \ + 0xAC, 0x80, 0x00, 0x00 //Erase Chip, Wait N ms, Release RESET to end the erase. //The only way to end a Chip Erase cycle is by temporarily releasing the Reset line +#define AVR_ISP_EXTENDED_ADDR(data) 0x4D, 0x00, data, 0x00 #define AVR_ISP_WRITE_FLASH_LO(add, data) 0x40, (add >> 8) & 0xFF, add & 0xFF, data #define AVR_ISP_WRITE_FLASH_HI(add, data) 0x48, (add >> 8) & 0xFF, add & 0xFF, data #define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00 #define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00 -#define AVR_ISP_WRITE_EEPROM(add, data) 0xC0, (add >> 8) & 0xFF, add & 0xFF, data //Send cmd, Wait N ms +#define AVR_ISP_WRITE_EEPROM(add, data) \ + 0xC0, (add >> 8) & 0xFF, add & 0xFF, data //Send cmd, Wait N ms #define AVR_ISP_READ_EEPROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF -#define AVR_ISP_COMMIT(add) 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 //Send cmd, polling read last addr page +#define AVR_ISP_COMMIT(add) \ + 0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 //Send cmd, polling read last addr page #define AVR_ISP_OSCCAL(add) 0x38, 0x00, add, 0x00 @@ -33,11 +37,10 @@ #define AVR_ISP_WRITE_FUSE_LOW(data) 0xAC, 0xA0, 0x00, data //Send cmd, Wait N ms #define AVR_ISP_READ_FUSE_LOW 0x50, 0x00, 0x00, 0x00 #define AVR_ISP_WRITE_FUSE_HIGH(data) 0xAC, 0xA8, 0x00, data //Send cmd, Wait N ms -#define AVR_ISP_READ_FUSE_HIGH 0x58, 0x08, 0x00, 0x00 -#define AVR_ISP_WRITE_FUSE_EXTENDED(data) 0xAC, 0xA4, 0x00, data //Send cmd, Wait N ms (~write) +#define AVR_ISP_READ_FUSE_HIGH 0x58, 0x08, 0x00, 0x00 +#define AVR_ISP_WRITE_FUSE_EXTENDED(data) 0xAC, 0xA4, 0x00, data //Send cmd, Wait N ms (~write) #define AVR_ISP_READ_FUSE_EXTENDED 0x50, 0x08, 0x00, 0x00 - #define AVR_ISP_EECHUNK 0x20 // https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf From 5f63fa0339cfb06091737b94240ca23af764b1ad Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 21:34:01 +0400 Subject: [PATCH 45/50] AVR_ISP: fix auto set speed spi --- .../avr_isp_programmer/helpers/avr_isp.c | 17 +++++++++++++++-- .../helpers/avr_isp_worker_rw.c | 6 +++--- .../lib/driver/avr_isp_prog.c | 19 ++++++++++++++++--- .../lib/driver/avr_isp_spi_sw.h | 4 ++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index d8b610e9b3b..826dc694bb3 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -121,22 +121,35 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { AvrIspSpiSwSpeed400Khz, AvrIspSpiSwSpeed250Khz, AvrIspSpiSwSpeed125Khz, + AvrIspSpiSwSpeed60Khz, AvrIspSpiSwSpeed40Khz, AvrIspSpiSwSpeed20Khz, + AvrIspSpiSwSpeed10Khz, + AvrIspSpiSwSpeed5Khz, + AvrIspSpiSwSpeed1Khz, }; for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_start_pmode(instance, spi_speed[i])) { AvrIspSignature sig = avr_isp_read_signature(instance); AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V654 uint8_t y = 0; - while(y < 16) { + while(y < 8) { if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) != 0) break; sig_examination = avr_isp_read_signature(instance); y++; } - if(y == 16) return true; + if(y == 8) { + if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { + if(i < COUNT_OF(spi_speed)) { + avr_isp_end_pmode(instance); + i++; + return avr_isp_start_pmode(instance, spi_speed[i]); + } + } + return true; + } } } return false; diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index 5380aa2d3c0..f586e164529 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -324,7 +324,7 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha i < avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2; i += avr_isp_chip_arr[instance->chip_arr_ind].pagesize / 2) { if(send_extended_addr) { - if(extended_addr == ((i >> 16) & 0xFF)) { + if(extended_addr <= ((i >> 16) & 0xFF)) { avr_isp_write_extended_addr(instance->avr_isp, extended_addr); extended_addr = ((i >> 16) & 0xFF) + 1; } @@ -534,7 +534,7 @@ static bool avr_isp_worker_rw_verification_flash(AvrIspWorkerRW* instance, const case FlipperI32HexFileStatusData: if(send_extended_addr) { - if(extended_addr == ((addr >> 16) & 0xFF)) { + if(extended_addr <= ((addr >> 16) & 0xFF)) { avr_isp_write_extended_addr(instance->avr_isp, extended_addr); extended_addr = ((addr >> 16) & 0xFF) + 1; } @@ -734,7 +734,7 @@ static void avr_isp_worker_rw_write_flash(AvrIspWorkerRW* instance, const char* case FlipperI32HexFileStatusData: if(send_extended_addr) { - if(extended_addr == ((addr >> 16) & 0xFF)) { + if(extended_addr <= ((addr >> 16) & 0xFF)) { avr_isp_write_extended_addr(instance->avr_isp, extended_addr); extended_addr = ((addr >> 16) & 0xFF) + 1; } diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index e61505790f0..276427850cb 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -285,23 +285,36 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { AvrIspSpiSwSpeed400Khz, AvrIspSpiSwSpeed250Khz, AvrIspSpiSwSpeed125Khz, + AvrIspSpiSwSpeed60Khz, AvrIspSpiSwSpeed40Khz, AvrIspSpiSwSpeed20Khz, + AvrIspSpiSwSpeed10Khz, + AvrIspSpiSwSpeed5Khz, + AvrIspSpiSwSpeed1Khz, }; for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { AvrIspProgSignature sig = avr_isp_prog_check_signature(instance); AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V654 uint8_t y = 0; - while(y < 16) { + while(y < 8) { if(memcmp( (uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspProgSignature)) != 0) break; - sig_examination = avr_isp_prog_check_signature(instance); + sig_examination = avr_isp_prog_check_signature(instance); y++; } - if(y == 16) return true; + if(y == 8) { + if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { + if(i < COUNT_OF(spi_speed)) { + avr_isp_prog_end_pmode(instance); + i++; + return avr_isp_prog_start_pmode(instance, spi_speed[i]); + } + } + return true; + } } } return false; diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h index c65e851b191..44de5ff79cb 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h @@ -7,8 +7,12 @@ typedef enum { AvrIspSpiSwSpeed400Khz = 1, AvrIspSpiSwSpeed250Khz = 2, AvrIspSpiSwSpeed125Khz = 4, + AvrIspSpiSwSpeed60Khz = 8, AvrIspSpiSwSpeed40Khz = 12, AvrIspSpiSwSpeed20Khz = 24, + AvrIspSpiSwSpeed10Khz = 48, + AvrIspSpiSwSpeed5Khz = 96, + AvrIspSpiSwSpeed1Khz = 480, } AvrIspSpiSwSpeed; typedef struct AvrIspSpiSw AvrIspSpiSw; From 1eaf629af2cd9dd013558b9989e70db06cb4cab2 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 22:20:03 +0400 Subject: [PATCH 46/50] AVR_ISP: fix gui --- .../avr_isp_programmer/helpers/avr_isp.c | 4 +-- .../lib/driver/avr_isp_prog.c | 4 +-- .../views/avr_isp_view_reader.c | 2 +- .../views/avr_isp_view_writer.c | 31 +++++++++++++++---- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 826dc694bb3..76e0a80b061 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -131,7 +131,7 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_start_pmode(instance, spi_speed[i])) { AvrIspSignature sig = avr_isp_read_signature(instance); - AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V654 + AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V656 uint8_t y = 0; while(y < 8) { if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) != @@ -142,7 +142,7 @@ bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) { } if(y == 8) { if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { - if(i < COUNT_OF(spi_speed)) { + if(i < (COUNT_OF(spi_speed) - 1)) { avr_isp_end_pmode(instance); i++; return avr_isp_start_pmode(instance, spi_speed[i]); diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index 276427850cb..b457e4c27b7 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -295,7 +295,7 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) { if(avr_isp_prog_start_pmode(instance, spi_speed[i])) { AvrIspProgSignature sig = avr_isp_prog_check_signature(instance); - AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V654 + AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V656 uint8_t y = 0; while(y < 8) { if(memcmp( @@ -307,7 +307,7 @@ static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) { } if(y == 8) { if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) { - if(i < COUNT_OF(spi_speed)) { + if(i < (COUNT_OF(spi_speed) - 1)) { avr_isp_prog_end_pmode(instance); i++; return avr_isp_prog_start_pmode(instance, spi_speed[i]); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c index 7beeacfcdfb..92d15bd7f8b 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.c @@ -64,7 +64,7 @@ void avr_isp_reader_view_draw(Canvas* canvas, AvrIspReaderViewModel* model) { elements_button_center(canvas, "Start"); break; case AvrIspReaderViewStatusReading: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reding dump"); + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Reading dump"); break; case AvrIspReaderViewStatusVerification: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifyng dump"); diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index bdc9ee392ff..516796838b8 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -54,26 +54,45 @@ void avr_isp_writer_set_file_path( void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_clear(canvas); - char str_buf[64] = {0}; + char str_flash[32] = {0}; + char str_eeprom[32] = {0}; canvas_set_font(canvas, FontPrimary); + switch(model->status) { case AvrIspWriterViewStatusIDLE: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to write"); canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Start"); + snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); + snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); break; case AvrIspWriterViewStatusWriting: - canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); + if(model->progress_flash == 0) { + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying firmware"); + snprintf(str_flash, sizeof(str_flash), "***"); + snprintf(str_eeprom, sizeof(str_eeprom), "***"); + } else { + canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing dump"); + snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); + snprintf( + str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); + } break; case AvrIspWriterViewStatusVerification: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying dump"); + snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); + snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); break; case AvrIspWriterViewStatusWritingFuse: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Writing fuse"); + snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); + snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); break; case AvrIspWriterViewStatusWritingFuseOk: canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Done!"); + snprintf(str_flash, sizeof(str_flash), "%d%%", (uint8_t)(model->progress_flash * 100)); + snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); canvas_set_font(canvas, FontSecondary); elements_button_center(canvas, "Reflash"); elements_button_right(canvas, "Exit"); @@ -85,11 +104,11 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 0, 27, "Flash"); - snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); - elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_buf); + // snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_flash * 100)); + elements_progress_bar_with_text(canvas, 44, 17, 84, model->progress_flash, str_flash); canvas_draw_str(canvas, 0, 43, "EEPROM"); - snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); - elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_buf); + // snprintf(str_buf, sizeof(str_buf), "%d%%", (uint8_t)(model->progress_eeprom * 100)); + elements_progress_bar_with_text(canvas, 44, 34, 84, model->progress_eeprom, str_eeprom); } bool avr_isp_writer_view_input(InputEvent* event, void* context) { From d6883fc5df3c133f524e8c2b516c813360848823 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 28 Mar 2023 23:54:20 +0400 Subject: [PATCH 47/50] AVR_ISP: fix PVS --- .../external/avr_isp_programmer/views/avr_isp_view_writer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index 516796838b8..d0d80753d7c 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -68,7 +68,7 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); break; case AvrIspWriterViewStatusWriting: - if(model->progress_flash == 0) { + if(model->progress_flash == 0.0f) { canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying firmware"); snprintf(str_flash, sizeof(str_flash), "***"); snprintf(str_eeprom, sizeof(str_eeprom), "***"); From 25f9b70b3e32bda2649da2494bba49b66b8f5f31 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 29 Mar 2023 10:20:52 +0400 Subject: [PATCH 48/50] AVR_ISP: fix PVS --- .../external/avr_isp_programmer/views/avr_isp_view_writer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c index d0d80753d7c..a06b7853555 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.c @@ -2,6 +2,7 @@ #include #include "../helpers/avr_isp_worker_rw.h" +#include struct AvrIspWriterView { View* view; @@ -68,7 +69,7 @@ void avr_isp_writer_view_draw(Canvas* canvas, AvrIspWriterViewModel* model) { snprintf(str_eeprom, sizeof(str_eeprom), "%d%%", (uint8_t)(model->progress_eeprom * 100)); break; case AvrIspWriterViewStatusWriting: - if(model->progress_flash == 0.0f) { + if(float_is_equal(model->progress_flash, 0.f)) { canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Verifying firmware"); snprintf(str_flash, sizeof(str_flash), "***"); snprintf(str_eeprom, sizeof(str_eeprom), "***"); From f327db72214227b31d37280bcf665babe6e97915 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 4 Apr 2023 17:47:53 +0400 Subject: [PATCH 49/50] ISP: switching on +5 volts to an external comb --- .../external/avr_isp_programmer/avr_isp_app.c | 12 ++++++++++++ .../avr_isp_programmer/helpers/avr_isp_worker_rw.c | 4 ++-- .../avr_isp_programmer/views/avr_isp_view_reader.h | 2 +- .../avr_isp_programmer/views/avr_isp_view_writer.h | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/applications/external/avr_isp_programmer/avr_isp_app.c b/applications/external/avr_isp_programmer/avr_isp_app.c index e582834c6a7..740dc3610a6 100644 --- a/applications/external/avr_isp_programmer/avr_isp_app.c +++ b/applications/external/avr_isp_programmer/avr_isp_app.c @@ -95,6 +95,13 @@ AvrIspApp* avr_isp_app_alloc() { AvrIspViewChipDetect, avr_isp_chip_detect_view_get_view(app->avr_isp_chip_detect_view)); + // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering + uint8_t attempts = 0; + while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + furi_hal_power_enable_otg(); + furi_delay_ms(10); + } + scene_manager_next_scene(app->scene_manager, AvrIspSceneStart); return app; @@ -103,6 +110,11 @@ AvrIspApp* avr_isp_app_alloc() { void avr_isp_app_free(AvrIspApp* app) { furi_assert(app); + // Disable 5v power + if(furi_hal_power_is_otg_enabled()) { + furi_hal_power_disable_otg(); + } + // Submenu view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu); submenu_free(app->submenu); diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c index f586e164529..fc8d3b09fe0 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c @@ -338,12 +338,12 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha sizeof(data)); flipper_i32hex_file_bin_to_i32hex_set_data( flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); instance->progress_flash = (float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f); } flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash); - //FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); + FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash)); flipper_i32hex_file_close(flipper_hex_flash); instance->progress_flash = 1.0f; } diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h index 94856fb26dc..44a43994815 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_reader.h @@ -20,7 +20,7 @@ void avr_isp_reader_set_file_path( AvrIspReaderView* instance, const char* file_path, const char* file_name); - + void avr_isp_reader_view_set_callback( AvrIspReaderView* instance, AvrIspReaderViewCallback callback, diff --git a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h index a2a3b7b85ca..1ff72838765 100644 --- a/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h +++ b/applications/external/avr_isp_programmer/views/avr_isp_view_writer.h @@ -22,7 +22,7 @@ void avr_isp_writer_set_file_path( AvrIspWriterView* instance, const char* file_path, const char* file_name); - + void avr_isp_writer_view_set_callback( AvrIspWriterView* instance, AvrIspWriterViewCallback callback, From 88349824270bd874bef5aa18bed15b57871ac7b7 Mon Sep 17 00:00:00 2001 From: SkorP Date: Tue, 4 Apr 2023 17:52:13 +0400 Subject: [PATCH 50/50] ISP: fix syntax --- .../avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c index 7bb0055af1d..79c23939074 100644 --- a/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c +++ b/applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c @@ -24,7 +24,7 @@ void avr_isp_scene_chip_detect_on_enter(void* context) { break; default: - avr_isp_chip_detect_set_state( + avr_isp_chip_detect_set_state( app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateNoDetect); break; }