Skip to content

Commit

Permalink
[FL-2797] Signal Generator app (flipperdevices#1793)
Browse files Browse the repository at this point in the history
* Signal Generator app
* MCO pin initialization in app
* furi_hal_pwm documentation

Co-authored-by: あく <alleteam@gmail.com>
  • Loading branch information
nminaylov and skotopes committed Sep 28, 2022
1 parent e87c6da commit 0164b50
Show file tree
Hide file tree
Showing 19 changed files with 1,069 additions and 1 deletion.
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

0 comments on commit 0164b50

Please sign in to comment.