From 14d8be069d8897eead25bcb2bc4ec337f7b7df84 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Sat, 24 Aug 2024 01:01:33 -0700 Subject: [PATCH] e-ink --- elink_src/images.h | 102 ++++++++++ elink_src/main.cpp | 456 +++++++++++++++++++++++++++++++++++++++++++++ include/ui.h | 9 +- platformio.ini | 34 +++- src/main.cpp | 58 +++--- src/ui.cpp | 20 +- 6 files changed, 651 insertions(+), 28 deletions(-) create mode 100644 elink_src/images.h create mode 100644 elink_src/main.cpp diff --git a/elink_src/images.h b/elink_src/images.h new file mode 100644 index 0000000..e33c6c3 --- /dev/null +++ b/elink_src/images.h @@ -0,0 +1,102 @@ +#define WiFi_Logo_width 60 +#define WiFi_Logo_height 36 +const uint8_t WiFi_Logo_bits[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, + 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xC0, 0xFF, + 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 0xFC, 0x77, 0x08, 0x00, + 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, + 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, + 0x70, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 0x1C, 0x70, + 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 0xC0, 0xFF, 0xFF, 0x1F, + 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, + 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, + 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char epd_bitmap_ucog[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x10, 0x84, 0xC3, 0x81, 0x03, 0x00, 0x60, 0x00, 0xCC, 0x07, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x30, 0xE6, 0xF3, 0xE3, 0x07, 0x00, 0x60, 0x00, 0x0C, 0x3E, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x30, 0x66, 0x10, 0x36, 0x00, 0x00, 0x60, 0x00, 0x06, 0xF8, + 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x30, 0x26, 0x18, 0x36, 0x00, 0x00, 0x60, 0x00, + 0x07, 0xE0, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x30, 0x26, 0x18, 0x36, 0x07, 0x00, + 0x60, 0x00, 0x03, 0x00, 0x1F, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x30, 0x26, 0x18, 0x36, + 0x06, 0x00, 0x60, 0x80, 0x01, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x30, 0x66, + 0x38, 0x76, 0x06, 0x0C, 0x60, 0xC0, 0x01, 0x00, 0xF0, 0x01, 0x78, 0x00, 0x00, 0x00, + 0xE0, 0xE3, 0xF3, 0xE3, 0x07, 0x0E, 0x60, 0xC0, 0x03, 0x00, 0x80, 0x0F, 0x1C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x60, 0xE0, 0x07, 0x00, 0x00, 0x3E, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x60, 0x60, 0x0E, 0x00, + 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x60, 0x70, + 0x1C, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, + 0x60, 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x60, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x00, 0xF0, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xFC, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xFE, 0x0F, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x67, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x61, 0x1C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, + 0x60, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x60, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0xE0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x67, 0xE0, 0x83, 0x03, 0x00, 0x00, 0xE0, 0xFF, 0xE1, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x63, 0x60, 0x07, 0x07, 0x00, 0xC0, 0xFF, + 0x03, 0x80, 0x03, 0x00, 0x00, 0x08, 0x00, 0x02, 0xF0, 0x61, 0x60, 0x1C, 0x1F, 0x80, + 0xFF, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, + 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x02, 0xF0, 0x7F, + 0x60, 0xDC, 0x1F, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x02, + 0xD0, 0x61, 0x60, 0x07, 0x0F, 0x00, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x67, 0xE0, 0x83, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xC1, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xE0, 0xC1, 0x01, 0x00, 0x00, 0x00, 0xF8, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x61, 0x1C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x67, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x00, 0xFC, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xF0, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x18, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x60, 0x30, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x60, 0x70, + 0x3C, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, + 0x60, 0x60, 0x1E, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x07, 0x60, 0xE0, 0x0F, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x03, 0x00, 0x0F, 0x60, 0xC0, 0x03, 0x00, 0x80, 0x0F, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x07, 0x00, 0x0C, 0x60, 0xC0, 0x01, 0x00, 0xF0, 0x01, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x81, 0x05, 0x00, 0x08, 0x60, 0xC0, 0x01, 0x00, 0x7C, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x0C, 0x00, 0x00, 0x60, 0x00, 0x03, 0x00, + 0x1F, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x0C, 0x00, 0x00, 0x60, 0x00, + 0x07, 0xE0, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x0F, 0x00, 0x00, + 0x60, 0x00, 0x06, 0xF8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x1F, + 0x00, 0x00, 0x60, 0x00, 0x0E, 0x3E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x80, + 0x67, 0x18, 0x00, 0x00, 0x60, 0x00, 0xCC, 0x07, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xFC, 0x01, 0x00, 0x00, + 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, +}; diff --git a/elink_src/main.cpp b/elink_src/main.cpp new file mode 100644 index 0000000..4829431 --- /dev/null +++ b/elink_src/main.cpp @@ -0,0 +1,456 @@ +/* Heltec Automation Ink screen example + * NOTE!!!: to upload we neew code you need to press button BOOT and RESET or you will + * have serial error. After upload you need reset device... + * + * Function: + * 1. Ink screen full brush demonstration + * + * Description: + * 1.Inherited from ssd1306 for drawing points, lines, and functions + * + * */ + +#include "HT_DEPG0290BxS800FxX_BW.h" +#include "global_config.h" +#include "images.h" +#include "ui.h" +#include + +// Disabling default lib display +#define HELTEC_NO_DISPLAY +#define DISPLAY_WIDTH 296 +#define DISPLAY_HEIGHT 128 +// Without this line Lora Radio doesn't work +#define ARDUINO_heltec_wifi_32_lora_V3 +#include "heltec_unofficial.h" +#include "modules/SX126x/patches/SX126x_patch_scan.h" + +// <--- Spectrum display Varriables START +#define SCAN_METHOD +#define METHOD_SPECTRAL +// numbers of the spectrum screan lines = width of screan +#define STEPS 296 // 128 +// Number of samples for each scan. Fewer samples = better temporal resolution. +#define MAX_POWER_LEVELS 33 +// multiplies STEPS * N to increase scan resolution. +#define SCAN_RBW_FACTOR 1 // 2 +// Print spectrum values pixels at once or by line +bool ANIMATED_RELOAD = false; +// Remove reading without neighbors +#define FILTER_SPECTRUM_RESULTS true +#define FILTER_SAMPLES_MIN +constexpr bool DRAW_DETECTION_TICKS = true; +// Number of samples for each frequency scan. Fewer samples = better temporal resolution. +// if more than 100 it can freez +#define SAMPLES 35 //(scan time = 1294) +// number of samples for RSSI method +#define SAMPLES_RSSI 30 // 21 // + +#define FREQ_BEGIN 750 + +#define RANGE (int)(FREQ_END - FREQ_BEGIN) + +#define SINGLE_STEP (float)(RANGE / (STEPS * SCAN_RBW_FACTOR)) + +uint64_t range = (int)(FREQ_END - FREQ_BEGIN); +uint64_t fr_begin = FREQ_BEGIN; +uint64_t fr_end = FREQ_BEGIN; + +// Feature to scan diapazones. Other frequency settings will be ignored. +// int SCAN_RANGES[] = {850890, 920950}; +int SCAN_RANGES[] = {}; + +// MHZ per page +// to put everething into one page set RANGE_PER_PAGE = FREQ_END - 800 +// uint64_t RANGE_PER_PAGE = FREQ_END - FREQ_BEGIN; // FREQ_END - FREQ_BEGIN + +// Override or e-ink +uint64_t RANGE_PER_PAGE = FREQ_BEGIN + DISPLAY_WIDTH; + +uint64_t iterations = RANGE / RANGE_PER_PAGE; + +// uint64_t range_frequency = FREQ_END - FREQ_BEGIN; +uint64_t median_frequency = FREQ_BEGIN + FREQ_END - FREQ_BEGIN / 2; + +// #define DISABLE_PLOT_CHART false // unused + +// Array to store the scan results +uint16_t result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; +uint16_t result_display_set[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; +uint16_t result_detections[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; +uint16_t filtered_result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; + +// Waterfall array +bool waterfall[STEPS], detected_y[STEPS]; // 20 - ??? steps of the waterfall + +// global variable + +// Used as a Led Light and Buzzer/count trigger +bool first_run, new_pixel, detected_x = false; +// drone detection flag +bool detected = false; +uint64_t drone_detection_level = DEFAULT_DRONE_DETECTION_LEVEL; +uint64_t drone_detected_frequency_start = 0; +uint64_t drone_detected_frequency_end = 0; +uint64_t detection_count = 0; +bool single_page_scan = false; +bool SOUND_ON = false; + +// #define PRINT_DEBUG +#define PRINT_PROFILE_TIME + +#ifdef PRINT_PROFILE_TIME +uint64_t loop_start = 0; +uint64_t loop_time = 0; +uint64_t scan_time = 0; +uint64_t scan_start_time = 0; +#endif + +uint64_t x, y, range_item, w = WATERFALL_START, i = 0; +int osd_x = 1, osd_y = 2, col = 0, max_bin = 32; +uint64_t ranges_count = 0; + +float freq = 0; +int rssi = 0; +int state = 0; + +#ifdef METHOD_SPECTRAL +constexpr int samples = SAMPLES; +#endif +#ifdef METHOD_RSSI +constexpr int samples = SAMPLES_RSSI; +#endif + +uint8_t result_index = 0; +uint8_t button_pressed_counter = 0; +uint64_t loop_cnt = 0; +// <--- Spectrum display Varriables END + +// Initialize the display +DEPG0290BxS800FxX_BW display(5, 4, 3, 6, 2, 1, -1, + 6000000); // rst,dc,cs,busy,sck,mosi,miso,frequency +typedef void (*Demo)(void); +/* screen rotation + * ANGLE_0_DEGREE + * ANGLE_90_DEGREE + * ANGLE_180_DEGREE + * ANGLE_270_DEGREE + */ +#define DIRECTION ANGLE_0_DEGREE +int demoMode = 0; + +void init_radio() +{ + // initialize SX1262 FSK modem at the initial frequency + Serial.println("Init radio"); + RADIOLIB_OR_HALT(radio.beginFSK(FREQ_BEGIN)); + + // upload a patch to the SX1262 to enable spectral scan + // NOTE: this patch is uploaded into volatile memory, + // and must be re-uploaded on every power up + Serial.println("Upload SX1262 patch"); + + // Upload binary patch into the SX126x device RAM. Patch is needed to e.g., + // enable spectral scan and must be uploaded again on every power cycle. + RADIOLIB_OR_HALT(radio.uploadPatch(sx126x_patch_scan, sizeof(sx126x_patch_scan))); + // configure scan bandwidth and disable the data shaping + + Serial.println("Setting up radio"); + RADIOLIB_OR_HALT(radio.setRxBandwidth(BANDWIDTH)); + + // and disable the data shaping + RADIOLIB_OR_HALT(radio.setDataShaping(RADIOLIB_SHAPING_NONE)); + Serial.println("Starting scanning..."); + + // calibrate only once ,,, at startup + // TODO: check documentation (9.2.1) if we must calibrate in certain ranges + radio.setFrequency(FREQ_BEGIN, true); + delay(50); +} + +#define HEIGHT 4 +DEPG0290BxS800FxX_BW display_instance = display; +/** + * @brief Draws ticks on the display at regular whole intervals. + * + * @param every The interval between ticks in MHz. + * @param length The length of each tick in pixels. + */ +void drawTicks(float every, int length) +{ + int first_tick; + bool correction; + int pixels_per_step; + int correction_number; + int tick; + int tick_minor; + int median; + + first_tick = 0; + //+ (every - (fr_begin - (int)(fr_begin / every) * every)); + /*if (first_tick < fr_begin) + { + first_tick += every; + }*/ + correction = false; + pixels_per_step = STEPS / (RANGE_PER_PAGE / every); + if (STEPS / RANGE_PER_PAGE != 0) + { + correction = true; + } + correction_number = STEPS - (int)(pixels_per_step * (RANGE_PER_PAGE / every)); + tick = 0; + tick_minor = 0; + median = (RANGE_PER_PAGE / every) / 2; + // TODO: (RANGE_PER_PAGE / every) + // * 2 has twice extra steps we need to figureout correct logic or minor + // ticks is not showing to the end + for (int t = 0; t <= (RANGE_PER_PAGE / every) * 2; t++) + { + // fix if pixels per step is not int and we have shift + if (correction && t % 2 != 0 && correction_number > 1) + { + // pixels_per_step++; + correction_number--; + } + tick += pixels_per_step; + tick_minor = tick / 2; + if (tick <= 128 - 3) + { + display_instance.drawLine(tick, HEIGHT + X_AXIS_WEIGHT, tick, + HEIGHT + X_AXIS_WEIGHT + length); + // Central tick + if (tick > (128 / 2) - 3 && tick < (128 / 2) + 3) + { + display_instance.drawLine(tick + 1, HEIGHT + X_AXIS_WEIGHT, tick + 1, + HEIGHT + X_AXIS_WEIGHT + length); + } + } +#ifdef MINOR_TICKS + // Fix two ticks together + if ((tick_minor + 1 != tick) && (tick_minor - 1 != tick) && + (tick_minor + 2 != tick) && (tick_minor - 2 != tick)) + { + display_instance.drawLine(tick_minor, HEIGHT + X_AXIS_WEIGHT, tick_minor, + HEIGHT + X_AXIS_WEIGHT + MINOR_TICK_LENGTH); + } + // Central tick + if (tick_minor > (128 / 2) - 3 && tick_minor < (128 / 2) + 3) + { + display_instance.drawLine(tick_minor + 1, HEIGHT + X_AXIS_WEIGHT, + tick_minor + 1, + HEIGHT + X_AXIS_WEIGHT + MINOR_TICK_LENGTH); + } +#endif + } +} + +void drawFontFaceDemo() +{ + // Font Demo1 + // create more fonts at http://oleddisplay.squix.ch/ + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + display.drawString(0, 0, "Spectrum Analizer Lora SA"); + display.setFont(ArialMT_Plain_16); + display.drawString(0, 10, "SX 1262"); + display.setFont(ArialMT_Plain_24); + display.drawString(0, 26, "e-ink display"); +} +void drawTextFlowDemo() +{ + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawStringMaxWidth( + 0, 0, DISPLAY_HEIGHT, + "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy " + "eirmod tempor invidunt ut labore."); +} +void drawTextAlignmentDemo() +{ + // Text alignment demo + char str[30]; + int x = 0; + int y = 0; + display.setFont(ArialMT_Plain_10); + // The coordinates define the left starting point of the text + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawString(x, y, "Left aligned (0,0)"); + // The coordinates define the center of the text + display.setTextAlignment(TEXT_ALIGN_CENTER); + x = display.width() / 2; + y = display.height() / 2 - 5; + sprintf(str, "Center aligned (%d,%d)", x, y); + display.drawString(x, y, str); + // The coordinates define the right end of the text + display.setTextAlignment(TEXT_ALIGN_RIGHT); + x = display.width(); + y = display.height() - 12; + sprintf(str, "Right aligned (%d,%d)", x, y); + display.drawString(x, y, str); +} +void drawRectDemo() +{ + // Draw a pixel at given position + for (int i = 0; i < 10; i++) + { + display.setPixel(i, i); + display.setPixel(10 - i, i); + } + display.drawRect(12, 12, 20, 20); + // Fill the rectangle + display.fillRect(14, 14, 17, 17); + // Draw a line horizontally + display.drawHorizontalLine(0, 40, 20); + // Draw a line horizontally + display.drawVerticalLine(40, 0, 20); +} +void drawCircleDemo() +{ + int x = display.width() / 4; + int y = display.height() / 2; + for (int i = 1; i < 8; i++) + { + display.setColor(WHITE); + display.drawCircle(x, y, i * 3); + if (i % 2 == 0) + { + display.setColor(BLACK); + } + int x = display.width() / 4 * 3; + display.fillCircle(x, y, 32 - i * 3); + } +} +void drawImageDemo() +{ + // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html + // on how to create xbm files + int x = display.width() / 2 - WiFi_Logo_width / 2; + int y = display.height() / 2 - WiFi_Logo_height / 2; + display.drawXbm(x, y, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits); +} +void VextON(void) +{ + pinMode(18, OUTPUT); + digitalWrite(18, HIGH); +} +void VextOFF(void) // Vext default OFF +{ + pinMode(18, OUTPUT); + digitalWrite(18, LOW); +} + +int lower_level = 108; +int up_level = 40; +int rssiToPix(int rssi) +{ + // Bigger is lower signal + if (abs(rssi) >= lower_level) + { + return lower_level - 1; + } + if (abs(rssi) <= up_level) + { + return up_level; + } + return abs(rssi); +} + +Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, + drawRectDemo, drawCircleDemo, drawImageDemo}; +int demoLength = (sizeof(demos) / sizeof(Demo)); +long timeSinceLastModeSwitch = 0; + +float fr = FREQ_BEGIN; +int rssi2 = 0; +int x1 = 0, y2 = 0; +unsigned int loop_counter = 1; +void loop() +{ + radio.setFrequency(fr, false); // false = no calibration need here + for (int i = 0; i < SAMPLES_RSSI; i++) + { + if (i % 2 == 0) + radio.setFrequency((float)fr + 0.33, false); + else if (i % 3 == 0) + radio.setFrequency((float)fr + 0.33, false); + rssi2 = radio.getRSSI(false); + if (rssi2 > lower_level) + continue; + // Serial.println(String(fr) + ":" + String(rssi2)); + // display.drawString(x1, (int)y2, String(fr) + ":" + String(rssi2)); + display.setPixel(x1, rssiToPix(rssi2)); + } + + fr++; + x1++; + if (x1 >= STEPS) + { + if (loop_counter > STEPS * 5) + { + loop_counter = 0; + // Draw a line horizontally + display.drawHorizontalLine(0, lower_level + 1, DISPLAY_WIDTH); + for (int x = 0; x < DISPLAY_WIDTH; x++) + { + if (x % (DISPLAY_WIDTH / 2) == 0 && x > 5) + { + display.drawVerticalLine(x, lower_level + 1, 8); + display.drawVerticalLine(x - 1, lower_level + 1, 8); + display.drawVerticalLine(x + 1, lower_level + 1, 8); + } + if (x % 10 == 0 || x == 0) + display.drawVerticalLine(x, lower_level + 1, 6); + if (x % 5 == 0) + display.drawVerticalLine(x, lower_level + 1, 3); + } + display.setFont(ArialMT_Plain_10); + + display.drawString(1, DISPLAY_HEIGHT - 10, String(FREQ_BEGIN)); + display.drawString(DISPLAY_WIDTH - 24, DISPLAY_HEIGHT - 10, String(fr)); + display.drawString((DISPLAY_WIDTH / 2) - 10, DISPLAY_HEIGHT - 10, + String(FREQ_BEGIN + ((fr - FREQ_BEGIN) / 2))); + + display.display(); + // delay(2000); + if (loop_counter == 0) + { + display.clear(); + } + } + fr = FREQ_BEGIN; + x1 = 0; + } + loop_counter++; +} + +void setup() +{ + // Initialising the UI will init the display too. + display.init(); + display.screenRotate(DIRECTION); + display.setFont(ArialMT_Plain_10); + display.clear(); + display.drawXbm((DISPLAY_WIDTH / 3) - 10, DISPLAY_HEIGHT / 4, 128, 60, + epd_bitmap_ucog); + display.display(); + delay(2000); + display.clear(); + Serial.begin(115200); + w = WATERFALL_START; + init_radio(); + state = radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_NONE); + if (state != RADIOLIB_ERR_NONE) + { + Serial.print(F("Failed to start receive mode, error code: ")); + Serial.println(state); + } + heltec_setup(); + Serial.println(); + Serial.println(); + drawFontFaceDemo(); + display.display(); + delay(1000); + VextON(); + display.clear(); +} diff --git a/include/ui.h b/include/ui.h index 2dcaa96..2ca7525 100644 --- a/include/ui.h +++ b/include/ui.h @@ -1,9 +1,12 @@ - #pragma once +#ifdef Vision_Master_E290 +#include "HT_DEPG0290BxS800FxX_BW.h" +#else #include "OLEDDisplayUi.h" #include "SSD1306Wire.h" #include +#endif // #include @@ -29,7 +32,11 @@ #define SCREEN_HEIGHT 64 // ???? not used // publish functions +#ifdef Vision_Master_E290 +extern void UI_Init(DEPG0290BxS800FxX_BW *); +#else extern void UI_Init(SSD1306Wire *); +#endif extern void UI_displayDecorate(int, int, bool); extern void UI_setLedFlag(bool); extern void UI_clearPlotter(void); diff --git a/platformio.ini b/platformio.ini index 5c24979..634c9a4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,6 +8,12 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html +[platformio] +;; for env:vision-master-e290 +;;src_dir = elink_src +;; for env:heltec_wifi_lora_32_V3 +;;src_dir = src + [env:heltec_wifi_lora_32_V3] platform = espressif32 board = heltec_wifi_lora_32_V3 @@ -15,5 +21,31 @@ framework = arduino upload_speed = 115200 monitor_speed = 115200 board_build.f_cpu = 240000000 -lib_deps = ropg/Heltec_ESP32_LoRa_v3@^0.9.1 +lib_deps = + ropg/Heltec_ESP32_LoRa_v3@^0.9.1 build_flags = -DHELTEC_POWER_BUTTON + +[env:vision-master-e290] +platform = espressif32 +board = heltec_wifi_lora_32_V3 +framework = arduino +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder +board_upload.use_1200bps_touch = true +build_flags = + -D HELTEC_BOARD=37 + -D SLOW_CLK_TPYE=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D LoRaWAN_DEBUG_LEVEL=0 + -D E290 + -D ESP32 + -D Vision_Master_E290 + -D RADIOLIB_EXCLUDE_CC1101=1 + -D RADIOLIB_EXCLUDE_LR11x0=1 +lib_deps = + SPI + Wire + adafruit/Adafruit BusIO @ 1.9.6 + https://github.com/HelTecAutomation/Heltec_ESP32/ + adafruit/Adafruit GFX Library@^1.11.10 + ropg/Heltec_ESP32_LoRa_v3@^0.9.1 diff --git a/src/main.cpp b/src/main.cpp index 6d3d619..be47549 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,8 @@ https://jgromes.github.io/RadioLib/ */ +// #define HELTEC_NO_DISPLAY + #include #include // This file contains a binary patch for the SX1262 @@ -241,7 +243,7 @@ uint64_t scan_time = 0; uint64_t scan_start_time = 0; #endif -uint64_t x, y, range_item, w, i = 0; +uint64_t x, y, range_item, w = WATERFALL_START, i = 0; int osd_x = 1, osd_y = 2, col = 0, max_bin = 32; uint64_t ranges_count = 0; @@ -473,6 +475,35 @@ void osdProcess() } #endif +void init_radio() +{ + // initialize SX1262 FSK modem at the initial frequency + both.println("Init radio"); + RADIOLIB_OR_HALT(radio.beginFSK(FREQ_BEGIN)); + + // upload a patch to the SX1262 to enable spectral scan + // NOTE: this patch is uploaded into volatile memory, + // and must be re-uploaded on every power up + both.println("Upload SX1262 patch"); + + // Upload binary patch into the SX126x device RAM. Patch is needed to e.g., + // enable spectral scan and must be uploaded again on every power cycle. + RADIOLIB_OR_HALT(radio.uploadPatch(sx126x_patch_scan, sizeof(sx126x_patch_scan))); + // configure scan bandwidth and disable the data shaping + + both.println("Setting up radio"); + RADIOLIB_OR_HALT(radio.setRxBandwidth(BANDWIDTH)); + + // and disable the data shaping + RADIOLIB_OR_HALT(radio.setDataShaping(RADIOLIB_SHAPING_NONE)); + both.println("Starting scanning..."); + + // calibrate only once ,,, at startup + // TODO: check documentation (9.2.1) if we must calibrate in certain ranges + radio.setFrequency(FREQ_BEGIN, true); + delay(50); +} + void setup(void) { // LED brightness @@ -517,26 +548,8 @@ void setup(void) } } - // initialize SX1262 FSK modem at the initial frequency - both.println("Init radio"); - RADIOLIB_OR_HALT(radio.beginFSK(FREQ_BEGIN)); + init_radio(); - // upload a patch to the SX1262 to enable spectral scan - // NOTE: this patch is uploaded into volatile memory, - // and must be re-uploaded on every power up - both.println("Upload SX1262 patch"); - - // Upload binary patch into the SX126x device RAM. Patch is needed to e.g., - // enable spectral scan and must be uploaded again on every power cycle. - RADIOLIB_OR_HALT(radio.uploadPatch(sx126x_patch_scan, sizeof(sx126x_patch_scan))); - // configure scan bandwidth and disable the data shaping - - both.println("Setting up radio"); - RADIOLIB_OR_HALT(radio.setRxBandwidth(BANDWIDTH)); - - // and disable the data shaping - RADIOLIB_OR_HALT(radio.setDataShaping(RADIOLIB_SHAPING_NONE)); - both.println("Starting scanning..."); vbat = heltec_vbat(); both.printf("V battery: %.2fV (%d%%)\n", vbat, heltec_battery_percent(vbat)); #ifdef WIFI_SCANNING_ENABLED @@ -610,11 +623,6 @@ void setup(void) display.clear(); Serial.println(); - // calibrate only once ,,, at startup - // TODO: check documentation (9.2.1) if we must calibrate in certain ranges - radio.setFrequency(FREQ_BEGIN, true); - delay(50); - #ifdef METHOD_RSSI // TODO: try RADIOLIB_SX126X_RX_TIMEOUT_INF state = radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_NONE); diff --git a/src/ui.cpp b/src/ui.cpp index 2760253..48a7bf1 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -18,9 +18,12 @@ static bool ui_initialized = false; static bool led_flag = false; static unsigned short int scan_progress_count = 0; +#ifdef Vision_Master_E290 +static DEPG0290BxS800FxX_BW *display_instance; +#else //(0x3c, SDA_OLED, SCL_OLED, DISPLAY_GEOMETRY); static SSD1306Wire *display_instance; - +#endif // temporary dirty import ... to be solved durring upcoming refactoring extern unsigned int drone_detection_level; extern unsigned int RANGE_PER_PAGE; @@ -37,6 +40,7 @@ extern unsigned int range_item; extern uint64_t loop_time; +#ifndef Vision_Master_E290 void UI_Init(SSD1306Wire *display_ptr) { // init pointer to display instance. @@ -47,6 +51,20 @@ void UI_Init(SSD1306Wire *display_ptr) display_instance->drawXbm(0, 2, 128, 64, epd_bitmap_ucog); display_instance->display(); } +#endif + +#ifdef Vision_Master_E290 +void UI_Init(DEPG0290BxS800FxX_BW *display_ptr) +{ + // init pointer to display instance. + display_instance = display_ptr; + // check for null ??? + display_instance->clear(); + // draw the UCOG welcome logo + display_instance->drawXbm(0, 2, 128, 64, epd_bitmap_ucog); + display_instance->display(); +} +#endif void UI_setLedFlag(bool new_status) { led_flag = new_status; }