[FL-580] Prepare BLE for certification (#376)

* api-hal-bt: separate bt init to core init and app start

* bt: add continuous TX and RX tests

* bt: finish rx test on Back button click

* api-hal-bt: check core 2 started, same f4 and f5 implementation

* bt: refactoring, move hopping test logic to main thread

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich 2021-03-11 12:31:07 +03:00 committed by GitHub
parent b920248693
commit 0af6c9882e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 601 additions and 9 deletions

View File

@ -1,13 +1,41 @@
#include "bt_i.h" #include "bt_i.h"
uint32_t bt_view_exit(void* context) {
(void)context;
return VIEW_NONE;
}
void bt_update_statusbar(void* arg) {
furi_assert(arg);
Bt* bt = arg;
BtMessage m = {.type = BtMessageTypeUpdateStatusbar};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
}
void bt_switch_freq(void* arg) {
furi_assert(arg);
Bt* bt = arg;
BtMessage m = {.type = BtMessageTypeStartTestToneTx};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
}
Bt* bt_alloc() { Bt* bt_alloc() {
Bt* bt = furi_alloc(sizeof(Bt)); Bt* bt = furi_alloc(sizeof(Bt));
bt->message_queue = osMessageQueueNew(8, sizeof(BtMessage), NULL);
bt->update_status_timer = osTimerNew(bt_update_statusbar, osTimerPeriodic, bt, NULL);
osTimerStart(bt->update_status_timer, 4000);
bt->hopping_mode_timer = osTimerNew(bt_switch_freq, osTimerPeriodic, bt, NULL);
bt->cli = furi_record_open("cli"); bt->cli = furi_record_open("cli");
cli_add_command(bt->cli, "bt_info", bt_cli_info, bt); cli_add_command(bt->cli, "bt_info", bt_cli_info, bt);
bt->gui = furi_record_open("gui"); bt->gui = furi_record_open("gui");
bt->menu = furi_record_open("menu"); bt->menu = furi_record_open("menu");
bt->state.type = BtStatusReady;
bt->state.param.channel = BtChannel2402;
bt->state.param.power = BtPower0dB;
bt->state.param.datarate = BtDateRate1M;
bt->statusbar_view_port = view_port_alloc(); bt->statusbar_view_port = view_port_alloc();
view_port_set_width(bt->statusbar_view_port, 5); view_port_set_width(bt->statusbar_view_port, 5);
view_port_draw_callback_set(bt->statusbar_view_port, bt_draw_statusbar_callback, bt); view_port_draw_callback_set(bt->statusbar_view_port, bt_draw_statusbar_callback, bt);
@ -16,9 +44,48 @@ Bt* bt_alloc() {
bt->menu_icon = assets_icons_get(A_Bluetooth_14); bt->menu_icon = assets_icons_get(A_Bluetooth_14);
bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon); bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon);
menu_item_subitem_add(
bt->menu_item, menu_item_alloc_function("Test tone TX", NULL, bt_menu_test_tone_tx, bt));
menu_item_subitem_add(
bt->menu_item,
menu_item_alloc_function("Test packet TX", NULL, bt_menu_test_packet_tx, bt));
menu_item_subitem_add(
bt->menu_item, menu_item_alloc_function("Test tone RX", NULL, bt_menu_test_tone_rx, bt));
menu_item_subitem_add(
bt->menu_item, menu_item_alloc_function("Start app", NULL, bt_menu_start_app, bt));
bt->view_test_tone_tx = view_alloc();
view_set_context(bt->view_test_tone_tx, bt);
view_set_draw_callback(bt->view_test_tone_tx, bt_view_test_tone_tx_draw);
view_allocate_model(
bt->view_test_tone_tx, ViewModelTypeLocking, sizeof(BtViewTestToneTxModel));
view_set_input_callback(bt->view_test_tone_tx, bt_view_test_tone_tx_input);
bt->view_test_packet_tx = view_alloc();
view_set_context(bt->view_test_packet_tx, bt);
view_set_draw_callback(bt->view_test_packet_tx, bt_view_test_packet_tx_draw);
view_allocate_model(
bt->view_test_packet_tx, ViewModelTypeLocking, sizeof(BtViewTestPacketTxModel));
view_set_input_callback(bt->view_test_packet_tx, bt_view_test_packet_tx_input);
bt->view_test_tone_rx = view_alloc();
view_set_context(bt->view_test_tone_rx, bt);
view_set_draw_callback(bt->view_test_tone_rx, bt_view_test_tone_rx_draw);
view_allocate_model(bt->view_test_tone_rx, ViewModelTypeLocking, sizeof(BtViewTestRxModel));
view_set_input_callback(bt->view_test_tone_rx, bt_view_test_tone_rx_input);
bt->view_start_app = view_alloc();
view_set_context(bt->view_start_app, bt);
view_set_draw_callback(bt->view_start_app, bt_view_app_draw);
view_set_previous_callback(bt->view_start_app, bt_view_exit);
bt->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_add_view(bt->view_dispatcher, BtViewTestToneTx, bt->view_test_tone_tx);
view_dispatcher_add_view(bt->view_dispatcher, BtViewTestPacketTx, bt->view_test_packet_tx);
view_dispatcher_add_view(bt->view_dispatcher, BtViewTestToneRx, bt->view_test_tone_rx);
view_dispatcher_add_view(bt->view_dispatcher, BtViewStartApp, bt->view_start_app);
Gui* gui = furi_record_open("gui");
view_dispatcher_attach_to_gui(bt->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
with_value_mutex( with_value_mutex(
bt->menu, (Menu * menu) { menu_item_add(menu, bt->menu_item); }); bt->menu, (Menu * menu) { menu_item_add(menu, bt->menu_item); });
return bt; return bt;
} }
@ -26,6 +93,47 @@ void bt_draw_statusbar_callback(Canvas* canvas, void* context) {
canvas_draw_icon_name(canvas, 0, 0, I_Bluetooth_5x8); canvas_draw_icon_name(canvas, 0, 0, I_Bluetooth_5x8);
} }
void bt_menu_test_tone_tx(void* context) {
furi_assert(context);
Bt* bt = context;
bt->state.type = BtStatusToneTx;
BtMessage message = {
.type = BtMessageTypeStartTestToneTx,
.param.channel = bt->state.param.channel,
.param.power = bt->state.param.power};
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
}
void bt_menu_test_packet_tx(void* context) {
furi_assert(context);
Bt* bt = context;
bt->state.type = BtStatusPacketSetup;
BtMessage message = {
.type = BtMessageTypeSetupTestPacketTx,
.param.channel = bt->state.param.channel,
.param.datarate = bt->state.param.datarate};
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
}
void bt_menu_test_tone_rx(void* context) {
furi_assert(context);
Bt* bt = context;
bt->state.type = BtStatusToneRx;
BtMessage message = {
.type = BtMessageTypeStartTestRx,
.param.channel = bt->state.param.channel,
.param.power = bt->state.param.power};
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
}
void bt_menu_start_app(void* context) {
furi_assert(context);
Bt* bt = context;
bt->state.type = BtStatusStartedApp;
BtMessage message = {.type = BtMessageTypeStartApp};
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
}
void bt_cli_info(string_t args, void* context) { void bt_cli_info(string_t args, void* context) {
string_t buffer; string_t buffer;
string_init(buffer); string_init(buffer);
@ -40,11 +148,81 @@ int32_t bt_task() {
furi_record_create("bt", bt); furi_record_create("bt", bt);
api_hal_bt_init(); api_hal_bt_init();
BtMessage message;
while(1) { while(1) {
view_port_enabled_set(bt->statusbar_view_port, api_hal_bt_is_alive()); furi_check(osMessageQueueGet(bt->message_queue, &message, NULL, osWaitForever) == osOK);
osDelay(1024); if(message.type == BtMessageTypeStartTestToneTx) {
// Start test tx
api_hal_bt_stop_tone_tx();
if(bt->state.type == BtStatusToneTx) {
api_hal_bt_start_tone_tx(message.param.channel, message.param.power);
} else {
bt->state.param.channel =
bt_switch_channel(InputKeyRight, bt->state.param.channel);
bt->state.param.power = BtPower6dB;
api_hal_bt_start_tone_tx(bt->state.param.channel, bt->state.param.power);
}
with_view_model(
bt->view_test_tone_tx, (BtViewTestToneTxModel * model) {
model->type = bt->state.type;
model->channel = bt->state.param.channel;
model->power = bt->state.param.power;
return true;
});
view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestToneTx);
} else if(message.type == BtMessageTypeStopTestToneTx) {
// Stop test tone tx
api_hal_bt_stop_tone_tx();
bt->state.type = BtStatusReady;
} else if(message.type == BtMessageTypeSetupTestPacketTx) {
// Update packet test setup
api_hal_bt_stop_packet_tx();
with_view_model(
bt->view_test_packet_tx, (BtViewTestPacketTxModel * model) {
model->type = bt->state.type;
model->channel = bt->state.param.channel;
model->datarate = bt->state.param.datarate;
return true;
});
view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketTx);
} else if(message.type == BtMessageTypeStartTestPacketTx) {
// Start sending packets
api_hal_bt_start_packet_tx(message.param.channel, message.param.datarate);
with_view_model(
bt->view_test_packet_tx, (BtViewTestPacketTxModel * model) {
model->type = bt->state.type;
model->channel = bt->state.param.channel;
model->datarate = bt->state.param.datarate;
return true;
});
view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketTx);
} else if(message.type == BtMessageTypeStopTestPacketTx) {
// Stop test packet tx
api_hal_bt_stop_packet_tx();
bt->state.type = BtStatusReady;
} else if(message.type == BtMessageTypeStartTestRx) {
// Start test rx
api_hal_bt_start_rx(message.param.channel);
with_view_model(
bt->view_test_tone_rx, (BtViewTestRxModel * model) {
model->channel = bt->state.param.channel;
return true;
});
view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestToneRx);
} else if(message.type == BtMessageTypeStopTestRx) {
// Stop test rx
api_hal_bt_stop_rx();
bt->state.type = BtStatusReady;
} else if(message.type == BtMessageTypeStartApp) {
// Start app
view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewStartApp);
if(api_hal_bt_start_app()) {
bt->state.type = BtStatusStartedApp;
}
} else if(message.type == BtMessageTypeUpdateStatusbar) {
// Update statusbar
view_port_enabled_set(bt->statusbar_view_port, api_hal_bt_is_alive());
}
} }
return 0; return 0;
} }

View File

@ -1 +1,3 @@
#pragma once #pragma once
typedef struct Bt Bt;

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "bt.h" #include "bt.h"
#include "bt_views.h"
#include "bt_types.h"
#include <furi.h> #include <furi.h>
#include <api-hal.h> #include <api-hal.h>
@ -9,11 +11,17 @@
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view_port.h> #include <gui/view_port.h>
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <menu/menu.h> #include <menu/menu.h>
#include <menu/menu_item.h> #include <menu/menu_item.h>
typedef struct { struct Bt {
osMessageQueueId_t message_queue;
BtState state;
osTimerId_t update_status_timer;
osTimerId_t hopping_mode_timer;
Cli* cli; Cli* cli;
Gui* gui; Gui* gui;
ValueMutex* menu; ValueMutex* menu;
@ -22,12 +30,27 @@ typedef struct {
// Menu // Menu
Icon* menu_icon; Icon* menu_icon;
MenuItem* menu_item; MenuItem* menu_item;
} Bt; View* view_test_tone_tx;
View* view_test_packet_tx;
View* view_test_tone_rx;
View* view_start_app;
ViewDispatcher* view_dispatcher;
};
Bt* bt_alloc(); Bt* bt_alloc();
void bt_draw_statusbar_callback(Canvas* canvas, void* context); void bt_draw_statusbar_callback(Canvas* canvas, void* context);
BtTestChannel bt_switch_channel(InputKey key, BtTestChannel inst_chan);
void bt_cli_info(string_t args, void* context); void bt_cli_info(string_t args, void* context);
void bt_draw_statusbar_callback(Canvas* canvas, void* context); void bt_draw_statusbar_callback(Canvas* canvas, void* context);
void bt_menu_test_tone_tx(void* context);
void bt_menu_test_packet_tx(void* context);
void bt_menu_test_tone_rx(void* context);
void bt_menu_start_app(void* context);

View File

@ -0,0 +1,58 @@
#pragma once
typedef enum {
BtMessageTypeStartTestToneTx,
BtMessageTypeHoppingTx,
BtMessageTypeStopTestToneTx,
BtMessageTypeSetupTestPacketTx,
BtMessageTypeStartTestPacketTx,
BtMessageTypeStopTestPacketTx,
BtMessageTypeStartTestRx,
BtMessageTypeStopTestRx,
BtMessageTypeStartApp,
BtMessageTypeUpdateStatusbar,
} BtMessageType;
typedef enum {
BtStatusReady,
BtStatusToneTx,
BtStatusHoppingTx,
BtStatusToneRx,
BtStatusPacketSetup,
BtStatusPacketTx,
BtStatusStartedApp,
} BtStateType;
typedef enum {
BtChannel2402 = 0,
BtChannel2440 = 19,
BtChannel2480 = 39,
} BtTestChannel;
typedef enum {
BtPower0dB = 0x19,
BtPower2dB = 0x1B,
BtPower4dB = 0x1D,
BtPower6dB = 0x1F,
} BtTestPower;
typedef enum {
BtDateRate1M = 1,
BtDateRate2M = 2,
} BtTestDataRate;
typedef struct {
BtTestChannel channel;
BtTestPower power;
BtTestDataRate datarate;
} BtTestParam;
typedef struct {
BtMessageType type;
BtTestParam param;
} BtMessage;
typedef struct {
BtStateType type;
BtTestParam param;
} BtState;

188
applications/bt/bt_views.c Normal file
View File

@ -0,0 +1,188 @@
#include "bt_views.h"
void bt_view_test_tone_tx_draw(Canvas* canvas, void* model) {
BtViewTestToneTxModel* m = model;
canvas_clear(canvas);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 12, "Performing continous TX test");
if(m->type == BtStatusToneTx) {
canvas_draw_str(canvas, 0, 24, "Manual control mode");
} else {
canvas_draw_str(canvas, 0, 24, "Hopping mode");
}
char buffer[32];
snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402);
canvas_draw_str(canvas, 0, 36, buffer);
snprintf(buffer, sizeof(buffer), "Power:%d dB", m->power - BtPower0dB);
canvas_draw_str(canvas, 0, 48, buffer);
}
void bt_view_test_tone_rx_draw(Canvas* canvas, void* model) {
BtViewTestRxModel* m = model;
canvas_clear(canvas);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 12, "Performing continous RX test");
char buffer[32];
snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402);
canvas_draw_str(canvas, 0, 24, buffer);
}
void bt_view_test_packet_tx_draw(Canvas* canvas, void* model) {
BtViewTestPacketTxModel* m = model;
canvas_clear(canvas);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 12, "Packets send TX test");
if(m->type == BtStatusPacketSetup) {
canvas_draw_str(canvas, 0, 24, "Setup parameters");
canvas_draw_str(canvas, 0, 36, "Press OK to send packets");
} else {
canvas_draw_str(canvas, 0, 24, "Sending packets");
canvas_draw_str(canvas, 0, 36, "Packets parameters:");
}
char buffer[32];
snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402);
canvas_draw_str(canvas, 0, 48, buffer);
snprintf(buffer, sizeof(buffer), "Daterate:%d Mbps", m->datarate);
canvas_draw_str(canvas, 0, 60, buffer);
}
void bt_view_app_draw(Canvas* canvas, void* model) {
canvas_clear(canvas);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 12, "Start BLE app");
}
BtTestChannel bt_switch_channel(InputKey key, BtTestChannel inst_chan) {
uint8_t pos = 0;
BtTestChannel arr[] = {BtChannel2402, BtChannel2440, BtChannel2480};
for(pos = 0; pos < sizeof(arr); pos++) {
if(arr[pos] == inst_chan) {
break;
}
}
if(key == InputKeyRight) {
pos = (pos + 1) % sizeof(arr);
return arr[pos];
} else if(key == InputKeyLeft) {
if(pos) {
return arr[pos - 1];
} else {
return arr[sizeof(arr) - 1];
}
}
return arr[0];
}
bool bt_view_test_tone_tx_input(InputEvent* event, void* context) {
furi_assert(event);
furi_assert(context);
Bt* bt = context;
if(event->type == InputTypeShort) {
if(event->key == InputKeyBack) {
if(osTimerIsRunning(bt->hopping_mode_timer)) {
osTimerStop(bt->hopping_mode_timer);
}
BtMessage m = {.type = BtMessageTypeStopTestToneTx};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE);
return true;
} else {
if(event->key == InputKeyRight || event->key == InputKeyLeft) {
bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel);
} else if(event->key == InputKeyUp) {
if(bt->state.param.power < BtPower6dB) {
bt->state.param.power += 2;
}
} else if(event->key == InputKeyDown) {
if(bt->state.param.power > BtPower0dB) {
bt->state.param.power -= 2;
}
} else if(event->key == InputKeyOk) {
if(bt->state.type == BtStatusToneTx) {
bt->state.type = BtStatusHoppingTx;
osTimerStart(bt->hopping_mode_timer, 2000);
} else {
bt->state.type = BtStatusToneTx;
osTimerStop(bt->hopping_mode_timer);
}
}
BtMessage m = {
.type = BtMessageTypeStartTestToneTx,
.param.channel = bt->state.param.channel,
.param.power = bt->state.param.power};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
return true;
}
}
return false;
}
bool bt_view_test_tone_rx_input(InputEvent* event, void* context) {
furi_assert(event);
furi_assert(context);
Bt* bt = context;
if(event->type == InputTypeShort) {
if(event->key == InputKeyRight || event->key == InputKeyLeft) {
bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel);
BtMessage m = {
.type = BtMessageTypeStartTestRx, .param.channel = bt->state.param.channel};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
return true;
} else if(event->key == InputKeyBack) {
BtMessage m = {.type = BtMessageTypeStopTestRx};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE);
return true;
} else {
return false;
}
}
return false;
}
bool bt_view_test_packet_tx_input(InputEvent* event, void* context) {
furi_assert(event);
furi_assert(context);
Bt* bt = context;
if(event->type == InputTypeShort) {
if(event->key < InputKeyOk) {
// Process InputKeyUp, InputKeyDown, InputKeyLeft, InputKeyRight
if(event->key == InputKeyRight || event->key == InputKeyLeft) {
bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel);
} else if(event->key == InputKeyUp) {
if(bt->state.param.datarate < BtDateRate2M) {
bt->state.param.datarate += 1;
}
} else if(event->key == InputKeyDown) {
if(bt->state.param.datarate > BtDateRate1M) {
bt->state.param.datarate -= 1;
}
}
bt->state.type = BtStatusPacketSetup;
BtMessage m = {
.type = BtMessageTypeSetupTestPacketTx,
.param.channel = bt->state.param.channel,
.param.datarate = bt->state.param.datarate,
};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
return true;
} else if(event->key == InputKeyOk) {
bt->state.type = BtStatusPacketTx;
BtMessage m = {
.type = BtMessageTypeStartTestPacketTx,
.param.channel = bt->state.param.channel,
.param.datarate = bt->state.param.datarate,
};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
return true;
} else if(event->key == InputKeyBack) {
BtMessage m = {
.type = BtMessageTypeStopTestPacketTx,
};
furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK);
view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE);
return true;
}
}
return false;
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "bt_i.h"
#include "bt_types.h"
#include <stdint.h>
#include <stdbool.h>
#include <gui/canvas.h>
#include <furi.h>
#include <gui/view_dispatcher.h>
#include <gui/view.h>
typedef enum {
BtViewTestToneTx,
BtViewTestPacketTx,
BtViewTestToneRx,
BtViewStartApp,
} BtView;
typedef struct {
BtStateType type;
BtTestChannel channel;
BtTestPower power;
} BtViewTestToneTxModel;
typedef struct {
BtStateType type;
BtTestChannel channel;
BtTestDataRate datarate;
} BtViewTestPacketTxModel;
typedef struct {
BtTestChannel channel;
} BtViewTestRxModel;
void bt_view_test_tone_tx_draw(Canvas* canvas, void* model);
bool bt_view_test_tone_tx_input(InputEvent* event, void* context);
void bt_view_test_packet_tx_draw(Canvas* canvas, void* model);
bool bt_view_test_packet_tx_input(InputEvent* event, void* context);
void bt_view_test_tone_rx_draw(Canvas* canvas, void* model);
bool bt_view_test_tone_rx_input(InputEvent* event, void* context);
void bt_view_app_draw(Canvas* canvas, void* model);

View File

@ -10,6 +10,9 @@ extern "C" {
/* Initialize */ /* Initialize */
void api_hal_bt_init(); void api_hal_bt_init();
/* Start BLE app */
bool api_hal_bt_start_app();
/* Get BT/BLE system component state */ /* Get BT/BLE system component state */
void api_hal_bt_dump_state(string_t buffer); void api_hal_bt_dump_state(string_t buffer);
@ -24,6 +27,24 @@ bool api_hal_bt_lock_flash();
/* Unlock shared access to flash controller */ /* Unlock shared access to flash controller */
void api_hal_bt_unlock_flash(); void api_hal_bt_unlock_flash();
/* Start ble tone tx at given channel and power */
void api_hal_bt_start_tone_tx(uint8_t tx_channel, uint8_t power);
/* Stop ble tone tx */
void api_hal_bt_stop_tone_tx();
/* Start sending ble packets at a given frequency and datarate */
void api_hal_bt_start_packet_tx(uint8_t frequency, uint8_t datarate);
/* Stop sending ble packets */
void api_hal_bt_stop_packet_tx();
/* Set up the RF to listen to a given RF channel */
void api_hal_bt_start_rx(uint8_t frequency);
/* Stop RF listenning */
void api_hal_bt_stop_rx();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -4,6 +4,7 @@
#include <stm32wbxx.h> #include <stm32wbxx.h>
#include <shci.h> #include <shci.h>
#include <cmsis_os2.h> #include <cmsis_os2.h>
#include <app_ble.h>
void api_hal_bt_init() { void api_hal_bt_init() {
// Explicitly tell that we are in charge of CLK48 domain // Explicitly tell that we are in charge of CLK48 domain
@ -12,6 +13,10 @@ void api_hal_bt_init() {
APPE_Init(); APPE_Init();
} }
bool api_hal_bt_start_app() {
return APP_BLE_Start();
}
void api_hal_bt_dump_state(string_t buffer) { void api_hal_bt_dump_state(string_t buffer) {
BleGlueStatus status = APPE_Status(); BleGlueStatus status = APPE_Status();
if (status == BleGlueStatusStarted) { if (status == BleGlueStatusStarted) {
@ -76,3 +81,29 @@ void api_hal_bt_unlock_flash() {
HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID); HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
} }
} }
void api_hal_bt_start_tone_tx(uint8_t tx_channel, uint8_t power) {
aci_hal_set_tx_power_level(0, power);
aci_hal_tone_start(tx_channel, 0);
}
void api_hal_bt_stop_tone_tx() {
aci_hal_tone_stop();
}
void api_hal_bt_start_packet_tx(uint8_t frequency, uint8_t datarate) {
hci_le_enhanced_transmitter_test(frequency, 0x25, 2, datarate);
}
void api_hal_bt_stop_packet_tx() {
uint16_t num_of_packets;
hci_le_test_end(&num_of_packets);
}
void api_hal_bt_start_rx(uint8_t frequency) {
aci_hal_rx_start(frequency);
}
void api_hal_bt_stop_rx() {
aci_hal_rx_stop();
}

View File

@ -1,5 +1,6 @@
#include "main.h" #include "main.h"
#include "app_entry.h"
#include "app_common.h" #include "app_common.h"
#include "dbg_trace.h" #include "dbg_trace.h"
#include "ble.h" #include "ble.h"
@ -158,7 +159,11 @@ bool APP_BLE_Init() {
// Register the hci transport layer to handle BLE User Asynchronous Events // Register the hci transport layer to handle BLE User Asynchronous Events
HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr); HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr);
// Starts the BLE Stack on CPU2 // Starts the BLE Stack on CPU2
if (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) != SHCI_Success) { return (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) == SHCI_Success);
}
bool APP_BLE_Start() {
if (APPE_Status() != BleGlueStatusStarted) {
return false; return false;
} }
// Initialization of HCI & GATT & GAP layer // Initialization of HCI & GATT & GAP layer

View File

@ -18,6 +18,7 @@ typedef enum {
} APP_BLE_ConnStatus_t; } APP_BLE_ConnStatus_t;
bool APP_BLE_Init(); bool APP_BLE_Init();
bool APP_BLE_Start();
APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status(); APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status();

View File

@ -4,6 +4,7 @@
#include <stm32wbxx.h> #include <stm32wbxx.h>
#include <shci.h> #include <shci.h>
#include <cmsis_os2.h> #include <cmsis_os2.h>
#include <app_ble.h>
void api_hal_bt_init() { void api_hal_bt_init() {
// Explicitly tell that we are in charge of CLK48 domain // Explicitly tell that we are in charge of CLK48 domain
@ -12,6 +13,10 @@ void api_hal_bt_init() {
APPE_Init(); APPE_Init();
} }
bool api_hal_bt_start_app() {
return APP_BLE_Start();
}
void api_hal_bt_dump_state(string_t buffer) { void api_hal_bt_dump_state(string_t buffer) {
BleGlueStatus status = APPE_Status(); BleGlueStatus status = APPE_Status();
if (status == BleGlueStatusStarted) { if (status == BleGlueStatusStarted) {
@ -76,3 +81,29 @@ void api_hal_bt_unlock_flash() {
HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID); HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
} }
} }
void api_hal_bt_start_tone_tx(uint8_t tx_channel, uint8_t power) {
aci_hal_set_tx_power_level(0, power);
aci_hal_tone_start(tx_channel, 0);
}
void api_hal_bt_stop_tone_tx() {
aci_hal_tone_stop();
}
void api_hal_bt_start_packet_tx(uint8_t frequency, uint8_t datarate) {
hci_le_enhanced_transmitter_test(frequency, 0x25, 2, datarate);
}
void api_hal_bt_stop_packet_tx() {
uint16_t num_of_packets;
hci_le_test_end(&num_of_packets);
}
void api_hal_bt_start_rx(uint8_t frequency) {
aci_hal_rx_start(frequency);
}
void api_hal_bt_stop_rx() {
aci_hal_rx_stop();
}

View File

@ -1,5 +1,6 @@
#include "main.h" #include "main.h"
#include "app_entry.h"
#include "app_common.h" #include "app_common.h"
#include "dbg_trace.h" #include "dbg_trace.h"
#include "ble.h" #include "ble.h"
@ -158,7 +159,11 @@ bool APP_BLE_Init() {
// Register the hci transport layer to handle BLE User Asynchronous Events // Register the hci transport layer to handle BLE User Asynchronous Events
HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr); HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr);
// Starts the BLE Stack on CPU2 // Starts the BLE Stack on CPU2
if (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) != SHCI_Success) { return (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) == SHCI_Success);
}
bool APP_BLE_Start() {
if (APPE_Status() != BleGlueStatusStarted) {
return false; return false;
} }
// Initialization of HCI & GATT & GAP layer // Initialization of HCI & GATT & GAP layer

View File

@ -18,6 +18,7 @@ typedef enum {
} APP_BLE_ConnStatus_t; } APP_BLE_ConnStatus_t;
bool APP_BLE_Init(); bool APP_BLE_Init();
bool APP_BLE_Start();
APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status(); APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status();