mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-06 17:42:00 +00:00
./fbt format
This commit is contained in:
@@ -16,70 +16,69 @@ typedef struct {
|
||||
InputEvent input;
|
||||
} PluginEvent;
|
||||
|
||||
|
||||
//QUEUE
|
||||
|
||||
struct node {
|
||||
int interval;
|
||||
struct node *next;
|
||||
struct node* next;
|
||||
};
|
||||
typedef struct node node;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int max_size;
|
||||
node *front;
|
||||
node *rear;
|
||||
node* front;
|
||||
node* rear;
|
||||
} queue;
|
||||
|
||||
static void init_queue(queue *q) {
|
||||
q->size = 0;
|
||||
q->max_size = 8;
|
||||
q->front = NULL;
|
||||
q->rear = NULL;
|
||||
static void init_queue(queue* q) {
|
||||
q->size = 0;
|
||||
q->max_size = 8;
|
||||
q->front = NULL;
|
||||
q->rear = NULL;
|
||||
}
|
||||
|
||||
static void queue_remove(queue *q) {
|
||||
node *tmp;
|
||||
static void queue_remove(queue* q) {
|
||||
node* tmp;
|
||||
tmp = q->front;
|
||||
q->front = q->front->next;
|
||||
q->size--;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static void queue_add(queue *q, int value) {
|
||||
node *tmp = malloc(sizeof(node));
|
||||
static void queue_add(queue* q, int value) {
|
||||
node* tmp = malloc(sizeof(node));
|
||||
tmp->interval = value;
|
||||
tmp->next = NULL;
|
||||
if (q->size == q->max_size) {
|
||||
queue_remove(q);
|
||||
}
|
||||
if(q->size == q->max_size) {
|
||||
queue_remove(q);
|
||||
}
|
||||
// check if empty
|
||||
if (q->rear == NULL) {
|
||||
q->front = tmp;
|
||||
q->rear = tmp;
|
||||
if(q->rear == NULL) {
|
||||
q->front = tmp;
|
||||
q->rear = tmp;
|
||||
} else {
|
||||
q->rear->next = tmp;
|
||||
q->rear = tmp;
|
||||
q->rear->next = tmp;
|
||||
q->rear = tmp;
|
||||
}
|
||||
q->size++;
|
||||
}
|
||||
|
||||
static float queue_avg(queue *q) {
|
||||
static float queue_avg(queue* q) {
|
||||
float avg = 0.0;
|
||||
if (q->size == 0){
|
||||
return avg;
|
||||
if(q->size == 0) {
|
||||
return avg;
|
||||
} else {
|
||||
node *tmp;
|
||||
float sum = 0.0;
|
||||
tmp = q->front;
|
||||
while (tmp != NULL) {
|
||||
sum = sum + tmp->interval;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
avg = sum / q->size;
|
||||
FURI_LOG_D("BPM-Tapper", "Sum: %.2f Avg: %.2f", (double)sum, (double)avg);
|
||||
return avg;
|
||||
node* tmp;
|
||||
float sum = 0.0;
|
||||
tmp = q->front;
|
||||
while(tmp != NULL) {
|
||||
sum = sum + tmp->interval;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
avg = sum / q->size;
|
||||
FURI_LOG_D("BPM-Tapper", "Sum: %.2f Avg: %.2f", (double)sum, (double)avg);
|
||||
return avg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,33 +94,32 @@ typedef struct {
|
||||
double bpm;
|
||||
uint32_t last_stamp;
|
||||
uint32_t interval;
|
||||
queue *tap_queue;
|
||||
queue* tap_queue;
|
||||
} BPMTapper;
|
||||
|
||||
static void show_hello() {
|
||||
// BEGIN HELLO DIALOG
|
||||
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
|
||||
// BEGIN HELLO DIALOG
|
||||
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
const char* header_text = "BPM Tapper";
|
||||
const char* message_text = "Tap center to start";
|
||||
|
||||
const char* header_text = "BPM Tapper";
|
||||
const char* message_text = "Tap center to start";
|
||||
dialog_message_set_header(message, header_text, 63, 3, AlignCenter, AlignTop);
|
||||
dialog_message_set_text(message, message_text, 0, 17, AlignLeft, AlignTop);
|
||||
dialog_message_set_buttons(message, NULL, "Tap", NULL);
|
||||
|
||||
dialog_message_set_header(message, header_text, 63, 3, AlignCenter, AlignTop);
|
||||
dialog_message_set_text(message, message_text, 0, 17, AlignLeft, AlignTop);
|
||||
dialog_message_set_buttons(message, NULL, "Tap", NULL);
|
||||
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
|
||||
|
||||
dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17);
|
||||
dialog_message_show(dialogs, message);
|
||||
|
||||
dialog_message_show(dialogs, message);
|
||||
|
||||
dialog_message_free(message);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
// END HELLO DIALOG
|
||||
dialog_message_free(message);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
// END HELLO DIALOG
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
furi_assert(event_queue);
|
||||
|
||||
PluginEvent event = {.type = EventTypeKey, .input = *input_event};
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
@@ -131,8 +129,8 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
string_t tempStr;
|
||||
|
||||
const BPMTapper* bpm_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
if (bpm_state == NULL) {
|
||||
return;
|
||||
if(bpm_state == NULL) {
|
||||
return;
|
||||
}
|
||||
// border
|
||||
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
@@ -152,7 +150,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignBottom, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
|
||||
string_printf(tempStr, "x2 %.2f /2 %.2f", bpm_state->bpm*2, bpm_state->bpm/2);
|
||||
string_printf(tempStr, "x2 %.2f /2 %.2f", bpm_state->bpm * 2, bpm_state->bpm / 2);
|
||||
canvas_draw_str_aligned(canvas, 64, 60, AlignCenter, AlignCenter, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
|
||||
@@ -166,97 +164,95 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
release_mutex((ValueMutex*)ctx, bpm_state);
|
||||
}
|
||||
|
||||
|
||||
static void bpm_state_init(BPMTapper* const plugin_state) {
|
||||
plugin_state->taps = 0;
|
||||
plugin_state->bpm = 120.0;
|
||||
plugin_state->last_stamp = 0;// furi_get_tick();
|
||||
plugin_state->interval = 0;
|
||||
queue *q;
|
||||
q = malloc(sizeof(queue));
|
||||
init_queue(q);
|
||||
plugin_state->tap_queue = q;
|
||||
plugin_state->taps = 0;
|
||||
plugin_state->bpm = 120.0;
|
||||
plugin_state->last_stamp = 0; // furi_get_tick();
|
||||
plugin_state->interval = 0;
|
||||
queue* q;
|
||||
q = malloc(sizeof(queue));
|
||||
init_queue(q);
|
||||
plugin_state->tap_queue = q;
|
||||
}
|
||||
|
||||
int32_t bpm_tapper_app(void* p) {
|
||||
UNUSED(p);
|
||||
UNUSED(p);
|
||||
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
||||
|
||||
BPMTapper* bpm_state = malloc(sizeof(BPMTapper));
|
||||
// setup
|
||||
bpm_state_init(bpm_state);
|
||||
|
||||
ValueMutex state_mutex;
|
||||
if (!init_mutex(&state_mutex, bpm_state, sizeof(bpm_state))) {
|
||||
FURI_LOG_E("BPM-Tapper", "cannot create mutex\r\n");
|
||||
free(bpm_state);
|
||||
return 255;
|
||||
}
|
||||
show_hello();
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
||||
|
||||
// BEGIN IMPLEMENTATION
|
||||
BPMTapper* bpm_state = malloc(sizeof(BPMTapper));
|
||||
// setup
|
||||
bpm_state_init(bpm_state);
|
||||
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
PluginEvent event;
|
||||
for (bool processing = true; processing;) {
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||
BPMTapper* bpm_state = (BPMTapper*)acquire_mutex_block(&state_mutex);
|
||||
if(event_status == FuriStatusOk) {
|
||||
// press events
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypePress) {
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
case InputKeyDown:
|
||||
case InputKeyRight:
|
||||
case InputKeyLeft:
|
||||
case InputKeyOk:
|
||||
bpm_state->taps++;
|
||||
uint32_t new_stamp = furi_get_tick();
|
||||
if (bpm_state->last_stamp == 0) {
|
||||
bpm_state->last_stamp = new_stamp;
|
||||
break;
|
||||
}
|
||||
bpm_state->interval = new_stamp - bpm_state->last_stamp;
|
||||
bpm_state->last_stamp = new_stamp;
|
||||
queue_add(bpm_state->tap_queue, bpm_state->interval);
|
||||
float avg = queue_avg(bpm_state->tap_queue);
|
||||
float bps = 1.0 / (avg / 1000.0);
|
||||
bpm_state->bpm = bps * 60.0;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
// Exit the plugin
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("BPM-Tapper", "FuriMessageQueue: event timeout");
|
||||
// event timeout
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, bpm_state, sizeof(bpm_state))) {
|
||||
FURI_LOG_E("BPM-Tapper", "cannot create mutex\r\n");
|
||||
free(bpm_state);
|
||||
return 255;
|
||||
}
|
||||
view_port_update(view_port);
|
||||
release_mutex(&state_mutex, bpm_state);
|
||||
}
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
queue *q = bpm_state->tap_queue;
|
||||
free(q);
|
||||
free(bpm_state);
|
||||
show_hello();
|
||||
|
||||
return 0;
|
||||
// BEGIN IMPLEMENTATION
|
||||
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
PluginEvent event;
|
||||
for(bool processing = true; processing;) {
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||
BPMTapper* bpm_state = (BPMTapper*)acquire_mutex_block(&state_mutex);
|
||||
if(event_status == FuriStatusOk) {
|
||||
// press events
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypePress) {
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
case InputKeyDown:
|
||||
case InputKeyRight:
|
||||
case InputKeyLeft:
|
||||
case InputKeyOk:
|
||||
bpm_state->taps++;
|
||||
uint32_t new_stamp = furi_get_tick();
|
||||
if(bpm_state->last_stamp == 0) {
|
||||
bpm_state->last_stamp = new_stamp;
|
||||
break;
|
||||
}
|
||||
bpm_state->interval = new_stamp - bpm_state->last_stamp;
|
||||
bpm_state->last_stamp = new_stamp;
|
||||
queue_add(bpm_state->tap_queue, bpm_state->interval);
|
||||
float avg = queue_avg(bpm_state->tap_queue);
|
||||
float bps = 1.0 / (avg / 1000.0);
|
||||
bpm_state->bpm = bps * 60.0;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
// Exit the plugin
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("BPM-Tapper", "FuriMessageQueue: event timeout");
|
||||
// event timeout
|
||||
}
|
||||
view_port_update(view_port);
|
||||
release_mutex(&state_mutex, bpm_state);
|
||||
}
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
queue* q = bpm_state->tap_queue;
|
||||
free(q);
|
||||
free(bpm_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,11 +425,11 @@ int32_t calculator_app(void* p) {
|
||||
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
|
||||
if(event.type == InputTypeLong) {
|
||||
switch(event.key) {
|
||||
case InputKeyOk:
|
||||
if (calculator_state->position.x == 0 && calculator_state->position.y == 4) {
|
||||
if(calculator_state->position.x == 0 && calculator_state->position.y == 4) {
|
||||
if(calculator_state->textLength < MAX_TEXT_LENGTH) {
|
||||
calculator_state->text[calculator_state->textLength++] = ')';
|
||||
calculator_state->text[calculator_state->textLength] = '\0';
|
||||
|
||||
@@ -26,59 +26,69 @@
|
||||
#ifndef TINYEXPR_H
|
||||
#define TINYEXPR_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct te_expr {
|
||||
int type;
|
||||
union {double value; const double *bound; const void *function;};
|
||||
void *parameters[1];
|
||||
union {
|
||||
double value;
|
||||
const double* bound;
|
||||
const void* function;
|
||||
};
|
||||
void* parameters[1];
|
||||
} te_expr;
|
||||
|
||||
|
||||
enum {
|
||||
TE_VARIABLE = 0,
|
||||
|
||||
TE_FUNCTION0 = 8, TE_FUNCTION1, TE_FUNCTION2, TE_FUNCTION3,
|
||||
TE_FUNCTION4, TE_FUNCTION5, TE_FUNCTION6, TE_FUNCTION7,
|
||||
TE_FUNCTION0 = 8,
|
||||
TE_FUNCTION1,
|
||||
TE_FUNCTION2,
|
||||
TE_FUNCTION3,
|
||||
TE_FUNCTION4,
|
||||
TE_FUNCTION5,
|
||||
TE_FUNCTION6,
|
||||
TE_FUNCTION7,
|
||||
|
||||
TE_CLOSURE0 = 16, TE_CLOSURE1, TE_CLOSURE2, TE_CLOSURE3,
|
||||
TE_CLOSURE4, TE_CLOSURE5, TE_CLOSURE6, TE_CLOSURE7,
|
||||
TE_CLOSURE0 = 16,
|
||||
TE_CLOSURE1,
|
||||
TE_CLOSURE2,
|
||||
TE_CLOSURE3,
|
||||
TE_CLOSURE4,
|
||||
TE_CLOSURE5,
|
||||
TE_CLOSURE6,
|
||||
TE_CLOSURE7,
|
||||
|
||||
TE_FLAG_PURE = 32
|
||||
};
|
||||
|
||||
typedef struct te_variable {
|
||||
const char *name;
|
||||
const void *address;
|
||||
const char* name;
|
||||
const void* address;
|
||||
int type;
|
||||
void *context;
|
||||
void* context;
|
||||
} te_variable;
|
||||
|
||||
|
||||
|
||||
/* Parses the input expression, evaluates it, and frees it. */
|
||||
/* Returns NaN on error. */
|
||||
double te_interp(const char *expression, int *error);
|
||||
double te_interp(const char* expression, int* error);
|
||||
|
||||
/* Parses the input expression and binds variables. */
|
||||
/* Returns NULL on error. */
|
||||
te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error);
|
||||
te_expr*
|
||||
te_compile(const char* expression, const te_variable* variables, int var_count, int* error);
|
||||
|
||||
/* Evaluates the expression. */
|
||||
double te_eval(const te_expr *n);
|
||||
double te_eval(const te_expr* n);
|
||||
|
||||
/* Prints debugging information on the syntax tree. */
|
||||
void te_print(const te_expr *n);
|
||||
void te_print(const te_expr* n);
|
||||
|
||||
/* Frees the expression. */
|
||||
/* This is safe to call on NULL pointers. */
|
||||
void te_free(te_expr *n);
|
||||
|
||||
void te_free(te_expr* n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ static void storage_DolphinBackup_scene_confirm_widget_callback(
|
||||
furi_assert(app);
|
||||
if(type == InputTypeShort) {
|
||||
if(result == GuiButtonTypeRight) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DolphinBackupCustomEventConfirm);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, DolphinBackupCustomEventConfirm);
|
||||
} else if(result == GuiButtonTypeLeft) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DolphinBackupCustomEventExit);
|
||||
}
|
||||
|
||||
@@ -83,10 +83,10 @@ static void app_free(DTMFDolphinApp* app) {
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t dtmf_dolphin_app(void *p) {
|
||||
int32_t dtmf_dolphin_app(void* p) {
|
||||
UNUSED(p);
|
||||
DTMFDolphinApp* app = app_alloc();
|
||||
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
app_free(app);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "dtmf_dolphin_audio.h"
|
||||
|
||||
DTMFDolphinAudio *current_player;
|
||||
DTMFDolphinAudio* current_player;
|
||||
|
||||
static void dtmf_dolphin_audio_dma_isr(void* ctx) {
|
||||
FuriMessageQueue *event_queue = ctx;
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
|
||||
if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
LL_DMA_ClearFlag_HT1(DMA1);
|
||||
|
||||
DTMFDolphinCustomEvent event = {.type = DTMFDolphinEventDMAHalfTransfer};
|
||||
@@ -21,13 +21,13 @@ static void dtmf_dolphin_audio_dma_isr(void* ctx) {
|
||||
}
|
||||
|
||||
void dtmf_dolphin_audio_clear_samples(DTMFDolphinAudio* player) {
|
||||
for (size_t i = 0; i < player->buffer_length; i++) {
|
||||
for(size_t i = 0; i < player->buffer_length; i++) {
|
||||
player->sample_buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
|
||||
DTMFDolphinOsc *osc = malloc(sizeof(DTMFDolphinOsc));
|
||||
DTMFDolphinOsc* osc = malloc(sizeof(DTMFDolphinOsc));
|
||||
osc->cached_freq = 0;
|
||||
osc->offset = 0;
|
||||
osc->period = 0;
|
||||
@@ -36,7 +36,7 @@ DTMFDolphinOsc* dtmf_dolphin_osc_alloc() {
|
||||
}
|
||||
|
||||
DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
|
||||
DTMFDolphinAudio *player = malloc(sizeof(DTMFDolphinAudio));
|
||||
DTMFDolphinAudio* player = malloc(sizeof(DTMFDolphinAudio));
|
||||
player->buffer_length = SAMPLE_BUFFER_LENGTH;
|
||||
player->half_buffer_length = SAMPLE_BUFFER_LENGTH / 2;
|
||||
player->sample_buffer = malloc(sizeof(uint16_t) * player->buffer_length);
|
||||
@@ -50,34 +50,32 @@ DTMFDolphinAudio* dtmf_dolphin_audio_alloc() {
|
||||
}
|
||||
|
||||
size_t calc_waveform_period(float freq) {
|
||||
if (!freq) {
|
||||
if(!freq) {
|
||||
return 0;
|
||||
}
|
||||
// DMA Rate calculation, thanks to Dr_Zlo
|
||||
float dma_rate = CPU_CLOCK_FREQ \
|
||||
/ 2 \
|
||||
/ DTMF_DOLPHIN_HAL_DMA_PRESCALER \
|
||||
/ (DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
|
||||
float dma_rate = CPU_CLOCK_FREQ / 2 / DTMF_DOLPHIN_HAL_DMA_PRESCALER /
|
||||
(DTMF_DOLPHIN_HAL_DMA_AUTORELOAD + 1);
|
||||
|
||||
// Using a constant scaling modifier, which likely represents
|
||||
// the combined system overhead and isr latency.
|
||||
return (uint16_t) dma_rate * 2 / freq * 0.801923;
|
||||
return (uint16_t)dma_rate * 2 / freq * 0.801923;
|
||||
}
|
||||
|
||||
void osc_generate_lookup_table(DTMFDolphinOsc* osc, float freq) {
|
||||
if (osc->lookup_table != NULL) {
|
||||
if(osc->lookup_table != NULL) {
|
||||
free(osc->lookup_table);
|
||||
}
|
||||
osc->offset = 0;
|
||||
osc->cached_freq = freq;
|
||||
osc->period = calc_waveform_period(freq);
|
||||
if (!osc->period) {
|
||||
if(!osc->period) {
|
||||
osc->lookup_table = NULL;
|
||||
return;
|
||||
}
|
||||
osc->lookup_table = malloc(sizeof(float) * osc->period);
|
||||
|
||||
for (size_t i = 0; i < osc->period; i++) {
|
||||
for(size_t i = 0; i < osc->period; i++) {
|
||||
osc->lookup_table[i] = sin(i * PERIOD_2_PI / osc->period) + 1;
|
||||
}
|
||||
}
|
||||
@@ -85,7 +83,7 @@ void osc_generate_lookup_table(DTMFDolphinOsc* osc, float freq) {
|
||||
float sample_frame(DTMFDolphinOsc* osc) {
|
||||
float frame = 0.0;
|
||||
|
||||
if (osc->period) {
|
||||
if(osc->period) {
|
||||
frame = osc->lookup_table[osc->offset];
|
||||
osc->offset = (osc->offset + 1) % osc->period;
|
||||
}
|
||||
@@ -103,7 +101,7 @@ void dtmf_dolphin_audio_free(DTMFDolphinAudio* player) {
|
||||
}
|
||||
|
||||
void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) {
|
||||
if (osc->lookup_table != NULL) {
|
||||
if(osc->lookup_table != NULL) {
|
||||
free(osc->lookup_table);
|
||||
}
|
||||
free(osc);
|
||||
@@ -112,18 +110,16 @@ void dtmf_dolphin_osc_free(DTMFDolphinOsc* osc) {
|
||||
bool generate_waveform(DTMFDolphinAudio* player, uint16_t buffer_index) {
|
||||
uint16_t* sample_buffer_start = &player->sample_buffer[buffer_index];
|
||||
|
||||
for (size_t i = 0; i < player->half_buffer_length; i++) {
|
||||
for(size_t i = 0; i < player->half_buffer_length; i++) {
|
||||
float data = 0;
|
||||
if (player->osc2->period) {
|
||||
data = \
|
||||
(sample_frame(player->osc1) / 2) + \
|
||||
(sample_frame(player->osc2) / 2);
|
||||
if(player->osc2->period) {
|
||||
data = (sample_frame(player->osc1) / 2) + (sample_frame(player->osc2) / 2);
|
||||
} else {
|
||||
data = (sample_frame(player->osc1));
|
||||
}
|
||||
data *= player->volume;
|
||||
data *= UINT8_MAX / 2; // scale -128..127
|
||||
data += UINT8_MAX / 2; // to unsigned
|
||||
data *= UINT8_MAX / 2; // scale -128..127
|
||||
data += UINT8_MAX / 2; // to unsigned
|
||||
|
||||
if(data < 0) {
|
||||
data = 0;
|
||||
@@ -151,7 +147,8 @@ bool dtmf_dolphin_audio_play_tones(float freq1, float freq2) {
|
||||
dtmf_dolphin_speaker_init();
|
||||
dtmf_dolphin_dma_init((uint32_t)current_player->sample_buffer, current_player->buffer_length);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdDma1Ch1, dtmf_dolphin_audio_dma_isr, current_player->queue);
|
||||
|
||||
dtmf_dolphin_dma_start();
|
||||
dtmf_dolphin_speaker_start();
|
||||
@@ -165,20 +162,20 @@ bool dtmf_dolphin_audio_stop_tones() {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
|
||||
|
||||
dtmf_dolphin_audio_free(current_player);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dtmf_dolphin_audio_handle_tick() {
|
||||
bool handled = false;
|
||||
|
||||
if (current_player) {
|
||||
if(current_player) {
|
||||
DTMFDolphinCustomEvent event;
|
||||
if(furi_message_queue_get(current_player->queue, &event, 250) == FuriStatusOk) {
|
||||
if(event.type == DTMFDolphinEventDMAHalfTransfer) {
|
||||
generate_waveform(current_player, 0);
|
||||
handled = true;
|
||||
} else if (event.type == DTMFDolphinEventDMAFullTransfer) {
|
||||
} else if(event.type == DTMFDolphinEventDMAFullTransfer) {
|
||||
generate_waveform(current_player, current_player->half_buffer_length);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ typedef struct {
|
||||
typedef struct {
|
||||
size_t buffer_length;
|
||||
size_t half_buffer_length;
|
||||
uint8_t *buffer_buffer;
|
||||
uint16_t *sample_buffer;
|
||||
uint8_t* buffer_buffer;
|
||||
uint16_t* sample_buffer;
|
||||
float volume;
|
||||
FuriMessageQueue *queue;
|
||||
DTMFDolphinOsc *osc1;
|
||||
DTMFDolphinOsc *osc2;
|
||||
FuriMessageQueue* queue;
|
||||
DTMFDolphinOsc* osc1;
|
||||
DTMFDolphinOsc* osc2;
|
||||
} DTMFDolphinAudio;
|
||||
|
||||
DTMFDolphinOsc* dtmf_dolphin_osc_alloc();
|
||||
|
||||
@@ -7,13 +7,13 @@ typedef struct {
|
||||
} DTMFDolphinTonePos;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char* name;
|
||||
const float frequency_1;
|
||||
const float frequency_2;
|
||||
const DTMFDolphinTonePos pos;
|
||||
const uint16_t pulses; // for Redbox
|
||||
const uint16_t pulse_ms; // for Redbox
|
||||
const uint16_t gap_duration; // for Redbox
|
||||
const uint16_t pulses; // for Redbox
|
||||
const uint16_t pulse_ms; // for Redbox
|
||||
const uint16_t gap_duration; // for Redbox
|
||||
} DTMFDolphinTones;
|
||||
|
||||
typedef struct {
|
||||
@@ -44,41 +44,38 @@ DTMFDolphinSceneData DTMFDolphinSceneDataDialer = {
|
||||
{"0", 941.0, 1336.0, {3, 1, 1}, 0, 0, 0},
|
||||
{"#", 941.0, 1477.0, {3, 2, 1}, 0, 0, 0},
|
||||
{"D", 941.0, 1633.0, {3, 3, 1}, 0, 0, 0},
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
DTMFDolphinSceneData DTMFDolphinSceneDataBluebox = {
|
||||
.name = "Bluebox",
|
||||
.block = DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX,
|
||||
.tone_count = 13,
|
||||
.tones = {
|
||||
{"1", 700.0, 900.0, {0, 0, 1}, 0, 0, 0},
|
||||
{"2", 700.0, 1100.0, {0, 1, 1}, 0, 0, 0},
|
||||
{"3", 900.0, 1100.0, {0, 2, 1}, 0, 0, 0},
|
||||
{"4", 700.0, 1300.0, {1, 0, 1}, 0, 0, 0},
|
||||
{"5", 900.0, 1300.0, {1, 1, 1}, 0, 0, 0},
|
||||
{"6", 1100.0, 1300.0, {1, 2, 1}, 0, 0, 0},
|
||||
{"7", 700.0, 1500.0, {2, 0, 1}, 0, 0, 0},
|
||||
{"8", 900.0, 1500.0, {2, 1, 1}, 0, 0, 0},
|
||||
{"9", 1100.0, 1500.0, {2, 2, 1}, 0, 0, 0},
|
||||
{"0", 1300.0, 1500.0, {3, 1, 1}, 0, 0, 0},
|
||||
{"KP", 1100.0, 1700.0, {0, 3, 2}, 0, 0, 0},
|
||||
{"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0},
|
||||
{"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0},
|
||||
}
|
||||
};
|
||||
{"1", 700.0, 900.0, {0, 0, 1}, 0, 0, 0},
|
||||
{"2", 700.0, 1100.0, {0, 1, 1}, 0, 0, 0},
|
||||
{"3", 900.0, 1100.0, {0, 2, 1}, 0, 0, 0},
|
||||
{"4", 700.0, 1300.0, {1, 0, 1}, 0, 0, 0},
|
||||
{"5", 900.0, 1300.0, {1, 1, 1}, 0, 0, 0},
|
||||
{"6", 1100.0, 1300.0, {1, 2, 1}, 0, 0, 0},
|
||||
{"7", 700.0, 1500.0, {2, 0, 1}, 0, 0, 0},
|
||||
{"8", 900.0, 1500.0, {2, 1, 1}, 0, 0, 0},
|
||||
{"9", 1100.0, 1500.0, {2, 2, 1}, 0, 0, 0},
|
||||
{"0", 1300.0, 1500.0, {3, 1, 1}, 0, 0, 0},
|
||||
{"KP", 1100.0, 1700.0, {0, 3, 2}, 0, 0, 0},
|
||||
{"ST", 1500.0, 1700.0, {1, 3, 2}, 0, 0, 0},
|
||||
{"2600", 2600.0, 0.0, {3, 2, 3}, 0, 0, 0},
|
||||
}};
|
||||
|
||||
DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUS = {
|
||||
.name = "Redbox (US)",
|
||||
.block = DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US,
|
||||
.tone_count = 4,
|
||||
.tones = {
|
||||
{"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0},
|
||||
{"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66},
|
||||
{"Nickel", 1700.0, 2200.0, {0, 0, 5}, 1, 66, 0},
|
||||
{"Dime", 1700.0, 2200.0, {1, 0, 5}, 2, 66, 66},
|
||||
{"Quarter", 1700.0, 2200.0, {2, 0, 5}, 5, 33, 33},
|
||||
{"Dollar", 1700.0, 2200.0, {3, 0, 5}, 1, 650, 0},
|
||||
}
|
||||
};
|
||||
{"Dollar", 1700.0, 2200.0, {3, 0, 5}, 1, 650, 0},
|
||||
}};
|
||||
|
||||
DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = {
|
||||
.name = "Redbox (UK)",
|
||||
@@ -87,28 +84,25 @@ DTMFDolphinSceneData DTMFDolphinSceneDataRedboxUK = {
|
||||
.tones = {
|
||||
{"10p", 1000.0, 0.0, {0, 0, 3}, 1, 200, 0},
|
||||
{"50p", 1000.0, 0.0, {1, 0, 3}, 1, 350, 0},
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
DTMFDolphinSceneData DTMFDolphinSceneDataMisc = {
|
||||
.name = "Misc",
|
||||
.block = DTMF_DOLPHIN_TONE_BLOCK_MISC,
|
||||
.tone_count = 3,
|
||||
.tones = {
|
||||
{"CCITT 11", 700.0, 1700.0, {0, 0, 5}, 0, 0, 0},
|
||||
{"CCITT 12", 900.0, 1700.0, {1, 0, 5}, 0, 0, 0},
|
||||
{"CCITT 11", 700.0, 1700.0, {0, 0, 5}, 0, 0, 0},
|
||||
{"CCITT 12", 900.0, 1700.0, {1, 0, 5}, 0, 0, 0},
|
||||
{"CCITT KP2", 1300.0, 1700.0, {2, 0, 5}, 0, 0, 0},
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
DTMFDolphinToneSection current_section;
|
||||
DTMFDolphinSceneData *current_scene_data;
|
||||
DTMFDolphinSceneData* current_scene_data;
|
||||
|
||||
void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section) {
|
||||
current_section = section;
|
||||
|
||||
switch (current_section)
|
||||
{
|
||||
switch(current_section) {
|
||||
case DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX:
|
||||
current_scene_data = &DTMFDolphinSceneDataBluebox;
|
||||
break;
|
||||
@@ -131,14 +125,14 @@ DTMFDolphinToneSection dtmf_dolphin_data_get_current_section() {
|
||||
return current_section;
|
||||
}
|
||||
|
||||
DTMFDolphinSceneData *dtmf_dolphin_data_get_current_scene_data() {
|
||||
DTMFDolphinSceneData* dtmf_dolphin_data_get_current_scene_data() {
|
||||
return current_scene_data;
|
||||
}
|
||||
|
||||
bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t row, uint8_t col) {
|
||||
for (size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col) {
|
||||
for(size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
DTMFDolphinTones tones = current_scene_data->tones[i];
|
||||
if (tones.pos.row == row && tones.pos.col == col) {
|
||||
if(tones.pos.row == row && tones.pos.col == col) {
|
||||
freq1[0] = tones.frequency_1;
|
||||
freq2[0] = tones.frequency_2;
|
||||
return true;
|
||||
@@ -148,9 +142,9 @@ bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t
|
||||
}
|
||||
|
||||
const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) {
|
||||
for (size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
for(size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
DTMFDolphinTones tones = current_scene_data->tones[i];
|
||||
if (tones.pos.row == row && tones.pos.col == col) {
|
||||
if(tones.pos.row == row && tones.pos.col == col) {
|
||||
return tones.name;
|
||||
}
|
||||
}
|
||||
@@ -158,7 +152,7 @@ const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col) {
|
||||
}
|
||||
|
||||
const char* dtmf_dolphin_data_get_current_section_name() {
|
||||
if (current_scene_data) {
|
||||
if(current_scene_data) {
|
||||
return current_scene_data->name;
|
||||
}
|
||||
return NULL;
|
||||
@@ -168,27 +162,26 @@ void dtmf_dolphin_tone_get_max_pos(uint8_t* max_rows, uint8_t* max_cols, uint8_t
|
||||
max_rows[0] = 0;
|
||||
max_cols[0] = 0;
|
||||
max_span[0] = 0;
|
||||
uint8_t tmp_rowspan[5] = { 0, 0, 0, 0, 0 };
|
||||
for (size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
uint8_t tmp_rowspan[5] = {0, 0, 0, 0, 0};
|
||||
for(size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
DTMFDolphinTones tones = current_scene_data->tones[i];
|
||||
if (tones.pos.row > max_rows[0]) {
|
||||
if(tones.pos.row > max_rows[0]) {
|
||||
max_rows[0] = tones.pos.row;
|
||||
}
|
||||
if (tones.pos.col > max_cols[0]) {
|
||||
if(tones.pos.col > max_cols[0]) {
|
||||
max_cols[0] = tones.pos.col;
|
||||
}
|
||||
tmp_rowspan[tones.pos.row] += tones.pos.span;
|
||||
if (tmp_rowspan[tones.pos.row] > max_span[0])
|
||||
max_span[0] = tmp_rowspan[tones.pos.row];
|
||||
if(tmp_rowspan[tones.pos.row] > max_span[0]) max_span[0] = tmp_rowspan[tones.pos.row];
|
||||
}
|
||||
max_rows[0]++;
|
||||
max_cols[0]++;
|
||||
}
|
||||
|
||||
uint8_t dtmf_dolphin_get_tone_span(uint8_t row, uint8_t col) {
|
||||
for (size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
for(size_t i = 0; i < current_scene_data->tone_count; i++) {
|
||||
DTMFDolphinTones tones = current_scene_data->tones[i];
|
||||
if (tones.pos.row == row && tones.pos.col == col) {
|
||||
if(tones.pos.row == row && tones.pos.col == col) {
|
||||
return tones.pos.span;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ void dtmf_dolphin_data_set_current_section(DTMFDolphinToneSection section);
|
||||
|
||||
DTMFDolphinToneSection dtmf_dolphin_data_get_current_section();
|
||||
|
||||
bool dtmf_dolphin_data_get_tone_frequencies(float *freq1, float *freq2, uint8_t row, uint8_t col);
|
||||
bool dtmf_dolphin_data_get_tone_frequencies(float* freq1, float* freq2, uint8_t row, uint8_t col);
|
||||
|
||||
const char* dtmf_dolphin_data_get_tone_name(uint8_t row, uint8_t col);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#define TAG "DTMFDolphin"
|
||||
|
||||
|
||||
enum DTMFDolphinSceneState {
|
||||
DTMFDolphinSceneStateDialer,
|
||||
DTMFDolphinSceneStateBluebox,
|
||||
@@ -39,7 +38,4 @@ typedef struct {
|
||||
NotificationApp* notification;
|
||||
} DTMFDolphinApp;
|
||||
|
||||
typedef enum {
|
||||
DTMFDolphinViewMainMenu,
|
||||
DTMFDolphinViewDialer
|
||||
} DTMFDolphinView;
|
||||
typedef enum { DTMFDolphinViewMainMenu, DTMFDolphinViewDialer } DTMFDolphinView;
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
// #include "../dtmf_dolphin_data.h"
|
||||
// #include "../dtmf_dolphin_audio.h"
|
||||
|
||||
|
||||
void dtmf_dolphin_scene_dialer_on_enter(void *context) {
|
||||
void dtmf_dolphin_scene_dialer_on_enter(void* context) {
|
||||
DTMFDolphinApp* app = context;
|
||||
DTMFDolphinScene scene_id = DTMFDolphinSceneDialer;
|
||||
enum DTMFDolphinSceneState state = scene_manager_get_scene_state(app->scene_manager, scene_id);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
switch(state) {
|
||||
case DTMFDolphinSceneStateBluebox:
|
||||
dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_BLUEBOX);
|
||||
break;
|
||||
break;
|
||||
case DTMFDolphinSceneStateRedboxUS:
|
||||
dtmf_dolphin_data_set_current_section(DTMF_DOLPHIN_TONE_BLOCK_REDBOX_US);
|
||||
break;
|
||||
|
||||
@@ -2,16 +2,10 @@
|
||||
|
||||
static void dtmf_dolphin_scene_start_main_menu_enter_callback(void* context, uint32_t index) {
|
||||
DTMFDolphinApp* app = context;
|
||||
if (index == DTMFDolphinSceneStateDialer) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher,
|
||||
DTMFDolphinEventStartDialer
|
||||
);
|
||||
} else if (index == DTMFDolphinSceneStateBluebox) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher,
|
||||
DTMFDolphinEventStartBluebox
|
||||
);
|
||||
if(index == DTMFDolphinSceneStateDialer) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DTMFDolphinEventStartDialer);
|
||||
} else if(index == DTMFDolphinSceneStateBluebox) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, DTMFDolphinEventStartBluebox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,21 +15,16 @@ void dtmf_dolphin_scene_start_on_enter(void* context) {
|
||||
|
||||
// VariableItem* item;
|
||||
variable_item_list_set_enter_callback(
|
||||
var_item_list,
|
||||
dtmf_dolphin_scene_start_main_menu_enter_callback,
|
||||
app);
|
||||
var_item_list, dtmf_dolphin_scene_start_main_menu_enter_callback, app);
|
||||
|
||||
variable_item_list_add(var_item_list, "Dialer", 0, NULL, NULL);
|
||||
variable_item_list_add(var_item_list, "Bluebox", 0, NULL, NULL);
|
||||
variable_item_list_add(var_item_list, "Misc", 0, NULL, NULL);
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
var_item_list,
|
||||
scene_manager_get_scene_state(app->scene_manager, DTMFDolphinSceneStart));
|
||||
var_item_list, scene_manager_get_scene_state(app->scene_manager, DTMFDolphinSceneStart));
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
app->view_dispatcher,
|
||||
DTMFDolphinViewMainMenu);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DTMFDolphinViewMainMenu);
|
||||
}
|
||||
|
||||
bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
@@ -44,14 +33,17 @@ bool dtmf_dolphin_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if (event.event == DTMFDolphinEventStartDialer) {
|
||||
scene_manager_set_scene_state(app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateDialer);
|
||||
if(event.event == DTMFDolphinEventStartDialer) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateDialer);
|
||||
scene_manager_next_scene(app->scene_manager, DTMFDolphinSceneDialer);
|
||||
} else if (event.event == DTMFDolphinEventStartBluebox) {
|
||||
scene_manager_set_scene_state(app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateBluebox);
|
||||
} else if(event.event == DTMFDolphinEventStartBluebox) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateBluebox);
|
||||
scene_manager_next_scene(app->scene_manager, DTMFDolphinSceneDialer);
|
||||
} else if (event.event == DTMFDolphinEventStartMisc) {
|
||||
scene_manager_set_scene_state(app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateMisc);
|
||||
} else if(event.event == DTMFDolphinEventStartMisc) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DTMFDolphinSceneDialer, DTMFDolphinSceneStateMisc);
|
||||
scene_manager_next_scene(app->scene_manager, DTMFDolphinSceneDialer);
|
||||
}
|
||||
consumed = true;
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
#define DTMF_DOLPHIN_NUMPAD_Y 14
|
||||
#define DTMF_DOLPHIN_BUTTON_WIDTH 13
|
||||
#define DTMF_DOLPHIN_BUTTON_HEIGHT 13
|
||||
#define DTMF_DOLPHIN_BUTTON_PADDING 1 // all sides
|
||||
#define DTMF_DOLPHIN_BUTTON_PADDING 1 // all sides
|
||||
|
||||
@@ -21,53 +21,55 @@ static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_diale
|
||||
static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dialer);
|
||||
static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dialer);
|
||||
static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_dialer);
|
||||
static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event);
|
||||
static bool
|
||||
dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event);
|
||||
|
||||
void draw_button(Canvas* canvas, uint8_t row, uint8_t col, bool invert) {
|
||||
|
||||
uint8_t left = DTMF_DOLPHIN_NUMPAD_X + \
|
||||
// ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
|
||||
(col * DTMF_DOLPHIN_BUTTON_WIDTH);
|
||||
// (col * DTMF_DOLPHIN_BUTTON_PADDING);
|
||||
uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + \
|
||||
// ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
|
||||
(row * DTMF_DOLPHIN_BUTTON_HEIGHT);
|
||||
// (row * DTMF_DOLPHIN_BUTTON_PADDING);
|
||||
uint8_t left = DTMF_DOLPHIN_NUMPAD_X + // ((col + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
|
||||
(col * DTMF_DOLPHIN_BUTTON_WIDTH);
|
||||
// (col * DTMF_DOLPHIN_BUTTON_PADDING);
|
||||
uint8_t top = DTMF_DOLPHIN_NUMPAD_Y + // ((row + 1) * DTMF_DOLPHIN_BUTTON_PADDING) +
|
||||
(row * DTMF_DOLPHIN_BUTTON_HEIGHT);
|
||||
// (row * DTMF_DOLPHIN_BUTTON_PADDING);
|
||||
|
||||
uint8_t span = dtmf_dolphin_get_tone_span(row, col);
|
||||
|
||||
if (span == 0) {
|
||||
if(span == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if (invert)
|
||||
canvas_draw_rbox(canvas, left, top,
|
||||
|
||||
if(invert)
|
||||
canvas_draw_rbox(
|
||||
canvas,
|
||||
left,
|
||||
top,
|
||||
(DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
|
||||
DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
|
||||
2);
|
||||
else
|
||||
canvas_draw_rframe(canvas, left, top,
|
||||
canvas_draw_rframe(
|
||||
canvas,
|
||||
left,
|
||||
top,
|
||||
(DTMF_DOLPHIN_BUTTON_WIDTH * span) - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
|
||||
DTMF_DOLPHIN_BUTTON_HEIGHT- (DTMF_DOLPHIN_BUTTON_PADDING * 2),
|
||||
DTMF_DOLPHIN_BUTTON_HEIGHT - (DTMF_DOLPHIN_BUTTON_PADDING * 2),
|
||||
2);
|
||||
|
||||
if (invert)
|
||||
canvas_invert_color(canvas);
|
||||
|
||||
if(invert) canvas_invert_color(canvas);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
// canvas_set_color(canvas, invert ? ColorWhite : ColorBlack);
|
||||
canvas_draw_str_aligned(canvas,
|
||||
left - 1 + (int) ((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2),
|
||||
top + (int) (DTMF_DOLPHIN_BUTTON_HEIGHT / 2),
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
left - 1 + (int)((DTMF_DOLPHIN_BUTTON_WIDTH * span) / 2),
|
||||
top + (int)(DTMF_DOLPHIN_BUTTON_HEIGHT / 2),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
dtmf_dolphin_data_get_tone_name(row, col));
|
||||
|
||||
if (invert)
|
||||
canvas_invert_color(canvas);
|
||||
if(invert) canvas_invert_color(canvas);
|
||||
}
|
||||
|
||||
void draw_dialer(Canvas* canvas, void* _model) {
|
||||
@@ -79,9 +81,9 @@ void draw_dialer(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
for (int r = 0; r < max_rows; r++) {
|
||||
for (int c = 0; c < max_cols; c++) {
|
||||
if (model->row == r && model->col == c)
|
||||
for(int r = 0; r < max_rows; r++) {
|
||||
for(int c = 0; c < max_cols; c++) {
|
||||
if(model->row == r && model->col == c)
|
||||
draw_button(canvas, r, c, true);
|
||||
else
|
||||
draw_button(canvas, r, c, false);
|
||||
@@ -89,20 +91,20 @@ void draw_dialer(Canvas* canvas, void* _model) {
|
||||
}
|
||||
}
|
||||
|
||||
void update_frequencies(DTMFDolphinDialerModel *model) {
|
||||
void update_frequencies(DTMFDolphinDialerModel* model) {
|
||||
dtmf_dolphin_data_get_tone_frequencies(&model->freq1, &model->freq2, model->row, model->col);
|
||||
}
|
||||
|
||||
static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
|
||||
DTMFDolphinDialerModel* model = _model;
|
||||
if (model->playing) {
|
||||
if(model->playing) {
|
||||
// Leverage the prioritized draw callback to handle
|
||||
// the DMA so that it doesn't skip.
|
||||
dtmf_dolphin_audio_handle_tick();
|
||||
// Don't do any drawing if audio is playing.
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas,
|
||||
canvas,
|
||||
canvas_width(canvas) / 2,
|
||||
canvas_height(canvas) / 2,
|
||||
AlignCenter,
|
||||
@@ -118,11 +120,15 @@ static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text(canvas, 2, 10, dtmf_dolphin_data_get_current_section_name());
|
||||
canvas_draw_line(canvas,
|
||||
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, 0,
|
||||
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1, canvas_height(canvas));
|
||||
canvas_draw_line(
|
||||
canvas,
|
||||
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1,
|
||||
0,
|
||||
(max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 1,
|
||||
canvas_height(canvas));
|
||||
elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 10, "Detail");
|
||||
canvas_draw_line(canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3);
|
||||
canvas_draw_line(
|
||||
canvas, 0, DTMF_DOLPHIN_NUMPAD_Y - 3, canvas_width(canvas), DTMF_DOLPHIN_NUMPAD_Y - 3);
|
||||
// elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Dialer Mode");
|
||||
|
||||
draw_dialer(canvas, model);
|
||||
@@ -130,22 +136,20 @@ static void dtmf_dolphin_dialer_draw_callback(Canvas* canvas, void* _model) {
|
||||
string_t output;
|
||||
string_init(output);
|
||||
|
||||
if (model->freq1 && model->freq2) {
|
||||
if(model->freq1 && model->freq2) {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Dual Tone\nF1: %u Hz\nF2: %u Hz\n",
|
||||
(unsigned int) model->freq1,
|
||||
(unsigned int) model->freq2);
|
||||
} else if (model->freq1) {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Single Tone\nF: %u Hz\n",
|
||||
(unsigned int) model->freq1);
|
||||
(unsigned int)model->freq1,
|
||||
(unsigned int)model->freq2);
|
||||
} else if(model->freq1) {
|
||||
string_cat_printf(output, "Single Tone\nF: %u Hz\n", (unsigned int)model->freq1);
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
elements_multiline_text(canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, string_get_cstr(output));
|
||||
elements_multiline_text(
|
||||
canvas, (max_span * DTMF_DOLPHIN_BUTTON_WIDTH) + 4, 21, string_get_cstr(output));
|
||||
|
||||
string_clear(output);
|
||||
}
|
||||
@@ -178,11 +182,11 @@ static bool dtmf_dolphin_dialer_process_up(DTMFDolphinDialer* dtmf_dolphin_diale
|
||||
dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
|
||||
uint8_t span = 0;
|
||||
uint8_t cursor = model->row;
|
||||
while (span == 0 && cursor > 0) {
|
||||
while(span == 0 && cursor > 0) {
|
||||
cursor--;
|
||||
span = dtmf_dolphin_get_tone_span(cursor, model->col);
|
||||
}
|
||||
if (span != 0) {
|
||||
if(span != 0) {
|
||||
model->row = cursor;
|
||||
}
|
||||
return true;
|
||||
@@ -204,7 +208,7 @@ static bool dtmf_dolphin_dialer_process_down(DTMFDolphinDialer* dtmf_dolphin_dia
|
||||
cursor++;
|
||||
span = dtmf_dolphin_get_tone_span(cursor, model->col);
|
||||
}
|
||||
if (span != 0) {
|
||||
if(span != 0) {
|
||||
model->row = cursor;
|
||||
}
|
||||
return true;
|
||||
@@ -217,11 +221,11 @@ static bool dtmf_dolphin_dialer_process_left(DTMFDolphinDialer* dtmf_dolphin_dia
|
||||
dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
|
||||
uint8_t span = 0;
|
||||
uint8_t cursor = model->col;
|
||||
while (span == 0 && cursor > 0) {
|
||||
while(span == 0 && cursor > 0) {
|
||||
cursor--;
|
||||
span = dtmf_dolphin_get_tone_span(model->row, cursor);
|
||||
}
|
||||
if (span != 0) {
|
||||
if(span != 0) {
|
||||
model->col = cursor;
|
||||
}
|
||||
return true;
|
||||
@@ -243,7 +247,7 @@ static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_di
|
||||
cursor++;
|
||||
span = dtmf_dolphin_get_tone_span(model->row, cursor);
|
||||
}
|
||||
if (span != 0) {
|
||||
if(span != 0) {
|
||||
model->col = cursor;
|
||||
}
|
||||
return true;
|
||||
@@ -251,14 +255,15 @@ static bool dtmf_dolphin_dialer_process_right(DTMFDolphinDialer* dtmf_dolphin_di
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) {
|
||||
static bool
|
||||
dtmf_dolphin_dialer_process_ok(DTMFDolphinDialer* dtmf_dolphin_dialer, InputEvent* event) {
|
||||
bool consumed = false;
|
||||
|
||||
with_view_model(
|
||||
dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
|
||||
if (event->type == InputTypePress) {
|
||||
if(event->type == InputTypePress) {
|
||||
model->playing = dtmf_dolphin_audio_play_tones(model->freq1, model->freq2);
|
||||
} else if (event->type == InputTypeRelease) {
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
model->playing = !dtmf_dolphin_audio_stop_tones();
|
||||
}
|
||||
|
||||
@@ -281,15 +286,15 @@ static void dtmf_dolphin_dialer_enter_callback(void* context) {
|
||||
model->freq2 = 0.0;
|
||||
model->playing = false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() {
|
||||
DTMFDolphinDialer* dtmf_dolphin_dialer = malloc(sizeof(DTMFDolphinDialer));
|
||||
|
||||
dtmf_dolphin_dialer->view = view_alloc();
|
||||
view_allocate_model(dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel));
|
||||
view_allocate_model(
|
||||
dtmf_dolphin_dialer->view, ViewModelTypeLocking, sizeof(DTMFDolphinDialerModel));
|
||||
|
||||
with_view_model(
|
||||
dtmf_dolphin_dialer->view, (DTMFDolphinDialerModel * model) {
|
||||
@@ -300,8 +305,7 @@ DTMFDolphinDialer* dtmf_dolphin_dialer_alloc() {
|
||||
model->freq2 = 0.0;
|
||||
model->playing = false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
view_set_context(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer);
|
||||
view_set_draw_callback(dtmf_dolphin_dialer->view, dtmf_dolphin_dialer_draw_callback);
|
||||
@@ -320,4 +324,3 @@ View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer) {
|
||||
furi_assert(dtmf_dolphin_dialer);
|
||||
return dtmf_dolphin_dialer->view;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,4 +12,7 @@ void dtmf_dolphin_dialer_free(DTMFDolphinDialer* dtmf_dolphin_dialer);
|
||||
|
||||
View* dtmf_dolphin_dialer_get_view(DTMFDolphinDialer* dtmf_dolphin_dialer);
|
||||
|
||||
void dtmf_dolphin_dialer_set_ok_callback(DTMFDolphinDialer* dtmf_dolphin_dialer, DTMFDolphinDialerOkCallback callback, void* context);
|
||||
void dtmf_dolphin_dialer_set_ok_callback(
|
||||
DTMFDolphinDialer* dtmf_dolphin_dialer,
|
||||
DTMFDolphinDialerOkCallback callback,
|
||||
void* context);
|
||||
|
||||
@@ -14,7 +14,7 @@ void elements_button_top_left(Canvas* canvas, const char* str) {
|
||||
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
|
||||
|
||||
const uint8_t x = 0;
|
||||
const uint8_t y = 0 + button_height;
|
||||
const uint8_t y = 0 + button_height;
|
||||
|
||||
canvas_draw_box(canvas, x, y - button_height, button_width, button_height);
|
||||
canvas_draw_line(canvas, x + button_width + 0, y - button_height, x + button_width + 0, y - 1);
|
||||
@@ -44,8 +44,8 @@ void elements_button_top_right(Canvas* canvas, const char* str) {
|
||||
|
||||
canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height);
|
||||
canvas_draw_line(canvas, x - button_width - 1, y - button_height, x - button_width - 1, y - 1);
|
||||
canvas_draw_line(canvas, x - button_width - 2, y - button_height, x - button_width - 2, y - 2);
|
||||
canvas_draw_line(canvas, x - button_width - 3, y - button_height, x - button_width - 3, y - 3);
|
||||
canvas_draw_line(canvas, x - button_width - 2, y - button_height, x - button_width - 2, y - 2);
|
||||
canvas_draw_line(canvas, x - button_width - 3, y - button_height, x - button_width - 3, y - 3);
|
||||
|
||||
canvas_invert_color(canvas);
|
||||
canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str);
|
||||
|
||||
@@ -21,351 +21,363 @@
|
||||
|
||||
#define wave_bitmap_left_width 4
|
||||
#define wave_bitmap_left_height 14
|
||||
static uint8_t wave_bitmap_left_bits[] = {
|
||||
0x08, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06,
|
||||
0x0C, 0x08
|
||||
};
|
||||
static uint8_t wave_bitmap_left_bits[] =
|
||||
{0x08, 0x0C, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x0C, 0x08};
|
||||
|
||||
#define wave_bitmap_right_width 4
|
||||
#define wave_bitmap_right_height 14
|
||||
static uint8_t wave_bitmap_right_bits[] = {
|
||||
0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06,
|
||||
0x03, 0x01
|
||||
};
|
||||
static uint8_t wave_bitmap_right_bits[] =
|
||||
{0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0x01};
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
EventType type;
|
||||
InputEvent input;
|
||||
EventType type;
|
||||
InputEvent input;
|
||||
} PluginEvent;
|
||||
|
||||
enum OutputMode {
|
||||
Loud,
|
||||
Vibro,
|
||||
Silent
|
||||
};
|
||||
enum OutputMode { Loud, Vibro, Silent };
|
||||
|
||||
typedef struct {
|
||||
double bpm;
|
||||
bool playing;
|
||||
int beats_per_bar;
|
||||
int note_length;
|
||||
int current_beat;
|
||||
enum OutputMode output_mode;
|
||||
FuriTimer* timer;
|
||||
NotificationApp* notifications;
|
||||
double bpm;
|
||||
bool playing;
|
||||
int beats_per_bar;
|
||||
int note_length;
|
||||
int current_beat;
|
||||
enum OutputMode output_mode;
|
||||
FuriTimer* timer;
|
||||
NotificationApp* notifications;
|
||||
} MetronomeState;
|
||||
|
||||
static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
const MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
if(metronome_state == NULL) {
|
||||
return;
|
||||
}
|
||||
const MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
if(metronome_state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
string_t tempStr;
|
||||
string_init(tempStr);
|
||||
string_t tempStr;
|
||||
string_init(tempStr);
|
||||
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
// draw bars/beat
|
||||
string_printf(tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length);
|
||||
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
// draw BPM value
|
||||
string_printf(tempStr, "%.2f", metronome_state->bpm);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignCenter, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
// draw bars/beat
|
||||
string_printf(tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length);
|
||||
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
|
||||
// draw volume indicator
|
||||
// always draw first waves
|
||||
canvas_draw_xbm(canvas, 20, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(canvas, canvas_width(canvas)-20-wave_bitmap_right_width, 17, wave_bitmap_right_width, wave_bitmap_right_height, wave_bitmap_right_bits);
|
||||
if (metronome_state->output_mode < Silent) {
|
||||
canvas_draw_xbm(canvas, 16, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(canvas, canvas_width(canvas)-16-wave_bitmap_right_width, 17, wave_bitmap_right_width, wave_bitmap_right_height, wave_bitmap_right_bits);
|
||||
}
|
||||
if (metronome_state->output_mode < Vibro) {
|
||||
canvas_draw_xbm(canvas, 12, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(canvas, canvas_width(canvas)-12-wave_bitmap_right_width, 17, wave_bitmap_right_width, wave_bitmap_right_height, wave_bitmap_right_bits);
|
||||
}
|
||||
// draw button prompts
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_left(canvas, "Slow");
|
||||
elements_button_right(canvas, "Fast");
|
||||
if (metronome_state->playing) {
|
||||
elements_button_center(canvas, "Stop ");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
}
|
||||
elements_button_top_left(canvas, "Push");
|
||||
elements_button_top_right(canvas, "Hold");
|
||||
// draw BPM value
|
||||
string_printf(tempStr, "%.2f", metronome_state->bpm);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignCenter, string_get_cstr(tempStr));
|
||||
string_reset(tempStr);
|
||||
|
||||
// draw progress bar
|
||||
elements_progress_bar(canvas, 8, 36, 112, (float)metronome_state->current_beat/metronome_state->beats_per_bar);
|
||||
// draw volume indicator
|
||||
// always draw first waves
|
||||
canvas_draw_xbm(
|
||||
canvas, 20, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(
|
||||
canvas,
|
||||
canvas_width(canvas) - 20 - wave_bitmap_right_width,
|
||||
17,
|
||||
wave_bitmap_right_width,
|
||||
wave_bitmap_right_height,
|
||||
wave_bitmap_right_bits);
|
||||
if(metronome_state->output_mode < Silent) {
|
||||
canvas_draw_xbm(
|
||||
canvas, 16, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(
|
||||
canvas,
|
||||
canvas_width(canvas) - 16 - wave_bitmap_right_width,
|
||||
17,
|
||||
wave_bitmap_right_width,
|
||||
wave_bitmap_right_height,
|
||||
wave_bitmap_right_bits);
|
||||
}
|
||||
if(metronome_state->output_mode < Vibro) {
|
||||
canvas_draw_xbm(
|
||||
canvas, 12, 17, wave_bitmap_left_width, wave_bitmap_left_height, wave_bitmap_left_bits);
|
||||
canvas_draw_xbm(
|
||||
canvas,
|
||||
canvas_width(canvas) - 12 - wave_bitmap_right_width,
|
||||
17,
|
||||
wave_bitmap_right_width,
|
||||
wave_bitmap_right_height,
|
||||
wave_bitmap_right_bits);
|
||||
}
|
||||
// draw button prompts
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_left(canvas, "Slow");
|
||||
elements_button_right(canvas, "Fast");
|
||||
if(metronome_state->playing) {
|
||||
elements_button_center(canvas, "Stop ");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
}
|
||||
elements_button_top_left(canvas, "Push");
|
||||
elements_button_top_right(canvas, "Hold");
|
||||
|
||||
// cleanup
|
||||
string_clear(tempStr);
|
||||
release_mutex((ValueMutex*)ctx, metronome_state);
|
||||
// draw progress bar
|
||||
elements_progress_bar(
|
||||
canvas, 8, 36, 112, (float)metronome_state->current_beat / metronome_state->beats_per_bar);
|
||||
|
||||
// cleanup
|
||||
string_clear(tempStr);
|
||||
release_mutex((ValueMutex*)ctx, metronome_state);
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
furi_assert(event_queue);
|
||||
|
||||
PluginEvent event = {.type = EventTypeKey, .input = *input_event};
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
PluginEvent event = {.type = EventTypeKey, .input = *input_event};
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void timer_callback(void* ctx) {
|
||||
// this is where we go BEEP!
|
||||
MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
metronome_state->current_beat++;
|
||||
if (metronome_state->current_beat > metronome_state->beats_per_bar) {
|
||||
metronome_state->current_beat = 1;
|
||||
}
|
||||
if (metronome_state->current_beat == 1) {
|
||||
// pronounced beat
|
||||
notification_message(metronome_state->notifications, &sequence_set_only_red_255);
|
||||
switch(metronome_state->output_mode) {
|
||||
case Loud:
|
||||
furi_hal_speaker_start(440.0f, 1.0f);
|
||||
break;
|
||||
case Vibro:
|
||||
notification_message(metronome_state->notifications, &sequence_set_vibro_on);
|
||||
break;
|
||||
case Silent:
|
||||
break;
|
||||
// this is where we go BEEP!
|
||||
MetronomeState* metronome_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
metronome_state->current_beat++;
|
||||
if(metronome_state->current_beat > metronome_state->beats_per_bar) {
|
||||
metronome_state->current_beat = 1;
|
||||
}
|
||||
} else {
|
||||
// unpronounced beat
|
||||
notification_message(metronome_state->notifications, &sequence_set_only_green_255);
|
||||
switch(metronome_state->output_mode) {
|
||||
case Loud:
|
||||
furi_hal_speaker_start(220.0f, 1.0f);
|
||||
break;
|
||||
case Vibro:
|
||||
notification_message(metronome_state->notifications, &sequence_set_vibro_on);
|
||||
break;
|
||||
case Silent:
|
||||
break;
|
||||
}
|
||||
};
|
||||
if(metronome_state->current_beat == 1) {
|
||||
// pronounced beat
|
||||
notification_message(metronome_state->notifications, &sequence_set_only_red_255);
|
||||
switch(metronome_state->output_mode) {
|
||||
case Loud:
|
||||
furi_hal_speaker_start(440.0f, 1.0f);
|
||||
break;
|
||||
case Vibro:
|
||||
notification_message(metronome_state->notifications, &sequence_set_vibro_on);
|
||||
break;
|
||||
case Silent:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// unpronounced beat
|
||||
notification_message(metronome_state->notifications, &sequence_set_only_green_255);
|
||||
switch(metronome_state->output_mode) {
|
||||
case Loud:
|
||||
furi_hal_speaker_start(220.0f, 1.0f);
|
||||
break;
|
||||
case Vibro:
|
||||
notification_message(metronome_state->notifications, &sequence_set_vibro_on);
|
||||
break;
|
||||
case Silent:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// this is a bit of a kludge... if we are on vibro and unpronounced, stop vibro after half the usual duration
|
||||
switch(metronome_state->output_mode) {
|
||||
// this is a bit of a kludge... if we are on vibro and unpronounced, stop vibro after half the usual duration
|
||||
switch(metronome_state->output_mode) {
|
||||
case Loud:
|
||||
furi_delay_ms(BEEP_DELAY_MS);
|
||||
furi_hal_speaker_stop();
|
||||
break;
|
||||
case Vibro:
|
||||
if (metronome_state->current_beat == 1) {
|
||||
furi_delay_ms(BEEP_DELAY_MS);
|
||||
notification_message(metronome_state->notifications, &sequence_reset_vibro);
|
||||
} else {
|
||||
furi_delay_ms((int)BEEP_DELAY_MS/2);
|
||||
notification_message(metronome_state->notifications, &sequence_reset_vibro);
|
||||
furi_delay_ms((int)BEEP_DELAY_MS/2);
|
||||
}
|
||||
break;
|
||||
furi_hal_speaker_stop();
|
||||
break;
|
||||
case Vibro:
|
||||
if(metronome_state->current_beat == 1) {
|
||||
furi_delay_ms(BEEP_DELAY_MS);
|
||||
notification_message(metronome_state->notifications, &sequence_reset_vibro);
|
||||
} else {
|
||||
furi_delay_ms((int)BEEP_DELAY_MS / 2);
|
||||
notification_message(metronome_state->notifications, &sequence_reset_vibro);
|
||||
furi_delay_ms((int)BEEP_DELAY_MS / 2);
|
||||
}
|
||||
break;
|
||||
case Silent:
|
||||
break;
|
||||
}
|
||||
notification_message(metronome_state->notifications, &sequence_reset_rgb);
|
||||
break;
|
||||
}
|
||||
notification_message(metronome_state->notifications, &sequence_reset_rgb);
|
||||
|
||||
release_mutex((ValueMutex*)ctx, metronome_state);
|
||||
release_mutex((ValueMutex*)ctx, metronome_state);
|
||||
}
|
||||
|
||||
static uint32_t state_to_sleep_ticks(MetronomeState* metronome_state) {
|
||||
// calculate time between beeps
|
||||
uint32_t tps = furi_kernel_get_tick_frequency();
|
||||
double multiplier = 4.0d/metronome_state->note_length;
|
||||
double bps = (double)metronome_state->bpm / 60;
|
||||
return (uint32_t)(round(tps / bps) - ((BEEP_DELAY_MS/1000)*tps)) * multiplier;
|
||||
// calculate time between beeps
|
||||
uint32_t tps = furi_kernel_get_tick_frequency();
|
||||
double multiplier = 4.0d / metronome_state->note_length;
|
||||
double bps = (double)metronome_state->bpm / 60;
|
||||
return (uint32_t)(round(tps / bps) - ((BEEP_DELAY_MS / 1000) * tps)) * multiplier;
|
||||
}
|
||||
|
||||
static void update_timer(MetronomeState* metronome_state) {
|
||||
if (furi_timer_is_running(metronome_state->timer)) {
|
||||
furi_timer_stop(metronome_state->timer);
|
||||
furi_timer_start(
|
||||
metronome_state->timer,
|
||||
state_to_sleep_ticks(metronome_state)
|
||||
);
|
||||
}
|
||||
if(furi_timer_is_running(metronome_state->timer)) {
|
||||
furi_timer_stop(metronome_state->timer);
|
||||
furi_timer_start(metronome_state->timer, state_to_sleep_ticks(metronome_state));
|
||||
}
|
||||
}
|
||||
|
||||
static void increase_bpm(MetronomeState* metronome_state, double amount) {
|
||||
metronome_state->bpm += amount;
|
||||
if(metronome_state->bpm > (double)BPM_BOUNDARY_HIGH) {
|
||||
metronome_state->bpm = BPM_BOUNDARY_HIGH;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
metronome_state->bpm += amount;
|
||||
if(metronome_state->bpm > (double)BPM_BOUNDARY_HIGH) {
|
||||
metronome_state->bpm = BPM_BOUNDARY_HIGH;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
}
|
||||
|
||||
static void decrease_bpm(MetronomeState* metronome_state, double amount) {
|
||||
metronome_state->bpm -= amount;
|
||||
if(metronome_state->bpm < (double)BPM_BOUNDARY_LOW) {
|
||||
metronome_state->bpm = BPM_BOUNDARY_LOW;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
metronome_state->bpm -= amount;
|
||||
if(metronome_state->bpm < (double)BPM_BOUNDARY_LOW) {
|
||||
metronome_state->bpm = BPM_BOUNDARY_LOW;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
}
|
||||
|
||||
static void cycle_beats_per_bar(MetronomeState* metronome_state) {
|
||||
metronome_state->beats_per_bar++;
|
||||
if (metronome_state->beats_per_bar > metronome_state->note_length) {
|
||||
metronome_state->beats_per_bar = 1;
|
||||
}
|
||||
metronome_state->beats_per_bar++;
|
||||
if(metronome_state->beats_per_bar > metronome_state->note_length) {
|
||||
metronome_state->beats_per_bar = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void cycle_note_length(MetronomeState* metronome_state) {
|
||||
metronome_state->note_length *= 2;
|
||||
if (metronome_state->note_length > 16) {
|
||||
metronome_state->note_length = 2;
|
||||
metronome_state->beats_per_bar = 1;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
metronome_state->note_length *= 2;
|
||||
if(metronome_state->note_length > 16) {
|
||||
metronome_state->note_length = 2;
|
||||
metronome_state->beats_per_bar = 1;
|
||||
}
|
||||
update_timer(metronome_state);
|
||||
}
|
||||
|
||||
static void cycle_output_mode(MetronomeState* metronome_state) {
|
||||
metronome_state->output_mode++;
|
||||
if (metronome_state->output_mode > Silent) {
|
||||
metronome_state->output_mode = Loud;
|
||||
if(metronome_state->output_mode > Silent) {
|
||||
metronome_state->output_mode = Loud;
|
||||
}
|
||||
}
|
||||
|
||||
static void metronome_state_init(MetronomeState* const metronome_state) {
|
||||
metronome_state->bpm = 120.0;
|
||||
metronome_state->playing = false;
|
||||
metronome_state->beats_per_bar = 4;
|
||||
metronome_state->note_length = 4;
|
||||
metronome_state->current_beat = 0;
|
||||
metronome_state->output_mode = Loud;
|
||||
metronome_state->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
metronome_state->bpm = 120.0;
|
||||
metronome_state->playing = false;
|
||||
metronome_state->beats_per_bar = 4;
|
||||
metronome_state->note_length = 4;
|
||||
metronome_state->current_beat = 0;
|
||||
metronome_state->output_mode = Loud;
|
||||
metronome_state->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
}
|
||||
|
||||
int32_t metronome_app() {
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
||||
|
||||
MetronomeState* metronome_state = malloc(sizeof(MetronomeState));
|
||||
metronome_state_init(metronome_state);
|
||||
MetronomeState* metronome_state = malloc(sizeof(MetronomeState));
|
||||
metronome_state_init(metronome_state);
|
||||
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, metronome_state, sizeof(MetronomeState))) {
|
||||
FURI_LOG_E("Metronome", "cannot create mutex\r\n");
|
||||
free(metronome_state);
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
metronome_state->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, &state_mutex);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
PluginEvent event;
|
||||
for(bool processing = true; processing;) {
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||
|
||||
MetronomeState* metronome_state = (MetronomeState*)acquire_mutex_block(&state_mutex);
|
||||
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypeShort) {
|
||||
// push events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
cycle_beats_per_bar(metronome_state);
|
||||
break;
|
||||
case InputKeyDown:
|
||||
cycle_output_mode(metronome_state);
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_FINE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_FINE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
metronome_state->playing = !metronome_state->playing;
|
||||
if (metronome_state->playing) {
|
||||
furi_timer_start(metronome_state->timer, state_to_sleep_ticks(metronome_state));
|
||||
} else {
|
||||
furi_timer_stop(metronome_state->timer);
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
} else if (event.input.type == InputTypeLong) {
|
||||
// hold events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
cycle_note_length(metronome_state);
|
||||
break;
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
} else if (event.input.type == InputTypeRepeat) {
|
||||
// repeat events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("Metronome", "FuriMessageQueue: event timeout");
|
||||
// event timeout
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, metronome_state, sizeof(MetronomeState))) {
|
||||
FURI_LOG_E("Metronome", "cannot create mutex\r\n");
|
||||
free(metronome_state);
|
||||
return 255;
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
release_mutex(&state_mutex, metronome_state);
|
||||
}
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
metronome_state->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, &state_mutex);
|
||||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
furi_timer_free(metronome_state->timer);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
free(metronome_state);
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
return 0;
|
||||
PluginEvent event;
|
||||
for(bool processing = true; processing;) {
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||
|
||||
MetronomeState* metronome_state = (MetronomeState*)acquire_mutex_block(&state_mutex);
|
||||
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypeShort) {
|
||||
// push events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
cycle_beats_per_bar(metronome_state);
|
||||
break;
|
||||
case InputKeyDown:
|
||||
cycle_output_mode(metronome_state);
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_FINE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_FINE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
metronome_state->playing = !metronome_state->playing;
|
||||
if(metronome_state->playing) {
|
||||
furi_timer_start(
|
||||
metronome_state->timer, state_to_sleep_ticks(metronome_state));
|
||||
} else {
|
||||
furi_timer_stop(metronome_state->timer);
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
} else if(event.input.type == InputTypeLong) {
|
||||
// hold events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
cycle_note_length(metronome_state);
|
||||
break;
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
} else if(event.input.type == InputTypeRepeat) {
|
||||
// repeat events
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyRight:
|
||||
increase_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
decrease_bpm(metronome_state, BPM_STEP_SIZE_COARSE);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_D("Metronome", "FuriMessageQueue: event timeout");
|
||||
// event timeout
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
release_mutex(&state_mutex, metronome_state);
|
||||
}
|
||||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close("gui");
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
delete_mutex(&state_mutex);
|
||||
furi_timer_free(metronome_state->timer);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
free(metronome_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1649
-1525
File diff suppressed because it is too large
Load Diff
@@ -22,16 +22,16 @@
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#define MEMORY_SIZE 4096 // 4096 x 4 bits (640 x 4 bits of RAM)
|
||||
#define MEMORY_SIZE 4096 // 4096 x 4 bits (640 x 4 bits of RAM)
|
||||
|
||||
#define MEM_RAM_ADDR 0x000
|
||||
#define MEM_RAM_SIZE 0x280
|
||||
#define MEM_DISPLAY1_ADDR 0xE00
|
||||
#define MEM_DISPLAY1_SIZE 0x050
|
||||
#define MEM_DISPLAY2_ADDR 0xE80
|
||||
#define MEM_DISPLAY2_SIZE 0x050
|
||||
#define MEM_IO_ADDR 0xF00
|
||||
#define MEM_IO_SIZE 0x080
|
||||
#define MEM_RAM_ADDR 0x000
|
||||
#define MEM_RAM_SIZE 0x280
|
||||
#define MEM_DISPLAY1_ADDR 0xE00
|
||||
#define MEM_DISPLAY1_SIZE 0x050
|
||||
#define MEM_DISPLAY2_ADDR 0xE80
|
||||
#define MEM_DISPLAY2_SIZE 0x050
|
||||
#define MEM_IO_ADDR 0xF00
|
||||
#define MEM_IO_SIZE 0x080
|
||||
|
||||
/* Define this if you want to reduce the footprint of the memory buffer from 4096 u4_t (most likely bytes)
|
||||
* to 464 u8_t (bytes for sure), while increasing slightly the number of operations needed to read/write from/to it.
|
||||
@@ -40,139 +40,162 @@
|
||||
|
||||
#ifdef LOW_FOOTPRINT
|
||||
/* Invalid memory areas are not buffered to reduce the footprint of the library in memory */
|
||||
#define MEM_BUFFER_SIZE (MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE + MEM_IO_SIZE)/2
|
||||
#define MEM_BUFFER_SIZE (MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE + MEM_IO_SIZE) / 2
|
||||
|
||||
/* Maps the CPU memory to the memory buffer */
|
||||
#define RAM_TO_MEMORY(n) ((n - MEM_RAM_ADDR)/2)
|
||||
#define DISP1_TO_MEMORY(n) ((n - MEM_DISPLAY1_ADDR + MEM_RAM_SIZE)/2)
|
||||
#define DISP2_TO_MEMORY(n) ((n - MEM_DISPLAY2_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE)/2)
|
||||
#define IO_TO_MEMORY(n) ((n - MEM_IO_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE)/2)
|
||||
#define RAM_TO_MEMORY(n) ((n - MEM_RAM_ADDR) / 2)
|
||||
#define DISP1_TO_MEMORY(n) ((n - MEM_DISPLAY1_ADDR + MEM_RAM_SIZE) / 2)
|
||||
#define DISP2_TO_MEMORY(n) ((n - MEM_DISPLAY2_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE) / 2)
|
||||
#define IO_TO_MEMORY(n) \
|
||||
((n - MEM_IO_ADDR + MEM_RAM_SIZE + MEM_DISPLAY1_SIZE + MEM_DISPLAY2_SIZE) / 2)
|
||||
|
||||
#define SET_RAM_MEMORY(buffer, n, v) {buffer[RAM_TO_MEMORY(n)] = (buffer[RAM_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | ((v) & 0xF) << (((n) % 2) << 2);}
|
||||
#define SET_DISP1_MEMORY(buffer, n, v) {buffer[DISP1_TO_MEMORY(n)] = (buffer[DISP1_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | ((v) & 0xF) << (((n) % 2) << 2);}
|
||||
#define SET_DISP2_MEMORY(buffer, n, v) {buffer[DISP2_TO_MEMORY(n)] = (buffer[DISP2_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | ((v) & 0xF) << (((n) % 2) << 2);}
|
||||
#define SET_IO_MEMORY(buffer, n, v) {buffer[IO_TO_MEMORY(n)] = (buffer[IO_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | ((v) & 0xF) << (((n) % 2) << 2);}
|
||||
#define SET_MEMORY(buffer, n, v) {if ((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) { \
|
||||
SET_RAM_MEMORY(buffer, n, v); \
|
||||
} else if ((n) < MEM_DISPLAY1_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if ((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { \
|
||||
SET_DISP1_MEMORY(buffer, n, v); \
|
||||
} else if ((n) < MEM_DISPLAY2_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if ((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { \
|
||||
SET_DISP2_MEMORY(buffer, n, v); \
|
||||
} else if ((n) < MEM_IO_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if ((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) { \
|
||||
SET_IO_MEMORY(buffer, n, v); \
|
||||
} else { \
|
||||
/* INVALID_MEMORY */ \
|
||||
}}
|
||||
#define SET_RAM_MEMORY(buffer, n, v) \
|
||||
{ \
|
||||
buffer[RAM_TO_MEMORY(n)] = (buffer[RAM_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \
|
||||
((v)&0xF) << (((n) % 2) << 2); \
|
||||
}
|
||||
#define SET_DISP1_MEMORY(buffer, n, v) \
|
||||
{ \
|
||||
buffer[DISP1_TO_MEMORY(n)] = (buffer[DISP1_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \
|
||||
((v)&0xF) << (((n) % 2) << 2); \
|
||||
}
|
||||
#define SET_DISP2_MEMORY(buffer, n, v) \
|
||||
{ \
|
||||
buffer[DISP2_TO_MEMORY(n)] = (buffer[DISP2_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \
|
||||
((v)&0xF) << (((n) % 2) << 2); \
|
||||
}
|
||||
#define SET_IO_MEMORY(buffer, n, v) \
|
||||
{ \
|
||||
buffer[IO_TO_MEMORY(n)] = (buffer[IO_TO_MEMORY(n)] & ~(0xF << (((n) % 2) << 2))) | \
|
||||
((v)&0xF) << (((n) % 2) << 2); \
|
||||
}
|
||||
#define SET_MEMORY(buffer, n, v) \
|
||||
{ \
|
||||
if((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) { \
|
||||
SET_RAM_MEMORY(buffer, n, v); \
|
||||
} else if((n) < MEM_DISPLAY1_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { \
|
||||
SET_DISP1_MEMORY(buffer, n, v); \
|
||||
} else if((n) < MEM_DISPLAY2_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { \
|
||||
SET_DISP2_MEMORY(buffer, n, v); \
|
||||
} else if((n) < MEM_IO_ADDR) { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} else if((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) { \
|
||||
SET_IO_MEMORY(buffer, n, v); \
|
||||
} else { \
|
||||
/* INVALID_MEMORY */ \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GET_RAM_MEMORY(buffer, n) ((buffer[RAM_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_DISP1_MEMORY(buffer, n) ((buffer[DISP1_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_DISP2_MEMORY(buffer, n) ((buffer[DISP2_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_IO_MEMORY(buffer, n) ((buffer[IO_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_MEMORY(buffer, n) ((buffer[ \
|
||||
((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) ? RAM_TO_MEMORY(n) : \
|
||||
((n) < MEM_DISPLAY1_ADDR) ? 0 : \
|
||||
((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) ? DISP1_TO_MEMORY(n) : \
|
||||
((n) < MEM_DISPLAY2_ADDR) ? 0 : \
|
||||
((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) ? DISP2_TO_MEMORY(n) : \
|
||||
((n) < MEM_IO_ADDR) ? 0 : \
|
||||
((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) ? IO_TO_MEMORY(n) : 0 \
|
||||
] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_RAM_MEMORY(buffer, n) ((buffer[RAM_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_DISP1_MEMORY(buffer, n) ((buffer[DISP1_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_DISP2_MEMORY(buffer, n) ((buffer[DISP2_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_IO_MEMORY(buffer, n) ((buffer[IO_TO_MEMORY(n)] >> (((n) % 2) << 2)) & 0xF)
|
||||
#define GET_MEMORY(buffer, n) \
|
||||
((buffer \
|
||||
[((n) < (MEM_RAM_ADDR + MEM_RAM_SIZE)) ? RAM_TO_MEMORY(n) : \
|
||||
((n) < MEM_DISPLAY1_ADDR) ? 0 : \
|
||||
((n) < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) ? DISP1_TO_MEMORY(n) : \
|
||||
((n) < MEM_DISPLAY2_ADDR) ? 0 : \
|
||||
((n) < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) ? DISP2_TO_MEMORY(n) : \
|
||||
((n) < MEM_IO_ADDR) ? 0 : \
|
||||
((n) < (MEM_IO_ADDR + MEM_IO_SIZE)) ? IO_TO_MEMORY(n) : \
|
||||
0] >> \
|
||||
(((n) % 2) << 2)) & \
|
||||
0xF)
|
||||
|
||||
#define MEM_BUFFER_TYPE u8_t
|
||||
#define MEM_BUFFER_TYPE u8_t
|
||||
#else
|
||||
#define MEM_BUFFER_SIZE MEMORY_SIZE
|
||||
#define MEM_BUFFER_SIZE MEMORY_SIZE
|
||||
|
||||
#define SET_MEMORY(buffer, n, v) {buffer[n] = v;}
|
||||
#define SET_RAM_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_DISP1_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_DISP2_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_IO_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_MEMORY(buffer, n, v) \
|
||||
{ buffer[n] = v; }
|
||||
#define SET_RAM_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_DISP1_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_DISP2_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
#define SET_IO_MEMORY(buffer, n, v) SET_MEMORY(buffer, n, v)
|
||||
|
||||
#define GET_MEMORY(buffer, n) (buffer[n])
|
||||
#define GET_RAM_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_DISP1_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_DISP2_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_IO_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_MEMORY(buffer, n) (buffer[n])
|
||||
#define GET_RAM_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_DISP1_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_DISP2_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
#define GET_IO_MEMORY(buffer, n) GET_MEMORY(buffer, n)
|
||||
|
||||
#define MEM_BUFFER_TYPE u4_t
|
||||
#define MEM_BUFFER_TYPE u4_t
|
||||
#endif
|
||||
|
||||
typedef struct breakpoint {
|
||||
u13_t addr;
|
||||
struct breakpoint *next;
|
||||
u13_t addr;
|
||||
struct breakpoint* next;
|
||||
} breakpoint_t;
|
||||
|
||||
/* Pins (TODO: add other pins) */
|
||||
typedef enum {
|
||||
PIN_K00 = 0x0,
|
||||
PIN_K01 = 0x1,
|
||||
PIN_K02 = 0x2,
|
||||
PIN_K03 = 0x3,
|
||||
PIN_K10 = 0X4,
|
||||
PIN_K11 = 0X5,
|
||||
PIN_K12 = 0X6,
|
||||
PIN_K13 = 0X7,
|
||||
PIN_K00 = 0x0,
|
||||
PIN_K01 = 0x1,
|
||||
PIN_K02 = 0x2,
|
||||
PIN_K03 = 0x3,
|
||||
PIN_K10 = 0X4,
|
||||
PIN_K11 = 0X5,
|
||||
PIN_K12 = 0X6,
|
||||
PIN_K13 = 0X7,
|
||||
} pin_t;
|
||||
|
||||
typedef enum {
|
||||
PIN_STATE_LOW = 0,
|
||||
PIN_STATE_HIGH = 1,
|
||||
PIN_STATE_LOW = 0,
|
||||
PIN_STATE_HIGH = 1,
|
||||
} pin_state_t;
|
||||
|
||||
typedef enum {
|
||||
INT_PROG_TIMER_SLOT = 0,
|
||||
INT_SERIAL_SLOT = 1,
|
||||
INT_K10_K13_SLOT = 2,
|
||||
INT_K00_K03_SLOT = 3,
|
||||
INT_STOPWATCH_SLOT = 4,
|
||||
INT_CLOCK_TIMER_SLOT = 5,
|
||||
INT_SLOT_NUM,
|
||||
INT_PROG_TIMER_SLOT = 0,
|
||||
INT_SERIAL_SLOT = 1,
|
||||
INT_K10_K13_SLOT = 2,
|
||||
INT_K00_K03_SLOT = 3,
|
||||
INT_STOPWATCH_SLOT = 4,
|
||||
INT_CLOCK_TIMER_SLOT = 5,
|
||||
INT_SLOT_NUM,
|
||||
} int_slot_t;
|
||||
|
||||
typedef struct {
|
||||
u4_t factor_flag_reg;
|
||||
u4_t mask_reg;
|
||||
bool_t triggered; /* 1 if triggered, 0 otherwise */
|
||||
u8_t vector;
|
||||
u4_t factor_flag_reg;
|
||||
u4_t mask_reg;
|
||||
bool_t triggered; /* 1 if triggered, 0 otherwise */
|
||||
u8_t vector;
|
||||
} interrupt_t;
|
||||
|
||||
typedef struct {
|
||||
u13_t *pc;
|
||||
u12_t *x;
|
||||
u12_t *y;
|
||||
u4_t *a;
|
||||
u4_t *b;
|
||||
u5_t *np;
|
||||
u8_t *sp;
|
||||
u4_t *flags;
|
||||
u13_t* pc;
|
||||
u12_t* x;
|
||||
u12_t* y;
|
||||
u4_t* a;
|
||||
u4_t* b;
|
||||
u5_t* np;
|
||||
u8_t* sp;
|
||||
u4_t* flags;
|
||||
|
||||
u32_t *tick_counter;
|
||||
u32_t *clk_timer_timestamp;
|
||||
u32_t *prog_timer_timestamp;
|
||||
bool_t *prog_timer_enabled;
|
||||
u8_t *prog_timer_data;
|
||||
u8_t *prog_timer_rld;
|
||||
u32_t* tick_counter;
|
||||
u32_t* clk_timer_timestamp;
|
||||
u32_t* prog_timer_timestamp;
|
||||
bool_t* prog_timer_enabled;
|
||||
u8_t* prog_timer_data;
|
||||
u8_t* prog_timer_rld;
|
||||
|
||||
u32_t *call_depth;
|
||||
u32_t* call_depth;
|
||||
|
||||
interrupt_t *interrupts;
|
||||
interrupt_t* interrupts;
|
||||
|
||||
MEM_BUFFER_TYPE *memory;
|
||||
MEM_BUFFER_TYPE* memory;
|
||||
} state_t;
|
||||
|
||||
|
||||
void cpu_add_bp(breakpoint_t **list, u13_t addr);
|
||||
void cpu_free_bp(breakpoint_t **list);
|
||||
void cpu_add_bp(breakpoint_t** list, u13_t addr);
|
||||
void cpu_free_bp(breakpoint_t** list);
|
||||
|
||||
void cpu_set_speed(u8_t speed);
|
||||
|
||||
state_t * cpu_get_state(void);
|
||||
state_t* cpu_get_state(void);
|
||||
|
||||
u32_t cpu_get_depth(void);
|
||||
|
||||
@@ -184,7 +207,7 @@ void cpu_refresh_hw(void);
|
||||
|
||||
void cpu_reset(void);
|
||||
|
||||
bool_t cpu_init(const u12_t *program, breakpoint_t *breakpoints, u32_t freq);
|
||||
bool_t cpu_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq);
|
||||
void cpu_release(void);
|
||||
|
||||
int cpu_step(void);
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
#include "../hal_types.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LOG_ERROR = 0x1,
|
||||
LOG_INFO = (0x1 << 1),
|
||||
LOG_MEMORY = (0x1 << 2),
|
||||
LOG_CPU = (0x1 << 3),
|
||||
LOG_ERROR = 0x1,
|
||||
LOG_INFO = (0x1 << 1),
|
||||
LOG_MEMORY = (0x1 << 2),
|
||||
LOG_CPU = (0x1 << 3),
|
||||
} log_level_t;
|
||||
|
||||
/* The Hardware Abstraction Layer
|
||||
@@ -38,52 +38,52 @@ typedef enum {
|
||||
* All pointers MUST be implemented, but some implementations can be left empty.
|
||||
*/
|
||||
typedef struct {
|
||||
/* Memory allocation functions
|
||||
/* Memory allocation functions
|
||||
* NOTE: Needed only if breakpoints support is required.
|
||||
*/
|
||||
void * (*malloc)(u32_t size);
|
||||
void (*free)(void *ptr);
|
||||
void* (*malloc)(u32_t size);
|
||||
void (*free)(void* ptr);
|
||||
|
||||
/* What to do if the CPU has halted
|
||||
/* What to do if the CPU has halted
|
||||
*/
|
||||
void (*halt)(void);
|
||||
void (*halt)(void);
|
||||
|
||||
/* Log related function
|
||||
/* Log related function
|
||||
* NOTE: Needed only if log messages are required.
|
||||
*/
|
||||
bool_t (*is_log_enabled)(log_level_t level);
|
||||
void (*log)(log_level_t level, char *buff, ...);
|
||||
bool_t (*is_log_enabled)(log_level_t level);
|
||||
void (*log)(log_level_t level, char* buff, ...);
|
||||
|
||||
/* Clock related functions
|
||||
/* Clock related functions
|
||||
* NOTE: Timestamps granularity is configured with tamalib_init(), an accuracy
|
||||
* of ~30 us (1/32768) is required for a cycle accurate emulation.
|
||||
*/
|
||||
void (*sleep_until)(timestamp_t ts);
|
||||
timestamp_t (*get_timestamp)(void);
|
||||
void (*sleep_until)(timestamp_t ts);
|
||||
timestamp_t (*get_timestamp)(void);
|
||||
|
||||
/* Screen related functions
|
||||
/* Screen related functions
|
||||
* NOTE: In case of direct hardware access to pixels, the set_XXXX() functions
|
||||
* (called for each pixel/icon update) can directly drive them, otherwise they
|
||||
* should just store the data in a buffer and let update_screen() do the actual
|
||||
* rendering (at 30 fps).
|
||||
*/
|
||||
void (*update_screen)(void);
|
||||
void (*set_lcd_matrix)(u8_t x, u8_t y, bool_t val);
|
||||
void (*set_lcd_icon)(u8_t icon, bool_t val);
|
||||
void (*update_screen)(void);
|
||||
void (*set_lcd_matrix)(u8_t x, u8_t y, bool_t val);
|
||||
void (*set_lcd_icon)(u8_t icon, bool_t val);
|
||||
|
||||
/* Sound related functions
|
||||
/* Sound related functions
|
||||
* NOTE: set_frequency() changes the output frequency of the sound, while
|
||||
* play_frequency() decides whether the sound should be heard or not.
|
||||
*/
|
||||
void (*set_frequency)(u32_t freq);
|
||||
void (*play_frequency)(bool_t en);
|
||||
void (*set_frequency)(u32_t freq);
|
||||
void (*play_frequency)(bool_t en);
|
||||
|
||||
/* Event handler from the main app (if any)
|
||||
/* Event handler from the main app (if any)
|
||||
* NOTE: This function usually handles button related events, states loading/saving ...
|
||||
*/
|
||||
int (*handler)(void);
|
||||
int (*handler)(void);
|
||||
} hal_t;
|
||||
|
||||
extern hal_t *g_hal;
|
||||
extern hal_t* g_hal;
|
||||
|
||||
#endif /* _HAL_H_ */
|
||||
|
||||
@@ -22,29 +22,27 @@
|
||||
#include "hal.h"
|
||||
|
||||
/* SEG -> LCD mapping */
|
||||
static u8_t seg_pos[40] = {0, 1, 2, 3, 4, 5, 6, 7, 32, 8, 9, 10, 11, 12 ,13 ,14, 15, 33, 34, 35, 31, 30, 29, 28, 27, 26, 25, 24, 36, 23, 22, 21, 20, 19, 18, 17, 16, 37, 38, 39};
|
||||
static u8_t seg_pos[40] = {0, 1, 2, 3, 4, 5, 6, 7, 32, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 33, 34, 35, 31, 30, 29, 28, 27, 26, 25, 24,
|
||||
36, 23, 22, 21, 20, 19, 18, 17, 16, 37, 38, 39};
|
||||
|
||||
bool_t hw_init(void) {
|
||||
/* Buttons are active LOW */
|
||||
cpu_set_input_pin(PIN_K00, PIN_STATE_HIGH);
|
||||
cpu_set_input_pin(PIN_K01, PIN_STATE_HIGH);
|
||||
cpu_set_input_pin(PIN_K02, PIN_STATE_HIGH);
|
||||
|
||||
bool_t hw_init(void)
|
||||
{
|
||||
/* Buttons are active LOW */
|
||||
cpu_set_input_pin(PIN_K00, PIN_STATE_HIGH);
|
||||
cpu_set_input_pin(PIN_K01, PIN_STATE_HIGH);
|
||||
cpu_set_input_pin(PIN_K02, PIN_STATE_HIGH);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hw_release(void)
|
||||
{
|
||||
void hw_release(void) {
|
||||
}
|
||||
|
||||
void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val)
|
||||
{
|
||||
if (seg_pos[seg] < LCD_WIDTH) {
|
||||
g_hal->set_lcd_matrix(seg_pos[seg], com, val);
|
||||
} else {
|
||||
/*
|
||||
void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val) {
|
||||
if(seg_pos[seg] < LCD_WIDTH) {
|
||||
g_hal->set_lcd_matrix(seg_pos[seg], com, val);
|
||||
} else {
|
||||
/*
|
||||
* IC n -> seg-com|...
|
||||
* IC 0 -> 8-0 |18-3 |19-2
|
||||
* IC 1 -> 8-1 |17-0 |19-3
|
||||
@@ -55,85 +53,82 @@ void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val)
|
||||
* IC 6 -> 28-14|37-15|39-12
|
||||
* IC 7 -> 28-15|38-12|39-13
|
||||
*/
|
||||
if (seg == 8 && com < 4) {
|
||||
g_hal->set_lcd_icon(com, val);
|
||||
} else if (seg == 28 && com >= 12) {
|
||||
g_hal->set_lcd_icon(com - 8, val);
|
||||
}
|
||||
}
|
||||
if(seg == 8 && com < 4) {
|
||||
g_hal->set_lcd_icon(com, val);
|
||||
} else if(seg == 28 && com >= 12) {
|
||||
g_hal->set_lcd_icon(com - 8, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hw_set_button(button_t btn, btn_state_t state)
|
||||
{
|
||||
pin_state_t pin_state = (state == BTN_STATE_PRESSED) ? PIN_STATE_LOW : PIN_STATE_HIGH;
|
||||
void hw_set_button(button_t btn, btn_state_t state) {
|
||||
pin_state_t pin_state = (state == BTN_STATE_PRESSED) ? PIN_STATE_LOW : PIN_STATE_HIGH;
|
||||
|
||||
switch (btn) {
|
||||
case BTN_LEFT:
|
||||
cpu_set_input_pin(PIN_K02, pin_state);
|
||||
break;
|
||||
switch(btn) {
|
||||
case BTN_LEFT:
|
||||
cpu_set_input_pin(PIN_K02, pin_state);
|
||||
break;
|
||||
|
||||
case BTN_MIDDLE:
|
||||
cpu_set_input_pin(PIN_K01, pin_state);
|
||||
break;
|
||||
case BTN_MIDDLE:
|
||||
cpu_set_input_pin(PIN_K01, pin_state);
|
||||
break;
|
||||
|
||||
case BTN_RIGHT:
|
||||
cpu_set_input_pin(PIN_K00, pin_state);
|
||||
break;
|
||||
}
|
||||
case BTN_RIGHT:
|
||||
cpu_set_input_pin(PIN_K00, pin_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hw_set_buzzer_freq(u4_t freq)
|
||||
{
|
||||
u32_t snd_freq = 0;
|
||||
void hw_set_buzzer_freq(u4_t freq) {
|
||||
u32_t snd_freq = 0;
|
||||
|
||||
switch (freq) {
|
||||
case 0:
|
||||
/* 4096.0 Hz */
|
||||
snd_freq = 40960;
|
||||
break;
|
||||
switch(freq) {
|
||||
case 0:
|
||||
/* 4096.0 Hz */
|
||||
snd_freq = 40960;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* 3276.8 Hz */
|
||||
snd_freq = 32768;
|
||||
break;
|
||||
case 1:
|
||||
/* 3276.8 Hz */
|
||||
snd_freq = 32768;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* 2730.7 Hz */
|
||||
snd_freq = 27307;
|
||||
break;
|
||||
case 2:
|
||||
/* 2730.7 Hz */
|
||||
snd_freq = 27307;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* 2340.6 Hz */
|
||||
snd_freq = 23406;
|
||||
break;
|
||||
case 3:
|
||||
/* 2340.6 Hz */
|
||||
snd_freq = 23406;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* 2048.0 Hz */
|
||||
snd_freq = 20480;
|
||||
break;
|
||||
case 4:
|
||||
/* 2048.0 Hz */
|
||||
snd_freq = 20480;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
/* 1638.4 Hz */
|
||||
snd_freq = 16384;
|
||||
break;
|
||||
case 5:
|
||||
/* 1638.4 Hz */
|
||||
snd_freq = 16384;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* 1365.3 Hz */
|
||||
snd_freq = 13653;
|
||||
break;
|
||||
case 6:
|
||||
/* 1365.3 Hz */
|
||||
snd_freq = 13653;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* 1170.3 Hz */
|
||||
snd_freq = 11703;
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
/* 1170.3 Hz */
|
||||
snd_freq = 11703;
|
||||
break;
|
||||
}
|
||||
|
||||
if (snd_freq != 0) {
|
||||
g_hal->set_frequency(snd_freq);
|
||||
}
|
||||
if(snd_freq != 0) {
|
||||
g_hal->set_frequency(snd_freq);
|
||||
}
|
||||
}
|
||||
|
||||
void hw_enable_buzzer(bool_t en)
|
||||
{
|
||||
g_hal->play_frequency(en);
|
||||
void hw_enable_buzzer(bool_t en) {
|
||||
g_hal->play_frequency(en);
|
||||
}
|
||||
|
||||
@@ -22,23 +22,22 @@
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#define LCD_WIDTH 32
|
||||
#define LCD_HEIGHT 16
|
||||
#define LCD_WIDTH 32
|
||||
#define LCD_HEIGHT 16
|
||||
|
||||
#define ICON_NUM 8
|
||||
#define ICON_NUM 8
|
||||
|
||||
typedef enum {
|
||||
BTN_STATE_RELEASED = 0,
|
||||
BTN_STATE_PRESSED,
|
||||
BTN_STATE_RELEASED = 0,
|
||||
BTN_STATE_PRESSED,
|
||||
} btn_state_t;
|
||||
|
||||
typedef enum {
|
||||
BTN_LEFT = 0,
|
||||
BTN_MIDDLE,
|
||||
BTN_RIGHT,
|
||||
BTN_LEFT = 0,
|
||||
BTN_MIDDLE,
|
||||
BTN_RIGHT,
|
||||
} button_t;
|
||||
|
||||
|
||||
bool_t hw_init(void);
|
||||
void hw_release(void);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "cpu.h"
|
||||
#include "hal.h"
|
||||
|
||||
#define DEFAULT_FRAMERATE 30 // fps
|
||||
#define DEFAULT_FRAMERATE 30 // fps
|
||||
|
||||
static exec_mode_t exec_mode = EXEC_MODE_RUN;
|
||||
|
||||
@@ -34,104 +34,95 @@ static u32_t ts_freq;
|
||||
|
||||
static u8_t g_framerate = DEFAULT_FRAMERATE;
|
||||
|
||||
hal_t *g_hal;
|
||||
hal_t* g_hal;
|
||||
|
||||
bool_t tamalib_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq) {
|
||||
bool_t res = 0;
|
||||
|
||||
bool_t tamalib_init(const u12_t *program, breakpoint_t *breakpoints, u32_t freq)
|
||||
{
|
||||
bool_t res = 0;
|
||||
res |= cpu_init(program, breakpoints, freq);
|
||||
res |= hw_init();
|
||||
|
||||
res |= cpu_init(program, breakpoints, freq);
|
||||
res |= hw_init();
|
||||
ts_freq = freq;
|
||||
|
||||
ts_freq = freq;
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
void tamalib_release(void)
|
||||
{
|
||||
hw_release();
|
||||
cpu_release();
|
||||
void tamalib_release(void) {
|
||||
hw_release();
|
||||
cpu_release();
|
||||
}
|
||||
|
||||
void tamalib_set_framerate(u8_t framerate)
|
||||
{
|
||||
g_framerate = framerate;
|
||||
void tamalib_set_framerate(u8_t framerate) {
|
||||
g_framerate = framerate;
|
||||
}
|
||||
|
||||
u8_t tamalib_get_framerate(void)
|
||||
{
|
||||
return g_framerate;
|
||||
u8_t tamalib_get_framerate(void) {
|
||||
return g_framerate;
|
||||
}
|
||||
|
||||
void tamalib_register_hal(hal_t *hal)
|
||||
{
|
||||
g_hal = hal;
|
||||
void tamalib_register_hal(hal_t* hal) {
|
||||
g_hal = hal;
|
||||
}
|
||||
|
||||
void tamalib_set_exec_mode(exec_mode_t mode)
|
||||
{
|
||||
exec_mode = mode;
|
||||
step_depth = cpu_get_depth();
|
||||
cpu_sync_ref_timestamp();
|
||||
void tamalib_set_exec_mode(exec_mode_t mode) {
|
||||
exec_mode = mode;
|
||||
step_depth = cpu_get_depth();
|
||||
cpu_sync_ref_timestamp();
|
||||
}
|
||||
|
||||
void tamalib_step(void)
|
||||
{
|
||||
if (exec_mode == EXEC_MODE_PAUSE) {
|
||||
return;
|
||||
}
|
||||
void tamalib_step(void) {
|
||||
if(exec_mode == EXEC_MODE_PAUSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu_step()) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
} else {
|
||||
switch (exec_mode) {
|
||||
case EXEC_MODE_PAUSE:
|
||||
case EXEC_MODE_RUN:
|
||||
break;
|
||||
if(cpu_step()) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
} else {
|
||||
switch(exec_mode) {
|
||||
case EXEC_MODE_PAUSE:
|
||||
case EXEC_MODE_RUN:
|
||||
break;
|
||||
|
||||
case EXEC_MODE_STEP:
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
break;
|
||||
case EXEC_MODE_STEP:
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
break;
|
||||
|
||||
case EXEC_MODE_NEXT:
|
||||
if (cpu_get_depth() <= step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
case EXEC_MODE_NEXT:
|
||||
if(cpu_get_depth() <= step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
|
||||
case EXEC_MODE_TO_CALL:
|
||||
if (cpu_get_depth() > step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
case EXEC_MODE_TO_CALL:
|
||||
if(cpu_get_depth() > step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
|
||||
case EXEC_MODE_TO_RET:
|
||||
if (cpu_get_depth() < step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case EXEC_MODE_TO_RET:
|
||||
if(cpu_get_depth() < step_depth) {
|
||||
exec_mode = EXEC_MODE_PAUSE;
|
||||
step_depth = cpu_get_depth();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tamalib_mainloop(void)
|
||||
{
|
||||
timestamp_t ts;
|
||||
void tamalib_mainloop(void) {
|
||||
timestamp_t ts;
|
||||
|
||||
while (!g_hal->handler()) {
|
||||
tamalib_step();
|
||||
while(!g_hal->handler()) {
|
||||
tamalib_step();
|
||||
|
||||
/* Update the screen @ g_framerate fps */
|
||||
ts = g_hal->get_timestamp();
|
||||
if (ts - screen_ts >= ts_freq/g_framerate) {
|
||||
screen_ts = ts;
|
||||
g_hal->update_screen();
|
||||
}
|
||||
}
|
||||
/* Update the screen @ g_framerate fps */
|
||||
ts = g_hal->get_timestamp();
|
||||
if(ts - screen_ts >= ts_freq / g_framerate) {
|
||||
screen_ts = ts;
|
||||
g_hal->update_screen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,35 +24,34 @@
|
||||
#include "hw.h"
|
||||
#include "hal.h"
|
||||
|
||||
#define tamalib_set_button(btn, state) hw_set_button(btn, state)
|
||||
#define tamalib_set_button(btn, state) hw_set_button(btn, state)
|
||||
|
||||
#define tamalib_set_speed(speed) cpu_set_speed(speed)
|
||||
#define tamalib_set_speed(speed) cpu_set_speed(speed)
|
||||
|
||||
#define tamalib_get_state() cpu_get_state()
|
||||
#define tamalib_refresh_hw() cpu_refresh_hw()
|
||||
#define tamalib_get_state() cpu_get_state()
|
||||
#define tamalib_refresh_hw() cpu_refresh_hw()
|
||||
|
||||
#define tamalib_reset() cpu_reset()
|
||||
#define tamalib_reset() cpu_reset()
|
||||
|
||||
#define tamalib_add_bp(list, addr) cpu_add_bp(list, addr)
|
||||
#define tamalib_free_bp(list) cpu_free_bp(list)
|
||||
#define tamalib_add_bp(list, addr) cpu_add_bp(list, addr)
|
||||
#define tamalib_free_bp(list) cpu_free_bp(list)
|
||||
|
||||
typedef enum {
|
||||
EXEC_MODE_PAUSE,
|
||||
EXEC_MODE_RUN,
|
||||
EXEC_MODE_STEP,
|
||||
EXEC_MODE_NEXT,
|
||||
EXEC_MODE_TO_CALL,
|
||||
EXEC_MODE_TO_RET,
|
||||
EXEC_MODE_PAUSE,
|
||||
EXEC_MODE_RUN,
|
||||
EXEC_MODE_STEP,
|
||||
EXEC_MODE_NEXT,
|
||||
EXEC_MODE_TO_CALL,
|
||||
EXEC_MODE_TO_RET,
|
||||
} exec_mode_t;
|
||||
|
||||
|
||||
void tamalib_release(void);
|
||||
bool_t tamalib_init(const u12_t *program, breakpoint_t *breakpoints, u32_t freq);
|
||||
bool_t tamalib_init(const u12_t* program, breakpoint_t* breakpoints, u32_t freq);
|
||||
|
||||
void tamalib_set_framerate(u8_t framerate);
|
||||
u8_t tamalib_get_framerate(void);
|
||||
|
||||
void tamalib_register_hal(hal_t *hal);
|
||||
void tamalib_register_hal(hal_t* hal);
|
||||
|
||||
void tamalib_set_exec_mode(exec_mode_t mode);
|
||||
|
||||
|
||||
@@ -1181,7 +1181,7 @@ static void tanks_game_init_game(TanksState* const tanks_state, GameState type)
|
||||
|
||||
static bool
|
||||
tanks_game_collision(Point const next_step, bool shoot, TanksState const* const tanks_state) {
|
||||
if((int8_t) next_step.x < 0 || (int8_t) next_step.y < 0) {
|
||||
if((int8_t)next_step.x < 0 || (int8_t)next_step.y < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1533,7 +1533,7 @@ static void tanks_game_process_game_step(TanksState* const tanks_state) {
|
||||
}
|
||||
|
||||
int32_t tanks_game_app(void* p) {
|
||||
UNUSED(p);
|
||||
UNUSED(p);
|
||||
srand(DWT->CYCCNT);
|
||||
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(TanksEvent));
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "../wifi_deauther_app_i.h"
|
||||
|
||||
void wifi_deauther_console_output_handle_rx_data_cb(uint8_t *buf, size_t len, void* context) {
|
||||
void wifi_deauther_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
|
||||
furi_assert(context);
|
||||
WifideautherApp* app = context;
|
||||
|
||||
// If text box store gets too big, then truncate it
|
||||
app->text_box_store_strlen += len;
|
||||
if (app->text_box_store_strlen >= WIFI_deauther_TEXT_BOX_STORE_SIZE - 1) {
|
||||
if(app->text_box_store_strlen >= WIFI_deauther_TEXT_BOX_STORE_SIZE - 1) {
|
||||
string_right(app->text_box_store, app->text_box_store_strlen / 2);
|
||||
app->text_box_store_strlen = string_size(app->text_box_store);
|
||||
}
|
||||
@@ -24,21 +24,22 @@ void wifi_deauther_scene_console_output_on_enter(void* context) {
|
||||
TextBox* text_box = app->text_box;
|
||||
text_box_reset(app->text_box);
|
||||
text_box_set_font(text_box, TextBoxFontText);
|
||||
if (app->focus_console_start) {
|
||||
if(app->focus_console_start) {
|
||||
text_box_set_focus(text_box, TextBoxFocusStart);
|
||||
} else {
|
||||
text_box_set_focus(text_box, TextBoxFocusEnd);
|
||||
}
|
||||
if (app->is_command) {
|
||||
if(app->is_command) {
|
||||
string_reset(app->text_box_store);
|
||||
app->text_box_store_strlen = 0;
|
||||
if (0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
|
||||
const char* help_msg = "For app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n";
|
||||
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
|
||||
const char* help_msg =
|
||||
"For app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n";
|
||||
string_cat_str(app->text_box_store, help_msg);
|
||||
app->text_box_store_strlen += strlen(help_msg);
|
||||
}
|
||||
|
||||
if (app->show_stopscan_tip) {
|
||||
if(app->show_stopscan_tip) {
|
||||
const char* help_msg = "Press BACK to send stopscan\n";
|
||||
string_cat_str(app->text_box_store, help_msg);
|
||||
app->text_box_store_strlen += strlen(help_msg);
|
||||
@@ -51,11 +52,13 @@ void wifi_deauther_scene_console_output_on_enter(void* context) {
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, WifideautherAppViewConsoleOutput);
|
||||
|
||||
// Register callback to receive data
|
||||
wifi_deauther_uart_set_handle_rx_data_cb(app->uart, wifi_deauther_console_output_handle_rx_data_cb); // setup callback for rx thread
|
||||
wifi_deauther_uart_set_handle_rx_data_cb(
|
||||
app->uart, wifi_deauther_console_output_handle_rx_data_cb); // setup callback for rx thread
|
||||
|
||||
// Send command with newline '\n'
|
||||
if (app->is_command && app->selected_tx_string) {
|
||||
wifi_deauther_uart_tx((uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
|
||||
if(app->is_command && app->selected_tx_string) {
|
||||
wifi_deauther_uart_tx(
|
||||
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
|
||||
wifi_deauther_uart_tx((uint8_t*)("\n"), 1);
|
||||
}
|
||||
}
|
||||
@@ -82,7 +85,7 @@ void wifi_deauther_scene_console_output_on_exit(void* context) {
|
||||
wifi_deauther_uart_set_handle_rx_data_cb(app->uart, NULL);
|
||||
|
||||
// Automatically stop the scan when exiting view
|
||||
if (app->is_command) {
|
||||
if(app->is_command) {
|
||||
wifi_deauther_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n"));
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,9 @@
|
||||
// For each command, define whether additional arguments are needed
|
||||
// (enabling text input to fill them out), and whether the console
|
||||
// text box should focus at the start of the output or the end
|
||||
typedef enum {
|
||||
NO_ARGS = 0,
|
||||
INPUT_ARGS,
|
||||
TOGGLE_ARGS
|
||||
} InputArgs;
|
||||
typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs;
|
||||
|
||||
typedef enum {
|
||||
FOCUS_CONSOLE_END = 0,
|
||||
FOCUS_CONSOLE_START,
|
||||
FOCUS_CONSOLE_TOGGLE
|
||||
} FocusConsole;
|
||||
typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole;
|
||||
|
||||
#define SHOW_STOPSCAN_TIP (true)
|
||||
#define NO_TIP (false)
|
||||
@@ -31,34 +23,78 @@ typedef struct {
|
||||
|
||||
// NUM_MENU_ITEMS defined in wifi_deauther_app_i.h - if you add an entry here, increment it!
|
||||
const WifideautherItem MenuItems[NUM_MENU_ITEMS] = {
|
||||
{ "View Log from", {"start", "end"}, 2, {}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP },
|
||||
{ "Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Stop", {""}, 1, {"stop all"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Scan", {"All", "SSIDs", "Stations"}, 3, {"scan", "scan aps", "scan stations"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Select", {"All", "SSIDs", "Stations"}, 3, {"select all", "select aps", "select stations"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Deselect", {"All", "SSIDs", "Stations"}, 3, {"deselect all", "deselect aps", "deselect stations"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Show", {"SSIDs", "Stations", "All", "Selected"}, 4, {"show ap", "show station", "show all", "show selected"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Attack", {"deauth", "deauthall", "beacon", "probe"}, 4, {"attack deauth", "attack deauthall", "attack beacon", "attack probe"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP },
|
||||
{ "Settings", {"Get", "Remove AP", "Set SSID", "Set Pass", "Save"}, 5, {"get settings", "set webinterface false", "set ssid: pwned", "set password: deauther", "save settings"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Sysinfo", {""}, 1, {"sysinfo"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{ "Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP },
|
||||
{"View Log from", {"start", "end"}, 2, {}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP},
|
||||
{"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Stop", {""}, 1, {"stop all"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Scan",
|
||||
{"All", "SSIDs", "Stations"},
|
||||
3,
|
||||
{"scan", "scan aps", "scan stations"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Select",
|
||||
{"All", "SSIDs", "Stations"},
|
||||
3,
|
||||
{"select all", "select aps", "select stations"},
|
||||
INPUT_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Deselect",
|
||||
{"All", "SSIDs", "Stations"},
|
||||
3,
|
||||
{"deselect all", "deselect aps", "deselect stations"},
|
||||
INPUT_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Show",
|
||||
{"SSIDs", "Stations", "All", "Selected"},
|
||||
4,
|
||||
{"show ap", "show station", "show all", "show selected"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Attack",
|
||||
{"deauth", "deauthall", "beacon", "probe"},
|
||||
4,
|
||||
{"attack deauth", "attack deauthall", "attack beacon", "attack probe"},
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Settings",
|
||||
{"Get", "Remove AP", "Set SSID", "Set Pass", "Save"},
|
||||
5,
|
||||
{"get settings",
|
||||
"set webinterface false",
|
||||
"set ssid: pwned",
|
||||
"set password: deauther",
|
||||
"save settings"},
|
||||
INPUT_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
NO_TIP},
|
||||
{"Sysinfo", {""}, 1, {"sysinfo"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
};
|
||||
|
||||
|
||||
static void wifi_deauther_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
WifideautherApp* app = context;
|
||||
if (app->selected_option_index[index] < MenuItems[index].num_options_menu) {
|
||||
app->selected_tx_string = MenuItems[index].actual_commands[app->selected_option_index[index]];
|
||||
if(app->selected_option_index[index] < MenuItems[index].num_options_menu) {
|
||||
app->selected_tx_string =
|
||||
MenuItems[index].actual_commands[app->selected_option_index[index]];
|
||||
}
|
||||
app->is_command = (1 <= index);
|
||||
app->is_custom_tx_string = false;
|
||||
app->selected_menu_index = index;
|
||||
app->focus_console_start = (MenuItems[index].focus_console == FOCUS_CONSOLE_TOGGLE) ? (app->selected_option_index[index] == 0) : MenuItems[index].focus_console;
|
||||
app->focus_console_start = (MenuItems[index].focus_console == FOCUS_CONSOLE_TOGGLE) ?
|
||||
(app->selected_option_index[index] == 0) :
|
||||
MenuItems[index].focus_console;
|
||||
app->show_stopscan_tip = MenuItems[index].show_stopscan_tip;
|
||||
|
||||
bool needs_keyboard = (MenuItems[index].needs_keyboard == TOGGLE_ARGS) ? (app->selected_option_index[index] != 0) : MenuItems[index].needs_keyboard;
|
||||
if (needs_keyboard) {
|
||||
bool needs_keyboard = (MenuItems[index].needs_keyboard == TOGGLE_ARGS) ?
|
||||
(app->selected_option_index[index] != 0) :
|
||||
MenuItems[index].needs_keyboard;
|
||||
if(needs_keyboard) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, WifideautherEventStartKeyboard);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, WifideautherEventStartConsole);
|
||||
@@ -86,11 +122,17 @@ void wifi_deauther_scene_start_on_enter(void* context) {
|
||||
var_item_list, wifi_deauther_scene_start_var_list_enter_callback, app);
|
||||
|
||||
VariableItem* item;
|
||||
for (int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
item = variable_item_list_add(var_item_list, MenuItems[i].item_string, MenuItems[i].num_options_menu, wifi_deauther_scene_start_var_list_change_callback, app);
|
||||
if (MenuItems[i].num_options_menu) {
|
||||
for(int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
MenuItems[i].item_string,
|
||||
MenuItems[i].num_options_menu,
|
||||
wifi_deauther_scene_start_var_list_change_callback,
|
||||
app);
|
||||
if(MenuItems[i].num_options_menu) {
|
||||
variable_item_set_current_value_index(item, app->selected_option_index[i]);
|
||||
variable_item_set_current_value_text(item, MenuItems[i].options_menu[app->selected_option_index[i]]);
|
||||
variable_item_set_current_value_text(
|
||||
item, MenuItems[i].options_menu[app->selected_option_index[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,15 +148,17 @@ bool wifi_deauther_scene_start_on_event(void* context, SceneManagerEvent event)
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if (event.event == WifideautherEventStartKeyboard) {
|
||||
scene_manager_set_scene_state(app->scene_manager, WifideautherSceneStart, app->selected_menu_index);
|
||||
if(event.event == WifideautherEventStartKeyboard) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifideautherSceneStart, app->selected_menu_index);
|
||||
scene_manager_next_scene(app->scene_manager, WifideautherAppViewTextInput);
|
||||
} else if (event.event == WifideautherEventStartConsole) {
|
||||
scene_manager_set_scene_state(app->scene_manager, WifideautherSceneStart, app->selected_menu_index);
|
||||
} else if(event.event == WifideautherEventStartConsole) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifideautherSceneStart, app->selected_menu_index);
|
||||
scene_manager_next_scene(app->scene_manager, WifideautherAppViewConsoleOutput);
|
||||
}
|
||||
consumed = true;
|
||||
} else if (event.type == SceneManagerEventTypeTick) {
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../wifi_deauther_app_i.h"
|
||||
|
||||
|
||||
void wifi_deauther_scene_text_input_callback(void* context) {
|
||||
WifideautherApp* app = context;
|
||||
|
||||
@@ -10,7 +9,7 @@ void wifi_deauther_scene_text_input_callback(void* context) {
|
||||
void wifi_deauther_scene_text_input_on_enter(void* context) {
|
||||
WifideautherApp* app = context;
|
||||
|
||||
if (false == app->is_custom_tx_string) {
|
||||
if(false == app->is_custom_tx_string) {
|
||||
// Fill text input with selected string so that user can add to it
|
||||
size_t length = strlen(app->selected_tx_string);
|
||||
furi_assert(length < WIFI_deauther_TEXT_INPUT_STORE_SIZE);
|
||||
@@ -19,27 +18,33 @@ void wifi_deauther_scene_text_input_on_enter(void* context) {
|
||||
|
||||
// Add space - because flipper keyboard currently doesn't have a space
|
||||
app->text_input_store[length] = ' ';
|
||||
app->text_input_store[length+1] = '\0';
|
||||
app->text_input_store[length + 1] = '\0';
|
||||
app->is_custom_tx_string = true;
|
||||
}
|
||||
|
||||
// Setup view
|
||||
TextInput* text_input = app->text_input;
|
||||
// Add help message to header
|
||||
if (0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) {
|
||||
if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) {
|
||||
text_input_set_header_text(text_input, "Enter # SSIDs to generate");
|
||||
} else if (0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) {
|
||||
} else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) {
|
||||
text_input_set_header_text(text_input, "Enter SSID name to add");
|
||||
} else if (0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) {
|
||||
} else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) {
|
||||
text_input_set_header_text(text_input, "Remove target from SSID list");
|
||||
} else if (0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) {
|
||||
} else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) {
|
||||
text_input_set_header_text(text_input, "Add target from AP list");
|
||||
} else if (0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) {
|
||||
} else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) {
|
||||
text_input_set_header_text(text_input, "Add target from SSID list");
|
||||
} else {
|
||||
text_input_set_header_text(text_input, "Add command arguments");
|
||||
}
|
||||
text_input_set_result_callback(text_input, wifi_deauther_scene_text_input_callback, app, app->text_input_store, WIFI_deauther_TEXT_INPUT_STORE_SIZE, false);
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
wifi_deauther_scene_text_input_callback,
|
||||
app,
|
||||
app->text_input_store,
|
||||
WIFI_deauther_TEXT_INPUT_STORE_SIZE,
|
||||
false);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, WifideautherAppViewTextInput);
|
||||
}
|
||||
@@ -48,8 +53,8 @@ bool wifi_deauther_scene_text_input_on_event(void* context, SceneManagerEvent ev
|
||||
WifideautherApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if (event.type == SceneManagerEventTypeCustom) {
|
||||
if (event.event == WifideautherEventStartConsole) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == WifideautherEventStartConsole) {
|
||||
// Point to custom string to send
|
||||
app->selected_tx_string = app->text_input_store;
|
||||
scene_manager_next_scene(app->scene_manager, WifideautherAppViewConsoleOutput);
|
||||
|
||||
@@ -47,17 +47,19 @@ WifideautherApp* wifi_deauther_app_alloc() {
|
||||
WifideautherAppViewVarItemList,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
for (int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
for(int i = 0; i < NUM_MENU_ITEMS; ++i) {
|
||||
app->selected_option_index[i] = 0;
|
||||
}
|
||||
|
||||
app->text_box = text_box_alloc();
|
||||
view_dispatcher_add_view(app->view_dispatcher, WifideautherAppViewConsoleOutput, text_box_get_view(app->text_box));
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, WifideautherAppViewConsoleOutput, text_box_get_view(app->text_box));
|
||||
string_init(app->text_box_store);
|
||||
string_reserve(app->text_box_store, WIFI_deauther_TEXT_BOX_STORE_SIZE);
|
||||
|
||||
app->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(app->view_dispatcher, WifideautherAppViewTextInput, text_input_get_view(app->text_input));
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, WifideautherAppViewTextInput, text_input_get_view(app->text_input));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, WifideautherSceneStart);
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ struct WifideautherUart {
|
||||
WifideautherApp* app;
|
||||
FuriThread* rx_thread;
|
||||
StreamBufferHandle_t rx_stream;
|
||||
uint8_t rx_buf[RX_BUF_SIZE+1];
|
||||
void (*handle_rx_data_cb)(uint8_t *buf, size_t len, void* context);
|
||||
uint8_t rx_buf[RX_BUF_SIZE + 1];
|
||||
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -19,7 +19,9 @@ typedef enum {
|
||||
WorkerEvtRxDone = (1 << 1),
|
||||
} WorkerEvtFlags;
|
||||
|
||||
void wifi_deauther_uart_set_handle_rx_data_cb(WifideautherUart* uart, void (*handle_rx_data_cb)(uint8_t *buf, size_t len, void* context)) {
|
||||
void wifi_deauther_uart_set_handle_rx_data_cb(
|
||||
WifideautherUart* uart,
|
||||
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) {
|
||||
furi_assert(uart);
|
||||
uart->handle_rx_data_cb = handle_rx_data_cb;
|
||||
}
|
||||
@@ -48,10 +50,9 @@ static int32_t uart_worker(void* context) {
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
size_t len =
|
||||
xStreamBufferReceive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0);
|
||||
size_t len = xStreamBufferReceive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0);
|
||||
if(len > 0) {
|
||||
if (uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app);
|
||||
if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,12 +62,12 @@ static int32_t uart_worker(void* context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wifi_deauther_uart_tx(uint8_t *data, size_t len) {
|
||||
void wifi_deauther_uart_tx(uint8_t* data, size_t len) {
|
||||
furi_hal_uart_tx(UART_CH, data, len);
|
||||
}
|
||||
|
||||
WifideautherUart* wifi_deauther_uart_init(WifideautherApp* app) {
|
||||
WifideautherUart *uart = malloc(sizeof(WifideautherUart));
|
||||
WifideautherUart* uart = malloc(sizeof(WifideautherUart));
|
||||
|
||||
furi_hal_console_disable();
|
||||
furi_hal_uart_set_br(UART_CH, BAUDRATE);
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
typedef struct WifideautherUart WifideautherUart;
|
||||
|
||||
void wifi_deauther_uart_set_handle_rx_data_cb(WifideautherUart* uart, void (*handle_rx_data_cb)(uint8_t *buf, size_t len, void* context));
|
||||
void wifi_deauther_uart_tx(uint8_t *data, size_t len);
|
||||
void wifi_deauther_uart_set_handle_rx_data_cb(
|
||||
WifideautherUart* uart,
|
||||
void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context));
|
||||
void wifi_deauther_uart_tx(uint8_t* data, size_t len);
|
||||
WifideautherUart* wifi_deauther_uart_init(WifideautherApp* app);
|
||||
void wifi_deauther_uart_free(WifideautherUart* uart);
|
||||
|
||||
@@ -112,7 +112,8 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenClock: {
|
||||
LoaderStatus status = loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Main/Clock.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Main/Clock.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
@@ -169,38 +170,38 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenSnake: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/Snake.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Snake.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpen2048: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/2048.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/2048.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenZombiez: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/Zombiez.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Zombiez.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenTetris: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/Tetris.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Tetris.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenDOOM: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/DOOM.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/DOOM.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case DesktopMainEventOpenDice: {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, "Applications", EXT_PATH("/apps/Games/Dice.fap"));
|
||||
LoaderStatus status =
|
||||
loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Dice.fap"));
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) {
|
||||
} else {
|
||||
str = "Set PIN + Off";
|
||||
}
|
||||
// } else if(i == DesktopLockMenuIndexGameMode) {
|
||||
// } else if(i == DesktopLockMenuIndexGameMode) {
|
||||
// str = "Games Mode";
|
||||
} else if(i == DesktopLockMenuIndexDummy) {
|
||||
if(m->dummy_mode) {
|
||||
@@ -151,7 +151,7 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) {
|
||||
lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context);
|
||||
} else if((idx == DesktopLockMenuIndexPinLockShutdown) && (event->type == InputTypeShort)) {
|
||||
lock_menu->callback(DesktopLockMenuEventPinLockShutdown, lock_menu->context);
|
||||
// } else if((idx == DesktopLockMenuIndexGameMode) && (event->type == InputTypeShort)) {
|
||||
// } else if((idx == DesktopLockMenuIndexGameMode) && (event->type == InputTypeShort)) {
|
||||
// desktop_view_lock_menu_dumbmode_changed(1);
|
||||
// DOLPHIN_DEED(getRandomDeed());
|
||||
// lock_menu->callback(DesktopLockMenuEventExit, lock_menu->context);
|
||||
|
||||
@@ -84,7 +84,8 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyDown) {
|
||||
main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
main_view->callback(DesktopMainEventOpenSubRemote, main_view->context); // OPENS SUBGHZ REMOTE
|
||||
main_view->callback(
|
||||
DesktopMainEventOpenSubRemote, main_view->context); // OPENS SUBGHZ REMOTE
|
||||
}
|
||||
}
|
||||
} else if(main_view->is_gamemode == true) {
|
||||
@@ -105,9 +106,11 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyUp) {
|
||||
main_view->callback(DesktopMainEventOpenDOOM, main_view->context); // OPENS DOOM
|
||||
} else if(event->key == InputKeyDown) {
|
||||
main_view->callback(DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez
|
||||
main_view->callback(
|
||||
DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
main_view->callback(DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS
|
||||
main_view->callback(
|
||||
DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -127,10 +130,12 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyUp) {
|
||||
main_view->callback(DesktopMainEventOpenSnake, main_view->context); // OPENS SNAKE
|
||||
} else if(event->key == InputKeyDown) {
|
||||
main_view->callback(DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez
|
||||
main_view->callback(
|
||||
DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
main_view->callback(DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS
|
||||
}
|
||||
main_view->callback(
|
||||
DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,10 +151,10 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent sme)
|
||||
consumed = true;
|
||||
break;
|
||||
// case SCENE_EVENT_SELECT_FAVORITE_GAME:
|
||||
// scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 2);
|
||||
// scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
// consumed = true;
|
||||
// break;
|
||||
// scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 2);
|
||||
// scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
// consumed = true;
|
||||
// break;
|
||||
case SCENE_EVENT_SELECT_PIN_SETUP:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
consumed = true;
|
||||
|
||||
@@ -19,16 +19,15 @@ static const Icon* const portrait_happy[7] = {
|
||||
&I_G0ku,
|
||||
&I_g0ku_1,
|
||||
&I_g0ku_2,
|
||||
&I_g0ku_3
|
||||
};
|
||||
&I_g0ku_3};
|
||||
// static const Icon* const portrait_ok[MOODS_TOTAL] = {
|
||||
// &I_passport_okay1_46x49,
|
||||
// &I_passport_okay2_46x49,
|
||||
// &I_passport_okay3_46x49};
|
||||
// &I_passport_okay1_46x49,
|
||||
// &I_passport_okay2_46x49,
|
||||
// &I_passport_okay3_46x49};
|
||||
// static const Icon* const portrait_bad[MOODS_TOTAL] = {
|
||||
// &I_passport_bad1_46x49,
|
||||
// &I_passport_bad2_46x49,
|
||||
// &I_passport_bad3_46x49};
|
||||
// &I_passport_bad1_46x49,
|
||||
// &I_passport_bad2_46x49,
|
||||
// &I_passport_bad3_46x49};
|
||||
|
||||
// static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad};
|
||||
static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy};
|
||||
@@ -49,8 +48,7 @@ static const char* const moods[16] = {
|
||||
"Annoyed",
|
||||
"Upset",
|
||||
"Angry",
|
||||
"Furious"
|
||||
};
|
||||
"Furious"};
|
||||
|
||||
static void input_callback(InputEvent* input, void* ctx) {
|
||||
FuriSemaphore* semaphore = ctx;
|
||||
@@ -87,7 +85,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
|
||||
// multipass
|
||||
canvas_draw_icon(canvas, 0, 0, &I_passport_DB);
|
||||
|
||||
|
||||
// portrait
|
||||
furi_assert((stats->level > 0) && (stats->level <= 30));
|
||||
uint16_t tmpLvl = 0;
|
||||
@@ -98,7 +96,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
if(stats->level > 24) tmpLvl = 5;
|
||||
if(stats->level > 27) tmpLvl = 6;
|
||||
canvas_draw_icon(canvas, 11, 2, portraits[mood][tmpLvl]);
|
||||
|
||||
|
||||
const char* my_name = furi_hal_version_get_name_ptr();
|
||||
snprintf(level_str, 12, "Level: %hu", stats->level);
|
||||
snprintf(xp_str, 12, "%lu/%lu", xp_above_last_levelup, xp_for_current_level);
|
||||
@@ -114,7 +112,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, 123 - xp_progress, 45, xp_progress + 1, 5);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t passport_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
@@ -142,8 +142,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati
|
||||
case KIADecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >=
|
||||
(uint32_t)(
|
||||
subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) {
|
||||
(uint32_t)(subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) {
|
||||
//Found stop bit
|
||||
instance->decoder.parser_step = KIADecoderStepReset;
|
||||
if(instance->decoder.decode_count_bit ==
|
||||
|
||||
Reference in New Issue
Block a user