mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-10 06:54:19 +00:00
Fix merge issues
This commit is contained in:
parent
8b8b78d001
commit
05e53cac26
22 changed files with 1670 additions and 11 deletions
|
@ -134,9 +134,9 @@ Min level: 3
|
|||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Sleigh_ride_128x64
|
||||
Name: L1_Senpai_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Max butthurt: 5
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
|
|
@ -211,9 +211,9 @@ Games:
|
|||
|
||||
## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||
|
||||
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/gps_nmea_uart/README.md)
|
||||
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/gps_nmea_uart/README.md)
|
||||
|
||||
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/flipper_i2ctools/README.md)
|
||||
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/flipper_i2ctools/README.md)
|
||||
|
||||
## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||
|
||||
|
|
|
@ -7,6 +7,6 @@ App(
|
|||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=60,
|
||||
fap_icon="../../plugins/mousejacker/mouse_10px.png",
|
||||
fap_icon="../../external/mousejacker/mouse_10px.png",
|
||||
fap_category="Debug",
|
||||
)
|
||||
|
|
105
applications/external/dap_link/README.md
vendored
Normal file
105
applications/external/dap_link/README.md
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
# Flipper Zero as CMSIS DAP/DAP Link
|
||||
Flipper Zero as a [Free-DAP](https://github.com/ataradov/free-dap) based SWD\JTAG debugger. Free-DAP is a free and open source firmware implementation of the [CMSIS-DAP](https://www.keil.com/pack/doc/CMSIS_Dev/DAP/html/index.html) debugger.
|
||||
|
||||
## Protocols
|
||||
SWD, JTAG , CMSIS-DAP v1 (18 KiB/s), CMSIS-DAP v2 (46 KiB/s), VCP (USB-UART).
|
||||
|
||||
WinUSB for driverless installation for Windows 8 and above.
|
||||
|
||||
## Usage
|
||||
|
||||
### VSCode + Cortex-Debug
|
||||
Set `"device": "cmsis-dap"`
|
||||
|
||||
<details>
|
||||
<summary>BluePill configuration example</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Attach (DAP)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "cmsis-dap",
|
||||
"configFiles": [
|
||||
"interface/cmsis-dap.cfg",
|
||||
"target/stm32f1x.cfg",
|
||||
],
|
||||
},
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Flipper Zero configuration example</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Attach (DAP)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"executable": "./build/latest/firmware.elf",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "cmsis-dap",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/cmsis-dap.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source debug/flipperapps.py",
|
||||
],
|
||||
},
|
||||
```
|
||||
</details>
|
||||
|
||||
### OpenOCD
|
||||
Use `interface/cmsis-dap.cfg`. You will need OpenOCD v0.11.0.
|
||||
|
||||
Additional commands:
|
||||
* `cmsis_dap_backend hid` for CMSIS-DAP v1 protocol.
|
||||
* `cmsis_dap_backend usb_bulk` for CMSIS-DAP v2 protocol.
|
||||
* `cmsis_dap_serial DAP_Oyevoxo` use DAP-Link running on Flipper named `Oyevoxo`.
|
||||
* `cmsis-dap cmd 81` - reboot connected DAP-Link.
|
||||
|
||||
<details>
|
||||
<summary>Flash BluePill</summary>
|
||||
|
||||
```
|
||||
openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c init -c "program build/firmware.bin reset exit 0x8000000"
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Flash Flipper Zero using DAP v2 protocol</summary>
|
||||
|
||||
```
|
||||
openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_backend usb_bulk" -f debug/stm32wbx.cfg -c init -c "program build/latest/firmware.bin reset exit 0x8000000"
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Reboot connected DAP-Link on Flipper named Oyevoxo</summary>
|
||||
|
||||
```
|
||||
openocd -f interface/cmsis-dap.cfg -c "cmsis_dap_serial DAP_Oyevoxo" -c "transport select swd" -c "adapter speed 4000000" -c init -c "cmsis-dap cmd 81" -c "exit"
|
||||
```
|
||||
</details>
|
||||
|
||||
### PlatformIO
|
||||
Use `debug_tool = cmsis-dap` and `upload_protocol = cmsis-dap`. [Documentation](https://docs.platformio.org/en/latest/plus/debug-tools/cmsis-dap.html#debugging-tool-cmsis-dap). Remember that Windows 8 and above do not require drivers.
|
||||
|
||||
<details>
|
||||
<summary>BluePill platformio.ini example</summary>
|
||||
|
||||
```
|
||||
[env:bluepill_f103c8]
|
||||
platform = ststm32
|
||||
board = bluepill_f103c8
|
||||
debug_tool = cmsis-dap
|
||||
upload_protocol = cmsis-dap
|
||||
```
|
||||
</details>
|
234
applications/external/dap_link/dap_config.h
vendored
Normal file
234
applications/external/dap_link/dap_config.h
vendored
Normal file
|
@ -0,0 +1,234 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
|
||||
|
||||
#ifndef _DAP_CONFIG_H_
|
||||
#define _DAP_CONFIG_H_
|
||||
|
||||
/*- Includes ----------------------------------------------------------------*/
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
/*- Definitions -------------------------------------------------------------*/
|
||||
#define DAP_CONFIG_ENABLE_JTAG
|
||||
|
||||
#define DAP_CONFIG_DEFAULT_PORT DAP_PORT_SWD
|
||||
#define DAP_CONFIG_DEFAULT_CLOCK 4200000 // Hz
|
||||
|
||||
#define DAP_CONFIG_PACKET_SIZE 64
|
||||
#define DAP_CONFIG_PACKET_COUNT 1
|
||||
|
||||
#define DAP_CONFIG_JTAG_DEV_COUNT 8
|
||||
|
||||
// DAP_CONFIG_PRODUCT_STR must contain "CMSIS-DAP" to be compatible with the standard
|
||||
#define DAP_CONFIG_VENDOR_STR "Flipper Zero"
|
||||
#define DAP_CONFIG_PRODUCT_STR "Generic CMSIS-DAP Adapter"
|
||||
#define DAP_CONFIG_SER_NUM_STR usb_serial_number
|
||||
#define DAP_CONFIG_CMSIS_DAP_VER_STR "2.0.0"
|
||||
|
||||
#define DAP_CONFIG_RESET_TARGET_FN dap_app_target_reset
|
||||
#define DAP_CONFIG_VENDOR_FN dap_app_vendor_cmd
|
||||
|
||||
// Attribute to use for performance-critical functions
|
||||
#define DAP_CONFIG_PERFORMANCE_ATTR
|
||||
|
||||
// A value at which dap_clock_test() produces 1 kHz output on the SWCLK pin
|
||||
// #define DAP_CONFIG_DELAY_CONSTANT 19000
|
||||
#define DAP_CONFIG_DELAY_CONSTANT 6290
|
||||
|
||||
// A threshold for switching to fast clock (no added delays)
|
||||
// This is the frequency produced by dap_clock_test(1) on the SWCLK pin
|
||||
#define DAP_CONFIG_FAST_CLOCK 2400000 // Hz
|
||||
|
||||
/*- Prototypes --------------------------------------------------------------*/
|
||||
extern char usb_serial_number[16];
|
||||
|
||||
/*- Implementations ---------------------------------------------------------*/
|
||||
extern GpioPin flipper_dap_swclk_pin;
|
||||
extern GpioPin flipper_dap_swdio_pin;
|
||||
extern GpioPin flipper_dap_reset_pin;
|
||||
extern GpioPin flipper_dap_tdo_pin;
|
||||
extern GpioPin flipper_dap_tdi_pin;
|
||||
|
||||
extern void dap_app_vendor_cmd(uint8_t cmd);
|
||||
extern void dap_app_target_reset();
|
||||
extern void dap_app_disconnect();
|
||||
extern void dap_app_connect_swd();
|
||||
extern void dap_app_connect_jtag();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_write(int value) {
|
||||
furi_hal_gpio_write(&flipper_dap_swclk_pin, value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_write(int value) {
|
||||
furi_hal_gpio_write(&flipper_dap_swdio_pin, value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_TDI_write(int value) {
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_write(&flipper_dap_tdi_pin, value);
|
||||
#else
|
||||
(void)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_TDO_write(int value) {
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_write(&flipper_dap_tdo_pin, value);
|
||||
#else
|
||||
(void)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_nTRST_write(int value) {
|
||||
(void)value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_nRESET_write(int value) {
|
||||
furi_hal_gpio_write(&flipper_dap_reset_pin, value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_SWCLK_TCK_read(void) {
|
||||
return furi_hal_gpio_read(&flipper_dap_swclk_pin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_SWDIO_TMS_read(void) {
|
||||
return furi_hal_gpio_read(&flipper_dap_swdio_pin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_TDO_read(void) {
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
return furi_hal_gpio_read(&flipper_dap_tdo_pin);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_TDI_read(void) {
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
return furi_hal_gpio_read(&flipper_dap_tdi_pin);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_nTRST_read(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline int DAP_CONFIG_nRESET_read(void) {
|
||||
return furi_hal_gpio_read(&flipper_dap_reset_pin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_set(void) {
|
||||
LL_GPIO_SetOutputPin(flipper_dap_swclk_pin.port, flipper_dap_swclk_pin.pin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWCLK_TCK_clr(void) {
|
||||
LL_GPIO_ResetOutputPin(flipper_dap_swclk_pin.port, flipper_dap_swclk_pin.pin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_in(void) {
|
||||
LL_GPIO_SetPinMode(flipper_dap_swdio_pin.port, flipper_dap_swdio_pin.pin, LL_GPIO_MODE_INPUT);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SWDIO_TMS_out(void) {
|
||||
LL_GPIO_SetPinMode(flipper_dap_swdio_pin.port, flipper_dap_swdio_pin.pin, LL_GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_SETUP(void) {
|
||||
furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_DISCONNECT(void) {
|
||||
furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
dap_app_disconnect();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_CONNECT_SWD(void) {
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_swdio_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_swdio_pin, true);
|
||||
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_swclk_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_swclk_pin, true);
|
||||
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_reset_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_reset_pin, true);
|
||||
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
dap_app_connect_swd();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_CONNECT_JTAG(void) {
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_swdio_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_swdio_pin, true);
|
||||
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_swclk_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_swclk_pin, true);
|
||||
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_reset_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_reset_pin, true);
|
||||
|
||||
#ifdef DAP_CONFIG_ENABLE_JTAG
|
||||
furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||
|
||||
furi_hal_gpio_init(
|
||||
&flipper_dap_tdi_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_write(&flipper_dap_tdi_pin, true);
|
||||
#endif
|
||||
dap_app_connect_jtag();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void DAP_CONFIG_LED(int index, int state) {
|
||||
(void)index;
|
||||
(void)state;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__attribute__((always_inline)) static inline void DAP_CONFIG_DELAY(uint32_t cycles) {
|
||||
asm volatile("1: subs %[cycles], %[cycles], #1 \n"
|
||||
" bne 1b \n"
|
||||
: [cycles] "+l"(cycles));
|
||||
}
|
||||
|
||||
#endif // _DAP_CONFIG_H_
|
527
applications/external/dap_link/dap_link.c
vendored
Normal file
527
applications/external/dap_link/dap_link.c
vendored
Normal file
|
@ -0,0 +1,527 @@
|
|||
#include <dap.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
|
||||
#include "dap_link.h"
|
||||
#include "dap_config.h"
|
||||
#include "gui/dap_gui.h"
|
||||
#include "usb/dap_v2_usb.h"
|
||||
#include <dialogs/dialogs.h>
|
||||
#include "dap_link_icons.h"
|
||||
|
||||
/***************************************************************************/
|
||||
/****************************** DAP COMMON *********************************/
|
||||
/***************************************************************************/
|
||||
|
||||
struct DapApp {
|
||||
FuriThread* dap_thread;
|
||||
FuriThread* cdc_thread;
|
||||
FuriThread* gui_thread;
|
||||
|
||||
DapState state;
|
||||
DapConfig config;
|
||||
};
|
||||
|
||||
void dap_app_get_state(DapApp* app, DapState* state) {
|
||||
*state = app->state;
|
||||
}
|
||||
|
||||
#define DAP_PROCESS_THREAD_TICK 500
|
||||
|
||||
typedef enum {
|
||||
DapThreadEventStop = (1 << 0),
|
||||
} DapThreadEvent;
|
||||
|
||||
void dap_thread_send_stop(FuriThread* thread) {
|
||||
furi_thread_flags_set(furi_thread_get_id(thread), DapThreadEventStop);
|
||||
}
|
||||
|
||||
GpioPin flipper_dap_swclk_pin;
|
||||
GpioPin flipper_dap_swdio_pin;
|
||||
GpioPin flipper_dap_reset_pin;
|
||||
GpioPin flipper_dap_tdo_pin;
|
||||
GpioPin flipper_dap_tdi_pin;
|
||||
|
||||
/***************************************************************************/
|
||||
/****************************** DAP PROCESS ********************************/
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[DAP_CONFIG_PACKET_SIZE];
|
||||
uint8_t size;
|
||||
} DapPacket;
|
||||
|
||||
typedef enum {
|
||||
DAPThreadEventStop = DapThreadEventStop,
|
||||
DAPThreadEventRxV1 = (1 << 1),
|
||||
DAPThreadEventRxV2 = (1 << 2),
|
||||
DAPThreadEventUSBConnect = (1 << 3),
|
||||
DAPThreadEventUSBDisconnect = (1 << 4),
|
||||
DAPThreadEventApplyConfig = (1 << 5),
|
||||
DAPThreadEventAll = DAPThreadEventStop | DAPThreadEventRxV1 | DAPThreadEventRxV2 |
|
||||
DAPThreadEventUSBConnect | DAPThreadEventUSBDisconnect |
|
||||
DAPThreadEventApplyConfig,
|
||||
} DAPThreadEvent;
|
||||
|
||||
#define USB_SERIAL_NUMBER_LEN 16
|
||||
char usb_serial_number[USB_SERIAL_NUMBER_LEN] = {0};
|
||||
|
||||
const char* dap_app_get_serial(DapApp* app) {
|
||||
UNUSED(app);
|
||||
return usb_serial_number;
|
||||
}
|
||||
|
||||
static void dap_app_rx1_callback(void* context) {
|
||||
furi_assert(context);
|
||||
FuriThreadId thread_id = (FuriThreadId)context;
|
||||
furi_thread_flags_set(thread_id, DAPThreadEventRxV1);
|
||||
}
|
||||
|
||||
static void dap_app_rx2_callback(void* context) {
|
||||
furi_assert(context);
|
||||
FuriThreadId thread_id = (FuriThreadId)context;
|
||||
furi_thread_flags_set(thread_id, DAPThreadEventRxV2);
|
||||
}
|
||||
|
||||
static void dap_app_usb_state_callback(bool state, void* context) {
|
||||
furi_assert(context);
|
||||
FuriThreadId thread_id = (FuriThreadId)context;
|
||||
if(state) {
|
||||
furi_thread_flags_set(thread_id, DAPThreadEventUSBConnect);
|
||||
} else {
|
||||
furi_thread_flags_set(thread_id, DAPThreadEventUSBDisconnect);
|
||||
}
|
||||
}
|
||||
|
||||
static void dap_app_process_v1() {
|
||||
DapPacket tx_packet;
|
||||
DapPacket rx_packet;
|
||||
memset(&tx_packet, 0, sizeof(DapPacket));
|
||||
rx_packet.size = dap_v1_usb_rx(rx_packet.data, DAP_CONFIG_PACKET_SIZE);
|
||||
dap_process_request(rx_packet.data, rx_packet.size, tx_packet.data, DAP_CONFIG_PACKET_SIZE);
|
||||
dap_v1_usb_tx(tx_packet.data, DAP_CONFIG_PACKET_SIZE);
|
||||
}
|
||||
|
||||
static void dap_app_process_v2() {
|
||||
DapPacket tx_packet;
|
||||
DapPacket rx_packet;
|
||||
memset(&tx_packet, 0, sizeof(DapPacket));
|
||||
rx_packet.size = dap_v2_usb_rx(rx_packet.data, DAP_CONFIG_PACKET_SIZE);
|
||||
size_t len = dap_process_request(
|
||||
rx_packet.data, rx_packet.size, tx_packet.data, DAP_CONFIG_PACKET_SIZE);
|
||||
dap_v2_usb_tx(tx_packet.data, len);
|
||||
}
|
||||
|
||||
void dap_app_vendor_cmd(uint8_t cmd) {
|
||||
// openocd -c "cmsis-dap cmd 81"
|
||||
if(cmd == 0x01) {
|
||||
furi_hal_power_reset();
|
||||
}
|
||||
}
|
||||
|
||||
void dap_app_target_reset() {
|
||||
FURI_LOG_I("DAP", "Target reset");
|
||||
}
|
||||
|
||||
static void dap_init_gpio(DapSwdPins swd_pins) {
|
||||
switch(swd_pins) {
|
||||
case DapSwdPinsPA7PA6:
|
||||
flipper_dap_swclk_pin = gpio_ext_pa7;
|
||||
flipper_dap_swdio_pin = gpio_ext_pa6;
|
||||
break;
|
||||
case DapSwdPinsPA14PA13:
|
||||
flipper_dap_swclk_pin = (GpioPin){.port = GPIOA, .pin = LL_GPIO_PIN_14};
|
||||
flipper_dap_swdio_pin = (GpioPin){.port = GPIOA, .pin = LL_GPIO_PIN_13};
|
||||
break;
|
||||
}
|
||||
|
||||
flipper_dap_reset_pin = gpio_ext_pa4;
|
||||
flipper_dap_tdo_pin = gpio_ext_pb3;
|
||||
flipper_dap_tdi_pin = gpio_ext_pb2;
|
||||
}
|
||||
|
||||
static void dap_deinit_gpio(DapSwdPins swd_pins) {
|
||||
// setup gpio pins to default state
|
||||
furi_hal_gpio_init(&flipper_dap_reset_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&flipper_dap_tdo_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&flipper_dap_tdi_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
if(DapSwdPinsPA14PA13 == swd_pins) {
|
||||
// PA14 and PA13 are used by SWD
|
||||
furi_hal_gpio_init_ex(
|
||||
&flipper_dap_swclk_pin,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullDown,
|
||||
GpioSpeedLow,
|
||||
GpioAltFn0JTCK_SWCLK);
|
||||
furi_hal_gpio_init_ex(
|
||||
&flipper_dap_swdio_pin,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn0JTMS_SWDIO);
|
||||
} else {
|
||||
furi_hal_gpio_init(&flipper_dap_swclk_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&flipper_dap_swdio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t dap_process(void* p) {
|
||||
DapApp* app = p;
|
||||
DapState* dap_state = &(app->state);
|
||||
|
||||
// allocate resources
|
||||
FuriHalUsbInterface* usb_config_prev;
|
||||
app->config.swd_pins = DapSwdPinsPA7PA6;
|
||||
DapSwdPins swd_pins_prev = app->config.swd_pins;
|
||||
|
||||
// init pins
|
||||
dap_init_gpio(swd_pins_prev);
|
||||
|
||||
// init dap
|
||||
dap_init();
|
||||
|
||||
// get name
|
||||
const char* name = furi_hal_version_get_name_ptr();
|
||||
if(!name) {
|
||||
name = "Flipper";
|
||||
}
|
||||
snprintf(usb_serial_number, USB_SERIAL_NUMBER_LEN, "DAP_%s", name);
|
||||
|
||||
// init usb
|
||||
usb_config_prev = furi_hal_usb_get_config();
|
||||
dap_common_usb_alloc_name(usb_serial_number);
|
||||
dap_common_usb_set_context(furi_thread_get_id(furi_thread_get_current()));
|
||||
dap_v1_usb_set_rx_callback(dap_app_rx1_callback);
|
||||
dap_v2_usb_set_rx_callback(dap_app_rx2_callback);
|
||||
dap_common_usb_set_state_callback(dap_app_usb_state_callback);
|
||||
furi_hal_usb_set_config(&dap_v2_usb_hid, NULL);
|
||||
|
||||
// work
|
||||
uint32_t events;
|
||||
while(1) {
|
||||
events = furi_thread_flags_wait(DAPThreadEventAll, FuriFlagWaitAny, FuriWaitForever);
|
||||
|
||||
if(!(events & FuriFlagError)) {
|
||||
if(events & DAPThreadEventRxV1) {
|
||||
dap_app_process_v1();
|
||||
dap_state->dap_counter++;
|
||||
dap_state->dap_version = DapVersionV1;
|
||||
}
|
||||
|
||||
if(events & DAPThreadEventRxV2) {
|
||||
dap_app_process_v2();
|
||||
dap_state->dap_counter++;
|
||||
dap_state->dap_version = DapVersionV2;
|
||||
}
|
||||
|
||||
if(events & DAPThreadEventUSBConnect) {
|
||||
dap_state->usb_connected = true;
|
||||
}
|
||||
|
||||
if(events & DAPThreadEventUSBDisconnect) {
|
||||
dap_state->usb_connected = false;
|
||||
dap_state->dap_version = DapVersionUnknown;
|
||||
}
|
||||
|
||||
if(events & DAPThreadEventApplyConfig) {
|
||||
if(swd_pins_prev != app->config.swd_pins) {
|
||||
dap_deinit_gpio(swd_pins_prev);
|
||||
swd_pins_prev = app->config.swd_pins;
|
||||
dap_init_gpio(swd_pins_prev);
|
||||
}
|
||||
}
|
||||
|
||||
if(events & DAPThreadEventStop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deinit usb
|
||||
furi_hal_usb_set_config(usb_config_prev, NULL);
|
||||
dap_common_usb_free_name();
|
||||
dap_deinit_gpio(swd_pins_prev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/****************************** CDC PROCESS ********************************/
|
||||
/***************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
CDCThreadEventStop = DapThreadEventStop,
|
||||
CDCThreadEventUARTRx = (1 << 1),
|
||||
CDCThreadEventCDCRx = (1 << 2),
|
||||
CDCThreadEventCDCConfig = (1 << 3),
|
||||
CDCThreadEventApplyConfig = (1 << 4),
|
||||
CDCThreadEventAll = CDCThreadEventStop | CDCThreadEventUARTRx | CDCThreadEventCDCRx |
|
||||
CDCThreadEventCDCConfig | CDCThreadEventApplyConfig,
|
||||
} CDCThreadEvent;
|
||||
|
||||
typedef struct {
|
||||
FuriStreamBuffer* rx_stream;
|
||||
FuriThreadId thread_id;
|
||||
FuriHalUartId uart_id;
|
||||
struct usb_cdc_line_coding line_coding;
|
||||
} CDCProcess;
|
||||
|
||||
static void cdc_uart_irq_cb(UartIrqEvent ev, uint8_t data, void* ctx) {
|
||||
CDCProcess* app = ctx;
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||
furi_thread_flags_set(app->thread_id, CDCThreadEventUARTRx);
|
||||
}
|
||||
}
|
||||
|
||||
static void cdc_usb_rx_callback(void* context) {
|
||||
CDCProcess* app = context;
|
||||
furi_thread_flags_set(app->thread_id, CDCThreadEventCDCRx);
|
||||
}
|
||||
|
||||
static void cdc_usb_control_line_callback(uint8_t state, void* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(state);
|
||||
}
|
||||
|
||||
static void cdc_usb_config_callback(struct usb_cdc_line_coding* config, void* context) {
|
||||
CDCProcess* app = context;
|
||||
app->line_coding = *config;
|
||||
furi_thread_flags_set(app->thread_id, CDCThreadEventCDCConfig);
|
||||
}
|
||||
|
||||
static FuriHalUartId cdc_init_uart(
|
||||
DapUartType type,
|
||||
DapUartTXRX swap,
|
||||
uint32_t baudrate,
|
||||
void (*cb)(UartIrqEvent ev, uint8_t data, void* ctx),
|
||||
void* ctx) {
|
||||
FuriHalUartId uart_id = FuriHalUartIdUSART1;
|
||||
if(baudrate == 0) baudrate = 115200;
|
||||
|
||||
switch(type) {
|
||||
case DapUartTypeUSART1:
|
||||
uart_id = FuriHalUartIdUSART1;
|
||||
furi_hal_console_disable();
|
||||
furi_hal_uart_deinit(uart_id);
|
||||
if(swap == DapUartTXRXSwap) {
|
||||
LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_SWAPPED);
|
||||
} else {
|
||||
LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD);
|
||||
}
|
||||
furi_hal_uart_init(uart_id, baudrate);
|
||||
furi_hal_uart_set_irq_cb(uart_id, cb, ctx);
|
||||
break;
|
||||
case DapUartTypeLPUART1:
|
||||
uart_id = FuriHalUartIdLPUART1;
|
||||
furi_hal_uart_deinit(uart_id);
|
||||
if(swap == DapUartTXRXSwap) {
|
||||
LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_SWAPPED);
|
||||
} else {
|
||||
LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD);
|
||||
}
|
||||
furi_hal_uart_init(uart_id, baudrate);
|
||||
furi_hal_uart_set_irq_cb(uart_id, cb, ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
return uart_id;
|
||||
}
|
||||
|
||||
static void cdc_deinit_uart(DapUartType type) {
|
||||
switch(type) {
|
||||
case DapUartTypeUSART1:
|
||||
furi_hal_uart_deinit(FuriHalUartIdUSART1);
|
||||
LL_USART_SetTXRXSwap(USART1, LL_USART_TXRX_STANDARD);
|
||||
furi_hal_console_init();
|
||||
break;
|
||||
case DapUartTypeLPUART1:
|
||||
furi_hal_uart_deinit(FuriHalUartIdLPUART1);
|
||||
LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_STANDARD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t cdc_process(void* p) {
|
||||
DapApp* dap_app = p;
|
||||
DapState* dap_state = &(dap_app->state);
|
||||
|
||||
dap_app->config.uart_pins = DapUartTypeLPUART1;
|
||||
dap_app->config.uart_swap = DapUartTXRXNormal;
|
||||
|
||||
DapUartType uart_pins_prev = dap_app->config.uart_pins;
|
||||
DapUartTXRX uart_swap_prev = dap_app->config.uart_swap;
|
||||
|
||||
CDCProcess* app = malloc(sizeof(CDCProcess));
|
||||
app->thread_id = furi_thread_get_id(furi_thread_get_current());
|
||||
app->rx_stream = furi_stream_buffer_alloc(512, 1);
|
||||
|
||||
const uint8_t rx_buffer_size = 64;
|
||||
uint8_t* rx_buffer = malloc(rx_buffer_size);
|
||||
|
||||
app->uart_id = cdc_init_uart(
|
||||
uart_pins_prev, uart_swap_prev, dap_state->cdc_baudrate, cdc_uart_irq_cb, app);
|
||||
|
||||
dap_cdc_usb_set_context(app);
|
||||
dap_cdc_usb_set_rx_callback(cdc_usb_rx_callback);
|
||||
dap_cdc_usb_set_control_line_callback(cdc_usb_control_line_callback);
|
||||
dap_cdc_usb_set_config_callback(cdc_usb_config_callback);
|
||||
|
||||
uint32_t events;
|
||||
while(1) {
|
||||
events = furi_thread_flags_wait(CDCThreadEventAll, FuriFlagWaitAny, FuriWaitForever);
|
||||
|
||||
if(!(events & FuriFlagError)) {
|
||||
if(events & CDCThreadEventCDCConfig) {
|
||||
if(dap_state->cdc_baudrate != app->line_coding.dwDTERate) {
|
||||
dap_state->cdc_baudrate = app->line_coding.dwDTERate;
|
||||
if(dap_state->cdc_baudrate > 0) {
|
||||
furi_hal_uart_set_br(app->uart_id, dap_state->cdc_baudrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(events & CDCThreadEventUARTRx) {
|
||||
size_t len =
|
||||
furi_stream_buffer_receive(app->rx_stream, rx_buffer, rx_buffer_size, 0);
|
||||
|
||||
if(len > 0) {
|
||||
dap_cdc_usb_tx(rx_buffer, len);
|
||||
}
|
||||
dap_state->cdc_rx_counter += len;
|
||||
}
|
||||
|
||||
if(events & CDCThreadEventCDCRx) {
|
||||
size_t len = dap_cdc_usb_rx(rx_buffer, rx_buffer_size);
|
||||
if(len > 0) {
|
||||
furi_hal_uart_tx(app->uart_id, rx_buffer, len);
|
||||
}
|
||||
dap_state->cdc_tx_counter += len;
|
||||
}
|
||||
|
||||
if(events & CDCThreadEventApplyConfig) {
|
||||
if(uart_pins_prev != dap_app->config.uart_pins ||
|
||||
uart_swap_prev != dap_app->config.uart_swap) {
|
||||
cdc_deinit_uart(uart_pins_prev);
|
||||
uart_pins_prev = dap_app->config.uart_pins;
|
||||
uart_swap_prev = dap_app->config.uart_swap;
|
||||
app->uart_id = cdc_init_uart(
|
||||
uart_pins_prev,
|
||||
uart_swap_prev,
|
||||
dap_state->cdc_baudrate,
|
||||
cdc_uart_irq_cb,
|
||||
app);
|
||||
}
|
||||
}
|
||||
|
||||
if(events & CDCThreadEventStop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cdc_deinit_uart(uart_pins_prev);
|
||||
free(rx_buffer);
|
||||
furi_stream_buffer_free(app->rx_stream);
|
||||
free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/******************************* MAIN APP **********************************/
|
||||
/***************************************************************************/
|
||||
|
||||
static DapApp* dap_app_alloc() {
|
||||
DapApp* dap_app = malloc(sizeof(DapApp));
|
||||
dap_app->dap_thread = furi_thread_alloc_ex("DAP Process", 1024, dap_process, dap_app);
|
||||
dap_app->cdc_thread = furi_thread_alloc_ex("DAP CDC", 1024, cdc_process, dap_app);
|
||||
dap_app->gui_thread = furi_thread_alloc_ex("DAP GUI", 1024, dap_gui_thread, dap_app);
|
||||
return dap_app;
|
||||
}
|
||||
|
||||
static void dap_app_free(DapApp* dap_app) {
|
||||
furi_assert(dap_app);
|
||||
furi_thread_free(dap_app->dap_thread);
|
||||
furi_thread_free(dap_app->cdc_thread);
|
||||
furi_thread_free(dap_app->gui_thread);
|
||||
free(dap_app);
|
||||
}
|
||||
|
||||
static DapApp* app_handle = NULL;
|
||||
|
||||
void dap_app_disconnect() {
|
||||
app_handle->state.dap_mode = DapModeDisconnected;
|
||||
}
|
||||
|
||||
void dap_app_connect_swd() {
|
||||
app_handle->state.dap_mode = DapModeSWD;
|
||||
}
|
||||
|
||||
void dap_app_connect_jtag() {
|
||||
app_handle->state.dap_mode = DapModeJTAG;
|
||||
}
|
||||
|
||||
void dap_app_set_config(DapApp* app, DapConfig* config) {
|
||||
app->config = *config;
|
||||
furi_thread_flags_set(furi_thread_get_id(app->dap_thread), DAPThreadEventApplyConfig);
|
||||
furi_thread_flags_set(furi_thread_get_id(app->cdc_thread), CDCThreadEventApplyConfig);
|
||||
}
|
||||
|
||||
DapConfig* dap_app_get_config(DapApp* app) {
|
||||
return &app->config;
|
||||
}
|
||||
|
||||
int32_t dap_link_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
if(furi_hal_usb_is_locked()) {
|
||||
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop);
|
||||
dialog_message_set_text(
|
||||
message,
|
||||
"Disconnect from\nPC or phone to\nuse this function.",
|
||||
3,
|
||||
30,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
dialog_message_set_icon(message, &I_ActiveConnection_50x64, 78, 0);
|
||||
dialog_message_show(dialogs, message);
|
||||
dialog_message_free(message);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// alloc app
|
||||
DapApp* app = dap_app_alloc();
|
||||
app_handle = app;
|
||||
|
||||
furi_thread_start(app->dap_thread);
|
||||
furi_thread_start(app->cdc_thread);
|
||||
furi_thread_start(app->gui_thread);
|
||||
|
||||
// wait until gui thread is finished
|
||||
furi_thread_join(app->gui_thread);
|
||||
|
||||
// send stop event to threads
|
||||
dap_thread_send_stop(app->dap_thread);
|
||||
dap_thread_send_stop(app->cdc_thread);
|
||||
|
||||
// wait for threads to stop
|
||||
furi_thread_join(app->dap_thread);
|
||||
furi_thread_join(app->cdc_thread);
|
||||
|
||||
// free app
|
||||
dap_app_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
55
applications/external/dap_link/dap_link.h
vendored
Normal file
55
applications/external/dap_link/dap_link.h
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
DapModeDisconnected,
|
||||
DapModeSWD,
|
||||
DapModeJTAG,
|
||||
} DapMode;
|
||||
|
||||
typedef enum {
|
||||
DapVersionUnknown,
|
||||
DapVersionV1,
|
||||
DapVersionV2,
|
||||
} DapVersion;
|
||||
|
||||
typedef struct {
|
||||
bool usb_connected;
|
||||
DapMode dap_mode;
|
||||
DapVersion dap_version;
|
||||
uint32_t dap_counter;
|
||||
uint32_t cdc_baudrate;
|
||||
uint32_t cdc_tx_counter;
|
||||
uint32_t cdc_rx_counter;
|
||||
} DapState;
|
||||
|
||||
typedef enum {
|
||||
DapSwdPinsPA7PA6, // Pins 2, 3
|
||||
DapSwdPinsPA14PA13, // Pins 10, 12
|
||||
} DapSwdPins;
|
||||
|
||||
typedef enum {
|
||||
DapUartTypeUSART1, // Pins 13, 14
|
||||
DapUartTypeLPUART1, // Pins 15, 16
|
||||
} DapUartType;
|
||||
|
||||
typedef enum {
|
||||
DapUartTXRXNormal,
|
||||
DapUartTXRXSwap,
|
||||
} DapUartTXRX;
|
||||
|
||||
typedef struct {
|
||||
DapSwdPins swd_pins;
|
||||
DapUartType uart_pins;
|
||||
DapUartTXRX uart_swap;
|
||||
} DapConfig;
|
||||
|
||||
typedef struct DapApp DapApp;
|
||||
|
||||
void dap_app_get_state(DapApp* app, DapState* state);
|
||||
|
||||
const char* dap_app_get_serial(DapApp* app);
|
||||
|
||||
void dap_app_set_config(DapApp* app, DapConfig* config);
|
||||
|
||||
DapConfig* dap_app_get_config(DapApp* app);
|
92
applications/external/dap_link/gui/dap_gui.c
vendored
Normal file
92
applications/external/dap_link/gui/dap_gui.c
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "dap_gui.h"
|
||||
#include "dap_gui_i.h"
|
||||
|
||||
#define DAP_GUI_TICK 250
|
||||
|
||||
static bool dap_gui_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
DapGuiApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool dap_gui_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
DapGuiApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void dap_gui_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
DapGuiApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
DapGuiApp* dap_gui_alloc() {
|
||||
DapGuiApp* app = malloc(sizeof(DapGuiApp));
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&dap_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, dap_gui_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, dap_gui_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, dap_gui_tick_event_callback, DAP_GUI_TICK);
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
app->var_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
DapGuiAppViewVarItemList,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
app->main_view = dap_main_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DapGuiAppViewMainView, dap_main_view_get_view(app->main_view));
|
||||
|
||||
app->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DapGuiAppViewWidget, widget_get_view(app->widget));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, DapSceneMain);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void dap_gui_free(DapGuiApp* app) {
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewVarItemList);
|
||||
variable_item_list_free(app->var_item_list);
|
||||
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewMainView);
|
||||
dap_main_view_free(app->main_view);
|
||||
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DapGuiAppViewWidget);
|
||||
widget_free(app->widget);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t dap_gui_thread(void* arg) {
|
||||
DapGuiApp* app = dap_gui_alloc();
|
||||
app->dap_app = arg;
|
||||
|
||||
notification_message_block(app->notifications, &sequence_display_backlight_enforce_on);
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
notification_message_block(app->notifications, &sequence_display_backlight_enforce_auto);
|
||||
|
||||
dap_gui_free(app);
|
||||
return 0;
|
||||
}
|
4
applications/external/dap_link/gui/dap_gui.h
vendored
Normal file
4
applications/external/dap_link/gui/dap_gui.h
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t dap_gui_thread(void* arg);
|
7
applications/external/dap_link/gui/dap_gui_custom_event.h
vendored
Normal file
7
applications/external/dap_link/gui/dap_gui_custom_event.h
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
DapAppCustomEventConfig,
|
||||
DapAppCustomEventHelp,
|
||||
DapAppCustomEventAbout,
|
||||
} DapAppCustomEvent;
|
34
applications/external/dap_link/gui/dap_gui_i.h
vendored
Normal file
34
applications/external/dap_link/gui/dap_gui_i.h
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include "dap_gui.h"
|
||||
#include "../dap_link.h"
|
||||
#include "scenes/config/dap_scene.h"
|
||||
#include "dap_gui_custom_event.h"
|
||||
#include "views/dap_main_view.h"
|
||||
|
||||
typedef struct {
|
||||
DapApp* dap_app;
|
||||
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
|
||||
VariableItemList* var_item_list;
|
||||
DapMainView* main_view;
|
||||
Widget* widget;
|
||||
} DapGuiApp;
|
||||
|
||||
typedef enum {
|
||||
DapGuiAppViewVarItemList,
|
||||
DapGuiAppViewMainView,
|
||||
DapGuiAppViewWidget,
|
||||
} DapGuiAppView;
|
4
applications/external/dap_link/gui/scenes/config/dap_scene_config.h
vendored
Normal file
4
applications/external/dap_link/gui/scenes/config/dap_scene_config.h
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
ADD_SCENE(dap, main, Main)
|
||||
ADD_SCENE(dap, config, Config)
|
||||
ADD_SCENE(dap, help, Help)
|
||||
ADD_SCENE(dap, about, About)
|
107
applications/external/dap_link/gui/scenes/dap_scene_config.c
vendored
Normal file
107
applications/external/dap_link/gui/scenes/dap_scene_config.c
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
#include "../dap_gui_i.h"
|
||||
|
||||
static const char* swd_pins[] = {[DapSwdPinsPA7PA6] = "2,3", [DapSwdPinsPA14PA13] = "10,12"};
|
||||
static const char* uart_pins[] = {[DapUartTypeUSART1] = "13,14", [DapUartTypeLPUART1] = "15,16"};
|
||||
static const char* uart_swap[] = {[DapUartTXRXNormal] = "No", [DapUartTXRXSwap] = "Yes"};
|
||||
|
||||
static void swd_pins_cb(VariableItem* item) {
|
||||
DapGuiApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, swd_pins[index]);
|
||||
|
||||
DapConfig* config = dap_app_get_config(app->dap_app);
|
||||
config->swd_pins = index;
|
||||
dap_app_set_config(app->dap_app, config);
|
||||
}
|
||||
|
||||
static void uart_pins_cb(VariableItem* item) {
|
||||
DapGuiApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, uart_pins[index]);
|
||||
|
||||
DapConfig* config = dap_app_get_config(app->dap_app);
|
||||
config->uart_pins = index;
|
||||
dap_app_set_config(app->dap_app, config);
|
||||
}
|
||||
|
||||
static void uart_swap_cb(VariableItem* item) {
|
||||
DapGuiApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, uart_swap[index]);
|
||||
|
||||
DapConfig* config = dap_app_get_config(app->dap_app);
|
||||
config->uart_swap = index;
|
||||
dap_app_set_config(app->dap_app, config);
|
||||
}
|
||||
|
||||
static void ok_cb(void* context, uint32_t index) {
|
||||
DapGuiApp* app = context;
|
||||
switch(index) {
|
||||
case 3:
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventHelp);
|
||||
break;
|
||||
case 4:
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventAbout);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dap_scene_config_on_enter(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
VariableItemList* var_item_list = app->var_item_list;
|
||||
VariableItem* item;
|
||||
DapConfig* config = dap_app_get_config(app->dap_app);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "SWC SWD Pins", COUNT_OF(swd_pins), swd_pins_cb, app);
|
||||
variable_item_set_current_value_index(item, config->swd_pins);
|
||||
variable_item_set_current_value_text(item, swd_pins[config->swd_pins]);
|
||||
|
||||
item =
|
||||
variable_item_list_add(var_item_list, "UART Pins", COUNT_OF(uart_pins), uart_pins_cb, app);
|
||||
variable_item_set_current_value_index(item, config->uart_pins);
|
||||
variable_item_set_current_value_text(item, uart_pins[config->uart_pins]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Swap TX RX", COUNT_OF(uart_swap), uart_swap_cb, app);
|
||||
variable_item_set_current_value_index(item, config->uart_swap);
|
||||
variable_item_set_current_value_text(item, uart_swap[config->uart_swap]);
|
||||
|
||||
variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL);
|
||||
variable_item_list_add(var_item_list, "About", 0, NULL, NULL);
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
var_item_list, scene_manager_get_scene_state(app->scene_manager, DapSceneConfig));
|
||||
|
||||
variable_item_list_set_enter_callback(var_item_list, ok_cb, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewVarItemList);
|
||||
}
|
||||
|
||||
bool dap_scene_config_on_event(void* context, SceneManagerEvent event) {
|
||||
DapGuiApp* app = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DapAppCustomEventHelp) {
|
||||
scene_manager_next_scene(app->scene_manager, DapSceneHelp);
|
||||
return true;
|
||||
} else if(event.event == DapAppCustomEventAbout) {
|
||||
scene_manager_next_scene(app->scene_manager, DapSceneAbout);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void dap_scene_config_on_exit(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
DapSceneConfig,
|
||||
variable_item_list_get_selected_item_index(app->var_item_list));
|
||||
variable_item_list_reset(app->var_item_list);
|
||||
}
|
102
applications/external/dap_link/gui/scenes/dap_scene_help.c
vendored
Normal file
102
applications/external/dap_link/gui/scenes/dap_scene_help.c
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include "../dap_gui_i.h"
|
||||
|
||||
void dap_scene_help_on_enter(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
DapConfig* config = dap_app_get_config(app->dap_app);
|
||||
FuriString* string = furi_string_alloc();
|
||||
|
||||
furi_string_cat(string, "CMSIS DAP/DAP Link v2\r\n");
|
||||
furi_string_cat_printf(string, "Serial: %s\r\n", dap_app_get_serial(app->dap_app));
|
||||
furi_string_cat(
|
||||
string,
|
||||
"Pinout:\r\n"
|
||||
"\e#SWD:\r\n");
|
||||
|
||||
switch(config->swd_pins) {
|
||||
case DapSwdPinsPA7PA6:
|
||||
furi_string_cat(
|
||||
string,
|
||||
" SWC: 2 [A7]\r\n"
|
||||
" SWD: 3 [A6]\r\n");
|
||||
break;
|
||||
case DapSwdPinsPA14PA13:
|
||||
furi_string_cat(
|
||||
string,
|
||||
" SWC: 10 [SWC]\r\n"
|
||||
" SWD: 12 [SIO]\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_cat(string, "\e#JTAG:\r\n");
|
||||
switch(config->swd_pins) {
|
||||
case DapSwdPinsPA7PA6:
|
||||
furi_string_cat(
|
||||
string,
|
||||
" TCK: 2 [A7]\r\n"
|
||||
" TMS: 3 [A6]\r\n"
|
||||
" RST: 4 [A4]\r\n"
|
||||
" TDO: 5 [B3]\r\n"
|
||||
" TDI: 6 [B2]\r\n");
|
||||
break;
|
||||
case DapSwdPinsPA14PA13:
|
||||
furi_string_cat(
|
||||
string,
|
||||
" RST: 4 [A4]\r\n"
|
||||
" TDO: 5 [B3]\r\n"
|
||||
" TDI: 6 [B2]\r\n"
|
||||
" TCK: 10 [SWC]\r\n"
|
||||
" TMS: 12 [SIO]\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_cat(string, "\e#UART:\r\n");
|
||||
switch(config->uart_pins) {
|
||||
case DapUartTypeUSART1:
|
||||
if(config->uart_swap == DapUartTXRXNormal) {
|
||||
furi_string_cat(
|
||||
string,
|
||||
" TX: 13 [TX]\r\n"
|
||||
" RX: 14 [RX]\r\n");
|
||||
} else {
|
||||
furi_string_cat(
|
||||
string,
|
||||
" RX: 13 [TX]\r\n"
|
||||
" TX: 14 [RX]\r\n");
|
||||
}
|
||||
break;
|
||||
case DapUartTypeLPUART1:
|
||||
if(config->uart_swap == DapUartTXRXNormal) {
|
||||
furi_string_cat(
|
||||
string,
|
||||
" TX: 15 [C1]\r\n"
|
||||
" RX: 16 [C0]\r\n");
|
||||
} else {
|
||||
furi_string_cat(
|
||||
string,
|
||||
" RX: 15 [C1]\r\n"
|
||||
" TX: 16 [C0]\r\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
widget_add_text_scroll_element(app->widget, 0, 0, 128, 64, furi_string_get_cstr(string));
|
||||
furi_string_free(string);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewWidget);
|
||||
}
|
||||
|
||||
bool dap_scene_help_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void dap_scene_help_on_exit(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
154
applications/external/dap_link/gui/scenes/dap_scene_main.c
vendored
Normal file
154
applications/external/dap_link/gui/scenes/dap_scene_main.c
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
#include "../dap_gui_i.h"
|
||||
#include "../../dap_link.h"
|
||||
|
||||
typedef struct {
|
||||
DapState dap_state;
|
||||
bool dap_active;
|
||||
bool tx_active;
|
||||
bool rx_active;
|
||||
} DapSceneMainState;
|
||||
|
||||
static bool process_dap_state(DapGuiApp* app) {
|
||||
DapSceneMainState* state =
|
||||
(DapSceneMainState*)scene_manager_get_scene_state(app->scene_manager, DapSceneMain);
|
||||
if(state == NULL) return true;
|
||||
|
||||
DapState* prev_state = &state->dap_state;
|
||||
DapState next_state;
|
||||
dap_app_get_state(app->dap_app, &next_state);
|
||||
bool need_to_update = false;
|
||||
|
||||
if(prev_state->dap_mode != next_state.dap_mode) {
|
||||
switch(next_state.dap_mode) {
|
||||
case DapModeDisconnected:
|
||||
dap_main_view_set_mode(app->main_view, DapMainViewModeDisconnected);
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
break;
|
||||
case DapModeSWD:
|
||||
dap_main_view_set_mode(app->main_view, DapMainViewModeSWD);
|
||||
notification_message(app->notifications, &sequence_blink_start_blue);
|
||||
break;
|
||||
case DapModeJTAG:
|
||||
dap_main_view_set_mode(app->main_view, DapMainViewModeJTAG);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
break;
|
||||
}
|
||||
need_to_update = true;
|
||||
}
|
||||
|
||||
if(prev_state->dap_version != next_state.dap_version) {
|
||||
switch(next_state.dap_version) {
|
||||
case DapVersionUnknown:
|
||||
dap_main_view_set_version(app->main_view, DapMainViewVersionUnknown);
|
||||
break;
|
||||
case DapVersionV1:
|
||||
dap_main_view_set_version(app->main_view, DapMainViewVersionV1);
|
||||
break;
|
||||
case DapVersionV2:
|
||||
dap_main_view_set_version(app->main_view, DapMainViewVersionV2);
|
||||
break;
|
||||
}
|
||||
need_to_update = true;
|
||||
}
|
||||
|
||||
if(prev_state->usb_connected != next_state.usb_connected) {
|
||||
dap_main_view_set_usb_connected(app->main_view, next_state.usb_connected);
|
||||
need_to_update = true;
|
||||
}
|
||||
|
||||
if(prev_state->dap_counter != next_state.dap_counter) {
|
||||
if(!state->dap_active) {
|
||||
state->dap_active = true;
|
||||
dap_main_view_set_dap(app->main_view, state->dap_active);
|
||||
need_to_update = true;
|
||||
}
|
||||
} else {
|
||||
if(state->dap_active) {
|
||||
state->dap_active = false;
|
||||
dap_main_view_set_dap(app->main_view, state->dap_active);
|
||||
need_to_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(prev_state->cdc_baudrate != next_state.cdc_baudrate) {
|
||||
dap_main_view_set_baudrate(app->main_view, next_state.cdc_baudrate);
|
||||
need_to_update = true;
|
||||
}
|
||||
|
||||
if(prev_state->cdc_tx_counter != next_state.cdc_tx_counter) {
|
||||
if(!state->tx_active) {
|
||||
state->tx_active = true;
|
||||
dap_main_view_set_tx(app->main_view, state->tx_active);
|
||||
need_to_update = true;
|
||||
notification_message(app->notifications, &sequence_blink_start_red);
|
||||
}
|
||||
} else {
|
||||
if(state->tx_active) {
|
||||
state->tx_active = false;
|
||||
dap_main_view_set_tx(app->main_view, state->tx_active);
|
||||
need_to_update = true;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
}
|
||||
|
||||
if(prev_state->cdc_rx_counter != next_state.cdc_rx_counter) {
|
||||
if(!state->rx_active) {
|
||||
state->rx_active = true;
|
||||
dap_main_view_set_rx(app->main_view, state->rx_active);
|
||||
need_to_update = true;
|
||||
notification_message(app->notifications, &sequence_blink_start_green);
|
||||
}
|
||||
} else {
|
||||
if(state->rx_active) {
|
||||
state->rx_active = false;
|
||||
dap_main_view_set_rx(app->main_view, state->rx_active);
|
||||
need_to_update = true;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
}
|
||||
|
||||
if(need_to_update) {
|
||||
dap_main_view_update(app->main_view);
|
||||
}
|
||||
|
||||
*prev_state = next_state;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dap_scene_main_on_left(void* context) {
|
||||
DapGuiApp* app = (DapGuiApp*)context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DapAppCustomEventConfig);
|
||||
}
|
||||
|
||||
void dap_scene_main_on_enter(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
DapSceneMainState* state = malloc(sizeof(DapSceneMainState));
|
||||
dap_main_view_set_left_callback(app->main_view, dap_scene_main_on_left, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DapGuiAppViewMainView);
|
||||
scene_manager_set_scene_state(app->scene_manager, DapSceneMain, (uint32_t)state);
|
||||
}
|
||||
|
||||
bool dap_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
DapGuiApp* app = context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DapAppCustomEventConfig) {
|
||||
scene_manager_next_scene(app->scene_manager, DapSceneConfig);
|
||||
return true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
return process_dap_state(app);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void dap_scene_main_on_exit(void* context) {
|
||||
DapGuiApp* app = context;
|
||||
DapSceneMainState* state =
|
||||
(DapSceneMainState*)scene_manager_get_scene_state(app->scene_manager, DapSceneMain);
|
||||
scene_manager_set_scene_state(app->scene_manager, DapSceneMain, (uint32_t)NULL);
|
||||
FURI_SW_MEMBARRIER();
|
||||
free(state);
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
189
applications/external/dap_link/gui/views/dap_main_view.c
vendored
Normal file
189
applications/external/dap_link/gui/views/dap_main_view.c
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
#include "dap_main_view.h"
|
||||
#include "dap_link_icons.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
// extern const Icon I_ArrowDownEmpty_12x18;
|
||||
// extern const Icon I_ArrowDownFilled_12x18;
|
||||
// extern const Icon I_ArrowUpEmpty_12x18;
|
||||
// extern const Icon I_ArrowUpFilled_12x18;
|
||||
|
||||
struct DapMainView {
|
||||
View* view;
|
||||
DapMainViewButtonCallback cb_left;
|
||||
void* cb_context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
DapMainViewMode mode;
|
||||
DapMainViewVersion version;
|
||||
bool usb_connected;
|
||||
uint32_t baudrate;
|
||||
bool dap_active;
|
||||
bool tx_active;
|
||||
bool rx_active;
|
||||
} DapMainViewModel;
|
||||
|
||||
static void dap_main_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
DapMainViewModel* model = _model;
|
||||
UNUSED(model);
|
||||
canvas_clear(canvas);
|
||||
elements_button_left(canvas, "Config");
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, 0, 127, 11);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
|
||||
const char* header_string;
|
||||
if(model->usb_connected) {
|
||||
if(model->version == DapMainViewVersionV1) {
|
||||
header_string = "DAP Link V1 Connected";
|
||||
} else if(model->version == DapMainViewVersionV2) {
|
||||
header_string = "DAP Link V2 Connected";
|
||||
} else {
|
||||
header_string = "DAP Link Connected";
|
||||
}
|
||||
} else {
|
||||
header_string = "DAP Link";
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 9, AlignCenter, AlignBottom, header_string);
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(model->dap_active) {
|
||||
canvas_draw_icon(canvas, 14, 16, &I_ArrowUpFilled_12x18);
|
||||
canvas_draw_icon(canvas, 28, 16, &I_ArrowDownFilled_12x18);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 14, 16, &I_ArrowUpEmpty_12x18);
|
||||
canvas_draw_icon(canvas, 28, 16, &I_ArrowDownEmpty_12x18);
|
||||
}
|
||||
|
||||
switch(model->mode) {
|
||||
case DapMainViewModeDisconnected:
|
||||
canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "----");
|
||||
break;
|
||||
case DapMainViewModeSWD:
|
||||
canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "SWD");
|
||||
break;
|
||||
case DapMainViewModeJTAG:
|
||||
canvas_draw_str_aligned(canvas, 26, 38, AlignCenter, AlignTop, "JTAG");
|
||||
break;
|
||||
}
|
||||
|
||||
if(model->tx_active) {
|
||||
canvas_draw_icon(canvas, 87, 16, &I_ArrowUpFilled_12x18);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 87, 16, &I_ArrowUpEmpty_12x18);
|
||||
}
|
||||
|
||||
if(model->rx_active) {
|
||||
canvas_draw_icon(canvas, 101, 16, &I_ArrowDownFilled_12x18);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 101, 16, &I_ArrowDownEmpty_12x18);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 100, 38, AlignCenter, AlignTop, "UART");
|
||||
|
||||
canvas_draw_line(canvas, 44, 52, 123, 52);
|
||||
if(model->baudrate == 0) {
|
||||
canvas_draw_str(canvas, 45, 62, "Baud: ????");
|
||||
} else {
|
||||
char baudrate_str[18];
|
||||
snprintf(baudrate_str, 18, "Baud: %lu", model->baudrate);
|
||||
canvas_draw_str(canvas, 45, 62, baudrate_str);
|
||||
}
|
||||
}
|
||||
|
||||
static bool dap_main_view_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
DapMainView* dap_main_view = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(dap_main_view->cb_left) {
|
||||
dap_main_view->cb_left(dap_main_view->cb_context);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
DapMainView* dap_main_view_alloc() {
|
||||
DapMainView* dap_main_view = malloc(sizeof(DapMainView));
|
||||
|
||||
dap_main_view->view = view_alloc();
|
||||
view_allocate_model(dap_main_view->view, ViewModelTypeLocking, sizeof(DapMainViewModel));
|
||||
view_set_context(dap_main_view->view, dap_main_view);
|
||||
view_set_draw_callback(dap_main_view->view, dap_main_view_draw_callback);
|
||||
view_set_input_callback(dap_main_view->view, dap_main_view_input_callback);
|
||||
return dap_main_view;
|
||||
}
|
||||
|
||||
void dap_main_view_free(DapMainView* dap_main_view) {
|
||||
view_free(dap_main_view->view);
|
||||
free(dap_main_view);
|
||||
}
|
||||
|
||||
View* dap_main_view_get_view(DapMainView* dap_main_view) {
|
||||
return dap_main_view->view;
|
||||
}
|
||||
|
||||
void dap_main_view_set_left_callback(
|
||||
DapMainView* dap_main_view,
|
||||
DapMainViewButtonCallback callback,
|
||||
void* context) {
|
||||
with_view_model(
|
||||
dap_main_view->view,
|
||||
DapMainViewModel * model,
|
||||
{
|
||||
UNUSED(model);
|
||||
dap_main_view->cb_left = callback;
|
||||
dap_main_view->cb_context = context;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void dap_main_view_set_mode(DapMainView* dap_main_view, DapMainViewMode mode) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->mode = mode; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_set_dap(DapMainView* dap_main_view, bool active) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->dap_active = active; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_set_tx(DapMainView* dap_main_view, bool active) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->tx_active = active; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_set_rx(DapMainView* dap_main_view, bool active) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->rx_active = active; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_set_baudrate(DapMainView* dap_main_view, uint32_t baudrate) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->baudrate = baudrate; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_update(DapMainView* dap_main_view) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { UNUSED(model); }, true);
|
||||
}
|
||||
|
||||
void dap_main_view_set_version(DapMainView* dap_main_view, DapMainViewVersion version) {
|
||||
with_view_model(
|
||||
dap_main_view->view, DapMainViewModel * model, { model->version = version; }, false);
|
||||
}
|
||||
|
||||
void dap_main_view_set_usb_connected(DapMainView* dap_main_view, bool connected) {
|
||||
with_view_model(
|
||||
dap_main_view->view,
|
||||
DapMainViewModel * model,
|
||||
{ model->usb_connected = connected; },
|
||||
false);
|
||||
}
|
45
applications/external/dap_link/gui/views/dap_main_view.h
vendored
Normal file
45
applications/external/dap_link/gui/views/dap_main_view.h
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct DapMainView DapMainView;
|
||||
|
||||
typedef void (*DapMainViewButtonCallback)(void* context);
|
||||
|
||||
typedef enum {
|
||||
DapMainViewVersionUnknown,
|
||||
DapMainViewVersionV1,
|
||||
DapMainViewVersionV2,
|
||||
} DapMainViewVersion;
|
||||
|
||||
typedef enum {
|
||||
DapMainViewModeDisconnected,
|
||||
DapMainViewModeSWD,
|
||||
DapMainViewModeJTAG,
|
||||
} DapMainViewMode;
|
||||
|
||||
DapMainView* dap_main_view_alloc();
|
||||
|
||||
void dap_main_view_free(DapMainView* dap_main_view);
|
||||
|
||||
View* dap_main_view_get_view(DapMainView* dap_main_view);
|
||||
|
||||
void dap_main_view_set_left_callback(
|
||||
DapMainView* dap_main_view,
|
||||
DapMainViewButtonCallback callback,
|
||||
void* context);
|
||||
|
||||
void dap_main_view_set_mode(DapMainView* dap_main_view, DapMainViewMode mode);
|
||||
|
||||
void dap_main_view_set_version(DapMainView* dap_main_view, DapMainViewVersion version);
|
||||
|
||||
void dap_main_view_set_dap(DapMainView* dap_main_view, bool active);
|
||||
|
||||
void dap_main_view_set_tx(DapMainView* dap_main_view, bool active);
|
||||
|
||||
void dap_main_view_set_rx(DapMainView* dap_main_view, bool active);
|
||||
|
||||
void dap_main_view_set_usb_connected(DapMainView* dap_main_view, bool connected);
|
||||
|
||||
void dap_main_view_set_baudrate(DapMainView* dap_main_view, uint32_t baudrate);
|
||||
|
||||
void dap_main_view_update(DapMainView* dap_main_view);
|
BIN
applications/external/dap_link/icons/ActiveConnection_50x64.png
vendored
Normal file
BIN
applications/external/dap_link/icons/ActiveConnection_50x64.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
applications/external/dap_link/icons/ArrowUpFilled_12x18.png
vendored
Normal file
BIN
applications/external/dap_link/icons/ArrowUpFilled_12x18.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 173 B |
|
@ -1,10 +1,10 @@
|
|||
App(
|
||||
appid="hid_usb",
|
||||
name="Remote",
|
||||
name="USB Keyboard & Mouse",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="hid_usb_app",
|
||||
stack_size=1 * 1024,
|
||||
fap_category="USB",
|
||||
fap_category="Misc",
|
||||
fap_icon="hid_usb_10px.png",
|
||||
fap_icon_assets="assets",
|
||||
fap_icon_assets_symbol="hid",
|
||||
|
@ -13,11 +13,11 @@ App(
|
|||
|
||||
App(
|
||||
appid="hid_ble",
|
||||
name="Remote",
|
||||
name="Bluetooth Remote",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="hid_ble_app",
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Bluetooth",
|
||||
fap_category="Misc",
|
||||
fap_icon="hid_ble_10px.png",
|
||||
fap_icon_assets="assets",
|
||||
fap_icon_assets_symbol="hid",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
App(
|
||||
appid="music_player",
|
||||
appid="Music_Player",
|
||||
name="Music Player",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="music_player_app",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
App(
|
||||
appid="signal_generator",
|
||||
appid="Signal_Generator",
|
||||
name="Signal Generator",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="signal_gen_app",
|
||||
|
|
Loading…
Reference in a new issue