Jelajahi Sumber

Added Marauder source

Just Call Me Koko 6 tahun lalu
induk
melakukan
7b4b589205

+ 457 - 0
esp32_marauder/Display.cpp

@@ -0,0 +1,457 @@
+#include "Display.h"
+
+/*
+Big thanks to bodmer for having great TFT and JPEG libraries
+
+https://github.com/bodmer
+*/
+
+Display::Display()
+{
+  //Serial.println("Initializing Display Object...");
+}
+
+void Display::main()
+{
+  return;
+}
+
+// Function to prepare the display and the menus
+void Display::RunSetup()
+{
+  run_setup = false;
+
+  // Need to declare new
+  display_buffer = new SimpleList<String>();
+  
+  tft.init();
+  tft.setRotation(0); // Portrait
+
+  tft.setCursor(0, 0);
+  //tft.setFreeFont(&FreeMonoBold9pt7b);
+
+  // Calibration data
+  //uint16_t calData[5] = { 390, 3516, 253, 3520, 7 }; tft.setRotation(1); // Portrait
+  uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait
+  tft.setTouch(calData);
+
+  //tft.fillScreen(TFT_BLACK);
+  clearScreen();
+
+  
+  // Initialize file system
+  // This should probably have its own class
+  if (!SPIFFS.begin()) {
+    Serial.println("SPIFFS initialisation failed!");
+    while (1) yield(); // Stay here twiddling thumbs waiting
+  }
+  //Serial.println("\r\nInitialisation done.");
+  //listFiles(); // Lists the files so you can see what is in the SPIFFS
+
+
+  // Draw the title screen
+  drawJpeg("/marauder3L.jpg", 0 , 0);     // 240 x 320 image
+
+  //showCenterText(version_number, 250);
+  tft.drawCentreString(version_number, 120, 250, 2);
+
+  digitalWrite(TFT_BL, HIGH);
+
+  delay(5000);
+}
+
+
+// Function to just draw the screen black
+void Display::clearScreen()
+{
+  Serial.println("clearScreen()");
+  tft.fillScreen(TFT_BLACK);
+  tft.setCursor(0, 0);
+}
+
+void Display::displayBuffer(bool do_clear)
+{
+  if (this->display_buffer->size() > 0)
+  {
+    delay(1);
+    
+    while (display_buffer->size() > 0)
+    {
+      xPos = 0;
+      //yDraw = scroll_line(TFT_RED);
+      //tft.setCursor(xPos, yDraw);
+
+      //tft.print(display_buffer->shift());
+      //tft.print(display_buffer->get(0));
+      if ((display_buffer->size() > 0) && (!loading))
+      {
+        //tft.print(display_buffer->pop());
+        printing = true;
+        delay(print_delay_1);
+        yDraw = scroll_line(TFT_RED);
+        tft.setCursor(xPos, yDraw);
+        tft.print(display_buffer->shift());
+        printing = false;
+        delay(print_delay_2);
+        //display_buffer->remove(0);
+      }
+      
+      blank[(18+(yStart - TOP_FIXED_AREA) / TEXT_HEIGHT)%19] = xPos;
+    }
+    
+    /*
+    while (display_buffer->get(0) != "")
+    {
+      Serial.println("Printing");
+      delay(10);
+      xPos = 0;
+      yDraw = scroll_line(TFT_RED);
+      tft.setCursor(xPos, yDraw);
+      if (display_buffer->get(0) != "")
+      {
+        tft.print(display_buffer->get(0));
+        display_buffer->replace(0, "");
+      }
+      blank[(18+(yStart - TOP_FIXED_AREA) / TEXT_HEIGHT)%19] = xPos;
+    }
+    */
+  }
+}
+
+void Display::showCenterText(String text, int y)
+{
+  tft.setCursor((SCREEN_WIDTH - (text.length() * 6)) / 2, y);
+  tft.println(text);
+}
+
+
+void Display::initScrollValues()
+{
+  Serial.println("initScrollValues()");
+  yDraw = YMAX - BOT_FIXED_AREA - TEXT_HEIGHT;
+
+  xPos = 0;
+
+  yStart = TOP_FIXED_AREA;
+
+  yArea = YMAX - TOP_FIXED_AREA - BOT_FIXED_AREA;
+
+  for(int i = 0; i < 18; i++) blank[i] = 0;
+}
+
+
+
+// Function to execute hardware scroll for TFT screen
+int Display::scroll_line(uint32_t color) {
+  //Serial.println("scroll_line()");
+  int yTemp = yStart; // Store the old yStart, this is where we draw the next line
+  // Use the record of line lengths to optimise the rectangle size we need to erase the top line
+  tft.fillRect(0,yStart,blank[(yStart-TOP_FIXED_AREA)/TEXT_HEIGHT],TEXT_HEIGHT, color);
+
+  // Change the top of the scroll area
+  yStart+=TEXT_HEIGHT;
+  // The value must wrap around as the screen memory is a circular buffer
+  if (yStart >= YMAX - BOT_FIXED_AREA) yStart = TOP_FIXED_AREA + (yStart - YMAX + BOT_FIXED_AREA);
+  // Now we can scroll the display
+  scrollAddress(yStart);
+  return  yTemp;
+}
+
+
+// Function to setup hardware scroll for TFT screen
+void Display::setupScrollArea(uint16_t tfa, uint16_t bfa) {
+  Serial.println("setupScrollAread()");
+  tft.writecommand(ILI9341_VSCRDEF); // Vertical scroll definition
+  tft.writedata(tfa >> 8);           // Top Fixed Area line count
+  tft.writedata(tfa);
+  tft.writedata((YMAX-tfa-bfa)>>8);  // Vertical Scrolling Area line count
+  tft.writedata(YMAX-tfa-bfa);
+  tft.writedata(bfa >> 8);           // Bottom Fixed Area line count
+  tft.writedata(bfa);
+}
+
+
+void Display::scrollAddress(uint16_t vsp) {
+  tft.writecommand(ILI9341_VSCRSADD); // Vertical scrolling pointer
+  tft.writedata(vsp>>8);
+  tft.writedata(vsp);
+}
+
+
+
+
+// JPEG_functions
+void Display::drawJpeg(const char *filename, int xpos, int ypos) {
+
+  //Serial.println("===========================");
+  //Serial.print("Drawing file: "); Serial.println(filename);
+  //Serial.println("===========================");
+
+  // Open the named file (the Jpeg decoder library will close it after rendering image)
+  fs::File jpegFile = SPIFFS.open( filename, "r");    // File handle reference for SPIFFS
+  //  File jpegFile = SD.open( filename, FILE_READ);  // or, file handle reference for SD library
+
+  //ESP32 always seems to return 1 for jpegFile so this null trap does not work
+  if ( !jpegFile ) {
+    Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
+    return;
+  }
+
+  // Use one of the three following methods to initialise the decoder,
+  // the filename can be a String or character array type:
+
+  //boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder,
+  //boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder,
+  boolean decoded = JpegDec.decodeFsFile(filename);  // or pass the filename (leading / distinguishes SPIFFS files)
+
+  if (decoded) {
+    // print information about the image to the serial port
+    jpegInfo();
+
+    // render the image onto the screen at given coordinates
+    jpegRender(xpos, ypos);
+  }
+  else {
+    Serial.println("Jpeg file format not supported!");
+  }
+}
+
+//====================================================================================
+//   Decode and render the Jpeg image onto the TFT screen
+//====================================================================================
+void Display::jpegRender(int xpos, int ypos) {
+
+  // retrieve infomration about the image
+  uint16_t  *pImg;
+  int16_t mcu_w = JpegDec.MCUWidth;
+  int16_t mcu_h = JpegDec.MCUHeight;
+  int32_t max_x = JpegDec.width;
+  int32_t max_y = JpegDec.height;
+
+  // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
+  // Typically these MCUs are 16x16 pixel blocks
+  // Determine the width and height of the right and bottom edge image blocks
+  int32_t min_w = minimum(mcu_w, max_x % mcu_w);
+  int32_t min_h = minimum(mcu_h, max_y % mcu_h);
+
+  // save the current image block size
+  int32_t win_w = mcu_w;
+  int32_t win_h = mcu_h;
+
+  // record the current time so we can measure how long it takes to draw an image
+  uint32_t drawTime = millis();
+
+  // save the coordinate of the right and bottom edges to assist image cropping
+  // to the screen size
+  max_x += xpos;
+  max_y += ypos;
+
+  // read each MCU block until there are no more
+  while ( JpegDec.readSwappedBytes()) { // Swapped byte order read
+
+    // save a pointer to the image block
+    pImg = JpegDec.pImage;
+
+    // calculate where the image block should be drawn on the screen
+    int mcu_x = JpegDec.MCUx * mcu_w + xpos;  // Calculate coordinates of top left corner of current MCU
+    int mcu_y = JpegDec.MCUy * mcu_h + ypos;
+
+    // check if the image block size needs to be changed for the right edge
+    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
+    else win_w = min_w;
+
+    // check if the image block size needs to be changed for the bottom edge
+    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
+    else win_h = min_h;
+
+    // copy pixels into a contiguous block
+    if (win_w != mcu_w)
+    {
+      for (int h = 1; h < win_h-1; h++)
+      {
+        memcpy(pImg + h * win_w, pImg + (h + 1) * mcu_w, win_w << 1);
+      }
+    }
+
+    // draw image MCU block only if it will fit on the screen
+    if ( mcu_x < tft.width() && mcu_y < tft.height())
+    {
+      // Now push the image block to the screen
+      tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
+    }
+
+    else if ( ( mcu_y + win_h) >= tft.height()) JpegDec.abort();
+
+  }
+
+  // calculate how long it took to draw the image
+  drawTime = millis() - drawTime; // Calculate the time it took
+
+  // print the results to the serial port
+  //Serial.print  ("Total render time was    : "); Serial.print(drawTime); Serial.println(" ms");
+  //Serial.println("=====================================");
+
+}
+
+//====================================================================================
+//   Print information decoded from the Jpeg image
+//====================================================================================
+void Display::jpegInfo() {
+/*
+  Serial.println("===============");
+  Serial.println("JPEG image info");
+  Serial.println("===============");
+  Serial.print  ("Width      :"); Serial.println(JpegDec.width);
+  Serial.print  ("Height     :"); Serial.println(JpegDec.height);
+  Serial.print  ("Components :"); Serial.println(JpegDec.comps);
+  Serial.print  ("MCU / row  :"); Serial.println(JpegDec.MCUSPerRow);
+  Serial.print  ("MCU / col  :"); Serial.println(JpegDec.MCUSPerCol);
+  Serial.print  ("Scan type  :"); Serial.println(JpegDec.scanType);
+  Serial.print  ("MCU width  :"); Serial.println(JpegDec.MCUWidth);
+  Serial.print  ("MCU height :"); Serial.println(JpegDec.MCUHeight);
+  Serial.println("===============");
+  Serial.println("");
+  */
+}
+
+//====================================================================================
+//   Open a Jpeg file and send it to the Serial port in a C array compatible format
+//====================================================================================
+void createArray(const char *filename) {
+
+  // Open the named file
+  fs::File jpgFile = SPIFFS.open( filename, "r");    // File handle reference for SPIFFS
+  //  File jpgFile = SD.open( filename, FILE_READ);  // or, file handle reference for SD library
+
+  if ( !jpgFile ) {
+    Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
+    return;
+  }
+
+  uint8_t data;
+  byte line_len = 0;
+  Serial.println("");
+  Serial.println("// Generated by a JPEGDecoder library example sketch:");
+  Serial.println("// https://github.com/Bodmer/JPEGDecoder");
+  Serial.println("");
+  Serial.println("#if defined(__AVR__)");
+  Serial.println("  #include <avr/pgmspace.h>");
+  Serial.println("#endif");
+  Serial.println("");
+  Serial.print  ("const uint8_t ");
+  while (*filename != '.') Serial.print(*filename++);
+  Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors, it is ignored by Due
+
+  while ( jpgFile.available()) {
+
+    data = jpgFile.read();
+    Serial.print("0x"); if (abs(data) < 16) Serial.print("0");
+    Serial.print(data, HEX); Serial.print(",");// Add value and comma
+    line_len++;
+    if ( line_len >= 32) {
+      line_len = 0;
+      Serial.println();
+    }
+
+  }
+
+  Serial.println("};\r\n");
+  jpgFile.close();
+}
+
+// End JPEG_functions
+
+// SPIFFS_functions
+
+#ifdef ESP8266
+void Display::listFiles(void) {
+  Serial.println();
+  Serial.println("SPIFFS files found:");
+
+  fs::Dir dir = SPIFFS.openDir("/"); // Root directory
+  String  line = "=====================================";
+
+  Serial.println(line);
+  Serial.println("  File name               Size");
+  Serial.println(line);
+
+  while (dir.next()) {
+    String fileName = dir.fileName();
+    Serial.print(fileName);
+    int spaces = 21 - fileName.length(); // Tabulate nicely
+    while (spaces--) Serial.print(" ");
+
+    fs::File f = dir.openFile("r");
+    String fileSize = (String) f.size();
+    spaces = 10 - fileSize.length(); // Tabulate nicely
+    while (spaces--) Serial.print(" ");
+    Serial.println(fileSize + " bytes");
+  }
+
+  Serial.println(line);
+  Serial.println();
+  delay(1000);
+}
+#endif
+
+//====================================================================================
+
+#ifdef ESP32
+
+void Display::listFiles(void) {
+  listDir(SPIFFS, "/", 0);
+}
+
+void Display::listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
+
+  Serial.println();
+  Serial.println("SPIFFS files found:");
+
+  Serial.printf("Listing directory: %s\n", "/");
+  String  line = "=====================================";
+
+  Serial.println(line);
+  Serial.println("  File name               Size");
+  Serial.println(line);
+
+  fs::File root = fs.open(dirname);
+  if (!root) {
+    Serial.println("Failed to open directory");
+    return;
+  }
+  if (!root.isDirectory()) {
+    Serial.println("Not a directory");
+    return;
+  }
+
+  fs::File file = root.openNextFile();
+  while (file) {
+
+    if (file.isDirectory()) {
+      Serial.print("DIR : ");
+      String fileName = file.name();
+      Serial.print(fileName);
+      if (levels) {
+        listDir(fs, file.name(), levels - 1);
+      }
+    } else {
+      String fileName = file.name();
+      Serial.print("  " + fileName);
+      int spaces = 20 - fileName.length(); // Tabulate nicely
+      while (spaces--) Serial.print(" ");
+      String fileSize = (String) file.size();
+      spaces = 10 - fileSize.length(); // Tabulate nicely
+      while (spaces--) Serial.print(" ");
+      Serial.println(fileSize + " bytes");
+    }
+
+    file = root.openNextFile();
+  }
+
+  Serial.println(line);
+  Serial.println();
+  delay(1000);
+}
+#endif
+
+// End SPIFFS_functions

+ 97 - 0
esp32_marauder/Display.h

@@ -0,0 +1,97 @@
+#ifndef Display_h
+#define Display_h
+
+
+#include <FS.h>
+#include <functional>
+#include <JPEGDecoder.h>
+#include <SimpleList.h>
+#include <SPI.h>
+#include "SPIFFS.h"
+#include <TFT_eSPI.h>
+//#include "Free_Fonts.h"
+
+
+#define SCREEN_WIDTH 240
+#define SCREEN_HEIGHT 320
+#define TEXT_HEIGHT 16 // Height of text to be printed and scrolled
+#define BOT_FIXED_AREA 0 // Number of lines in bottom fixed area (lines counted from bottom of screen)
+#define TOP_FIXED_AREA 16 // Number of lines in top fixed area (lines counted from top of screen)
+#define YMAX 320 // Bottom of screen area
+#define minimum(a,b)     (((a) < (b)) ? (a) : (b))
+//#define MENU_FONT NULL
+#define MENU_FONT &FreeMono9pt7b // Winner
+//#define MENU_FONT &FreeMonoBold9pt7b
+//#define MENU_FONT &FreeSans9pt7b
+//#define MENU_FONT &FreeSansBold9pt7b
+
+
+class Display
+{
+  private:
+    
+    bool run_setup = true;
+    
+    // For the byte we read from the serial port
+    byte data = 0;
+    
+    // A few test variables used during debugging
+    boolean change_colour = 1;
+    boolean selected = 1;
+
+    //void addNodes(Menu* menu, String name, Menu* child, std::function<void()> callable);
+    //void changeMenu(Menu* menu);
+    //void showMenuList(Menu* menu, int layer);
+
+  public:
+    Display();
+    TFT_eSPI tft = TFT_eSPI();
+    String version_number = "v0.1";
+
+    bool printing = false;
+
+    bool loading = false;
+
+    int print_delay_1, print_delay_2 = 10;
+
+    //Menu* current_menu;
+    
+    //Menu mainMenu;
+    //Menu wifiMenu;
+    //Menu bluetoothMenu;
+
+    SimpleList<String>* display_buffer;
+
+    // The initial y coordinate of the top of the bottom text line
+    uint16_t yDraw = YMAX - BOT_FIXED_AREA - TEXT_HEIGHT;
+
+    // Keep track of the drawing x coordinate
+    uint16_t xPos = 0;
+
+    // The initial y coordinate of the top of the scrolling area
+    uint16_t yStart = TOP_FIXED_AREA;
+    // yArea must be a integral multiple of TEXT_HEIGHT
+    uint16_t yArea = YMAX - TOP_FIXED_AREA - BOT_FIXED_AREA;
+
+    // We have to blank the top line each time the display is scrolled, but this takes up to 13 milliseconds
+    // for a full width line, meanwhile the serial buffer may be filling... and overflowing
+    // We can speed up scrolling of short text lines by just blanking the character we drew
+    int blank[19]; // We keep all the strings pixel lengths to optimise the speed of the top line blanking
+    
+    void clearScreen();
+    void displayBuffer(bool do_clear = false);
+    void drawJpeg(const char *filename, int xpos, int ypos);
+    void getTouchWhileFunction(bool pressed);
+    void initScrollValues();
+    void jpegInfo();
+    void jpegRender(int xpos, int ypos);
+    void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
+    void listFiles();
+    void main();
+    void RunSetup();
+    void scrollAddress(uint16_t vsp);
+    int scroll_line(uint32_t color);
+    void setupScrollArea(uint16_t tfa, uint16_t bfa);
+    void showCenterText(String text, int y);
+};
+#endif

+ 314 - 0
esp32_marauder/MenuFunctions.cpp

@@ -0,0 +1,314 @@
+#include "MenuFunctions.h"
+
+
+MenuFunctions::MenuFunctions()
+{
+  //Serial.println("Initializing Menu Object...");
+}
+
+// Function to check menu input
+void MenuFunctions::main()
+{
+  // This is code from bodmer's keypad example
+  uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
+
+  // Get the display buffer out of the way
+  if (wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF)
+    display_obj.displayBuffer();
+  //else
+  //  display_obj.displayBuffer(true);
+
+  //Serial.println("Cycle");
+
+  // Pressed will be set true is there is a valid touch on the screen
+  //vTaskDelay(10 / portTICK_PERIOD_MS);
+  boolean pressed = display_obj.tft.getTouch(&t_x, &t_y);
+  //boolean pressed = false;
+
+  
+  // This is if there are scans going on
+  if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) && (pressed))
+  //if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) && (x != -1) && (y != -1))
+  {  
+    // Stop the current scan
+    if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ST) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) || 
+    (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
+    {
+      Serial.println("Stopping scan...");
+      wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+  
+      // If we don't do this, the text and button coordinates will be off
+      display_obj.tft.init();
+  
+      // Take us back to the menu
+      changeMenu(current_menu);
+    }
+
+    x = -1;
+    y = -1;
+
+    return;
+  }
+  
+  // / Check if any key coordinate boxes contain the touch coordinates
+  for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+    if (pressed && key[b].contains(t_x, t_y)) {
+      key[b].press(true);  // tell the button it is pressed
+    } else {
+      key[b].press(false);  // tell the button it is NOT pressed
+    }
+  }
+
+  // Check if any key has changed state
+  for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+    display_obj.tft.setFreeFont(MENU_FONT);
+    if (key[b].justPressed()) {
+      key[b].drawButton2(current_menu->list->get(b).name, true);  // draw invert
+    }
+
+    // If button was just release, execute the button's function
+    if (key[b].justReleased())
+    {
+      key[b].drawButton2(current_menu->list->get(b).name);     // draw normal
+      //Serial.print("Executing button -> ");
+      //Serial.println(current_menu->list->get(b).name);
+      current_menu->list->get(b).callable();
+    }
+    display_obj.tft.setFreeFont(NULL);
+  }
+
+  // This is if there are any scans or sniffs going on
+  if(digitalRead(FLASH_BUTTON) == 0)
+  {
+    // Stop the current scan
+    if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ST) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
+    {
+      Serial.println("Stopping scan...");
+      wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+  
+      // If we don't do this, the text and button coordinates will be off
+      display_obj.tft.init();
+  
+      // Take us back to the menu
+      changeMenu(current_menu);
+    }
+  }
+  
+  //else
+  //{
+  //  display_obj.displayBuffer();
+  //}
+  x = -1;
+  y = -1;
+}
+
+
+void MenuFunctions::handlePress(boolean pressed, uint16_t t_x, uint16_t t_y)
+{
+  if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) && (pressed))
+  {  
+    // Stop the current scan
+    if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ST) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) || 
+    (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
+    {
+      Serial.println("Stopping scan...");
+      wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+  
+      // If we don't do this, the text and button coordinates will be off
+      display_obj.tft.init();
+  
+      // Take us back to the menu
+      changeMenu(current_menu);
+    }
+
+    return;
+  }
+  
+  // / Check if any key coordinate boxes contain the touch coordinates
+  for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+    if (pressed && key[b].contains(t_x, t_y)) {
+      key[b].press(true);  // tell the button it is pressed
+    } else {
+      key[b].press(false);  // tell the button it is NOT pressed
+    }
+  }
+
+  // Check if any key has changed state
+  for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+    display_obj.tft.setFreeFont(MENU_FONT);
+    if (key[b].justPressed()) {
+      key[b].drawButton2(current_menu->list->get(b).name, true);  // draw invert
+    }
+
+    // If button was just release, execute the button's function
+    if (key[b].justReleased())
+    {
+      key[b].drawButton2(current_menu->list->get(b).name);     // draw normal
+      //Serial.print("Executing button -> ");
+      //Serial.println(current_menu->list->get(b).name);
+      current_menu->list->get(b).callable();
+    }
+    display_obj.tft.setFreeFont(NULL);
+  }
+
+  // This is if there are any scans or sniffs going on
+  if(digitalRead(FLASH_BUTTON) == 0)
+  {
+    // Stop the current scan
+    if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ST) ||
+    (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+    (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
+    {
+      Serial.println("Stopping scan...");
+      wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+  
+      // If we don't do this, the text and button coordinates will be off
+      display_obj.tft.init();
+  
+      // Take us back to the menu
+      changeMenu(current_menu);
+    }
+  }
+}
+
+// Function to build the menus
+void MenuFunctions::RunSetup()
+{
+  mainMenu.list = new SimpleList<MenuNode>(); // Get list in first menu ready
+  wifiMenu.list = new SimpleList<MenuNode>(); // Get list in second menu ready
+  bluetoothMenu.list = new SimpleList<MenuNode>(); // Get list in third menu ready
+
+  // Build Main Menu
+  mainMenu.parentMenu = NULL;
+  addNodes(&mainMenu, "WiFi", TFT_GREEN, NULL, 0, [this](){changeMenu(&wifiMenu);});
+  addNodes(&mainMenu, "Bluetooth", TFT_CYAN, NULL, 1, [this](){changeMenu(&bluetoothMenu);});
+  addNodes(&mainMenu, "Pee", TFT_MAGENTA, NULL, 2, NULL);
+
+  // Build WiFi Menu
+  wifiMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
+  addNodes(&wifiMenu, "Back", TFT_RED, NULL, 0, [this](){changeMenu(wifiMenu.parentMenu);});
+  addNodes(&wifiMenu, "Probe Request Sniff", TFT_MAGENTA, NULL, 1, [this](){wifi_scan_obj.StartScan(WIFI_SCAN_PROBE);});
+  addNodes(&wifiMenu, "Beacon Sniff", TFT_BLUE, NULL, 2, [this](){wifi_scan_obj.StartScan(WIFI_SCAN_AP);});
+
+  // Build Bluetooth Menu
+  bluetoothMenu.parentMenu = &mainMenu; // Second Menu is third menu parent
+  addNodes(&bluetoothMenu, "Back", TFT_RED, NULL, 0, [this](){changeMenu(bluetoothMenu.parentMenu);});
+  addNodes(&bluetoothMenu, "Bluetooth Sniffer", TFT_GREEN, NULL, 1, [this](){wifi_scan_obj.StartScan(BT_SCAN_ALL);});
+  addNodes(&bluetoothMenu, "Detect Card Skimmers", TFT_MAGENTA, NULL, 2, [this](){wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS);});
+
+
+  // Set the current menu to the mainMenu
+  changeMenu(&mainMenu);
+
+  // Show the current menu
+  //Serial.println("\n\nCurrent Menu Tree:");
+  //Serial.println("-------------------------------");
+  //showMenuList(current_menu, 0);
+  //xTaskCreate(&MenuFunctions::getPresses, "getPresses", 2048, NULL, 5, NULL);
+}
+
+// Function to change menu
+void MenuFunctions::changeMenu(Menu* menu)
+{  
+  //display_obj.clearScreen();
+  display_obj.initScrollValues();
+  display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+  display_obj.tft.init();
+  current_menu = menu;
+
+  buildButtons(menu);
+
+  displayCurrentMenu();
+}
+
+// Function to show all MenuNodes in a Menu
+void MenuFunctions::showMenuList(Menu* menu, int layer)
+{
+  // Iterate through all of the menu nodes in the menu
+  for (int i = 0; i < menu->list->size(); i++)
+  {
+    // Depending on layer, indent
+    for (int x = 0; x < layer * 4; x++)
+      Serial.print(" ");
+    Serial.print("Node: ");
+    Serial.println(menu->list->get(i).name);
+
+    // If the current menu node points to another menu, list that menu
+    if (menu->list->get(i).childMenu != NULL)
+      showMenuList(menu->list->get(i).childMenu, layer+1);
+  }
+  Serial.println();
+}
+
+
+// Function to add MenuNodes to a menu
+void MenuFunctions::addNodes(Menu* menu, String name, uint16_t color, Menu* child, int place, std::function<void()> callable)
+{
+  TFT_eSPI_Button new_button;
+  menu->list->add(MenuNode{name, color, child, &new_button, callable});
+}
+
+void MenuFunctions::buildButtons(Menu* menu)
+{
+  Serial.println("Bulding buttons...");
+  //display_obj.clearScreen();
+  if (menu->list != NULL)
+  {
+    for (int i = 0; i < menu->list->size(); i++)
+    {
+      TFT_eSPI_Button new_button;
+      //Serial.print("Building button -> ");
+      //Serial.println(menu->list->get(i).name);
+      char buf[menu->list->get(i).name.length() + 1] = {};
+      menu->list->get(i).name.toCharArray(buf, menu->list->get(i).name.length() + 1);
+      //for (int x = 0; x < sizeof(buf); x++)
+      //  Serial.print(buf[x]);
+      //Serial.println();
+      key[i].initButton(&display_obj.tft,
+                        KEY_X + 0 * (KEY_W + KEY_SPACING_X),
+                        KEY_Y + i * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
+                        KEY_W,
+                        KEY_H,
+                        TFT_BLACK, // Outline
+                        TFT_BLACK, // Fill
+                        menu->list->get(i).color, // Text
+                        buf,
+                        KEY_TEXTSIZE);
+                        
+    }
+  }
+}
+
+void MenuFunctions::displayCurrentMenu()
+{
+  Serial.println("Displaying current menu...");
+  display_obj.clearScreen();
+  display_obj.tft.setTextColor(TFT_LIGHTGREY, TFT_DARKGREY);
+  display_obj.tft.fillRect(0,0,240,16, TFT_DARKGREY);
+  display_obj.tft.drawCentreString(" ESP32 Marauder ",120,0,2);
+  if (current_menu->list != NULL)
+  {
+    display_obj.tft.setFreeFont(MENU_FONT);
+    for (int i = 0; i < current_menu->list->size(); i++)
+    {
+      key[i].drawButton2(current_menu->list->get(i).name);
+    }
+    display_obj.tft.setFreeFont(NULL);
+  }
+}

+ 74 - 0
esp32_marauder/MenuFunctions.h

@@ -0,0 +1,74 @@
+#ifndef MenuFunctions_h
+#define MenuFunctions_h
+
+#include "WiFiScan.h"
+#include "Display.h"
+
+extern Display display_obj;
+extern WiFiScan wifi_scan_obj;
+
+// Keypad start position, key sizes and spacing
+#define KEY_X 120 // Centre of key
+#define KEY_Y 50
+#define KEY_W 240 // Width and height
+#define KEY_H 18
+#define KEY_SPACING_X 0 // X and Y gap
+#define KEY_SPACING_Y 1
+#define KEY_TEXTSIZE 1   // Font size multiplier
+#define BUTTON_ARRAY_LEN 5
+
+#define FLASH_BUTTON 0
+
+
+struct Menu;
+
+// Individual Nodes of a menu
+
+struct MenuNode {
+    String name;
+    uint16_t color;
+    Menu *childMenu;
+    TFT_eSPI_Button* button;
+    std::function<void()> callable; // Make a function that changes menu to a child menu
+};
+
+// Full Menus
+struct Menu {
+    SimpleList<MenuNode>* list;
+    Menu                * parentMenu;
+    uint8_t               selected;
+};
+
+
+class MenuFunctions
+{
+  private:    
+    Menu* current_menu;
+    
+    Menu mainMenu;
+    Menu wifiMenu;
+    Menu bluetoothMenu;
+
+    TFT_eSPI_Button key[BUTTON_ARRAY_LEN];
+    //SimpleList<TFT_eSPI_Button>* key;
+    
+    void addNodes(Menu* menu, String name, uint16_t color, Menu* child, int place, std::function<void()> callable);
+    void showMenuList(Menu* menu, int layer);
+
+  public:    
+    MenuFunctions();
+
+    uint16_t x = -1, y = -1;
+    boolean pressed = false;
+
+    void buildButtons(Menu* menu);
+    void changeMenu(Menu* menu);
+    void displayCurrentMenu();
+    void handlePress(boolean pressed, uint16_t t_x, uint16_t t_y);
+    void main();
+    void RunSetup();
+};
+
+
+
+#endif

+ 415 - 0
esp32_marauder/WiFiScan.cpp

@@ -0,0 +1,415 @@
+#include "WiFiScan.h"
+
+
+class bluetoothScanAllCallback: public BLEAdvertisedDeviceCallbacks {
+    void onResult(BLEAdvertisedDevice advertisedDevice) {
+      String display_string = "";
+      String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"};
+      //Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
+      if (display_obj.display_buffer->size() >= 0)
+      {
+        display_string.concat(" RSSI: ");
+        display_string.concat(advertisedDevice.getRSSI());
+        Serial.print(" RSSI: ");
+        Serial.print(advertisedDevice.getRSSI());
+
+        display_string.concat(" ");
+        Serial.print(" ");
+        
+        Serial.print("Device: ");
+        if(advertisedDevice.getName().length() != 0)
+        {
+          display_string.concat(advertisedDevice.getName().c_str());
+          Serial.print(advertisedDevice.getName().c_str());
+          /*
+          for(int i = 0; i < bad_list_length; i++)
+          {
+            if(strcmp(advertisedDevice.getName().c_str(), bad_list[i].c_str()) == 0)
+            {
+              Serial.println("Found some shit");
+              //digitalWrite(LED, HIGH);
+            }
+          }*/
+          
+        }
+        else
+        {
+          display_string.concat(advertisedDevice.getAddress().toString().c_str());
+          Serial.print(advertisedDevice.getAddress().toString().c_str());
+        }
+
+        int temp_len = display_string.length();
+        for (int i = 0; i < 40 - temp_len; i++)
+        {
+          display_string.concat(" ");
+        }
+
+        Serial.println();
+
+        //while (1)
+        //{
+        //  if (display_obj.display_buffer->size() == 0)
+        //  {
+        //    display_obj.display_buffer->add(display_string);
+        //    break;
+        //  }
+        //}
+        while (display_obj.printing)
+          delay(1);
+        display_obj.loading = true;
+        display_obj.display_buffer->add(display_string);
+        display_obj.loading = false;
+      }
+    }
+};
+
+class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks {
+    void onResult(BLEAdvertisedDevice advertisedDevice) {
+      String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"};
+      //Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
+      Serial.print("Device: ");
+      if(advertisedDevice.getName().length() != 0)
+      {
+        Serial.print(advertisedDevice.getName().c_str());
+        for(int i = 0; i < bad_list_length; i++)
+        {
+          if(strcmp(advertisedDevice.getName().c_str(), bad_list[i].c_str()) == 0)
+          {
+            Serial.println("Found some shit");
+            //digitalWrite(LED, HIGH);
+          }
+        }
+      }
+      else
+        Serial.print(advertisedDevice.getAddress().toString().c_str());
+      Serial.print(" RSSI: ");
+      Serial.println(advertisedDevice.getRSSI());
+    }
+};
+
+
+WiFiScan::WiFiScan()
+{
+  //printf("WiFiScan Object initializing...");
+}
+
+// Function to prepare to run a specific scan
+void WiFiScan::StartScan(uint8_t scan_mode)
+{  
+  if (scan_mode == WIFI_SCAN_OFF)
+    StopScan(scan_mode);
+  else if (scan_mode == WIFI_SCAN_PROBE)
+    RunProbeScan(scan_mode);
+  else if (scan_mode == WIFI_SCAN_AP)
+    RunBeaconScan(scan_mode);
+  else if (scan_mode == BT_SCAN_ALL)
+    RunBluetoothScan(scan_mode);
+  else if (scan_mode == BT_SCAN_SKIMMERS)
+    RunBluetoothScan(scan_mode);
+
+  WiFiScan::currentScanMode = scan_mode;
+}
+
+// Function to stop all wifi scans
+void WiFiScan::StopScan(uint8_t scan_mode)
+{
+  if ((currentScanMode == WIFI_SCAN_PROBE) ||
+  (currentScanMode == WIFI_SCAN_AP) ||
+  (currentScanMode == WIFI_SCAN_ST) ||
+  (currentScanMode == WIFI_SCAN_ALL))
+  {
+    esp_wifi_set_promiscuous(false);
+  }
+  else if ((currentScanMode == BT_SCAN_ALL) ||
+  (currentScanMode == BT_SCAN_SKIMMERS))
+  {
+    Serial.println("Stopping BLE scan...");
+    pBLEScan->stop();
+    Serial.println("BLE Scan Stopped");
+  }
+
+  display_obj.display_buffer->clear();
+  Serial.print("display_buffer->size(): ");
+  Serial.println(display_obj.display_buffer->size());
+}
+
+// Function for updating scan status
+void WiFiScan::main(uint32_t currentTime)
+{
+  // WiFi operations
+  if ((currentScanMode == WIFI_SCAN_PROBE) ||
+  (currentScanMode == WIFI_SCAN_AP) ||
+  (currentScanMode == WIFI_SCAN_ST) ||
+  (currentScanMode == WIFI_SCAN_ALL))
+  {
+    if (currentTime - initTime >= 1000)
+    {
+      initTime = millis();
+      channelHop();
+    }
+  }
+
+  // Bluetooth operations
+  /*
+  else if ((currentScanMode == BT_SCAN_ALL) ||
+  (currentScanMode == BT_SCAN_SKIMMERS))
+  {
+    if (currentTime - initTime >= 2000)
+    {
+      BLEScanResults foundDevices = pBLEScan->start(bluetoothScanTime, false);
+      Serial.print("Devices found: ");
+      Serial.print(foundDevices.getCount());
+      Serial.println(" Scan done!\n\n");
+      pBLEScan->clearResults();
+      initTime = millis();
+    }
+  }
+  */
+}
+
+// Function to start running a beacon scan
+void WiFiScan::RunBeaconScan(uint8_t scan_mode)
+{
+  //Serial.println("Preparing beacon scan...");
+  display_obj.print_delay_1 = 15;
+  display_obj.print_delay_2 = 10;
+  display_obj.clearScreen();
+  display_obj.initScrollValues();
+  display_obj.tft.setTextWrap(false);
+  display_obj.tft.setTextColor(TFT_WHITE, TFT_BLUE);
+  display_obj.tft.fillRect(0,0,240,16, TFT_BLUE);
+  display_obj.tft.drawCentreString(" Beacon Sniffer ",120,0,2);
+  display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+  display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
+  esp_wifi_init(&cfg);
+  esp_wifi_set_storage(WIFI_STORAGE_RAM);
+  esp_wifi_set_mode(WIFI_MODE_NULL);
+  esp_wifi_set_promiscuous(true);
+  esp_wifi_set_promiscuous_filter(&filt);
+  esp_wifi_set_promiscuous_rx_cb(&beaconSnifferCallback);
+  esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
+  initTime = millis();
+  //Serial.println("Finished scan init");
+}
+
+
+// Function for running probe request scan
+void WiFiScan::RunProbeScan(uint8_t scan_mode)
+{
+  //Serial.println("Preparing probe request scan...");
+  display_obj.print_delay_1 = 15;
+  display_obj.print_delay_2 = 10;
+  display_obj.clearScreen();
+  display_obj.initScrollValues();
+  display_obj.tft.setTextWrap(false);
+  display_obj.tft.setTextColor(TFT_BLACK, TFT_MAGENTA);
+  display_obj.tft.fillRect(0,0,240,16, TFT_MAGENTA);
+  display_obj.tft.drawCentreString(" Probe Request Sniffer ",120,0,2);
+  display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+  display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
+  esp_wifi_init(&cfg);
+  esp_wifi_set_storage(WIFI_STORAGE_RAM);
+  esp_wifi_set_mode(WIFI_MODE_NULL);
+  esp_wifi_set_promiscuous(true);
+  esp_wifi_set_promiscuous_filter(&filt);
+  esp_wifi_set_promiscuous_rx_cb(&probeSnifferCallback);
+  esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
+  initTime = millis();
+  //Serial.println("Finished scan init");
+}
+
+// Function to start running any BLE scan
+void WiFiScan::RunBluetoothScan(uint8_t scan_mode)
+{
+  display_obj.print_delay_1 = 50;
+  display_obj.print_delay_2 = 20;
+  BLEDevice::init("");
+  pBLEScan = BLEDevice::getScan(); //create new scan
+  if (scan_mode == BT_SCAN_ALL)
+  {
+    display_obj.clearScreen();
+    display_obj.initScrollValues();
+    display_obj.tft.setTextWrap(false);
+    display_obj.tft.setTextColor(TFT_BLACK, TFT_GREEN);
+    display_obj.tft.fillRect(0,0,240,16, TFT_GREEN);
+    display_obj.tft.drawCentreString(" Bluetooth Sniff ",120,0,2);
+    display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+    display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+    pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback());
+  }
+  else if (scan_mode == BT_SCAN_SKIMMERS)
+  {
+    display_obj.clearScreen();
+    display_obj.initScrollValues();
+    display_obj.tft.setTextWrap(false);
+    display_obj.tft.setTextColor(TFT_BLACK, TFT_MAGENTA);
+    display_obj.tft.fillRect(0,0,240,16, TFT_MAGENTA);
+    display_obj.tft.drawCentreString(" Detect Card Skimmers ",120,0,2);
+    display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
+    display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+    pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanSkimmersCallback());
+  }
+  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
+  pBLEScan->setInterval(100);
+  pBLEScan->setWindow(99);  // less or equal setInterval value
+  pBLEScan->start(0, scanCompleteCB);
+  Serial.println("Started BLE Scan");
+  initTime = millis();
+}
+
+// Function that is called when BLE scan is completed
+void WiFiScan::scanCompleteCB(BLEScanResults scanResults) {
+  printf("Scan complete!\n");
+  printf("Found %d devices\n", scanResults.getCount());
+  scanResults.dump();
+} // scanCompleteCB
+
+
+// Function to extract MAC addr from a packet at given offset
+void WiFiScan::getMAC(char *addr, uint8_t* data, uint16_t offset) {
+  sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
+}
+
+void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
+{
+  wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
+  WifiMgmtHdr *frameControl = (WifiMgmtHdr*)snifferPacket->payload;
+  wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)snifferPacket->rx_ctrl;
+  int len = snifferPacket->rx_ctrl.sig_len;
+
+  String display_string = "";
+
+  if (type == WIFI_PKT_MGMT)
+  {
+    int fctl = ntohs(frameControl->fctl);
+    const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
+    const WifiMgmtHdr *hdr = &ipkt->hdr;
+
+    // If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP
+    if ((snifferPacket->payload[0] == 0x80) && (display_obj.display_buffer->size() == 0))
+    {
+      delay(random(0, 10));
+      Serial.print("RSSI: ");
+      Serial.print(snifferPacket->rx_ctrl.rssi);
+      Serial.print(" Ch: ");
+      Serial.print(snifferPacket->rx_ctrl.channel);
+      Serial.print(" BSSID: ");
+      char addr[] = "00:00:00:00:00:00";
+      getMAC(addr, snifferPacket->payload, 10);
+      Serial.print(addr);
+      display_string.concat(addr);
+      Serial.print(" ESSID: ");
+      display_string.concat(" -> ");
+      for (int i = 0; i < snifferPacket->payload[37]; i++)
+      {
+        Serial.print((char)snifferPacket->payload[i + 38]);
+        display_string.concat((char)snifferPacket->payload[i + 38]);
+      }
+
+      for (int i = 0; i < 19 - snifferPacket->payload[37]; i++)
+      {
+        display_string.concat(" ");
+      }
+
+      Serial.print(" ");
+
+      //while (display_obj.display_buffer->get(0) != "")
+      //  delay(10);
+      //while (display_obj.display_buffer->size() > 0)
+      //  delay(10);
+
+      if (display_obj.display_buffer->size() == 0)
+      {
+        //while (display_obj.printing)
+        //  delay(1);
+        display_obj.loading = true;
+        display_obj.display_buffer->add(display_string);
+        display_obj.loading = false;
+      }
+      //display_obj.display_buffer->add(0, display_string);
+
+      //Serial.print(display_obj.display_buffer->size());
+      
+
+      
+      Serial.println();
+    }
+  }
+}
+
+void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) {
+  wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
+  WifiMgmtHdr *frameControl = (WifiMgmtHdr*)snifferPacket->payload;
+  wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)snifferPacket->rx_ctrl;
+  int len = snifferPacket->rx_ctrl.sig_len;
+
+  String display_string = "";
+
+  if (type == WIFI_PKT_MGMT)
+  {
+    int fctl = ntohs(frameControl->fctl);
+    const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
+    const WifiMgmtHdr *hdr = &ipkt->hdr;
+
+
+    // If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP
+    if ((snifferPacket->payload[0] == 0x40) && (display_obj.display_buffer->size() == 0))
+    {
+      delay(random(0, 10));
+      Serial.print("RSSI: ");
+      Serial.print(snifferPacket->rx_ctrl.rssi);
+      Serial.print(" Ch: ");
+      Serial.print(snifferPacket->rx_ctrl.channel);
+      Serial.print(" Client: ");
+      char addr[] = "00:00:00:00:00:00";
+      getMAC(addr, snifferPacket->payload, 10);
+      Serial.print(addr);
+      display_string.concat(addr);
+      Serial.print(" Requesting: ");
+      display_string.concat(" -> ");
+      for (int i = 0; i < snifferPacket->payload[25]; i++)
+      {
+        Serial.print((char)snifferPacket->payload[26 + i]);
+        display_string.concat((char)snifferPacket->payload[26 + i]);
+      }
+
+      // Print spaces because of the rotating lines of the hardware scroll.
+      // The same characters print from previous lines so I just overwrite them
+      // with spaces.
+      for (int i = 0; i < 19 - snifferPacket->payload[25]; i++)
+      {
+        display_string.concat(" ");
+      }
+
+      if (display_obj.display_buffer->size() == 0)
+      {
+        //while (display_obj.printing)
+        //  delay(1);
+        display_obj.loading = true;
+        display_obj.display_buffer->add(display_string);
+        display_obj.loading = false;
+      }
+      
+      Serial.println();    
+    }
+  }
+}
+
+//void WiFiScan::sniffer_callback(void* buf, wifi_promiscuous_pkt_type_t type) {
+//  wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
+//  showMetadata(snifferPacket, type);
+//}
+
+// Function to cycle to the next channel
+void WiFiScan::channelHop()
+{
+  set_channel = set_channel + 1;
+  if (set_channel > 13) {
+    set_channel = 1;
+  }
+  esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
+  //Serial.println(set_channel);
+  delay(1);
+}

+ 74 - 0
esp32_marauder/WiFiScan.h

@@ -0,0 +1,74 @@
+#ifndef WiFiScan_h
+#define WiFiScan_h
+
+#include <BLEDevice.h>
+#include <BLEUtils.h>
+#include <BLEScan.h>
+#include <BLEAdvertisedDevice.h>
+
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include "Display.h"
+//#include "MenuFunctions.h"
+
+#define bad_list_length 3
+
+#define WIFI_SCAN_OFF 0
+#define WIFI_SCAN_PROBE 1
+#define WIFI_SCAN_AP 2
+#define WIFI_SCAN_ST 3
+#define WIFI_SCAN_ALL 4
+#define BT_SCAN_ALL 5
+#define BT_SCAN_SKIMMERS 6
+
+extern Display display_obj;
+
+
+class WiFiScan
+{
+  private:
+    uint32_t initTime = 0;
+    bool run_setup = true;
+    int set_channel = 1;
+    int bluetoothScanTime = 5;
+    const wifi_promiscuous_filter_t filt = {.filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT | WIFI_PROMIS_FILTER_MASK_DATA};
+    BLEScan* pBLEScan;
+
+    typedef struct
+    {
+      int16_t fctl;
+      int16_t duration;
+      uint8_t da;
+      uint8_t sa;
+      uint8_t bssid;
+      int16_t seqctl;
+      unsigned char payload[];
+    } __attribute__((packed)) WifiMgmtHdr;
+    
+    typedef struct {
+      WifiMgmtHdr hdr;
+      uint8_t payload[0];
+    } wifi_ieee80211_packet_t;
+
+    void RunBeaconScan(uint8_t scan_mode);
+    void RunProbeScan(uint8_t scan_mode);
+    void RunBluetoothScan(uint8_t scan_mode);
+    static void scanCompleteCB(BLEScanResults scanResults);
+
+  public:
+    WiFiScan();
+    
+    void channelHop();
+    uint8_t currentScanMode = 0;
+    void main(uint32_t currentTime);
+    void StartScan(uint8_t scan_mode);
+    void StopScan(uint8_t scan_mode);
+
+    //static String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"};
+    
+    static void getMAC(char *addr, uint8_t* data, uint16_t offset);
+    static void beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
+    static void probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
+    //static void sniffer_callback(void* buf, wifi_promiscuous_pkt_type_t type);
+};
+#endif

TEMPAT SAMPAH
esp32_marauder/data/marauder3L.jpg


+ 92 - 0
esp32_marauder/esp32_marauder.ino

@@ -0,0 +1,92 @@
+#include <WiFi.h>
+#include <Wire.h>
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_system.h"
+#include <Arduino.h>
+
+#include "Display.h"
+#include "WiFiScan.h"
+#include "MenuFunctions.h"
+
+Display display_obj;
+WiFiScan wifi_scan_obj;
+MenuFunctions menu_function_obj;
+
+uint32_t currentTime  = 0;
+
+/*
+void getPresses(void *pvParameter)
+{
+  uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
+   
+  while (true)
+  {
+    boolean pressed = display_obj.tft.getTouch(&t_x, &t_y);
+    Serial.print("X: ");
+    Serial.print(t_x);
+    Serial.print(" Y: ");
+    Serial.println(t_y);
+
+    menu_function_obj.pressed = pressed;
+
+    
+    //menu_function_obj.handlePress(pressed, t_x, t_y);
+    if (pressed)
+    {
+      menu_function_obj.x = t_x;
+      menu_function_obj.y = t_y;
+    }
+
+    
+    delay(1);
+  }
+}*/
+
+void setup()
+{
+
+  pinMode(FLASH_BUTTON, INPUT);
+  pinMode(TFT_BL, OUTPUT);
+  digitalWrite(TFT_BL, LOW);
+  
+  Serial.begin(115200);
+  Serial.println("\n\n--------------------------------");
+  Serial.println("         ESP32 Marauder      ");
+  Serial.println("--------------------------------\n\n");
+
+  // Run display setup
+  display_obj.RunSetup();
+
+  // Build menus
+  menu_function_obj.RunSetup();
+  //menu_function_obj.displayCurrentMenu();
+
+  //xTaskCreate(&getPresses, "getPresses", 2048, NULL, 5, NULL);
+  
+
+  // Start a scan mode automatically
+  // In the real version, just setup wifi
+  // and wait for user input for scan modes
+  //wifi_scan_obj.StartScan(WIFI_SCAN_PROBE);
+
+}
+
+
+void loop()
+{
+  // get the current time
+  currentTime = millis();
+
+  // Update all of our objects
+  display_obj.main(); 
+  wifi_scan_obj.main(currentTime);
+  //if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF)
+  menu_function_obj.main();
+
+  //vTaskDelay(portMAX_DELAY);
+  delay(1);
+}