mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 20:49:49 +04:00
Merge branch 'fz-dev' into dev
This commit is contained in:
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
@@ -11,5 +11,8 @@
|
|||||||
"augustocdias.tasks-shell-input"
|
"augustocdias.tasks-shell-input"
|
||||||
],
|
],
|
||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
"unwantedRecommendations": []
|
"unwantedRecommendations": [
|
||||||
|
"twxs.cmake",
|
||||||
|
"ms-vscode.cmake-tools"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="accessor",
|
appid="accessor",
|
||||||
name="Accessor",
|
name="Accessor",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="accessor_app",
|
entry_point="accessor_app",
|
||||||
cdefines=["APP_ACCESSOR"],
|
cdefines=["APP_ACCESSOR"],
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "bt_carrier_test.h"
|
#include "bt_carrier_test.h"
|
||||||
#include "bt_test.h"
|
#include "bt_test.h"
|
||||||
#include "bt_test_types.h"
|
#include "bt_test_types.h"
|
||||||
#include "furi_hal_bt.h"
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
struct BtCarrierTest {
|
struct BtCarrierTest {
|
||||||
BtTest* bt_test;
|
BtTest* bt_test;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "bt_packet_test.h"
|
#include "bt_packet_test.h"
|
||||||
#include "bt_test.h"
|
#include "bt_test.h"
|
||||||
#include "bt_test_types.h"
|
#include "bt_test_types.h"
|
||||||
#include "furi_hal_bt.h"
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
struct BtPacketTest {
|
struct BtPacketTest {
|
||||||
BtTest* bt_test;
|
BtTest* bt_test;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#include <file_browser_test_icons.h>
|
|
||||||
#include "file_browser_app_i.h"
|
#include "file_browser_app_i.h"
|
||||||
#include "gui/modules/file_browser.h"
|
#include <file_browser_test_icons.h>
|
||||||
#include <furi.h>
|
|
||||||
#include <furi_hal.h>
|
#include <gui/modules/file_browser.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <lib/toolbox/path.h>
|
#include <lib/toolbox/path.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
static bool file_browser_app_custom_event_callback(void* context, uint32_t event) {
|
static bool file_browser_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="lfrfid_debug",
|
appid="lfrfid_debug",
|
||||||
name="LF-RFID Debug",
|
name="LF-RFID Debug",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="lfrfid_debug_app",
|
entry_point="lfrfid_debug_app",
|
||||||
requires=[
|
requires=[
|
||||||
"gui",
|
"gui",
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ static void test_rpc_setup(void) {
|
|||||||
}
|
}
|
||||||
furi_check(rpc_session[0].session);
|
furi_check(rpc_session[0].session);
|
||||||
|
|
||||||
rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
|
rpc_session[0].output_stream = furi_stream_buffer_alloc(4096, 1);
|
||||||
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
||||||
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
||||||
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
||||||
|
|||||||
44
applications/examples/example_thermo/README.md
Normal file
44
applications/examples/example_thermo/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# 1-Wire Thermometer
|
||||||
|
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
|
||||||
|
It also covers basic GUI, input handling, threads and localisation.
|
||||||
|
|
||||||
|
## Electrical connections
|
||||||
|
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
|
||||||
|
| DS18B20 | Flipper |
|
||||||
|
| :-----: | :-----: |
|
||||||
|
| VDD | 9 |
|
||||||
|
| GND | 18 |
|
||||||
|
| DQ | 17 |
|
||||||
|
|
||||||
|
*NOTE 1*: GND is also available on pins 8 and 11.
|
||||||
|
|
||||||
|
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
|
||||||
|
|
||||||
|
## Launching the application
|
||||||
|
In order to launch this demo, follow the steps below:
|
||||||
|
1. Make sure your Flipper has an SD card installed.
|
||||||
|
2. Connect your Flipper to the computer via a USB cable.
|
||||||
|
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice.
|
||||||
|
|
||||||
|
## Changing the data pin
|
||||||
|
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Possible GPIO pin choices:
|
||||||
|
- gpio_ext_pc0
|
||||||
|
- gpio_ext_pc1
|
||||||
|
- gpio_ext_pc3
|
||||||
|
- gpio_ext_pb2
|
||||||
|
- gpio_ext_pb3
|
||||||
|
- gpio_ext_pa4
|
||||||
|
- gpio_ext_pa6
|
||||||
|
- gpio_ext_pa7
|
||||||
|
- ibutton_gpio
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define THERMO_GPIO_PIN (ibutton_gpio)
|
||||||
|
```
|
||||||
|
Do not forget about the external pull-up resistor as these pins do not have one built-in.
|
||||||
|
|
||||||
|
With the changes been made, recompile and launch the application again.
|
||||||
|
The on-screen text should reflect it by asking to connect the thermometer to another pin.
|
||||||
10
applications/examples/example_thermo/application.fam
Normal file
10
applications/examples/example_thermo/application.fam
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
App(
|
||||||
|
appid="example_thermo",
|
||||||
|
name="Example: Thermometer",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_thermo_main",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_icon="example_thermo_10px.png",
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
||||||
356
applications/examples/example_thermo/example_thermo.c
Normal file
356
applications/examples/example_thermo/example_thermo.c
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* This file contains an example application that reads and displays
|
||||||
|
* the temperature from a DS18B20 1-wire thermometer.
|
||||||
|
*
|
||||||
|
* It also covers basic GUI, input handling, threads and localisation.
|
||||||
|
*
|
||||||
|
* References:
|
||||||
|
* [1] DS18B20 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view_port.h>
|
||||||
|
|
||||||
|
#include <core/thread.h>
|
||||||
|
#include <core/kernel.h>
|
||||||
|
|
||||||
|
#include <locale/locale.h>
|
||||||
|
|
||||||
|
#include <one_wire/maxim_crc.h>
|
||||||
|
#include <one_wire/one_wire_host.h>
|
||||||
|
|
||||||
|
#define UPDATE_PERIOD_MS 1000UL
|
||||||
|
#define TEXT_STORE_SIZE 64U
|
||||||
|
|
||||||
|
#define DS18B20_CMD_CONVERT 0x44U
|
||||||
|
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
|
||||||
|
|
||||||
|
#define DS18B20_CFG_RESOLUTION_POS 5U
|
||||||
|
#define DS18B20_CFG_RESOLUTION_MASK 0x03U
|
||||||
|
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
||||||
|
|
||||||
|
#define DS18B20_SIGN_MASK 0xf0U
|
||||||
|
|
||||||
|
/* Possible GPIO pin choices:
|
||||||
|
- gpio_ext_pc0
|
||||||
|
- gpio_ext_pc1
|
||||||
|
- gpio_ext_pc3
|
||||||
|
- gpio_ext_pb2
|
||||||
|
- gpio_ext_pb3
|
||||||
|
- gpio_ext_pa4
|
||||||
|
- gpio_ext_pa6
|
||||||
|
- gpio_ext_pa7
|
||||||
|
- ibutton_gpio
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define THERMO_GPIO_PIN (ibutton_gpio)
|
||||||
|
|
||||||
|
/* Flags which the reader thread responds to */
|
||||||
|
typedef enum {
|
||||||
|
ReaderThreadFlagExit = 1,
|
||||||
|
} ReaderThreadFlag;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint8_t temp_lsb; /* Least significant byte of the temperature */
|
||||||
|
uint8_t temp_msb; /* Most significant byte of the temperature */
|
||||||
|
uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */
|
||||||
|
uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */
|
||||||
|
uint8_t config; /* Configuration register */
|
||||||
|
uint8_t reserved[3]; /* Not used */
|
||||||
|
uint8_t crc; /* CRC checksum for error detection */
|
||||||
|
} fields;
|
||||||
|
uint8_t bytes[9];
|
||||||
|
} DS18B20Scratchpad;
|
||||||
|
|
||||||
|
/* Application context structure */
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
ViewPort* view_port;
|
||||||
|
FuriThread* reader_thread;
|
||||||
|
FuriMessageQueue* event_queue;
|
||||||
|
OneWireHost* onewire;
|
||||||
|
float temp_celsius;
|
||||||
|
bool has_device;
|
||||||
|
} ExampleThermoContext;
|
||||||
|
|
||||||
|
/*************** 1-Wire Communication and Processing *****************/
|
||||||
|
|
||||||
|
/* Commands the thermometer to begin measuring the temperature. */
|
||||||
|
static void example_thermo_request_temperature(ExampleThermoContext* context) {
|
||||||
|
OneWireHost* onewire = context->onewire;
|
||||||
|
|
||||||
|
/* All 1-wire transactions must happen in a critical section, i.e
|
||||||
|
not interrupted by other threads. */
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
do {
|
||||||
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
|
if(!onewire_host_reset(onewire)) break;
|
||||||
|
/* After the reset, a ROM operation must follow.
|
||||||
|
If there is only one device connected, the "Skip ROM" command is most appropriate
|
||||||
|
(it can also be used to address all of the connected devices in some cases).*/
|
||||||
|
onewire_host_skip(onewire);
|
||||||
|
/* After the ROM operation, a device-specific command is issued.
|
||||||
|
In this case, it's a request to start measuring the temperature. */
|
||||||
|
onewire_host_write(onewire, DS18B20_CMD_CONVERT);
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
context->has_device = success;
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads the measured temperature from the thermometer. */
|
||||||
|
static void example_thermo_read_temperature(ExampleThermoContext* context) {
|
||||||
|
/* If there was no device detected, don't try to read the temperature */
|
||||||
|
if(!context->has_device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OneWireHost* onewire = context->onewire;
|
||||||
|
|
||||||
|
/* All 1-wire transactions must happen in a critical section, i.e
|
||||||
|
not interrupted by other threads. */
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
DS18B20Scratchpad buf;
|
||||||
|
|
||||||
|
/* Attempt reading the temperature 10 times before giving up */
|
||||||
|
size_t attempts_left = 10;
|
||||||
|
do {
|
||||||
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
|
if(!onewire_host_reset(onewire)) continue;
|
||||||
|
|
||||||
|
/* After the reset, a ROM operation must follow.
|
||||||
|
If there is only one device connected, the "Skip ROM" command is most appropriate
|
||||||
|
(it can also be used to address all of the connected devices in some cases).*/
|
||||||
|
onewire_host_skip(onewire);
|
||||||
|
|
||||||
|
/* After the ROM operation, a device-specific command is issued.
|
||||||
|
This time, it will be the "Read Scratchpad" command which will
|
||||||
|
prepare the device's internal buffer memory for reading. */
|
||||||
|
onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD);
|
||||||
|
|
||||||
|
/* The actual reading happens here. A total of 9 bytes is read. */
|
||||||
|
onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes));
|
||||||
|
|
||||||
|
/* Calculate the checksum and compare it with one provided by the device. */
|
||||||
|
const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT);
|
||||||
|
|
||||||
|
/* Checksums match, exit the loop */
|
||||||
|
if(crc == buf.fields.crc) break;
|
||||||
|
|
||||||
|
} while(--attempts_left);
|
||||||
|
|
||||||
|
if(attempts_left == 0) break;
|
||||||
|
|
||||||
|
/* Get the measurement resolution from the configuration register. (See [1] page 9) */
|
||||||
|
const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) &
|
||||||
|
DS18B20_CFG_RESOLUTION_MASK;
|
||||||
|
|
||||||
|
/* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */
|
||||||
|
const uint8_t decimal_mask =
|
||||||
|
(DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) &
|
||||||
|
DS18B20_DECIMAL_PART_MASK;
|
||||||
|
|
||||||
|
/* Get the integer and decimal part of the temperature (See [1] page 6) */
|
||||||
|
const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U);
|
||||||
|
const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask;
|
||||||
|
|
||||||
|
/* Calculate the sign of the temperature (See [1] page 6) */
|
||||||
|
const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0;
|
||||||
|
|
||||||
|
/* Combine the integer and decimal part together */
|
||||||
|
const float temp_celsius_abs = integer_part + decimal_part / 16.f;
|
||||||
|
|
||||||
|
/* Set the appropriate sign */
|
||||||
|
context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs;
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
context->has_device = success;
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */
|
||||||
|
static int32_t example_thermo_reader_thread_callback(void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
/* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */
|
||||||
|
example_thermo_request_temperature(context);
|
||||||
|
|
||||||
|
/* Wait for the measurement to finish. At the same time wait for an exit signal. */
|
||||||
|
const uint32_t flags =
|
||||||
|
furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS);
|
||||||
|
|
||||||
|
/* If an exit signal was received, return from this thread. */
|
||||||
|
if(flags != (unsigned)FuriFlagErrorTimeout) break;
|
||||||
|
|
||||||
|
/* The measurement is now ready, read it from the termometer. */
|
||||||
|
example_thermo_read_temperature(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************** GUI, Input and Main Loop *****************/
|
||||||
|
|
||||||
|
/* Draw the GUI of the application. The screen is completely redrawn during each call. */
|
||||||
|
static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
char text_store[TEXT_STORE_SIZE];
|
||||||
|
const size_t middle_x = canvas_width(canvas) / 2U;
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo");
|
||||||
|
canvas_draw_line(canvas, 0, 16, 128, 16);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer");
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
text_store,
|
||||||
|
TEXT_STORE_SIZE,
|
||||||
|
"to GPIO pin %ld",
|
||||||
|
furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN));
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontKeyboard);
|
||||||
|
|
||||||
|
if(context->has_device) {
|
||||||
|
float temp;
|
||||||
|
char temp_units;
|
||||||
|
|
||||||
|
/* The applicaton is locale-aware.
|
||||||
|
Change Settings->System->Units to check it out. */
|
||||||
|
switch(locale_get_measurement_unit()) {
|
||||||
|
case LocaleMeasurementUnitsMetric:
|
||||||
|
temp = context->temp_celsius;
|
||||||
|
temp_units = 'C';
|
||||||
|
break;
|
||||||
|
case LocaleMeasurementUnitsImperial:
|
||||||
|
temp = locale_celsius_to_fahrenheit(context->temp_celsius);
|
||||||
|
temp_units = 'F';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_crash("Illegal measurement units");
|
||||||
|
}
|
||||||
|
/* If a reading is available, display it */
|
||||||
|
snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units);
|
||||||
|
} else {
|
||||||
|
/* Or show a message that no data is available */
|
||||||
|
strncpy(text_store, "-- No data --", TEXT_STORE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called from the GUI thread. All it does is put the event
|
||||||
|
into the application's queue so it can be processed later. */
|
||||||
|
static void example_thermo_input_callback(InputEvent* event, void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
furi_message_queue_put(context->event_queue, event, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Starts the reader thread and handles the input */
|
||||||
|
static void example_thermo_run(ExampleThermoContext* context) {
|
||||||
|
/* Configure the hardware in host mode */
|
||||||
|
onewire_host_start(context->onewire);
|
||||||
|
|
||||||
|
/* Start the reader thread. It will talk to the thermometer in the background. */
|
||||||
|
furi_thread_start(context->reader_thread);
|
||||||
|
|
||||||
|
/* An endless loop which handles the input*/
|
||||||
|
for(bool is_running = true; is_running;) {
|
||||||
|
InputEvent event;
|
||||||
|
/* Wait for an input event. Input events come from the GUI thread via a callback. */
|
||||||
|
const FuriStatus status =
|
||||||
|
furi_message_queue_get(context->event_queue, &event, FuriWaitForever);
|
||||||
|
|
||||||
|
/* This application is only interested in short button presses. */
|
||||||
|
if((status != FuriStatusOk) || (event.type != InputTypeShort)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the user presses the "Back" button, break the loop and exit the application. */
|
||||||
|
if(event.key == InputKeyBack) {
|
||||||
|
is_running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal the reader thread to cease operation and exit */
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit);
|
||||||
|
|
||||||
|
/* Wait for the reader thread to finish */
|
||||||
|
furi_thread_join(context->reader_thread);
|
||||||
|
|
||||||
|
/* Reset the hardware */
|
||||||
|
onewire_host_stop(context->onewire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************** Initialisation & startup *****************************/
|
||||||
|
|
||||||
|
/* Allocate the memory and initialise the variables */
|
||||||
|
static ExampleThermoContext* example_thermo_context_alloc() {
|
||||||
|
ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext));
|
||||||
|
|
||||||
|
context->view_port = view_port_alloc();
|
||||||
|
view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context);
|
||||||
|
view_port_input_callback_set(context->view_port, example_thermo_input_callback, context);
|
||||||
|
|
||||||
|
context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||||
|
|
||||||
|
context->reader_thread = furi_thread_alloc();
|
||||||
|
furi_thread_set_stack_size(context->reader_thread, 1024U);
|
||||||
|
furi_thread_set_context(context->reader_thread, context);
|
||||||
|
furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback);
|
||||||
|
|
||||||
|
context->gui = furi_record_open(RECORD_GUI);
|
||||||
|
gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
|
context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the unused resources and deallocate memory */
|
||||||
|
static void example_thermo_context_free(ExampleThermoContext* context) {
|
||||||
|
view_port_enabled_set(context->view_port, false);
|
||||||
|
gui_remove_view_port(context->gui, context->view_port);
|
||||||
|
|
||||||
|
onewire_host_free(context->onewire);
|
||||||
|
furi_thread_free(context->reader_thread);
|
||||||
|
furi_message_queue_free(context->event_queue);
|
||||||
|
view_port_free(context->view_port);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The application's entry point. Execution starts from here. */
|
||||||
|
int32_t example_thermo_main(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
/* Allocate all of the necessary structures */
|
||||||
|
ExampleThermoContext* context = example_thermo_context_alloc();
|
||||||
|
|
||||||
|
/* Start the applicaton's main loop. It won't return until the application was requested to exit. */
|
||||||
|
example_thermo_run(context);
|
||||||
|
|
||||||
|
/* Release all unneeded resources */
|
||||||
|
example_thermo_context_free(context);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
applications/examples/example_thermo/example_thermo_10px.png
Normal file
BIN
applications/examples/example_thermo/example_thermo_10px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
@@ -1,10 +1,11 @@
|
|||||||
#include <archive/views/archive_browser_view.h>
|
|
||||||
#include "archive_files.h"
|
#include "archive_files.h"
|
||||||
#include "archive_apps.h"
|
#include "archive_apps.h"
|
||||||
#include "archive_browser.h"
|
#include "archive_browser.h"
|
||||||
|
#include "../views/archive_browser_view.h"
|
||||||
|
|
||||||
#include <core/common_defines.h>
|
#include <core/common_defines.h>
|
||||||
#include <core/log.h>
|
#include <core/log.h>
|
||||||
#include "gui/modules/file_browser_worker.h"
|
#include <gui/modules/file_browser_worker.h>
|
||||||
#include <fap_loader/fap_loader_app.h>
|
#include <fap_loader/fap_loader_app.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../helpers/archive_files.h"
|
||||||
|
#include "../helpers/archive_favorites.h"
|
||||||
|
|
||||||
#include <gui/gui_i.h>
|
#include <gui/gui_i.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <gui/canvas.h>
|
#include <gui/canvas.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <furi.h>
|
#include <gui/modules/file_browser_worker.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include "../helpers/archive_files.h"
|
#include <furi.h>
|
||||||
#include "../helpers/archive_menu.h"
|
|
||||||
#include "../helpers/archive_favorites.h"
|
|
||||||
#include "gui/modules/file_browser_worker.h"
|
|
||||||
|
|
||||||
#define MAX_LEN_PX 110
|
#define MAX_LEN_PX 110
|
||||||
#define MAX_NAME_LEN 255
|
#define MAX_NAME_LEN 255
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "../bad_usb_app_i.h"
|
#include "../bad_usb_app_i.h"
|
||||||
#include "furi_hal_power.h"
|
#include <furi_hal_power.h>
|
||||||
#include "furi_hal_usb.h"
|
#include <furi_hal_usb.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
static bool bad_usb_file_select(BadUsbApp* bad_usb) {
|
static bool bad_usb_file_select(BadUsbApp* bad_usb) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "../bad_usb_script.h"
|
#include "../bad_usb_script.h"
|
||||||
#include "../bad_usb_app_i.h"
|
#include "../bad_usb_app_i.h"
|
||||||
#include "../views/bad_usb_view.h"
|
#include "../views/bad_usb_view.h"
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
#include "toolbox/path.h"
|
#include "toolbox/path.h"
|
||||||
|
|
||||||
void bad_usb_scene_work_button_callback(InputKey key, void* context) {
|
void bad_usb_scene_work_button_callback(InputKey key, void* context) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ GpioApp* gpio_app_alloc() {
|
|||||||
GpioApp* app = malloc(sizeof(GpioApp));
|
GpioApp* app = malloc(sizeof(GpioApp));
|
||||||
|
|
||||||
app->gui = furi_record_open(RECORD_GUI);
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
|
app->gpio_items = gpio_items_alloc();
|
||||||
|
|
||||||
app->view_dispatcher = view_dispatcher_alloc();
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app);
|
app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app);
|
||||||
@@ -47,7 +48,7 @@ GpioApp* gpio_app_alloc() {
|
|||||||
app->view_dispatcher,
|
app->view_dispatcher,
|
||||||
GpioAppViewVarItemList,
|
GpioAppViewVarItemList,
|
||||||
variable_item_list_get_view(app->var_item_list));
|
variable_item_list_get_view(app->var_item_list));
|
||||||
app->gpio_test = gpio_test_alloc();
|
app->gpio_test = gpio_test_alloc(app->gpio_items);
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
|
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ void gpio_app_free(GpioApp* app) {
|
|||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
gpio_items_free(app->gpio_items);
|
||||||
free(app);
|
free(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "gpio_app.h"
|
#include "gpio_app.h"
|
||||||
#include "gpio_item.h"
|
#include "gpio_items.h"
|
||||||
#include "scenes/gpio_scene.h"
|
#include "scenes/gpio_scene.h"
|
||||||
#include "gpio_custom_event.h"
|
#include "gpio_custom_event.h"
|
||||||
#include "usb_uart_bridge.h"
|
#include "usb_uart_bridge.h"
|
||||||
@@ -28,6 +28,7 @@ struct GpioApp {
|
|||||||
VariableItem* var_item_flow;
|
VariableItem* var_item_flow;
|
||||||
GpioTest* gpio_test;
|
GpioTest* gpio_test;
|
||||||
GpioUsbUart* gpio_usb_uart;
|
GpioUsbUart* gpio_usb_uart;
|
||||||
|
GPIOItems* gpio_items;
|
||||||
UsbUartBridge* usb_uart_bridge;
|
UsbUartBridge* usb_uart_bridge;
|
||||||
UsbUartConfig* usb_uart_cfg;
|
UsbUartConfig* usb_uart_cfg;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
#include "gpio_item.h"
|
|
||||||
|
|
||||||
#include <furi_hal_resources.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char* name;
|
|
||||||
const GpioPin* pin;
|
|
||||||
} GpioItem;
|
|
||||||
|
|
||||||
static const GpioItem gpio_item[GPIO_ITEM_COUNT] = {
|
|
||||||
{"1.2: PA7", &gpio_ext_pa7},
|
|
||||||
{"1.3: PA6", &gpio_ext_pa6},
|
|
||||||
{"1.4: PA4", &gpio_ext_pa4},
|
|
||||||
{"1.5: PB3", &gpio_ext_pb3},
|
|
||||||
{"1.6: PB2", &gpio_ext_pb2},
|
|
||||||
{"1.7: PC3", &gpio_ext_pc3},
|
|
||||||
{"2.7: PC1", &gpio_ext_pc1},
|
|
||||||
{"2.8: PC0", &gpio_ext_pc0},
|
|
||||||
};
|
|
||||||
|
|
||||||
void gpio_item_configure_pin(uint8_t index, GpioMode mode) {
|
|
||||||
furi_assert(index < GPIO_ITEM_COUNT);
|
|
||||||
furi_hal_gpio_write(gpio_item[index].pin, false);
|
|
||||||
furi_hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_item_configure_all_pins(GpioMode mode) {
|
|
||||||
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
|
|
||||||
gpio_item_configure_pin(i, mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_item_set_pin(uint8_t index, bool level) {
|
|
||||||
furi_assert(index < GPIO_ITEM_COUNT);
|
|
||||||
furi_hal_gpio_write(gpio_item[index].pin, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_item_set_all_pins(bool level) {
|
|
||||||
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
|
|
||||||
gpio_item_set_pin(i, level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* gpio_item_get_pin_name(uint8_t index) {
|
|
||||||
furi_assert(index < GPIO_ITEM_COUNT + 1);
|
|
||||||
if(index == GPIO_ITEM_COUNT) {
|
|
||||||
return "ALL";
|
|
||||||
} else {
|
|
||||||
return gpio_item[index].name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <furi_hal_gpio.h>
|
|
||||||
|
|
||||||
#define GPIO_ITEM_COUNT 8
|
|
||||||
|
|
||||||
void gpio_item_configure_pin(uint8_t index, GpioMode mode);
|
|
||||||
|
|
||||||
void gpio_item_configure_all_pins(GpioMode mode);
|
|
||||||
|
|
||||||
void gpio_item_set_pin(uint8_t index, bool level);
|
|
||||||
|
|
||||||
void gpio_item_set_all_pins(bool level);
|
|
||||||
|
|
||||||
const char* gpio_item_get_pin_name(uint8_t index);
|
|
||||||
69
applications/main/gpio/gpio_items.c
Normal file
69
applications/main/gpio/gpio_items.c
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#include "gpio_items.h"
|
||||||
|
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
|
||||||
|
struct GPIOItems {
|
||||||
|
GpioPinRecord* pins;
|
||||||
|
size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
GPIOItems* gpio_items_alloc() {
|
||||||
|
GPIOItems* items = malloc(sizeof(GPIOItems));
|
||||||
|
|
||||||
|
items->count = 0;
|
||||||
|
for(size_t i = 0; i < gpio_pins_count; i++) {
|
||||||
|
if(!gpio_pins[i].debug) {
|
||||||
|
items->count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items->pins = malloc(sizeof(GpioPinRecord) * items->count);
|
||||||
|
for(size_t i = 0; i < items->count; i++) {
|
||||||
|
if(!gpio_pins[i].debug) {
|
||||||
|
items->pins[i].pin = gpio_pins[i].pin;
|
||||||
|
items->pins[i].name = gpio_pins[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_items_free(GPIOItems* items) {
|
||||||
|
free(items->pins);
|
||||||
|
free(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t gpio_items_get_count(GPIOItems* items) {
|
||||||
|
return items->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode) {
|
||||||
|
furi_assert(index < items->count);
|
||||||
|
furi_hal_gpio_write(items->pins[index].pin, false);
|
||||||
|
furi_hal_gpio_init(items->pins[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode) {
|
||||||
|
for(uint8_t i = 0; i < items->count; i++) {
|
||||||
|
gpio_items_configure_pin(items, i, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level) {
|
||||||
|
furi_assert(index < items->count);
|
||||||
|
furi_hal_gpio_write(items->pins[index].pin, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_items_set_all_pins(GPIOItems* items, bool level) {
|
||||||
|
for(uint8_t i = 0; i < items->count; i++) {
|
||||||
|
gpio_items_set_pin(items, i, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index) {
|
||||||
|
furi_assert(index < items->count + 1);
|
||||||
|
if(index == items->count) {
|
||||||
|
return "ALL";
|
||||||
|
} else {
|
||||||
|
return items->pins[index].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
applications/main/gpio/gpio_items.h
Normal file
29
applications/main/gpio/gpio_items.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal_gpio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct GPIOItems GPIOItems;
|
||||||
|
|
||||||
|
GPIOItems* gpio_items_alloc();
|
||||||
|
|
||||||
|
void gpio_items_free(GPIOItems* items);
|
||||||
|
|
||||||
|
uint8_t gpio_items_get_count(GPIOItems* items);
|
||||||
|
|
||||||
|
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode);
|
||||||
|
|
||||||
|
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode);
|
||||||
|
|
||||||
|
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level);
|
||||||
|
|
||||||
|
void gpio_items_set_all_pins(GPIOItems* items, bool level);
|
||||||
|
|
||||||
|
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "../gpio_app_i.h"
|
#include "../gpio_app_i.h"
|
||||||
#include "furi_hal_power.h"
|
#include <furi_hal_power.h>
|
||||||
#include "furi_hal_usb.h"
|
#include <furi_hal_usb.h>
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
enum GpioItem {
|
enum GpioItem {
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ void gpio_scene_test_ok_callback(InputType type, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gpio_scene_test_on_enter(void* context) {
|
void gpio_scene_test_on_enter(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
GpioApp* app = context;
|
GpioApp* app = context;
|
||||||
gpio_item_configure_all_pins(GpioModeOutputPushPull);
|
gpio_items_configure_all_pins(app->gpio_items, GpioModeOutputPushPull);
|
||||||
gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app);
|
gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app);
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest);
|
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest);
|
||||||
}
|
}
|
||||||
@@ -25,6 +26,7 @@ bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gpio_scene_test_on_exit(void* context) {
|
void gpio_scene_test_on_exit(void* context) {
|
||||||
UNUSED(context);
|
furi_assert(context);
|
||||||
gpio_item_configure_all_pins(GpioModeAnalog);
|
GpioApp* app = context;
|
||||||
|
gpio_items_configure_all_pins(app->gpio_items, GpioModeAnalog);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "../usb_uart_bridge.h"
|
#include "../usb_uart_bridge.h"
|
||||||
#include "../gpio_app_i.h"
|
#include "../gpio_app_i.h"
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UsbUartLineIndexVcp,
|
UsbUartLineIndexVcp,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "usb_uart_bridge.h"
|
#include "usb_uart_bridge.h"
|
||||||
#include "furi_hal.h"
|
|
||||||
#include <furi_hal_usb_cdc.h>
|
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
#include "cli/cli_vcp.h"
|
#include <cli/cli_vcp.h>
|
||||||
|
#include <cli/cli.h>
|
||||||
#include <toolbox/api_lock.h>
|
#include <toolbox/api_lock.h>
|
||||||
#include "cli/cli.h"
|
#include <furi_hal.h>
|
||||||
|
#include <furi_hal_usb_cdc.h>
|
||||||
|
|
||||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||||
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "gpio_test.h"
|
#include "gpio_test.h"
|
||||||
#include "../gpio_item.h"
|
#include "../gpio_items.h"
|
||||||
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ struct GpioTest {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t pin_idx;
|
uint8_t pin_idx;
|
||||||
|
GPIOItems* gpio_items;
|
||||||
} GpioTestModel;
|
} GpioTestModel;
|
||||||
|
|
||||||
static bool gpio_test_process_left(GpioTest* gpio_test);
|
static bool gpio_test_process_left(GpioTest* gpio_test);
|
||||||
@@ -25,7 +26,12 @@ static void gpio_test_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
elements_multiline_text_aligned(
|
elements_multiline_text_aligned(
|
||||||
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
|
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
|
||||||
elements_multiline_text_aligned(
|
elements_multiline_text_aligned(
|
||||||
canvas, 64, 32, AlignCenter, AlignTop, gpio_item_get_pin_name(model->pin_idx));
|
canvas,
|
||||||
|
64,
|
||||||
|
32,
|
||||||
|
AlignCenter,
|
||||||
|
AlignTop,
|
||||||
|
gpio_items_get_pin_name(model->gpio_items, model->pin_idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gpio_test_input_callback(InputEvent* event, void* context) {
|
static bool gpio_test_input_callback(InputEvent* event, void* context) {
|
||||||
@@ -64,7 +70,7 @@ static bool gpio_test_process_right(GpioTest* gpio_test) {
|
|||||||
gpio_test->view,
|
gpio_test->view,
|
||||||
GpioTestModel * model,
|
GpioTestModel * model,
|
||||||
{
|
{
|
||||||
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
|
||||||
model->pin_idx++;
|
model->pin_idx++;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -80,17 +86,17 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
|
|||||||
GpioTestModel * model,
|
GpioTestModel * model,
|
||||||
{
|
{
|
||||||
if(event->type == InputTypePress) {
|
if(event->type == InputTypePress) {
|
||||||
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
|
||||||
gpio_item_set_pin(model->pin_idx, true);
|
gpio_items_set_pin(model->gpio_items, model->pin_idx, true);
|
||||||
} else {
|
} else {
|
||||||
gpio_item_set_all_pins(true);
|
gpio_items_set_all_pins(model->gpio_items, true);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
if(model->pin_idx < GPIO_ITEM_COUNT) {
|
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
|
||||||
gpio_item_set_pin(model->pin_idx, false);
|
gpio_items_set_pin(model->gpio_items, model->pin_idx, false);
|
||||||
} else {
|
} else {
|
||||||
gpio_item_set_all_pins(false);
|
gpio_items_set_all_pins(model->gpio_items, false);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
@@ -101,11 +107,15 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
|
|||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpioTest* gpio_test_alloc() {
|
GpioTest* gpio_test_alloc(GPIOItems* gpio_items) {
|
||||||
GpioTest* gpio_test = malloc(sizeof(GpioTest));
|
GpioTest* gpio_test = malloc(sizeof(GpioTest));
|
||||||
|
|
||||||
gpio_test->view = view_alloc();
|
gpio_test->view = view_alloc();
|
||||||
view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
|
view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
|
||||||
|
|
||||||
|
with_view_model(
|
||||||
|
gpio_test->view, GpioTestModel * model, { model->gpio_items = gpio_items; }, false);
|
||||||
|
|
||||||
view_set_context(gpio_test->view, gpio_test);
|
view_set_context(gpio_test->view, gpio_test);
|
||||||
view_set_draw_callback(gpio_test->view, gpio_test_draw_callback);
|
view_set_draw_callback(gpio_test->view, gpio_test_draw_callback);
|
||||||
view_set_input_callback(gpio_test->view, gpio_test_input_callback);
|
view_set_input_callback(gpio_test->view, gpio_test_input_callback);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../gpio_items.h"
|
||||||
|
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
|
|
||||||
typedef struct GpioTest GpioTest;
|
typedef struct GpioTest GpioTest;
|
||||||
typedef void (*GpioTestOkCallback)(InputType type, void* context);
|
typedef void (*GpioTestOkCallback)(InputType type, void* context);
|
||||||
|
|
||||||
GpioTest* gpio_test_alloc();
|
GpioTest* gpio_test_alloc(GPIOItems* gpio_items);
|
||||||
|
|
||||||
void gpio_test_free(GpioTest* gpio_test);
|
void gpio_test_free(GpioTest* gpio_test);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "../usb_uart_bridge.h"
|
#include "../usb_uart_bridge.h"
|
||||||
#include "../gpio_app_i.h"
|
#include "../gpio_app_i.h"
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
|
|
||||||
struct GpioUsbUart {
|
struct GpioUsbUart {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="ibutton",
|
appid="ibutton",
|
||||||
name="iButton",
|
name="iButton",
|
||||||
apptype=FlipperAppType.APP,
|
apptype=FlipperAppType.APP,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="ibutton_app",
|
entry_point="ibutton_app",
|
||||||
cdefines=["APP_IBUTTON"],
|
cdefines=["APP_IBUTTON"],
|
||||||
requires=[
|
requires=[
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ void onewire_cli_print_usage() {
|
|||||||
|
|
||||||
static void onewire_cli_search(Cli* cli) {
|
static void onewire_cli_search(Cli* cli) {
|
||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
OneWireHost* onewire = onewire_host_alloc();
|
OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio);
|
||||||
uint8_t address[8];
|
uint8_t address[8];
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ App(
|
|||||||
name="Infrared",
|
name="Infrared",
|
||||||
apptype=FlipperAppType.APP,
|
apptype=FlipperAppType.APP,
|
||||||
entry_point="infrared_app",
|
entry_point="infrared_app",
|
||||||
|
targets=["f7"],
|
||||||
cdefines=["APP_INFRARED"],
|
cdefines=["APP_INFRARED"],
|
||||||
requires=[
|
requires=[
|
||||||
"gui",
|
"gui",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../infrared_i.h"
|
#include "../infrared_i.h"
|
||||||
#include "gui/canvas.h"
|
#include <gui/canvas.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
InfraredRpcStateIdle,
|
InfraredRpcStateIdle,
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ void infrared_scene_universal_on_enter(void* context) {
|
|||||||
infrared_scene_universal_submenu_callback,
|
infrared_scene_universal_submenu_callback,
|
||||||
context);
|
context);
|
||||||
|
|
||||||
submenu_set_selected_item(submenu, 0);
|
submenu_set_selected_item(
|
||||||
|
submenu, scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneUniversal));
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu);
|
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu);
|
||||||
}
|
}
|
||||||
@@ -79,6 +80,7 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
|
|||||||
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
|
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event);
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "infrared_debug_view.h"
|
#include "infrared_debug_view.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <gui/canvas.h>
|
#include <gui/canvas.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define INFRARED_DEBUG_TEXT_LENGTH 64
|
#define INFRARED_DEBUG_TEXT_LENGTH 64
|
||||||
|
|
||||||
struct InfraredDebugView {
|
struct InfraredDebugView {
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
#include <core/check.h>
|
|
||||||
#include "furi_hal_resources.h"
|
|
||||||
#include "assets_icons.h"
|
|
||||||
#include "gui/canvas.h"
|
|
||||||
#include "gui/view.h"
|
|
||||||
#include "input/input.h"
|
|
||||||
#include <gui/elements.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include "infrared_progress_view.h"
|
#include "infrared_progress_view.h"
|
||||||
#include "gui/modules/button_panel.h"
|
|
||||||
|
#include <assets_icons.h>
|
||||||
|
#include <gui/canvas.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
#include <gui/modules/button_panel.h>
|
||||||
|
#include <input/input.h>
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
#include <core/check.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct InfraredProgressView {
|
struct InfraredProgressView {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="lfrfid",
|
appid="lfrfid",
|
||||||
name="125 kHz RFID",
|
name="125 kHz RFID",
|
||||||
apptype=FlipperAppType.APP,
|
apptype=FlipperAppType.APP,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="lfrfid_app",
|
entry_point="lfrfid_app",
|
||||||
cdefines=["APP_LF_RFID"],
|
cdefines=["APP_LF_RFID"],
|
||||||
requires=[
|
requires=[
|
||||||
|
|||||||
@@ -47,21 +47,28 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexRead) {
|
if(event.event == SubmenuIndexRead) {
|
||||||
|
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexRead);
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexSaved) {
|
} else if(event.event == SubmenuIndexSaved) {
|
||||||
|
// Like in the other apps, explicitly save the scene state
|
||||||
|
// in each branch in case the user cancels loading a file.
|
||||||
|
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexSaved);
|
||||||
furi_string_set(app->file_path, LFRFID_APP_FOLDER);
|
furi_string_set(app->file_path, LFRFID_APP_FOLDER);
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexAddManually) {
|
} else if(event.event == SubmenuIndexAddManually) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
app->scene_manager, LfRfidSceneStart, SubmenuIndexAddManually);
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexExtraActions) {
|
} else if(event.event == SubmenuIndexExtraActions) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
app->scene_manager, LfRfidSceneStart, SubmenuIndexExtraActions);
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="nfc",
|
appid="nfc",
|
||||||
name="NFC",
|
name="NFC",
|
||||||
apptype=FlipperAppType.APP,
|
apptype=FlipperAppType.APP,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="nfc_app",
|
entry_point="nfc_app",
|
||||||
cdefines=["APP_NFC"],
|
cdefines=["APP_NFC"],
|
||||||
requires=[
|
requires=[
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "nfc_i.h"
|
#include "nfc_i.h"
|
||||||
#include "furi_hal_nfc.h"
|
#include <furi_hal_nfc.h>
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
bool nfc_custom_event_callback(void* context, uint32_t event) {
|
bool nfc_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ ADD_SCENE(nfc, saved_menu, SavedMenu)
|
|||||||
ADD_SCENE(nfc, extra_actions, ExtraActions)
|
ADD_SCENE(nfc, extra_actions, ExtraActions)
|
||||||
ADD_SCENE(nfc, set_type, SetType)
|
ADD_SCENE(nfc, set_type, SetType)
|
||||||
ADD_SCENE(nfc, set_sak, SetSak)
|
ADD_SCENE(nfc, set_sak, SetSak)
|
||||||
ADD_SCENE(nfc, set_atqa, SetAtqua)
|
ADD_SCENE(nfc, set_atqa, SetAtqa)
|
||||||
ADD_SCENE(nfc, set_uid, SetUid)
|
ADD_SCENE(nfc, set_uid, SetUid)
|
||||||
ADD_SCENE(nfc, generate_info, GenerateInfo)
|
ADD_SCENE(nfc, generate_info, GenerateInfo)
|
||||||
ADD_SCENE(nfc, read_card_success, ReadCardSuccess)
|
ADD_SCENE(nfc, read_card_success, ReadCardSuccess)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
|||||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
} else {
|
} else {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneStart);
|
nfc->scene_manager, NfcSceneFileSelect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
|||||||
SubmenuIndexMfUltralightUnlock,
|
SubmenuIndexMfUltralightUnlock,
|
||||||
nfc_scene_extra_actions_submenu_callback,
|
nfc_scene_extra_actions_submenu_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
submenu_set_selected_item(
|
||||||
|
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions));
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
ByteInput* byte_input = nfc->byte_input;
|
ByteInput* byte_input = nfc->byte_input;
|
||||||
byte_input_set_header_text(byte_input, "Enter atqa in hex");
|
byte_input_set_header_text(byte_input, "Enter ATQA in hex");
|
||||||
byte_input_set_result_callback(
|
byte_input_set_result_callback(
|
||||||
byte_input,
|
byte_input,
|
||||||
nfc_scene_set_atqa_byte_input_callback,
|
nfc_scene_set_atqa_byte_input_callback,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventByteInputDone) {
|
if(event.event == NfcCustomEventByteInputDone) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqa);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
|
|||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
ByteInput* byte_input = nfc->byte_input;
|
ByteInput* byte_input = nfc->byte_input;
|
||||||
byte_input_set_header_text(byte_input, "Enter uid in hex");
|
byte_input_set_header_text(byte_input, "Enter UID in hex");
|
||||||
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
|
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
|
||||||
byte_input_set_result_callback(
|
byte_input_set_result_callback(
|
||||||
byte_input,
|
byte_input,
|
||||||
|
|||||||
@@ -48,11 +48,14 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexRead) {
|
if(event.event == SubmenuIndexRead) {
|
||||||
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead);
|
||||||
nfc->dev->dev_data.read_mode = NfcReadModeAuto;
|
nfc->dev->dev_data.read_mode = NfcReadModeAuto;
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
|
||||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexDetectReader) {
|
} else if(event.event == SubmenuIndexDetectReader) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader);
|
||||||
bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK;
|
bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK;
|
||||||
if(sd_exist) {
|
if(sd_exist) {
|
||||||
nfc_device_data_clear(&nfc->dev->dev_data);
|
nfc_device_data_clear(&nfc->dev->dev_data);
|
||||||
@@ -63,19 +66,27 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexSaved) {
|
} else if(event.event == SubmenuIndexSaved) {
|
||||||
|
// Save the scene state explicitly in each branch, so that
|
||||||
|
// if the user cancels loading a file, the Saved menu item
|
||||||
|
// is properly reselected.
|
||||||
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexExtraAction) {
|
} else if(event.event == SubmenuIndexExtraAction) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexAddManually) {
|
} else if(event.event == SubmenuIndexAddManually) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexDebug) {
|
} else if(event.event == SubmenuIndexDebug) {
|
||||||
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event);
|
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="subghz",
|
appid="subghz",
|
||||||
name="Sub-GHz",
|
name="Sub-GHz",
|
||||||
apptype=FlipperAppType.APP,
|
apptype=FlipperAppType.APP,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="subghz_app",
|
entry_point="subghz_app",
|
||||||
cdefines=["APP_SUBGHZ"],
|
cdefines=["APP_SUBGHZ"],
|
||||||
requires=[
|
requires=[
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event
|
|||||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
|
||||||
} else if(scene_manager_search_and_switch_to_previous_scene(
|
} else if(scene_manager_search_and_switch_to_previous_scene(
|
||||||
subghz->scene_manager, SubGhzSceneSaved)) {
|
subghz->scene_manager, SubGhzSceneSaved)) {
|
||||||
|
// Commented so that the user doesn't have to press
|
||||||
|
// back twice to get to the main SubGhz menu after
|
||||||
|
// deleting a file.
|
||||||
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
|
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
|
||||||
} else {
|
} else {
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "../u2f_app_i.h"
|
#include "../u2f_app_i.h"
|
||||||
#include "../views/u2f_view.h"
|
#include "../views/u2f_view.h"
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
#include "../u2f.h"
|
#include "../u2f.h"
|
||||||
|
|
||||||
#define U2F_REQUEST_TIMEOUT 500
|
#define U2F_REQUEST_TIMEOUT 500
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <lib/flipper_format/flipper_format.h>
|
#include <lib/flipper_format/flipper_format.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
|
|
||||||
#define TAG "MusicPlayerWorker"
|
#define TAG "MusicPlayerWorker"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="nfc_magic",
|
appid="nfc_magic",
|
||||||
name="NFC Magic",
|
name="NFC Magic",
|
||||||
apptype=FlipperAppType.EXTERNAL,
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="nfc_magic_app",
|
entry_point="nfc_magic_app",
|
||||||
requires=[
|
requires=[
|
||||||
"storage",
|
"storage",
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
|||||||
free(nfc_magic);
|
free(nfc_magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const NotificationSequence nfc_magic_sequence_blink_start_blue = {
|
static const NotificationSequence nfc_magic_sequence_blink_start_cyan = {
|
||||||
&message_blink_start_10,
|
&message_blink_start_10,
|
||||||
&message_blink_set_color_blue,
|
&message_blink_set_color_cyan,
|
||||||
&message_do_not_reset,
|
&message_do_not_reset,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
@@ -149,7 +149,7 @@ static const NotificationSequence nfc_magic_sequence_blink_stop = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void nfc_magic_blink_start(NfcMagic* nfc_magic) {
|
void nfc_magic_blink_start(NfcMagic* nfc_magic) {
|
||||||
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_blue);
|
notification_message(nfc_magic->notifications, &nfc_magic_sequence_blink_start_cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_magic_blink_stop(NfcMagic* nfc_magic) {
|
void nfc_magic_blink_stop(NfcMagic* nfc_magic) {
|
||||||
|
|||||||
@@ -40,16 +40,24 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexCheck) {
|
if(event.event == SubmenuIndexCheck) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexWriteGen1A) {
|
} else if(event.event == SubmenuIndexWriteGen1A) {
|
||||||
|
// Explicitly save state in each branch so that the
|
||||||
|
// correct option is reselected if the user cancels
|
||||||
|
// loading a file.
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A);
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexWipe) {
|
} else if(event.event == SubmenuIndexWipe) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe);
|
||||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart, event.event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="Picopass",
|
appid="Picopass",
|
||||||
name="PicoPass Reader",
|
name="PicoPass Reader",
|
||||||
apptype=FlipperAppType.EXTERNAL,
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="picopass_app",
|
entry_point="picopass_app",
|
||||||
requires=[
|
requires=[
|
||||||
"storage",
|
"storage",
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ void picopass_text_store_clear(Picopass* picopass) {
|
|||||||
memset(picopass->text_store, 0, sizeof(picopass->text_store));
|
memset(picopass->text_store, 0, sizeof(picopass->text_store));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const NotificationSequence picopass_sequence_blink_start_blue = {
|
static const NotificationSequence picopass_sequence_blink_start_cyan = {
|
||||||
&message_blink_start_10,
|
&message_blink_start_10,
|
||||||
&message_blink_set_color_blue,
|
&message_blink_set_color_cyan,
|
||||||
&message_do_not_reset,
|
&message_do_not_reset,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
@@ -150,7 +150,7 @@ static const NotificationSequence picopass_sequence_blink_stop = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void picopass_blink_start(Picopass* picopass) {
|
void picopass_blink_start(Picopass* picopass) {
|
||||||
notification_message(picopass->notifications, &picopass_sequence_blink_start_blue);
|
notification_message(picopass->notifications, &picopass_sequence_blink_start_cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void picopass_blink_stop(Picopass* picopass) {
|
void picopass_blink_stop(Picopass* picopass) {
|
||||||
|
|||||||
@@ -32,13 +32,18 @@ bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexRead) {
|
if(event.event == SubmenuIndexRead) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
picopass->scene_manager, PicopassSceneStart, SubmenuIndexRead);
|
||||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCard);
|
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCard);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexSaved) {
|
} else if(event.event == SubmenuIndexSaved) {
|
||||||
|
// Explicitly save state so that the correct item is
|
||||||
|
// reselected if the user cancels loading a file.
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
picopass->scene_manager, PicopassSceneStart, SubmenuIndexSaved);
|
||||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneFileSelect);
|
scene_manager_next_scene(picopass->scene_manager, PicopassSceneFileSelect);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneStart, event.event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "scenes/signal_gen_scene.h"
|
#include "scenes/signal_gen_scene.h"
|
||||||
|
|
||||||
#include "furi_hal_clock.h"
|
#include <furi_hal_clock.h>
|
||||||
#include "furi_hal_pwm.h"
|
#include <furi_hal_pwm.h>
|
||||||
|
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../signal_gen_app_i.h"
|
#include "../signal_gen_app_i.h"
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <Signal_Generator_icons.h>
|
#include <Signal_Generator_icons.h>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ App(
|
|||||||
appid="weather_station",
|
appid="weather_station",
|
||||||
name="Weather Station",
|
name="Weather Station",
|
||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
targets=["f7"],
|
||||||
entry_point="weather_station_app",
|
entry_point="weather_station_app",
|
||||||
cdefines=["APP_WEATHER_STATION"],
|
cdefines=["APP_WEATHER_STATION"],
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <lib/flipper_format/flipper_format.h>
|
#include <lib/flipper_format/flipper_format.h>
|
||||||
#include "furi.h"
|
#include "furi.h"
|
||||||
#include "furi_hal.h"
|
#include <furi_hal.h>
|
||||||
#include <lib/subghz/types.h>
|
#include <lib/subghz/types.h>
|
||||||
#include <locale/locale.h>
|
#include <locale/locale.h>
|
||||||
|
|
||||||
|
|||||||
@@ -5,28 +5,6 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const GpioPin* pin;
|
|
||||||
const char* name;
|
|
||||||
const bool debug;
|
|
||||||
} CliCommandGpio;
|
|
||||||
|
|
||||||
const CliCommandGpio cli_command_gpio_pins[] = {
|
|
||||||
{.pin = &gpio_ext_pc0, .name = "PC0", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pc1, .name = "PC1", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pc3, .name = "PC3", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pb2, .name = "PB2", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pb3, .name = "PB3", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pa4, .name = "PA4", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pa6, .name = "PA6", .debug = false},
|
|
||||||
{.pin = &gpio_ext_pa7, .name = "PA7", .debug = false},
|
|
||||||
/* Dangerous pins, may damage hardware */
|
|
||||||
{.pin = &gpio_infrared_rx, .name = "PA0", .debug = true},
|
|
||||||
{.pin = &gpio_usart_rx, .name = "PB7", .debug = true},
|
|
||||||
{.pin = &gpio_speaker, .name = "PB8", .debug = true},
|
|
||||||
{.pin = &gpio_infrared_tx, .name = "PB9", .debug = true},
|
|
||||||
};
|
|
||||||
|
|
||||||
void cli_command_gpio_print_usage() {
|
void cli_command_gpio_print_usage() {
|
||||||
printf("Usage:\r\n");
|
printf("Usage:\r\n");
|
||||||
printf("gpio <cmd> <args>\r\n");
|
printf("gpio <cmd> <args>\r\n");
|
||||||
@@ -38,9 +16,9 @@ void cli_command_gpio_print_usage() {
|
|||||||
|
|
||||||
static bool pin_name_to_int(FuriString* pin_name, size_t* result) {
|
static bool pin_name_to_int(FuriString* pin_name, size_t* result) {
|
||||||
bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
|
bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
|
||||||
for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) {
|
for(size_t i = 0; i < gpio_pins_count; i++) {
|
||||||
if(furi_string_equal(pin_name, cli_command_gpio_pins[i].name)) {
|
if(furi_string_equal(pin_name, gpio_pins[i].name)) {
|
||||||
if(!cli_command_gpio_pins[i].debug || is_debug_mode) {
|
if(!gpio_pins[i].debug || is_debug_mode) {
|
||||||
*result = i;
|
*result = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -53,9 +31,9 @@ static bool pin_name_to_int(FuriString* pin_name, size_t* result) {
|
|||||||
static void gpio_print_pins(void) {
|
static void gpio_print_pins(void) {
|
||||||
printf("Wrong pin name. Available pins: ");
|
printf("Wrong pin name. Available pins: ");
|
||||||
bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
|
bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug);
|
||||||
for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) {
|
for(size_t i = 0; i < gpio_pins_count; i++) {
|
||||||
if(!cli_command_gpio_pins[i].debug || is_debug_mode) {
|
if(!gpio_pins[i].debug || is_debug_mode) {
|
||||||
printf("%s ", cli_command_gpio_pins[i].name);
|
printf("%s ", gpio_pins[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,7 +91,7 @@ void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cli_command_gpio_pins[num].debug) { //-V779
|
if(gpio_pins[num].debug) { //-V779
|
||||||
printf(
|
printf(
|
||||||
"Changing this pin mode may damage hardware. Are you sure you want to continue? (y/n)?\r\n");
|
"Changing this pin mode may damage hardware. Are you sure you want to continue? (y/n)?\r\n");
|
||||||
char c = cli_getc(cli);
|
char c = cli_getc(cli);
|
||||||
@@ -124,12 +102,12 @@ void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(value == 1) { // output
|
if(value == 1) { // output
|
||||||
furi_hal_gpio_write(cli_command_gpio_pins[num].pin, false);
|
furi_hal_gpio_write(gpio_pins[num].pin, false);
|
||||||
furi_hal_gpio_init_simple(cli_command_gpio_pins[num].pin, GpioModeOutputPushPull);
|
furi_hal_gpio_init_simple(gpio_pins[num].pin, GpioModeOutputPushPull);
|
||||||
printf("Pin %s is now an output (low)", cli_command_gpio_pins[num].name);
|
printf("Pin %s is now an output (low)", gpio_pins[num].name);
|
||||||
} else { // input
|
} else { // input
|
||||||
furi_hal_gpio_init_simple(cli_command_gpio_pins[num].pin, GpioModeInput);
|
furi_hal_gpio_init_simple(gpio_pins[num].pin, GpioModeInput);
|
||||||
printf("Pin %s is now an input", cli_command_gpio_pins[num].name);
|
printf("Pin %s is now an input", gpio_pins[num].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,15 +122,14 @@ void cli_command_gpio_read(Cli* cli, FuriString* args, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(LL_GPIO_MODE_INPUT != //-V779
|
if(LL_GPIO_MODE_INPUT != //-V779
|
||||||
LL_GPIO_GetPinMode(
|
LL_GPIO_GetPinMode(gpio_pins[num].pin->port, gpio_pins[num].pin->pin)) {
|
||||||
cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) {
|
printf("Err: pin %s is not set as an input.", gpio_pins[num].name);
|
||||||
printf("Err: pin %s is not set as an input.", cli_command_gpio_pins[num].name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t val = !!furi_hal_gpio_read(cli_command_gpio_pins[num].pin);
|
uint8_t val = !!furi_hal_gpio_read(gpio_pins[num].pin);
|
||||||
|
|
||||||
printf("Pin %s <= %u", cli_command_gpio_pins[num].name, val);
|
printf("Pin %s <= %u", gpio_pins[num].name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) {
|
void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) {
|
||||||
@@ -174,14 +151,13 @@ void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(LL_GPIO_MODE_OUTPUT != //-V779
|
if(LL_GPIO_MODE_OUTPUT != //-V779
|
||||||
LL_GPIO_GetPinMode(
|
LL_GPIO_GetPinMode(gpio_pins[num].pin->port, gpio_pins[num].pin->pin)) {
|
||||||
cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) {
|
printf("Err: pin %s is not set as an output.", gpio_pins[num].name);
|
||||||
printf("Err: pin %s is not set as an output.", cli_command_gpio_pins[num].name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra check if debug pins used
|
// Extra check if debug pins used
|
||||||
if(cli_command_gpio_pins[num].debug) {
|
if(gpio_pins[num].debug) {
|
||||||
printf(
|
printf(
|
||||||
"Setting this pin may damage hardware. Are you sure you want to continue? (y/n)?\r\n");
|
"Setting this pin may damage hardware. Are you sure you want to continue? (y/n)?\r\n");
|
||||||
char c = cli_getc(cli);
|
char c = cli_getc(cli);
|
||||||
@@ -191,8 +167,8 @@ void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_hal_gpio_write(cli_command_gpio_pins[num].pin, !!value);
|
furi_hal_gpio_write(gpio_pins[num].pin, !!value);
|
||||||
printf("Pin %s => %u", cli_command_gpio_pins[num].name, !!value);
|
printf("Pin %s => %u", gpio_pins[num].name, !!value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_gpio(Cli* cli, FuriString* args, void* context) {
|
void cli_command_gpio(Cli* cli, FuriString* args, void* context) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "dialogs/dialogs_message.h"
|
#include "dialogs_message.h"
|
||||||
#include "dialogs_i.h"
|
#include "dialogs_i.h"
|
||||||
#include <toolbox/api_lock.h>
|
#include <toolbox/api_lock.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "dialogs_i.h"
|
#include "dialogs_i.h"
|
||||||
|
|
||||||
|
#include <gui/modules/file_browser.h>
|
||||||
#include <toolbox/api_lock.h>
|
#include <toolbox/api_lock.h>
|
||||||
#include "gui/modules/file_browser.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriApiLock lock;
|
FuriApiLock lock;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/pubsub.h>
|
|
||||||
#include "gui/view.h"
|
|
||||||
#include "helpers/dolphin_deed.h"
|
#include "helpers/dolphin_deed.h"
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <core/pubsub.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
#include "elements.h"
|
#include "elements.h"
|
||||||
#include "m-core.h"
|
#include <m-core.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
#include "furi_hal_resources.h"
|
#include <furi_hal_resources.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include "gui/canvas.h"
|
|
||||||
|
|
||||||
|
#include <gui/canvas.h>
|
||||||
#include <gui/icon_i.h>
|
#include <gui/icon_i.h>
|
||||||
#include <gui/icon_animation_i.h>
|
#include <gui/icon_animation_i.h>
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "canvas_i.h"
|
#include "canvas_i.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include "gui/canvas.h"
|
|
||||||
#include "gui_i.h"
|
#include "gui_i.h"
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#include "button_menu.h"
|
#include "button_menu.h"
|
||||||
#include "gui/canvas.h"
|
|
||||||
#include "gui/elements.h"
|
#include <gui/canvas.h>
|
||||||
#include "input/input.h"
|
#include <gui/elements.h>
|
||||||
#include <m-array.h>
|
#include <input/input.h>
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
#define ITEM_FIRST_OFFSET 17
|
#define ITEM_FIRST_OFFSET 17
|
||||||
#define ITEM_NEXT_OFFSET 4
|
#define ITEM_NEXT_OFFSET 4
|
||||||
#define ITEM_HEIGHT 14
|
#define ITEM_HEIGHT 14
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#include "button_panel.h"
|
#include "button_panel.h"
|
||||||
#include "furi_hal_resources.h"
|
|
||||||
#include "gui/canvas.h"
|
#include <gui/canvas.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
#include <m-i-list.h>
|
#include <m-i-list.h>
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/elements.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// uint16_t to support multi-screen, wide button panel
|
// uint16_t to support multi-screen, wide button panel
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#include <furi.h>
|
|
||||||
#include <gui/elements.h>
|
|
||||||
#include <assets_icons.h>
|
|
||||||
#include "byte_input.h"
|
#include "byte_input.h"
|
||||||
|
|
||||||
|
#include <gui/elements.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include <assets_icons.h>
|
||||||
|
|
||||||
struct ByteInput {
|
struct ByteInput {
|
||||||
View* view;
|
View* view;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
#include "file_browser.h"
|
#include "file_browser.h"
|
||||||
#include "assets_icons.h"
|
|
||||||
#include "file_browser_worker.h"
|
#include "file_browser_worker.h"
|
||||||
|
|
||||||
|
#include <gui/elements.h>
|
||||||
|
#include <assets_icons.h>
|
||||||
|
#include <toolbox/path.h>
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
|
||||||
#include <core/check.h>
|
#include <core/check.h>
|
||||||
#include <core/common_defines.h>
|
#include <core/common_defines.h>
|
||||||
#include <core/log.h>
|
#include <core/log.h>
|
||||||
#include "furi_hal_resources.h"
|
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
#include <gui/elements.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include "toolbox/path.h"
|
|
||||||
|
|
||||||
#define LIST_ITEMS 5u
|
#define LIST_ITEMS 5u
|
||||||
#define MAX_LEN_PX 110
|
#define MAX_LEN_PX 110
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
#include "file_browser_worker.h"
|
#include "file_browser_worker.h"
|
||||||
|
|
||||||
|
#include <storage/filesystem_api_defines.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
#include <toolbox/path.h>
|
||||||
#include <core/check.h>
|
#include <core/check.h>
|
||||||
#include <core/common_defines.h>
|
#include <core/common_defines.h>
|
||||||
#include "storage/filesystem_api_defines.h"
|
#include <furi.h>
|
||||||
|
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <storage/storage.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "toolbox/path.h"
|
|
||||||
|
|
||||||
#define TAG "BrowserWorker"
|
#define TAG "BrowserWorker"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
#include <stdint.h>
|
#include "loading.h"
|
||||||
#include <furi.h>
|
|
||||||
#include <assets_icons.h>
|
|
||||||
#include <gui/icon_animation.h>
|
#include <gui/icon_animation.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <gui/canvas.h>
|
#include <gui/canvas.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
|
|
||||||
#include "loading.h"
|
#include <furi.h>
|
||||||
|
#include <assets_icons.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
struct Loading {
|
struct Loading {
|
||||||
View* view;
|
View* view;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
|
||||||
#include <m-array.h>
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
struct Menu {
|
struct Menu {
|
||||||
View* view;
|
View* view;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "submenu.h"
|
#include "submenu.h"
|
||||||
|
|
||||||
#include <m-array.h>
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
struct Submenu {
|
struct Submenu {
|
||||||
View* view;
|
View* view;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "text_box.h"
|
#include "text_box.h"
|
||||||
#include "gui/canvas.h"
|
#include <gui/canvas.h>
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
|
#include <furi.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct TextBox {
|
struct TextBox {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <furi.h>
|
|
||||||
#include "validators.h"
|
#include "validators.h"
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
struct ValidatorIsFile {
|
struct ValidatorIsFile {
|
||||||
char* app_path_folder;
|
char* app_path_folder;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/common_defines.h>
|
#include <core/common_defines.h>
|
||||||
|
#include <core/string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "variable_item_list.h"
|
#include "variable_item_list.h"
|
||||||
#include "gui/canvas.h"
|
|
||||||
#include <m-array.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
|
#include <gui/canvas.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include <m-array.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct VariableItem {
|
struct VariableItem {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <furi.h>
|
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include <m-array.h>
|
|
||||||
#include "widget_elements/widget_element_i.h"
|
#include "widget_elements/widget_element_i.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
ARRAY_DEF(ElementArray, WidgetElement*, M_PTR_OPLIST);
|
ARRAY_DEF(ElementArray, WidgetElement*, M_PTR_OPLIST);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#include "gui/view.h"
|
|
||||||
#include <core/memmgr.h>
|
|
||||||
#include "view_stack.h"
|
#include "view_stack.h"
|
||||||
#include "view_i.h"
|
#include "view_i.h"
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <core/memmgr.h>
|
||||||
|
|
||||||
#define MAX_VIEWS 3
|
#define MAX_VIEWS 3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "furi_hal_light.h"
|
#include <furi_hal_light.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "furi_hal_resources.h"
|
#include <furi_hal_resources.h>
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
#include "notification_messages_notes.h"
|
#include "notification_messages_notes.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <stm32_adafruit_sd.h>
|
|
||||||
|
|
||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
@@ -61,28 +60,26 @@ static void storage_cli_info(Cli* cli, FuriString* path) {
|
|||||||
}
|
}
|
||||||
} else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) {
|
} else if(furi_string_cmp_str(path, STORAGE_EXT_PATH_PREFIX) == 0) {
|
||||||
SDInfo sd_info;
|
SDInfo sd_info;
|
||||||
SD_CID sd_cid;
|
|
||||||
FS_Error error = storage_sd_info(api, &sd_info);
|
FS_Error error = storage_sd_info(api, &sd_info);
|
||||||
BSP_SD_GetCIDRegister(&sd_cid);
|
|
||||||
|
|
||||||
if(error != FSE_OK) {
|
if(error != FSE_OK) {
|
||||||
storage_cli_print_error(error);
|
storage_cli_print_error(error);
|
||||||
} else {
|
} else {
|
||||||
printf(
|
printf(
|
||||||
"Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n"
|
"Label: %s\r\nType: %s\r\n%luKiB total\r\n%luKiB free\r\n"
|
||||||
"%02x%2.2s %5.5s %i.%i\r\nSN:%04lx %02i/%i\r\n",
|
"%02x%s %s v%i.%i\r\nSN:%04lx %02i/%i\r\n",
|
||||||
sd_info.label,
|
sd_info.label,
|
||||||
sd_api_get_fs_type_text(sd_info.fs_type),
|
sd_api_get_fs_type_text(sd_info.fs_type),
|
||||||
sd_info.kb_total,
|
sd_info.kb_total,
|
||||||
sd_info.kb_free,
|
sd_info.kb_free,
|
||||||
sd_cid.ManufacturerID,
|
sd_info.manufacturer_id,
|
||||||
sd_cid.OEM_AppliID,
|
sd_info.oem_id,
|
||||||
sd_cid.ProdName,
|
sd_info.product_name,
|
||||||
sd_cid.ProdRev >> 4,
|
sd_info.product_revision_major,
|
||||||
sd_cid.ProdRev & 0xf,
|
sd_info.product_revision_minor,
|
||||||
sd_cid.ProdSN,
|
sd_info.product_serial_number,
|
||||||
sd_cid.ManufactMonth,
|
sd_info.manufacturing_month,
|
||||||
sd_cid.ManufactYear + 2000);
|
sd_info.manufacturing_year);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
storage_cli_print_usage();
|
storage_cli_print_usage();
|
||||||
|
|||||||
@@ -12,9 +12,7 @@
|
|||||||
|
|
||||||
#define TAG "StorageAPI"
|
#define TAG "StorageAPI"
|
||||||
|
|
||||||
#define S_API_PROLOGUE \
|
#define S_API_PROLOGUE FuriApiLock lock = api_lock_alloc_locked();
|
||||||
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0); \
|
|
||||||
furi_check(semaphore != NULL);
|
|
||||||
|
|
||||||
#define S_FILE_API_PROLOGUE \
|
#define S_FILE_API_PROLOGUE \
|
||||||
Storage* storage = file->storage; \
|
Storage* storage = file->storage; \
|
||||||
@@ -24,13 +22,12 @@
|
|||||||
furi_check( \
|
furi_check( \
|
||||||
furi_message_queue_put(storage->message_queue, &message, FuriWaitForever) == \
|
furi_message_queue_put(storage->message_queue, &message, FuriWaitForever) == \
|
||||||
FuriStatusOk); \
|
FuriStatusOk); \
|
||||||
furi_semaphore_acquire(semaphore, FuriWaitForever); \
|
api_lock_wait_unlock_and_free(lock)
|
||||||
furi_semaphore_free(semaphore);
|
|
||||||
|
|
||||||
#define S_API_MESSAGE(_command) \
|
#define S_API_MESSAGE(_command) \
|
||||||
SAReturn return_data; \
|
SAReturn return_data; \
|
||||||
StorageMessage message = { \
|
StorageMessage message = { \
|
||||||
.semaphore = semaphore, \
|
.lock = lock, \
|
||||||
.command = _command, \
|
.command = _command, \
|
||||||
.data = &data, \
|
.data = &data, \
|
||||||
.return_data = &return_data, \
|
.return_data = &return_data, \
|
||||||
|
|||||||
@@ -31,29 +31,13 @@ void storage_file_clear(StorageFile* obj) {
|
|||||||
/****************** storage data ******************/
|
/****************** storage data ******************/
|
||||||
|
|
||||||
void storage_data_init(StorageData* storage) {
|
void storage_data_init(StorageData* storage) {
|
||||||
storage->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
||||||
furi_check(storage->mutex != NULL);
|
|
||||||
storage->data = NULL;
|
storage->data = NULL;
|
||||||
storage->status = StorageStatusNotReady;
|
storage->status = StorageStatusNotReady;
|
||||||
StorageFileList_init(storage->files);
|
StorageFileList_init(storage->files);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool storage_data_lock(StorageData* storage) {
|
|
||||||
return (furi_mutex_acquire(storage->mutex, FuriWaitForever) == FuriStatusOk);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool storage_data_unlock(StorageData* storage) {
|
|
||||||
return (furi_mutex_release(storage->mutex) == FuriStatusOk);
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageStatus storage_data_status(StorageData* storage) {
|
StorageStatus storage_data_status(StorageData* storage) {
|
||||||
StorageStatus status;
|
return storage->status;
|
||||||
|
|
||||||
storage_data_lock(storage);
|
|
||||||
status = storage->status;
|
|
||||||
storage_data_unlock(storage);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* storage_data_status_text(StorageData* storage) {
|
const char* storage_data_status_text(StorageData* storage) {
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ void storage_file_set(StorageFile* obj, const StorageFile* src);
|
|||||||
void storage_file_clear(StorageFile* obj);
|
void storage_file_clear(StorageFile* obj);
|
||||||
|
|
||||||
void storage_data_init(StorageData* storage);
|
void storage_data_init(StorageData* storage);
|
||||||
bool storage_data_lock(StorageData* storage);
|
|
||||||
bool storage_data_unlock(StorageData* storage);
|
|
||||||
StorageStatus storage_data_status(StorageData* storage);
|
StorageStatus storage_data_status(StorageData* storage);
|
||||||
const char* storage_data_status_text(StorageData* storage);
|
const char* storage_data_status_text(StorageData* storage);
|
||||||
void storage_data_timestamp(StorageData* storage);
|
void storage_data_timestamp(StorageData* storage);
|
||||||
@@ -57,7 +55,6 @@ struct StorageData {
|
|||||||
const FS_Api* fs_api;
|
const FS_Api* fs_api;
|
||||||
StorageApi api;
|
StorageApi api;
|
||||||
void* data;
|
void* data;
|
||||||
FuriMutex* mutex;
|
|
||||||
StorageStatus status;
|
StorageStatus status;
|
||||||
StorageFileList_t files;
|
StorageFileList_t files;
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <toolbox/api_lock.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -130,7 +131,7 @@ typedef enum {
|
|||||||
} StorageCommand;
|
} StorageCommand;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriSemaphore* semaphore;
|
FuriApiLock lock;
|
||||||
StorageCommand command;
|
StorageCommand command;
|
||||||
SAData* data;
|
SAData* data;
|
||||||
SAReturn* return_data;
|
SAReturn* return_data;
|
||||||
|
|||||||
@@ -2,15 +2,7 @@
|
|||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
#include <m-dict.h>
|
#include <m-dict.h>
|
||||||
|
|
||||||
#define FS_CALL(_storage, _fn) \
|
#define FS_CALL(_storage, _fn) ret = _storage->fs_api->_fn;
|
||||||
storage_data_lock(_storage); \
|
|
||||||
ret = _storage->fs_api->_fn; \
|
|
||||||
storage_data_unlock(_storage);
|
|
||||||
|
|
||||||
#define ST_CALL(_storage, _fn) \
|
|
||||||
storage_data_lock(_storage); \
|
|
||||||
ret = _storage->api._fn; \
|
|
||||||
storage_data_unlock(_storage);
|
|
||||||
|
|
||||||
static StorageData* storage_get_storage_by_type(Storage* app, StorageType type) {
|
static StorageData* storage_get_storage_by_type(Storage* app, StorageType type) {
|
||||||
furi_check(type == ST_EXT || type == ST_INT);
|
furi_check(type == ST_EXT || type == ST_INT);
|
||||||
@@ -44,16 +36,11 @@ static const char* remove_vfs(const char* path) {
|
|||||||
|
|
||||||
static StorageType storage_get_type_by_path(Storage* app, const char* path) {
|
static StorageType storage_get_type_by_path(Storage* app, const char* path) {
|
||||||
StorageType type = ST_ERROR;
|
StorageType type = ST_ERROR;
|
||||||
if(strlen(path) >= strlen(STORAGE_EXT_PATH_PREFIX) &&
|
if(memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) {
|
||||||
memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) {
|
|
||||||
type = ST_EXT;
|
type = ST_EXT;
|
||||||
} else if(
|
} else if(memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) {
|
||||||
strlen(path) >= strlen(STORAGE_INT_PATH_PREFIX) &&
|
|
||||||
memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) {
|
|
||||||
type = ST_INT;
|
type = ST_INT;
|
||||||
} else if(
|
} else if(memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) {
|
||||||
strlen(path) >= strlen(STORAGE_ANY_PATH_PREFIX) &&
|
|
||||||
memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) {
|
|
||||||
type = ST_ANY;
|
type = ST_ANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,21 +55,15 @@ static StorageType storage_get_type_by_path(Storage* app, const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) {
|
static void storage_path_change_to_real_storage(FuriString* path, StorageType real_storage) {
|
||||||
if(memcmp(
|
if(furi_string_search(path, STORAGE_ANY_PATH_PREFIX) == 0) {
|
||||||
furi_string_get_cstr(path), STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) ==
|
|
||||||
0) {
|
|
||||||
switch(real_storage) {
|
switch(real_storage) {
|
||||||
case ST_EXT:
|
case ST_EXT:
|
||||||
furi_string_set_char(path, 0, STORAGE_EXT_PATH_PREFIX[0]);
|
furi_string_replace_at(
|
||||||
furi_string_set_char(path, 1, STORAGE_EXT_PATH_PREFIX[1]);
|
path, 0, strlen(STORAGE_EXT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX);
|
||||||
furi_string_set_char(path, 2, STORAGE_EXT_PATH_PREFIX[2]);
|
|
||||||
furi_string_set_char(path, 3, STORAGE_EXT_PATH_PREFIX[3]);
|
|
||||||
break;
|
break;
|
||||||
case ST_INT:
|
case ST_INT:
|
||||||
furi_string_set_char(path, 0, STORAGE_INT_PATH_PREFIX[0]);
|
furi_string_replace_at(
|
||||||
furi_string_set_char(path, 1, STORAGE_INT_PATH_PREFIX[1]);
|
path, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_INT_PATH_PREFIX);
|
||||||
furi_string_set_char(path, 2, STORAGE_INT_PATH_PREFIX[2]);
|
|
||||||
furi_string_set_char(path, 3, STORAGE_INT_PATH_PREFIX[3]);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -604,7 +585,7 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_semaphore_release(message->semaphore);
|
api_lock_unlock(message->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void storage_process_message(Storage* app, StorageMessage* message) {
|
void storage_process_message(Storage* app, StorageMessage* message) {
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ typedef struct {
|
|||||||
uint16_t cluster_size;
|
uint16_t cluster_size;
|
||||||
uint16_t sector_size;
|
uint16_t sector_size;
|
||||||
char label[SD_LABEL_LENGTH];
|
char label[SD_LABEL_LENGTH];
|
||||||
|
|
||||||
|
uint8_t manufacturer_id;
|
||||||
|
char oem_id[3];
|
||||||
|
char product_name[6];
|
||||||
|
uint8_t product_revision_major;
|
||||||
|
uint8_t product_revision_minor;
|
||||||
|
uint32_t product_serial_number;
|
||||||
|
uint8_t manufacturing_month;
|
||||||
|
uint16_t manufacturing_year;
|
||||||
|
|
||||||
FS_Error error;
|
FS_Error error;
|
||||||
} SDInfo;
|
} SDInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,10 @@ static FS_Error storage_ext_parse_error(SDError error);
|
|||||||
|
|
||||||
static bool sd_mount_card(StorageData* storage, bool notify) {
|
static bool sd_mount_card(StorageData* storage, bool notify) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
uint8_t counter = BSP_SD_MaxMountRetryCount();
|
uint8_t counter = sd_max_mount_retry_count();
|
||||||
uint8_t bsp_result;
|
uint8_t bsp_result;
|
||||||
SDData* sd_data = storage->data;
|
SDData* sd_data = storage->data;
|
||||||
|
|
||||||
storage_data_lock(storage);
|
|
||||||
|
|
||||||
while(result == false && counter > 0 && hal_sd_detect()) {
|
while(result == false && counter > 0 && hal_sd_detect()) {
|
||||||
if(notify) {
|
if(notify) {
|
||||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||||
@@ -41,9 +39,9 @@ static bool sd_mount_card(StorageData* storage, bool notify) {
|
|||||||
|
|
||||||
if((counter % 2) == 0) {
|
if((counter % 2) == 0) {
|
||||||
// power reset sd card
|
// power reset sd card
|
||||||
bsp_result = BSP_SD_Init(true);
|
bsp_result = sd_init(true);
|
||||||
} else {
|
} else {
|
||||||
bsp_result = BSP_SD_Init(false);
|
bsp_result = sd_init(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bsp_result) {
|
if(bsp_result) {
|
||||||
@@ -91,7 +89,6 @@ static bool sd_mount_card(StorageData* storage, bool notify) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
storage_data_timestamp(storage);
|
storage_data_timestamp(storage);
|
||||||
storage_data_unlock(storage);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -100,14 +97,12 @@ FS_Error sd_unmount_card(StorageData* storage) {
|
|||||||
SDData* sd_data = storage->data;
|
SDData* sd_data = storage->data;
|
||||||
SDError error;
|
SDError error;
|
||||||
|
|
||||||
storage_data_lock(storage);
|
|
||||||
storage->status = StorageStatusNotReady;
|
storage->status = StorageStatusNotReady;
|
||||||
error = FR_DISK_ERR;
|
error = FR_DISK_ERR;
|
||||||
|
|
||||||
// TODO do i need to close the files?
|
// TODO do i need to close the files?
|
||||||
|
|
||||||
f_mount(0, sd_data->path, 0);
|
f_mount(0, sd_data->path, 0);
|
||||||
storage_data_unlock(storage);
|
|
||||||
return storage_ext_parse_error(error);
|
return storage_ext_parse_error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +115,6 @@ FS_Error sd_format_card(StorageData* storage) {
|
|||||||
SDData* sd_data = storage->data;
|
SDData* sd_data = storage->data;
|
||||||
SDError error;
|
SDError error;
|
||||||
|
|
||||||
storage_data_lock(storage);
|
|
||||||
|
|
||||||
work_area = malloc(_MAX_SS);
|
work_area = malloc(_MAX_SS);
|
||||||
error = f_mkfs(sd_data->path, FM_ANY, 0, work_area, _MAX_SS);
|
error = f_mkfs(sd_data->path, FM_ANY, 0, work_area, _MAX_SS);
|
||||||
free(work_area);
|
free(work_area);
|
||||||
@@ -138,8 +131,6 @@ FS_Error sd_format_card(StorageData* storage) {
|
|||||||
storage->status = StorageStatusOK;
|
storage->status = StorageStatusOK;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
storage_data_unlock(storage);
|
|
||||||
|
|
||||||
return storage_ext_parse_error(error);
|
return storage_ext_parse_error(error);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -156,14 +147,12 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) {
|
|||||||
memset(sd_info, 0, sizeof(SDInfo));
|
memset(sd_info, 0, sizeof(SDInfo));
|
||||||
|
|
||||||
// get fs info
|
// get fs info
|
||||||
storage_data_lock(storage);
|
|
||||||
error = f_getlabel(sd_data->path, sd_info->label, NULL);
|
error = f_getlabel(sd_data->path, sd_info->label, NULL);
|
||||||
if(error == FR_OK) {
|
if(error == FR_OK) {
|
||||||
#ifndef FURI_RAM_EXEC
|
#ifndef FURI_RAM_EXEC
|
||||||
error = f_getfree(sd_data->path, &free_clusters, &fs);
|
error = f_getfree(sd_data->path, &free_clusters, &fs);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
storage_data_unlock(storage);
|
|
||||||
|
|
||||||
if(error == FR_OK) {
|
if(error == FR_OK) {
|
||||||
// calculate size
|
// calculate size
|
||||||
@@ -210,6 +199,20 @@ FS_Error sd_card_info(StorageData* storage, SDInfo* sd_info) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SD_CID cid;
|
||||||
|
SdSpiStatus status = sd_get_cid(&cid);
|
||||||
|
|
||||||
|
if(status == SdSpiStatusOK) {
|
||||||
|
sd_info->manufacturer_id = cid.ManufacturerID;
|
||||||
|
memcpy(sd_info->oem_id, cid.OEM_AppliID, sizeof(cid.OEM_AppliID));
|
||||||
|
memcpy(sd_info->product_name, cid.ProdName, sizeof(cid.ProdName));
|
||||||
|
sd_info->product_revision_major = cid.ProdRev >> 4;
|
||||||
|
sd_info->product_revision_minor = cid.ProdRev & 0x0F;
|
||||||
|
sd_info->product_serial_number = cid.ProdSN;
|
||||||
|
sd_info->manufacturing_year = 2000 + cid.ManufactYear;
|
||||||
|
sd_info->manufacturing_month = cid.ManufactMonth;
|
||||||
|
}
|
||||||
|
|
||||||
return storage_ext_parse_error(error);
|
return storage_ext_parse_error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,29 @@ typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMess
|
|||||||
static DialogMessageButton product_screen(DialogsApp* dialogs, DialogMessage* message) {
|
static DialogMessageButton product_screen(DialogsApp* dialogs, DialogMessage* message) {
|
||||||
DialogMessageButton result;
|
DialogMessageButton result;
|
||||||
|
|
||||||
const char* screen_header = "Product: Flipper Zero\n"
|
FuriString* screen_header = furi_string_alloc_printf(
|
||||||
"Model: FZ.1\n";
|
"Product: %s\n"
|
||||||
const char* screen_text = "FCC ID: 2A2V6-FZ\n"
|
"Model: %s",
|
||||||
"IC: 27624-FZ";
|
furi_hal_version_get_model_name(),
|
||||||
|
furi_hal_version_get_model_code());
|
||||||
|
|
||||||
dialog_message_set_header(message, screen_header, 0, 0, AlignLeft, AlignTop);
|
FuriString* screen_text = furi_string_alloc_printf(
|
||||||
dialog_message_set_text(message, screen_text, 0, 26, AlignLeft, AlignTop);
|
"FCC ID: %s\n"
|
||||||
|
"IC: %s",
|
||||||
|
furi_hal_version_get_fcc_id(),
|
||||||
|
furi_hal_version_get_ic_id());
|
||||||
|
|
||||||
|
dialog_message_set_header(
|
||||||
|
message, furi_string_get_cstr(screen_header), 0, 0, AlignLeft, AlignTop);
|
||||||
|
dialog_message_set_text(
|
||||||
|
message, furi_string_get_cstr(screen_text), 0, 26, AlignLeft, AlignTop);
|
||||||
result = dialog_message_show(dialogs, message);
|
result = dialog_message_show(dialogs, message);
|
||||||
dialog_message_set_header(message, NULL, 0, 0, AlignLeft, AlignTop);
|
dialog_message_set_header(message, NULL, 0, 0, AlignLeft, AlignTop);
|
||||||
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
|
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
|
||||||
|
|
||||||
|
furi_string_free(screen_header);
|
||||||
|
furi_string_free(screen_text);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../bt_settings_app.h"
|
#include "../bt_settings_app.h"
|
||||||
#include "furi_hal_bt.h"
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) {
|
void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../bt_settings_app.h"
|
#include "../bt_settings_app.h"
|
||||||
#include "furi_hal_bt.h"
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
void bt_settings_app_scene_forget_dev_success_popup_callback(void* context) {
|
void bt_settings_app_scene_forget_dev_success_popup_callback(void* context) {
|
||||||
BtSettingsApp* app = context;
|
BtSettingsApp* app = context;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../bt_settings_app.h"
|
#include "../bt_settings_app.h"
|
||||||
#include "furi_hal_bt.h"
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
enum BtSetting {
|
enum BtSetting {
|
||||||
BtSettingOff,
|
BtSettingOff,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "../storage_settings.h"
|
#include "../storage_settings.h"
|
||||||
#include <stm32_adafruit_sd.h>
|
|
||||||
|
|
||||||
static void storage_settings_scene_sd_info_dialog_callback(DialogExResult result, void* context) {
|
static void storage_settings_scene_sd_info_dialog_callback(DialogExResult result, void* context) {
|
||||||
StorageSettings* app = context;
|
StorageSettings* app = context;
|
||||||
@@ -12,9 +11,7 @@ void storage_settings_scene_sd_info_on_enter(void* context) {
|
|||||||
DialogEx* dialog_ex = app->dialog_ex;
|
DialogEx* dialog_ex = app->dialog_ex;
|
||||||
|
|
||||||
SDInfo sd_info;
|
SDInfo sd_info;
|
||||||
SD_CID sd_cid;
|
|
||||||
FS_Error sd_status = storage_sd_info(app->fs_api, &sd_info);
|
FS_Error sd_status = storage_sd_info(app->fs_api, &sd_info);
|
||||||
BSP_SD_GetCIDRegister(&sd_cid);
|
|
||||||
|
|
||||||
scene_manager_set_scene_state(app->scene_manager, StorageSettingsSDInfo, sd_status);
|
scene_manager_set_scene_state(app->scene_manager, StorageSettingsSDInfo, sd_status);
|
||||||
|
|
||||||
@@ -31,19 +28,19 @@ void storage_settings_scene_sd_info_on_enter(void* context) {
|
|||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
app->text_string,
|
app->text_string,
|
||||||
"Label: %s\nType: %s\n%lu KiB total\n%lu KiB free\n"
|
"Label: %s\nType: %s\n%lu KiB total\n%lu KiB free\n"
|
||||||
"%02X%2.2s %5.5s %i.%i\nSN:%04lX %02i/%i",
|
"%02X%s %s v%i.%i\nSN:%04lX %02i/%i",
|
||||||
sd_info.label,
|
sd_info.label,
|
||||||
sd_api_get_fs_type_text(sd_info.fs_type),
|
sd_api_get_fs_type_text(sd_info.fs_type),
|
||||||
sd_info.kb_total,
|
sd_info.kb_total,
|
||||||
sd_info.kb_free,
|
sd_info.kb_free,
|
||||||
sd_cid.ManufacturerID,
|
sd_info.manufacturer_id,
|
||||||
sd_cid.OEM_AppliID,
|
sd_info.oem_id,
|
||||||
sd_cid.ProdName,
|
sd_info.product_name,
|
||||||
sd_cid.ProdRev >> 4,
|
sd_info.product_revision_major,
|
||||||
sd_cid.ProdRev & 0xf,
|
sd_info.product_revision_minor,
|
||||||
sd_cid.ProdSN,
|
sd_info.product_serial_number,
|
||||||
sd_cid.ManufactMonth,
|
sd_info.manufacturing_month,
|
||||||
sd_cid.ManufactYear + 2000);
|
sd_info.manufacturing_year);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, furi_string_get_cstr(app->text_string), 4, 1, AlignLeft, AlignTop);
|
dialog_ex, furi_string_get_cstr(app->text_string), 4, 1, AlignLeft, AlignTop);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "../storage_move_to_sd.h"
|
#include "../storage_move_to_sd.h"
|
||||||
#include "gui/canvas.h"
|
#include <gui/canvas.h>
|
||||||
#include "gui/modules/widget_elements/widget_element_i.h"
|
#include <gui/modules/widget_elements/widget_element_i.h>
|
||||||
#include "storage/storage.h"
|
#include <storage/storage.h>
|
||||||
|
|
||||||
static void storage_move_to_sd_scene_confirm_widget_callback(
|
static void storage_move_to_sd_scene_confirm_widget_callback(
|
||||||
GuiButtonType result,
|
GuiButtonType result,
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "gui/modules/widget_elements/widget_element_i.h"
|
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
#include <notification/notification_messages.h>
|
|
||||||
|
|
||||||
#include <gui/modules/widget.h>
|
#include <gui/modules/widget.h>
|
||||||
#include <gui/modules/popup.h>
|
#include <gui/modules/popup.h>
|
||||||
|
#include <gui/modules/widget_elements/widget_element_i.h>
|
||||||
|
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <storage/storage_sd_api.h>
|
#include <storage/storage_sd_api.h>
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
#include "scenes/storage_move_to_sd_scene.h"
|
#include "scenes/storage_move_to_sd_scene.h"
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ static void updater_cli_ep(Cli* cli, FuriString* args, void* context) {
|
|||||||
for(size_t idx = 0; idx < COUNT_OF(update_cli_subcommands); ++idx) {
|
for(size_t idx = 0; idx < COUNT_OF(update_cli_subcommands); ++idx) {
|
||||||
const CliSubcommand* subcmd_def = &update_cli_subcommands[idx];
|
const CliSubcommand* subcmd_def = &update_cli_subcommands[idx];
|
||||||
if(furi_string_cmp_str(subcommand, subcmd_def->command) == 0) {
|
if(furi_string_cmp_str(subcommand, subcmd_def->command) == 0) {
|
||||||
furi_string_free(subcommand);
|
|
||||||
subcmd_def->handler(args);
|
subcmd_def->handler(args);
|
||||||
|
furi_string_free(subcommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,7 +287,9 @@ bool update_task_parse_manifest(UpdateTask* update_task) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_task_set_progress(update_task, UpdateTaskStageProgress, 50);
|
update_task_set_progress(update_task, UpdateTaskStageProgress, 50);
|
||||||
if(manifest->target != furi_hal_version_get_hw_target()) {
|
/* Check target only if it's set - skipped for pre-production samples */
|
||||||
|
if(furi_hal_version_get_hw_target() &&
|
||||||
|
(manifest->target != furi_hal_version_get_hw_target())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
documentation/HardwareTargets.md
Normal file
44
documentation/HardwareTargets.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
## What a Firmware Target is
|
||||||
|
|
||||||
|
Flipper's firmware is modular and supports different hardware configurations in a common code base. It encapsulates hardware-specific differences in `furi_hal`, board initialization code, linker files, SDK data and other information in a _target definition_.
|
||||||
|
|
||||||
|
Target-specific files are placed in a single sub-folder in `firmware/targets`. It must contain a target definition file, `target.json`, and may contain other files if they are referenced by current target's definition. By default, `fbt` gathers all source files in target folder, unless they are explicitly excluded.
|
||||||
|
|
||||||
|
Targets can inherit most code parts from other targets, to reduce common code duplication.
|
||||||
|
|
||||||
|
|
||||||
|
## Target Definition File
|
||||||
|
|
||||||
|
A target definition file, `target.json`, is a JSON file that can contain the following fields:
|
||||||
|
|
||||||
|
* `include_paths`: list of strings, folder paths relative to current target folder to add to global C/C++ header path lookup list.
|
||||||
|
* `sdk_header_paths`: list of strings, folder paths relative to current target folder to gather headers from for including in SDK.
|
||||||
|
* `startup_script`: filename of a startup script, performing initial hardware initialization.
|
||||||
|
* `linker_script_flash`: filename of a linker script for creating the main firmware image.
|
||||||
|
* `linker_script_ram`: filename of a linker script to use in "updater" build configuration.
|
||||||
|
* `linker_script_app`: filename of a linker script to use for linking .fap files.
|
||||||
|
* `sdk_symbols`: filename of a .csv file containing current SDK configuration for this target.
|
||||||
|
* `linker_dependencies`: list of libraries to link the firmware with. Note that those not in the list won't be built by `fbt`. Also several link passes might be needed, in such case you may need to specify same library name twice.
|
||||||
|
* `inherit`: string, specifies hardware target to borrow main configuration from. Current configuration may specify additional values for parameters that are lists of strings, or override values that are not lists.
|
||||||
|
* `excluded_sources`: list of filenames from the inherited configuration(s) NOT to be built.
|
||||||
|
* `excluded_headers`: list of headers from the inherited configuration(s) NOT to be included in generated SDK.
|
||||||
|
* `excluded_modules`: list of strings specifying fbt library (module) names to exclude from being used to configure build environment.
|
||||||
|
|
||||||
|
|
||||||
|
## Applications & Hardware
|
||||||
|
|
||||||
|
Not all applications are available on different hardware targets.
|
||||||
|
|
||||||
|
* For applications built into the firmware, you have to specify a compatible application set using `FIRMWARE_APP_SET=...` fbt option. See [fbt docs](./fbt.md#firmware-application-set) for details on build configurations.
|
||||||
|
|
||||||
|
* For applications built as external .faps, you have to explicitly specify compatible targets in application's manifest, `application.fam`. For example, to limit application to a single target, add `targets=["f7"],` to the manifest. It won't be built for other targets.
|
||||||
|
|
||||||
|
For details on application manifests, check out [their docs page](./AppManifests.md).
|
||||||
|
|
||||||
|
|
||||||
|
## Building Firmware for a Specific Target
|
||||||
|
|
||||||
|
You have to specify TARGET_HW (and, optionally, FIRMWARE_APP_SET) for `fbt` to build firmware for non-default target. For example, building and flashing debug firmware for f18 can be done with
|
||||||
|
|
||||||
|
./fbt TARGET_HW=18 flash_usb_full
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user