Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FL-2797] Signal Generator app #1793

Merged
merged 4 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions applications/plugins/signal_generator/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
App(
appid="signal_generator",
name="Signal Generator",
apptype=FlipperAppType.PLUGIN,
entry_point="signal_gen_app",
cdefines=["APP_SIGNAL_GEN"],
requires=["gui"],
stack_size=1 * 1024,
order=50,
fap_icon="signal_gen_10px.png",
fap_category="Tools",
)
30 changes: 30 additions & 0 deletions applications/plugins/signal_generator/scenes/signal_gen_scene.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../signal_gen_app_i.h"

// Generate scene on_enter handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
void (*const signal_gen_scene_on_enter_handlers[])(void*) = {
#include "signal_gen_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_event handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
bool (*const signal_gen_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
#include "signal_gen_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_exit handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
void (*const signal_gen_scene_on_exit_handlers[])(void* context) = {
#include "signal_gen_scene_config.h"
};
#undef ADD_SCENE

// Initialize scene handlers configuration structure
const SceneManagerHandlers signal_gen_scene_handlers = {
.on_enter_handlers = signal_gen_scene_on_enter_handlers,
.on_event_handlers = signal_gen_scene_on_event_handlers,
.on_exit_handlers = signal_gen_scene_on_exit_handlers,
.scene_num = SignalGenSceneNum,
};
29 changes: 29 additions & 0 deletions applications/plugins/signal_generator/scenes/signal_gen_scene.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <gui/scene_manager.h>

// Generate scene id and total number
#define ADD_SCENE(prefix, name, id) SignalGenScene##id,
typedef enum {
#include "signal_gen_scene_config.h"
SignalGenSceneNum,
} SignalGenScene;
#undef ADD_SCENE

extern const SceneManagerHandlers signal_gen_scene_handlers;

// Generate scene on_enter handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
#include "signal_gen_scene_config.h"
#undef ADD_SCENE

// Generate scene on_event handlers declaration
#define ADD_SCENE(prefix, name, id) \
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
#include "signal_gen_scene_config.h"
#undef ADD_SCENE

// Generate scene on_exit handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
#include "signal_gen_scene_config.h"
#undef ADD_SCENE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ADD_SCENE(signal_gen, start, Start)
ADD_SCENE(signal_gen, pwm, Pwm)
ADD_SCENE(signal_gen, mco, Mco)
132 changes: 132 additions & 0 deletions applications/plugins/signal_generator/scenes/signal_gen_scene_mco.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "../signal_gen_app_i.h"

typedef enum {
LineIndexSource,
LineIndexDivision,
} LineIndex;

static const char* const mco_source_names[] = {
"32768",
"64MHz",
"~100K",
"~200K",
"~400K",
"~800K",
"~1MHz",
"~2MHz",
"~4MHz",
"~8MHz",
"~16MHz",
"~24MHz",
"~32MHz",
"~48MHz",
};

static const FuriHalClockMcoSourceId mco_sources[] = {
FuriHalClockMcoLse,
FuriHalClockMcoSysclk,
FuriHalClockMcoMsi100k,
FuriHalClockMcoMsi200k,
FuriHalClockMcoMsi400k,
FuriHalClockMcoMsi800k,
FuriHalClockMcoMsi1m,
FuriHalClockMcoMsi2m,
FuriHalClockMcoMsi4m,
FuriHalClockMcoMsi8m,
FuriHalClockMcoMsi16m,
FuriHalClockMcoMsi24m,
FuriHalClockMcoMsi32m,
FuriHalClockMcoMsi48m,
};

static const char* const mco_divisor_names[] = {
"1",
"2",
"4",
"8",
"16",
};

static const FuriHalClockMcoDivisorId mco_divisors[] = {
FuriHalClockMcoDiv1,
FuriHalClockMcoDiv2,
FuriHalClockMcoDiv4,
FuriHalClockMcoDiv8,
FuriHalClockMcoDiv16,
};

static void mco_source_list_change_callback(VariableItem* item) {
SignalGenApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, mco_source_names[index]);

app->mco_src = mco_sources[index];

view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate);
}

static void mco_divisor_list_change_callback(VariableItem* item) {
SignalGenApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, mco_divisor_names[index]);

app->mco_div = mco_divisors[index];

view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenMcoEventUpdate);
}

void signal_gen_scene_mco_on_enter(void* context) {
SignalGenApp* app = context;
VariableItemList* var_item_list = app->var_item_list;

VariableItem* item;

item = variable_item_list_add(
var_item_list, "Source", COUNT_OF(mco_source_names), mco_source_list_change_callback, app);
variable_item_set_current_value_index(item, 0);
variable_item_set_current_value_text(item, mco_source_names[0]);

item = variable_item_list_add(
var_item_list,
"Division",
COUNT_OF(mco_divisor_names),
mco_divisor_list_change_callback,
app);
variable_item_set_current_value_index(item, 0);
variable_item_set_current_value_text(item, mco_divisor_names[0]);

variable_item_list_set_selected_item(var_item_list, LineIndexSource);

view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewVarItemList);

app->mco_src = FuriHalClockMcoLse;
app->mco_div = FuriHalClockMcoDiv1;
furi_hal_clock_mco_enable(app->mco_src, app->mco_div);
furi_hal_gpio_init_ex(
&gpio_usart_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn0MCO);
}

bool signal_gen_scene_mco_on_event(void* context, SceneManagerEvent event) {
SignalGenApp* app = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SignalGenMcoEventUpdate) {
consumed = true;
furi_hal_clock_mco_enable(app->mco_src, app->mco_div);
}
}
return consumed;
}

void signal_gen_scene_mco_on_exit(void* context) {
SignalGenApp* app = context;
variable_item_list_reset(app->var_item_list);
furi_hal_gpio_init_ex(
&gpio_usart_tx,
GpioModeAltFunctionPushPull,
GpioPullUp,
GpioSpeedVeryHigh,
GpioAltFn7USART1);
furi_hal_clock_mco_disable();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "../signal_gen_app_i.h"

static const FuriHalPwmOutputId pwm_ch_id[] = {
FuriHalPwmOutputIdTim1PA7,
FuriHalPwmOutputIdLptim2PA4,
};

#define DEFAULT_FREQ 1000
#define DEFAULT_DUTY 50

static void
signal_gen_pwm_callback(uint8_t channel_id, uint32_t freq, uint8_t duty, void* context) {
SignalGenApp* app = context;

app->pwm_freq = freq;
app->pwm_duty = duty;

if(app->pwm_ch != pwm_ch_id[channel_id]) {
app->pwm_ch_prev = app->pwm_ch;
app->pwm_ch = pwm_ch_id[channel_id];
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventChannelChange);
} else {
app->pwm_ch = pwm_ch_id[channel_id];
view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventUpdate);
}
}

void signal_gen_scene_pwm_on_enter(void* context) {
SignalGenApp* app = context;

view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewPwm);

signal_gen_pwm_set_callback(app->pwm_view, signal_gen_pwm_callback, app);

signal_gen_pwm_set_params(app->pwm_view, 0, DEFAULT_FREQ, DEFAULT_DUTY);
furi_hal_pwm_start(pwm_ch_id[0], DEFAULT_FREQ, DEFAULT_DUTY);
}

bool signal_gen_scene_pwm_on_event(void* context, SceneManagerEvent event) {
SignalGenApp* app = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SignalGenPwmEventUpdate) {
consumed = true;
furi_hal_pwm_set_params(app->pwm_ch, app->pwm_freq, app->pwm_duty);
} else if(event.event == SignalGenPwmEventChannelChange) {
consumed = true;
furi_hal_pwm_stop(app->pwm_ch_prev);
furi_hal_pwm_start(app->pwm_ch, app->pwm_freq, app->pwm_duty);
}
}
return consumed;
}

void signal_gen_scene_pwm_on_exit(void* context) {
SignalGenApp* app = context;
variable_item_list_reset(app->var_item_list);
furi_hal_pwm_stop(app->pwm_ch);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "../signal_gen_app_i.h"

typedef enum {
SubmenuIndexPwm,
SubmenuIndexClockOutput,
} SubmenuIndex;

void signal_gen_scene_start_submenu_callback(void* context, uint32_t index) {
SignalGenApp* app = context;

view_dispatcher_send_custom_event(app->view_dispatcher, index);
}

void signal_gen_scene_start_on_enter(void* context) {
SignalGenApp* app = context;
Submenu* submenu = app->submenu;

submenu_add_item(
submenu, "PWM", SubmenuIndexPwm, signal_gen_scene_start_submenu_callback, app);
submenu_add_item(
submenu,
"Clock Output",
SubmenuIndexClockOutput,
signal_gen_scene_start_submenu_callback,
app);

submenu_set_selected_item(
submenu, scene_manager_get_scene_state(app->scene_manager, SignalGenSceneStart));

view_dispatcher_switch_to_view(app->view_dispatcher, SignalGenViewSubmenu);
}

bool signal_gen_scene_start_on_event(void* context, SceneManagerEvent event) {
SignalGenApp* app = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexPwm) {
scene_manager_next_scene(app->scene_manager, SignalGenScenePwm);
consumed = true;
} else if(event.event == SubmenuIndexClockOutput) {
scene_manager_next_scene(app->scene_manager, SignalGenSceneMco);
consumed = true;
}
scene_manager_set_scene_state(app->scene_manager, SignalGenSceneStart, event.event);
}

return consumed;
}

void signal_gen_scene_start_on_exit(void* context) {
SignalGenApp* app = context;

submenu_reset(app->submenu);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading