Merge branch 'UNLEASHED' into 420
21
CHANGELOG.md
@@ -1,6 +1,23 @@
|
||||
### New changes
|
||||
* Fix crash when furi_halt is called (was found when you try to power off flipper with usb cable connected)
|
||||
* Fix bug when NFC keys was removed during scan
|
||||
* Plugins: New AM2320 Sensor plugin (@xMasterX)
|
||||
* Plugins -> PR: Added DHT Temperature sensor Monitor (by @quen0n | PR #147) [(plugin repo)](https://github.com/quen0n/FipperZero-DHT-Monitor)
|
||||
* Plugins -> PR: USB Keyboard - added additional row for function keys (by @huuck | PR #145)
|
||||
* Plugins -> PR: Added Morse Code plugin (by @wh00hw | PR #144) [(plugin repo)](https://github.com/wh00hw/MorseCodeFAP)
|
||||
* Plugins -> PR: FlappyBird - Fix animation (by @msvsergey | PR #148)
|
||||
* Plugins: Added Game15 [(by x27)](https://github.com/x27/flipperzero-game15)
|
||||
* Plugins: Update and fix TOTP
|
||||
* Plugins: Update Wifi Marauder
|
||||
* Plugins: fix proper deinit of gpio and spi bus in NRF24 driver
|
||||
* Snake game: Fix food spawn bug
|
||||
* Replaced furi check hotfix with proper fix from OFW
|
||||
* Disable halloween theme
|
||||
* SubGHz: BFT Mitto fix, other small fixes
|
||||
* OFW: WS -> add protocol Ambient_Weather
|
||||
* OFW: Handle storage full error
|
||||
* OFW: fbt fixes for mfbt pt2
|
||||
* OFW: Gui: refactor buttons remapping
|
||||
* OFW: Furi: raise bkpt only if debug session initiated, add debug support for release builds
|
||||
* OFW PR: BadUSB scrolllock typo fix (OFW PR 1968 by nminaylov)
|
||||
|
||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
10
SConstruct
@@ -33,10 +33,6 @@ coreenv = SConscript(
|
||||
)
|
||||
SConscript("site_scons/cc.scons", exports={"ENV": coreenv})
|
||||
|
||||
# Store root dir in environment for certain tools
|
||||
coreenv["ROOT_DIR"] = Dir(".")
|
||||
|
||||
|
||||
# Create a separate "dist" environment and add construction envs to it
|
||||
distenv = coreenv.Clone(
|
||||
tools=[
|
||||
@@ -233,13 +229,13 @@ distenv.PhonyTarget(
|
||||
# Linter
|
||||
distenv.PhonyTarget(
|
||||
"lint",
|
||||
"${PYTHON3} scripts/lint.py check ${LINT_SOURCES}",
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format",
|
||||
"${PYTHON3} scripts/lint.py format ${LINT_SOURCES}",
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=firmware_env["LINT_SOURCES"],
|
||||
)
|
||||
|
||||
@@ -280,7 +276,7 @@ distenv.PhonyTarget(
|
||||
)
|
||||
|
||||
# Start Flipper CLI via PySerial's miniterm
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} scripts/serial_cli.py")
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
|
||||
@@ -86,7 +86,7 @@ static const DuckyKey ducky_keys[] = {
|
||||
{"PAGEUP", HID_KEYBOARD_PAGE_UP},
|
||||
{"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN},
|
||||
{"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN},
|
||||
{"SCROLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SPACE", HID_KEYBOARD_SPACEBAR},
|
||||
{"TAB", HID_KEYBOARD_TAB},
|
||||
{"MENU", HID_KEYBOARD_APPLICATION},
|
||||
|
||||
@@ -67,6 +67,8 @@ bool subghz_scene_set_seed_bft_on_event(void* context, SceneManagerEvent event)
|
||||
flipper_format_write_hex(
|
||||
subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t));
|
||||
|
||||
flipper_format_write_string_cstr(subghz->txrx->fff_data, "Manufacture", "BFT");
|
||||
|
||||
generated_protocol = true;
|
||||
} else {
|
||||
generated_protocol = false;
|
||||
|
||||
14
applications/plugins/am2320_temp_sensor/application.fam
Normal file
@@ -0,0 +1,14 @@
|
||||
App(
|
||||
appid="am2320_temp_sensor",
|
||||
name="[AM2320] Temp. Sensor",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="am_temperature_sensor_app",
|
||||
cdefines=["APP_AM_TEMPERATURE_SENSOR"],
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
order=90,
|
||||
fap_icon="temperature_sensor.png",
|
||||
fap_category="GPIO",
|
||||
)
|
||||
336
applications/plugins/am2320_temp_sensor/temperature_sensor.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* Flipper Plugin to read the values from a AM2320/AM2321 Sensor */
|
||||
/* Created by @xMasterX, original app (was used as template) by Mywk - https://github.com/Mywk */
|
||||
/* Lib used as reference: https://github.com/Gozem/am2320/blob/master/am2321.c*/
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_i2c.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TS_DEFAULT_VALUE 0xFFFF
|
||||
|
||||
#define AM2320_ADDRESS (0x5C << 1)
|
||||
|
||||
#define DATA_BUFFER_SIZE 8
|
||||
|
||||
// External I2C BUS
|
||||
#define I2C_BUS &furi_hal_i2c_handle_external
|
||||
|
||||
typedef enum {
|
||||
TSSInitializing,
|
||||
TSSNoSensor,
|
||||
TSSPendingUpdate,
|
||||
} TSStatus;
|
||||
|
||||
typedef enum {
|
||||
TSEventTypeTick,
|
||||
TSEventTypeInput,
|
||||
} TSEventType;
|
||||
|
||||
typedef struct {
|
||||
TSEventType type;
|
||||
InputEvent input;
|
||||
} TSEvent;
|
||||
|
||||
extern const NotificationSequence sequence_blink_red_100;
|
||||
extern const NotificationSequence sequence_blink_blue_100;
|
||||
|
||||
static TSStatus temperature_sensor_current_status = TSSInitializing;
|
||||
|
||||
// Temperature and Humidity data buffers, ready to print
|
||||
char ts_data_buffer_temperature_c[DATA_BUFFER_SIZE];
|
||||
char ts_data_buffer_temperature_f[DATA_BUFFER_SIZE];
|
||||
char ts_data_buffer_relative_humidity[DATA_BUFFER_SIZE];
|
||||
char ts_data_buffer_absolute_humidity[DATA_BUFFER_SIZE];
|
||||
|
||||
// CRC16 calculation
|
||||
static uint16_t get_crc16(const uint8_t* buf, size_t len) {
|
||||
uint16_t crc = 0xFFFF;
|
||||
|
||||
while(len--) {
|
||||
crc ^= (uint16_t)*buf++;
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(crc & 0x0001) {
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
// Combine bytes
|
||||
static uint16_t combine_bytes(uint8_t msb, uint8_t lsb) {
|
||||
return ((uint16_t)msb << 8) | (uint16_t)lsb;
|
||||
}
|
||||
|
||||
// Executes an I2C wake up, sends command and reads result
|
||||
// true if fetch was successful, false otherwise
|
||||
static bool temperature_sensor_get_data(uint8_t* buffer, uint8_t size) {
|
||||
uint32_t timeout = furi_ms_to_ticks(100);
|
||||
uint8_t cmdbuffer[3] = {0, 0, 0};
|
||||
bool ret = false;
|
||||
|
||||
// Aquire I2C bus
|
||||
furi_hal_i2c_acquire(I2C_BUS);
|
||||
|
||||
// Wake UP AM2320 (sensor goes to sleep to not warm up and affect the humidity sensor)
|
||||
furi_hal_i2c_is_device_ready(I2C_BUS, (uint8_t)AM2320_ADDRESS, timeout);
|
||||
// Check if device woken up then we do next stuff
|
||||
if(furi_hal_i2c_is_device_ready(I2C_BUS, (uint8_t)AM2320_ADDRESS, timeout)) {
|
||||
// Wait a bit
|
||||
furi_delay_us(1000);
|
||||
|
||||
// Prepare command: Addr 0x03, start register = 0x00, number of registers to read = 0x04
|
||||
cmdbuffer[0] = 0x03;
|
||||
cmdbuffer[1] = 0x00;
|
||||
cmdbuffer[2] = 0x04;
|
||||
|
||||
// Transmit command to read registers
|
||||
ret = furi_hal_i2c_tx(I2C_BUS, (uint8_t)AM2320_ADDRESS, cmdbuffer, 3, timeout);
|
||||
|
||||
// Wait a bit
|
||||
furi_delay_us(1600);
|
||||
if(ret) {
|
||||
/*
|
||||
* Read out 8 bytes of data
|
||||
* Byte 0: Should be Modbus function code 0x03
|
||||
* Byte 1: Should be number of registers to read (0x04)
|
||||
* Byte 2: Humidity msb
|
||||
* Byte 3: Humidity lsb
|
||||
* Byte 4: Temperature msb
|
||||
* Byte 5: Temperature lsb
|
||||
* Byte 6: CRC lsb byte
|
||||
* Byte 7: CRC msb byte
|
||||
*/
|
||||
ret = furi_hal_i2c_rx(I2C_BUS, (uint8_t)AM2320_ADDRESS, buffer, size, timeout);
|
||||
}
|
||||
}
|
||||
// Release i2c bus
|
||||
furi_hal_i2c_release(I2C_BUS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Fetches temperature and humidity from sensor
|
||||
// Temperature and humidity must be preallocated
|
||||
// true if fetch was successful, false otherwise
|
||||
static bool temperature_sensor_fetch_info(double* temperature, double* humidity) {
|
||||
*humidity = (float)0;
|
||||
bool ret = false;
|
||||
|
||||
uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
// Fetch data from sensor
|
||||
ret = temperature_sensor_get_data(buffer, 8);
|
||||
|
||||
// If we got no result
|
||||
if(!ret) return false;
|
||||
|
||||
if(buffer[0] != 0x03) return false; // must be 0x03 modbus reply
|
||||
if(buffer[1] != 0x04) return false; // must be 0x04 number of registers reply
|
||||
|
||||
// Check CRC16 sum, if not correct - return false
|
||||
uint16_t crcdata = get_crc16(buffer, 6);
|
||||
uint16_t crcread = combine_bytes(buffer[7], buffer[6]);
|
||||
if(crcdata != crcread) return false;
|
||||
|
||||
// Combine bytes for temp and humidity
|
||||
uint16_t temp16 = combine_bytes(buffer[4], buffer[5]);
|
||||
uint16_t humi16 = combine_bytes(buffer[2], buffer[3]);
|
||||
|
||||
/* Temperature resolution is 16Bit,
|
||||
* temperature highest bit (Bit15) is equal to 1 indicates a
|
||||
* negative temperature, the temperature highest bit (Bit15)
|
||||
* is equal to 0 indicates a positive temperature;
|
||||
* temperature in addition to the most significant bit (Bit14 ~ Bit0)
|
||||
* indicates the temperature sensor string value.
|
||||
* Temperature sensor value is a string of 10 times the
|
||||
* actual temperature value.
|
||||
*/
|
||||
if(temp16 & 0x8000) {
|
||||
temp16 = -(temp16 & 0x7FFF);
|
||||
}
|
||||
|
||||
// Prepare output data
|
||||
*temperature = (float)temp16 / 10.0;
|
||||
*humidity = (float)humi16 / 10.0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Draw callback
|
||||
|
||||
static void temperature_sensor_draw_callback(Canvas* canvas, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 2, 10, "AM2320/AM2321 Sensor");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 2, 62, "Press back to exit.");
|
||||
|
||||
switch(temperature_sensor_current_status) {
|
||||
case TSSInitializing:
|
||||
canvas_draw_str(canvas, 2, 30, "Initializing..");
|
||||
break;
|
||||
case TSSNoSensor:
|
||||
canvas_draw_str(canvas, 2, 30, "No sensor found!");
|
||||
break;
|
||||
case TSSPendingUpdate: {
|
||||
canvas_draw_str(canvas, 3, 24, "Temperature");
|
||||
canvas_draw_str(canvas, 68, 24, "Humidity");
|
||||
|
||||
// Draw vertical lines
|
||||
canvas_draw_line(canvas, 61, 16, 61, 50);
|
||||
canvas_draw_line(canvas, 62, 16, 62, 50);
|
||||
|
||||
// Draw horizontal line
|
||||
canvas_draw_line(canvas, 2, 27, 122, 27);
|
||||
|
||||
// Draw temperature and humidity values
|
||||
canvas_draw_str(canvas, 8, 38, ts_data_buffer_temperature_c);
|
||||
canvas_draw_str(canvas, 42, 38, "C");
|
||||
canvas_draw_str(canvas, 8, 48, ts_data_buffer_temperature_f);
|
||||
canvas_draw_str(canvas, 42, 48, "F");
|
||||
canvas_draw_str(canvas, 68, 38, ts_data_buffer_relative_humidity);
|
||||
canvas_draw_str(canvas, 100, 38, "%");
|
||||
canvas_draw_str(canvas, 68, 48, ts_data_buffer_absolute_humidity);
|
||||
canvas_draw_str(canvas, 100, 48, "g/m3");
|
||||
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Input callback
|
||||
|
||||
static void temperature_sensor_input_callback(InputEvent* input_event, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
|
||||
TSEvent event = {.type = TSEventTypeInput, .input = *input_event};
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
}
|
||||
|
||||
// Timer callback
|
||||
|
||||
static void temperature_sensor_timer_callback(FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
TSEvent event = {.type = TSEventTypeTick};
|
||||
furi_message_queue_put(event_queue, &event, 0);
|
||||
}
|
||||
|
||||
// App entry point
|
||||
|
||||
int32_t am_temperature_sensor_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
// Declare our variables and assign variables a default value
|
||||
TSEvent tsEvent;
|
||||
bool sensorFound = false;
|
||||
double celsius, fahrenheit, rel_humidity, abs_humidity = TS_DEFAULT_VALUE;
|
||||
|
||||
// Used for absolute humidity calculation
|
||||
double vapour_pressure = 0;
|
||||
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(TSEvent));
|
||||
|
||||
// Register callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, temperature_sensor_draw_callback, NULL);
|
||||
view_port_input_callback_set(view_port, temperature_sensor_input_callback, event_queue);
|
||||
|
||||
// Create timer and register its callback
|
||||
FuriTimer* timer =
|
||||
furi_timer_alloc(temperature_sensor_timer_callback, FuriTimerTypePeriodic, event_queue);
|
||||
furi_timer_start(timer, furi_kernel_get_tick_frequency());
|
||||
|
||||
// Register viewport
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
// Used to notify the user by blinking red (error) or blue (fetch successful)
|
||||
NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
while(1) {
|
||||
furi_check(furi_message_queue_get(event_queue, &tsEvent, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
// Handle events
|
||||
if(tsEvent.type == TSEventTypeInput) {
|
||||
// Exit on back key
|
||||
if(tsEvent.input.key ==
|
||||
InputKeyBack) // We dont check for type here, we can check the type of keypress like: (event.input.type == InputTypeShort)
|
||||
break;
|
||||
|
||||
} else if(tsEvent.type == TSEventTypeTick) {
|
||||
// Update sensor data
|
||||
// Fetch data and set the sensor current status accordingly
|
||||
sensorFound = temperature_sensor_fetch_info(&celsius, &rel_humidity);
|
||||
temperature_sensor_current_status = (sensorFound ? TSSPendingUpdate : TSSNoSensor);
|
||||
|
||||
if(sensorFound) {
|
||||
// Blink blue
|
||||
notification_message(notifications, &sequence_blink_blue_100);
|
||||
|
||||
if(celsius != TS_DEFAULT_VALUE && rel_humidity != TS_DEFAULT_VALUE) {
|
||||
// Convert celsius to fahrenheit
|
||||
fahrenheit = (celsius * 9 / 5) + 32;
|
||||
|
||||
// Calculate absolute humidity - For more info refer to https://github.com/Mywk/FlipperTemperatureSensor/issues/1
|
||||
// Calculate saturation vapour pressure first
|
||||
vapour_pressure =
|
||||
(double)6.11 *
|
||||
pow(10, (double)(((double)7.5 * celsius) / ((double)237.3 + celsius)));
|
||||
// Then the vapour pressure in Pa
|
||||
vapour_pressure = vapour_pressure * rel_humidity;
|
||||
// Calculate absolute humidity
|
||||
abs_humidity =
|
||||
(double)2.16679 * (double)(vapour_pressure / ((double)273.15 + celsius));
|
||||
|
||||
// Fill our buffers here, not on the canvas draw callback
|
||||
snprintf(ts_data_buffer_temperature_c, DATA_BUFFER_SIZE, "%.2f", celsius);
|
||||
snprintf(ts_data_buffer_temperature_f, DATA_BUFFER_SIZE, "%.2f", fahrenheit);
|
||||
snprintf(
|
||||
ts_data_buffer_relative_humidity, DATA_BUFFER_SIZE, "%.2f", rel_humidity);
|
||||
snprintf(
|
||||
ts_data_buffer_absolute_humidity, DATA_BUFFER_SIZE, "%.2f", abs_humidity);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Reset our variables to their default values
|
||||
celsius = fahrenheit = rel_humidity = abs_humidity = TS_DEFAULT_VALUE;
|
||||
|
||||
// Blink red
|
||||
notification_message(notifications, &sequence_blink_red_100);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t wait_ticks = furi_ms_to_ticks(!sensorFound ? 100 : 500);
|
||||
furi_delay_tick(wait_ticks);
|
||||
}
|
||||
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
// Dobby is freee (free our variables, Flipper will crash if we don't do this!)
|
||||
furi_timer_free(timer);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 181 B |
@@ -448,14 +448,13 @@ int32_t arkanoid_game_app(void* p) {
|
||||
arkanoid_state->ball_state.dy = -1;
|
||||
//start the game flag
|
||||
arkanoid_state->gameStarted = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Event timeout
|
||||
FURI_LOG_D(TAG, "furi_message_queue: Event timeout");
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
|
||||
@@ -523,12 +523,11 @@ int32_t barcode_UPCA_generator_app(void* p) {
|
||||
plugin_state->modeIndex = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("barcode_UPCA_generator", "osMessageQueue: event timeout");
|
||||
// event timeout
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
|
||||
@@ -442,6 +442,8 @@ int32_t quenon_dht_mon_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@ void sensorEdit_scene(PluginData* app) {
|
||||
app->item, DHTMon_GPIO_getName(app->currentSensorEdit->GPIO));
|
||||
variable_item_list_add(variable_item_list, "Save", 1, NULL, app);
|
||||
|
||||
//Сброс выбранного пункта в ноль
|
||||
variable_item_list_set_selected_item(variable_item_list, 0);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ADDSENSOR_MENU_VIEW);
|
||||
}
|
||||
void sensorEdit_sceneRemove(void) {
|
||||
|
||||
@@ -350,14 +350,13 @@ int32_t flappy_game_app(void* p) {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(event.type == EventTypeTick) {
|
||||
flappy_game_tick(game_state);
|
||||
}
|
||||
} else {
|
||||
// FURI_LOG_D(TAG, "osMessageQueue: event timeout");
|
||||
// event timeout
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
|
||||
@@ -134,6 +134,8 @@ void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* cont
|
||||
case InputKeyBack:
|
||||
context->is_running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +159,8 @@ void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* conte
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,6 +546,8 @@ void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* cont
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,8 @@ void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* co
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneSelectFile;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
# Game "15" for Flipper Zero
|
||||
|
||||
[Original link](https://github.com/x27/flipperzero-game15)
|
||||
|
||||
Logic game [Wikipedia](https://en.wikipedia.org/wiki/15_puzzle)
|
||||
|
||||

|
||||
@@ -9,4 +11,3 @@ Logic game [Wikipedia](https://en.wikipedia.org/wiki/15_puzzle)
|
||||
|
||||

|
||||
|
||||
FAP file for firmware 0.69.1
|
||||
|
||||
@@ -426,6 +426,8 @@ static void game_event_handler(GameEvent const event) {
|
||||
sandbox_loop_exit();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(event.type == EventTypeTick) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# GPS for Flipper Zero
|
||||
|
||||
A simple Flipper Zero application for NMEA 0183 serial GPS modules, such as the
|
||||
|
||||
[Original link](https://github.com/ezod/flipperzero-gps)
|
||||
[Adafruit Ultimate GPS Breakout].
|
||||
|
||||
[Original link](https://github.com/ezod/flipperzero-gps)
|
||||
|
||||
@@ -110,11 +110,11 @@ int32_t gps_app(void* p) {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("GPS", "FuriMessageQueue: event timeout");
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
|
||||
@@ -230,6 +230,8 @@ int32_t hc_sr04_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 914 KiB After Width: | Height: | Size: 914 KiB |
BIN
applications/plugins/htu21d_temp_sensor/temperature_sensor.png
Normal file
|
After Width: | Height: | Size: 181 B |
@@ -320,6 +320,8 @@ int32_t metronome_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(event.input.type == InputTypeLong) {
|
||||
// hold events
|
||||
@@ -340,6 +342,8 @@ int32_t metronome_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(event.input.type == InputTypeRepeat) {
|
||||
// repeat events
|
||||
@@ -359,6 +363,8 @@ int32_t metronome_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,6 +476,8 @@ int32_t minesweeper_app(void* p) {
|
||||
// Exit the plugin
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(event.input.type == InputTypeLong) {
|
||||
// hold events
|
||||
@@ -493,6 +495,8 @@ int32_t minesweeper_app(void* p) {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ typedef struct {
|
||||
MorseCodeWorker* worker;
|
||||
} MorseCode;
|
||||
|
||||
|
||||
static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
MorseCode* morse_code = ctx;
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
@@ -35,19 +34,25 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
//write words
|
||||
elements_multiline_text_aligned(canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words));
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words));
|
||||
|
||||
// volume view_port
|
||||
// volume view_port
|
||||
uint8_t vol_bar_x_pos = 124;
|
||||
uint8_t vol_bar_y_pos = 0;
|
||||
const uint8_t volume_h =
|
||||
(64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume;
|
||||
const uint8_t volume_h = (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume;
|
||||
canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64);
|
||||
canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h);
|
||||
|
||||
//dit bpm
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 0, 10, AlignLeft, AlignCenter, furi_string_get_cstr(furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta)));
|
||||
canvas,
|
||||
0,
|
||||
10,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
furi_string_get_cstr(
|
||||
furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta)));
|
||||
|
||||
//button info
|
||||
elements_button_center(canvas, "Press/Hold");
|
||||
@@ -59,9 +64,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void morse_code_worker_callback(
|
||||
FuriString* words,
|
||||
void* context) {
|
||||
static void morse_code_worker_callback(FuriString* words, void* context) {
|
||||
MorseCode* morse_code = context;
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
morse_code->model->words = words;
|
||||
@@ -115,42 +118,42 @@ int32_t morse_code_app() {
|
||||
InputEvent input;
|
||||
morse_code_worker_start(morse_code->worker);
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == FuriStatusOk){
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) ==
|
||||
FuriStatusOk) {
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
if(input.key == InputKeyBack) {
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
break;
|
||||
}else if(input.key == InputKeyOk){
|
||||
if(input.type == InputTypePress)
|
||||
morse_code_worker_play(morse_code->worker, true);
|
||||
else if(input.type == InputTypeRelease)
|
||||
morse_code_worker_play(morse_code->worker, false);
|
||||
}else if(input.key == InputKeyUp && input.type == InputTypePress){
|
||||
if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1)
|
||||
morse_code->model->volume++;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
}else if(input.key == InputKeyDown && input.type == InputTypePress){
|
||||
if(morse_code->model->volume > 0)
|
||||
morse_code->model->volume--;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
}else if(input.key == InputKeyLeft && input.type == InputTypePress){
|
||||
if(morse_code->model->dit_delta > 10)
|
||||
morse_code->model->dit_delta-=10;
|
||||
morse_code_worker_set_dit_delta(
|
||||
morse_code->worker, morse_code->model->dit_delta);
|
||||
}
|
||||
else if(input.key == InputKeyRight && input.type == InputTypePress){
|
||||
if(morse_code->model->dit_delta >= 10)
|
||||
morse_code->model->dit_delta+=10;
|
||||
morse_code_worker_set_dit_delta(
|
||||
morse_code->worker, morse_code->model->dit_delta);
|
||||
}
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
break;
|
||||
} else if(input.key == InputKeyOk) {
|
||||
if(input.type == InputTypePress)
|
||||
morse_code_worker_play(morse_code->worker, true);
|
||||
else if(input.type == InputTypeRelease)
|
||||
morse_code_worker_play(morse_code->worker, false);
|
||||
} else if(input.key == InputKeyUp && input.type == InputTypePress) {
|
||||
if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1)
|
||||
morse_code->model->volume++;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
} else if(input.key == InputKeyDown && input.type == InputTypePress) {
|
||||
if(morse_code->model->volume > 0) morse_code->model->volume--;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
} else if(input.key == InputKeyLeft && input.type == InputTypePress) {
|
||||
if(morse_code->model->dit_delta > 10) morse_code->model->dit_delta -= 10;
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
} else if(input.key == InputKeyRight && input.type == InputTypePress) {
|
||||
if(morse_code->model->dit_delta >= 10) morse_code->model->dit_delta += 10;
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
}
|
||||
|
||||
FURI_LOG_D("Input", "%s %s %ld", input_get_key_name(input.key), input_get_type_name(input.type), input.sequence);
|
||||
FURI_LOG_D(
|
||||
"Input",
|
||||
"%s %s %ld",
|
||||
input_get_key_name(input.key),
|
||||
input_get_type_name(input.type),
|
||||
input.sequence);
|
||||
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
view_port_update(morse_code->view_port);
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
#include <furi_hal.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
|
||||
|
||||
#define TAG "MorseCodeWorker"
|
||||
|
||||
#define MORSE_CODE_VERSION 0
|
||||
|
||||
//A-Z0-1
|
||||
const char morse_array[36][6] ={
|
||||
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.",
|
||||
"--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....",
|
||||
"-....", "--...", "---..", "----.", "-----"
|
||||
};
|
||||
const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||
'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
const char morse_array[36][6] = {".-", "-...", "-.-.", "-..", ".", "..-.",
|
||||
"--.", "....", "..", ".---", "-.-", ".-..",
|
||||
"--", "-.", "---", ".--.", "--.-", ".-.",
|
||||
"...", "-", "..-", "...-", ".--", "-..-",
|
||||
"-.--", "--..", ".----", "..---", "...--", "....-",
|
||||
".....", "-....", "--...", "---..", "----.", "-----"};
|
||||
const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
|
||||
struct MorseCodeWorker {
|
||||
FuriThread* thread;
|
||||
@@ -28,31 +29,28 @@ struct MorseCodeWorker {
|
||||
FuriString* words;
|
||||
};
|
||||
|
||||
void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration){
|
||||
void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration) {
|
||||
FURI_LOG_D("MorseCode: Duration", "%ld", duration);
|
||||
if( duration <= instance->dit_delta)
|
||||
if(duration <= instance->dit_delta)
|
||||
furi_string_push_back(instance->buffer, *DOT);
|
||||
else if(duration <= (instance->dit_delta * 3))
|
||||
furi_string_push_back(instance->buffer, *LINE);
|
||||
if(furi_string_size(instance->buffer) > 5)
|
||||
furi_string_reset(instance->buffer);
|
||||
if(furi_string_size(instance->buffer) > 5) furi_string_reset(instance->buffer);
|
||||
FURI_LOG_D("MorseCode: Buffer", "%s", furi_string_get_cstr(instance->buffer));
|
||||
}
|
||||
|
||||
void morse_code_worker_fill_letter(MorseCodeWorker* instance){
|
||||
if(furi_string_size(instance->words) > 63)
|
||||
furi_string_reset(instance->words);
|
||||
for (size_t i = 0; i < sizeof(morse_array); i++){
|
||||
if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0){
|
||||
furi_string_push_back(instance->words, symbol_array[i]);
|
||||
furi_string_reset(instance->buffer);
|
||||
break;
|
||||
}
|
||||
void morse_code_worker_fill_letter(MorseCodeWorker* instance) {
|
||||
if(furi_string_size(instance->words) > 63) furi_string_reset(instance->words);
|
||||
for(size_t i = 0; i < sizeof(morse_array); i++) {
|
||||
if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0) {
|
||||
furi_string_push_back(instance->words, symbol_array[i]);
|
||||
furi_string_reset(instance->buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
FURI_LOG_D("MorseCode: Words", "%s", furi_string_get_cstr(instance->words));
|
||||
}
|
||||
|
||||
|
||||
static int32_t morse_code_worker_thread_callback(void* context) {
|
||||
furi_assert(context);
|
||||
MorseCodeWorker* instance = context;
|
||||
@@ -61,16 +59,16 @@ static int32_t morse_code_worker_thread_callback(void* context) {
|
||||
uint32_t end_tick = 0;
|
||||
bool pushed = true;
|
||||
bool spaced = true;
|
||||
while(instance->is_running){
|
||||
while(instance->is_running) {
|
||||
furi_delay_ms(SLEEP);
|
||||
if(instance->play){
|
||||
if(!was_playing){
|
||||
if(instance->play) {
|
||||
if(!was_playing) {
|
||||
start_tick = furi_get_tick();
|
||||
furi_hal_speaker_start(FREQUENCY, instance->volume);
|
||||
was_playing = true;
|
||||
}
|
||||
}else{
|
||||
if(was_playing){
|
||||
} else {
|
||||
if(was_playing) {
|
||||
pushed = false;
|
||||
spaced = false;
|
||||
furi_hal_speaker_stop();
|
||||
@@ -80,21 +78,21 @@ static int32_t morse_code_worker_thread_callback(void* context) {
|
||||
start_tick = 0;
|
||||
}
|
||||
}
|
||||
if(!pushed){
|
||||
if(end_tick + (instance->dit_delta * 3) < furi_get_tick()){
|
||||
if(!pushed) {
|
||||
if(end_tick + (instance->dit_delta * 3) < furi_get_tick()) {
|
||||
//NEW LETTER
|
||||
morse_code_worker_fill_letter(instance);
|
||||
if(instance->callback)
|
||||
instance->callback(instance->words, instance->callback_context);
|
||||
instance->callback(instance->words, instance->callback_context);
|
||||
pushed = true;
|
||||
}
|
||||
}
|
||||
if(!spaced){
|
||||
if(end_tick + (instance->dit_delta * 7) < furi_get_tick()){
|
||||
if(!spaced) {
|
||||
if(end_tick + (instance->dit_delta * 7) < furi_get_tick()) {
|
||||
//NEW WORD
|
||||
furi_string_push_back(instance->words, *SPACE);
|
||||
if(instance->callback)
|
||||
instance->callback(instance->words, instance->callback_context);
|
||||
instance->callback(instance->words, instance->callback_context);
|
||||
spaced = true;
|
||||
}
|
||||
}
|
||||
@@ -132,17 +130,17 @@ void morse_code_worker_set_callback(
|
||||
instance->callback_context = context;
|
||||
}
|
||||
|
||||
void morse_code_worker_play(MorseCodeWorker* instance, bool play){
|
||||
void morse_code_worker_play(MorseCodeWorker* instance, bool play) {
|
||||
furi_assert(instance);
|
||||
instance->play = play;
|
||||
}
|
||||
|
||||
void morse_code_worker_set_volume(MorseCodeWorker* instance, float level){
|
||||
void morse_code_worker_set_volume(MorseCodeWorker* instance, float level) {
|
||||
furi_assert(instance);
|
||||
instance->volume = level;
|
||||
}
|
||||
|
||||
void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta){
|
||||
void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta) {
|
||||
furi_assert(instance);
|
||||
instance->dit_delta = delta;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
#define LINE "-"
|
||||
#define SPACE " "
|
||||
|
||||
typedef void (*MorseCodeWorkerCallback)(
|
||||
FuriString* buffer,
|
||||
void* context);
|
||||
typedef void (*MorseCodeWorkerCallback)(FuriString* buffer, void* context);
|
||||
|
||||
typedef struct MorseCodeWorker MorseCodeWorker;
|
||||
|
||||
@@ -34,9 +32,3 @@ void morse_code_worker_play(MorseCodeWorker* instance, bool play);
|
||||
void morse_code_worker_set_volume(MorseCodeWorker* instance, float level);
|
||||
|
||||
void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -374,6 +374,8 @@ int32_t mousejacker_app(void* p) {
|
||||
plugin_state->close_thread_please = false;
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,7 +386,7 @@ int32_t mousejacker_app(void* p) {
|
||||
}
|
||||
|
||||
furi_thread_free(plugin_state->mjthread);
|
||||
furi_hal_spi_release(nrf24_HANDLE);
|
||||
nrf24_deinit();
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
@@ -400,6 +400,8 @@ int32_t nrfsniff_app(void* p) {
|
||||
case InputKeyBack:
|
||||
if(event.input.type == InputTypeLong) processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,7 +446,7 @@ int32_t nrfsniff_app(void* p) {
|
||||
sample_time = DEFAULT_SAMPLE_TIME;
|
||||
target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps)
|
||||
sniffing_state = false;
|
||||
furi_hal_spi_release(nrf24_HANDLE);
|
||||
nrf24_deinit();
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
BIN
applications/plugins/picopass/125_10px.png
Normal file
|
After Width: | Height: | Size: 308 B |
@@ -9,7 +9,8 @@ App(
|
||||
],
|
||||
stack_size=4 * 1024,
|
||||
order=175,
|
||||
fap_icon="../../../assets/icons/Archive/125_10px.png",
|
||||
order=30,
|
||||
fap_icon="125_10px.png",
|
||||
fap_category="Tools",
|
||||
fap_libs=["mbedtls"],
|
||||
fap_private_libs=[
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <st25r3916.h>
|
||||
#include <rfal_analogConfig.h>
|
||||
#include <rfal_rf.h>
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "rfal_picopass.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define RFAL_PICOPASS_TXRX_FLAGS \
|
||||
(FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | \
|
||||
@@ -97,7 +96,7 @@ FuriHalNfcReturn rfalPicoPassPollerSelect(uint8_t* csn, rfalPicoPassSelectRes* s
|
||||
|
||||
rfalPicoPassSelectReq selReq;
|
||||
selReq.CMD = RFAL_PICOPASS_CMD_SELECT;
|
||||
ST_MEMCPY(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN);
|
||||
memcpy(selReq.CSN, csn, RFAL_PICOPASS_UID_LEN);
|
||||
uint16_t recvLen = 0;
|
||||
uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS;
|
||||
uint32_t fwt = furi_hal_nfc_ll_ms2fc(20);
|
||||
@@ -146,8 +145,8 @@ FuriHalNfcReturn rfalPicoPassPollerCheck(uint8_t* mac, rfalPicoPassCheckRes* chk
|
||||
FuriHalNfcReturn ret;
|
||||
rfalPicoPassCheckReq chkReq;
|
||||
chkReq.CMD = RFAL_PICOPASS_CMD_CHECK;
|
||||
ST_MEMCPY(chkReq.mac, mac, 4);
|
||||
ST_MEMSET(chkReq.null, 0, 4);
|
||||
memcpy(chkReq.mac, mac, 4);
|
||||
memset(chkReq.null, 0, 4);
|
||||
uint16_t recvLen = 0;
|
||||
uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS;
|
||||
uint32_t fwt = furi_hal_nfc_ll_ms2fc(20);
|
||||
|
||||
@@ -143,6 +143,8 @@ int32_t sentry_safe_app(void* p) {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@ static Point snake_game_get_new_fruit(SnakeState const* const snake_state) {
|
||||
if((buffer[y] & mask) == 0) {
|
||||
if(newFruit == 0) {
|
||||
Point p = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.x = x * 2,
|
||||
.y = y * 2,
|
||||
};
|
||||
return p;
|
||||
}
|
||||
@@ -361,6 +361,8 @@ int32_t snake_game_app(void* p) {
|
||||
snake_game_save_game_to_file(snake_state);
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(event.type == EventTypeTick) {
|
||||
|
||||
@@ -496,6 +496,8 @@ int32_t spectrum_analyzer_app(void* p) {
|
||||
case InputKeyBack:
|
||||
exit_loop = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
furi_mutex_release(spectrum_analyzer->model_mutex);
|
||||
|
||||
@@ -442,6 +442,8 @@ int32_t tetris_game_app() {
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(event.type == EventTypeTick) {
|
||||
|
||||
@@ -358,12 +358,11 @@ int32_t tictactoe_game_app(void* p) {
|
||||
case InputKeyOk:
|
||||
tictactoe_state->button_state = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Event timeout
|
||||
FURI_LOG_D(TAG, "furi_message_queue: Event timeout");
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
|
||||
@@ -282,6 +282,8 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
|
||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,8 @@ bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState*
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState*
|
||||
scene_state->code_length--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +303,8 @@ bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginStat
|
||||
break;
|
||||
case InputKeyBack:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,8 @@ bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* p
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1064,6 +1064,8 @@ int32_t unirfremix_app(void* p) {
|
||||
unirfremix_tx_stop(app);
|
||||
exit_loop = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(app->processing == 0) {
|
||||
@@ -1135,6 +1137,8 @@ int32_t unirfremix_app(void* p) {
|
||||
case InputKeyBack:
|
||||
exit_loop = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(exit_loop == true) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define WS_VERSION_APP "0.3.1"
|
||||
#define WS_VERSION_APP "0.4"
|
||||
#define WS_DEVELOPED "SkorP"
|
||||
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/acurite.c
|
||||
*
|
||||
* Acurite 592TXR Temperature Humidity sensor decoder
|
||||
* Message Type 0x04, 7 bytes
|
||||
|
||||
278
applications/plugins/weather_station/protocols/ambient_weather.c
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "ambient_weather.h"
|
||||
#include <lib/toolbox/manchester_decoder.h>
|
||||
|
||||
#define TAG "WSProtocolAmbient_Weather"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/ambient_weather.c
|
||||
*
|
||||
* Decode Ambient Weather F007TH, F012TH, TF 30.3208.02, SwitchDoc F016TH.
|
||||
* Devices supported:
|
||||
* - Ambient Weather F007TH Thermo-Hygrometer.
|
||||
* - Ambient Weather F012TH Indoor/Display Thermo-Hygrometer.
|
||||
* - TFA senders 30.3208.02 from the TFA "Klima-Monitor" 30.3054,
|
||||
* - SwitchDoc Labs F016TH.
|
||||
* This decoder handles the 433mhz/868mhz thermo-hygrometers.
|
||||
* The 915mhz (WH*) family of devices use different modulation/encoding.
|
||||
* Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5
|
||||
* xxxxMMMM IIIIIIII BCCCTTTT TTTTTTTT HHHHHHHH MMMMMMMM
|
||||
* - x: Unknown 0x04 on F007TH/F012TH
|
||||
* - M: Model Number?, 0x05 on F007TH/F012TH/SwitchDocLabs F016TH
|
||||
* - I: ID byte (8 bits), volatie, changes at power up,
|
||||
* - B: Battery Low
|
||||
* - C: Channel (3 bits 1-8) - F007TH set by Dip switch, F012TH soft setting
|
||||
* - T: Temperature 12 bits - Fahrenheit * 10 + 400
|
||||
* - H: Humidity (8 bits)
|
||||
* - M: Message integrity check LFSR Digest-8, gen 0x98, key 0x3e, init 0x64
|
||||
*
|
||||
* three repeats without gap
|
||||
* full preamble is 0x00145 (the last bits might not be fixed, e.g. 0x00146)
|
||||
* and on decoding also 0xffd45
|
||||
*/
|
||||
|
||||
#define AMBIENT_WEATHER_PACKET_HEADER_1 0xFFD440000000000 //0xffd45 .. 0xffd46
|
||||
#define AMBIENT_WEATHER_PACKET_HEADER_2 0x001440000000000 //0x00145 .. 0x00146
|
||||
#define AMBIENT_WEATHER_PACKET_HEADER_MASK 0xFFFFC0000000000
|
||||
|
||||
static const SubGhzBlockConst ws_protocol_ambient_weather_const = {
|
||||
.te_short = 500,
|
||||
.te_long = 1000,
|
||||
.te_delta = 120,
|
||||
.min_count_bit_for_found = 48,
|
||||
};
|
||||
|
||||
struct WSProtocolDecoderAmbient_Weather {
|
||||
SubGhzProtocolDecoderBase base;
|
||||
|
||||
SubGhzBlockDecoder decoder;
|
||||
WSBlockGeneric generic;
|
||||
ManchesterState manchester_saved_state;
|
||||
uint16_t header_count;
|
||||
};
|
||||
|
||||
struct WSProtocolEncoderAmbient_Weather {
|
||||
SubGhzProtocolEncoderBase base;
|
||||
|
||||
SubGhzProtocolBlockEncoder encoder;
|
||||
WSBlockGeneric generic;
|
||||
};
|
||||
|
||||
const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder = {
|
||||
.alloc = ws_protocol_decoder_ambient_weather_alloc,
|
||||
.free = ws_protocol_decoder_ambient_weather_free,
|
||||
|
||||
.feed = ws_protocol_decoder_ambient_weather_feed,
|
||||
.reset = ws_protocol_decoder_ambient_weather_reset,
|
||||
|
||||
.get_hash_data = ws_protocol_decoder_ambient_weather_get_hash_data,
|
||||
.serialize = ws_protocol_decoder_ambient_weather_serialize,
|
||||
.deserialize = ws_protocol_decoder_ambient_weather_deserialize,
|
||||
.get_string = ws_protocol_decoder_ambient_weather_get_string,
|
||||
};
|
||||
|
||||
const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder = {
|
||||
.alloc = NULL,
|
||||
.free = NULL,
|
||||
|
||||
.deserialize = NULL,
|
||||
.stop = NULL,
|
||||
.yield = NULL,
|
||||
};
|
||||
|
||||
const SubGhzProtocol ws_protocol_ambient_weather = {
|
||||
.name = WS_PROTOCOL_AMBIENT_WEATHER_NAME,
|
||||
.type = SubGhzProtocolWeatherStation,
|
||||
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
|
||||
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
|
||||
|
||||
.decoder = &ws_protocol_ambient_weather_decoder,
|
||||
.encoder = &ws_protocol_ambient_weather_encoder,
|
||||
};
|
||||
|
||||
void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
WSProtocolDecoderAmbient_Weather* instance = malloc(sizeof(WSProtocolDecoderAmbient_Weather));
|
||||
instance->base.protocol = &ws_protocol_ambient_weather;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_ambient_weather_free(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_ambient_weather_reset(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
manchester_advance(
|
||||
instance->manchester_saved_state,
|
||||
ManchesterEventReset,
|
||||
&instance->manchester_saved_state,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static bool ws_protocol_ambient_weather_check_crc(WSProtocolDecoderAmbient_Weather* instance) {
|
||||
uint8_t msg[] = {
|
||||
instance->decoder.decode_data >> 40,
|
||||
instance->decoder.decode_data >> 32,
|
||||
instance->decoder.decode_data >> 24,
|
||||
instance->decoder.decode_data >> 16,
|
||||
instance->decoder.decode_data >> 8};
|
||||
|
||||
uint8_t crc = subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64;
|
||||
return (crc == (uint8_t)(instance->decoder.decode_data & 0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysis of received data
|
||||
* @param instance Pointer to a WSBlockGeneric* instance
|
||||
*/
|
||||
static void ws_protocol_ambient_weather_remote_controller(WSBlockGeneric* instance) {
|
||||
instance->id = (instance->data >> 32) & 0xFF;
|
||||
instance->battery_low = (instance->data >> 31) & 1;
|
||||
instance->channel = ((instance->data >> 28) & 0x07) + 1;
|
||||
instance->temp = ws_block_generic_fahrenheit_to_celsius(
|
||||
((float)((instance->data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
instance->humidity = (instance->data >> 8) & 0xFF;
|
||||
instance->btn = WS_NO_BTN;
|
||||
|
||||
// ToDo maybe it won't be needed
|
||||
/*
|
||||
Sanity checks to reduce false positives and other bad data
|
||||
Packets with Bad data often pass the MIC check.
|
||||
- humidity > 100 (such as 255) and
|
||||
- temperatures > 140 F (such as 369.5 F and 348.8 F
|
||||
Specs in the F007TH and F012TH manuals state the range is:
|
||||
- Temperature: -40 to 140 F
|
||||
- Humidity: 10 to 99%
|
||||
@todo - sanity check b[0] "model number"
|
||||
- 0x45 - F007TH and F012TH
|
||||
- 0x?5 - SwitchDocLabs F016TH temperature sensor (based on comment b[0] & 0x0f == 5)
|
||||
- ? - TFA 30.3208.02
|
||||
if (instance->humidity < 0 || instance->humidity > 100) {
|
||||
ERROR;
|
||||
}
|
||||
|
||||
if (instance->temp < -40.0 || instance->temp > 140.0) {
|
||||
ERROR;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
if(!level) {
|
||||
if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) <
|
||||
ws_protocol_ambient_weather_const.te_delta) {
|
||||
event = ManchesterEventShortLow;
|
||||
} else if(
|
||||
DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) <
|
||||
ws_protocol_ambient_weather_const.te_delta * 2) {
|
||||
event = ManchesterEventLongLow;
|
||||
}
|
||||
} else {
|
||||
if(DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_short) <
|
||||
ws_protocol_ambient_weather_const.te_delta) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else if(
|
||||
DURATION_DIFF(duration, ws_protocol_ambient_weather_const.te_long) <
|
||||
ws_protocol_ambient_weather_const.te_delta * 2) {
|
||||
event = ManchesterEventLongHigh;
|
||||
}
|
||||
}
|
||||
if(event != ManchesterEventReset) {
|
||||
bool data;
|
||||
bool data_ok = manchester_advance(
|
||||
instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
|
||||
|
||||
if(data_ok) {
|
||||
instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
|
||||
}
|
||||
|
||||
if(((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) ==
|
||||
AMBIENT_WEATHER_PACKET_HEADER_1) ||
|
||||
((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) ==
|
||||
AMBIENT_WEATHER_PACKET_HEADER_2)) {
|
||||
if(ws_protocol_ambient_weather_check_crc(instance)) {
|
||||
instance->decoder.decode_data = instance->decoder.decode_data;
|
||||
instance->generic.data = instance->decoder.decode_data;
|
||||
instance->generic.data_count_bit =
|
||||
ws_protocol_ambient_weather_const.min_count_bit_for_found;
|
||||
ws_protocol_ambient_weather_remote_controller(&instance->generic);
|
||||
if(instance->base.callback)
|
||||
instance->base.callback(&instance->base, instance->base.context);
|
||||
instance->decoder.decode_data = 0;
|
||||
instance->decoder.decode_count_bit = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instance->decoder.decode_data = 0;
|
||||
instance->decoder.decode_count_bit = 0;
|
||||
manchester_advance(
|
||||
instance->manchester_saved_state,
|
||||
ManchesterEventReset,
|
||||
&instance->manchester_saved_state,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
return subghz_protocol_blocks_get_hash_data(
|
||||
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||
}
|
||||
|
||||
bool ws_protocol_decoder_ambient_weather_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||
}
|
||||
|
||||
bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
bool ret = false;
|
||||
do {
|
||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||
break;
|
||||
}
|
||||
if(instance->generic.data_count_bit !=
|
||||
ws_protocol_ambient_weather_const.min_count_bit_for_found) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
ret = true;
|
||||
} while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) {
|
||||
furi_assert(context);
|
||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||
furi_string_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Sn:0x%lX Ch:%d Bat:%d\r\n"
|
||||
"Temp:%d.%d C Hum:%d%%",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
(uint32_t)(instance->generic.data >> 32),
|
||||
(uint32_t)(instance->generic.data),
|
||||
instance->generic.id,
|
||||
instance->generic.channel,
|
||||
instance->generic.battery_low,
|
||||
(int16_t)instance->generic.temp,
|
||||
abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))),
|
||||
instance->generic.humidity);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
|
||||
#include <lib/subghz/blocks/const.h>
|
||||
#include <lib/subghz/blocks/decoder.h>
|
||||
#include <lib/subghz/blocks/encoder.h>
|
||||
#include "ws_generic.h"
|
||||
#include <lib/subghz/blocks/math.h>
|
||||
|
||||
#define WS_PROTOCOL_AMBIENT_WEATHER_NAME "Ambient_Weather"
|
||||
|
||||
typedef struct WSProtocolDecoderAmbient_Weather WSProtocolDecoderAmbient_Weather;
|
||||
typedef struct WSProtocolEncoderAmbient_Weather WSProtocolEncoderAmbient_Weather;
|
||||
|
||||
extern const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder;
|
||||
extern const SubGhzProtocolEncoder ws_protocol_ambient_weather_encoder;
|
||||
extern const SubGhzProtocol ws_protocol_ambient_weather;
|
||||
|
||||
/**
|
||||
* Allocate WSProtocolDecoderAmbient_Weather.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return WSProtocolDecoderAmbient_Weather* pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
*/
|
||||
void* ws_protocol_decoder_ambient_weather_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free WSProtocolDecoderAmbient_Weather.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
*/
|
||||
void ws_protocol_decoder_ambient_weather_free(void* context);
|
||||
|
||||
/**
|
||||
* Reset decoder WSProtocolDecoderAmbient_Weather.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
*/
|
||||
void ws_protocol_decoder_ambient_weather_reset(void* context);
|
||||
|
||||
/**
|
||||
* Parse a raw sequence of levels and durations received from the air.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
* @param level Signal level true-high false-low
|
||||
* @param duration Duration of this level in, us
|
||||
*/
|
||||
void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_t duration);
|
||||
|
||||
/**
|
||||
* Getting the hash sum of the last randomly received parcel.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
* @return hash Hash sum
|
||||
*/
|
||||
uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context);
|
||||
|
||||
/**
|
||||
* Serialize data WSProtocolDecoderAmbient_Weather.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||
* @return true On success
|
||||
*/
|
||||
bool ws_protocol_decoder_ambient_weather_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset);
|
||||
|
||||
/**
|
||||
* Deserialize data WSProtocolDecoderAmbient_Weather.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return true On success
|
||||
*/
|
||||
bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Getting a textual representation of the received data.
|
||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||
* @param output Resulting text
|
||||
*/
|
||||
void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output);
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://github.com/merbanan/rtl_433/blob/5f0ff6db624270a4598958ab9dd79bb385ced3ef/src/devices/gt_wt_03.c
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/gt_wt_03.c
|
||||
*
|
||||
*
|
||||
* Globaltronics GT-WT-03 sensor on 433.92MHz.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://github.com/merbanan/rtl_433/blob/7e83cfd27d14247b6c3c81732bfe4a4f9a974d30/src/devices/lacrosse_tx141x.c
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse_tx141x.c
|
||||
*
|
||||
* iiii iiii | bkcc tttt | tttt tttt | hhhh hhhh | cccc cccc | u
|
||||
* - i: identification; changes on battery switch
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://github.com/merbanan/rtl_433/blob/ef2d37cf51e3264d11cde9149ef87de2f0a4d37a/src/devices/nexus.c
|
||||
* https://github.com/merbanan/rtl_433/blob/master/src/devices/nexus.c
|
||||
*
|
||||
* Nexus sensor protocol with ID, temperature and optional humidity
|
||||
* also FreeTec (Pearl) NC-7345 sensors for FreeTec Weatherstation NC-7344,
|
||||
|
||||
@@ -9,6 +9,7 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = {
|
||||
&ws_protocol_lacrosse_tx141thbv2,
|
||||
&ws_protocol_oregon2,
|
||||
&ws_protocol_acurite_592txr,
|
||||
&ws_protocol_ambient_weather,
|
||||
};
|
||||
|
||||
const SubGhzProtocolRegistry weather_station_protocol_registry = {
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
#include "lacrosse_tx141thbv2.h"
|
||||
#include "oregon2.h"
|
||||
#include "acurite_592txr.h"
|
||||
#include "ambient_weather.h"
|
||||
|
||||
extern const SubGhzProtocolRegistry weather_station_protocol_registry;
|
||||
|
||||
@@ -12,6 +12,7 @@ App(
|
||||
order=70,
|
||||
sdk_headers=[
|
||||
"gui.h",
|
||||
"icon_i.h",
|
||||
"elements.h",
|
||||
"canvas_i.h",
|
||||
"view_dispatcher.h",
|
||||
|
||||
@@ -7,61 +7,51 @@
|
||||
|
||||
// TODO add mutex to view_port ops
|
||||
|
||||
static void view_port_remap_buttons_vertical(InputEvent* event) {
|
||||
switch(event->key) {
|
||||
case InputKeyUp:
|
||||
event->key = InputKeyRight;
|
||||
break;
|
||||
case InputKeyDown:
|
||||
event->key = InputKeyLeft;
|
||||
break;
|
||||
case InputKeyRight:
|
||||
event->key = InputKeyDown;
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
event->key = InputKeyUp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
_Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count");
|
||||
_Static_assert(
|
||||
(ViewPortOrientationHorizontal == 0 && ViewPortOrientationHorizontalFlip == 1 &&
|
||||
ViewPortOrientationVertical == 2 && ViewPortOrientationVerticalFlip == 3),
|
||||
"Incorrect ViewPortOrientation order");
|
||||
_Static_assert(InputKeyMAX == 6, "Incorrect InputKey count");
|
||||
_Static_assert(
|
||||
(InputKeyUp == 0 && InputKeyDown == 1 && InputKeyRight == 2 && InputKeyLeft == 3 &&
|
||||
InputKeyOk == 4 && InputKeyBack == 5),
|
||||
"Incorrect InputKey order");
|
||||
|
||||
static void view_port_remap_buttons_vertical_flip(InputEvent* event) {
|
||||
switch(event->key) {
|
||||
case InputKeyUp:
|
||||
event->key = InputKeyLeft;
|
||||
break;
|
||||
case InputKeyDown:
|
||||
event->key = InputKeyRight;
|
||||
break;
|
||||
case InputKeyRight:
|
||||
event->key = InputKeyUp;
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
event->key = InputKeyDown;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/** InputKey directional keys mappings for different screen orientations
|
||||
*
|
||||
*/
|
||||
static const InputKey view_port_input_mapping[ViewPortOrientationMAX][InputKeyMAX] = {
|
||||
{InputKeyUp,
|
||||
InputKeyDown,
|
||||
InputKeyRight,
|
||||
InputKeyLeft,
|
||||
InputKeyOk,
|
||||
InputKeyBack}, //ViewPortOrientationHorizontal
|
||||
{InputKeyDown,
|
||||
InputKeyUp,
|
||||
InputKeyLeft,
|
||||
InputKeyRight,
|
||||
InputKeyOk,
|
||||
InputKeyBack}, //ViewPortOrientationHorizontalFlip
|
||||
{InputKeyRight,
|
||||
InputKeyLeft,
|
||||
InputKeyDown,
|
||||
InputKeyUp,
|
||||
InputKeyOk,
|
||||
InputKeyBack}, //ViewPortOrientationVertical
|
||||
{InputKeyLeft,
|
||||
InputKeyRight,
|
||||
InputKeyUp,
|
||||
InputKeyDown,
|
||||
InputKeyOk,
|
||||
InputKeyBack}, //ViewPortOrientationVerticalFlip
|
||||
};
|
||||
|
||||
static void view_port_remap_buttons_horizontal_flip(InputEvent* event) {
|
||||
switch(event->key) {
|
||||
case InputKeyUp:
|
||||
event->key = InputKeyDown;
|
||||
break;
|
||||
case InputKeyDown:
|
||||
event->key = InputKeyUp;
|
||||
break;
|
||||
case InputKeyRight:
|
||||
event->key = InputKeyLeft;
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
event->key = InputKeyRight;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Remaps directional pad buttons on Flipper based on ViewPort orientation
|
||||
static void view_port_map_input(InputEvent* event, ViewPortOrientation orientation) {
|
||||
furi_assert(orientation < ViewPortOrientationMAX && event->key < InputKeyMAX);
|
||||
event->key = view_port_input_mapping[orientation][event->key];
|
||||
}
|
||||
|
||||
static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) {
|
||||
@@ -170,19 +160,7 @@ void view_port_input(ViewPort* view_port, InputEvent* event) {
|
||||
|
||||
if(view_port->input_callback) {
|
||||
ViewPortOrientation orientation = view_port_get_orientation(view_port);
|
||||
switch(orientation) {
|
||||
case ViewPortOrientationHorizontalFlip:
|
||||
view_port_remap_buttons_horizontal_flip(event);
|
||||
break;
|
||||
case ViewPortOrientationVertical:
|
||||
view_port_remap_buttons_vertical(event);
|
||||
break;
|
||||
case ViewPortOrientationVerticalFlip:
|
||||
view_port_remap_buttons_vertical_flip(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
view_port_map_input(event, orientation);
|
||||
view_port->input_callback(event, view_port->input_callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef enum {
|
||||
ViewPortOrientationHorizontalFlip,
|
||||
ViewPortOrientationVertical,
|
||||
ViewPortOrientationVerticalFlip,
|
||||
ViewPortOrientationMAX, /**< Special value, don't use it */
|
||||
} ViewPortOrientation;
|
||||
|
||||
/** ViewPort Draw callback
|
||||
|
||||
@@ -60,8 +60,9 @@ const char* input_get_type_name(InputType type) {
|
||||
return "Long";
|
||||
case InputTypeRepeat:
|
||||
return "Repeat";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
int32_t input_srv(void* p) {
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef enum {
|
||||
InputTypeShort, /**< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */
|
||||
InputTypeLong, /**< Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease */
|
||||
InputTypeRepeat, /**< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */
|
||||
InputTypeMAX, /**< Special value for exceptional */
|
||||
} InputType;
|
||||
|
||||
/** Input Event, dispatches with FuriPubSub */
|
||||
|
||||
@@ -405,6 +405,10 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
||||
if(!fs_operation_success) {
|
||||
send_response = true;
|
||||
command_status = rpc_system_storage_get_file_error(file);
|
||||
if(command_status == PB_CommandStatus_OK) {
|
||||
// Report errors not handled by underlying APIs
|
||||
command_status = PB_CommandStatus_ERROR_STORAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
if(send_response) {
|
||||
|
||||
2
assets/dolphin/external/manifest.txt
vendored
@@ -55,7 +55,7 @@ Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 30
|
||||
Weight: 14
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Painting_128x64
|
||||
Min butthurt: 0
|
||||
|
||||
|
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 410 B |
@@ -1,6 +1,7 @@
|
||||
Import("ENV", "fw_build_meta")
|
||||
|
||||
from SCons.Errors import UserError
|
||||
from SCons.Node import FS
|
||||
import itertools
|
||||
|
||||
from fbt_extra.util import (
|
||||
@@ -14,7 +15,6 @@ env = ENV.Clone(
|
||||
("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}),
|
||||
"fwbin",
|
||||
"fbt_apps",
|
||||
"fbt_sdk",
|
||||
],
|
||||
COMPILATIONDB_USE_ABSPATH=False,
|
||||
BUILD_DIR=fw_build_meta["build_dir"],
|
||||
@@ -112,7 +112,9 @@ lib_targets = env.BuildModules(
|
||||
|
||||
|
||||
# Now, env is fully set up with everything to build apps
|
||||
fwenv = env.Clone()
|
||||
fwenv = env.Clone(FW_ARTIFACTS=[])
|
||||
|
||||
fw_artifacts = fwenv["FW_ARTIFACTS"]
|
||||
|
||||
# Set up additional app-specific build flags
|
||||
SConscript("site_scons/firmwareopts.scons", exports={"ENV": fwenv})
|
||||
@@ -130,7 +132,14 @@ if extra_int_apps := GetOption("extra_int_apps"):
|
||||
if fwenv["FAP_EXAMPLES"]:
|
||||
fwenv.Append(APPDIRS=[("applications/examples", False)])
|
||||
|
||||
fwenv.LoadApplicationManifests()
|
||||
for app_dir, _ in env["APPDIRS"]:
|
||||
app_dir_node = env.Dir("#").Dir(app_dir)
|
||||
|
||||
for entry in app_dir_node.glob("*"):
|
||||
if isinstance(entry, FS.Dir) and not str(entry).startswith("."):
|
||||
fwenv.LoadAppManifest(entry)
|
||||
|
||||
|
||||
fwenv.PrepareApplicationsBuild()
|
||||
|
||||
# Build external apps
|
||||
@@ -138,6 +147,7 @@ if env["IS_BASE_FIRMWARE"]:
|
||||
extapps = fwenv["FW_EXTAPPS"] = SConscript(
|
||||
"site_scons/extapps.scons", exports={"ENV": fwenv}
|
||||
)
|
||||
fw_artifacts.append(extapps["sdk_tree"])
|
||||
|
||||
|
||||
# Add preprocessor definitions for current set of apps
|
||||
@@ -220,7 +230,10 @@ Depends(fwelf, lib_targets)
|
||||
AddPostAction(fwelf, fwenv["APPBUILD_DUMP"])
|
||||
AddPostAction(
|
||||
fwelf,
|
||||
Action('${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" elf ${TARGET}', "Firmware size"),
|
||||
Action(
|
||||
'${PYTHON3} "${BIN_SIZE_SCRIPT}" elf ${TARGET}',
|
||||
"Firmware size",
|
||||
),
|
||||
)
|
||||
|
||||
# Produce extra firmware files
|
||||
@@ -228,7 +241,7 @@ fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}")
|
||||
fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}")
|
||||
AddPostAction(
|
||||
fwbin,
|
||||
Action('@${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" bin ${TARGET}'),
|
||||
Action('@${PYTHON3} "${BIN_SIZE_SCRIPT}" bin ${TARGET}'),
|
||||
)
|
||||
|
||||
fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}")
|
||||
@@ -238,12 +251,14 @@ fwdump = fwenv.ObjDump("${FIRMWARE_BUILD_CFG}")
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_list", fwdump)
|
||||
|
||||
|
||||
fw_artifacts = fwenv["FW_ARTIFACTS"] = [
|
||||
fwhex,
|
||||
fwbin,
|
||||
fwdfu,
|
||||
fwenv["FW_VERSION_JSON"],
|
||||
]
|
||||
fw_artifacts.extend(
|
||||
[
|
||||
fwhex,
|
||||
fwbin,
|
||||
fwdfu,
|
||||
fwenv["FW_VERSION_JSON"],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
fwcdb = fwenv.CompilationDatabase()
|
||||
@@ -272,34 +287,5 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS):
|
||||
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts)
|
||||
|
||||
if fwenv["IS_BASE_FIRMWARE"]:
|
||||
sdk_source = fwenv.SDKPrebuilder(
|
||||
"sdk_origin",
|
||||
# Deps on root SDK headers and generated files
|
||||
(fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"]),
|
||||
)
|
||||
# Extra deps on headers included in deeper levels
|
||||
Depends(sdk_source, fwenv.ProcessSdkDepends("sdk_origin.d"))
|
||||
|
||||
fwenv["SDK_DIR"] = fwenv.Dir("sdk")
|
||||
sdk_tree = fwenv.SDKTree(fwenv["SDK_DIR"], "sdk_origin")
|
||||
fw_artifacts.append(sdk_tree)
|
||||
# AlwaysBuild(sdk_tree)
|
||||
Alias("sdk_tree", sdk_tree)
|
||||
|
||||
sdk_apicheck = fwenv.SDKSymUpdater(fwenv["SDK_DEFINITION"], "sdk_origin")
|
||||
Precious(sdk_apicheck)
|
||||
NoClean(sdk_apicheck)
|
||||
AlwaysBuild(sdk_apicheck)
|
||||
Alias("sdk_check", sdk_apicheck)
|
||||
|
||||
sdk_apisyms = fwenv.SDKSymGenerator(
|
||||
"assets/compiled/symbols.h", fwenv["SDK_DEFINITION"]
|
||||
)
|
||||
Alias("api_syms", sdk_apisyms)
|
||||
|
||||
if fwenv["FORCE"]:
|
||||
fwenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms)
|
||||
|
||||
|
||||
Return("fwenv")
|
||||
|
||||
@@ -2,11 +2,10 @@ Import("env")
|
||||
|
||||
env.Append(
|
||||
LINT_SOURCES=["firmware"],
|
||||
# SDK_HEADERS=[env.File("#/firmware/targets/furi_hal_include/furi_hal.h")],
|
||||
SDK_HEADERS=[
|
||||
*env.GlobRecursive("*.h", "#/firmware/targets/furi_hal_include", "*_i.h"),
|
||||
*env.GlobRecursive("*.h", "#/firmware/targets/f${TARGET_HW}/furi_hal", "*_i.h"),
|
||||
File("#/firmware/targets/f7/platform_specific/intrinsic_export.h"),
|
||||
*env.GlobRecursive("*.h", "targets/furi_hal_include", "*_i.h"),
|
||||
*env.GlobRecursive("*.h", "targets/f${TARGET_HW}/furi_hal", "*_i.h"),
|
||||
File("targets/f7/platform_specific/intrinsic_export.h"),
|
||||
File("#/firmware/targets/furi_hal_include/furi_hal_subghz.h"),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,8.2,,
|
||||
Version,+,8.4,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@@ -8,6 +8,7 @@ Header,+,applications/services/dolphin/dolphin.h,,
|
||||
Header,+,applications/services/gui/canvas_i.h,,
|
||||
Header,+,applications/services/gui/elements.h,,
|
||||
Header,+,applications/services/gui/gui.h,,
|
||||
Header,+,applications/services/gui/icon_i.h,,
|
||||
Header,+,applications/services/gui/modules/button_menu.h,,
|
||||
Header,+,applications/services/gui/modules/button_panel.h,,
|
||||
Header,+,applications/services/gui/modules/byte_input.h,,
|
||||
@@ -123,6 +124,33 @@ Header,+,lib/lfrfid/lfrfid_raw_worker.h,,
|
||||
Header,+,lib/lfrfid/lfrfid_worker.h,,
|
||||
Header,+,lib/lfrfid/protocols/lfrfid_protocols.h,,
|
||||
Header,+,lib/lfrfid/tools/bit_lib.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_button.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_consumer.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_desktop.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_device.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_game.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_keyboard.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_led.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_ordinal.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_power.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_simulation.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_sport.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_telephony.h,,
|
||||
Header,+,lib/libusb_stm32/inc/hid_usage_vr.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdc.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdca.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdce.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdci.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdcp.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_cdcw.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_dfu.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_hid.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_std.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usb_tmc.h,,
|
||||
Header,+,lib/libusb_stm32/inc/usbd_core.h,,
|
||||
Header,+,lib/mbedtls/include/mbedtls/des.h,,
|
||||
Header,+,lib/mbedtls/include/mbedtls/sha1.h,,
|
||||
Header,+,lib/micro-ecc/uECC.h,,
|
||||
Header,+,lib/one_wire/ibutton/ibutton_worker.h,,
|
||||
Header,+,lib/one_wire/maxim_crc.h,,
|
||||
@@ -417,6 +445,7 @@ Function,-,_system_r,int,"_reent*, const char*"
|
||||
Function,-,_tempnam_r,char*,"_reent*, const char*, const char*"
|
||||
Function,-,_tmpfile_r,FILE*,_reent*
|
||||
Function,-,_tmpnam_r,char*,"_reent*, char*"
|
||||
Function,-,_tzset_r,void,_reent*
|
||||
Function,-,_ungetc_r,int,"_reent*, int, FILE*"
|
||||
Function,-,_unsetenv_r,int,"_reent*, const char*"
|
||||
Function,-,_vasiprintf_r,int,"_reent*, char**, const char*, __gnuc_va_list"
|
||||
@@ -464,6 +493,8 @@ Function,+,args_read_hex_bytes,_Bool,"FuriString*, uint8_t*, size_t"
|
||||
Function,+,args_read_int_and_trim,_Bool,"FuriString*, int*"
|
||||
Function,+,args_read_probably_quoted_string_and_trim,_Bool,"FuriString*, FuriString*"
|
||||
Function,+,args_read_string_and_trim,_Bool,"FuriString*, FuriString*"
|
||||
Function,-,asctime,char*,const tm*
|
||||
Function,-,asctime_r,char*,"const tm*, char*"
|
||||
Function,-,asin,double,double
|
||||
Function,-,asinf,float,float
|
||||
Function,-,asinh,double,double
|
||||
@@ -645,6 +676,7 @@ Function,+,cli_read_timeout,size_t,"Cli*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,cli_session_close,void,Cli*
|
||||
Function,+,cli_session_open,void,"Cli*, void*"
|
||||
Function,+,cli_write,void,"Cli*, const uint8_t*, size_t"
|
||||
Function,-,clock,clock_t,
|
||||
Function,-,copysign,double,"double, double"
|
||||
Function,-,copysignf,float,"float, float"
|
||||
Function,-,copysignl,long double,"long double, long double"
|
||||
@@ -657,6 +689,8 @@ Function,-,cosl,long double,long double
|
||||
Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t"
|
||||
Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*"
|
||||
Function,-,ctermid,char*,char*
|
||||
Function,-,ctime,char*,const time_t*
|
||||
Function,-,ctime_r,char*,"const time_t*, char*"
|
||||
Function,-,cuserid,char*,char*
|
||||
Function,+,delete_mutex,_Bool,ValueMutex*
|
||||
Function,+,dialog_ex_alloc,DialogEx*,
|
||||
@@ -683,6 +717,7 @@ Function,+,dialog_message_set_icon,void,"DialogMessage*, const Icon*, uint8_t, u
|
||||
Function,+,dialog_message_set_text,void,"DialogMessage*, const char*, uint8_t, uint8_t, Align, Align"
|
||||
Function,+,dialog_message_show,DialogMessageButton,"DialogsApp*, const DialogMessage*"
|
||||
Function,+,dialog_message_show_storage_error,void,"DialogsApp*, const char*"
|
||||
Function,-,difftime,double,"time_t, time_t"
|
||||
Function,-,digital_signal_alloc,DigitalSignal*,uint32_t
|
||||
Function,-,digital_signal_append,_Bool,"DigitalSignal*, DigitalSignal*"
|
||||
Function,-,digital_signal_free,void,DigitalSignal*
|
||||
@@ -1502,6 +1537,8 @@ Function,-,getenv,char*,const char*
|
||||
Function,-,gets,char*,char*
|
||||
Function,-,getsubopt,int,"char**, char**, char**"
|
||||
Function,-,getw,int,FILE*
|
||||
Function,-,gmtime,tm*,const time_t*
|
||||
Function,-,gmtime_r,tm*,"const time_t*, tm*"
|
||||
Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*"
|
||||
Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer"
|
||||
Function,+,gui_get_framebuffer_size,size_t,Gui*
|
||||
@@ -1701,6 +1738,8 @@ Function,+,loader_update_menu,void,
|
||||
Function,+,loading_alloc,Loading*,
|
||||
Function,+,loading_free,void,Loading*
|
||||
Function,+,loading_get_view,View*,Loading*
|
||||
Function,-,localtime,tm*,const time_t*
|
||||
Function,-,localtime_r,tm*,"const time_t*, tm*"
|
||||
Function,-,log,double,double
|
||||
Function,-,log10,double,double
|
||||
Function,-,log10f,float,float
|
||||
@@ -1729,6 +1768,36 @@ Function,+,manchester_encoder_advance,_Bool,"ManchesterEncoderState*, const _Boo
|
||||
Function,+,manchester_encoder_finish,ManchesterEncoderResult,ManchesterEncoderState*
|
||||
Function,+,manchester_encoder_reset,void,ManchesterEncoderState*
|
||||
Function,+,maxim_crc8,uint8_t,"const uint8_t*, const uint8_t, const uint8_t"
|
||||
Function,-,mbedtls_des3_crypt_cbc,int,"mbedtls_des3_context*, int, size_t, unsigned char[8], const unsigned char*, unsigned char*"
|
||||
Function,-,mbedtls_des3_crypt_ecb,int,"mbedtls_des3_context*, const unsigned char[8], unsigned char[8]"
|
||||
Function,-,mbedtls_des3_free,void,mbedtls_des3_context*
|
||||
Function,-,mbedtls_des3_init,void,mbedtls_des3_context*
|
||||
Function,-,mbedtls_des3_set2key_dec,int,"mbedtls_des3_context*, const unsigned char[8 * 2]"
|
||||
Function,-,mbedtls_des3_set2key_enc,int,"mbedtls_des3_context*, const unsigned char[8 * 2]"
|
||||
Function,-,mbedtls_des3_set3key_dec,int,"mbedtls_des3_context*, const unsigned char[8 * 3]"
|
||||
Function,-,mbedtls_des3_set3key_enc,int,"mbedtls_des3_context*, const unsigned char[8 * 3]"
|
||||
Function,-,mbedtls_des_crypt_cbc,int,"mbedtls_des_context*, int, size_t, unsigned char[8], const unsigned char*, unsigned char*"
|
||||
Function,-,mbedtls_des_crypt_ecb,int,"mbedtls_des_context*, const unsigned char[8], unsigned char[8]"
|
||||
Function,-,mbedtls_des_free,void,mbedtls_des_context*
|
||||
Function,-,mbedtls_des_init,void,mbedtls_des_context*
|
||||
Function,-,mbedtls_des_key_check_key_parity,int,const unsigned char[8]
|
||||
Function,-,mbedtls_des_key_check_weak,int,const unsigned char[8]
|
||||
Function,-,mbedtls_des_key_set_parity,void,unsigned char[8]
|
||||
Function,-,mbedtls_des_self_test,int,int
|
||||
Function,-,mbedtls_des_setkey,void,"uint32_t[32], const unsigned char[8]"
|
||||
Function,-,mbedtls_des_setkey_dec,int,"mbedtls_des_context*, const unsigned char[8]"
|
||||
Function,-,mbedtls_des_setkey_enc,int,"mbedtls_des_context*, const unsigned char[8]"
|
||||
Function,-,mbedtls_internal_sha1_process,int,"mbedtls_sha1_context*, const unsigned char[64]"
|
||||
Function,-,mbedtls_platform_gmtime_r,tm*,"const mbedtls_time_t*, tm*"
|
||||
Function,-,mbedtls_platform_zeroize,void,"void*, size_t"
|
||||
Function,-,mbedtls_sha1,int,"const unsigned char*, size_t, unsigned char[20]"
|
||||
Function,-,mbedtls_sha1_clone,void,"mbedtls_sha1_context*, const mbedtls_sha1_context*"
|
||||
Function,-,mbedtls_sha1_finish,int,"mbedtls_sha1_context*, unsigned char[20]"
|
||||
Function,-,mbedtls_sha1_free,void,mbedtls_sha1_context*
|
||||
Function,-,mbedtls_sha1_init,void,mbedtls_sha1_context*
|
||||
Function,-,mbedtls_sha1_self_test,int,int
|
||||
Function,-,mbedtls_sha1_starts,int,mbedtls_sha1_context*
|
||||
Function,-,mbedtls_sha1_update,int,"mbedtls_sha1_context*, const unsigned char*, size_t"
|
||||
Function,-,mblen,int,"const char*, size_t"
|
||||
Function,-,mbstowcs,size_t,"wchar_t*, const char*, size_t"
|
||||
Function,-,mbtowc,int,"wchar_t*, const char*, size_t"
|
||||
@@ -1769,6 +1838,7 @@ Function,-,mkostemps,int,"char*, int, int"
|
||||
Function,-,mkstemp,int,char*
|
||||
Function,-,mkstemps,int,"char*, int"
|
||||
Function,-,mktemp,char*,char*
|
||||
Function,-,mktime,time_t,tm*
|
||||
Function,-,modf,double,"double, double*"
|
||||
Function,-,modff,float,"float, float*"
|
||||
Function,-,modfl,long double,"long double, long double*"
|
||||
@@ -1797,6 +1867,7 @@ Function,+,notification_message,void,"NotificationApp*, const NotificationSequen
|
||||
Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*"
|
||||
Function,-,nrand48,long,unsigned short[3]
|
||||
Function,-,nrf24_configure,void,"FuriHalSpiBusHandle*, uint8_t, uint8_t*, uint8_t*, uint8_t, uint8_t, _Bool, _Bool"
|
||||
Function,+,nrf24_deinit,void,
|
||||
Function,+,nrf24_find_channel,uint8_t,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, uint8_t, uint8_t, uint8_t, uint8_t, _Bool"
|
||||
Function,-,nrf24_flush_rx,uint8_t,FuriHalSpiBusHandle*
|
||||
Function,-,nrf24_flush_tx,uint8_t,FuriHalSpiBusHandle*
|
||||
@@ -2309,6 +2380,8 @@ Function,+,stream_write_vaformat,size_t,"Stream*, const char*, va_list"
|
||||
Function,-,strerror,char*,int
|
||||
Function,-,strerror_l,char*,"int, locale_t"
|
||||
Function,-,strerror_r,char*,"int, char*, size_t"
|
||||
Function,-,strftime,size_t,"char*, size_t, const char*, const tm*"
|
||||
Function,-,strftime_l,size_t,"char*, size_t, const char*, const tm*, locale_t"
|
||||
Function,+,string_stream_alloc,Stream*,
|
||||
Function,-,strlcat,size_t,"char*, const char*, size_t"
|
||||
Function,+,strlcpy,size_t,"char*, const char*, size_t"
|
||||
@@ -2323,6 +2396,8 @@ Function,-,strndup,char*,"const char*, size_t"
|
||||
Function,-,strnlen,size_t,"const char*, size_t"
|
||||
Function,-,strnstr,char*,"const char*, const char*, size_t"
|
||||
Function,-,strpbrk,char*,"const char*, const char*"
|
||||
Function,-,strptime,char*,"const char*, const char*, tm*"
|
||||
Function,-,strptime_l,char*,"const char*, const char*, tm*, locale_t"
|
||||
Function,+,strrchr,char*,"const char*, int"
|
||||
Function,-,strsep,char*,"char**, const char*"
|
||||
Function,-,strsignal,char*,int
|
||||
@@ -2933,6 +3008,7 @@ Function,-,tga_save,void,const char*
|
||||
Function,-,tgamma,double,double
|
||||
Function,-,tgammaf,float,float
|
||||
Function,-,tgammal,long double,long double
|
||||
Function,-,time,time_t,time_t*
|
||||
Function,+,timerCalculateTimer,uint32_t,uint16_t
|
||||
Function,-,timerDelay,void,uint16_t
|
||||
Function,+,timerIsExpired,_Bool,uint32_t
|
||||
@@ -4005,6 +4081,7 @@ Function,-,u8x8_upscale_byte,uint16_t,uint8_t
|
||||
Function,-,u8x8_utf8_init,void,u8x8_t*
|
||||
Function,-,u8x8_utf8_next,uint16_t,"u8x8_t*, uint8_t"
|
||||
Function,-,u8x8_utoa,const char*,uint16_t
|
||||
Function,-,tzset,void,
|
||||
Function,-,uECC_compress,void,"const uint8_t*, uint8_t*, uECC_Curve"
|
||||
Function,+,uECC_compute_public_key,int,"const uint8_t*, uint8_t*, uECC_Curve"
|
||||
Function,-,uECC_curve_private_key_size,int,uECC_Curve
|
||||
@@ -4263,10 +4340,13 @@ Variable,-,MSIRangeTable,const uint32_t[16],
|
||||
Variable,-,SmpsPrescalerTable,const uint32_t[4][6],
|
||||
Variable,+,SystemCoreClock,uint32_t,
|
||||
Variable,+,_ctype_,const char[],
|
||||
Variable,-,_daylight,int,
|
||||
Variable,+,_global_impure_ptr,_reent*,
|
||||
Variable,+,_impure_ptr,_reent*,
|
||||
Variable,-,_sys_errlist,const char*[],
|
||||
Variable,-,_sys_nerr,int,
|
||||
Variable,-,_timezone,long,
|
||||
Variable,-,_tzname,char*[2],
|
||||
Variable,+,cli_vcp,CliSession,
|
||||
Variable,+,furi_hal_i2c_bus_external,FuriHalI2cBus,
|
||||
Variable,+,furi_hal_i2c_bus_power,FuriHalI2cBus,
|
||||
|
||||
|
@@ -20,6 +20,7 @@ typedef enum {
|
||||
InputKeyLeft,
|
||||
InputKeyOk,
|
||||
InputKeyBack,
|
||||
InputKeyMAX, /**< Special value */
|
||||
} InputKey;
|
||||
|
||||
/* Light */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
@@ -24,30 +25,31 @@ PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[12] = {0};
|
||||
: \
|
||||
: "memory");
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
// Restore registers and halt MCU with bkpt mcu debug state
|
||||
#define RESTORE_REGISTERS_AND_HALT_MCU() \
|
||||
asm volatile("ldr r12, =__furi_check_registers \n" \
|
||||
"ldm r12, {r0-r11} \n" \
|
||||
"loop%=: \n" \
|
||||
"bkpt 0x00 \n" \
|
||||
"wfi \n" \
|
||||
"b loop%= \n" \
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
#else
|
||||
// Restore registers and halt MCU for release builds without bkpt instruction
|
||||
#define RESTORE_REGISTERS_AND_HALT_MCU() \
|
||||
asm volatile("ldr r12, =__furi_check_registers \n" \
|
||||
"ldm r12, {r0-r11} \n" \
|
||||
/** Restore registers and halt MCU
|
||||
*
|
||||
* - Always use it with GET_MESSAGE_AND_STORE_REGISTERS
|
||||
* - If debugger is(was) connected this routine will raise bkpt
|
||||
* - If debugger is not connected then endless loop
|
||||
*
|
||||
*/
|
||||
#define RESTORE_REGISTERS_AND_HALT_MCU(debug) \
|
||||
register const bool r0 asm("r0") = debug; \
|
||||
asm volatile("cbnz r0, with_debugger%= \n" \
|
||||
"ldr r12, =__furi_check_registers\n" \
|
||||
"ldm r12, {r0-r11} \n" \
|
||||
"loop%=: \n" \
|
||||
"wfi \n" \
|
||||
"b loop%= \n" \
|
||||
: \
|
||||
"b loop%= \n" \
|
||||
"with_debugger%=: \n" \
|
||||
"ldr r12, =__furi_check_registers\n" \
|
||||
"ldm r12, {r0-r11} \n" \
|
||||
"debug_loop%=: \n" \
|
||||
"bkpt 0x00 \n" \
|
||||
"wfi \n" \
|
||||
"b debug_loop%= \n" \
|
||||
: \
|
||||
: "r"(r0) \
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
extern size_t xPortGetTotalHeapSize(void);
|
||||
extern size_t xPortGetFreeHeapSize(void);
|
||||
@@ -109,16 +111,19 @@ FURI_NORETURN void __furi_crash() {
|
||||
}
|
||||
__furi_print_heap_info();
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
RESTORE_REGISTERS_AND_HALT_MCU();
|
||||
#else
|
||||
furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
|
||||
furi_hal_console_puts("\r\nRebooting system.\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
furi_hal_power_reset();
|
||||
#endif
|
||||
// Check if debug enabled by DAP
|
||||
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
|
||||
bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
|
||||
if(debug) {
|
||||
furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
RESTORE_REGISTERS_AND_HALT_MCU(debug);
|
||||
} else {
|
||||
furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
|
||||
furi_hal_console_puts("\r\nRebooting system.\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
furi_hal_power_reset();
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -137,6 +142,11 @@ FURI_NORETURN void __furi_halt() {
|
||||
furi_hal_console_puts(__furi_check_message);
|
||||
furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
RESTORE_REGISTERS_AND_HALT_MCU();
|
||||
|
||||
// Check if debug enabled by DAP
|
||||
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
|
||||
bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
|
||||
RESTORE_REGISTERS_AND_HALT_MCU(debug);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ env.Append(
|
||||
"lib/print",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/one_wire/one_wire_host_timing.h"),
|
||||
File("#/lib/one_wire/one_wire_host.h"),
|
||||
File("#/lib/one_wire/one_wire_slave.h"),
|
||||
File("#/lib/one_wire/one_wire_device.h"),
|
||||
File("#/lib/one_wire/ibutton/ibutton_worker.h"),
|
||||
File("#/lib/one_wire/maxim_crc.h"),
|
||||
File("#/lib/u8g2/u8g2.h"),
|
||||
File("one_wire/one_wire_host_timing.h"),
|
||||
File("one_wire/one_wire_host.h"),
|
||||
File("one_wire/one_wire_slave.h"),
|
||||
File("one_wire/one_wire_device.h"),
|
||||
File("one_wire/ibutton/ibutton_worker.h"),
|
||||
File("one_wire/maxim_crc.h"),
|
||||
File("u8g2/u8g2.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ env.Append(
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
*env.GlobRecursive("*_ll_*.h", "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/", exclude="*usb.h"),
|
||||
File("#/lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h"),
|
||||
File("#/lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h"),
|
||||
File("STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h"),
|
||||
File("STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ env.Append(
|
||||
"#/lib/drivers",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/drivers/nrf24.h"),
|
||||
File("nrf24.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ void nrf24_init() {
|
||||
furi_hal_gpio_write(nrf24_CE_PIN, false);
|
||||
}
|
||||
|
||||
void nrf24_deinit() {
|
||||
furi_hal_spi_release(nrf24_HANDLE);
|
||||
furi_hal_spi_bus_handle_deinit(nrf24_HANDLE);
|
||||
furi_hal_gpio_write(nrf24_CE_PIN, false);
|
||||
furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void nrf24_spi_trx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx,
|
||||
|
||||
@@ -116,6 +116,11 @@ uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle);
|
||||
*/
|
||||
void nrf24_init();
|
||||
|
||||
/** Must call this when we end using nrf24 device
|
||||
*
|
||||
*/
|
||||
void nrf24_deinit();
|
||||
|
||||
/** Send flush rx command
|
||||
*
|
||||
* @param handle - pointer to FuriHalSpiHandle
|
||||
|
||||
@@ -5,7 +5,7 @@ env.Append(
|
||||
"#/lib/flipper_application",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/flipper_application/flipper_application.h"),
|
||||
File("flipper_application.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ env.Append(
|
||||
"#/lib/flipper_format",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/flipper_format/flipper_format.h"),
|
||||
File("#/lib/flipper_format/flipper_format_i.h"),
|
||||
File("flipper_format.h"),
|
||||
File("flipper_format_i.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ env.Append(
|
||||
"#/lib/infrared/worker",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/infrared/worker/infrared_transmit.h"),
|
||||
File("#/lib/infrared/worker/infrared_worker.h"),
|
||||
File("#/lib/infrared/encoder_decoder/infrared.h"),
|
||||
File("encoder_decoder/infrared.h"),
|
||||
File("worker/infrared_worker.h"),
|
||||
File("worker/infrared_transmit.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ env.Append(
|
||||
"#/lib/lfrfid",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/lfrfid/lfrfid_worker.h"),
|
||||
File("#/lib/lfrfid/lfrfid_raw_worker.h"),
|
||||
File("#/lib/lfrfid/lfrfid_raw_file.h"),
|
||||
File("#/lib/lfrfid/lfrfid_dict_file.h"),
|
||||
File("#/lib/lfrfid/tools/bit_lib.h"),
|
||||
File("#/lib/lfrfid/protocols/lfrfid_protocols.h"),
|
||||
File("lfrfid_worker.h"),
|
||||
File("lfrfid_raw_worker.h"),
|
||||
File("lfrfid_raw_file.h"),
|
||||
File("lfrfid_dict_file.h"),
|
||||
File("tools/bit_lib.h"),
|
||||
File("protocols/lfrfid_protocols.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ env.Append(
|
||||
CPPDEFINES=[
|
||||
("USB_PMASIZE", "0x400"),
|
||||
],
|
||||
SDK_HEADERS=env.GlobRecursive(
|
||||
"*.h",
|
||||
Dir("libusb_stm32/inc"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ env.Append(
|
||||
"#/lib/mbedtls",
|
||||
"#/lib/mbedtls/include",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("mbedtls/include/mbedtls/des.h"),
|
||||
File("mbedtls/include/mbedtls/sha1.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ env.Append(
|
||||
"PB_ENABLE_MALLOC",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/micro-ecc/uECC.h"),
|
||||
File("micro-ecc/uECC.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ for wrapped_fn in wrapped_fn_list:
|
||||
|
||||
env.Append(
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/print/wrappers.h"),
|
||||
File("wrappers.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,20 +5,20 @@ env.Append(
|
||||
"#/lib/subghz",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/subghz/environment.h"),
|
||||
File("#/lib/subghz/receiver.h"),
|
||||
File("#/lib/subghz/subghz_worker.h"),
|
||||
File("#/lib/subghz/subghz_tx_rx_worker.h"),
|
||||
File("#/lib/subghz/transmitter.h"),
|
||||
File("#/lib/subghz/registry.h"),
|
||||
File("#/lib/subghz/protocols/protocol_items.h"),
|
||||
File("#/lib/subghz/protocols/raw.h"),
|
||||
File("#/lib/subghz/blocks/const.h"),
|
||||
File("#/lib/subghz/blocks/decoder.h"),
|
||||
File("#/lib/subghz/blocks/encoder.h"),
|
||||
File("#/lib/subghz/blocks/generic.h"),
|
||||
File("#/lib/subghz/blocks/math.h"),
|
||||
File("#/lib/subghz/subghz_setting.h"),
|
||||
File("environment.h"),
|
||||
File("receiver.h"),
|
||||
File("subghz_worker.h"),
|
||||
File("subghz_tx_rx_worker.h"),
|
||||
File("transmitter.h"),
|
||||
File("registry.h"),
|
||||
File("protocols/protocol_items.h"),
|
||||
File("protocols/raw.h"),
|
||||
File("blocks/const.h"),
|
||||
File("blocks/decoder.h"),
|
||||
File("blocks/encoder.h"),
|
||||
File("blocks/generic.h"),
|
||||
File("blocks/math.h"),
|
||||
File("subghz_setting.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -462,10 +462,7 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat*
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
|
||||
@@ -476,6 +473,11 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat*
|
||||
}
|
||||
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
|
||||
seed_data[3];
|
||||
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
res = true;
|
||||
} while(false);
|
||||
|
||||
|
||||
@@ -371,15 +371,6 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "ENCODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
|
||||
@@ -390,6 +381,20 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
|
||||
seed_data[3];
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "ENCODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
|
||||
subghz_protocol_keeloq_check_remote_controller(
|
||||
&instance->generic, instance->keystore, &instance->manufacture_name);
|
||||
|
||||
@@ -979,9 +984,22 @@ bool subghz_protocol_decoder_keeloq_serialize(
|
||||
subghz_protocol_keeloq_check_remote_controller(
|
||||
&instance->generic, instance->keystore, &instance->manufacture_name);
|
||||
|
||||
if(strcmp(instance->manufacture_name, "BFT") == 0) {
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF;
|
||||
}
|
||||
if(res && !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) {
|
||||
FURI_LOG_E(TAG, "DECODER Serialize: Unable to add Seed");
|
||||
res = false;
|
||||
}
|
||||
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
|
||||
seed_data[3];
|
||||
}
|
||||
|
||||
if(res && !flipper_format_write_string_cstr(
|
||||
flipper_format, "Manufacture", instance->manufacture_name)) {
|
||||
FURI_LOG_E(TAG, "Unable to add manufacture name");
|
||||
FURI_LOG_E(TAG, "DECODER Serialize: Unable to add manufacture name");
|
||||
res = false;
|
||||
}
|
||||
return res;
|
||||
@@ -1001,19 +1019,6 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "DECODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
uint8_t seed_data[sizeof(uint32_t)] = {0};
|
||||
for(size_t i = 0; i < sizeof(uint32_t); i++) {
|
||||
@@ -1024,6 +1029,21 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl
|
||||
}
|
||||
instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 |
|
||||
seed_data[3];
|
||||
|
||||
// Read manufacturer from file
|
||||
if(flipper_format_read_string(
|
||||
flipper_format, "Manufacture", instance->manufacture_from_file)) {
|
||||
instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
mfname = furi_string_get_cstr(instance->manufacture_from_file);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "DECODER: Missing Manufacture");
|
||||
}
|
||||
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
|
||||
res = true;
|
||||
} while(false);
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ void* subghz_protocol_encoder_nice_flor_s_alloc(SubGhzEnvironment* environment)
|
||||
instance->nice_flor_s_rainbow_table_file_name =
|
||||
subghz_environment_get_nice_flor_s_rainbow_table_file_name(environment);
|
||||
if(instance->nice_flor_s_rainbow_table_file_name) {
|
||||
FURI_LOG_I(
|
||||
FURI_LOG_D(
|
||||
TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name);
|
||||
}
|
||||
instance->encoder.repeat = 10;
|
||||
@@ -343,7 +343,7 @@ void* subghz_protocol_decoder_nice_flor_s_alloc(SubGhzEnvironment* environment)
|
||||
instance->nice_flor_s_rainbow_table_file_name =
|
||||
subghz_environment_get_nice_flor_s_rainbow_table_file_name(environment);
|
||||
if(instance->nice_flor_s_rainbow_table_file_name) {
|
||||
FURI_LOG_I(
|
||||
FURI_LOG_D(
|
||||
TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name);
|
||||
}
|
||||
return instance;
|
||||
|
||||
@@ -8,23 +8,23 @@ env.Append(
|
||||
"#/lib/toolbox",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("#/lib/toolbox/manchester_decoder.h"),
|
||||
File("#/lib/toolbox/manchester_encoder.h"),
|
||||
File("#/lib/toolbox/path.h"),
|
||||
File("#/lib/toolbox/random_name.h"),
|
||||
File("#/lib/toolbox/hmac_sha256.h"),
|
||||
File("#/lib/toolbox/crc32_calc.h"),
|
||||
File("#/lib/toolbox/dir_walk.h"),
|
||||
File("#/lib/toolbox/md5.h"),
|
||||
File("#/lib/toolbox/args.h"),
|
||||
File("#/lib/toolbox/saved_struct.h"),
|
||||
File("#/lib/toolbox/version.h"),
|
||||
File("#/lib/toolbox/tar/tar_archive.h"),
|
||||
File("#/lib/toolbox/stream/stream.h"),
|
||||
File("#/lib/toolbox/stream/file_stream.h"),
|
||||
File("#/lib/toolbox/stream/string_stream.h"),
|
||||
File("#/lib/toolbox/stream/buffered_file_stream.h"),
|
||||
File("#/lib/toolbox/protocols/protocol_dict.h"),
|
||||
File("manchester_decoder.h"),
|
||||
File("manchester_encoder.h"),
|
||||
File("path.h"),
|
||||
File("random_name.h"),
|
||||
File("hmac_sha256.h"),
|
||||
File("crc32_calc.h"),
|
||||
File("dir_walk.h"),
|
||||
File("md5.h"),
|
||||
File("args.h"),
|
||||
File("saved_struct.h"),
|
||||
File("version.h"),
|
||||
File("tar/tar_archive.h"),
|
||||
File("stream/stream.h"),
|
||||
File("stream/file_stream.h"),
|
||||
File("stream/string_stream.h"),
|
||||
File("stream/buffered_file_stream.h"),
|
||||
File("protocols/protocol_dict.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import SCons
|
||||
from SCons.Subst import quote_spaces
|
||||
from SCons.Errors import StopError
|
||||
from SCons.Node.FS import _my_normcase
|
||||
|
||||
import re
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)")
|
||||
|
||||
@@ -41,3 +41,14 @@ def link_dir(target_path, source_path, is_windows):
|
||||
|
||||
def single_quote(arg_list):
|
||||
return " ".join(f"'{arg}'" if " " in arg else str(arg) for arg in arg_list)
|
||||
|
||||
|
||||
def extract_abs_dir_path(node):
|
||||
if isinstance(node, SCons.Node.FS.EntryProxy):
|
||||
node = node.get()
|
||||
|
||||
for repo_dir in node.get_all_rdirs():
|
||||
if os.path.exists(repo_dir.abspath):
|
||||
return repo_dir.abspath
|
||||
|
||||
raise StopError(f"Can't find absolute path for {node.name}")
|
||||
|
||||
@@ -37,6 +37,21 @@ def _get_tool_version(env, tool):
|
||||
|
||||
|
||||
def generate(env, **kw):
|
||||
if not env.get("VERBOSE", False):
|
||||
env.SetDefault(
|
||||
CCCOMSTR="\tCC\t${SOURCE}",
|
||||
CXXCOMSTR="\tCPP\t${SOURCE}",
|
||||
ASCOMSTR="\tASM\t${SOURCE}",
|
||||
ARCOMSTR="\tAR\t${TARGET}",
|
||||
RANLIBCOMSTR="\tRANLIB\t${TARGET}",
|
||||
LINKCOMSTR="\tLINK\t${TARGET}",
|
||||
INSTALLSTR="\tINSTALL\t${TARGET}",
|
||||
APPSCOMSTR="\tAPPS\t${TARGET}",
|
||||
VERSIONCOMSTR="\tVERSION\t${TARGET}",
|
||||
STRIPCOMSTR="\tSTRIP\t${TARGET}",
|
||||
OBJDUMPCOMSTR="\tOBJDUMP\t${TARGET}",
|
||||
)
|
||||
|
||||
for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump):
|
||||
orig_tool.generate(env)
|
||||
env.SetDefault(
|
||||
|
||||
@@ -2,7 +2,7 @@ from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Warnings import warn, WarningOnByDefault
|
||||
import SCons
|
||||
import os.path
|
||||
from ansi.color import fg
|
||||
|
||||
from fbt.appmanifest import (
|
||||
FlipperAppType,
|
||||
@@ -16,21 +16,20 @@ from fbt.appmanifest import (
|
||||
# AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config
|
||||
|
||||
|
||||
def LoadApplicationManifests(env):
|
||||
appmgr = env["APPMGR"] = AppManager()
|
||||
for app_dir, _ in env["APPDIRS"]:
|
||||
app_dir_node = env.Dir("#").Dir(app_dir)
|
||||
def LoadAppManifest(env, entry):
|
||||
try:
|
||||
APP_MANIFEST_NAME = "application.fam"
|
||||
manifest_glob = entry.glob(APP_MANIFEST_NAME)
|
||||
if len(manifest_glob) == 0:
|
||||
raise FlipperManifestException(
|
||||
f"Folder {entry}: manifest {APP_MANIFEST_NAME} is missing"
|
||||
)
|
||||
|
||||
for entry in app_dir_node.glob("*", ondisk=True, source=True):
|
||||
if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."):
|
||||
try:
|
||||
app_manifest_file_path = os.path.join(
|
||||
entry.abspath, "application.fam"
|
||||
)
|
||||
appmgr.load_manifest(app_manifest_file_path, entry)
|
||||
env.Append(PY_LINT_SOURCES=[app_manifest_file_path])
|
||||
except FlipperManifestException as e:
|
||||
warn(WarningOnByDefault, str(e))
|
||||
app_manifest_file_path = manifest_glob[0].rfile().abspath
|
||||
env["APPMGR"].load_manifest(app_manifest_file_path, entry)
|
||||
env.Append(PY_LINT_SOURCES=[app_manifest_file_path])
|
||||
except FlipperManifestException as e:
|
||||
warn(WarningOnByDefault, str(e))
|
||||
|
||||
|
||||
def PrepareApplicationsBuild(env):
|
||||
@@ -46,12 +45,12 @@ def PrepareApplicationsBuild(env):
|
||||
|
||||
def DumpApplicationConfig(target, source, env):
|
||||
print(f"Loaded {len(env['APPMGR'].known_apps)} app definitions.")
|
||||
print("Firmware modules configuration:")
|
||||
print(fg.boldgreen("Firmware modules configuration:"))
|
||||
for apptype in FlipperAppType:
|
||||
app_sublist = env["APPBUILD"].get_apps_of_type(apptype)
|
||||
if app_sublist:
|
||||
print(
|
||||
f"{apptype.value}:\n\t",
|
||||
fg.green(f"{apptype.value}:\n\t"),
|
||||
", ".join(app.appid for app in app_sublist),
|
||||
)
|
||||
|
||||
@@ -65,8 +64,11 @@ def build_apps_c(target, source, env):
|
||||
|
||||
|
||||
def generate(env):
|
||||
env.AddMethod(LoadApplicationManifests)
|
||||
env.AddMethod(LoadAppManifest)
|
||||
env.AddMethod(PrepareApplicationsBuild)
|
||||
env.SetDefault(
|
||||
APPMGR=AppManager(),
|
||||
)
|
||||
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import SCons
|
||||
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Node.FS import File
|
||||
from SCons.Errors import SConsEnvironmentError
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from ansi.color import fg
|
||||
|
||||
|
||||
def icons_emitter(target, source, env):
|
||||
@@ -13,7 +12,6 @@ def icons_emitter(target, source, env):
|
||||
target[0].File(env.subst("${ICON_FILE_NAME}.c")),
|
||||
target[0].File(env.subst("${ICON_FILE_NAME}.h")),
|
||||
]
|
||||
source = env.GlobRecursive("*.*", env["ICON_SRC_DIR"])
|
||||
return target, source
|
||||
|
||||
|
||||
@@ -86,7 +84,7 @@ def proto_ver_generator(target, source, env):
|
||||
)
|
||||
except (subprocess.CalledProcessError, EnvironmentError) as e:
|
||||
# Not great, not terrible
|
||||
print("Git: fetch failed")
|
||||
print(fg.boldred("Git: fetch failed"))
|
||||
|
||||
try:
|
||||
git_describe = _invoke_git(
|
||||
@@ -94,10 +92,8 @@ def proto_ver_generator(target, source, env):
|
||||
source_dir=src_dir,
|
||||
)
|
||||
except (subprocess.CalledProcessError, EnvironmentError) as e:
|
||||
print("Git: describe failed")
|
||||
Exit("git error")
|
||||
raise SConsEnvironmentError("Git: describe failed")
|
||||
|
||||
# print("describe=", git_describe)
|
||||
git_major, git_minor = git_describe.split(".")
|
||||
version_file_data = (
|
||||
"#pragma once",
|
||||
@@ -116,7 +112,7 @@ def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"
|
||||
|
||||
icons = env.IconBuilder(
|
||||
target_dir,
|
||||
ICON_SRC_DIR=source_dir,
|
||||
source_dir,
|
||||
ICON_FILE_NAME=icon_bundle_name,
|
||||
)
|
||||
env.Depends(icons, icons_src)
|
||||
@@ -125,8 +121,8 @@ def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"
|
||||
|
||||
def generate(env):
|
||||
env.SetDefault(
|
||||
ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py",
|
||||
NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py",
|
||||
ASSETS_COMPILER="${FBT_SCRIPT_DIR}/assets.py",
|
||||
NANOPB_COMPILER="${ROOT_DIR}/lib/nanopb/generator/nanopb_generator.py",
|
||||
)
|
||||
env.AddMethod(CompileIcons)
|
||||
|
||||
@@ -143,7 +139,7 @@ def generate(env):
|
||||
BUILDERS={
|
||||
"IconBuilder": Builder(
|
||||
action=Action(
|
||||
'${PYTHON3} "${ASSETS_COMPILER}" icons ${ICON_SRC_DIR} ${TARGET.dir} --filename ${ICON_FILE_NAME}',
|
||||
'${PYTHON3} "${ASSETS_COMPILER}" icons ${ABSPATHGETTERFUNC(SOURCE)} ${TARGET.dir} --filename ${ICON_FILE_NAME}',
|
||||
"${ICONSCOMSTR}",
|
||||
),
|
||||
emitter=icons_emitter,
|
||||
|
||||
@@ -103,7 +103,7 @@ def DistCommand(env, name, source, **kw):
|
||||
command = env.Command(
|
||||
target,
|
||||
source,
|
||||
'@${PYTHON3} "${ROOT_DIR.abspath}/scripts/sconsdist.py" copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}',
|
||||
'@${PYTHON3} "${DIST_SCRIPT}" copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}',
|
||||
**kw,
|
||||
)
|
||||
env.Pseudo(target)
|
||||
@@ -121,6 +121,9 @@ def generate(env):
|
||||
|
||||
env.SetDefault(
|
||||
COPRO_MCU_FAMILY="STM32WB5x",
|
||||
SELFUPDATE_SCRIPT="${FBT_SCRIPT_DIR}/selfupdate.py",
|
||||
DIST_SCRIPT="${FBT_SCRIPT_DIR}/sconsdist.py",
|
||||
COPRO_ASSETS_SCRIPT="${FBT_SCRIPT_DIR}/assets.py",
|
||||
)
|
||||
|
||||
env.Append(
|
||||
@@ -128,7 +131,7 @@ def generate(env):
|
||||
"UsbInstall": Builder(
|
||||
action=[
|
||||
Action(
|
||||
'${PYTHON3} "${ROOT_DIR.abspath}/scripts/selfupdate.py" dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf'
|
||||
'${PYTHON3} "${SELFUPDATE_SCRIPT}" dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf'
|
||||
),
|
||||
Touch("${TARGET}"),
|
||||
]
|
||||
@@ -136,7 +139,7 @@ def generate(env):
|
||||
"CoproBuilder": Builder(
|
||||
action=Action(
|
||||
[
|
||||
'${PYTHON3} "${ROOT_DIR.abspath}/scripts/assets.py" '
|
||||
'${PYTHON3} "${COPRO_ASSETS_SCRIPT}" '
|
||||
"copro ${COPRO_CUBE_DIR} "
|
||||
"${TARGET} ${COPRO_MCU_FAMILY} "
|
||||
"--cube_ver=${COPRO_CUBE_VERSION} "
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import shutil
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Errors import UserError
|
||||
import SCons.Warnings
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
from fbt.elfmanifest import assemble_manifest_data
|
||||
from fbt.appmanifest import FlipperApplication, FlipperManifestException
|
||||
from fbt.sdk.cache import SdkCache
|
||||
from fbt.util import extract_abs_dir_path
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import itertools
|
||||
import shutil
|
||||
|
||||
from ansi.color import fg
|
||||
|
||||
|
||||
@@ -62,7 +65,7 @@ def BuildAppElf(env, app):
|
||||
lib_src_root_path = os.path.join(app_work_dir, "lib", lib_def.name)
|
||||
app_env.AppendUnique(
|
||||
CPPPATH=list(
|
||||
app_env.Dir(lib_src_root_path).Dir(incpath).srcnode()
|
||||
app_env.Dir(lib_src_root_path).Dir(incpath).srcnode().rfile().abspath
|
||||
for incpath in lib_def.fap_include_paths
|
||||
),
|
||||
)
|
||||
@@ -82,7 +85,12 @@ def BuildAppElf(env, app):
|
||||
*lib_def.cflags,
|
||||
],
|
||||
CPPDEFINES=lib_def.cdefines,
|
||||
CPPPATH=list(map(app._appdir.Dir, lib_def.cincludes)),
|
||||
CPPPATH=list(
|
||||
map(
|
||||
lambda cpath: extract_abs_dir_path(app._appdir.Dir(cpath)),
|
||||
lib_def.cincludes,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
lib = private_lib_env.StaticLibrary(
|
||||
@@ -157,7 +165,6 @@ def prepare_app_metadata(target, source, env):
|
||||
app = env["APP"]
|
||||
meta_file_name = source[0].path + ".meta"
|
||||
with open(meta_file_name, "wb") as f:
|
||||
# f.write(f"hello this is {app}")
|
||||
f.write(
|
||||
assemble_manifest_data(
|
||||
app_manifest=app,
|
||||
@@ -236,7 +243,10 @@ def fap_dist_action(target, source, env):
|
||||
|
||||
|
||||
def generate(env, **kw):
|
||||
env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR"))
|
||||
env.SetDefault(
|
||||
EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR"),
|
||||
APP_RUN_SCRIPT="${FBT_SCRIPT_DIR}/runfap.py",
|
||||
)
|
||||
|
||||
if not env["VERBOSE"]:
|
||||
env.SetDefault(
|
||||
|
||||
@@ -46,7 +46,9 @@ def prebuild_sdk_emitter(target, source, env):
|
||||
def prebuild_sdk_create_origin_file(target, source, env):
|
||||
mega_file = env.subst("${TARGET}.c", target=target[0])
|
||||
with open(mega_file, "wt") as sdk_c:
|
||||
sdk_c.write("\n".join(f"#include <{h.path}>" for h in env["SDK_HEADERS"]))
|
||||
sdk_c.write(
|
||||
"\n".join(f"#include <{h.srcnode().path}>" for h in env["SDK_HEADERS"])
|
||||
)
|
||||
|
||||
|
||||
class SdkMeta:
|
||||
@@ -62,18 +64,25 @@ class SdkMeta:
|
||||
"cc_args": self._wrap_scons_vars("$CCFLAGS $_CCCOMCOM"),
|
||||
"cpp_args": self._wrap_scons_vars("$CXXFLAGS $CCFLAGS $_CCCOMCOM"),
|
||||
"linker_args": self._wrap_scons_vars("$LINKFLAGS"),
|
||||
"linker_script": self.env.subst("${LINKER_SCRIPT_PATH}"),
|
||||
"linker_libs": self.env.subst("${LIBS}"),
|
||||
"app_ep_subst": self.env.subst("${APP_ENTRY}"),
|
||||
"sdk_path_subst": self.env.subst("${SDK_DIR_SUBST}"),
|
||||
"hardware": self.env.subst("${TARGET_HW}"),
|
||||
}
|
||||
with open(json_manifest_path, "wt") as f:
|
||||
json.dump(meta_contents, f, indent=4)
|
||||
|
||||
def _wrap_scons_vars(self, vars: str):
|
||||
expanded_vars = self.env.subst(vars, target=Entry("dummy"))
|
||||
expanded_vars = self.env.subst(
|
||||
vars,
|
||||
target=Entry("dummy"),
|
||||
)
|
||||
return expanded_vars.replace("\\", "/")
|
||||
|
||||
|
||||
class SdkTreeBuilder:
|
||||
SDK_DIR_SUBST = "SDK_ROOT_DIR"
|
||||
SDK_APP_EP_SUBST = "SDK_APP_EP_SUBST"
|
||||
|
||||
def __init__(self, env, target, source) -> None:
|
||||
self.env = env
|
||||
@@ -87,6 +96,11 @@ class SdkTreeBuilder:
|
||||
self.sdk_root_dir = target[0].Dir(".")
|
||||
self.sdk_deploy_dir = self.sdk_root_dir.Dir(self.target_sdk_dir_name)
|
||||
|
||||
self.sdk_env = self.env.Clone(
|
||||
APP_ENTRY=self.SDK_APP_EP_SUBST,
|
||||
SDK_DIR_SUBST=self.SDK_DIR_SUBST,
|
||||
)
|
||||
|
||||
def _parse_sdk_depends(self):
|
||||
deps_file = self.source[0]
|
||||
with open(deps_file.path, "rt") as deps_f:
|
||||
@@ -95,38 +109,36 @@ class SdkTreeBuilder:
|
||||
self.header_depends = list(
|
||||
filter(lambda fname: fname.endswith(".h"), depends.split()),
|
||||
)
|
||||
self.header_depends.append(self.env.subst("${LINKER_SCRIPT_PATH}"))
|
||||
self.header_depends.append(self.env.subst("${SDK_DEFINITION}"))
|
||||
self.header_depends.append(self.sdk_env.subst("${LINKER_SCRIPT_PATH}"))
|
||||
self.header_depends.append(self.sdk_env.subst("${SDK_DEFINITION}"))
|
||||
self.header_dirs = sorted(
|
||||
set(map(os.path.normpath, map(os.path.dirname, self.header_depends)))
|
||||
)
|
||||
|
||||
def _generate_sdk_meta(self):
|
||||
filtered_paths = [self.target_sdk_dir_name]
|
||||
filtered_paths = ["."]
|
||||
full_fw_paths = list(
|
||||
map(
|
||||
os.path.normpath,
|
||||
(self.env.Dir(inc_dir).relpath for inc_dir in self.env["CPPPATH"]),
|
||||
(
|
||||
self.sdk_env.Dir(inc_dir).relpath
|
||||
for inc_dir in self.sdk_env["CPPPATH"]
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
sdk_dirs = ", ".join(f"'{dir}'" for dir in self.header_dirs)
|
||||
filtered_paths.extend(
|
||||
map(
|
||||
self.build_sdk_file_path,
|
||||
filter(lambda path: path in sdk_dirs, full_fw_paths),
|
||||
)
|
||||
filter(lambda path: path in sdk_dirs, full_fw_paths),
|
||||
)
|
||||
filtered_paths = list(map(self.build_sdk_file_path, filtered_paths))
|
||||
|
||||
sdk_env = self.env.Clone()
|
||||
sdk_env.Replace(
|
||||
self.sdk_env.Replace(
|
||||
CPPPATH=filtered_paths,
|
||||
LINKER_SCRIPT=self.env.subst("${APP_LINKER_SCRIPT}"),
|
||||
ORIG_LINKER_SCRIPT_PATH=self.env["LINKER_SCRIPT_PATH"],
|
||||
LINKER_SCRIPT_PATH=self.build_sdk_file_path("${ORIG_LINKER_SCRIPT_PATH}"),
|
||||
)
|
||||
|
||||
meta = SdkMeta(sdk_env, self)
|
||||
meta = SdkMeta(self.sdk_env, self)
|
||||
meta.save_to(self.target[0].path)
|
||||
|
||||
def build_sdk_file_path(self, orig_path: str) -> str:
|
||||
@@ -211,7 +223,7 @@ def validate_sdk_cache(source, target, env):
|
||||
current_sdk = SdkCollector()
|
||||
current_sdk.process_source_file_for_sdk(source[0].path)
|
||||
for h in env["SDK_HEADERS"]:
|
||||
current_sdk.add_header_to_sdk(pathlib.Path(h.path).as_posix())
|
||||
current_sdk.add_header_to_sdk(pathlib.Path(h.srcnode().path).as_posix())
|
||||
|
||||
sdk_cache = SdkCache(target[0].path)
|
||||
sdk_cache.validate_api(current_sdk.get_api())
|
||||
|
||||
@@ -12,11 +12,14 @@ def version_emitter(target, source, env):
|
||||
|
||||
|
||||
def generate(env):
|
||||
env.SetDefault(
|
||||
VERSION_SCRIPT="${FBT_SCRIPT_DIR}/version.py",
|
||||
)
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
"VersionBuilder": Builder(
|
||||
action=Action(
|
||||
'${PYTHON3} "${ROOT_DIR.abspath}/scripts/version.py" generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir "${ROOT_DIR}"',
|
||||
'${PYTHON3} "${VERSION_SCRIPT}" generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir "${ROOT_DIR}"',
|
||||
"${VERSIONCOMSTR}",
|
||||
),
|
||||
emitter=version_emitter,
|
||||
|
||||
@@ -8,7 +8,8 @@ __NM_ARM_BIN = "arm-none-eabi-nm"
|
||||
|
||||
def generate(env):
|
||||
env.SetDefault(
|
||||
BIN2DFU="${ROOT_DIR.abspath}/scripts/bin2dfu.py",
|
||||
BIN2DFU="${FBT_SCRIPT_DIR}/bin2dfu.py",
|
||||
BIN_SIZE_SCRIPT="${FBT_SCRIPT_DIR}/fwsize.py",
|
||||
OBJCOPY=__OBJCOPY_ARM_BIN, # FIXME
|
||||
NM=__NM_ARM_BIN, # FIXME
|
||||
)
|
||||
|
||||