/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved * See the LICENSE file for information about the license. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app_buffer.h" #define TAG "ProtoView" #define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100 #define BITMAP_SEEK_NOT_FOUND UINT32_MAX #define DEBUG_MSG 1 typedef struct ProtoViewApp ProtoViewApp; /* Subghz system state */ typedef enum { TxRxStateIDLE, TxRxStateRx, TxRxStateSleep, } TxRxState; /* Currently active view. */ typedef enum { ViewRawPulses, ViewInfo, ViewFrequencySettings, ViewModulationSettings, ViewLast, /* Just a sentinel to wrap around. */ } ProtoViewCurrentView; typedef struct { const char *name; FuriHalSubGhzPreset preset; uint8_t *custom; } ProtoViewModulation; extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ /* This is the context of our subghz worker and associated thread. * It receives data and we get our protocol "feed" callback called * with the level (1 or 0) and duration. */ struct ProtoViewTxRx { SubGhzWorker* worker; /* Our background worker. */ SubGhzEnvironment* environment; SubGhzReceiver* receiver; TxRxState txrx_state; /* Receiving, idle or sleeping? */ }; typedef struct ProtoViewTxRx ProtoViewTxRx; /* This stucture is filled by the decoder for specific protocols with the * informations about the message. ProtoView will display such information * in the message info view. */ #define PROTOVIEW_MSG_STR_LEN 32 typedef struct ProtoViewMsgInfo { char name[PROTOVIEW_MSG_STR_LEN]; /* Protocol name and version. */ char raw[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific raw representation.*/ /* The following is what the decoder wants to show to user. Each decoder * can use the number of fileds it needs. */ char info1[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 1. */ char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */ char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */ uint64_t len; /* Bits consumed from the stream. */ } ProtoViewMsgInfo; struct ProtoViewApp { /* GUI */ Gui *gui; ViewPort *view_port; /* We just use a raw viewport and we render everything into the low level canvas. */ ProtoViewCurrentView current_view; /* Active view ID. */ FuriMessageQueue *event_queue; /* Keypress events go here. */ /* Radio related. */ ProtoViewTxRx *txrx; /* Radio state. */ SubGhzSetting *setting; /* A list of valid frequencies. */ /* Generic app state. */ int running; /* Once false exists the app. */ uint32_t signal_bestlen; /* Longest coherent signal observed so far. */ bool signal_decoded; /* Was the current signal decoded? */ ProtoViewMsgInfo signal_info; /* Decoded message, if signal_decoded true. */ /* Raw view apps state. */ uint32_t us_scale; /* microseconds per pixel. */ uint32_t signal_offset; /* Long press left/right panning in raw view. */ /* Configuration view app state. */ uint32_t frequency; /* Current frequency. */ uint8_t modulation; /* Current modulation ID, array index in the ProtoViewModulations table. */ }; typedef struct ProtoViewDecoder { const char *name; /* Protocol name. */ /* The decode function takes a buffer that is actually a bitmap, with * high and low levels represented as 0 and 1. The number of high/low * pulses represented by the bitmap is passed as the 'numbits' argument, * while 'numbytes' represents the total size of the bitmap pointed by * 'bits'. So 'numbytes' is mainly useful to pass as argument to other * functions that perform bit extraction with bound checking, such as * bitmap_get() and so forth. */ bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info); } ProtoViewDecoder; extern RawSamplesBuffer *RawSamples, *DetectedSamples; /* app_radio.c */ void radio_begin(ProtoViewApp* app); uint32_t radio_rx(ProtoViewApp* app); void radio_idle(ProtoViewApp* app); void radio_rx_end(ProtoViewApp* app); void radio_sleep(ProtoViewApp* app); /* signal.c */ uint32_t duration_delta(uint32_t a, uint32_t b); void reset_current_signal(ProtoViewApp *app); void scan_for_signal(ProtoViewApp *app); bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos); void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val); void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat); void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len); bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits); uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits); uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern); /* view_*.c */ void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app); void process_input_raw_pulses(ProtoViewApp *app, InputEvent input); void render_view_settings(Canvas *const canvas, ProtoViewApp *app); void process_input_settings(ProtoViewApp *app, InputEvent input); void render_view_info(Canvas *const canvas, ProtoViewApp *app); void process_input_info(ProtoViewApp *app, InputEvent input); /* ui.c */ void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color);