| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- #include <furi.h>
- #include <gui/gui.h>
- #include <input/input.h>
- #include <stdlib.h>
- #include <dolphin/dolphin.h>
- #include <notification/notification.h>
- #include <notification/notification_messages.h>
- #include "dcf77_app.h"
- uint8_t get_dcf_message_bit(uint8_t* message, uint8_t bit) {
- if(bit == 59 || bit == 0) {
- return 0;
- }
- uint8_t byte_ = bit / 8;
- uint8_t bit_ = bit % 8;
- uint8_t bit_value = *(message + byte_) & (1 << (7 - bit_));
- if(!!bit_value) {
- return 1;
- }
- return 0;
- }
- // should it still be const?
- static void update_dcf77_message_from_rtc(AppFSM* app_fsm) {
- DateTime dt;
- furi_hal_rtc_get_datetime(&dt);
- app_fsm->bit_number = dt.second;
- app_fsm->next_message = malloc(8);
- /*
- set_dcf_message(app_fsm->next_message, dt.minute, dt.hour,
- dt.day, dt.month, (uint8_t)(dt.year % 100), dt.weekday,
- false, false, false, false, 0x0000);
- */
- //set_dcf_message(app_fsm->next_message, 41, 17, 27, 12, 22, 2, false, false, false, false, 0x0000);
- app_fsm->tx_hour = 17;
- app_fsm->tx_minute = 41;
- app_fsm->tx_day = 27;
- app_fsm->tx_month = 12;
- app_fsm->tx_year = 22;
- app_fsm->tx_dow = 2;
- app_fsm->tx_hour = dt.hour;
- app_fsm->tx_minute = dt.minute;
- app_fsm->tx_day = dt.day;
- app_fsm->tx_month = dt.month;
- app_fsm->tx_year = dt.year % 100;
- app_fsm->tx_dow = dt.weekday;
- set_dcf_message(
- app_fsm->next_message,
- app_fsm->tx_minute,
- app_fsm->tx_hour,
- app_fsm->tx_day,
- app_fsm->tx_month,
- app_fsm->tx_year,
- app_fsm->tx_dow,
- false,
- false,
- false,
- false,
- 0x0000);
- app_fsm->buffer_swap_pending = true;
- }
- static void set_outputs(bool status, AppFSM* app_fsm) {
- UNUSED(app_fsm);
- static bool last;
- if(last != status) {
- if(status) {
- furi_hal_light_set(LightRed, 0xFF);
- furi_hal_light_set(LightGreen, 0x1F);
- // furi_hal_speaker_start(50, 1);
- } else {
- furi_hal_light_set(LightRed | LightGreen | LightBlue, 0);
- // furi_hal_speaker_stop();
- }
- }
- last = status;
- }
- static void comparator_trigger_callback(bool level, void* comp_ctx) {
- UNUSED(comp_ctx);
- furi_hal_gpio_write(&gpio_ext_pa7, !level);
- }
- void gpio_init() {
- furi_hal_gpio_write(OUTPUT_PIN, false);
- furi_hal_gpio_init(OUTPUT_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
- }
- void gpio_mark() {
- furi_hal_gpio_write(OUTPUT_PIN, true);
- }
- void gpio_space() {
- furi_hal_gpio_write(OUTPUT_PIN, false);
- }
- void gpio_deinit() {
- furi_hal_gpio_init(OUTPUT_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedVeryHigh);
- }
- void dcf77_lf_init(int freq, AppFSM* app_fsm) {
- /* // this ends up doing
- // LL_TIM_SetAutoReload(FURI_HAL_RFID_READ_TIMER, period);
- // LL_TIM_OC_SetCompareCH1(FURI_HAL_RFID_READ_TIMER, period*duty_cycle);
- */
- furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
- furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app_fsm);
- furi_hal_rfid_tim_read_start(freq, 0.5);
- furi_hal_rfid_pin_pull_release();
- }
- void dcf77_mark(int freq) {
- UNUSED(freq);
- furi_hal_rfid_comp_start();
- furi_hal_rfid_tim_read_continue();
- //furi_hal_rfid_tim_read_start(freq, 0.5);
- /* --- */
- furi_hal_rfid_comp_stop();
- furi_hal_rfid_tim_read_pause();
- }
- void dcf77_space() {
- furi_hal_rfid_comp_stop();
- furi_hal_rfid_tim_read_pause();
- }
- void dcf77_deinit() {
- dcf77_space();
- furi_hal_rfid_comp_stop();
- furi_hal_rfid_comp_set_callback(NULL, NULL);
- furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
- furi_hal_rfid_tim_read_stop();
- furi_hal_rfid_pins_reset();
- }
- static void render_callback(Canvas* const canvas, void* ctx) {
- furi_assert(ctx);
- AppFSM* app_fsm = ctx;
- furi_mutex_acquire(app_fsm->mutex, FuriWaitForever);
- char buffer[64];
- uint8_t yoffset = 9;
- uint8_t bit_number = app_fsm->bit_number;
- uint8_t bit_value = app_fsm->bit_value;
- uint8_t underline_x = (bit_number / 8) * 12 + 16;
- uint8_t byte_ = app_fsm->dcf77_message[bit_number / 8];
- char display_bits[9] = "00000000";
- if(app_fsm->buffer_swap_pending) {
- memcpy(app_fsm->dcf77_message, app_fsm->next_message, 8);
- canvas_draw_str_aligned(canvas, 112, 10, AlignCenter, AlignBottom, "*");
- app_fsm->buffer_swap_pending = false;
- }
- canvas_draw_frame(canvas, 0, 0, 128, 64);
- canvas_set_font(canvas, FontPrimary);
- snprintf(buffer, 64, "%1x.%1x=%01x", bit_number / 8, (bit_number % 8), bit_value);
- DateTime dt;
- furi_hal_rtc_get_datetime(&dt);
- //canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, "DCF77 emulator");
- snprintf(
- buffer,
- 64,
- "%02d:%02d %02d.%02d.%02d",
- app_fsm->tx_hour,
- app_fsm->tx_minute,
- app_fsm->tx_day,
- app_fsm->tx_month,
- app_fsm->tx_year);
- canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, buffer);
- if(app_fsm->debug_flag) {
- canvas_draw_str_aligned(canvas, 8, 10, AlignCenter, AlignBottom, "D");
- }
- snprintf(buffer, 64, "%1x.%1x=%01x", bit_number / 8, (bit_number % 8), bit_value);
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str_aligned(canvas, 64, 24 + (9 - yoffset), AlignCenter, AlignBottom, buffer);
- snprintf(buffer, 64, "%s (bit %d)", dcf77_bitnames[bit_number], bit_value);
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str_aligned(canvas, 64, 34 + (9 - yoffset), AlignCenter, AlignBottom, buffer);
- snprintf(
- buffer,
- 64,
- "%02x%02x%02x%02x%02x%02x%02x%02x",
- app_fsm->dcf77_message[0],
- app_fsm->dcf77_message[1],
- app_fsm->dcf77_message[2],
- app_fsm->dcf77_message[3],
- app_fsm->dcf77_message[4],
- app_fsm->dcf77_message[5],
- app_fsm->dcf77_message[6],
- app_fsm->dcf77_message[7]);
- canvas_set_font(canvas, FontKeyboard);
- canvas_draw_str_aligned(canvas, 64, 44 + (9 - yoffset), AlignCenter, AlignBottom, buffer);
- canvas_draw_line(canvas, underline_x, 45, underline_x + 10, 45);
- for(int i = 0; i < 8; i++) {
- if((byte_ & (1 << (7 - i))) != 0) {
- display_bits[i] = '1';
- }
- }
- canvas_set_font(canvas, FontKeyboard);
- snprintf(buffer, 64, "%02x=%s", byte_, display_bits);
- canvas_draw_str_aligned(
- canvas, 64, 54 + (9 - yoffset), AlignCenter, AlignBottom, buffer); // whole message
- underline_x = (bit_number % 8) * 6 + 49;
- canvas_draw_line(canvas, underline_x, 55, underline_x + 4, 55); // current byte
- furi_mutex_release(app_fsm->mutex);
- }
- static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
- furi_assert(event_queue);
- AppEvent event = {.type = EventKeyPress, .input = *input_event};
- furi_message_queue_put(event_queue, &event, FuriWaitForever);
- }
- static void timer_tick_callback(FuriMessageQueue* event_queue) {
- furi_assert(event_queue);
- AppEvent event = {.type = EventTimerTick};
- furi_message_queue_put(event_queue, &event, 0);
- }
- static void app_init(AppFSM* const app_fsm, FuriMessageQueue* event_queue) {
- app_fsm->counter = 0;
- app_fsm->dcf77_message = &dcf77_message_buffer[0];
- app_fsm->next_message = &dcf77_next_buffer[0];
- dcf77_lf_init(LF_FREQ, app_fsm);
- gpio_init();
- app_fsm->dcf77_message = malloc(8); // message had 60 bits since 1959 and is unlikely to change
- // app_fsm->next_message = malloc(8);
- update_dcf77_message_from_rtc(app_fsm);
- app_fsm->baseband_counter = 0;
- app_fsm->_event_queue = event_queue;
- FuriTimer* timer =
- furi_timer_alloc(timer_tick_callback, FuriTimerTypePeriodic, app_fsm->_event_queue);
- furi_timer_start(timer, furi_kernel_get_tick_frequency() / TIMER_HZ);
- app_fsm->_timer = timer;
- }
- static void app_deinit(AppFSM* const app_fsm) {
- dcf77_deinit();
- gpio_deinit();
- app_fsm->buffer_swap_pending = false;
- free(app_fsm->dcf77_message);
- furi_timer_free(app_fsm->_timer);
- }
- static void on_timer_tick(AppFSM* app_fsm) {
- static uint8_t last_second = 61;
- static bool last_output = false;
- bool output = true;
- DateTime dt;
- furi_hal_rtc_get_datetime(&dt);
- app_fsm->bit_number = dt.second;
- app_fsm->bit_value = get_dcf_message_bit(app_fsm->dcf77_message, app_fsm->bit_number);
- if(dt.second != last_second) {
- app_fsm->baseband_counter = 0;
- output = true;
- } else {
- app_fsm->baseband_counter++;
- }
- /*
- if (app_fsm->baseband_counter < 8)
- {
- app_fsm->debug_flag = true;
- }
- else
- {
- app_fsm->debug_flag = false;
- }*/
- if(dt.second == 0 && app_fsm->baseband_counter == 3) {
- update_dcf77_message_from_rtc(app_fsm);
- }
- if(dt.second == 59) {
- output = true;
- } else {
- if(app_fsm->baseband_counter > TIME_ZERO && app_fsm->bit_value == 0) {
- output = false;
- } else if(app_fsm->baseband_counter > TIME_ONE && app_fsm->bit_value == 1) {
- output = false;
- }
- }
- if(last_output != output) {
- set_outputs(output, app_fsm);
- if(!output) {
- dcf77_space();
- gpio_space();
- } else {
- dcf77_mark(LF_FREQ);
- gpio_mark();
- }
- }
- last_second = dt.second;
- last_output = output;
- }
- int32_t dcf77_app_main(void* p) {
- UNUSED(p);
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
- AppFSM* app_fsm = malloc(sizeof(AppFSM));
- app_init(app_fsm, event_queue);
- app_fsm->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
- if(!app_fsm->mutex) {
- FURI_LOG_E(TAG, "cannot create mutex\r\n");
- free(app_fsm);
- return 255;
- }
- ViewPort* view_port = view_port_alloc();
- view_port_draw_callback_set(view_port, render_callback, app_fsm);
- view_port_input_callback_set(view_port, input_callback, event_queue);
- // Open GUI and register view_port
- Gui* gui = furi_record_open(RECORD_GUI);
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
- NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
- notification_message_block(notification, &sequence_display_backlight_enforce_on);
- if(furi_hal_speaker_acquire(500)) {
- ;
- }
- dolphin_deed(DolphinDeedPluginGameStart);
- AppEvent event;
- for(bool processing = true; processing;) {
- FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
- furi_mutex_acquire(app_fsm->mutex, FuriWaitForever);
- if(event_status == FuriStatusOk) {
- // kepress events
- if(event.type == EventKeyPress) {
- if(event.input.type == InputTypeShort) {
- switch(event.input.key) {
- case InputKeyUp:
- app_fsm->last_key = KeyUp;
- break;
- case InputKeyDown:
- app_fsm->last_key = KeyDown;
- break;
- case InputKeyRight:
- app_fsm->last_key = KeyRight;
- break;
- case InputKeyLeft:
- app_fsm->last_key = KeyLeft;
- break;
- case InputKeyOk:
- app_fsm->last_key = KeyOK;
- app_fsm->counter = -5;
- break;
- case InputKeyBack:
- processing = false;
- break;
- default:
- break;
- }
- }
- // user events
- } else if(event.type == EventTimerTick) {
- FURI_CRITICAL_ENTER();
- on_timer_tick(app_fsm);
- FURI_CRITICAL_EXIT();
- }
- }
- furi_mutex_release(app_fsm->mutex);
- view_port_update(view_port);
- }
- furi_hal_speaker_release();
- notification_message_block(notification, &seq_c_minor);
- // Wait for all notifications to be played and return backlight to normal state
- app_deinit(app_fsm);
- notification_message_block(notification, &sequence_display_backlight_enforce_auto);
- view_port_enabled_set(view_port, false);
- gui_remove_view_port(gui, view_port);
- furi_record_close(RECORD_GUI);
- furi_record_close(RECORD_NOTIFICATION);
- view_port_free(view_port);
- furi_message_queue_free(event_queue);
- furi_mutex_free(app_fsm->mutex);
- free(app_fsm);
- return 0;
- }
|