Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Morse Code FAP#144

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
xMasterX merged 2 commits intoDarkFlippers:devfromwh00hw:dev
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes fromall 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
1 change: 1 addition & 0 deletionsReadMe.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,7 @@ Also check changelog in releases for latest updates!
- i2c Tools [(By NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only!
- Temperature Sensor Plugin - HTU21D / SI7021 [(By Mywk)](https://github.com/Mywk/FlipperTemperatureSensor) - [How to Connect](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/temperature_sensor/Readme.md)
- HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo)
- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP)

Games:
- DOOM (fixed) [(By p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
Expand Down
15 changes: 15 additions & 0 deletionsapplications/plugins/morse_code/application.fam
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
App(
appid="morse_code",
name="Morse Code",
apptype=FlipperAppType.EXTERNAL,
entry_point="morse_code_app",
cdefines=["APP_MORSE_CODE"],
requires=[
"gui",
],
stack_size=1 * 1024,
order=20,
fap_icon="morse_code_10px.png",
fap_category="Music"

)
161 changes: 161 additions & 0 deletionsapplications/plugins/morse_code/morse_code.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
#include "morse_code_worker.h"
#include <furi.h>
#include <gui/gui.h>
#include <gui/elements.h>
#include <input/input.h>
#include <stdlib.h>
#include <furi_hal.h>
#include <string.h>

static const float MORSE_CODE_VOLUMES[] = {0, .25, .5, .75, 1};

typedef struct {
FuriString* words;
uint8_t volume;
uint32_t dit_delta;
} MorseCodeModel;

typedef struct {
MorseCodeModel* model;
FuriMutex** model_mutex;

FuriMessageQueue* input_queue;

ViewPort* view_port;
Gui* gui;

MorseCodeWorker* worker;
} MorseCode;


static void render_callback(Canvas* const canvas, void* ctx) {
MorseCode* morse_code = ctx;
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
// border around the edge of the screen
canvas_set_font(canvas, FontPrimary);

//write words
elements_multiline_text_aligned(canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words));

// volume view_port
uint8_t vol_bar_x_pos = 124;
uint8_t vol_bar_y_pos = 0;
const uint8_t volume_h =
(64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume;
canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64);
canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h);

//dit bpm
canvas_draw_str_aligned(
canvas, 0, 10, AlignLeft, AlignCenter, furi_string_get_cstr(furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta)));

//button info
elements_button_center(canvas, "Press/Hold");
furi_mutex_release(morse_code->model_mutex);
}

static void input_callback(InputEvent* input_event, void* ctx) {
MorseCode* morse_code = ctx;
furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever);
}

static void morse_code_worker_callback(
FuriString* words,
void* context) {
MorseCode* morse_code = context;
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
morse_code->model->words = words;
furi_mutex_release(morse_code->model_mutex);
view_port_update(morse_code->view_port);
}

MorseCode* morse_code_alloc() {
MorseCode* instance = malloc(sizeof(MorseCode));

instance->model = malloc(sizeof(MorseCodeModel));
instance->model->words = furi_string_alloc_set_str("");
instance->model->volume = 3;
instance->model->dit_delta = 150;
instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);

instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));

instance->worker = morse_code_worker_alloc();

morse_code_worker_set_callback(instance->worker, morse_code_worker_callback, instance);

instance->view_port = view_port_alloc();
view_port_draw_callback_set(instance->view_port, render_callback, instance);
view_port_input_callback_set(instance->view_port, input_callback, instance);

// Open GUI and register view_port
instance->gui = furi_record_open(RECORD_GUI);
gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);

return instance;
}

void morse_code_free(MorseCode* instance) {
gui_remove_view_port(instance->gui, instance->view_port);
furi_record_close(RECORD_GUI);
view_port_free(instance->view_port);

morse_code_worker_free(instance->worker);

furi_message_queue_free(instance->input_queue);

furi_mutex_free(instance->model_mutex);

free(instance->model);
free(instance);
}

int32_t morse_code_app() {
MorseCode* morse_code = morse_code_alloc();
InputEvent input;
morse_code_worker_start(morse_code->worker);
morse_code_worker_set_volume(
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == FuriStatusOk){
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
if(input.key == InputKeyBack) {
furi_mutex_release(morse_code->model_mutex);
break;
}else if(input.key == InputKeyOk){
if(input.type == InputTypePress)
morse_code_worker_play(morse_code->worker, true);
else if(input.type == InputTypeRelease)
morse_code_worker_play(morse_code->worker, false);
}else if(input.key == InputKeyUp && input.type == InputTypePress){
if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1)
morse_code->model->volume++;
morse_code_worker_set_volume(
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
}else if(input.key == InputKeyDown && input.type == InputTypePress){
if(morse_code->model->volume > 0)
morse_code->model->volume--;
morse_code_worker_set_volume(
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
}else if(input.key == InputKeyLeft && input.type == InputTypePress){
if(morse_code->model->dit_delta > 10)
morse_code->model->dit_delta-=10;
morse_code_worker_set_dit_delta(
morse_code->worker, morse_code->model->dit_delta);
}
else if(input.key == InputKeyRight && input.type == InputTypePress){
if(morse_code->model->dit_delta >= 10)
morse_code->model->dit_delta+=10;
morse_code_worker_set_dit_delta(
morse_code->worker, morse_code->model->dit_delta);
}

FURI_LOG_D("Input", "%s %s %ld", input_get_key_name(input.key), input_get_type_name(input.type), input.sequence);

furi_mutex_release(morse_code->model_mutex);
view_port_update(morse_code->view_port);
}
morse_code_worker_stop(morse_code->worker);
morse_code_free(morse_code);
return 0;
}
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
164 changes: 164 additions & 0 deletionsapplications/plugins/morse_code/morse_code_worker.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
#include "morse_code_worker.h"
#include <furi_hal.h>
#include <lib/flipper_format/flipper_format.h>


#define TAG "MorseCodeWorker"

#define MORSE_CODE_VERSION 0

//A-Z0-1
const char morse_array[36][6] ={
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.",
"--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....",
"-....", "--...", "---..", "----.", "-----"
};
const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};

struct MorseCodeWorker {
FuriThread* thread;
MorseCodeWorkerCallback callback;
void* callback_context;
bool is_running;
bool play;
float volume;
uint32_t dit_delta;
FuriString* buffer;
FuriString* words;
};

void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration){
FURI_LOG_D("MorseCode: Duration", "%ld", duration);
if( duration <= instance->dit_delta)
furi_string_push_back(instance->buffer, *DOT);
else if(duration <= (instance->dit_delta * 3))
furi_string_push_back(instance->buffer, *LINE);
if(furi_string_size(instance->buffer) > 5)
furi_string_reset(instance->buffer);
FURI_LOG_D("MorseCode: Buffer", "%s", furi_string_get_cstr(instance->buffer));
}

void morse_code_worker_fill_letter(MorseCodeWorker* instance){
if(furi_string_size(instance->words) > 63)
furi_string_reset(instance->words);
for (size_t i = 0; i < sizeof(morse_array); i++){
if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0){
furi_string_push_back(instance->words, symbol_array[i]);
furi_string_reset(instance->buffer);
break;
}
}
FURI_LOG_D("MorseCode: Words", "%s", furi_string_get_cstr(instance->words));
}


static int32_t morse_code_worker_thread_callback(void* context) {
furi_assert(context);
MorseCodeWorker* instance = context;
bool was_playing = false;
uint32_t start_tick = 0;
uint32_t end_tick = 0;
bool pushed = true;
bool spaced = true;
while(instance->is_running){
furi_delay_ms(SLEEP);
if(instance->play){
if(!was_playing){
start_tick = furi_get_tick();
furi_hal_speaker_start(FREQUENCY, instance->volume);
was_playing = true;
}
}else{
if(was_playing){
pushed = false;
spaced = false;
furi_hal_speaker_stop();
end_tick = furi_get_tick();
was_playing = false;
morse_code_worker_fill_buffer(instance, end_tick - start_tick);
start_tick = 0;
}
}
if(!pushed){
if(end_tick + (instance->dit_delta * 3) < furi_get_tick()){
//NEW LETTER
morse_code_worker_fill_letter(instance);
if(instance->callback)
instance->callback(instance->words, instance->callback_context);
pushed = true;
}
}
if(!spaced){
if(end_tick + (instance->dit_delta * 7) < furi_get_tick()){
//NEW WORD
furi_string_push_back(instance->words, *SPACE);
if(instance->callback)
instance->callback(instance->words, instance->callback_context);
spaced = true;
}
}
}
return 0;
}

MorseCodeWorker* morse_code_worker_alloc() {
MorseCodeWorker* instance = malloc(sizeof(MorseCodeWorker));
instance->thread = furi_thread_alloc();
furi_thread_set_name(instance->thread, "MorseCodeWorker");
furi_thread_set_stack_size(instance->thread, 1024);
furi_thread_set_context(instance->thread, instance);
furi_thread_set_callback(instance->thread, morse_code_worker_thread_callback);
instance->play = false;
instance->volume = 1.0f;
instance->dit_delta = 150;
instance->buffer = furi_string_alloc_set_str("");
instance->words = furi_string_alloc_set_str("");
return instance;
}

void morse_code_worker_free(MorseCodeWorker* instance) {
furi_assert(instance);
furi_thread_free(instance->thread);
free(instance);
}

void morse_code_worker_set_callback(
MorseCodeWorker* instance,
MorseCodeWorkerCallback callback,
void* context) {
furi_assert(instance);
instance->callback = callback;
instance->callback_context = context;
}

void morse_code_worker_play(MorseCodeWorker* instance, bool play){
furi_assert(instance);
instance->play = play;
}

void morse_code_worker_set_volume(MorseCodeWorker* instance, float level){
furi_assert(instance);
instance->volume = level;
}

void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta){
furi_assert(instance);
instance->dit_delta = delta;
}

void morse_code_worker_start(MorseCodeWorker* instance) {
furi_assert(instance);
furi_assert(instance->is_running == false);
instance->is_running = true;
furi_thread_start(instance->thread);
FURI_LOG_D("MorseCode: Start", "is Running");
}

void morse_code_worker_stop(MorseCodeWorker* instance) {
furi_assert(instance);
furi_assert(instance->is_running == true);
instance->is_running = false;
furi_thread_join(instance->thread);
FURI_LOG_D("MorseCode: Stop", "Stop");
}
42 changes: 42 additions & 0 deletionsapplications/plugins/morse_code/morse_code_worker.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>
#include <furi.h>

#define FREQUENCY 261.63f
#define SLEEP 10
#define DOT "."
#define LINE "-"
#define SPACE " "

typedef void (*MorseCodeWorkerCallback)(
FuriString* buffer,
void* context);

typedef struct MorseCodeWorker MorseCodeWorker;

MorseCodeWorker* morse_code_worker_alloc();

void morse_code_worker_free(MorseCodeWorker* instance);

void morse_code_worker_set_callback(
MorseCodeWorker* instance,
MorseCodeWorkerCallback callback,
void* context);

void morse_code_worker_start(MorseCodeWorker* instance);

void morse_code_worker_stop(MorseCodeWorker* instance);

void morse_code_worker_play(MorseCodeWorker* instance, bool play);

void morse_code_worker_set_volume(MorseCodeWorker* instance, float level);

void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta);







[8]ページ先頭

©2009-2025 Movatter.jp