[AVR_ISP]: add AVR ISP Programmer FAP (#2475)
* [AVR_ISP]: add AVR ISP Programmer FAP * [AVR_ISP]: add auto detect AVR chip * [AVR_ISP]: fix auto detect chip * [AVR_ISP]: fix fast write flash * AVR_ISP: auto set SPI speed * AVR_ISP: add clock 4Mhz on &gpio_ext_pa4 * AVR_ISP: fix "[CRASH][ISR 4] NULL pointer dereference" with no AVR chip connected * AVR_ISP: add AVR ISP Reader * AVR_ISP: add read and check I32HEX file * AVR_ISP: add write eerom, flash, fuse, lock byte * AVR_ISP: add gui Reader, Writer * Github: unshallow on decontamination * AVR_ISP: move to external * API: fix api_symbols * AVR_ISP: add wiring scene * GUI: model mutex FuriMutexTypeNormal -> FuriMutexTypeRecursive * AVR_ISP: add chip_detect view * AVR_ISP: refactoring gui ISP Programmer * AVR_ISP: add gui "Dump AVR" * AVR_ISP: add gui "Flash AVR" * AVR_ISP: fix navigation gui * GUI: model mutex FuriMutexTypeRecursive -> FuriMutexTypeNormal * AVR_ISP: fix conflicts * AVR_ISP: fix build * AVR_ISP: delete images * AVR_ISP: add images * AVR_ISP: fix gui * AVR_ISP: fix stuck in navigation * AVR_ISP: changing the Fuse bit recording logic * AVR_ISP: fix read/write chips with memory greater than 64Kb * AVR_ISP: fix auto set speed SPI * AVR_ISP: fix gui * ISP: switching on +5 volts to an external GPIO Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
213
applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c
vendored
Normal file
213
applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.c
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
#include "avr_isp_view_chip_detect.h"
|
||||
#include <avr_isp_icons.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "../helpers/avr_isp_worker_rw.h"
|
||||
|
||||
struct AvrIspChipDetectView {
|
||||
View* view;
|
||||
AvrIspWorkerRW* avr_isp_worker_rw;
|
||||
AvrIspChipDetectViewCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16_t idx;
|
||||
const char* name_chip;
|
||||
uint32_t flash_size;
|
||||
AvrIspChipDetectViewState state;
|
||||
} 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_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state) {
|
||||
furi_assert(instance);
|
||||
|
||||
with_view_model(
|
||||
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->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);
|
||||
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 AvrIspChipDetectViewStateErrorOccured:
|
||||
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 AvrIspChipDetectViewStateErrorVerification:
|
||||
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:
|
||||
//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);
|
||||
|
||||
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->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;
|
||||
}
|
||||
|
||||
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->state = AvrIspChipDetectViewStateDetected;
|
||||
} else {
|
||||
model->state = AvrIspChipDetectViewStateNoDetect;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
void avr_isp_chip_detect_view_enter(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspChipDetectView* instance = context;
|
||||
bool detect_chip = false;
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspChipDetectViewModel * model,
|
||||
{
|
||||
if(model->state == AvrIspChipDetectViewStateNoDetect ||
|
||||
model->state == AvrIspChipDetectViewStateDetected) {
|
||||
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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspChipDetectView* instance = context;
|
||||
|
||||
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() {
|
||||
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->state = AvrIspChipDetectViewStateNoDetect; },
|
||||
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;
|
||||
}
|
32
applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h
vendored
Normal file
32
applications/external/avr_isp_programmer/views/avr_isp_view_chip_detect.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#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 {
|
||||
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_state(AvrIspChipDetectView* instance, AvrIspChipDetectViewState state);
|
||||
|
||||
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);
|
134
applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c
vendored
Normal file
134
applications/external/avr_isp_programmer/views/avr_isp_view_programmer.c
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "avr_isp_view_programmer.h"
|
||||
#include <avr_isp_icons.h>
|
||||
|
||||
#include "../helpers/avr_isp_worker.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
struct AvrIspProgrammerView {
|
||||
View* view;
|
||||
AvrIspWorker* worker;
|
||||
AvrIspProgrammerViewCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
AvrIspProgrammerViewStatus status;
|
||||
} AvrIspProgrammerViewModel;
|
||||
|
||||
void avr_isp_programmer_view_set_callback(
|
||||
AvrIspProgrammerView* instance,
|
||||
AvrIspProgrammerViewCallback 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);
|
||||
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);
|
||||
elements_multiline_text(canvas, 0, 25, "Waiting for\nsoftware\nconnection");
|
||||
}
|
||||
}
|
||||
|
||||
bool avr_isp_programmer_view_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
UNUSED(context);
|
||||
|
||||
if(event->key == InputKeyBack || event->type != InputTypeShort) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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,
|
||||
{
|
||||
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;
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspProgrammerViewModel * model,
|
||||
{ model->status = AvrIspProgrammerViewStatusNoUSBConnect; },
|
||||
true);
|
||||
|
||||
//Start worker
|
||||
instance->worker = avr_isp_worker_alloc(instance->context);
|
||||
|
||||
avr_isp_worker_set_callback(
|
||||
instance->worker, avr_isp_programmer_usb_connect_callback, instance);
|
||||
|
||||
avr_isp_worker_start(instance->worker);
|
||||
}
|
||||
|
||||
void avr_isp_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_set_callback(instance->worker, NULL, NULL);
|
||||
avr_isp_worker_free(instance->worker);
|
||||
}
|
||||
|
||||
AvrIspProgrammerView* avr_isp_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_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,
|
||||
AvrIspProgrammerViewModel * model,
|
||||
{ model->status = AvrIspProgrammerViewStatusNoUSBConnect; },
|
||||
false);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void avr_isp_programmer_view_free(AvrIspProgrammerView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->view;
|
||||
}
|
27
applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h
vendored
Normal file
27
applications/external/avr_isp_programmer/views/avr_isp_view_programmer.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/avr_isp_types.h"
|
||||
#include "../helpers/avr_isp_event.h"
|
||||
|
||||
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,
|
||||
void* context);
|
||||
|
||||
AvrIspProgrammerView* avr_isp_programmer_view_alloc();
|
||||
|
||||
void avr_isp_programmer_view_free(AvrIspProgrammerView* instance);
|
||||
|
||||
View* avr_isp_programmer_view_get_view(AvrIspProgrammerView* instance);
|
||||
|
||||
void avr_isp_programmer_view_exit(void* context);
|
215
applications/external/avr_isp_programmer/views/avr_isp_view_reader.c
vendored
Normal file
215
applications/external/avr_isp_programmer/views/avr_isp_view_reader.c
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
#include "avr_isp_view_reader.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "../helpers/avr_isp_worker_rw.h"
|
||||
|
||||
struct AvrIspReaderView {
|
||||
View* view;
|
||||
AvrIspWorkerRW* avr_isp_worker_rw;
|
||||
const char* file_path;
|
||||
const char* file_name;
|
||||
AvrIspReaderViewCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
AvrIspReaderViewStatus status;
|
||||
float progress_flash;
|
||||
float progress_eeprom;
|
||||
} 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,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
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) {
|
||||
canvas_clear(canvas);
|
||||
char str_buf[64] = {0};
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
switch(model->status) {
|
||||
case AvrIspReaderViewStatusIDLE:
|
||||
canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "Press start to dump");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_center(canvas, "Start");
|
||||
break;
|
||||
case AvrIspReaderViewStatusReading:
|
||||
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");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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) {
|
||||
furi_assert(context);
|
||||
AvrIspReaderView* instance = context;
|
||||
|
||||
bool ret = true;
|
||||
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;
|
||||
}
|
||||
},
|
||||
false);
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspReaderViewModel * model,
|
||||
{
|
||||
if(model->status == AvrIspReaderViewStatusIDLE) {
|
||||
model->status = AvrIspReaderViewStatusReading;
|
||||
avr_isp_worker_rw_read_dump_start(
|
||||
instance->avr_isp_worker_rw, instance->file_path, instance->file_name);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
model->status = AvrIspReaderViewStatusVerification;
|
||||
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;
|
||||
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspReaderViewModel * model,
|
||||
{
|
||||
model->status = AvrIspReaderViewStatusIDLE;
|
||||
model->progress_flash = 0.0f;
|
||||
model->progress_eeprom = 0.0f;
|
||||
},
|
||||
true);
|
||||
|
||||
//Start avr_isp_worker_rw
|
||||
instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context);
|
||||
|
||||
avr_isp_worker_rw_set_callback_status(
|
||||
instance->avr_isp_worker_rw, avr_isp_reader_callback_status, instance);
|
||||
|
||||
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_worker_rw
|
||||
if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) {
|
||||
avr_isp_worker_rw_stop(instance->avr_isp_worker_rw);
|
||||
}
|
||||
|
||||
avr_isp_worker_rw_free(instance->avr_isp_worker_rw);
|
||||
}
|
||||
|
||||
AvrIspReaderView* avr_isp_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_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);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void avr_isp_reader_view_free(AvrIspReaderView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* avr_isp_reader_view_get_view(AvrIspReaderView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->view;
|
||||
}
|
35
applications/external/avr_isp_programmer/views/avr_isp_view_reader.h
vendored
Normal file
35
applications/external/avr_isp_programmer/views/avr_isp_view_reader.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/avr_isp_types.h"
|
||||
#include "../helpers/avr_isp_event.h"
|
||||
|
||||
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,
|
||||
const char* file_name);
|
||||
|
||||
void avr_isp_reader_view_set_callback(
|
||||
AvrIspReaderView* instance,
|
||||
AvrIspReaderViewCallback callback,
|
||||
void* context);
|
||||
|
||||
AvrIspReaderView* avr_isp_reader_view_alloc();
|
||||
|
||||
void avr_isp_reader_view_free(AvrIspReaderView* instance);
|
||||
|
||||
View* avr_isp_reader_view_get_view(AvrIspReaderView* instance);
|
||||
|
||||
void avr_isp_reader_view_exit(void* context);
|
268
applications/external/avr_isp_programmer/views/avr_isp_view_writer.c
vendored
Normal file
268
applications/external/avr_isp_programmer/views/avr_isp_view_writer.c
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "avr_isp_view_writer.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "../helpers/avr_isp_worker_rw.h"
|
||||
#include <float_tools.h>
|
||||
|
||||
struct AvrIspWriterView {
|
||||
View* view;
|
||||
AvrIspWorkerRW* avr_isp_worker_rw;
|
||||
const char* file_path;
|
||||
const char* file_name;
|
||||
AvrIspWriterViewCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
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,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = 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) {
|
||||
canvas_clear(canvas);
|
||||
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:
|
||||
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), "***");
|
||||
} 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");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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_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_eeprom);
|
||||
}
|
||||
|
||||
bool avr_isp_writer_view_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
AvrIspWriterView* instance = context;
|
||||
|
||||
bool ret = true;
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspWriterViewModel * model,
|
||||
{
|
||||
if((model->status == AvrIspWriterViewStatusIDLE) ||
|
||||
(model->status == AvrIspWriterViewStatusWritingFuseOk)) {
|
||||
if(instance->callback)
|
||||
instance->callback(AvrIspCustomEventSceneExit, instance->context);
|
||||
ret = false;
|
||||
}
|
||||
},
|
||||
false);
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspWriterViewModel * model,
|
||||
{
|
||||
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);
|
||||
}
|
||||
},
|
||||
false);
|
||||
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspWriterViewModel * model,
|
||||
{
|
||||
if((model->status == AvrIspWriterViewStatusIDLE) ||
|
||||
(model->status == AvrIspWriterViewStatusWritingFuseOk)) {
|
||||
if(instance->callback)
|
||||
instance->callback(AvrIspCustomEventSceneExitStartMenu, instance->context);
|
||||
ret = false;
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
model->status = AvrIspWriterViewStatusVerification;
|
||||
break;
|
||||
case AvrIspWorkerRWStatusErrorVerification:
|
||||
if(instance->callback)
|
||||
instance->callback(AvrIspCustomEventSceneErrorVerification, instance->context);
|
||||
break;
|
||||
case AvrIspWorkerRWStatusEndVerification:
|
||||
avr_isp_worker_rw_write_fuse_start(
|
||||
instance->avr_isp_worker_rw, instance->file_path, instance->file_name);
|
||||
model->status = AvrIspWriterViewStatusWritingFuse;
|
||||
break;
|
||||
case AvrIspWorkerRWStatusErrorWritingFuse:
|
||||
if(instance->callback)
|
||||
instance->callback(AvrIspCustomEventSceneErrorWritingFuse, instance->context);
|
||||
break;
|
||||
case AvrIspWorkerRWStatusEndWritingFuse:
|
||||
model->status = AvrIspWriterViewStatusWritingFuseOk;
|
||||
break;
|
||||
|
||||
default:
|
||||
//AvrIspWorkerRWStatusErrorWriting;
|
||||
if(instance->callback)
|
||||
instance->callback(AvrIspCustomEventSceneErrorWriting, instance->context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void avr_isp_writer_view_enter(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspWriterView* instance = context;
|
||||
with_view_model(
|
||||
instance->view,
|
||||
AvrIspWriterViewModel * model,
|
||||
{
|
||||
model->status = AvrIspWriterViewStatusIDLE;
|
||||
model->progress_flash = 0.0f;
|
||||
model->progress_eeprom = 0.0f;
|
||||
},
|
||||
true);
|
||||
|
||||
//Start avr_isp_worker_rw
|
||||
instance->avr_isp_worker_rw = avr_isp_worker_rw_alloc(instance->context);
|
||||
|
||||
avr_isp_worker_rw_set_callback_status(
|
||||
instance->avr_isp_worker_rw, avr_isp_writer_callback_status, instance);
|
||||
|
||||
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_worker_rw
|
||||
if(avr_isp_worker_rw_is_running(instance->avr_isp_worker_rw)) {
|
||||
avr_isp_worker_rw_stop(instance->avr_isp_worker_rw);
|
||||
}
|
||||
|
||||
avr_isp_worker_rw_free(instance->avr_isp_worker_rw);
|
||||
}
|
||||
|
||||
AvrIspWriterView* avr_isp_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_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);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void avr_isp_writer_view_free(AvrIspWriterView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* avr_isp_writer_view_get_view(AvrIspWriterView* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->view;
|
||||
}
|
37
applications/external/avr_isp_programmer/views/avr_isp_view_writer.h
vendored
Normal file
37
applications/external/avr_isp_programmer/views/avr_isp_view_writer.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/avr_isp_types.h"
|
||||
#include "../helpers/avr_isp_event.h"
|
||||
|
||||
typedef struct AvrIspWriterView AvrIspWriterView;
|
||||
|
||||
typedef void (*AvrIspWriterViewCallback)(AvrIspCustomEvent event, void* context);
|
||||
|
||||
typedef enum {
|
||||
AvrIspWriterViewStatusIDLE,
|
||||
AvrIspWriterViewStatusWriting,
|
||||
AvrIspWriterViewStatusVerification,
|
||||
AvrIspWriterViewStatusWritingFuse,
|
||||
AvrIspWriterViewStatusWritingFuseOk,
|
||||
} 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,
|
||||
void* context);
|
||||
|
||||
AvrIspWriterView* avr_isp_writer_view_alloc();
|
||||
|
||||
void avr_isp_writer_view_free(AvrIspWriterView* instance);
|
||||
|
||||
View* avr_isp_writer_view_get_view(AvrIspWriterView* instance);
|
||||
|
||||
void avr_isp_writer_view_exit(void* context);
|
Reference in New Issue
Block a user