From 2e3d413309905f6facbb011e29cda40b5fd86815 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Tue, 13 Aug 2024 03:12:29 -0700 Subject: [PATCH] OSD integration --- include/DFRobot_OSD.cpp | 224 +++++++++++++++++++++++++++++++++++++++ include/DFRobot_OSD.h | 228 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 169 +++++++++++++++++++++++++++-- 3 files changed, 612 insertions(+), 9 deletions(-) create mode 100644 include/DFRobot_OSD.cpp create mode 100644 include/DFRobot_OSD.h diff --git a/include/DFRobot_OSD.cpp b/include/DFRobot_OSD.cpp new file mode 100644 index 0000000..66a1941 --- /dev/null +++ b/include/DFRobot_OSD.cpp @@ -0,0 +1,224 @@ +/*! + * @file DFRobot_OSD.cpp + * @brief Define the infrastructure DFRobot_OSD class + * @details This is a Library for OSD,the function is the superposition of characters. + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @license The MIT License (MIT) + * @author [Luyuhao](yuhao.lu@dfrobot.com) + * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) + * @version V1.0 + * @date 2022-05-19 + * @url https://github.com/DFRobot/DFRobot_OSD + */ +#include +#include + +void DFRobot_OSD::writeAddrData(unsigned char addr, unsigned char value) +{ + digitalWrite(nCS, LOW); + SPI.transfer(addr); + SPI.transfer(value); + digitalWrite(nCS, HIGH); +} + +void DFRobot_OSD::writeData(unsigned char value) +{ + digitalWrite(nCS, LOW); + SPI.transfer(value); + digitalWrite(nCS, HIGH); +} + +void DFRobot_OSD::clear(void) +{ + unsigned int i; + writeAddrData(DMAH, 0x00); // address + writeAddrData(DMAL, 0); + writeAddrData(DMM, 0x01); + for (i = 0; i < (16 * 30); i++) + { + writeData(0); + } + writeData(0xff); +} + +void DFRobot_OSD::displayChar(unsigned char row, unsigned char col, unsigned short addr) +{ + unsigned short k; + unsigned char addrH, j; + + k = row * 30 + col; + addrH = k >> 8; + writeAddrData(OSDBL, 0X00); + writeAddrData(DMM, 0x40); + writeAddrData(DMAH, addrH | 0x2); + writeAddrData(DMAL, k); + j = CHAR_LBC << 5; + if ((addr >> 8) != 0) + j |= 0x10; + writeAddrData(DMDI, j); + writeAddrData(DMAH, addrH); + writeAddrData(DMAL, k); + writeAddrData(DMDI, addr); + writeAddrData(VM0, 0x48); +} + +void DFRobot_OSD::displayString(unsigned char row, unsigned char col, const char *s) +{ + unsigned short k; + unsigned char addrH, j; + unsigned char c; + unsigned short value; + c = *s++; + int flag = 0; + k = row * 30 + col; + writeAddrData(OSDBL, 0X00); + while (c != 0) + { + flag = 0; + int i = 0; + for (i = 0; i < 34; i++) + { + if (c == tAsciiAddr[i].ascii) + { + value = tAsciiAddr[i].addr; + flag = 1; + } + } + if (flag == 0) + { + if ((c >= '0') && (c <= '9')) + value = ((c == '0') ? 10 : c - '1' + 1); + else if ((c >= 'A') && (c <= 'Z')) + value = (c - 'A' + 11); + else if ((c >= 'a') && (c <= 'z')) + value = (c - 'a' + 37); + else + value = (0x00); + } + + addrH = k >> 8; + writeAddrData(DMM, 0x40); + writeAddrData(DMAH, addrH | 0x2); + writeAddrData(DMAL, k); + j = CHAR_LBC << 5; + if ((value >> 8) != 0) + j |= 0x10; + writeAddrData(DMDI, j); + writeAddrData(DMAH, addrH); + writeAddrData(DMAL, k); + writeAddrData(DMDI, value); + c = *s++; + k = k + 1; + } + writeAddrData(VM0, 0x48); +} + +void DFRobot_OSD::displayString(unsigned char row, unsigned char col, String s) +{ + const char *str = s.c_str(); + displayString(row, col, str); +} + +void DFRobot_OSD::init(int SCK, int MISO, int MOSI) +{ + pinMode(nCS, OUTPUT); + SPI.begin(SCK, MISO, MOSI); + writeAddrData(VM0, 0x42); // Software Reset, takes 100us, PAL/NTSC???? + writeAddrData(DMAH, 0x00); // address + writeAddrData(DMAL, 68); + writeAddrData(OSDM, 0x00); +} + +DFRobot_OSD::DFRobot_OSD(int CS) { nCS = CS; } + +DFRobot_OSD::~DFRobot_OSD() {} + +void DFRobot_OSD::writeAT7456E(unsigned short addr, int *dt) +{ + unsigned char addrH, n; + addrH = (addr >> 8); + + writeAddrData(VM0, (0x00)); + delay(30); + writeAddrData(CMAH, addr); + + writeAddrData(DMM, 0); + + for (n = 0; n < 54; n++) + { + char i = *dt; + writeAddrData(CMAL, n | (addrH << 6)); + writeAddrData(CMDI, i); + dt++; + } + writeAddrData(CMM, RAM_NVM); + delay(10); + + writeAddrData(VM0, 0x01 << 3); +} + +void DFRobot_OSD::storeChar(unsigned short addr, int temp[]) +{ + int buf[54] = {0}; + int dt[54] = {0}; + int i = 0; + int n = 0; + int *p; + for (i = 0; i < 54; i++) + { + if (i < 8) + { + dt[i] = 0; + } + else + dt[i] = temp[i - 8]; + } + for (i = 0; i < 18; i++) + { + p = extend(dt[i * 2]); + buf[n++] = *p; + buf[n++] = *(p + 1); + p = extend(dt[i * 2 + 1]); + buf[n++] = *p; + } + writeAT7456E(addr, buf); +} + +int *DFRobot_OSD::extend(int src) +{ + int i = 0; + src = unified(src); + static int tar[2]; + tar[0] = 0; + tar[1] = 0; + for (i = 0; i < 4; i++) + { + if ((src >> i) & 0x01) + { + tar[0] = 0x02 | (tar[0] << 2); + } + else + tar[0] = 0x01 | (tar[0] << 2); + } + for (i = 4; i < 8; i++) + { + if ((src >> i) & 0x01) + { + tar[1] = 0x02 | (tar[1] << 2); + } + else + tar[1] = 0x01 | (tar[1] << 2); + } + return tar; +} + +int DFRobot_OSD::unified(int src) +{ + int num = 0; + int i = 0; + for (i = 0; i < 8; i++) + { + num = (num << 1) | ((src >> i) & 0x01); + } + return num; +} diff --git a/include/DFRobot_OSD.h b/include/DFRobot_OSD.h new file mode 100644 index 0000000..4b07007 --- /dev/null +++ b/include/DFRobot_OSD.h @@ -0,0 +1,228 @@ +/*! + * @file DFRobot_OSD.h + * @brief Define infrastructure of DFRobot_OSD class + * @details This is a Library for OSD,the function is the superposition of characters. + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @license The MIT License (MIT) + * @author [Luyuhao](yuhao.lu@dfrobot.com) + * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) + * @version V1.0 + * @date 2022-05-19 + * @url https://github.com/DFRobot/DFRobot_OSD + */ +#ifndef _DFRobot_OSD_H_ +#define _DFRobot_OSD_H_ + +#include + + +// #define ENABLE_DBG //!< Open this macro and you can see the details of the program +#ifdef ENABLE_DBG + #define DBG(...) {Serial.print("[");Serial.print(__FUNCTION__); Serial.print("(): "); Serial.print(__LINE__); Serial.print(" ] "); Serial.println(__VA_ARGS__);} +#else + #define DBG(...) +#endif + + +/* at7456 */ +#define VM0 0x00 ///< Video Mode0 +#define VM1 0x01 ///< Video Mode1 +#define HOS 0x02 ///< Horizontal Offset +#define VOS 0x03 ///< Vertical Offset +#define DMM 0x04 ///< Display Memory Mode +#define DMAH 0x05 ///< Display Memory Address High +#define DMAL 0x06 ///< Display Memory Address Low +#define DMDI 0x07 ///< Display Memory Data In +#define CMM 0x08 ///< Character Memory Mode +#define CMAH 0x09 ///< Character Memory Address High +#define CMAL 0x0a ///< Character Memory Address Low +#define CMDI 0x0b ///< Character Memory Data In +#define OSDM 0x0c ///< OSD Insertion Mux +#define RB0 0x10 ///< Row 0 Brightness +#define RB1 0x11 ///< Row 1 Brightness +#define RB2 0x12 ///< Row 2 Brightness +#define RB3 0x13 ///< Row 3 Brightness +#define RB4 0x14 ///< Row 4 Brightness +#define RB5 0x15 ///< Row 5 Brightness +#define RB6 0x16 ///< Row 6 Brightness +#define RB7 0x17 ///< Row 7 Brightness +#define RB8 0x18 ///< Row 8 Brightness +#define RB9 0x19 ///< Row 9 Brightness +#define RB10 0x1a ///< Row 10 Brightness +#define RB11 0x1b ///< Row 11 Brightness +#define RB12 0x1c ///< Row 12 Brightness +#define RB13 0x1d ///< Row 13 Brightness +#define RB14 0x1e ///< Row 14 Brightness +#define RB15 0x1f ///< Row 15 Brightness +#define OSDBL 0x6c ///< OSD Black Level +#define STAT 0x20 ///< Status +#define DMDO 0x30 ///< Display Memory Data Out +#define CMDO 0x40 ///< Character Memory Data Out +#define NVM_RAM 0x50 ///< Read the fonts in the NVM into the mirror RAM +#define RAM_NVM 0xa0 ///< Write the database data in the mirror RAM to the NVM +/* VM0 */ +#define NTSC (0 << 6) ///< D6 --- Vidoe Standard Select +#define PAL (1 << 6) +#define SYNC_AUTO (0 << 4) ///< D5,D4 --- Sync Select Mode +#define SYNC_EXTERNAL (2 << 4) +#define SYNC_INTERNAL (3 << 4) +#define OSD_ENABLE (1 << 3) ///< D3 --- Enable Display of OSD image +#define OSD_DISABLE (0 << 3) +#define SOFT_RESET (1 << 1) ///< D1 --- Software Reset +#define VOUT_ENABLE (0 << 0) +#define VOUT_DISABLE (1 << 0) +/* VM1 */ +#define BACKGND_0 (0 << 4) ///< Background level WHT% +#define BACKGND_7 (1 << 4) +#define BACKGND_14 (2 << 4) +#define BACKGND_21 (3 << 4) +#define BACKGND_28 (4 << 4) +#define BACKGND_35 (5 << 4) +#define BACKGND_42 (6 << 4) +#define BACKGND_49 (7 << 4) +#define BLINK_TIME40 (0 << 2) ///< Blink cycle, ms +#define BLINK_TIME80 (1 << 2) +#define BLINK_TIME120 (2 << 2) +#define BLINK_TIME160 (3 << 2) ///< Scintillation ratio(ON : OFF) +#define BLINK_DUTY_1_1 0 ///< BT : BT +#define BLINK_DUTY_1_2 1 ///< BT : 2BT +#define BLINK_DUTY_1_3 2 ///< BT : 3BT +#define BLINK_DUTY_3_1 3 ///< 3BT : BT // DMM +#define SPI_BIT16 (0 << 6) ///< use 16bit When writing characters, and the character attribute is from the DMM[5:3] +#define SPI_BIT8 (1 << 6) ///< Write characters in 8bit, and character attributes are written separately +#define CHAR_LBC (1 << 5) ///< The local background +#define CHAR_BLK (1 << 4) ///< blinking display +#define CHAR_INV (1 << 3) ///< display negative image +#define CLEAR_SRAM (1 << 2) ///< clear,20us +#define VETICAL_SYNC (1 << 1) ///< The command is in sync with the action +#define AUTO_INC (1 << 0) ///< The character address automatically increases +/* RBi */ +#define BLACK_LEVEL_0 (0 << 2) ///< 0% white level +#define BLACK_LEVEL_10 (1 << 2) ///< 10% white level +#define BLACK_LEVEL_20 (2 << 2) ///< 20% white level +#define BLACK_LEVEL_30 (3 << 2) ///< 30% white level +#define WHITE_LEVEL_120 (0 << 0) ///< 120% white level +#define WHITE_LEVEL_100 (1 << 0) ///< 110% white level +#define WHITE_LEVEL_90 (2 << 0) ///< 90% white level +#define WHITE_LEVEL_80 (3 << 0) ///< 80% white level +/* STAT */ +#define PAL_DETECT (1 << 0) ///< Check the PAL signal +#define NTSC_DETECT (1 << 1) ///< Check the NTSC signal +#define LOS_DETECT (1 << 2) ///< Check the LOS signal +#define VSYNC (1 << 4) ///< synchronous + +/** + * @struct AsciiAddr + * @brief Ascii corresponding address struct + */ +typedef struct +{ + char ascii; + short addr; +}AsciiAddr; + +const AsciiAddr tAsciiAddr[]={ + {' ',0x00}, + {'(',0x3f}, + {')',0x40}, + {'.',0x41}, + {'?',0x42}, + {';',0x43}, + {':',0x44}, + {',',0x45}, + {'\'',0x46}, + {'/',0x47}, + {'"',0x48}, + {'-',0x49}, + {'<',0x4a}, + {'>',0x4b}, + {'@',0x4c}, + {'!',0x121}, + {'#',0x123}, + {'$',0x124}, + {'%',0x125}, + {'&',0x126}, + {'(',0x128}, + {')',0x129}, + {'*',0x12a}, + {'+',0x12b}, + {'_',0x12d}, + {'=',0x13d}, + {'[',0x15b}, + {']',0x15d}, + {'^',0x15e}, + {'`',0x160}, + {'{',0x17b}, + {'|',0x17c}, + {'}',0x17d}, + {'~',0x17e}, +}; + +class DFRobot_OSD +{ +public: + /** + * @fn DFRobot_OSD + * @brief Constructor + * @param CS - CS selection pin + * @return None + */ + DFRobot_OSD(int CS); + ~DFRobot_OSD(); + + /** + * @fn init + * @brief Init function + * @return None + */ + void init(int a, int b, int c); + + /** + * @fn displayChar + * @brief display char + * @param row - Horizontal coordinate, range(0,15) + * @param col - Vertical coordinate, range(0,29) + * @param value - addr of char in eeprom + * @return None + */ + void displayChar(unsigned char row, unsigned char col, unsigned short addr); + + /** + * @fn displayChar + * @brief display string + * @param row - Horizontal coordinate, range(0,15) + * @param col - Vertical coordinate, range(0,29) + * @param s - String + * @return None + */ + void displayString(unsigned char row, unsigned char col, const char *s); + void displayString(unsigned char row, unsigned char col, String s); + + /** + * @fn clear + * @brief Clear screen + * @return None + */ + void clear(void); + + /** + * @fn storeChar + * @brief Write the custom character to the OSD, replacing the original character + * @param addr - Address of the stored character + * @param dt - Array generated through the tool + * @return None + */ + void storeChar(unsigned short addr,int dt[]); + +private: + void writeAddrData(unsigned char addr, unsigned char dat); + void writeAT7456E(unsigned short addr, int *dt); + void writeData(unsigned char dat); + int * extend(int src); + int unified(int src); + +private: + int nCS; +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index a6ad755..0a3df3f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,7 +24,35 @@ #include #include // This file contains a binary patch for the SX1262 +#include "DFRobot_OSD.cpp" #include "modules/SX126x/patches/SX126x_patch_scan.h" +#define CS 47 +#define OSD_MISO 33 +#define OSD_MOSI 34 +#define OSD_SCK 26 +#define OSD_WIDTH 30 +#define OSD_HEIGHT 16 +#define OSD_CHART_WIDTH 15 +#define OSD_CHART_HEIGHT 5 +#define OSD_X_START 1 +#define OSD_Y_START 16 + +int osd_chart_buffer[OSD_CHART_WIDTH]; + +DFRobot_OSD osd(CS); + +/*Define Chinese characters*/ +int buf0[36] = {0x02, 0x80, 0x02, 0x40, 0x7F, 0xE0, 0x42, 0x00, 0x42, 0x00, 0x7A, 0x40, + 0x4A, 0x40, 0x4A, 0x80, 0x49, 0x20, 0x5A, 0xA0, 0x44, 0x60, 0x88, 0x20}; +int buf1[36] = {0x20, 0x00, 0x25, 0xE0, 0x75, 0x20, 0x29, 0x20, 0xFD, 0x40, 0x21, 0x40, + 0x7D, 0x20, 0xC5, 0x20, 0x7D, 0x20, 0x45, 0xC0, 0x7D, 0x00, 0x45, 0x00}; +int buf2[36] = {0x20, 0x00, 0x2F, 0xC0, 0x24, 0x40, 0xF4, 0x40, 0x24, 0x80, 0x64, 0xE0, + 0x74, 0x20, 0xA6, 0x20, 0x25, 0x40, 0x28, 0x80, 0x29, 0x40, 0x32, 0x20}; +int buf3[36] = {0x3F, 0x00, 0x2A, 0xE0, 0xFA, 0x20, 0x2E, 0xA0, 0x2A, 0xA0, 0xFE, 0xA0, + 0x2A, 0x40, 0xAB, 0x40, 0xBE, 0xA0, 0xA3, 0x20, 0xE2, 0x00, 0xBF, 0xE0}; + +// SPI pins +// .pio/libdeps/heltec_wifi_lora_32_V3/Heltec_ESP32_LoRa_v3/src/heltec_unofficial.h#L34-L35 // project components #include "global_config.h" @@ -53,6 +81,8 @@ uint64_t RANGE_PER_PAGE = FREQ_END - FREQ_BEGIN; // FREQ_END - FREQ_BEGIN // multiplies STEPS * N to increase scan resolution. #define SCAN_RBW_RFACTOR 2 +int OSD_PIXELS_PER_CHAR = (STEPS * SCAN_RBW_RFACTOR) / OSD_CHART_WIDTH; + // To Enable Multi Screen scan // uint64_t RANGE_PER_PAGE = 50; // Default Range on Menu Button Switch @@ -108,7 +138,7 @@ 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 = true; +bool SOUND_ON = false; #define PRINT_PROFILE_TIME @@ -119,7 +149,8 @@ uint64_t scan_time = 0; uint64_t scan_start_time = 0; #endif -uint64_t x, y, range_item, w = 0; +uint64_t x, y, range_item, w, i = 0; +int osd_x = 1, osd_y = 2; uint64_t ranges_count = 0; float freq = 0; @@ -131,8 +162,77 @@ uint8_t button_pressed_counter = 0; uint64_t loop_cnt = 0; +unsigned short selectFreqChar(int bin) +{ + if (bin > 26) + { + return 0x105; + } + if (bin == 25) + { + return 0x106; + } + if (bin == 24) + { + return 0x107; + } + if (bin == 23) + { + return 0x108; + } + if (bin == 22) + { + return 0x109; + } + if (bin == 21) + { + return 0x10a; + } + if (bin == 20) + { + return 0x10b; + } + if (bin == 19) + { + return 0x10c; + } + if (bin == 18) + { + return 0x10d; + } + if (bin == 17) + { + return 0x10e; + } + return 0x105; +} + void setup(void) { + + osd.init(OSD_SCK, OSD_MISO, OSD_MOSI); + osd.clear(); + /* Write the custom character to the OSD, replacing the original character*/ + /* Expand 0xe0 to 0x0e0, the high 8 bits indicate page number and the low 8 bits + * indicate the inpage address.*/ + osd.storeChar(0xe0, buf0); + osd.storeChar(0xe1, buf1); + osd.storeChar(0xe2, buf2); + osd.storeChar(0xe3, buf3); + /*Displays custom characters*/ + osd.displayChar(2, 2, 0xe0); + osd.displayChar(2, 3, 0xe1); + osd.displayChar(2, 4, 0xe2); + osd.displayChar(2, 5, 0xe3); + /*display character*/ + osd.displayChar(9, 9, 0x11d); + osd.displayChar(9, 10, 0x11e); + osd.displayChar(8, 11, 0x10f); + osd.displayChar(14, 0, 0x10f); + /*display String*/ + osd.displayString(14, 15, " Lora SA"); + osd.displayString(2, 1, " Spectral RF Analyzer"); + float vbat; float resolution; loop_cnt = 0; @@ -148,7 +248,7 @@ void setup(void) delay(10); if (button.pressed()) { - SOUND_ON = false; + SOUND_ON = !SOUND_ON; tone(BUZZER_PIN, 205, 100); delay(50); tone(BUZZER_PIN, 205, 100); @@ -344,8 +444,16 @@ void loop(void) drone_detected_frequency_start = 0; display.setTextAlignment(TEXT_ALIGN_RIGHT); + int max_bins_array[30]; + for (int i = 0; i < 30; i++) + { + max_bins_array[i] = 33; + } + // memset(max_bins_array, 33, 30); // horizontal (x axis) Frequency loop + int osd_x = 1, osd_y = 1, s = 0; + // x loop for (x = 0; x < STEPS * SCAN_RBW_RFACTOR; x++) { @@ -365,7 +473,9 @@ void loop(void) // x > STEPS on SCAN_RBW_RFACTOR int dispaly_x = x / SCAN_RBW_RFACTOR; waterfall[dispaly_x] = false; - freq = fr_begin + (range * ((float)x / (STEPS * SCAN_RBW_RFACTOR))); + float step = (range * ((float)x / (STEPS * SCAN_RBW_RFACTOR))); + + freq = fr_begin + step; radio.setFrequency(freq, false); // false = no calibration need here @@ -386,6 +496,39 @@ void loop(void) } // read the results Array to which the results will be saved radio.spectralScanGetResult(result); + int max_bin = 0; + + int mhz_in_bin = 5; + int steps = 12; + + for (int i = 1; i < 33; i++) + { + if (result[i] > 0 && (result[i + 1] > 0)) + { + max_bin = i; + Serial.println(String(max_bin)); + break; + } + } + if (max_bins_array[s] > max_bin) + { + max_bins_array[s] = max_bin; + } + // Going to the next OSD step + if (x % steps == 0 && s < 30) + { + // PRINT SIGNAL CHAR ROW, COL, VALUE + osd.displayChar(14, s + 1, selectFreqChar(max_bins_array[s])); + Serial.println("MAX:" + String(max_bins_array[s])); + // osd.displayString(14, s, "" + String(max_bins_array[s]) + ""); + s++; + if (s == 30) + { + s = 0; + } + } + // osd.displayString(osd_y++, osd_x, + // String(freq) + "-" + String((max_bin * 4)) + "dB"); } #endif #if SCAN_METHOD == METHOD_RSSI @@ -399,8 +542,12 @@ void loop(void) } // memset - memset(result, 0, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE); - result_index = 0u; + // memset(result, 0, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE); + for (i = 0; i < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; i++) + { + result[i] = 0; + } + result_index = 0; // N of samples for (int r = 0; r < SAMPLES_RSSI; r++) { @@ -436,6 +583,7 @@ void loop(void) for (y = 0; y < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; y++) { + #ifdef PRINT_DEBUG // Serial.printf("%04X,", result[y]); #endif @@ -536,8 +684,11 @@ void loop(void) #if (DRAW_DETECTION_TICKS == true) // draw vertical line on top of display for "drone detected" // frequencies - display.drawLine(dispaly_x, 1, dispaly_x, 6); - detected_y[dispaly_x] = true; + if (!detected_y[dispaly_x]) + { + display.drawLine(dispaly_x, 1, dispaly_x, 6); + detected_y[dispaly_x] = true; + } #endif } @@ -572,7 +723,7 @@ void loop(void) // ------------------------------------------------------------- // Draw "Detection Level line" every 2 pixel // ------------------------------------------------------------- - if ((y == drone_detection_level) && (dispaly_x % 2 == 0) && new_pixel) + if ((y == drone_detection_level) && (dispaly_x % 2 == 0)) { display.setColor(WHITE); if (filtered_result[y] == 1)