mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
SubGHz: Rework GPS as plugin, fix VGM (#5)
- Streamlined atomic init and deinit - Load from plugin into RAM dynamically - Don't attempt load if VGM / Expansion is connected - Deduplicated some code, cleaned up some other bits
This commit is contained in:
@@ -10,6 +10,8 @@ App(
|
||||
# Sources separation breaks linking with subghz on internal, commented for now
|
||||
# sources=[
|
||||
# "*.c",
|
||||
# "!helpers/subghz_gps.c",
|
||||
# "!helpers/minmea.c",
|
||||
# "!subghz_cli.c",
|
||||
# "!helpers/subghz_chat.c",
|
||||
# "!subghz_extended_freq.c",
|
||||
@@ -32,6 +34,15 @@ App(
|
||||
fap_category="Sub-GHz",
|
||||
)
|
||||
|
||||
App(
|
||||
appid="subghz_gps",
|
||||
targets=["f7"],
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="subghz_gps_plugin_ep",
|
||||
requires=["subghz"],
|
||||
sources=["helpers/subghz_gps.c", "helpers/minmea.c"],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="subghz_cli",
|
||||
targets=["f7"],
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
#include "subghz_gps.h"
|
||||
#include "minmea.h"
|
||||
|
||||
#include <expansion/expansion.h>
|
||||
#include <momentum/momentum.h>
|
||||
|
||||
#define UART_CH (momentum_settings.uart_nmea_channel)
|
||||
|
||||
typedef enum {
|
||||
WorkerEvtStop = (1 << 0),
|
||||
WorkerEvtRxDone = (1 << 1),
|
||||
} WorkerEvtFlags;
|
||||
|
||||
#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
|
||||
|
||||
static void subghz_gps_uart_parse_nmea(SubGhzGPS* subghz_gps, char* line) {
|
||||
switch(minmea_sentence_id(line, false)) {
|
||||
case MINMEA_SENTENCE_RMC: {
|
||||
@@ -113,9 +125,93 @@ static int32_t subghz_gps_uart_worker(void* context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SubGhzGPS* subghz_gps_init() {
|
||||
SubGhzGPS* subghz_gps = malloc(sizeof(SubGhzGPS));
|
||||
static void subghz_gps_deinit(SubGhzGPS* subghz_gps) {
|
||||
furi_assert(subghz_gps);
|
||||
|
||||
furi_hal_serial_async_rx_stop(subghz_gps->serial_handle);
|
||||
furi_hal_serial_deinit(subghz_gps->serial_handle);
|
||||
furi_hal_serial_control_release(subghz_gps->serial_handle);
|
||||
|
||||
expansion_enable(furi_record_open(RECORD_EXPANSION));
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(subghz_gps->thread), WorkerEvtStop);
|
||||
furi_thread_join(subghz_gps->thread);
|
||||
furi_thread_free(subghz_gps->thread);
|
||||
|
||||
furi_stream_buffer_free(subghz_gps->rx_stream);
|
||||
}
|
||||
|
||||
static float subghz_gps_deg2rad(float deg) {
|
||||
return (deg * M_PI / 180);
|
||||
}
|
||||
|
||||
static float subghz_gps_calc_distance(float lat1d, float lon1d, float lat2d, float lon2d) {
|
||||
float lat1r, lon1r, lat2r, lon2r;
|
||||
double u, v;
|
||||
lat1r = subghz_gps_deg2rad(lat1d);
|
||||
lon1r = subghz_gps_deg2rad(lon1d);
|
||||
lat2r = subghz_gps_deg2rad(lat2d);
|
||||
lon2r = subghz_gps_deg2rad(lon2d);
|
||||
u = sin((lat2r - lat1r) / 2);
|
||||
v = sin((lon2r - lon1r) / 2);
|
||||
return 2 * 6371 * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
|
||||
}
|
||||
|
||||
static float subghz_gps_calc_angle(float lat1, float lon1, float lat2, float lon2) {
|
||||
return atan2(lat1 - lat2, lon1 - lon2) * 180 / (double)M_PI;
|
||||
}
|
||||
|
||||
static void subghz_gps_get_descr(
|
||||
SubGhzGPS* subghz_gps,
|
||||
FuriString* descr,
|
||||
float latitude,
|
||||
float longitude) {
|
||||
float distance =
|
||||
subghz_gps_calc_distance(latitude, longitude, subghz_gps->latitude, subghz_gps->longitude);
|
||||
|
||||
float angle =
|
||||
subghz_gps_calc_angle(latitude, longitude, subghz_gps->latitude, subghz_gps->longitude);
|
||||
|
||||
char* angle_str = "?";
|
||||
if(angle > -22.5 && angle <= 22.5) {
|
||||
angle_str = "E";
|
||||
} else if(angle > 22.5 && angle <= 67.5) {
|
||||
angle_str = "NE";
|
||||
} else if(angle > 67.5 && angle <= 112.5) {
|
||||
angle_str = "N";
|
||||
} else if(angle > 112.5 && angle <= 157.5) {
|
||||
angle_str = "NW";
|
||||
} else if(angle < -22.5 && angle >= -67.5) {
|
||||
angle_str = "SE";
|
||||
} else if(angle < -67.5 && angle >= -112.5) {
|
||||
angle_str = "S";
|
||||
} else if(angle < -112.5 && angle >= -157.5) {
|
||||
angle_str = "SW";
|
||||
} else if(angle < -157.5 || angle >= 157.5) {
|
||||
angle_str = "W";
|
||||
}
|
||||
|
||||
furi_string_printf(
|
||||
descr,
|
||||
"Captured at: %f,\r\n"
|
||||
"%f\r\n"
|
||||
"\r\n"
|
||||
"Realtime: Sats: %d\r\n"
|
||||
"Distance: %.2f%s Dir: %s\r\n"
|
||||
"GPS time: %02d:%02d:%02d UTC",
|
||||
(double)latitude,
|
||||
(double)longitude,
|
||||
subghz_gps->satellites,
|
||||
(double)(subghz_gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0),
|
||||
distance > 1 ? "km" : "m",
|
||||
angle_str,
|
||||
subghz_gps->fix_hour,
|
||||
subghz_gps->fix_minute,
|
||||
subghz_gps->fix_second);
|
||||
}
|
||||
|
||||
static void subghz_gps_init(SubGhzGPS* subghz_gps, uint32_t baudrate) {
|
||||
subghz_gps->latitude = NAN;
|
||||
subghz_gps->longitude = NAN;
|
||||
subghz_gps->satellites = 0;
|
||||
@@ -125,69 +221,32 @@ SubGhzGPS* subghz_gps_init() {
|
||||
|
||||
subghz_gps->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
|
||||
|
||||
subghz_gps->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(subghz_gps->thread, "SubGhzGPSWorker");
|
||||
furi_thread_set_stack_size(subghz_gps->thread, 1024);
|
||||
furi_thread_set_context(subghz_gps->thread, subghz_gps);
|
||||
furi_thread_set_callback(subghz_gps->thread, subghz_gps_uart_worker);
|
||||
subghz_gps->thread =
|
||||
furi_thread_alloc_ex("SubGhzGPSWorker", 1024, subghz_gps_uart_worker, subghz_gps);
|
||||
furi_thread_start(subghz_gps->thread);
|
||||
|
||||
subghz_gps->expansion = furi_record_open(RECORD_EXPANSION);
|
||||
expansion_disable(subghz_gps->expansion);
|
||||
expansion_disable(furi_record_open(RECORD_EXPANSION));
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
|
||||
subghz_gps->serial_handle = furi_hal_serial_control_acquire(UART_CH);
|
||||
furi_check(subghz_gps->serial_handle);
|
||||
furi_hal_serial_init(subghz_gps->serial_handle, 9600);
|
||||
furi_hal_serial_init(subghz_gps->serial_handle, baudrate);
|
||||
|
||||
furi_hal_serial_async_rx_start(
|
||||
subghz_gps->serial_handle, subghz_gps_uart_on_irq_cb, subghz_gps, false);
|
||||
|
||||
return subghz_gps;
|
||||
subghz_gps->deinit = &subghz_gps_deinit;
|
||||
subghz_gps->get_descr = &subghz_gps_get_descr;
|
||||
}
|
||||
|
||||
void subghz_gps_deinit(SubGhzGPS* subghz_gps) {
|
||||
furi_assert(subghz_gps);
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
furi_hal_serial_async_rx_stop(subghz_gps->serial_handle);
|
||||
furi_hal_serial_deinit(subghz_gps->serial_handle);
|
||||
furi_hal_serial_control_release(subghz_gps->serial_handle);
|
||||
static const FlipperAppPluginDescriptor plugin_descriptor = {
|
||||
.appid = "subghz_gps",
|
||||
.ep_api_version = 1,
|
||||
.entry_point = &subghz_gps_init,
|
||||
};
|
||||
|
||||
expansion_enable(subghz_gps->expansion);
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
|
||||
furi_thread_free(subghz_gps->thread);
|
||||
furi_stream_buffer_free(subghz_gps->rx_stream);
|
||||
|
||||
free(subghz_gps);
|
||||
const FlipperAppPluginDescriptor* subghz_gps_plugin_ep(void) {
|
||||
return &plugin_descriptor;
|
||||
}
|
||||
|
||||
void subghz_gps_start(SubGhzGPS* subghz_gps) {
|
||||
furi_thread_start(subghz_gps->thread);
|
||||
}
|
||||
|
||||
void subghz_gps_stop(SubGhzGPS* subghz_gps) {
|
||||
furi_thread_flags_set(furi_thread_get_id(subghz_gps->thread), WorkerEvtStop);
|
||||
furi_thread_join(subghz_gps->thread);
|
||||
}
|
||||
|
||||
void subghz_gps_set_baudrate(SubGhzGPS* subghz_gps, uint32_t baudrate) {
|
||||
furi_hal_serial_set_br(subghz_gps->serial_handle, baudrate);
|
||||
}
|
||||
|
||||
double subghz_gps_deg2rad(double deg) {
|
||||
return (deg * (double)M_PI / 180);
|
||||
}
|
||||
|
||||
double subghz_gps_calc_distance(double lat1d, double lon1d, double lat2d, double lon2d) {
|
||||
double lat1r, lon1r, lat2r, lon2r, u, v;
|
||||
lat1r = subghz_gps_deg2rad(lat1d);
|
||||
lon1r = subghz_gps_deg2rad(lon1d);
|
||||
lat2r = subghz_gps_deg2rad(lat2d);
|
||||
lon2r = subghz_gps_deg2rad(lon2d);
|
||||
u = sin((lat2r - lat1r) / 2);
|
||||
v = sin((lon2r - lon1r) / 2);
|
||||
return 2 * 6371 * asin(sqrt(u * u + cos((double)lat1r) * cos((double)lat2r) * v * v));
|
||||
}
|
||||
|
||||
double subghz_gps_calc_angle(double lat1, double lon1, double lat2, double lon2) {
|
||||
return atan2(lat1 - lat2, lon1 - lon2) * 180 / (double)M_PI;
|
||||
}
|
||||
@@ -1,25 +1,18 @@
|
||||
#include <furi_hal.h>
|
||||
#include <momentum/momentum.h>
|
||||
#include <expansion/expansion.h>
|
||||
#pragma once
|
||||
|
||||
#define UART_CH (momentum_settings.uart_nmea_channel)
|
||||
#include <furi_hal.h>
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#define RX_BUF_SIZE 1024
|
||||
|
||||
typedef enum {
|
||||
WorkerEvtStop = (1 << 0),
|
||||
WorkerEvtRxDone = (1 << 1),
|
||||
} WorkerEvtFlags;
|
||||
typedef struct SubGhzGPS SubGhzGPS;
|
||||
|
||||
#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
|
||||
|
||||
typedef struct {
|
||||
Expansion* expansion;
|
||||
struct SubGhzGPS {
|
||||
FlipperApplication* plugin_app;
|
||||
FuriThread* thread;
|
||||
FuriStreamBuffer* rx_stream;
|
||||
uint8_t rx_buf[RX_BUF_SIZE];
|
||||
FuriHalSerialHandle* serial_handle;
|
||||
|
||||
FuriTimer* timer;
|
||||
|
||||
float latitude;
|
||||
@@ -28,73 +21,40 @@ typedef struct {
|
||||
uint8_t fix_second;
|
||||
uint8_t fix_minute;
|
||||
uint8_t fix_hour;
|
||||
} SubGhzGPS;
|
||||
|
||||
/**
|
||||
* Deinitialize SubGhzGPS object
|
||||
* To be used by plugin handler
|
||||
*
|
||||
* @param subghz_gps SubGhzGPS object
|
||||
* @return void
|
||||
*/
|
||||
void (*deinit)(SubGhzGPS* subghz_gps);
|
||||
|
||||
/**
|
||||
* Get description for signal info
|
||||
*
|
||||
* @param subghz_gps SubGhzGPS object
|
||||
* @param descr Output string
|
||||
* @param latitude Latitude
|
||||
* @param longitude Longitude
|
||||
* @return void
|
||||
*/
|
||||
void (*get_descr)(SubGhzGPS* subghz_gps, FuriString* descr, float latitude, float longitude);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize SubGhzGPS object
|
||||
*
|
||||
* Initialize SubGhzGPS plugin
|
||||
* Fails and returns NULL if Expansion is connected
|
||||
*
|
||||
* @return SubGhzGPS* SubGhzGPS object
|
||||
*/
|
||||
SubGhzGPS* subghz_gps_init();
|
||||
SubGhzGPS* subghz_gps_plugin_init();
|
||||
|
||||
/**
|
||||
* Deinitialize SubGhzGPS object
|
||||
* Deinitialize SubGhzGPS plugin
|
||||
*
|
||||
* @param subghz_gps SubGhzGPS object
|
||||
* @return void
|
||||
*/
|
||||
void subghz_gps_deinit(SubGhzGPS* subghz_gps);
|
||||
|
||||
/**
|
||||
* Start GPS thread
|
||||
*
|
||||
* @param subghz_gps SubGhzGPS object
|
||||
* @return void
|
||||
*/
|
||||
void subghz_gps_start(SubGhzGPS* subghz_gps);
|
||||
|
||||
/**
|
||||
* Stop GPS thread
|
||||
*
|
||||
* @param subghz_gps SubGhzGPS object
|
||||
* @return void
|
||||
*/
|
||||
void subghz_gps_stop(SubGhzGPS* subghz_gps);
|
||||
|
||||
/**
|
||||
* Set baudrate for GPS
|
||||
*
|
||||
* @param baudrate Baudrate
|
||||
* @return void
|
||||
*/
|
||||
void subghz_gps_set_baudrate(SubGhzGPS* subghz_gps, uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* Convert degree to radian
|
||||
*
|
||||
* @param deg Degree
|
||||
* @return double Radian
|
||||
*/
|
||||
double subghz_gps_deg2rad(double deg);
|
||||
|
||||
/**
|
||||
* Calculate distance between two coordinates
|
||||
*
|
||||
* @param lat1d Latitude 1
|
||||
* @param lon1d Longitude 1
|
||||
* @param lat2d Latitude 2
|
||||
* @param lon2d Longitude 2
|
||||
* @return double Distance in km
|
||||
*/
|
||||
double subghz_gps_calc_distance(double lat1d, double lon1d, double lat2d, double lon2d);
|
||||
|
||||
/**
|
||||
* Calculate angle between two coordinates
|
||||
*
|
||||
* @param lat1 Latitude 1
|
||||
* @param lon1 Longitude 1
|
||||
* @param lat2 Latitude 2
|
||||
* @param lon2 Longitude 2
|
||||
* @return double Angle in degree
|
||||
*/
|
||||
double subghz_gps_calc_angle(double lat1, double lon1, double lat2, double lon2);
|
||||
void subghz_gps_plugin_deinit(SubGhzGPS* subghz_gps);
|
||||
|
||||
71
applications/main/subghz/helpers/subghz_gps_plugin.c
Normal file
71
applications/main/subghz/helpers/subghz_gps_plugin.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "subghz_gps.h"
|
||||
|
||||
#include <expansion/expansion.h>
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define TAG "SubGhzGPS"
|
||||
|
||||
SubGhzGPS* subghz_gps_plugin_init(uint32_t baudrate) {
|
||||
bool connected = expansion_is_connected(furi_record_open(RECORD_EXPANSION));
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
if(connected) return NULL;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperApplication* plugin_app = flipper_application_alloc(storage, firmware_api_interface);
|
||||
do {
|
||||
FlipperApplicationPreloadStatus preload_res = flipper_application_preload(
|
||||
plugin_app, EXT_PATH("apps_data/subghz/plugins/subghz_gps.fal"));
|
||||
|
||||
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to preload GPS plugin. Code: %d\r\n", preload_res);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_application_is_plugin(plugin_app)) {
|
||||
FURI_LOG_E(TAG, "GPS plugin file is not a library\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(plugin_app);
|
||||
if(load_status != FlipperApplicationLoadStatusSuccess) {
|
||||
FURI_LOG_E(TAG, "Failed to load GPS plugin file. Code %d\r\n", load_status);
|
||||
break;
|
||||
}
|
||||
|
||||
const FlipperAppPluginDescriptor* app_descriptor =
|
||||
flipper_application_plugin_get_descriptor(plugin_app);
|
||||
|
||||
if(strcmp(app_descriptor->appid, "subghz_gps") != 0) {
|
||||
FURI_LOG_E(TAG, "GPS plugin type doesn't match\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(app_descriptor->ep_api_version != 1) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"GPS plugin version %" PRIu32 " doesn't match\r\n",
|
||||
app_descriptor->ep_api_version);
|
||||
break;
|
||||
}
|
||||
|
||||
void (*subghz_gps_init)(SubGhzGPS* subghz_gps, uint32_t baudrate) =
|
||||
app_descriptor->entry_point;
|
||||
|
||||
SubGhzGPS* subghz_gps = malloc(sizeof(SubGhzGPS));
|
||||
subghz_gps->plugin_app = plugin_app;
|
||||
subghz_gps_init(subghz_gps, baudrate);
|
||||
return subghz_gps;
|
||||
|
||||
} while(false);
|
||||
flipper_application_free(plugin_app);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void subghz_gps_plugin_deinit(SubGhzGPS* subghz_gps) {
|
||||
subghz_gps->deinit(subghz_gps);
|
||||
flipper_application_free(subghz_gps->plugin_app);
|
||||
free(subghz_gps);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
@@ -158,18 +158,14 @@ void subghz_txrx_get_frequency_and_modulation(
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_txrx_get_latitude_and_longitude(
|
||||
SubGhzTxRx* instance,
|
||||
FuriString* latitude,
|
||||
FuriString* longitude) {
|
||||
float subghz_txrx_get_latitude(SubGhzTxRx* instance) {
|
||||
furi_assert(instance);
|
||||
SubGhzRadioPreset* preset = instance->preset;
|
||||
if(latitude != NULL) {
|
||||
furi_string_printf(latitude, "%f", (double)preset->latitude);
|
||||
}
|
||||
if(longitude != NULL) {
|
||||
furi_string_printf(longitude, "%f", (double)preset->longitude);
|
||||
}
|
||||
return instance->preset->latitude;
|
||||
}
|
||||
|
||||
float subghz_txrx_get_longitude(SubGhzTxRx* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->preset->longitude;
|
||||
}
|
||||
|
||||
static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) {
|
||||
|
||||
@@ -92,16 +92,20 @@ void subghz_txrx_get_frequency_and_modulation(
|
||||
bool long_name);
|
||||
|
||||
/**
|
||||
* Get string latitude and longitude
|
||||
*
|
||||
* Get latitude value
|
||||
*
|
||||
* @param instance Pointer to a SubGhzTxRx
|
||||
* @param latitude Pointer to a string latitude
|
||||
* @param longitude Pointer to a string longitude
|
||||
* @return latitude
|
||||
*/
|
||||
void subghz_txrx_get_latitude_and_longitude(
|
||||
SubGhzTxRx* instance,
|
||||
FuriString* latitude,
|
||||
FuriString* longitude);
|
||||
float subghz_txrx_get_latitude(SubGhzTxRx* instance);
|
||||
|
||||
/**
|
||||
* Get longitude value
|
||||
*
|
||||
* @param instance Pointer to a SubGhzTxRx
|
||||
* @return longitude
|
||||
*/
|
||||
float subghz_txrx_get_longitude(SubGhzTxRx* instance);
|
||||
|
||||
/**
|
||||
* Start TX CC1101
|
||||
|
||||
@@ -23,5 +23,4 @@ ADD_SCENE(subghz, decode_raw, DecodeRAW)
|
||||
ADD_SCENE(subghz, delete_raw, DeleteRAW)
|
||||
ADD_SCENE(subghz, need_saving, NeedSaving)
|
||||
ADD_SCENE(subghz, rpc, Rpc)
|
||||
ADD_SCENE(subghz, show_gps, ShowGps)
|
||||
ADD_SCENE(subghz, saved_show_gps, SavedShowGps)
|
||||
ADD_SCENE(subghz, show_gps, ShowGps)
|
||||
@@ -9,7 +9,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
|
||||
if(!subghz_history_get_text_space_left(
|
||||
subghz->history,
|
||||
history_stat_str,
|
||||
subghz->gps->satellites,
|
||||
subghz->gps ? subghz->gps->satellites : 0,
|
||||
subghz->last_settings->delete_old_signals)) {
|
||||
FuriString* frequency_str = furi_string_alloc();
|
||||
FuriString* modulation_str = furi_string_alloc();
|
||||
@@ -57,8 +57,13 @@ static void subghz_scene_add_to_history_callback(
|
||||
FuriString* item_time = furi_string_alloc();
|
||||
uint16_t idx = subghz_history_get_item(subghz->history);
|
||||
SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx);
|
||||
preset.latitude = subghz->gps->latitude;
|
||||
preset.longitude = subghz->gps->longitude;
|
||||
if(subghz->gps) {
|
||||
preset.latitude = subghz->gps->latitude;
|
||||
preset.longitude = subghz->gps->longitude;
|
||||
} else {
|
||||
preset.latitude = 0;
|
||||
preset.longitude = 0;
|
||||
}
|
||||
|
||||
if(subghz->last_settings->delete_old_signals && subghz_history_full(subghz->history)) {
|
||||
subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver);
|
||||
|
||||
@@ -154,11 +154,17 @@ static void subghz_scene_receiver_config_set_gps(VariableItem* item) {
|
||||
subghz_last_settings_save(subghz->last_settings);
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
subghz_gps_stop(subghz->gps);
|
||||
subghz_gps_set_baudrate(subghz->gps, subghz->last_settings->gps_baudrate);
|
||||
subghz_gps_start(subghz->gps);
|
||||
if(subghz->gps) {
|
||||
furi_hal_serial_set_br(
|
||||
subghz->gps->serial_handle, subghz->last_settings->gps_baudrate);
|
||||
} else {
|
||||
subghz->gps = subghz_gps_plugin_init(subghz->last_settings->gps_baudrate);
|
||||
}
|
||||
} else {
|
||||
subghz_gps_stop(subghz->gps);
|
||||
if(subghz->gps) {
|
||||
subghz_gps_plugin_deinit(subghz->gps);
|
||||
subghz->gps = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
|
||||
if(!subghz_history_get_text_space_left(
|
||||
subghz->history,
|
||||
history_stat_str,
|
||||
subghz->gps->satellites,
|
||||
subghz->gps ? subghz->gps->satellites : 0,
|
||||
subghz->last_settings->delete_old_signals)) {
|
||||
FuriString* frequency_str = furi_string_alloc();
|
||||
FuriString* modulation_str = furi_string_alloc();
|
||||
@@ -131,8 +131,13 @@ static void subghz_scene_add_to_history_callback(
|
||||
uint16_t idx = subghz_history_get_item(history);
|
||||
|
||||
SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx);
|
||||
preset.latitude = subghz->gps->latitude;
|
||||
preset.longitude = subghz->gps->longitude;
|
||||
if(subghz->gps) {
|
||||
preset.latitude = subghz->gps->latitude;
|
||||
preset.longitude = subghz->gps->longitude;
|
||||
} else {
|
||||
preset.latitude = 0;
|
||||
preset.longitude = 0;
|
||||
}
|
||||
|
||||
if(subghz->last_settings->delete_old_signals && subghz_history_full(subghz->history)) {
|
||||
subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver);
|
||||
@@ -484,7 +489,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(
|
||||
subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx));
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
DateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
if((datetime.second - subghz->gps->fix_second) > 15) {
|
||||
@@ -506,7 +511,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
switch(subghz->state_notifications) {
|
||||
case SubGhzNotificationStateRx:
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
if(subghz->gps->satellites > 0) {
|
||||
notification_message(subghz->notifications, &sequence_blink_green_10);
|
||||
} else {
|
||||
|
||||
@@ -17,9 +17,7 @@ void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, v
|
||||
} else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoSave);
|
||||
} else if(
|
||||
(result == GuiButtonTypeLeft) && (type == InputTypeShort) &&
|
||||
subghz->last_settings->gps_baudrate != 0) {
|
||||
} else if((result == GuiButtonTypeLeft) && (type == InputTypeShort) && subghz->gps) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneReceiverInfoSats);
|
||||
}
|
||||
@@ -81,7 +79,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text));
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
widget_add_button_element(
|
||||
subghz->widget,
|
||||
GuiButtonTypeLeft,
|
||||
@@ -189,7 +187,8 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubGhzCustomEventSceneReceiverInfoSats) {
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneShowGps, false);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowGps);
|
||||
return true;
|
||||
} else {
|
||||
@@ -205,7 +204,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
notification_message(subghz->notifications, &sequence_blink_magenta_10);
|
||||
break;
|
||||
case SubGhzNotificationStateRx:
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
if(subghz->gps->satellites > 0) {
|
||||
notification_message(subghz->notifications, &sequence_blink_green_10);
|
||||
} else {
|
||||
|
||||
@@ -35,13 +35,8 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
subghz_scene_saved_menu_submenu_callback,
|
||||
subghz);
|
||||
|
||||
FuriString* lat_str = furi_string_alloc();
|
||||
FuriString* lon_str = furi_string_alloc();
|
||||
|
||||
subghz_txrx_get_latitude_and_longitude(subghz->txrx, lat_str, lon_str);
|
||||
|
||||
if(strcmp(furi_string_get_cstr(lat_str), "nan") != 0 &&
|
||||
strcmp(furi_string_get_cstr(lon_str), "nan") != 0) {
|
||||
if(!isnanf(subghz_txrx_get_latitude(subghz->txrx)) &&
|
||||
!isnanf(subghz_txrx_get_longitude(subghz->txrx))) {
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Geographic info",
|
||||
@@ -50,9 +45,6 @@ void subghz_scene_saved_menu_on_enter(void* context) {
|
||||
subghz);
|
||||
}
|
||||
|
||||
furi_string_free(lon_str);
|
||||
furi_string_free(lat_str);
|
||||
|
||||
submenu_set_selected_item(
|
||||
subghz->submenu,
|
||||
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSavedMenu));
|
||||
@@ -82,7 +74,8 @@ bool subghz_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
} else if(event.event == SubmenuIndexGeo) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneSavedMenu, SubmenuIndexGeo);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedShowGps);
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneShowGps, true);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowGps);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
#include "../subghz_i.h"
|
||||
#include "../helpers/subghz_custom_event.h"
|
||||
|
||||
void subghz_scene_saved_show_gps_draw_satellites(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
FuriString* text_str = furi_string_alloc();
|
||||
FuriString* lat_str = furi_string_alloc();
|
||||
FuriString* lon_str = furi_string_alloc();
|
||||
|
||||
subghz_txrx_get_latitude_and_longitude(subghz->txrx, lat_str, lon_str);
|
||||
|
||||
DateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
if((datetime.second - subghz->gps->fix_second) > 15) {
|
||||
subghz->gps->latitude = NAN;
|
||||
subghz->gps->longitude = NAN;
|
||||
subghz->gps->satellites = 0;
|
||||
subghz->gps->fix_hour = 0;
|
||||
subghz->gps->fix_minute = 0;
|
||||
subghz->gps->fix_second = 0;
|
||||
}
|
||||
|
||||
double latitude = atof(furi_string_get_cstr(lat_str));
|
||||
double longitude = atof(furi_string_get_cstr(lon_str));
|
||||
|
||||
double distance = subghz_gps_calc_distance(
|
||||
latitude, longitude, (double)subghz->gps->latitude, (double)subghz->gps->longitude);
|
||||
|
||||
float angle = subghz_gps_calc_angle(
|
||||
latitude, longitude, (double)subghz->gps->latitude, (double)subghz->gps->longitude);
|
||||
|
||||
char* angle_str = "?";
|
||||
if(angle > -22.5 && angle <= 22.5) {
|
||||
angle_str = "E";
|
||||
} else if(angle > 22.5 && angle <= 67.5) {
|
||||
angle_str = "NE";
|
||||
} else if(angle > 67.5 && angle <= 112.5) {
|
||||
angle_str = "N";
|
||||
} else if(angle > 112.5 && angle <= 157.5) {
|
||||
angle_str = "NW";
|
||||
} else if(angle < -22.5 && angle >= -67.5) {
|
||||
angle_str = "SE";
|
||||
} else if(angle < -67.5 && angle >= -112.5) {
|
||||
angle_str = "S";
|
||||
} else if(angle < -112.5 && angle >= -157.5) {
|
||||
angle_str = "SW";
|
||||
} else if(angle < -157.5 || angle >= 157.5) {
|
||||
angle_str = "W";
|
||||
}
|
||||
|
||||
furi_string_printf(
|
||||
text_str,
|
||||
"Captured at: %f,\r\n%f\r\n\r\nRealtime: Sats: %d\r\nDistance: %.2f%s Dir: %s\r\nGPS time: %02d:%02d:%02d UTC",
|
||||
latitude,
|
||||
longitude,
|
||||
subghz->gps->satellites,
|
||||
subghz->gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0,
|
||||
distance > 1 ? "km" : "m",
|
||||
angle_str,
|
||||
subghz->gps->fix_hour,
|
||||
subghz->gps->fix_minute,
|
||||
subghz->gps->fix_second);
|
||||
|
||||
widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text_str));
|
||||
|
||||
furi_string_free(text_str);
|
||||
furi_string_free(lat_str);
|
||||
furi_string_free(lon_str);
|
||||
}
|
||||
|
||||
void subghz_scene_saved_show_gps_refresh_screen(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
widget_reset(subghz->widget);
|
||||
subghz_scene_saved_show_gps_draw_satellites(subghz);
|
||||
}
|
||||
|
||||
void subghz_scene_saved_show_gps_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
subghz_scene_saved_show_gps_draw_satellites(subghz);
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
subghz->gps->timer = furi_timer_alloc(
|
||||
subghz_scene_saved_show_gps_refresh_screen, FuriTimerTypePeriodic, subghz);
|
||||
furi_timer_start(subghz->gps->timer, 1000);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
||||
}
|
||||
|
||||
bool subghz_scene_saved_show_gps_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_scene_saved_show_gps_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
furi_timer_stop(subghz->gps->timer);
|
||||
furi_timer_free(subghz->gps->timer);
|
||||
}
|
||||
|
||||
widget_reset(subghz->widget);
|
||||
}
|
||||
@@ -4,9 +4,6 @@
|
||||
void subghz_scene_show_gps_draw_satellites(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
FuriString* text = furi_string_alloc();
|
||||
FuriString* time_text = furi_string_alloc();
|
||||
|
||||
DateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
if((datetime.second - subghz->gps->fix_second) > 15) {
|
||||
@@ -18,81 +15,20 @@ void subghz_scene_show_gps_draw_satellites(void* context) {
|
||||
subghz->gps->fix_second = 0;
|
||||
}
|
||||
|
||||
subghz_history_get_time_item_menu(subghz->history, time_text, subghz->idx_menu_chosen);
|
||||
|
||||
double distance = subghz_gps_calc_distance(
|
||||
(double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen),
|
||||
(double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen),
|
||||
(double)subghz->gps->latitude,
|
||||
(double)subghz->gps->longitude);
|
||||
|
||||
float angle = subghz_gps_calc_angle(
|
||||
(double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen),
|
||||
(double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen),
|
||||
(double)subghz->gps->latitude,
|
||||
(double)subghz->gps->longitude);
|
||||
|
||||
char* angle_str = "?";
|
||||
if(angle > -22.5 && angle <= 22.5) {
|
||||
angle_str = "E";
|
||||
} else if(angle > 22.5 && angle <= 67.5) {
|
||||
angle_str = "NE";
|
||||
} else if(angle > 67.5 && angle <= 112.5) {
|
||||
angle_str = "N";
|
||||
} else if(angle > 112.5 && angle <= 157.5) {
|
||||
angle_str = "NW";
|
||||
} else if(angle < -22.5 && angle >= -67.5) {
|
||||
angle_str = "SE";
|
||||
} else if(angle < -67.5 && angle >= -112.5) {
|
||||
angle_str = "S";
|
||||
} else if(angle < -112.5 && angle >= -157.5) {
|
||||
angle_str = "SW";
|
||||
} else if(angle < -157.5 || angle >= 157.5) {
|
||||
angle_str = "W";
|
||||
}
|
||||
|
||||
FuriString* lat_str = furi_string_alloc();
|
||||
FuriString* lon_str = furi_string_alloc();
|
||||
|
||||
if(isnan(subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen))) {
|
||||
furi_string_printf(lat_str, "N/A");
|
||||
float latitude, longitude;
|
||||
// Get from saved file or from history
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowGps)) {
|
||||
latitude = subghz_txrx_get_latitude(subghz->txrx);
|
||||
longitude = subghz_txrx_get_longitude(subghz->txrx);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
lat_str,
|
||||
"%f",
|
||||
(double)subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen));
|
||||
latitude = subghz_history_get_latitude(subghz->history, subghz->idx_menu_chosen);
|
||||
longitude = subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen);
|
||||
}
|
||||
|
||||
if(isnan(subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen))) {
|
||||
furi_string_printf(lon_str, "N/A");
|
||||
} else {
|
||||
furi_string_printf(
|
||||
lon_str,
|
||||
"%f",
|
||||
(double)subghz_history_get_longitude(subghz->history, subghz->idx_menu_chosen));
|
||||
}
|
||||
|
||||
furi_string_printf(
|
||||
text,
|
||||
"Captured at: %s,\r\n%s Time: %s\r\n\r\nRealtime: Sats: %d\r\nDistance: %.2f%s Dir: %s\r\nGPS time: %02d:%02d:%02d UTC",
|
||||
furi_string_get_cstr(lat_str),
|
||||
furi_string_get_cstr(lon_str),
|
||||
furi_string_get_cstr(time_text),
|
||||
subghz->gps->satellites,
|
||||
subghz->gps->satellites > 0 ? distance > 1 ? distance : distance * 1000 : 0,
|
||||
distance > 1 ? "km" : "m",
|
||||
angle_str,
|
||||
subghz->gps->fix_hour,
|
||||
subghz->gps->fix_minute,
|
||||
subghz->gps->fix_second);
|
||||
|
||||
widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text));
|
||||
|
||||
furi_string_free(lat_str);
|
||||
furi_string_free(lon_str);
|
||||
|
||||
furi_string_free(text);
|
||||
furi_string_free(time_text);
|
||||
FuriString* text_str = furi_string_alloc();
|
||||
subghz->gps->get_descr(subghz->gps, text_str, latitude, longitude);
|
||||
widget_add_text_scroll_element(subghz->widget, 0, 0, 128, 64, furi_string_get_cstr(text_str));
|
||||
furi_string_free(text_str);
|
||||
}
|
||||
|
||||
void subghz_scene_show_gps_refresh_screen(void* context) {
|
||||
@@ -106,18 +42,24 @@ void subghz_scene_show_gps_on_enter(void* context) {
|
||||
|
||||
subghz_scene_show_gps_draw_satellites(subghz);
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
subghz->gps->timer =
|
||||
furi_timer_alloc(subghz_scene_show_gps_refresh_screen, FuriTimerTypePeriodic, subghz);
|
||||
furi_timer_start(subghz->gps->timer, 1000);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
|
||||
}
|
||||
|
||||
bool subghz_scene_show_gps_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// No rx blink if opened from saved file
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowGps)) return false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->state_notifications == SubGhzNotificationStateRx) {
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
if(subghz->gps->satellites > 0) {
|
||||
notification_message(subghz->notifications, &sequence_blink_green_10);
|
||||
} else {
|
||||
@@ -134,7 +76,7 @@ bool subghz_scene_show_gps_on_event(void* context, SceneManagerEvent event) {
|
||||
void subghz_scene_show_gps_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
if(subghz->gps) {
|
||||
furi_timer_stop(subghz->gps->timer);
|
||||
furi_timer_free(subghz->gps->timer);
|
||||
}
|
||||
|
||||
@@ -251,10 +251,8 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
|
||||
//Init Error_str
|
||||
subghz->error_str = furi_string_alloc();
|
||||
|
||||
subghz->gps = subghz_gps_init();
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
subghz_gps_set_baudrate(subghz->gps, subghz->last_settings->gps_baudrate);
|
||||
subghz_gps_start(subghz->gps);
|
||||
subghz->gps = subghz_gps_plugin_init(subghz->last_settings->gps_baudrate);
|
||||
}
|
||||
|
||||
return subghz;
|
||||
@@ -352,10 +350,9 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
|
||||
furi_string_free(subghz->file_path_tmp);
|
||||
|
||||
// GPS
|
||||
if(subghz->last_settings->gps_baudrate != 0) {
|
||||
subghz_gps_stop(subghz->gps);
|
||||
if(subghz->gps) {
|
||||
subghz_gps_plugin_deinit(subghz->gps);
|
||||
}
|
||||
subghz_gps_deinit(subghz->gps);
|
||||
|
||||
subghz_last_settings_free(subghz->last_settings);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user