./fbt format

This commit is contained in:
RogueMaster
2022-09-21 14:28:03 -04:00
parent 3f3258d9f3
commit 32e18d5500
37 changed files with 2764 additions and 2572 deletions
+133 -137
View File
@@ -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;
}
+2 -2
View File
@@ -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';
+31 -21
View File
@@ -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);
+289 -277
View File
@@ -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;
}
File diff suppressed because it is too large Load Diff
+129 -106
View File
@@ -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);
+26 -26
View File
@@ -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_ */
+75 -80
View File
@@ -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);
}
+8 -9
View File
@@ -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);
+67 -76
View File
@@ -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();
}
}
}
+15 -16
View File
@@ -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);
+2 -2
View File
@@ -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);
+1 -2
View File
@@ -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 ==