Merge branch 'dev' into custom-buttons
|
@ -1,4 +1,6 @@
|
|||
### New changes
|
||||
* SubGHz: Support for Allmatic(reads as Beninca), also fix Beninca protocol
|
||||
* SubGHz: Allmatic -> Add Manually
|
||||
* Plugins: Show External CC1101 module status in Weather Station and in POCSAG Pager plugins
|
||||
* Plugins: Update **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) (Fixes BT issues)
|
||||
* SubGHz: Fix false detections of StarLine 72bit, flipper can decode only 64bit
|
||||
|
|
10
ReadMe.md
|
@ -69,9 +69,9 @@ Also check the changelog in releases for latest updates!
|
|||
### Current modified and new Sub-GHz protocols list:
|
||||
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols.
|
||||
|
||||
Encoders/sending made by Eng1n33r & @xMasterX:
|
||||
Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||
|
||||
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||
Encoders or sending made by @xMasterX:
|
||||
- Keeloq: HCS101
|
||||
- Keeloq: AN-Motors
|
||||
- Keeloq: JCM Tech
|
||||
|
@ -81,16 +81,18 @@ Encoders/sending made by Eng1n33r & @xMasterX:
|
|||
- Keeloq: FAAC RC,XT
|
||||
- Keeloq: Mutancode
|
||||
- Keeloq: Normstahl
|
||||
- Keeloq: Beninca
|
||||
- Keeloq: Beninca + Allmatic
|
||||
- Keeloq: Stilmatic / Schellenberg
|
||||
- Keeloq: CAME Space
|
||||
- Keeloq: Aprimatic (model TR and similar)
|
||||
|
||||
Encoders/sending made by @Eng1n33r & @xMasterX:
|
||||
- CAME Atomo
|
||||
- Nice Flor S
|
||||
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- Keeloq: BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)] -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Security+ v1 & v2
|
||||
- Star Line
|
||||
- Security+ v1 & v2
|
||||
|
||||
Encoders made by @assasinfil & @xMasterX:
|
||||
- Somfy Telis
|
||||
|
|
17
applications/external/avr_isp_programmer/application.fam
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
App(
|
||||
appid="avr_isp",
|
||||
name="AVR Flasher",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="avr_isp_app",
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
order=20,
|
||||
fap_icon="avr_app_icon_10x10.png",
|
||||
fap_category="GPIO",
|
||||
fap_icon_assets="images",
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="driver",
|
||||
),
|
||||
],
|
||||
)
|
BIN
applications/external/avr_isp_programmer/avr_app_icon_10x10.png
vendored
Normal file
After Width: | Height: | Size: 3.5 KiB |
167
applications/external/avr_isp_programmer/avr_isp_app.c
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
#include "avr_isp_app_i.h"
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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));
|
||||
|
||||
// Text Input
|
||||
app->text_input = text_input_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);
|
||||
|
||||
// Programmer view
|
||||
app->avr_isp_programmer_view = avr_isp_programmer_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
AvrIspViewProgrammer,
|
||||
avr_isp_programmer_view_get_view(app->avr_isp_programmer_view));
|
||||
|
||||
// Reader view
|
||||
app->avr_isp_reader_view = avr_isp_reader_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
AvrIspViewReader,
|
||||
avr_isp_reader_view_get_view(app->avr_isp_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);
|
||||
|
||||
return app;
|
||||
} //-V773
|
||||
|
||||
void avr_isp_app_free(AvrIspApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu);
|
||||
submenu_free(app->submenu);
|
||||
|
||||
// Widget
|
||||
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);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewPopup);
|
||||
popup_free(app->popup);
|
||||
|
||||
//Dialog
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
|
||||
// Programmer view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer);
|
||||
avr_isp_programmer_view_free(app->avr_isp_programmer_view);
|
||||
|
||||
// Reader view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader);
|
||||
avr_isp_reader_view_free(app->avr_isp_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);
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
app->notifications = NULL;
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
// Path strings
|
||||
furi_string_free(app->file_path);
|
||||
|
||||
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;
|
||||
}
|
31
applications/external/avr_isp_programmer/avr_isp_app_i.c
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "avr_isp_app_i.h"
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#define TAG "AvrIsp"
|
||||
|
||||
bool avr_isp_load_from_file(AvrIspApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
FuriString* file_path = furi_string_alloc();
|
||||
FuriString* file_name = furi_string_alloc();
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
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, file_path, app->file_path, &browser_options);
|
||||
|
||||
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);
|
||||
|
||||
return res;
|
||||
}
|
44
applications/external/avr_isp_programmer/avr_isp_app_i.h
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "helpers/avr_isp_types.h"
|
||||
#include <avr_isp_icons.h>
|
||||
|
||||
#include "scenes/avr_isp_scene.h"
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <storage/storage.h>
|
||||
#include <gui/modules/popup.h>
|
||||
|
||||
#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
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
Popup* popup;
|
||||
Submenu* submenu;
|
||||
Widget* widget;
|
||||
TextInput* text_input;
|
||||
FuriString* file_path;
|
||||
char file_name_tmp[AVR_ISP_MAX_LEN_NAME];
|
||||
AvrIspProgrammerView* avr_isp_programmer_view;
|
||||
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);
|
490
applications/external/avr_isp_programmer/helpers/avr_isp.c
vendored
Normal file
|
@ -0,0 +1,490 @@
|
|||
#include "avr_isp.h"
|
||||
#include "../lib/driver/avr_isp_prog_cmd.h"
|
||||
#include "../lib/driver/avr_isp_spi_sw.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320
|
||||
#define TAG "AvrIsp"
|
||||
|
||||
struct AvrIsp {
|
||||
AvrIspSpiSw* spi;
|
||||
bool pmode;
|
||||
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) {
|
||||
furi_assert(instance);
|
||||
|
||||
AvrIspSpiSwSpeed spi_speed[] = {
|
||||
AvrIspSpiSwSpeed1Mhz,
|
||||
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); //-V656
|
||||
uint8_t y = 0;
|
||||
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 == 8) {
|
||||
if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) {
|
||||
if(i < (COUNT_OF(spi_speed) - 1)) {
|
||||
avr_isp_end_pmode(instance);
|
||||
i++;
|
||||
return avr_isp_start_pmode(instance, spi_speed[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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 page_size,
|
||||
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));
|
||||
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 page_size,
|
||||
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));
|
||||
addr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool avr_isp_read_page(
|
||||
AvrIsp* instance,
|
||||
uint32_t mem_type,
|
||||
uint16_t addr,
|
||||
uint16_t page_size,
|
||||
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);
|
||||
if(mem_type == STK_SET_EEPROM_TYPE)
|
||||
res = avr_isp_eeprom_read_page(instance, addr, page_size, data, data_size);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
signature.part_number = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER);
|
||||
return signature;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
70
applications/external/avr_isp_programmer/helpers/avr_isp.h
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
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);
|
||||
|
||||
void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context);
|
||||
|
||||
bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance);
|
||||
|
||||
AvrIspSignature avr_isp_read_signature(AvrIsp* instance);
|
||||
|
||||
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 page_size,
|
||||
uint8_t* data,
|
||||
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);
|
||||
|
||||
void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr);
|
23
applications/external/avr_isp_programmer/helpers/avr_isp_event.h
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
//SubmenuIndex
|
||||
SubmenuIndexAvrIspProgrammer = 10,
|
||||
SubmenuIndexAvrIspReader,
|
||||
SubmenuIndexAvrIspWriter,
|
||||
SubmenuIndexAvrIsWiring,
|
||||
SubmenuIndexAvrIspAbout,
|
||||
|
||||
//AvrIspCustomEvent
|
||||
AvrIspCustomEventSceneChipDetectOk = 100,
|
||||
AvrIspCustomEventSceneReadingOk,
|
||||
AvrIspCustomEventSceneWritingOk,
|
||||
AvrIspCustomEventSceneErrorVerification,
|
||||
AvrIspCustomEventSceneErrorReading,
|
||||
AvrIspCustomEventSceneErrorWriting,
|
||||
AvrIspCustomEventSceneErrorWritingFuse,
|
||||
AvrIspCustomEventSceneInputName,
|
||||
AvrIspCustomEventSceneSuccess,
|
||||
AvrIspCustomEventSceneExit,
|
||||
AvrIspCustomEventSceneExitStartMenu,
|
||||
} AvrIspCustomEvent;
|
32
applications/external/avr_isp_programmer/helpers/avr_isp_types.h
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#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_APP_FILE_VERSION 1
|
||||
#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR"
|
||||
#define AVR_ISP_APP_EXTENSION ".avr"
|
||||
|
||||
typedef enum {
|
||||
//AvrIspViewVariableItemList,
|
||||
AvrIspViewSubmenu,
|
||||
AvrIspViewProgrammer,
|
||||
AvrIspViewReader,
|
||||
AvrIspViewWriter,
|
||||
AvrIspViewWidget,
|
||||
AvrIspViewPopup,
|
||||
AvrIspViewTextInput,
|
||||
AvrIspViewChipDetect,
|
||||
} AvrIspView;
|
||||
|
||||
typedef enum {
|
||||
AvrIspErrorNoError,
|
||||
AvrIspErrorReading,
|
||||
AvrIspErrorWriting,
|
||||
AvrIspErrorVerification,
|
||||
AvrIspErrorWritingFuse,
|
||||
} AvrIspError;
|
266
applications/external/avr_isp_programmer/helpers/avr_isp_worker.c
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
#include "avr_isp_worker.h"
|
||||
#include <furi_hal_pwm.h>
|
||||
#include "../lib/driver/avr_isp_prog.h"
|
||||
#include "../lib/driver/avr_isp_prog_cmd.h"
|
||||
#include "../lib/driver/avr_isp_chip_arr.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "AvrIspWorker"
|
||||
|
||||
typedef enum {
|
||||
AvrIspWorkerEvtStop = (1 << 0),
|
||||
|
||||
AvrIspWorkerEvtRx = (1 << 1),
|
||||
AvrIspWorkerEvtTxCoplete = (1 << 2),
|
||||
AvrIspWorkerEvtTx = (1 << 3),
|
||||
AvrIspWorkerEvtState = (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 | \
|
||||
AvrIspWorkerEvtState)
|
||||
|
||||
//########################/* VCP CDC */#############################################
|
||||
#include "usb_cdc.h"
|
||||
#include <cli/cli_vcp.h>
|
||||
#include <cli/cli.h>
|
||||
#include <furi_hal_usb_cdc.h>
|
||||
|
||||
#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);
|
||||
|
||||
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) {
|
||||
UNUSED(context);
|
||||
UNUSED(state);
|
||||
}
|
||||
|
||||
static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) {
|
||||
UNUSED(context);
|
||||
UNUSED(config);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
|
||||
static int32_t avr_isp_worker_prog_thread(void* context) {
|
||||
AvrIspProg* prog = context;
|
||||
FURI_LOG_D(TAG, "AvrIspProgWorker Start");
|
||||
while(1) {
|
||||
if(furi_thread_flags_get() & AvrIspWorkerEvtStop) break;
|
||||
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
|
||||
* @return exit code
|
||||
*/
|
||||
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);
|
||||
|
||||
uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE];
|
||||
size_t len = 0;
|
||||
|
||||
FuriThread* prog_thread =
|
||||
furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog);
|
||||
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);
|
||||
|
||||
if(events & AvrIspWorkerEvtRx) {
|
||||
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)) {
|
||||
len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
avr_isp_prog_exit(prog);
|
||||
furi_delay_ms(10);
|
||||
furi_thread_join(prog_thread);
|
||||
furi_thread_free(prog_thread);
|
||||
|
||||
avr_isp_prog_free(prog);
|
||||
furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4);
|
||||
avr_isp_worker_vcp_cdc_deinit();
|
||||
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);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void avr_isp_worker_free(AvrIspWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
furi_check(!instance->worker_running);
|
||||
furi_thread_free(instance->thread);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void avr_isp_worker_set_callback(
|
||||
AvrIspWorker* instance,
|
||||
AvrIspWorkerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
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_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtStop);
|
||||
|
||||
furi_thread_join(instance->thread);
|
||||
}
|
||||
|
||||
bool avr_isp_worker_is_running(AvrIspWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->worker_running;
|
||||
}
|
49
applications/external/avr_isp_programmer/helpers/avr_isp_worker.h
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
typedef struct AvrIspWorker AvrIspWorker;
|
||||
|
||||
typedef void (*AvrIspWorkerCallback)(void* context, bool connect_usb);
|
||||
|
||||
/** 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_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);
|
1145
applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c
vendored
Normal file
99
applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
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,
|
||||
AvrIspWorkerRWStatusEndWriting = 3,
|
||||
AvrIspWorkerRWStatusEndWritingFuse = 4,
|
||||
|
||||
AvrIspWorkerRWStatusErrorReading = (-1),
|
||||
AvrIspWorkerRWStatusErrorVerification = (-2),
|
||||
AvrIspWorkerRWStatusErrorWriting = (-3),
|
||||
AvrIspWorkerRWStatusErrorWritingFuse = (-4),
|
||||
|
||||
AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization.
|
||||
} AvrIspWorkerRWStatus;
|
||||
|
||||
typedef void (*AvrIspWorkerRWStatusCallback)(void* context, AvrIspWorkerRWStatus status);
|
||||
|
||||
AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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_read_dump(
|
||||
AvrIspWorkerRW* instance,
|
||||
const char* file_path,
|
||||
const char* file_name);
|
||||
|
||||
void avr_isp_worker_rw_read_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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
321
applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c
vendored
Normal file
|
@ -0,0 +1,321 @@
|
|||
#include "flipper_i32hex_file.h"
|
||||
#include <string.h>
|
||||
#include <storage/storage.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/hex.h>
|
||||
|
||||
//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;
|
||||
FlipperI32HexFileStatus file_open;
|
||||
};
|
||||
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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%02X\r\n", (instance->addr >> 16), crc);
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
ret.status = FlipperI32HexFileStatusData;
|
||||
} 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[4];
|
||||
data[1] = data[5];
|
||||
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);
|
||||
|
||||
uint32_t data_size = 280;
|
||||
uint8_t data[280] = {0};
|
||||
bool ret = true;
|
||||
|
||||
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, 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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
55
applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
uint32_t data_size);
|
BIN
applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png
vendored
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/external/avr_isp_programmer/images/avr_wiring.png
vendored
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
applications/external/avr_isp_programmer/images/chif_not_found_83x37.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_error_70x22.png
vendored
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_long_70x22.png
vendored
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_not_found_83x37.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png
vendored
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
applications/external/avr_isp_programmer/images/isp_active_128x53.png
vendored
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
applications/external/avr_isp_programmer/images/link_waiting_77x56.png
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
386
applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c
vendored
Normal file
|
@ -0,0 +1,386 @@
|
|||
#include "avr_isp_chip_arr.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
//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
|
||||
};
|
||||
|
||||
const size_t avr_isp_chip_arr_size = COUNT_OF(avr_isp_chip_arr);
|
33
applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
#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[];
|
||||
extern const size_t avr_isp_chip_arr_size;
|
633
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c
vendored
Normal file
|
@ -0,0 +1,633 @@
|
|||
#include "avr_isp_prog.h"
|
||||
#include "avr_isp_prog_cmd.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#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;
|
||||
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 AvrIspProgCfgDevice AvrIspProgCfgDevice;
|
||||
|
||||
struct AvrIspProg {
|
||||
AvrIspSpiSw* spi;
|
||||
AvrIspProgCfgDevice* cfg;
|
||||
FuriStreamBuffer* stream_rx;
|
||||
FuriStreamBuffer* stream_tx;
|
||||
|
||||
uint16_t error;
|
||||
uint16_t addr;
|
||||
bool pmode;
|
||||
bool exit;
|
||||
bool rst_active_high;
|
||||
uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE];
|
||||
|
||||
AvrIspProgCallback callback;
|
||||
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));
|
||||
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->rst_active_high = false;
|
||||
instance->exit = false;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void avr_isp_prog_free(AvrIspProg* instance) {
|
||||
furi_assert(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);
|
||||
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);
|
||||
furi_assert(len != 0);
|
||||
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);
|
||||
return furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 0);
|
||||
}
|
||||
|
||||
void avr_isp_prog_exit(AvrIspProg* instance) {
|
||||
furi_assert(instance);
|
||||
instance->exit = true;
|
||||
}
|
||||
|
||||
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);
|
||||
furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), FuriWaitForever);
|
||||
}
|
||||
|
||||
static uint8_t avr_isp_prog_getch(AvrIspProg* instance) {
|
||||
furi_assert(instance);
|
||||
uint8_t data[1] = {0};
|
||||
while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) {
|
||||
if(instance->exit) break;
|
||||
};
|
||||
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) ? true : false);
|
||||
}
|
||||
|
||||
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, 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) {
|
||||
furi_assert(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 {
|
||||
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(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);
|
||||
} 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 STK_HW_VER:
|
||||
avr_isp_prog_breply(instance, AVR_ISP_HWVER);
|
||||
break;
|
||||
case STK_SW_MAJOR:
|
||||
avr_isp_prog_breply(instance, AVR_ISP_SWMAJ);
|
||||
break;
|
||||
case STK_SW_MINOR:
|
||||
avr_isp_prog_breply(instance, AVR_ISP_SWMIN);
|
||||
break;
|
||||
case AVP_ISP_CONNECT_TYPE:
|
||||
avr_isp_prog_breply(instance, AVP_ISP_SERIAL_CONNECT_TYPE);
|
||||
break;
|
||||
default:
|
||||
avr_isp_prog_breply(instance, AVR_ISP_RESP_0);
|
||||
}
|
||||
}
|
||||
|
||||
static void avr_isp_prog_set_cfg(AvrIspProg* instance) {
|
||||
furi_assert(instance);
|
||||
// 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->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 void avr_isp_prog_end_pmode(AvrIspProg* instance) {
|
||||
furi_assert(instance);
|
||||
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->spi = NULL;
|
||||
}
|
||||
|
||||
instance->pmode = false;
|
||||
}
|
||||
|
||||
static bool avr_isp_prog_start_pmode(AvrIspProg* 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_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);
|
||||
|
||||
// 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_ms(1);
|
||||
|
||||
avr_isp_prog_reset_target(instance, true);
|
||||
|
||||
// Send the enable programming command:
|
||||
// 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;
|
||||
}
|
||||
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,
|
||||
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); //-V656
|
||||
uint8_t y = 0;
|
||||
while(y < 8) {
|
||||
if(memcmp(
|
||||
(uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspProgSignature)) !=
|
||||
0)
|
||||
break;
|
||||
sig_examination = avr_isp_prog_check_signature(instance);
|
||||
y++;
|
||||
}
|
||||
if(y == 8) {
|
||||
if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) {
|
||||
if(i < (COUNT_OF(spi_speed) - 1)) {
|
||||
avr_isp_prog_end_pmode(instance);
|
||||
i++;
|
||||
return 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;
|
||||
|
||||
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_commit(AvrIspProg* instance, uint16_t addr, uint8_t data) {
|
||||
furi_assert(instance);
|
||||
avr_isp_prog_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_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) {
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t avr_isp_prog_current_page(AvrIspProg* 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_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) {
|
||||
if(page != avr_isp_prog_current_page(instance)) {
|
||||
--x;
|
||||
avr_isp_prog_commit(instance, page, instance->buff[x++]);
|
||||
page = avr_isp_prog_current_page(instance);
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
||||
avr_isp_prog_commit(instance, page, instance->buff[--x]);
|
||||
return STK_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
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) {
|
||||
furi_assert(instance);
|
||||
// this writes byte-by-byte,
|
||||
// page writing may be faster (4 bytes at a time)
|
||||
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_EEPROM(addr, instance->buff[x]));
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
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;
|
||||
if(length > instance->cfg->eepromsize) {
|
||||
instance->error++;
|
||||
return STK_FAILED;
|
||||
}
|
||||
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);
|
||||
// flash memory @addr, (length) bytes
|
||||
if(memtype == STK_SET_FLASH_TYPE) {
|
||||
avr_isp_prog_write_flash(instance, length);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
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_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_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, AVR_ISP_READ_EEPROM(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);
|
||||
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 == STK_SET_FLASH_TYPE) result = avr_isp_prog_flash_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);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||
|
||||
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:
|
||||
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);
|
||||
|
||||
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 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);
|
||||
else
|
||||
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||
}
|
||||
|
||||
if(instance->callback) {
|
||||
instance->callback(instance->context);
|
||||
}
|
||||
}
|
16
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "avr_isp_spi_sw.h"
|
||||
#include <furi_hal.h>
|
||||
|
||||
typedef struct AvrIspProg AvrIspProg;
|
||||
typedef void (*AvrIspProgCallback)(void* context);
|
||||
|
||||
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);
|
||||
void avr_isp_prog_exit(AvrIspProg* instance);
|
||||
void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context);
|
97
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
// 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_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_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_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_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
|
||||
|
||||
// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf
|
||||
// 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
|
||||
|
||||
#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_EEPROM_TYPE 0X45
|
||||
#define STK_SET_FLASH_TYPE 0X46
|
73
applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "avr_isp_spi_sw.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#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_pb2
|
||||
|
||||
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_init(instance->res, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
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);
|
||||
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); //-V792
|
||||
|
||||
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);
|
||||
}
|
24
applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
typedef enum {
|
||||
AvrIspSpiSwSpeed1Mhz = 0,
|
||||
AvrIspSpiSwSpeed400Khz = 1,
|
||||
AvrIspSpiSwSpeed250Khz = 2,
|
||||
AvrIspSpiSwSpeed125Khz = 4,
|
||||
AvrIspSpiSwSpeed60Khz = 8,
|
||||
AvrIspSpiSwSpeed40Khz = 12,
|
||||
AvrIspSpiSwSpeed20Khz = 24,
|
||||
AvrIspSpiSwSpeed10Khz = 48,
|
||||
AvrIspSpiSwSpeed5Khz = 96,
|
||||
AvrIspSpiSwSpeed1Khz = 480,
|
||||
} 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);
|
BIN
applications/external/avr_isp_programmer/lib/driver/clock.png
vendored
Normal file
After Width: | Height: | Size: 3.6 KiB |
30
applications/external/avr_isp_programmer/scenes/avr_isp_scene.c
vendored
Normal file
|
@ -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,
|
||||
};
|
29
applications/external/avr_isp_programmer/scenes/avr_isp_scene.h
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// 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
|
99
applications/external/avr_isp_programmer/scenes/avr_isp_scene_about.c
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
#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) {
|
||||
furi_assert(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) {
|
||||
furi_assert(context);
|
||||
|
||||
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);
|
||||
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,
|
||||
"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, "\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,
|
||||
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! 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) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void avr_isp_scene_about_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
// Clear views
|
||||
widget_reset(app->widget);
|
||||
}
|
72
applications/external/avr_isp_programmer/scenes/avr_isp_scene_chip_detect.c
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include "../avr_isp_app_i.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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
switch(app->error) {
|
||||
case AvrIspErrorReading:
|
||||
case AvrIspErrorWriting:
|
||||
case AvrIspErrorWritingFuse:
|
||||
avr_isp_chip_detect_set_state(
|
||||
app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorOccured);
|
||||
break;
|
||||
case AvrIspErrorVerification:
|
||||
avr_isp_chip_detect_set_state(
|
||||
app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateErrorVerification);
|
||||
break;
|
||||
|
||||
default:
|
||||
avr_isp_chip_detect_set_state(
|
||||
app->avr_isp_chip_detect_view, AvrIspChipDetectViewStateNoDetect);
|
||||
break;
|
||||
}
|
||||
app->error = AvrIspErrorNoError;
|
||||
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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case AvrIspCustomEventSceneChipDetectOk:
|
||||
|
||||
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:
|
||||
break;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void avr_isp_scene_chip_detect_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
10
applications/external/avr_isp_programmer/scenes/avr_isp_scene_config.h
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
ADD_SCENE(avr_isp, start, Start)
|
||||
ADD_SCENE(avr_isp, about, About)
|
||||
ADD_SCENE(avr_isp, programmer, Programmer)
|
||||
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)
|
||||
ADD_SCENE(avr_isp, wiring, Wiring)
|
||||
ADD_SCENE(avr_isp, chip_detect, ChipDetect)
|
||||
ADD_SCENE(avr_isp, success, Success)
|
89
applications/external/avr_isp_programmer/scenes/avr_isp_scene_input_name.c
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "../avr_isp_app_i.h"
|
||||
#include <gui/modules/validators.h>
|
||||
|
||||
#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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
// Setup view
|
||||
TextInput* text_input = app->text_input;
|
||||
bool dev_name_empty = false;
|
||||
|
||||
FuriString* file_name = furi_string_alloc();
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == AvrIspCustomEventSceneInputName) {
|
||||
if(strcmp(app->file_name_tmp, "") != 0) {
|
||||
scene_manager_next_scene(app->scene_manager, AvrIspSceneReader);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void avr_isp_scene_input_name_on_exit(void* 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);
|
||||
}
|
22
applications/external/avr_isp_programmer/scenes/avr_isp_scene_load.c
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "../avr_isp_app_i.h"
|
||||
|
||||
void avr_isp_scene_load_on_enter(void* 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_previous_scene(app->scene_manager);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
28
applications/external/avr_isp_programmer/scenes/avr_isp_scene_programmer.c
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "../avr_isp_app_i.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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
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);
|
||||
}
|
||||
|
||||
bool avr_isp_scene_programmer_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void avr_isp_scene_programmer_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
64
applications/external/avr_isp_programmer/scenes/avr_isp_scene_reader.c
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "../avr_isp_app_i.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) {
|
||||
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);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewReader);
|
||||
}
|
||||
|
||||
bool avr_isp_scene_reader_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"
|
||||
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;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
avr_isp_reader_update_progress(app->avr_isp_reader_view);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void avr_isp_scene_reader_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
75
applications/external/avr_isp_programmer/scenes/avr_isp_scene_start.c
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
#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(
|
||||
submenu, "Dump AVR", SubmenuIndexAvrIspReader, avr_isp_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Flash AVR", SubmenuIndexAvrIspWriter, avr_isp_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"ISP Programmer",
|
||||
SubmenuIndexAvrIspProgrammer,
|
||||
avr_isp_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu, "Wiring", SubmenuIndexAvrIsWiring, 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) {
|
||||
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);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexAvrIspProgrammer) {
|
||||
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_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_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);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, AvrIspSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void avr_isp_scene_start_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
44
applications/external/avr_isp_programmer/scenes/avr_isp_scene_success.c
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "../avr_isp_app_i.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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
Popup* popup = app->popup;
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void avr_isp_scene_success_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
Popup* popup = app->popup;
|
||||
popup_reset(popup);
|
||||
}
|
21
applications/external/avr_isp_programmer/scenes/avr_isp_scene_wiring.c
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "../avr_isp_app_i.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);
|
||||
}
|
||||
|
||||
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) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
69
applications/external/avr_isp_programmer/scenes/avr_isp_scene_writer.c
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "../avr_isp_app_i.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) {
|
||||
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);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, AvrIspViewWriter);
|
||||
}
|
||||
|
||||
bool avr_isp_scene_writer_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_assert(context);
|
||||
|
||||
AvrIspApp* app = context;
|
||||
bool consumed = false;
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
//do not handle exit on "Back"
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
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;
|
||||
case AvrIspCustomEventSceneErrorWritingFuse:
|
||||
app->error = AvrIspErrorWritingFuse;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, AvrIspSceneChipDetect);
|
||||
consumed = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
avr_isp_writer_update_progress(app->avr_isp_writer_view);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void avr_isp_scene_writer_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
|
@ -14,43 +14,69 @@ void picopass_scene_device_info_widget_callback(
|
|||
void picopass_scene_device_info_on_enter(void* context) {
|
||||
Picopass* picopass = context;
|
||||
|
||||
FuriString* credential_str;
|
||||
FuriString* wiegand_str;
|
||||
credential_str = furi_string_alloc();
|
||||
wiegand_str = furi_string_alloc();
|
||||
FuriString* csn_str = furi_string_alloc_set("CSN:");
|
||||
FuriString* credential_str = furi_string_alloc();
|
||||
FuriString* wiegand_str = furi_string_alloc();
|
||||
FuriString* sio_str = furi_string_alloc();
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Setup view
|
||||
PicopassBlock* AA1 = picopass->dev->dev_data.AA1;
|
||||
PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
|
||||
Widget* widget = picopass->widget;
|
||||
|
||||
size_t bytesLength = 1 + pacs->record.bitLength / 8;
|
||||
furi_string_set(credential_str, "");
|
||||
for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) {
|
||||
furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]);
|
||||
uint8_t csn[PICOPASS_BLOCK_LEN] = {0};
|
||||
memcpy(csn, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN);
|
||||
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
|
||||
furi_string_cat_printf(csn_str, "%02X ", csn[i]);
|
||||
}
|
||||
|
||||
if(pacs->record.valid) {
|
||||
furi_string_cat_printf(
|
||||
wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber);
|
||||
if(pacs->record.bitLength == 0 || pacs->record.bitLength == 255) {
|
||||
// Neither of these are valid. Indicates the block was all 0x00 or all 0xff
|
||||
furi_string_cat_printf(wiegand_str, "Invalid PACS");
|
||||
} else {
|
||||
furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength);
|
||||
size_t bytesLength = pacs->record.bitLength / 8;
|
||||
if(pacs->record.bitLength % 8 > 0) {
|
||||
// Add extra byte if there are bits remaining
|
||||
bytesLength++;
|
||||
}
|
||||
furi_string_set(credential_str, "");
|
||||
for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) {
|
||||
furi_string_cat_printf(credential_str, " %02X", pacs->credential[i]);
|
||||
}
|
||||
|
||||
if(pacs->record.valid) {
|
||||
furi_string_cat_printf(
|
||||
wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber);
|
||||
} else {
|
||||
furi_string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength);
|
||||
}
|
||||
|
||||
if(pacs->sio) {
|
||||
furi_string_cat_printf(sio_str, "+SIO");
|
||||
}
|
||||
}
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str));
|
||||
widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(csn_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str));
|
||||
widget_add_string_element(
|
||||
widget,
|
||||
64,
|
||||
32,
|
||||
36,
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
FontSecondary,
|
||||
furi_string_get_cstr(credential_str));
|
||||
widget_add_string_element(
|
||||
widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(sio_str));
|
||||
|
||||
furi_string_free(csn_str);
|
||||
furi_string_free(credential_str);
|
||||
furi_string_free(wiegand_str);
|
||||
furi_string_free(sio_str);
|
||||
|
||||
widget_add_button_element(
|
||||
picopass->widget,
|
||||
|
|
|
@ -283,6 +283,10 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
|||
delay_val = ducky_parse_line(bad_usb, bad_usb->line_prev);
|
||||
if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line
|
||||
return 0;
|
||||
} else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays
|
||||
return delay_val;
|
||||
} else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button
|
||||
return delay_val;
|
||||
} else if(delay_val < 0) { // Script error
|
||||
bad_usb->st.error_line = bad_usb->st.line_cur - 1;
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur - 1U);
|
||||
|
@ -320,6 +324,8 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
|||
return 0;
|
||||
} else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays
|
||||
return delay_val;
|
||||
} else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button
|
||||
return delay_val;
|
||||
} else if(delay_val < 0) {
|
||||
bad_usb->st.error_line = bad_usb->st.line_cur;
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur);
|
||||
|
@ -509,6 +515,9 @@ static int32_t bad_usb_worker(void* context) {
|
|||
delay_val = bad_usb->defdelay;
|
||||
bad_usb->string_print_pos = 0;
|
||||
worker_state = BadUsbStateStringDelay;
|
||||
} else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // set state to wait for user input
|
||||
worker_state = BadUsbStateWaitForBtn;
|
||||
bad_usb->st.state = BadUsbStateWaitForBtn; // Show long delays
|
||||
} else if(delay_val > 1000) {
|
||||
bad_usb->st.state = BadUsbStateDelay; // Show long delays
|
||||
bad_usb->st.delay_remain = delay_val / 1000;
|
||||
|
@ -516,6 +525,23 @@ static int32_t bad_usb_worker(void* context) {
|
|||
} else {
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
}
|
||||
} else if(worker_state == BadUsbStateWaitForBtn) { // State: Wait for button Press
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
|
||||
if(!(flags & FuriFlagError)) {
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
delay_val = 0;
|
||||
worker_state = BadUsbStateRunning;
|
||||
} else if(flags & WorkerEvtDisconnect) {
|
||||
worker_state = BadUsbStateNotConnected; // USB disconnected
|
||||
furi_hal_hid_kb_release_all();
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
continue;
|
||||
}
|
||||
} else if(worker_state == BadUsbStateStringDelay) { // State: print string with delays
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
||||
|
|
|
@ -15,6 +15,7 @@ typedef enum {
|
|||
BadUsbStateRunning,
|
||||
BadUsbStateDelay,
|
||||
BadUsbStateStringDelay,
|
||||
BadUsbStateWaitForBtn,
|
||||
BadUsbStateDone,
|
||||
BadUsbStateScriptError,
|
||||
BadUsbStateFileError,
|
||||
|
|
|
@ -143,6 +143,14 @@ static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_waitforbutton(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
UNUSED(bad_usb);
|
||||
UNUSED(line);
|
||||
|
||||
return SCRIPT_STATE_WAIT_FOR_BTN;
|
||||
}
|
||||
|
||||
static const DuckyCmd ducky_commands[] = {
|
||||
{"REM ", NULL, -1},
|
||||
{"ID ", NULL, -1},
|
||||
|
@ -160,8 +168,12 @@ static const DuckyCmd ducky_commands[] = {
|
|||
{"ALTCODE ", ducky_fnc_altstring, -1},
|
||||
{"HOLD ", ducky_fnc_hold, -1},
|
||||
{"RELEASE ", ducky_fnc_release, -1},
|
||||
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
|
||||
};
|
||||
|
||||
#define TAG "BadUSB"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
int32_t ducky_execute_cmd(BadUsbScript* bad_usb, const char* line) {
|
||||
for(size_t i = 0; i < COUNT_OF(ducky_commands); i++) {
|
||||
if(strncmp(line, ducky_commands[i].name, strlen(ducky_commands[i].name)) == 0) {
|
||||
|
|
|
@ -13,6 +13,7 @@ extern "C" {
|
|||
#define SCRIPT_STATE_NEXT_LINE (-3)
|
||||
#define SCRIPT_STATE_CMD_UNKNOWN (-4)
|
||||
#define SCRIPT_STATE_STRING_START (-5)
|
||||
#define SCRIPT_STATE_WAIT_FOR_BTN (-6)
|
||||
|
||||
#define FILE_BUFFER_LEN 16
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
|||
elements_button_left(canvas, "Config");
|
||||
} else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadUsbStateWaitForBtn) {
|
||||
elements_button_center(canvas, "Press to continue");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ typedef enum {
|
|||
SubmenuIndexSomfyTelis,
|
||||
SubmenuIndexBeninca433,
|
||||
SubmenuIndexBeninca868,
|
||||
SubmenuIndexAllmatic433,
|
||||
SubmenuIndexAllmatic868,
|
||||
SubmenuIndexIronLogic,
|
||||
SubmenuIndexElmesElectronic,
|
||||
SubmenuIndexSommer_FM_434,
|
||||
|
|
|
@ -171,6 +171,18 @@ void subghz_scene_set_type_on_enter(void* context) {
|
|||
SubmenuIndexBeninca868,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: Allmatic 433MHz",
|
||||
SubmenuIndexAllmatic433,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: Allmatic 868MHz",
|
||||
SubmenuIndexAllmatic868,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: Sommer 434MHz",
|
||||
|
@ -505,6 +517,30 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexAllmatic433:
|
||||
if(subghz_scene_set_type_submenu_gen_data_keeloq(
|
||||
subghz,
|
||||
"AM650",
|
||||
433920000,
|
||||
(key & 0x00FFFF00) | 0x01000011,
|
||||
0xC,
|
||||
0x0005,
|
||||
"Beninca")) {
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexAllmatic868:
|
||||
if(subghz_scene_set_type_submenu_gen_data_keeloq(
|
||||
subghz,
|
||||
"AM650",
|
||||
868350000,
|
||||
(key & 0x00FFFF00) | 0x01000011,
|
||||
0xC,
|
||||
0x0005,
|
||||
"Beninca")) {
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexElmesElectronic:
|
||||
if(subghz_scene_set_type_submenu_gen_data_keeloq(
|
||||
subghz,
|
||||
|
|
|
@ -77,6 +77,13 @@ Up to 5 keys can be hold simultaneously.
|
|||
| HOLD | Special key or single character | Press and hold key untill RELEASE command |
|
||||
| RELEASE | Special key or single character | Release key |
|
||||
|
||||
## Wait for button press
|
||||
|
||||
Will wait indefinitely for a button to be pressed
|
||||
| Command | Parameters | Notes |
|
||||
| --------------------- | ------------ | --------------------------------------------------------------------- |
|
||||
| WAIT_FOR_BUTTON_PRESS | None | Will wait for the user to press a button to continue script execution |
|
||||
|
||||
|
||||
## String
|
||||
|
||||
|
|
|
@ -158,6 +158,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,,
|
||||
|
@ -1314,6 +1315,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*
|
||||
|
@ -1875,6 +1880,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,
|
||||
|
|
|
|
@ -194,6 +194,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,,
|
||||
|
@ -1633,6 +1634,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,-,hypot,double,"double, double"
|
||||
Function,-,hypotf,float,"float, float"
|
||||
Function,-,hypotl,long double,"long double, long double"
|
||||
|
@ -4435,6 +4440,7 @@ Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned
|
|||
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,-,ucStreamBufferGetStreamBufferType,uint8_t,StreamBufferHandle_t
|
||||
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,
|
||||
|
|
|
|
@ -232,9 +232,9 @@ static bool subghz_protocol_keeloq_gen_data(
|
|||
decrypt = btn << 28 | (instance->generic.serial & 0xFF) << 16 | instance->generic.cnt;
|
||||
}
|
||||
|
||||
// Beninca -> 4bit serial - simple XOR
|
||||
// Beninca / Allmatic -> no serial - simple XOR
|
||||
if(strcmp(instance->manufacture_name, "Beninca") == 0) {
|
||||
decrypt = btn << 28 | (instance->generic.serial & 0xF) << 16 | instance->generic.cnt;
|
||||
decrypt = btn << 28 | (0x000) << 16 | instance->generic.cnt;
|
||||
}
|
||||
|
||||
if(strcmp(instance->manufacture_name, "Unknown") == 0) {
|
||||
|
|
|
@ -28,6 +28,7 @@ env.Append(
|
|||
File("stream/buffered_file_stream.h"),
|
||||
File("protocols/protocol_dict.h"),
|
||||
File("pretty_format.h"),
|
||||
File("hex.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
|