merge port p2

This commit is contained in:
MX 2023-11-08 11:08:17 +04:00
parent 19f524ec43
commit 9ed23799eb
No known key found for this signature in database
GPG key ID: 7CCC66B7DBDD1C83
5 changed files with 229 additions and 60 deletions

View file

@ -28,6 +28,8 @@ typedef struct {
GapConfig* config;
GapConnectionParams connection_params;
GapState state;
int8_t conn_rssi;
uint32_t time_rssi_sample;
FuriMutex* state_mutex;
GapEventCallback on_event_cb;
void* context;
@ -56,6 +58,19 @@ static Gap* gap = NULL;
static void gap_advertise_start(GapState new_state);
static int32_t gap_app(void* context);
/** function for updating rssi informations in global Gap object
*
*/
static inline void fetch_rssi() {
uint8_t ret_rssi = 127;
if(hci_read_rssi(gap->service.connection_handle, &ret_rssi) == BLE_STATUS_SUCCESS) {
gap->conn_rssi = (int8_t)ret_rssi;
gap->time_rssi_sample = furi_get_tick();
return;
}
FURI_LOG_D(TAG, "Failed to read RSSI");
}
static void gap_verify_connection_parameters(Gap* gap) {
furi_assert(gap);
@ -128,6 +143,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
FURI_LOG_I(TAG, "Connection parameters event complete");
gap_verify_connection_parameters(gap);
// Save rssi for current connection
fetch_rssi();
break;
}
@ -162,6 +180,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->service.connection_handle = event->Connection_Handle;
gap_verify_connection_parameters(gap);
// Save rssi for current connection
fetch_rssi();
// Start pairing by sending security request
aci_gap_slave_security_req(event->Connection_Handle);
} break;
@ -242,6 +263,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
pairing_complete->Status);
aci_gap_terminate(gap->service.connection_handle, 5);
} else {
// Save RSSI
fetch_rssi();
FURI_LOG_I(TAG, "Pairing complete");
GapEvent event = {.type = GapEventTypeConnected};
gap->on_event_cb(event, gap->context); //-V595
@ -310,7 +334,7 @@ static void gap_init_svc(Gap* gap) {
// Initialize GATT interface
aci_gatt_init();
// Initialize GAP interface
// Skip fist symbol AD_TYPE_COMPLETE_LOCAL_NAME
// Skip first symbol AD_TYPE_COMPLETE_LOCAL_NAME
char* name = gap->service.adv_name + 1;
aci_gap_init(
GAP_PERIPHERAL_ROLE,
@ -346,21 +370,34 @@ static void gap_init_svc(Gap* gap) {
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
// Set I/O capability
bool keypress_supported = false;
// New things below
uint8_t conf_mitm = CFG_MITM_PROTECTION;
uint8_t conf_used_fixed_pin = CFG_USED_FIXED_PIN;
bool conf_bonding = gap->config->bonding_mode;
if(gap->config->pairing_method == GapPairingPinCodeShow) {
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
} else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) {
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
keypress_supported = true;
} else if(gap->config->pairing_method == GapPairingNone) {
// Just works pairing method (IOS accept it, it seems android and linux doesn't)
conf_mitm = 0;
conf_used_fixed_pin = 0;
conf_bonding = false;
// if just works isn't supported, we want the numeric comparaison method
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
keypress_supported = true;
}
// Setup authentication
aci_gap_set_authentication_requirement(
gap->config->bonding_mode,
CFG_MITM_PROTECTION,
conf_bonding,
conf_mitm,
CFG_SC_SUPPORT,
keypress_supported,
CFG_ENCRYPTION_KEY_SIZE_MIN,
CFG_ENCRYPTION_KEY_SIZE_MAX,
CFG_USED_FIXED_PIN,
conf_used_fixed_pin, // 0x0 for no pin
0,
CFG_IDENTITY_ADDRESS);
// Configure whitelist
@ -463,7 +500,7 @@ void gap_stop_advertising() {
furi_mutex_release(gap->state_mutex);
}
static void gap_advetise_timer_callback(void* context) {
static void gap_advertise_timer_callback(void* context) {
UNUSED(context);
GapCommand command = GapCommandAdvLowPower;
furi_check(furi_message_queue_put(gap->command_queue, &command, 0) == FuriStatusOk);
@ -477,7 +514,7 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
gap = malloc(sizeof(Gap));
gap->config = config;
// Create advertising timer
gap->advertise_timer = furi_timer_alloc(gap_advetise_timer_callback, FuriTimerTypeOnce, NULL);
gap->advertise_timer = furi_timer_alloc(gap_advertise_timer_callback, FuriTimerTypeOnce, NULL);
// Initialization of GATT & GAP layer
gap->service.adv_name = config->adv_name;
gap_init_svc(gap);
@ -489,6 +526,9 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
gap->service.connection_handle = 0xFFFF;
gap->enable_adv = true;
gap->conn_rssi = 127;
gap->time_rssi_sample = 0;
// Thread configuration
gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap);
furi_thread_start(gap->thread);
@ -508,6 +548,17 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
return true;
}
// Get RSSI
uint32_t gap_get_remote_conn_rssi(int8_t* rssi) {
if(gap && gap->state == GapStateConnected) {
fetch_rssi();
*rssi = gap->conn_rssi;
if(gap->time_rssi_sample) return furi_get_tick() - gap->time_rssi_sample;
}
return 0;
}
GapState gap_get_state() {
GapState state;
if(gap) {

View file

@ -9,12 +9,6 @@
#include <furi.h>
#include <math.h>
// #define INFRARED_TX_DEBUG
#if defined INFRARED_TX_DEBUG
#define gpio_infrared_tx gpio_ext_pa7
#endif
#define INFRARED_TIM_TX_DMA_BUFFER_SIZE 200
#define INFRARED_POLARITY_SHIFT 1
@ -84,6 +78,7 @@ typedef enum {
static volatile InfraredState furi_hal_infrared_state = InfraredStateIdle;
static InfraredTimTx infrared_tim_tx;
static InfraredTimRx infrared_tim_rx;
static bool infrared_external_output;
static void furi_hal_infrared_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_shift);
static void furi_hal_infrared_async_tx_free_resources(void);
@ -94,6 +89,14 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void);
static void furi_hal_infrared_tx_dma_polarity_isr();
static void furi_hal_infrared_tx_dma_isr();
void furi_hal_infrared_set_debug_out(bool enable) {
infrared_external_output = enable;
}
bool furi_hal_infrared_get_debug_out_status(void) {
return infrared_external_output;
}
static void furi_hal_infrared_tim_rx_isr() {
static uint32_t previous_captured_ch2 = 0;
@ -348,9 +351,10 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
LL_TIM_SetAutoReload(
INFRARED_DMA_TIMER,
__LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(INFRARED_DMA_TIMER), freq));
#if defined INFRARED_TX_DEBUG
if(infrared_external_output) {
LL_TIM_OC_SetCompareCH1(
INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
INFRARED_DMA_TIMER,
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
/* LL_TIM_OCMODE_PWM2 set by DMA */
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
@ -358,9 +362,10 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N);
LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER);
#else
} else {
LL_TIM_OC_SetCompareCH3(
INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
INFRARED_DMA_TIMER,
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
/* LL_TIM_OCMODE_PWM2 set by DMA */
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE);
@ -368,7 +373,7 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N);
LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER);
#endif
}
LL_TIM_DisableMasterSlaveMode(INFRARED_DMA_TIMER);
LL_TIM_EnableAllOutputs(INFRARED_DMA_TIMER);
LL_TIM_DisableIT_UPDATE(INFRARED_DMA_TIMER);
@ -377,11 +382,11 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
LL_DMA_InitTypeDef dma_config = {0};
#if defined INFRARED_TX_DEBUG
if(infrared_external_output) {
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1);
#else
} else {
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2);
#endif
}
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
dma_config.Mode = LL_DMA_MODE_NORMAL;
@ -575,7 +580,11 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
(furi_hal_infrared_state == InfraredStateIdle) ||
(furi_hal_infrared_state == InfraredStateAsyncTxStopped));
if(infrared_external_output) {
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
} else {
furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
}
furi_hal_interrupt_set_isr(INFRARED_DMA_CH1_IRQ, NULL, NULL);
furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, NULL, NULL);
@ -636,10 +645,22 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
furi_delay_us(5);
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* DMA -> TIMx_RCR */
furi_delay_us(5);
if(infrared_external_output) {
LL_GPIO_ResetOutputPin(
gpio_infrared_tx.port, gpio_infrared_tx.pin); /* when disable it prevents false pulse */
gpio_ext_pa7.port, gpio_ext_pa7.pin); /* when disable it prevents false pulse */
furi_hal_gpio_init_ex(
&gpio_infrared_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
&gpio_ext_pa7, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
} else {
LL_GPIO_ResetOutputPin(
gpio_infrared_tx.port,
gpio_infrared_tx.pin); /* when disable it prevents false pulse */
furi_hal_gpio_init_ex(
&gpio_infrared_tx,
GpioModeAltFunctionPushPull,
GpioPullUp,
GpioSpeedHigh,
GpioAltFn1TIM1);
}
FURI_CRITICAL_ENTER();
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */

View file

@ -1,6 +1,6 @@
#include <furi_hal_subghz.h>
#include <lib/subghz/devices/cc1101_configs.h>
#include <furi_hal_region.h>
#include <furi_hal_version.h>
#include <furi_hal_rtc.h>
#include <furi_hal_spi.h>
@ -51,14 +51,41 @@ typedef struct {
volatile SubGhzState state;
volatile SubGhzRegulation regulation;
const GpioPin* async_mirror_pin;
int8_t rolling_counter_mult;
bool ext_power_amp : 1;
bool dangerous_frequency_i : 1;
} FuriHalSubGhz;
volatile FuriHalSubGhz furi_hal_subghz = {
.state = SubGhzStateInit,
.regulation = SubGhzRegulationTxRx,
.async_mirror_pin = NULL,
.rolling_counter_mult = 1,
.ext_power_amp = false,
.dangerous_frequency_i = false,
};
int8_t furi_hal_subghz_get_rolling_counter_mult(void) {
return furi_hal_subghz.rolling_counter_mult;
}
void furi_hal_subghz_set_rolling_counter_mult(int8_t mult) {
furi_hal_subghz.rolling_counter_mult = mult;
}
void furi_hal_subghz_set_dangerous_frequency(bool state_i) {
furi_hal_subghz.dangerous_frequency_i = state_i;
}
void furi_hal_subghz_set_ext_power_amp(bool enabled) {
furi_hal_subghz.ext_power_amp = enabled;
}
bool furi_hal_subghz_get_ext_power_amp() {
return furi_hal_subghz.ext_power_amp;
}
void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) {
furi_hal_subghz.async_mirror_pin = pin;
}
@ -207,6 +234,7 @@ bool furi_hal_subghz_rx_pipe_not_empty() {
cc1101_read_reg(
&furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status);
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
// TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly
if(status->NUM_RXBYTES > 0) {
return true;
} else {
@ -291,10 +319,15 @@ uint8_t furi_hal_subghz_get_lqi() {
return data[0] & 0x7F;
}
/*
Modified by @tkerby & MX to the full YARD Stick One extended range of 281-361 MHz, 378-481 MHz, and 749-962 MHz.
These changes are at your own risk. The PLL may not lock and FZ devs have warned of possible damage!
*/
bool furi_hal_subghz_is_frequency_valid(uint32_t value) {
if(!(value >= 299999755 && value <= 348000335) &&
!(value >= 386999938 && value <= 464000000) &&
!(value >= 778999847 && value <= 928000000)) {
if(!(value >= 281000000 && value <= 361000000) &&
!(value >= 378000000 && value <= 481000000) &&
!(value >= 749000000 && value <= 962000000)) {
return false;
}
@ -302,12 +335,13 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value) {
}
uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) {
// Set these values to the extended frequency range only. They dont define if you can transmit but do select the correct RF path
value = furi_hal_subghz_set_frequency(value);
if(value >= 299999755 && value <= 348000335) {
if(value >= 281000000 && value <= 361000000) {
furi_hal_subghz_set_path(FuriHalSubGhzPath315);
} else if(value >= 386999938 && value <= 464000000) {
} else if(value >= 378000000 && value <= 481000000) {
furi_hal_subghz_set_path(FuriHalSubGhzPath433);
} else if(value >= 778999847 && value <= 928000000) {
} else if(value >= 749000000 && value <= 962000000) {
furi_hal_subghz_set_path(FuriHalSubGhzPath868);
} else {
furi_crash("SubGhz: Incorrect frequency during set.");
@ -315,8 +349,27 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) {
return value;
}
bool furi_hal_subghz_is_tx_allowed(uint32_t value) {
bool allow_extended_for_int = furi_hal_subghz.dangerous_frequency_i;
if(!(allow_extended_for_int) &&
!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
!(value >= 778999847 && value <= 928000000)) {
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
return false;
} else if(
(allow_extended_for_int) && //
!furi_hal_subghz_is_frequency_valid(value)) {
FURI_LOG_I(TAG, "Frequency blocked - outside dangerous range");
return false;
}
return true;
}
uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
if(furi_hal_region_is_frequency_allowed(value)) {
if(furi_hal_subghz_is_tx_allowed(value)) {
furi_hal_subghz.regulation = SubGhzRegulationTxRx;
} else {
furi_hal_subghz.regulation = SubGhzRegulationOnlyRx;
@ -431,7 +484,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
TIM_InitStruct.Prescaler = 64 - 1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter
// Clock division for capture filter
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
LL_TIM_Init(TIM2, &TIM_InitStruct);
// Timer: advanced
@ -695,6 +749,11 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
// Start debug
if(furi_hal_subghz_start_debug()) {
const GpioPin* gpio = furi_hal_subghz.async_mirror_pin;
// //Preparing bit mask
// //Debug pin is may be only PORTB! (PB0, PB1, .., PB15)
// furi_hal_subghz_debug_gpio_buff[0] = 0;
// furi_hal_subghz_debug_gpio_buff[1] = 0;
furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
furi_hal_subghz_debug_gpio_buff[1] = gpio->pin;

View file

@ -0,0 +1,3 @@
#pragma once
void furi_hal_subghz_set_dangerous_frequency(bool state_i);

View file

@ -90,7 +90,7 @@ typedef struct {
static FuriHalVersion furi_hal_version = {0};
static void furi_hal_version_set_name(const char* name) {
void furi_hal_version_set_name(const char* name) {
if(name != NULL) {
strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH);
snprintf(
@ -106,8 +106,16 @@ static void furi_hal_version_set_name(const char* name) {
// BLE Mac address
uint32_t udn = LL_FLASH_GetUDN();
if(version_get_custom_name(NULL) != NULL) {
udn = *((uint32_t*)version_get_custom_name(NULL));
}
uint32_t company_id = LL_FLASH_GetSTCompanyID();
uint32_t device_id = LL_FLASH_GetDeviceID();
// uint32_t device_id = LL_FLASH_GetDeviceID();
// Some flippers return 0x27 (flippers with chip revision 2003 6495) instead of 0x26 (flippers with chip revision 2001 6495)
// Mobile apps expects it to return 0x26
// Hardcoded here temporarily until mobile apps is updated to handle 0x27
uint32_t device_id = 0x26;
furi_hal_version.ble_mac[0] = (uint8_t)(udn & 0x000000FF);
furi_hal_version.ble_mac[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
furi_hal_version.ble_mac[2] = (uint8_t)((udn & 0x00FF0000) >> 16);
@ -129,8 +137,12 @@ static void furi_hal_version_load_otp_v0() {
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
if(version_get_custom_name(NULL) != NULL) {
furi_hal_version_set_name(version_get_custom_name(NULL));
} else {
furi_hal_version_set_name(otp->name);
}
}
static void furi_hal_version_load_otp_v1() {
const FuriHalVersionOTPv1* otp = (FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS;
@ -143,8 +155,12 @@ static void furi_hal_version_load_otp_v1() {
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
if(version_get_custom_name(NULL) != NULL) {
furi_hal_version_set_name(version_get_custom_name(NULL));
} else {
furi_hal_version_set_name(otp->name);
}
}
static void furi_hal_version_load_otp_v2() {
const FuriHalVersionOTPv2* otp = (FuriHalVersionOTPv2*)FURI_HAL_VERSION_OTP_ADDRESS;
@ -163,7 +179,11 @@ static void furi_hal_version_load_otp_v2() {
if(otp->board_color != 0xFF) {
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
if(version_get_custom_name(NULL) != NULL) {
furi_hal_version_set_name(version_get_custom_name(NULL));
} else {
furi_hal_version_set_name(otp->name);
}
} else {
furi_hal_version.board_color = 0;
furi_hal_version.board_region = 0;
@ -239,11 +259,19 @@ uint8_t furi_hal_version_get_hw_connect() {
}
FuriHalVersionRegion furi_hal_version_get_hw_region() {
return FuriHalVersionRegionUnknown;
}
FuriHalVersionRegion furi_hal_version_get_hw_region_otp() {
return furi_hal_version.board_region;
}
const char* furi_hal_version_get_hw_region_name() {
switch(furi_hal_version_get_hw_region()) {
return "R00";
}
const char* furi_hal_version_get_hw_region_name_otp() {
switch(furi_hal_version_get_hw_region_otp()) {
case FuriHalVersionRegionUnknown:
return "R00";
case FuriHalVersionRegionEuRu:
@ -290,6 +318,13 @@ size_t furi_hal_version_uid_size() {
return 64 / 8;
}
const uint8_t* furi_hal_version_uid() {
const uint8_t* furi_hal_version_uid_default() {
return (const uint8_t*)UID64_BASE;
}
const uint8_t* furi_hal_version_uid() {
if(version_get_custom_name(NULL) != NULL) {
return (const uint8_t*)&(*((uint32_t*)version_get_custom_name(NULL)));
}
return (const uint8_t*)UID64_BASE;
}