Added files via upload

Added files via upload

Arduino program for controlling Charlie's head

#if (ARDUINO >= 100)
 #include <Arduino.h>
#else
 #include <WProgram.h>
#endif

#include <Servo.h>
#include <ros.h>
#include <std_msgs/UInt16.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

ros::NodeHandle  nh;

int xpos = 250;
int ypos = 175;
int xserv = 327;
int yserv = 327;
int centxmax = 275;
int centymax = 200;
int centxmin = 225;
int centymin = 150;

void servox( const std_msgs::UInt16& cmd_msg)
{
  xpos = cmd_msg.data;
  digitalWrite(13, HIGH-digitalRead(13));  //toggle led
  if(xpos < centxmin)
    {
      if(xserv < 525)
      {
       xserv = xserv + 1;
      }
    }
    else if(xpos > centxmax)
    {
      if(xserv > 125)
      {
       xserv = xserv - 1;
      }
    }
    pwm.setPWM(6,0,xserv);
    Serial.println("x = ");
    Serial.println(xserv);
}
void servoy( const std_msgs::UInt16& cmd_msg)
{
  ypos = cmd_msg.data;
  digitalWrite(13, HIGH-digitalRead(13));  //toggle led
  if(ypos < centymin)
    {
      if( yserv > 237)
      {
        yserv = yserv - 1;
      }
    }
    else if(ypos > centymax)
    {
      if( yserv < 341)
      {
        yserv = yserv + 1;
      }
    }
    pwm.setPWM(8,0,yserv);
    Serial.println("y = ");
    Serial.println(yserv);
}

ros::Subscriber<std_msgs::UInt16> sub1("/face_detector/face_position_X", servox);
ros::Subscriber<std_msgs::UInt16> sub2("/face_detector/face_position_Y", servoy);

void setup()
{
  Serial.begin(57600);
  pinMode(13, OUTPUT);
  nh.initNode();
  nh.subscribe(sub1);
  nh.subscribe(sub2);
  #ifdef ESP8266
    Wire.pins(2, 14);   // ESP8266 can use any two pins, such as SDA to #2 and SCL to #14
  #endif
  pwm.begin();
  pwm.setPWMFreq(60);

}

void loop(){
  nh.spinOnce();
  delay(1);
}

error: pathspec 'CharlieNeck.ino' did not match any file(s) known to git


//////////////////////////////////////////////////////////////////////////////////
/*
    Dreamcast Companion App
*/
#include "global.h"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <FS.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <SPIFlash.h>
#include "AsyncJson.h"
#include "ArduinoJson.h"
#include <Task.h>
#include "task/FlashTask.h"
#include "task/FlashVerifyTask.h"
#include "task/FlashESPTask.h"
#include "task/FlashESPIndexTask.h"
#include "task/FPGATask.h"
#include "task/DebugTask.h"
#include "task/TimeoutTask.h"
#include "task/FlashCheckTask.h"
#include "task/FlashEraseTask.h"
#include "task/InfoTask.h"
#include "util.h"
#include "data.h"
#include "web.h"
#include "Menu.h"
#include "pwgen.h"

//////////////////////////////////////////////////////////////////////////////////

bool isHhttpAuthPassGenerated = false;
bool isRelaxedFirmware = false;

char ssid[64] = DEFAULT_SSID;
char password[64] = DEFAULT_PASSWORD;
char otaPassword[64] = DEFAULT_OTA_PASSWORD;
char firmwareServer[256] = DEFAULT_FW_SERVER;
char firmwareServerPath[256] = DEFAULT_FW_SERVER_PATH;
char firmwareVersion[64] = DEFAULT_FW_VERSION;
char firmwareVariant[64] = DEFAULT_FW_VARIANT;
char httpAuthUser[64] = DEFAULT_HTTP_USER;
char httpAuthPass[64] = "";
char confIPAddr[24] = DEFAULT_CONF_IP_ADDR;
char confIPGateway[24] = DEFAULT_CONF_IP_GATEWAY;
char confIPMask[24] = DEFAULT_CONF_IP_MASK;
char confIPDNS[24] = DEFAULT_CONF_IP_DNS;
char host[64] = DEFAULT_HOST;
char videoMode[16] = "";
char configuredResolution[16] = "";
char resetMode[16] = "";
char deinterlaceMode480i[16] = "";
char deinterlaceMode576i[16] = "";
char protectedMode[8] = "";
char AP_NameChar[64];
char WiFiAPPSK[12] = "";
char keyboardLayout[8] = DEFAULT_KEYBOARD_LAYOUT;
IPAddress ipAddress( 192, 168, 4, 1 );
bool inInitialSetupMode = false;
AsyncWebServer server(80);
SPIFlash flash(CS);
int last_error = NO_ERROR;
int totalLength;
int readLength;
bool currentJobDone = true;

File flashFile;

uint8_t CurrentResolution = RESOLUTION_1080p;
uint8_t PrevCurrentResolution;
uint8_t CurrentResolutionData = 0;
uint8_t ForceVGA = VGA_ON;
uint8_t CurrentResetMode = RESET_MODE_LED;
uint8_t CurrentDeinterlaceMode480i = DEINTERLACE_MODE_BOB;
uint8_t CurrentDeinterlaceMode576i = DEINTERLACE_MODE_BOB;
uint8_t CurrentProtectedMode = PROTECTED_MODE_OFF;
int8_t Offset240p;
int8_t OffsetVGA;
int8_t AutoOffsetVGA = 0;
uint8_t UpscalingMode;
uint8_t ColorSpace;

char md5FPGA[48];
char md5ESP[48];
char md5IndexHtml[48];

bool scanlinesActive;
int scanlinesIntensity;
bool scanlinesOddeven;
bool scanlinesThickness;

bool reflashNeccessary;
bool reflashNeccessary2;
bool reflashNeccessary3;

MD5Builder md5;
TaskManager taskManager;
FlashTask flashTask(1);
FlashESPTask flashESPTask(1);
FlashESPIndexTask flashESPIndexTask(1);
DebugTask debugTask(16);
TimeoutTask timeoutTask(MsToTaskTime(100));
FlashCheckTask flashCheckTask(1, NULL);
FlashVerifyTask flashVerifyTask(1);
FlashEraseTask flashEraseTask(1);
InfoTask infoTask(16);

extern Menu mainMenu;
Menu *currentMenu;
Menu *previousMenu;

//////////////////////////////////////////////////////////////////////////////////

void setupSPIFFS() {
    DEBUG2(">> Setting up SPIFFS...\n");
    if (!SPIFFS.begin()) {
        DEBUG(">> SPIFFS begin failed, trying to format...");
        if (SPIFFS.format()) {
            DEBUG("done.\n");
        } else {
            DEBUG("error.\n");
        }
    }
}

void setupResetMode() {
    readCurrentResetMode();
    DEBUG2(">> Setting up reset mode: %x\n", CurrentResetMode);
    reflashNeccessary3 = !forceI2CWrite(
        I2C_RESET_CONF, CurrentResetMode,
        I2C_PING, 0
    );
}

void setupOutputResolution() {
    readVideoMode();
    readCurrentResolution();
    readCurrentDeinterlaceMode480i();
    readCurrentDeinterlaceMode576i();

    DEBUG2(">> Setting up output resolution: %x\n", ForceVGA | CurrentResolution);
    reflashNeccessary = !forceI2CWrite(
        I2C_OUTPUT_RESOLUTION, ForceVGA | mapResolution(CurrentResolution),
        //ForceVGA ? I2C_DC_RESET : I2C_PING, 0
        I2C_DC_RESET, 0
    );
}

void setupScanlines() {
    readScanlinesActive();
    readScanlinesIntensity();
    readScanlinesOddeven();
    readScanlinesThickness();

    uint8_t upper = getScanlinesUpperPart();
    uint8_t lower = getScanlinesLowerPart();

    DEBUG2(">> Setting up scanlines:\n");
    reflashNeccessary2 = !forceI2CWrite(
        I2C_SCANLINE_UPPER, upper,
        I2C_SCANLINE_LOWER, lower
    );
}

void setupOffsets() {
    read240pOffset();
    readVGAOffset();
    forceI2CWrite(I2C_240P_OFFSET, Offset240p, I2C_240P_OFFSET, Offset240p);
    forceI2CWrite(I2C_VGA_OFFSET, getEffectiveOffsetVGA(), I2C_VGA_OFFSET, getEffectiveOffsetVGA());
}

void setupUpscalingMode() {
    readUpscalingMode();
    forceI2CWrite(
        I2C_UPSCALING_MODE, UpscalingMode,
        I2C_UPSCALING_MODE, UpscalingMode
    );
}

void setupColorSpace() {
    readColorSpace();
    forceI2CWrite(
        I2C_COLOR_SPACE, ColorSpace,
        I2C_COLOR_SPACE, ColorSpace
    );
}

void setupTaskManager() {
    DEBUG2(">> Setting up task manager...\n");
    taskManager.Setup();
    taskManager.StartTask(&fpgaTask);
}

void setupCredentials(void) {
    DEBUG2(">> Reading stored values...\n");

    _readFile("/etc/ssid", ssid, 64, DEFAULT_SSID);
    _readFile("/etc/password", password, 64, DEFAULT_PASSWORD);
    _readFile("/etc/ota_pass", otaPassword, 64, DEFAULT_OTA_PASSWORD);
    _readFile("/etc/firmware_server", firmwareServer, 256, DEFAULT_FW_SERVER);
    _readFile("/etc/firmware_server_path", firmwareServerPath, 256, DEFAULT_FW_SERVER_PATH);
    _readFile("/etc/firmware_variant", firmwareVariant, 64, DEFAULT_FW_VARIANT);
    _readFile("/etc/firmware_version", firmwareVersion, 64, DEFAULT_FW_VERSION);
    _readFile("/etc/http_auth_user", httpAuthUser, 64, DEFAULT_HTTP_USER);
    _readFile("/etc/http_auth_pass", httpAuthPass, 64, DEFAULT_HTTP_PASS);
    _readFile("/etc/conf_ip_addr", confIPAddr, 24, DEFAULT_CONF_IP_ADDR);
    _readFile("/etc/conf_ip_gateway", confIPGateway, 24, DEFAULT_CONF_IP_GATEWAY);
    _readFile("/etc/conf_ip_mask", confIPMask, 24, DEFAULT_CONF_IP_MASK);
    _readFile("/etc/conf_ip_dns", confIPDNS, 24, DEFAULT_CONF_IP_DNS);
    _readFile("/etc/hostname", host, 64, DEFAULT_HOST);
    _readFile("/etc/keyblayout", keyboardLayout, 8, DEFAULT_KEYBOARD_LAYOUT);
    readCurrentProtectedMode();

    if (strlen(httpAuthPass) == 0) {
        generate_password(httpAuthPass);
        isHhttpAuthPassGenerated = true;
    }
}

void generateWiFiPassword() {
    generate_password(WiFiAPPSK);
    DEBUG2("AP password: %s\n", WiFiAPPSK);
}

void setupAPMode(void) {
    WiFi.mode(WIFI_AP);
    uint8_t mac[WL_MAC_ADDR_LENGTH];
    WiFi.softAPmacAddress(mac);
    String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
    String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
    macID.toUpperCase();
    String AP_NameString = String("DCHDMI") + String("-") + macID;

    memset(AP_NameChar, 0, AP_NameString.length() + 1);

    for (uint i=0; i<AP_NameString.length(); i++) {
        if (i < 63) {
            AP_NameChar[i] = AP_NameString.charAt(i);
        }
    }

    DEBUG2("AP_NameChar: %s\n", AP_NameChar);
    generateWiFiPassword();
    WiFi.softAP(AP_NameChar, WiFiAPPSK);
    DEBUG2(">> SSID:   %s\n", AP_NameChar);
    DEBUG2(">> AP-PSK: %s\n", WiFiAPPSK);
    inInitialSetupMode = true;
}

void setupWiFi() {
    WiFi.persistent(false);
    if (strlen(ssid) == 0) {
        DEBUG2(">> No ssid, starting AP mode...\n");
        setupAPMode();
    } else {
        DEBUG2(">> Trying to connect in client mode first...\n");
        setupWiFiStation();
    }
}

void setupWiFiStation() {
    bool doStaticIpConfig = false;
    IPAddress ipAddr;
    doStaticIpConfig = ipAddr.fromString(confIPAddr);
    IPAddress ipGateway;
    doStaticIpConfig = doStaticIpConfig && ipGateway.fromString(confIPGateway);
    IPAddress ipMask;
    doStaticIpConfig = doStaticIpConfig && ipMask.fromString(confIPMask);
    IPAddress ipDNS;
    doStaticIpConfig = doStaticIpConfig && ipDNS.fromString(confIPDNS);

    //WIFI INIT
    WiFi.mode(WIFI_STA);
    WiFi.begin();
    WiFi.disconnect(true);
    WiFi.softAPdisconnect(true);
    // WiFi.setAutoConnect(true);
    // WiFi.setAutoReconnect(true);

    DEBUG(">> Do static ip configuration: %i\n", doStaticIpConfig);
    if (doStaticIpConfig) {
        WiFi.config(ipAddr, ipGateway, ipMask, ipDNS);
    }

    DEBUG(">> WiFi.getAutoConnect: %i\n", WiFi.getAutoConnect());
    DEBUG(">> Connecting to %s\n", ssid);

    if (String(WiFi.SSID()) != String(ssid)) {
        WiFi.begin(ssid, password);
        DEBUG(">> WiFi.begin: %s@%s\n", password, ssid);
    }

    bool success = true;
    int tries = 0;
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        DBG_OUTPUT_PORT.print(".");
        if (tries == 60) {
            WiFi.disconnect();
            success = false;
            break;
        }
        tries++;
    }

    DEBUG2(">> success: %i\n", success);

    if (!success) {
        // setup AP mode to configure ssid and password
        setupAPMode();
    } else {
        WiFi.hostname(host);
        WiFi.setAutoReconnect(true);

        ipAddress = WiFi.localIP();
        IPAddress gateway = WiFi.gatewayIP();
        IPAddress subnet = WiFi.subnetMask();

        DEBUG2(
            ">> Connected!\n   IP address:      %d.%d.%d.%d\n",
            ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]
        );
        DEBUG2(
            "   Gateway address: %d.%d.%d.%d\n",
            gateway[0], gateway[1], gateway[2], gateway[3]
        );
        DEBUG2(
            "   Subnet mask:     %d.%d.%d.%d\n",
            subnet[0], subnet[1], subnet[2], subnet[3]
        );
        DEBUG2(
            "   Hostname:        %s\n",
            WiFi.hostname().c_str()
        );
        DEBUG2(
            "   MAC addr:        %s\n",
            WiFi.macAddress().c_str()
        );
    }
}

void setupMDNS() {
    DEBUG2(">> Setting up mDNS...\n");
    if (MDNS.begin(host, ipAddress)) {
        DEBUG2(">> mDNS started.\n");
        MDNS.addService("http", "tcp", 80);
        DEBUG(
            ">> http://%s.local/\n",
            host
        );
    } else {
        DEBUG2(">> mDNS setup failed.\n");
    }
}

void setupHTTPServer() {
    DEBUG2(">> Setting up HTTP server...\n");

    server.on("/upload/fpga", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, FIRMWARE_FILE, index, data, len, final);
    });

    server.on("/upload/esp", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, ESP_FIRMWARE_FILE, index, data, len, final);
    });

    server.on("/upload/index", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, ESP_INDEX_STAGING_FILE, index, data, len, final);
    });

    server.on("/debug", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[64];
        _readFile("/debug", msg, 64, "---");
        request->send(200, "text/plain", msg);
    });

    server.on("/list-files", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncJsonResponse * response = new AsyncJsonResponse();
        response->addHeader("Server","DCHDMI");
        JsonObject& root = response->getRoot();
        FSInfo fs_info;
        SPIFFS.info(fs_info);

        root["totalBytes"] = fs_info.totalBytes;
        root["usedBytes"] = fs_info.usedBytes;
        // root["blockSize"] = fs_info.blockSize;
        // root["pageSize"] = fs_info.pageSize;
        // root["maxOpenFiles"] = fs_info.maxOpenFiles;
        // root["maxPathLength"] = fs_info.maxPathLength;
        // root["freeSketchSpace"] = ESP.getFreeSketchSpace();
        // root["maxSketchSpace"] = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
        // root["flashChipSize"] = ESP.getFlashChipSize();
        // root["freeHeapSize"] = ESP.getFreeHeap();

        JsonArray &datas = root.createNestedArray("files");

        Dir dir = SPIFFS.openDir("/");
        while (dir.next()) {
            JsonObject &data = datas.createNestedObject();
            data["name"] = dir.fileName();
            data["size"] = dir.fileSize();
        }

        response->setLength();
        request->send(response);
    });

    server.on("/download/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleFPGADownload(request);
    });

    server.on("/download/esp", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPDownload(request);
    });

    server.on("/download/index", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPIndexDownload(request);
    });

    server.on("/flash/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleFlash(request, FIRMWARE_FILE);
    });

    server.on("/flash/esp", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPFlash(request, ESP_FIRMWARE_FILE);
    });

    server.on("/flash/index", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPIndexFlash(request);
    });

    server.on("/cleanupindex", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove(ESP_INDEX_FILE);
        SPIFFS.remove(String(ESP_INDEX_FILE) + ".md5");
        request->send(200);
    });

    server.on("/cleanup", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove(FIRMWARE_FILE);
        SPIFFS.remove(ESP_FIRMWARE_FILE);
        SPIFFS.remove(ESP_INDEX_STAGING_FILE);
        SPIFFS.remove(String(FIRMWARE_FILE) + ".md5");
        SPIFFS.remove(String(ESP_FIRMWARE_FILE) + ".md5");
        SPIFFS.remove(String(ESP_INDEX_STAGING_FILE) + ".md5");

        SPIFFS.remove(LOCAL_FPGA_MD5);
        SPIFFS.remove(LOCAL_ESP_MD5);
        SPIFFS.remove(LOCAL_ESP_INDEX_MD5);

        SPIFFS.remove(SERVER_FPGA_MD5);
        SPIFFS.remove(SERVER_ESP_MD5);
        SPIFFS.remove(SERVER_ESP_INDEX_MD5);

        // remove legacy config data
        SPIFFS.remove("/etc/firmware_fpga");
        SPIFFS.remove("/etc/firmware_format");
        SPIFFS.remove("/etc/force_vga");
        SPIFFS.remove("/etc/resolution");
        request->send(200);
    });

    server.on("/resetconfig", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove("/etc/ssid");
        SPIFFS.remove("/etc/password");
        SPIFFS.remove("/etc/ota_pass");
        SPIFFS.remove("/etc/http_auth_user");
        SPIFFS.remove("/etc/http_auth_pass");
        SPIFFS.remove("/etc/conf_ip_addr");
        SPIFFS.remove("/etc/conf_ip_gateway");
        SPIFFS.remove("/etc/conf_ip_mask");
        SPIFFS.remove("/etc/conf_ip_dns");
        SPIFFS.remove("/etc/hostname");
        SPIFFS.remove("/etc/keyblayout");

        ssid[0] = '\0';
        password[0] = '\0';
        otaPassword[0] = '\0';
        keyboardLayout[0] = '\0';
        // keep passwords alive until power off
        //httpAuthUser[0] = '\0';
        //httpAuthPass[0] = '\0';
        confIPAddr[0] = '\0';
        confIPGateway[0] = '\0';
        confIPMask[0] = '\0';
        confIPDNS[0] = '\0';
        host[0] = '\0';

        request->send(200);
    });

    server.on("/factoryresetall", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.format();
        request->send(200);
    });

   server.on("/flash/secure/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        disableFPGA();
        handleFlash(request, FIRMWARE_FILE);
    });

    server.on("/progress", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("progress requested...\n");
        char msg[64];
        if (last_error) {
            sprintf(msg, "ERROR %i\n", last_error);
            request->send(200, "text/plain", msg);
            DEBUG("...delivered: %s (%i).\n", msg, last_error);
            // clear last_error
            last_error = NO_ERROR;
        } else {
            int progress = totalLength <= 0 ? 0 : (int)(readLength * 100 / totalLength);
            if (progress == 100 && !currentJobDone) {
                progress = 99;
            }
            sprintf(msg, "%i\n", progress);
            request->send(200, "text/plain", msg);
            DEBUG2("...delivered: %s.\n", msg);
        }
    });

    server.on("/flash_size", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[64];
        sprintf(msg, "%lu\n", (long unsigned int) ESP.getFlashChipSize());
        request->send(200, "text/plain", msg);
    });

    server.on("/reset/fpga", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("FPGA reset requested...\n");
        fpgaTask.DoResetFPGA();
        request->send(200, "text/plain", "OK\n");
        DEBUG("...delivered.\n");
    });

    server.on("/reset/dc", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("DC reset requested...\n");
        fpgaTask.Write(I2C_DC_RESET, 0, NULL);
        request->send(200, "text/plain", "OK\n");
        DEBUG("...delivered.\n");
    });

    server.on("/reset/all", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        resetall();
    });

    server.on("/reset/pll", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_PLL_RESET, 0, NULL);
        request->send(200, "text/plain", "OK\n");
    });

    server.on("/issetupmode", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200, "text/plain", inInitialSetupMode ? "true\n" : "false\n");
    });

    server.on("/ping", HTTP_GET, [](AsyncWebServerRequest *request) {
        request->send(200);
    });

    server.on("/setup", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        writeSetupParameter(request, "ssid", ssid, 64, DEFAULT_SSID);
        writeSetupParameter(request, "password", password, 64, DEFAULT_PASSWORD);
        writeSetupParameter(request, "ota_pass", otaPassword, 64, DEFAULT_OTA_PASSWORD);
        writeSetupParameter(request, "firmware_server", firmwareServer, 256, DEFAULT_FW_SERVER);
        writeSetupParameter(request, "firmware_server_path", firmwareServerPath, 256, DEFAULT_FW_SERVER_PATH);
        writeSetupParameter(request, "firmware_version", firmwareVersion, 64, DEFAULT_FW_VERSION);
        writeSetupParameter(request, "http_auth_user", httpAuthUser, 64, DEFAULT_HTTP_USER, true);
        writeSetupParameter(request, "http_auth_pass", httpAuthPass, 64, DEFAULT_HTTP_PASS, true);
        writeSetupParameter(request, "conf_ip_addr", confIPAddr, 24, DEFAULT_CONF_IP_ADDR);
        writeSetupParameter(request, "conf_ip_gateway", confIPGateway, 24, DEFAULT_CONF_IP_GATEWAY);
        writeSetupParameter(request, "conf_ip_mask", confIPMask, 24, DEFAULT_CONF_IP_MASK);
        writeSetupParameter(request, "conf_ip_dns", confIPDNS, 24, DEFAULT_CONF_IP_DNS);
        writeSetupParameter(request, "hostname", host, 64, DEFAULT_HOST);
        writeSetupParameter(request, "video_resolution", configuredResolution, "/etc/video/resolution", 16, DEFAULT_VIDEO_RESOLUTION);
        writeSetupParameter(request, "video_mode", videoMode, "/etc/video/mode", 16, DEFAULT_VIDEO_MODE);
        writeSetupParameter(request, "reset_mode", resetMode, "/etc/reset/mode", 16, DEFAULT_RESET_MODE);
        writeSetupParameter(request, "deinterlace_mode", deinterlaceMode480i, "/etc/deinterlace/mode/480i", 16, DEFAULT_DEINTERLACE_MODE);
        writeSetupParameter(request, "deinterlace_mode", deinterlaceMode576i, "/etc/deinterlace/mode/576i", 16, DEFAULT_DEINTERLACE_MODE);
        writeSetupParameter(request, "protected_mode", protectedMode, "/etc/protected/mode", 8, DEFAULT_PROTECTED_MODE);
        writeSetupParameter(request, "keyboard_layout", keyboardLayout, "/etc/keyblayout", 8, DEFAULT_KEYBOARD_LAYOUT);
        readCurrentProtectedMode(true);

        request->send(200, "text/plain", "OK\n");
    });

    server.on("/config", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncJsonResponse * response = new AsyncJsonResponse();
        JsonObject& root = response->getRoot();

        root["ssid"] = ssid;
        root["password"] = password;
        root["ota_pass"] = otaPassword;
        root["firmware_server"] = firmwareServer;
        root["firmware_server_path"] = firmwareServerPath;
        root["firmware_version"] = firmwareVersion;
        root["http_auth_user"] = httpAuthUser;
        root["http_auth_pass"] = httpAuthPass;
        root["flash_chip_size"] = ESP.getFlashChipSize();
        root["conf_ip_addr"] = confIPAddr;
        root["conf_ip_gateway"] = confIPGateway;
        root["conf_ip_mask"] = confIPMask;
        root["conf_ip_dns"] = confIPDNS;
        root["hostname"] = host;
        root["fw_version"] = isRelaxedFirmware ? FW_VERSION "-rlx" : FW_VERSION "-std";
        root["video_resolution"] = configuredResolution;
        root["video_mode"] = videoMode;
        root["reset_mode"] = resetMode;
        root["deinterlace_mode"] = deinterlaceMode480i;
        root["protected_mode"] = protectedMode;
        root["keyboard_layout"] = keyboardLayout;

        response->setLength();
        request->send(response);
    });

    server.on("/reset/esp", HTTP_ANY, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        //ESP.eraseConfig();
        ESP.restart();
    });

    server.on("/test", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
    });

    server.on("/osdwrite", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *column = request->getParam("column", true);
        AsyncWebParameter *row = request->getParam("row", true);
        AsyncWebParameter *text = request->getParam("text", true);

        fpgaTask.DoWriteToOSD(atoi(column->value().c_str()), atoi(row->value().c_str()), (uint8_t*) text->value().c_str());
        request->send(200);
    });

    server.on("/240p_offset", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *offset = request->getParam("offset", true);
        fpgaTask.Write(I2C_240P_OFFSET, atoi(offset->value().c_str()), NULL);
        request->send(200);
    });

    server.on("/scanlines", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *s_intensity = request->getParam("intensity", true);
        AsyncWebParameter *s_thickness = request->getParam("thickness", true);
        AsyncWebParameter *s_oddeven = request->getParam("oddeven", true);
        AsyncWebParameter *s_active = request->getParam("active", true);

        scanlinesIntensity = atoi(s_intensity->value().c_str());
        scanlinesThickness = atoi(s_thickness->value().c_str());
        scanlinesOddeven = atoi(s_oddeven->value().c_str());
        scanlinesActive = atoi(s_active->value().c_str());

        uint8_t upper = getScanlinesUpperPart();
        uint8_t lower = getScanlinesLowerPart();

        setScanlines(upper, lower, NULL);
        request->send(200);
    });

    server.on("/osd/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        openOSD();
        request->send(200);
    });

    server.on("/osd/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        closeOSD();
        request->send(200);
    });

    server.on("/hq2x/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_UPSCALING_MODE, 0x01, NULL);
        request->send(200);
    });

    server.on("/hq2x/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_UPSCALING_MODE, 0x00, NULL);
        request->send(200);
    });

    server.on("/res/VGA", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_VGA);
        request->send(200);
    });

    server.on("/res/480p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_480p);
        request->send(200);
    });

    server.on("/res/960p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_960p);
        request->send(200);
    });

    server.on("/res/1080p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_1080p);
        request->send(200);
    });

    server.on("/deinterlace/bob", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        CurrentDeinterlaceMode480i = DEINTERLACE_MODE_BOB;
        CurrentDeinterlaceMode576i = DEINTERLACE_MODE_BOB;
        switchResolution(CurrentResolution);
        request->send(200);
    });

    server.on("/deinterlace/passthru", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        CurrentDeinterlaceMode480i = DEINTERLACE_MODE_PASSTHRU;
        CurrentDeinterlaceMode576i = DEINTERLACE_MODE_PASSTHRU;
        switchResolution(CurrentResolution);
        request->send(200);
    });

    server.on("/generate/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_VIDEO_GEN, GENERATE_TIMING_AND_VIDEO, NULL);
        request->send(200);
    });

    server.on("/generate/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_VIDEO_GEN, 0, NULL);
        request->send(200);
    });

    server.on("/spi/flash/erase", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        taskManager.StartTask(&flashEraseTask);
        request->send(200);
    });

    server.on("/clock/config/get", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Read(0xD0, 1, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            char msg[16];
            sprintf(msg, "%u\n", buffer[0]);
            request->send(200, "text/plain", msg);
        });
    });

    server.on("/clock/config/set", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *s_value = request->getParam("value", true);
        fpgaTask.Write(0xD0, atoi(s_value->value().c_str()), NULL);
        request->send(200);
    });

    server.on("/mac/get", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[32];
        sprintf(msg, "%s\n", WiFi.macAddress().c_str());
        request->send(200, "text/plain", msg);
    });

    server.on("/nbp/reset", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_NBP_RESET, 0x01, [](uint8_t Address, uint8_t Value) {
            DEBUG2("nbp reset.\n");
        });
        request->send(200, "text/plain", "OK\n");
    });

    server.on("/testdata2", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[16];
        sprintf(
            msg,
            "%02x %02x %02x %02x %02x\n",
            remapResolution(CurrentResolution),
            mapResolution(CurrentResolution, true),
            CurrentResolutionData,
            CurrentDeinterlaceMode480i,
            CurrentDeinterlaceMode576i
        );
        request->send(200, "text/plain", msg);
    });

    server.on("/testdata", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Read(I2C_TESTDATA_BASE, I2C_TESTDATA_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            if (len == I2C_TESTDATA_LENGTH) {
                char msg[I2C_TESTDATA_LENGTH * 3 + 1] = "";
                int p = 0;
                for (int i = 0 ; i < I2C_TESTDATA_LENGTH ; i++) {
                    sprintf((char*) &msg[p], "%02x ", buffer[i]);
                    p = p + 3;
                }
                sprintf((char*) &msg[p], "\n");
                request->send(200, "text/plain", msg);

                // request->send("text/plain", I2C_TESTDATA_LENGTH * 3 + 1, [ buffer ](uint8_t *buffer_out, size_t maxLen, size_t index) -> size_t {
                //     return I2C_TESTDATA_LENGTH * 3 + 1;
                // });
            } else {
                request->send(200, "text/plain", "SOMETHING_IS_WRONG\n");
            }
        });
        fpgaTask.ForceLoop();
    });

    AsyncStaticWebHandler* handler = &server
        .serveStatic("/", SPIFFS, "/")
        .setDefaultFile("index.html");
    // set authentication by configured user/pass later
    handler->setAuthentication(httpAuthUser, httpAuthPass);

    server.onNotFound([](AsyncWebServerRequest *request){
        if (request->url().endsWith("md5")) {
           request->send(200, "text/plain", DEFAULT_MD5_SUM"\n");
           return;
        }
        request->send(404);
    });

    server.begin();
}

void setupArduinoOTA() {
    DEBUG2(">> Setting up ArduinoOTA...\n");

    ArduinoOTA.setPort(8266);
    ArduinoOTA.setHostname(host);
    ArduinoOTA.setPassword(otaPassword);

    ArduinoOTA.onStart([]() {
        DEBUG("ArduinoOTA >> Start\n");
    });
    ArduinoOTA.onEnd([]() {
        DEBUG("\nArduinoOTA >> End\n");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        DEBUG("ArduinoOTA >> Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        DEBUG("ArduinoOTA >> Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR) {
            DEBUG("ArduinoOTA >> Auth Failed\n");
        } else if (error == OTA_BEGIN_ERROR) {
            DEBUG("ArduinoOTA >> Begin Failed\n");
        } else if (error == OTA_CONNECT_ERROR) {
            DEBUG("ArduinoOTA >> Connect Failed\n");
        } else if (error == OTA_RECEIVE_ERROR) {
            DEBUG("ArduinoOTA >> Receive Failed\n");
        } else if (error == OTA_END_ERROR) {
            DEBUG("ArduinoOTA >> End Failed\n");
        }
    });
    ArduinoOTA.begin(true);
    DEBUG2(">> ArduinoOTA started.\n");
}

void waitForController() {
    bool gotValidPacket = false;
    uint8_t _ForceVGA = ForceVGA;
    DEBUG2(">> Checking video mode controller override...\n");

    for (int i = 0 ; i < 3333 ; i++) {
        // stop, if we got a valid packet
        if (gotValidPacket) {
            DEBUG2("   found valid controller packet at %i\n", i);
            if (_ForceVGA != ForceVGA) {
                ForceVGA = _ForceVGA;
                writeVideoMode();
                DEBUG2("   performing a resetall\n");
                resetall();
            } else {
                switchResolution();
                fpgaTask.ForceLoop();
                DEBUG2("   video mode NOT changed: %u\n", ForceVGA);
            }
            return;
        }
        fpgaTask.Read(I2C_CONTROLLER_AND_DATA_BASE, I2C_CONTROLLER_AND_DATA_BASE_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            if (len == I2C_CONTROLLER_AND_DATA_BASE_LENGTH) {
                uint16_t cdata = (buffer[0] << 8 | buffer[1]);
                uint8_t metadata = buffer[2];
                if (CHECK_BIT(cdata, CTRLR_DATA_VALID)) {
                    isRelaxedFirmware = metadata & HQ2X_MODE_FLAG;
                    storeResolutionData(metadata);
                    DEBUG2("   %i: %04x %02x\n", i, cdata, metadata);
                    if (CHECK_BIT(cdata, CTRLR_PAD_UP)) {
                        _ForceVGA = VGA_ON;
                    } else if (CHECK_BIT(cdata, CTRLR_PAD_DOWN)) {
                        _ForceVGA = VGA_OFF;
                    }
                    gotValidPacket = true;
                }
            }
        });
        fpgaTask.ForceLoop();
        delay(1);
    }
    DEBUG2("no valid controller packet found within timeout\n");
}

void doReflash() {
    disableFPGA();
    if (flashTask.doStart()) {
        // [](int read, int total, bool done, int error) {
        // }
        DEBUG2("   firmware flashing started.\n");
        while (!flashTask.doUpdate()) {
            yield();
        }
        flashTask.doStop();
        DEBUG2("   firmware flashing done.\n");
        resetall();
    }
}

void printSerialMenu() {
    DEBUG2("- Menu -----------------------\n");
    DEBUG2("f: re-flash fpga firmware\n");
    DEBUG2("i: show info\n");
    DEBUG2("r: reset visible area counters\n");
    DEBUG2("p: reset PLL\n");
    DEBUG2("t: show visible area counters\n");
    DEBUG2("o: activate OTA update\n");
    DEBUG2("w: print wifi rssi information\n");
    DEBUG2("h: print this menu\n");
    DEBUG2("------------------------------\n");
}

void setup(void) {
    DBG_OUTPUT_PORT.begin(115200);
    DEBUG2("\n>> ESP starting... " DCHDMI_VERSION "\n");
    DEBUG2(">> %s\n", ESP.getFullVersion().c_str());
    DBG_OUTPUT_PORT.setDebugOutput(false);

    pinMode(NCE, INPUT);
    pinMode(NCONFIG, INPUT);

    setupI2C();
    setupSPIFFS();
    setupResetMode();
    setupOutputResolution();
    setupScanlines();
    setupOffsets();
    setupUpscalingMode();
    setupColorSpace();
    setupTaskManager();
    setupCredentials();
    waitForController();
    fpgaTask.Write(I2C_ACTIVATE_HDMI, 1, NULL); fpgaTask.ForceLoop();
    setupWiFi();

    setOSD(false, NULL); fpgaTask.ForceLoop();
    char buff[MENU_WIDTH+1]; osd_get_resolution(buff);
    fpgaTask.DoWriteToOSD(0, MENU_WIDTH, (uint8_t*) buff); fpgaTask.ForceLoop();

    if (!inInitialSetupMode) {
        // skip MDNS setup, because it can cause random crashes on startup
        //setupMDNS();
    }

    if (reflashNeccessary && reflashNeccessary2 && reflashNeccessary3) {
        DEBUG2("FPGA firmware missing or broken, reflash needed.\n");
        doReflash();
    }
    setupHTTPServer();
    DEBUG2(">> httpAuthUser: %s\n", httpAuthUser);
    DEBUG2(">> httpAuthPass: %s\n", httpAuthPass);
    DEBUG2(">> Ready.\n");
    printSerialMenu();
}

void showInfo() {
    DEBUG2("ESP: " DCHDMI_VERSION "\n");
    DEBUG2("Arduino ESP version: %s\n", ESP.getFullVersion().c_str());
    DEBUG2("Free sketch space: %u\n", ESP.getFreeSketchSpace());
    DEBUG2("Max sketch space: %u\n", (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
    DEBUG2("Flash chip size: %u\n", ESP.getFlashChipSize());
    DEBUG2("Free heap size: %u\n\n", ESP.getFreeHeap());
}

int getWiFiQuality(int dBm) {
  if (WiFi.status() != WL_CONNECTED)
    return -1;
  if (dBm <= -100)
    return 0;
  if (dBm >= -50)
    return 100;
  return 2 * (dBm + 100);
}

void loop(void){
    ArduinoOTA.handle();
    taskManager.Loop();
    if (Serial.available() > 0) {
        int incomingByte = Serial.read();
        if (incomingByte == 'f') {
            doReflash();
        } else if (incomingByte == 'i') {
            showInfo();
        } else if (incomingByte == 'h') {
            printSerialMenu();
        } else if (incomingByte == 'p') {
            fpgaTask.Write(I2C_PLL_RESET, 0, [](uint8_t Address, uint8_t Value) {
                DEBUG2("pll reset.\n");
            });
        } else if (incomingByte == 'r') {
            fpgaTask.Write(I2C_NBP_RESET, 0, [](uint8_t Address, uint8_t Value) {
                DEBUG2("nbp reset.\n");
            });
        } else if (incomingByte == 't') {
            fpgaTask.Read(I2C_TESTDATA_BASE, I2C_TESTDATA_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
                int nbp1 = (buffer[35] << 4) | (buffer[36] >> 4);
                int nbp2 = ((buffer[36] & 0xF) << 8) | buffer[37];
                DEBUG2("nbp: %02x %02x %02x %dx%d\n", buffer[35], buffer[36], buffer[37], nbp1, nbp2);
            });
        } else if (incomingByte == 'o') {
            if (strlen(otaPassword)) {
                setupArduinoOTA();
            } else {
                DEBUG2("Please set an OTA password via web interface first!\n");
            }
        } else if (incomingByte == 'w') {
            int dBm = WiFi.RSSI();
            DEBUG2("RSSI: %d dBm, quality: %d%%, channel: %d\n", dBm, getWiFiQuality(dBm), WiFi.channel());
        }
    }
}

//////////////////////////////////////////////////////////////////////////////////
/*
    Dreamcast Companion App
*/
#include "global.h"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <FS.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <SPIFlash.h>
#include "AsyncJson.h"
#include "ArduinoJson.h"
#include <Task.h>
#include "task/FlashTask.h"
#include "task/FlashVerifyTask.h"
#include "task/FlashESPTask.h"
#include "task/FlashESPIndexTask.h"
#include "task/FPGATask.h"
#include "task/DebugTask.h"
#include "task/TimeoutTask.h"
#include "task/FlashCheckTask.h"
#include "task/FlashEraseTask.h"
#include "task/InfoTask.h"
#include "util.h"
#include "data.h"
#include "web.h"
#include "Menu.h"
#include "pwgen.h"

//////////////////////////////////////////////////////////////////////////////////

bool isHhttpAuthPassGenerated = false;
bool isRelaxedFirmware = false;

char ssid[64] = DEFAULT_SSID;
char password[64] = DEFAULT_PASSWORD;
char otaPassword[64] = DEFAULT_OTA_PASSWORD;
char firmwareServer[256] = DEFAULT_FW_SERVER;
char firmwareServerPath[256] = DEFAULT_FW_SERVER_PATH;
char firmwareVersion[64] = DEFAULT_FW_VERSION;
char firmwareVariant[64] = DEFAULT_FW_VARIANT;
char httpAuthUser[64] = DEFAULT_HTTP_USER;
char httpAuthPass[64] = "";
char confIPAddr[24] = DEFAULT_CONF_IP_ADDR;
char confIPGateway[24] = DEFAULT_CONF_IP_GATEWAY;
char confIPMask[24] = DEFAULT_CONF_IP_MASK;
char confIPDNS[24] = DEFAULT_CONF_IP_DNS;
char host[64] = DEFAULT_HOST;
char videoMode[16] = "";
char configuredResolution[16] = "";
char resetMode[16] = "";
char deinterlaceMode480i[16] = "";
char deinterlaceMode576i[16] = "";
char protectedMode[8] = "";
char AP_NameChar[64];
char WiFiAPPSK[12] = "";
char keyboardLayout[8] = DEFAULT_KEYBOARD_LAYOUT;
IPAddress ipAddress( 192, 168, 4, 1 );
bool inInitialSetupMode = false;
AsyncWebServer server(80);
SPIFlash flash(CS);
int last_error = NO_ERROR;
int totalLength;
int readLength;
bool currentJobDone = true;

File flashFile;

uint8_t CurrentResolution = RESOLUTION_1080p;
uint8_t PrevCurrentResolution;
uint8_t CurrentResolutionData = 0;
uint8_t ForceVGA = VGA_ON;
uint8_t CurrentResetMode = RESET_MODE_LED;
uint8_t CurrentDeinterlaceMode480i = DEINTERLACE_MODE_BOB;
uint8_t CurrentDeinterlaceMode576i = DEINTERLACE_MODE_BOB;
uint8_t CurrentProtectedMode = PROTECTED_MODE_OFF;
int8_t Offset240p;
int8_t OffsetVGA;
int8_t AutoOffsetVGA = 0;
uint8_t UpscalingMode;
uint8_t ColorSpace;

char md5FPGA[48];
char md5ESP[48];
char md5IndexHtml[48];

bool scanlinesActive;
int scanlinesIntensity;
bool scanlinesOddeven;
bool scanlinesThickness;

bool reflashNeccessary;
bool reflashNeccessary2;
bool reflashNeccessary3;

MD5Builder md5;
TaskManager taskManager;
FlashTask flashTask(1);
FlashESPTask flashESPTask(1);
FlashESPIndexTask flashESPIndexTask(1);
DebugTask debugTask(16);
TimeoutTask timeoutTask(MsToTaskTime(100));
FlashCheckTask flashCheckTask(1, NULL);
FlashVerifyTask flashVerifyTask(1);
FlashEraseTask flashEraseTask(1);
InfoTask infoTask(16);

extern Menu mainMenu;
Menu *currentMenu;
Menu *previousMenu;

//////////////////////////////////////////////////////////////////////////////////

void setupSPIFFS() {
    DEBUG2(">> Setting up SPIFFS...\n");
    if (!SPIFFS.begin()) {
        DEBUG(">> SPIFFS begin failed, trying to format...");
        if (SPIFFS.format()) {
            DEBUG("done.\n");
        } else {
            DEBUG("error.\n");
        }
    }
}

void setupResetMode() {
    readCurrentResetMode();
    DEBUG2(">> Setting up reset mode: %x\n", CurrentResetMode);
    reflashNeccessary3 = !forceI2CWrite(
        I2C_RESET_CONF, CurrentResetMode,
        I2C_PING, 0
    );
}

void setupOutputResolution() {
    readVideoMode();
    readCurrentResolution();
    readCurrentDeinterlaceMode480i();
    readCurrentDeinterlaceMode576i();

    DEBUG2(">> Setting up output resolution: %x\n", ForceVGA | CurrentResolution);
    reflashNeccessary = !forceI2CWrite(
        I2C_OUTPUT_RESOLUTION, ForceVGA | mapResolution(CurrentResolution),
        //ForceVGA ? I2C_DC_RESET : I2C_PING, 0
        I2C_DC_RESET, 0
    );
}

void setupScanlines() {
    readScanlinesActive();
    readScanlinesIntensity();
    readScanlinesOddeven();
    readScanlinesThickness();

    uint8_t upper = getScanlinesUpperPart();
    uint8_t lower = getScanlinesLowerPart();

    DEBUG2(">> Setting up scanlines:\n");
    reflashNeccessary2 = !forceI2CWrite(
        I2C_SCANLINE_UPPER, upper,
        I2C_SCANLINE_LOWER, lower
    );
}

void setupOffsets() {
    read240pOffset();
    readVGAOffset();
    forceI2CWrite(I2C_240P_OFFSET, Offset240p, I2C_240P_OFFSET, Offset240p);
    forceI2CWrite(I2C_VGA_OFFSET, getEffectiveOffsetVGA(), I2C_VGA_OFFSET, getEffectiveOffsetVGA());
}

void setupUpscalingMode() {
    readUpscalingMode();
    forceI2CWrite(
        I2C_UPSCALING_MODE, UpscalingMode,
        I2C_UPSCALING_MODE, UpscalingMode
    );
}

void setupColorSpace() {
    readColorSpace();
    forceI2CWrite(
        I2C_COLOR_SPACE, ColorSpace,
        I2C_COLOR_SPACE, ColorSpace
    );
}

void setupTaskManager() {
    DEBUG2(">> Setting up task manager...\n");
    taskManager.Setup();
    taskManager.StartTask(&fpgaTask);
}

void setupCredentials(void) {
    DEBUG2(">> Reading stored values...\n");

    _readFile("/etc/ssid", ssid, 64, DEFAULT_SSID);
    _readFile("/etc/password", password, 64, DEFAULT_PASSWORD);
    _readFile("/etc/ota_pass", otaPassword, 64, DEFAULT_OTA_PASSWORD);
    _readFile("/etc/firmware_server", firmwareServer, 256, DEFAULT_FW_SERVER);
    _readFile("/etc/firmware_server_path", firmwareServerPath, 256, DEFAULT_FW_SERVER_PATH);
    _readFile("/etc/firmware_variant", firmwareVariant, 64, DEFAULT_FW_VARIANT);
    _readFile("/etc/firmware_version", firmwareVersion, 64, DEFAULT_FW_VERSION);
    _readFile("/etc/http_auth_user", httpAuthUser, 64, DEFAULT_HTTP_USER);
    _readFile("/etc/http_auth_pass", httpAuthPass, 64, DEFAULT_HTTP_PASS);
    _readFile("/etc/conf_ip_addr", confIPAddr, 24, DEFAULT_CONF_IP_ADDR);
    _readFile("/etc/conf_ip_gateway", confIPGateway, 24, DEFAULT_CONF_IP_GATEWAY);
    _readFile("/etc/conf_ip_mask", confIPMask, 24, DEFAULT_CONF_IP_MASK);
    _readFile("/etc/conf_ip_dns", confIPDNS, 24, DEFAULT_CONF_IP_DNS);
    _readFile("/etc/hostname", host, 64, DEFAULT_HOST);
    _readFile("/etc/keyblayout", keyboardLayout, 8, DEFAULT_KEYBOARD_LAYOUT);
    readCurrentProtectedMode();

    if (strlen(httpAuthPass) == 0) {
        generate_password(httpAuthPass);
        isHhttpAuthPassGenerated = true;
    }
}

void generateWiFiPassword() {
    generate_password(WiFiAPPSK);
    DEBUG2("AP password: %s\n", WiFiAPPSK);
}

void setupAPMode(void) {
    WiFi.mode(WIFI_AP);
    uint8_t mac[WL_MAC_ADDR_LENGTH];
    WiFi.softAPmacAddress(mac);
    String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
    String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
    macID.toUpperCase();
    String AP_NameString = String("DCHDMI") + String("-") + macID;

    memset(AP_NameChar, 0, AP_NameString.length() + 1);

    for (uint i=0; i<AP_NameString.length(); i++) {
        if (i < 63) {
            AP_NameChar[i] = AP_NameString.charAt(i);
        }
    }

    DEBUG2("AP_NameChar: %s\n", AP_NameChar);
    generateWiFiPassword();
    WiFi.softAP(AP_NameChar, WiFiAPPSK);
    DEBUG2(">> SSID:   %s\n", AP_NameChar);
    DEBUG2(">> AP-PSK: %s\n", WiFiAPPSK);
    inInitialSetupMode = true;
}

void setupWiFi() {
    WiFi.persistent(false);
    if (strlen(ssid) == 0) {
        DEBUG2(">> No ssid, starting AP mode...\n");
        setupAPMode();
    } else {
        DEBUG2(">> Trying to connect in client mode first...\n");
        setupWiFiStation();
    }
}

void setupWiFiStation() {
    bool doStaticIpConfig = false;
    IPAddress ipAddr;
    doStaticIpConfig = ipAddr.fromString(confIPAddr);
    IPAddress ipGateway;
    doStaticIpConfig = doStaticIpConfig && ipGateway.fromString(confIPGateway);
    IPAddress ipMask;
    doStaticIpConfig = doStaticIpConfig && ipMask.fromString(confIPMask);
    IPAddress ipDNS;
    doStaticIpConfig = doStaticIpConfig && ipDNS.fromString(confIPDNS);

    //WIFI INIT
    WiFi.mode(WIFI_STA);
    WiFi.begin();
    WiFi.disconnect(true);
    WiFi.softAPdisconnect(true);
    // WiFi.setAutoConnect(true);
    // WiFi.setAutoReconnect(true);

    DEBUG(">> Do static ip configuration: %i\n", doStaticIpConfig);
    if (doStaticIpConfig) {
        WiFi.config(ipAddr, ipGateway, ipMask, ipDNS);
    }

    DEBUG(">> WiFi.getAutoConnect: %i\n", WiFi.getAutoConnect());
    DEBUG(">> Connecting to %s\n", ssid);

    if (String(WiFi.SSID()) != String(ssid)) {
        WiFi.begin(ssid, password);
        DEBUG(">> WiFi.begin: %s@%s\n", password, ssid);
    }

    bool success = true;
    int tries = 0;
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        DBG_OUTPUT_PORT.print(".");
        if (tries == 60) {
            WiFi.disconnect();
            success = false;
            break;
        }
        tries++;
    }

    DEBUG2(">> success: %i\n", success);

    if (!success) {
        // setup AP mode to configure ssid and password
        setupAPMode();
    } else {
        WiFi.hostname(host);
        WiFi.setAutoReconnect(true);

        ipAddress = WiFi.localIP();
        IPAddress gateway = WiFi.gatewayIP();
        IPAddress subnet = WiFi.subnetMask();

        DEBUG2(
            ">> Connected!\n   IP address:      %d.%d.%d.%d\n",
            ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]
        );
        DEBUG2(
            "   Gateway address: %d.%d.%d.%d\n",
            gateway[0], gateway[1], gateway[2], gateway[3]
        );
        DEBUG2(
            "   Subnet mask:     %d.%d.%d.%d\n",
            subnet[0], subnet[1], subnet[2], subnet[3]
        );
        DEBUG2(
            "   Hostname:        %s\n",
            WiFi.hostname().c_str()
        );
        DEBUG2(
            "   MAC addr:        %s\n",
            WiFi.macAddress().c_str()
        );
    }
}

void setupMDNS() {
    DEBUG2(">> Setting up mDNS...\n");
    _writeFile("/tmp/checkpoint", "invalid", 16);
    if (MDNS.begin(host, ipAddress)) {
        DEBUG2(">> mDNS started.\n");
        MDNS.addService("http", "tcp", 80);
        DEBUG(
            ">> http://%s.local/\n",
            host
        );
        SPIFFS.remove("/tmp/checkpoint");
    } else {
        DEBUG2(">> mDNS setup failed.\n");
    }
}

void setupHTTPServer() {
    DEBUG2(">> Setting up HTTP server...\n");

    server.on("/upload/fpga", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, FIRMWARE_FILE, index, data, len, final);
    });

    server.on("/upload/esp", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, ESP_FIRMWARE_FILE, index, data, len, final);
    });

    server.on("/upload/index", HTTP_POST, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200);
    }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
        handleUpload(request, ESP_INDEX_STAGING_FILE, index, data, len, final);
    });

    server.on("/debug", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[64];
        _readFile("/debug", msg, 64, "---");
        request->send(200, "text/plain", msg);
    });

    server.on("/list-files", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncJsonResponse * response = new AsyncJsonResponse();
        response->addHeader("Server","DCHDMI");
        JsonObject& root = response->getRoot();
        FSInfo fs_info;
        SPIFFS.info(fs_info);

        root["totalBytes"] = fs_info.totalBytes;
        root["usedBytes"] = fs_info.usedBytes;
        // root["blockSize"] = fs_info.blockSize;
        // root["pageSize"] = fs_info.pageSize;
        // root["maxOpenFiles"] = fs_info.maxOpenFiles;
        // root["maxPathLength"] = fs_info.maxPathLength;
        // root["freeSketchSpace"] = ESP.getFreeSketchSpace();
        // root["maxSketchSpace"] = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
        // root["flashChipSize"] = ESP.getFlashChipSize();
        // root["freeHeapSize"] = ESP.getFreeHeap();

        JsonArray &datas = root.createNestedArray("files");

        Dir dir = SPIFFS.openDir("/");
        while (dir.next()) {
            JsonObject &data = datas.createNestedObject();
            data["name"] = dir.fileName();
            data["size"] = dir.fileSize();
        }

        response->setLength();
        request->send(response);
    });

    server.on("/download/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleFPGADownload(request);
    });

    server.on("/download/esp", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPDownload(request);
    });

    server.on("/download/index", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPIndexDownload(request);
    });

    server.on("/flash/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleFlash(request, FIRMWARE_FILE);
    });

    server.on("/flash/esp", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPFlash(request, ESP_FIRMWARE_FILE);
    });

    server.on("/flash/index", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        handleESPIndexFlash(request);
    });

    server.on("/cleanupindex", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove(ESP_INDEX_FILE);
        SPIFFS.remove(String(ESP_INDEX_FILE) + ".md5");
        request->send(200);
    });

    server.on("/cleanup", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove(FIRMWARE_FILE);
        SPIFFS.remove(ESP_FIRMWARE_FILE);
        SPIFFS.remove(ESP_INDEX_STAGING_FILE);
        SPIFFS.remove(String(FIRMWARE_FILE) + ".md5");
        SPIFFS.remove(String(ESP_FIRMWARE_FILE) + ".md5");
        SPIFFS.remove(String(ESP_INDEX_STAGING_FILE) + ".md5");

        SPIFFS.remove(LOCAL_FPGA_MD5);
        SPIFFS.remove(LOCAL_ESP_MD5);
        SPIFFS.remove(LOCAL_ESP_INDEX_MD5);

        SPIFFS.remove(SERVER_FPGA_MD5);
        SPIFFS.remove(SERVER_ESP_MD5);
        SPIFFS.remove(SERVER_ESP_INDEX_MD5);

        // remove legacy config data
        SPIFFS.remove("/etc/firmware_fpga");
        SPIFFS.remove("/etc/firmware_format");
        SPIFFS.remove("/etc/force_vga");
        SPIFFS.remove("/etc/resolution");
        request->send(200);
    });

    server.on("/resetconfig", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.remove("/etc/ssid");
        SPIFFS.remove("/etc/password");
        SPIFFS.remove("/etc/ota_pass");
        SPIFFS.remove("/etc/http_auth_user");
        SPIFFS.remove("/etc/http_auth_pass");
        SPIFFS.remove("/etc/conf_ip_addr");
        SPIFFS.remove("/etc/conf_ip_gateway");
        SPIFFS.remove("/etc/conf_ip_mask");
        SPIFFS.remove("/etc/conf_ip_dns");
        SPIFFS.remove("/etc/hostname");
        SPIFFS.remove("/etc/keyblayout");

        ssid[0] = '\0';
        password[0] = '\0';
        otaPassword[0] = '\0';
        keyboardLayout[0] = '\0';
        // keep passwords alive until power off
        //httpAuthUser[0] = '\0';
        //httpAuthPass[0] = '\0';
        confIPAddr[0] = '\0';
        confIPGateway[0] = '\0';
        confIPMask[0] = '\0';
        confIPDNS[0] = '\0';
        host[0] = '\0';

        request->send(200);
    });

    server.on("/factoryresetall", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        SPIFFS.format();
        request->send(200);
    });

   server.on("/flash/secure/fpga", HTTP_GET, [](AsyncWebServerRequest *request){
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        disableFPGA();
        handleFlash(request, FIRMWARE_FILE);
    });

    server.on("/progress", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("progress requested...\n");
        char msg[64];
        if (last_error) {
            sprintf(msg, "ERROR %i\n", last_error);
            request->send(200, "text/plain", msg);
            DEBUG("...delivered: %s (%i).\n", msg, last_error);
            // clear last_error
            last_error = NO_ERROR;
        } else {
            int progress = totalLength <= 0 ? 0 : (int)(readLength * 100 / totalLength);
            if (progress == 100 && !currentJobDone) {
                progress = 99;
            }
            sprintf(msg, "%i\n", progress);
            request->send(200, "text/plain", msg);
            DEBUG2("...delivered: %s.\n", msg);
        }
    });

    server.on("/flash_size", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[64];
        sprintf(msg, "%lu\n", (long unsigned int) ESP.getFlashChipSize());
        request->send(200, "text/plain", msg);
    });

    server.on("/reset/fpga", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("FPGA reset requested...\n");
        fpgaTask.DoResetFPGA();
        request->send(200, "text/plain", "OK\n");
        DEBUG("...delivered.\n");
    });

    server.on("/reset/dc", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        DEBUG("DC reset requested...\n");
        fpgaTask.Write(I2C_DC_RESET, 0, NULL);
        request->send(200, "text/plain", "OK\n");
        DEBUG("...delivered.\n");
    });

    server.on("/reset/all", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        resetall();
    });

    server.on("/reset/pll", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_PLL_RESET, 0, NULL);
        request->send(200, "text/plain", "OK\n");
    });

    server.on("/issetupmode", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        request->send(200, "text/plain", inInitialSetupMode ? "true\n" : "false\n");
    });

    server.on("/ping", HTTP_GET, [](AsyncWebServerRequest *request) {
        request->send(200);
    });

    server.on("/setup", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        writeSetupParameter(request, "ssid", ssid, 64, DEFAULT_SSID);
        writeSetupParameter(request, "password", password, 64, DEFAULT_PASSWORD);
        writeSetupParameter(request, "ota_pass", otaPassword, 64, DEFAULT_OTA_PASSWORD);
        writeSetupParameter(request, "firmware_server", firmwareServer, 256, DEFAULT_FW_SERVER);
        writeSetupParameter(request, "firmware_server_path", firmwareServerPath, 256, DEFAULT_FW_SERVER_PATH);
        writeSetupParameter(request, "firmware_version", firmwareVersion, 64, DEFAULT_FW_VERSION);
        writeSetupParameter(request, "http_auth_user", httpAuthUser, 64, DEFAULT_HTTP_USER, true);
        writeSetupParameter(request, "http_auth_pass", httpAuthPass, 64, DEFAULT_HTTP_PASS, true);
        writeSetupParameter(request, "conf_ip_addr", confIPAddr, 24, DEFAULT_CONF_IP_ADDR);
        writeSetupParameter(request, "conf_ip_gateway", confIPGateway, 24, DEFAULT_CONF_IP_GATEWAY);
        writeSetupParameter(request, "conf_ip_mask", confIPMask, 24, DEFAULT_CONF_IP_MASK);
        writeSetupParameter(request, "conf_ip_dns", confIPDNS, 24, DEFAULT_CONF_IP_DNS);
        writeSetupParameter(request, "hostname", host, 64, DEFAULT_HOST);
        writeSetupParameter(request, "video_resolution", configuredResolution, "/etc/video/resolution", 16, DEFAULT_VIDEO_RESOLUTION);
        writeSetupParameter(request, "video_mode", videoMode, "/etc/video/mode", 16, DEFAULT_VIDEO_MODE);
        writeSetupParameter(request, "reset_mode", resetMode, "/etc/reset/mode", 16, DEFAULT_RESET_MODE);
        writeSetupParameter(request, "deinterlace_mode", deinterlaceMode480i, "/etc/deinterlace/mode/480i", 16, DEFAULT_DEINTERLACE_MODE);
        writeSetupParameter(request, "deinterlace_mode", deinterlaceMode576i, "/etc/deinterlace/mode/576i", 16, DEFAULT_DEINTERLACE_MODE);
        writeSetupParameter(request, "protected_mode", protectedMode, "/etc/protected/mode", 8, DEFAULT_PROTECTED_MODE);
        writeSetupParameter(request, "keyboard_layout", keyboardLayout, "/etc/keyblayout", 8, DEFAULT_KEYBOARD_LAYOUT);
        readCurrentProtectedMode(true);

        request->send(200, "text/plain", "OK\n");
    });

    server.on("/config", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncJsonResponse * response = new AsyncJsonResponse();
        JsonObject& root = response->getRoot();

        root["ssid"] = ssid;
        root["password"] = password;
        root["ota_pass"] = otaPassword;
        root["firmware_server"] = firmwareServer;
        root["firmware_server_path"] = firmwareServerPath;
        root["firmware_version"] = firmwareVersion;
        root["http_auth_user"] = httpAuthUser;
        root["http_auth_pass"] = httpAuthPass;
        root["flash_chip_size"] = ESP.getFlashChipSize();
        root["conf_ip_addr"] = confIPAddr;
        root["conf_ip_gateway"] = confIPGateway;
        root["conf_ip_mask"] = confIPMask;
        root["conf_ip_dns"] = confIPDNS;
        root["hostname"] = host;
        root["fw_version"] = isRelaxedFirmware ? FW_VERSION "-rlx" : FW_VERSION "-std";
        root["video_resolution"] = configuredResolution;
        root["video_mode"] = videoMode;
        root["reset_mode"] = resetMode;
        root["deinterlace_mode"] = deinterlaceMode480i;
        root["protected_mode"] = protectedMode;
        root["keyboard_layout"] = keyboardLayout;

        response->setLength();
        request->send(response);
    });

    server.on("/reset/esp", HTTP_ANY, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        //ESP.eraseConfig();
        ESP.restart();
    });

    server.on("/test", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
    });

    server.on("/osdwrite", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *column = request->getParam("column", true);
        AsyncWebParameter *row = request->getParam("row", true);
        AsyncWebParameter *text = request->getParam("text", true);

        fpgaTask.DoWriteToOSD(atoi(column->value().c_str()), atoi(row->value().c_str()), (uint8_t*) text->value().c_str());
        request->send(200);
    });

    server.on("/240p_offset", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *offset = request->getParam("offset", true);
        fpgaTask.Write(I2C_240P_OFFSET, atoi(offset->value().c_str()), NULL);
        request->send(200);
    });

    server.on("/scanlines", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *s_intensity = request->getParam("intensity", true);
        AsyncWebParameter *s_thickness = request->getParam("thickness", true);
        AsyncWebParameter *s_oddeven = request->getParam("oddeven", true);
        AsyncWebParameter *s_active = request->getParam("active", true);

        scanlinesIntensity = atoi(s_intensity->value().c_str());
        scanlinesThickness = atoi(s_thickness->value().c_str());
        scanlinesOddeven = atoi(s_oddeven->value().c_str());
        scanlinesActive = atoi(s_active->value().c_str());

        uint8_t upper = getScanlinesUpperPart();
        uint8_t lower = getScanlinesLowerPart();

        setScanlines(upper, lower, NULL);
        request->send(200);
    });

    server.on("/osd/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        openOSD();
        request->send(200);
    });

    server.on("/osd/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        closeOSD();
        request->send(200);
    });

    server.on("/hq2x/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_UPSCALING_MODE, 0x01, NULL);
        request->send(200);
    });

    server.on("/hq2x/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_UPSCALING_MODE, 0x00, NULL);
        request->send(200);
    });

    server.on("/res/VGA", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_VGA);
        request->send(200);
    });

    server.on("/res/480p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_480p);
        request->send(200);
    });

    server.on("/res/960p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_960p);
        request->send(200);
    });

    server.on("/res/1080p", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        switchResolution(RESOLUTION_1080p);
        request->send(200);
    });

    server.on("/deinterlace/bob", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        CurrentDeinterlaceMode480i = DEINTERLACE_MODE_BOB;
        CurrentDeinterlaceMode576i = DEINTERLACE_MODE_BOB;
        switchResolution(CurrentResolution);
        request->send(200);
    });

    server.on("/deinterlace/passthru", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        CurrentDeinterlaceMode480i = DEINTERLACE_MODE_PASSTHRU;
        CurrentDeinterlaceMode576i = DEINTERLACE_MODE_PASSTHRU;
        switchResolution(CurrentResolution);
        request->send(200);
    });

    server.on("/generate/on", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_VIDEO_GEN, GENERATE_TIMING_AND_VIDEO, NULL);
        request->send(200);
    });

    server.on("/generate/off", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_VIDEO_GEN, 0, NULL);
        request->send(200);
    });

    server.on("/spi/flash/erase", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        taskManager.StartTask(&flashEraseTask);
        request->send(200);
    });

    server.on("/clock/config/get", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Read(0xD0, 1, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            char msg[16];
            sprintf(msg, "%u\n", buffer[0]);
            request->send(200, "text/plain", msg);
        });
    });

    server.on("/clock/config/set", HTTP_POST, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }

        AsyncWebParameter *s_value = request->getParam("value", true);
        fpgaTask.Write(0xD0, atoi(s_value->value().c_str()), NULL);
        request->send(200);
    });

    server.on("/mac/get", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[32];
        sprintf(msg, "%s\n", WiFi.macAddress().c_str());
        request->send(200, "text/plain", msg);
    });

    server.on("/nbp/reset", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Write(I2C_NBP_RESET, 0x01, [](uint8_t Address, uint8_t Value) {
            DEBUG2("nbp reset.\n");
        });
        request->send(200, "text/plain", "OK\n");
    });

    server.on("/testdata2", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        char msg[16];
        sprintf(
            msg,
            "%02x %02x %02x %02x %02x\n",
            remapResolution(CurrentResolution),
            mapResolution(CurrentResolution, true),
            CurrentResolutionData,
            CurrentDeinterlaceMode480i,
            CurrentDeinterlaceMode576i
        );
        request->send(200, "text/plain", msg);
    });

    server.on("/testdata", HTTP_GET, [](AsyncWebServerRequest *request) {
        if(!_isAuthenticated(request)) {
            return request->requestAuthentication();
        }
        fpgaTask.Read(I2C_TESTDATA_BASE, I2C_TESTDATA_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            if (len == I2C_TESTDATA_LENGTH) {
                char msg[I2C_TESTDATA_LENGTH * 3 + 1] = "";
                int p = 0;
                for (int i = 0 ; i < I2C_TESTDATA_LENGTH ; i++) {
                    sprintf((char*) &msg[p], "%02x ", buffer[i]);
                    p = p + 3;
                }
                sprintf((char*) &msg[p], "\n");
                request->send(200, "text/plain", msg);

                // request->send("text/plain", I2C_TESTDATA_LENGTH * 3 + 1, [ buffer ](uint8_t *buffer_out, size_t maxLen, size_t index) -> size_t {
                //     return I2C_TESTDATA_LENGTH * 3 + 1;
                // });
            } else {
                request->send(200, "text/plain", "SOMETHING_IS_WRONG\n");
            }
        });
        fpgaTask.ForceLoop();
    });

    AsyncStaticWebHandler* handler = &server
        .serveStatic("/", SPIFFS, "/")
        .setDefaultFile("index.html");
    // set authentication by configured user/pass later
    handler->setAuthentication(httpAuthUser, httpAuthPass);

    server.onNotFound([](AsyncWebServerRequest *request){
        if (request->url().endsWith("md5")) {
           request->send(200, "text/plain", DEFAULT_MD5_SUM"\n");
           return;
        }
        request->send(404);
    });

    server.begin();
}

void setupArduinoOTA() {
    DEBUG2(">> Setting up ArduinoOTA...\n");

    ArduinoOTA.setPort(8266);
    ArduinoOTA.setHostname(host);
    ArduinoOTA.setPassword(otaPassword);

    ArduinoOTA.onStart([]() {
        DEBUG("ArduinoOTA >> Start\n");
    });
    ArduinoOTA.onEnd([]() {
        DEBUG("\nArduinoOTA >> End\n");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        DEBUG("ArduinoOTA >> Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        DEBUG("ArduinoOTA >> Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR) {
            DEBUG("ArduinoOTA >> Auth Failed\n");
        } else if (error == OTA_BEGIN_ERROR) {
            DEBUG("ArduinoOTA >> Begin Failed\n");
        } else if (error == OTA_CONNECT_ERROR) {
            DEBUG("ArduinoOTA >> Connect Failed\n");
        } else if (error == OTA_RECEIVE_ERROR) {
            DEBUG("ArduinoOTA >> Receive Failed\n");
        } else if (error == OTA_END_ERROR) {
            DEBUG("ArduinoOTA >> End Failed\n");
        }
    });
    ArduinoOTA.begin(true);
    DEBUG2(">> ArduinoOTA started.\n");
}

void waitForController() {
    bool gotValidPacket = false;
    uint8_t _ForceVGA = ForceVGA;
    DEBUG2(">> Checking video mode controller override...\n");

    for (int i = 0 ; i < 3333 ; i++) {
        // stop, if we got a valid packet
        if (gotValidPacket) {
            DEBUG2("   found valid controller packet at %i\n", i);
            if (_ForceVGA != ForceVGA) {
                ForceVGA = _ForceVGA;
                writeVideoMode();
                DEBUG2("   performing a resetall\n");
                resetall();
            } else {
                switchResolution();
                fpgaTask.ForceLoop();
                DEBUG2("   video mode NOT changed: %u\n", ForceVGA);
            }
            return;
        }
        fpgaTask.Read(I2C_CONTROLLER_AND_DATA_BASE, I2C_CONTROLLER_AND_DATA_BASE_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
            if (len == I2C_CONTROLLER_AND_DATA_BASE_LENGTH) {
                uint16_t cdata = (buffer[0] << 8 | buffer[1]);
                uint8_t metadata = buffer[2];
                if (CHECK_BIT(cdata, CTRLR_DATA_VALID)) {
                    isRelaxedFirmware = metadata & HQ2X_MODE_FLAG;
                    storeResolutionData(metadata);
                    DEBUG2("   %i: %04x %02x\n", i, cdata, metadata);
                    if (CHECK_BIT(cdata, CTRLR_PAD_UP)) {
                        _ForceVGA = VGA_ON;
                    } else if (CHECK_BIT(cdata, CTRLR_PAD_DOWN)) {
                        _ForceVGA = VGA_OFF;
                    }
                    gotValidPacket = true;
                }
            }
        });
        fpgaTask.ForceLoop();
        delay(1);
    }
    DEBUG2("no valid controller packet found within timeout\n");
}

void doReflash() {
    disableFPGA();
    if (flashTask.doStart()) {
        // [](int read, int total, bool done, int error) {
        // }
        DEBUG2("   firmware flashing started.\n");
        while (!flashTask.doUpdate()) {
            yield();
        }
        flashTask.doStop();
        DEBUG2("   firmware flashing done.\n");
        resetall();
    }
}

void printSerialMenu() {
    DEBUG2("- Menu -----------------------\n");
    DEBUG2("f: re-flash fpga firmware\n");
    DEBUG2("i: show info\n");
    DEBUG2("r: reset visible area counters\n");
    DEBUG2("p: reset PLL\n");
    DEBUG2("t: show visible area counters\n");
    DEBUG2("o: activate OTA update\n");
    DEBUG2("w: print wifi rssi information\n");
    DEBUG2("h: print this menu\n");
    DEBUG2("------------------------------\n");
}

void setup(void) {
    DBG_OUTPUT_PORT.begin(115200);
    if (SPIFFS.exists("/tmp/checkpoint")) {
        ESP.eraseConfig();
        SPIFFS.remove("/tmp/checkpoint");
        DEBUG2("erased persistent config.\n");
        resetall();
    }
    DEBUG2("\n>> ESP starting... " DCHDMI_VERSION "\n");
    DEBUG2(">> %s\n", ESP.getFullVersion().c_str());
    DBG_OUTPUT_PORT.setDebugOutput(false);

    pinMode(NCE, INPUT);
    pinMode(NCONFIG, INPUT);

    setupI2C();
    setupSPIFFS();
    setupResetMode();
    setupOutputResolution();
    setupScanlines();
    setupOffsets();
    setupUpscalingMode();
    setupColorSpace();
    setupTaskManager();
    setupCredentials();
    waitForController();
    fpgaTask.Write(I2C_ACTIVATE_HDMI, 1, NULL); fpgaTask.ForceLoop();
    setupWiFi();

    setOSD(false, NULL); fpgaTask.ForceLoop();
    char buff[MENU_WIDTH+1]; osd_get_resolution(buff);
    fpgaTask.DoWriteToOSD(0, MENU_WIDTH, (uint8_t*) buff); fpgaTask.ForceLoop();

    if (!inInitialSetupMode) {
        setupMDNS();
    }

    if (reflashNeccessary && reflashNeccessary2 && reflashNeccessary3) {
        DEBUG2("FPGA firmware missing or broken, reflash needed.\n");
        doReflash();
    }
    setupHTTPServer();
    DEBUG2(">> httpAuthUser: %s\n", httpAuthUser);
    DEBUG2(">> httpAuthPass: %s\n", httpAuthPass);
    DEBUG2(">> Ready.\n");
    printSerialMenu();
}

void showInfo() {
    DEBUG2("ESP: " DCHDMI_VERSION "\n");
    DEBUG2("Arduino ESP version: %s\n", ESP.getFullVersion().c_str());
    DEBUG2("Free sketch space: %u\n", ESP.getFreeSketchSpace());
    DEBUG2("Max sketch space: %u\n", (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
    DEBUG2("Flash chip size: %u\n", ESP.getFlashChipSize());
    DEBUG2("Free heap size: %u\n\n", ESP.getFreeHeap());
}

int getWiFiQuality(int dBm) {
  if (WiFi.status() != WL_CONNECTED)
    return -1;
  if (dBm <= -100)
    return 0;
  if (dBm >= -50)
    return 100;
  return 2 * (dBm + 100);
}

void loop(void){
    ArduinoOTA.handle();
    taskManager.Loop();
    if (Serial.available() > 0) {
        int incomingByte = Serial.read();
        if (incomingByte == 'f') {
            doReflash();
        } else if (incomingByte == 'i') {
            showInfo();
        } else if (incomingByte == 'h') {
            printSerialMenu();
        } else if (incomingByte == 'p') {
            fpgaTask.Write(I2C_PLL_RESET, 0, [](uint8_t Address, uint8_t Value) {
                DEBUG2("pll reset.\n");
            });
        } else if (incomingByte == 'r') {
            fpgaTask.Write(I2C_NBP_RESET, 0, [](uint8_t Address, uint8_t Value) {
                DEBUG2("nbp reset.\n");
            });
        } else if (incomingByte == 't') {
            fpgaTask.Read(I2C_TESTDATA_BASE, I2C_TESTDATA_LENGTH, [&](uint8_t address, uint8_t* buffer, uint8_t len) {
                int nbp1 = (buffer[35] << 4) | (buffer[36] >> 4);
                int nbp2 = ((buffer[36] & 0xF) << 8) | buffer[37];
                DEBUG2("nbp: %02x %02x %02x %dx%d\n", buffer[35], buffer[36], buffer[37], nbp1, nbp2);
            });
        } else if (incomingByte == 'o') {
            if (strlen(otaPassword)) {
                setupArduinoOTA();
            } else {
                DEBUG2("Please set an OTA password via web interface first!\n");
            }
        } else if (incomingByte == 'w') {
            int dBm = WiFi.RSSI();
            DEBUG2("RSSI: %d dBm, quality: %d%%, channel: %d\n", dBm, getWiFiQuality(dBm), WiFi.channel());
        }
    }
}


added IR sensor

added IR sensor

int LED = 13; // Use the onboard Uno LED
int isObstaclePin = A0;  // This is our input pin
int isObstacle = HIGH;  // HIGH MEANS NO OBSTACLE

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(isObstaclePin, INPUT);
  Serial.begin(9600);

}

void loop() {
  isObstacle = analogRead(isObstaclePin);
  Serial.println(isObstacle);
  if (isObstacle == LOW)
  {
    Serial.println("OBSTACLE!!, OBSTACLE!!");
    digitalWrite(LED, HIGH);
  }
  else
  {
    Serial.println("clear");
    digitalWrite(LED, LOW);
  }
  delay(200);
}

error: pathspec 'Hello_IR_Sensor/Hello_IR_Sensor.ino' did not match any file(s) known to git


Returned Keypad-MC17-4x4 to original

Returned Keypad-MC17-4x4 to original

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JulianNicholls/Arduino.git/'


working

working

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/nburns/tractor.git/'


Add switchesAndLEDs examples

Add switchesAndLEDs examples

/*******************************************************
Switches and LEDs ParticleIoT Example

This example contains 4 switches and 4 LEDs:

 * 4 LED Lights
     - Red   = garage       A3      Photon pin 9
     - Green = kitchen      RX      Photon pin 4
     - Blue  = living room  TX      Photon pin 3
     - Amber = bedroom      WKP     Photon pin 5

 * 4 Switches
     - Switch 1             D4      Photon pin 17
     - Switch 2             D5      Photon pin 18
     - Switch 3             D6      Photon pin 19
     - Switch 4             D7      Photon pin 20

http://www.github.com/rlisle/ParticleIoT

Written by Ron Lisle

BSD license, check LICENSE for more information.
All text above must be included in any redistribution.

Changelog:
2017-03-11: Created switch & leds
2017-03-07: Initial creation
********************************************************/

/****************/
/*** INCLUDES ***/
/****************/
#include <IoT.h>

/*****************/
/*** CONSTANTS ***/
/*****************/
// LED pins
#define kLed1Pin        A3      // pin 9
#define kLed2Pin        RX      // pin 4
#define kLed3Pin        TX      // pin 3
#define kLed4Pin        WKP     // pin 5

// LED light names
#define kLight1         "garage"        // Can be any name you want
#define kLight2         "kitchen"       // "
#define kLight3         "livingroom"    // "
#define kLight4         "bedroom"       // "

// Switch pins
#define kSwitch1Pin     D4      // pin 17 Can be any event you want
#define kSwitch2Pin     D5      // pin 18
#define kSwitch3Pin     D6      // pin 19
#define kSwitch4Pin     D7      // pin 20

// Event names can be anything you want, but should indicate activity
// and not just the name of an appliance.
#define kEvent1         "sleep"     // Turn off all lights except night lights
#define kEvent2         "watchtv"   // Dim living room lights
#define kEvent3         "cook"      // Turn on kitchen lights, fan
#define kEvent4         "bedtime"   // Turn on bedroom lights, all others off
#define kEvent5         "kitchen"   // Kitchen temp & humidity

/*****************/
/*** VARIABLES ***/
/*****************/
IoT *iot;

/*************/
/*** SETUP ***/
/*************/
void setup() {
    initializeIoT();
    addLights();
    addSwitches();

    iot->exposeControllers();
    iot->exposeActivities();
}

void initializeIoT() {
    iot = IoT::getInstance();
    iot->setControllerName("lislerv");
    iot->setPublishName("RonTest");
    iot->begin();
}

void addSwitches() {
    iot->addSwitch(kSwitch4Pin, kEvent4);
    iot->addSwitch(kSwitch3Pin, kEvent3);
    iot->addSwitch(kSwitch2Pin, kEvent2);
    iot->addSwitch(kSwitch1Pin, kEvent1);
}

void addLights() {
    iot->addLight(kLed1Pin, kLight1);
    iot->addLight(kLed2Pin, kLight2);
    iot->addLight(kLed3Pin, kLight3);
    iot->addLight(kLed4Pin, kLight4);
}

/************/
/*** LOOP ***/
/************/
void loop() {
    iot->loop(millis());
}

error: pathspec 'Photon/IoTlib/examples/switchesAndLEDs/switchesAndLEDs.ino' did not match any file(s) known to git


First working version of the arduino code.

/**
 *
Pianoduino

 * 61 key MIDI Keyboard with Arduino Uno Code, 24 shiftout outputs, 24 shiftin inputs
 * 1 resistive touchscreen and 16 analog I/O.
 * @author Malcolm Davis
 * @version 0.1
 * @since 2017-02-03
 */
 //Arduino Pins
 static const int muxAPin = 5;
 static const int muxBPin = 4;
 static const int muxCPin = 3;
 static const int muxReadPin = A0;
 static const int inClkPin = 7; //Shift in clock
 static const int loadPin = 6; //Shift in or load input. When high data, shifted. When Low data is loaded from parallel inputs.
 static const int inEnPin = 8; //Active low
 static const int inReadPin = 9;
 static const int dataPin = 11;
 static const int outClkPin = 12;
 static const int latchPin = 10;
 //If a Analog mux is added, just connect the control pins in parallel and add the En pin to the list.
 static const int muxEn [] = {2};

 //Constants
 int mask[] = { B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000 };//To read the columns values
 int blank = B00000000;//To send blank to the register.
 byte noteOn = B10010000;
 byte noteOff = B10000000;
 byte pitchBend = B11100001;
 static const byte  keyMidi[144]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                  B00101000, B00101000, B00101001, B00101001, B00101010, B00101010, B00101011, B00101011, B00101100, B00101100, B00100111, B00100111,
                                  B00101110, B00101110, B00101111, B00101111, B00110000, B00110000, 0, 0, 0, 0, B00101101, B00101101,
                                  B00111010, B00111010, B00111011, B00111011, 0, 0, B00110111, B00110111, B00111000, B00111000, B00111001, B00111001,
                                  B00110100, B00110100, B00110101, B00110101, B00110110, B00110110, B00110001, B00110001, B00110010, B00110010, B00110011, B00110011,
                                  B01010010, B01010010, B01010011, B01010011, B01010100, B01010100, B01001111, B01001111, B01010000, B01010000, B01010001, B01010001,
                                  B01001100, B01001100, B01001101, B01001101, B01001110, B01001110, B01001001, B01001001, B01001010, B01001010, B01001011, B01001011,
                                  B01000110, B01000110, B01000111, B01000111, B01001000, B01001000, B01000011, B01000011, B01000100, B01000100, B01000101, B01000101,
                                  B01000000, B01000000, B01000001, B01000001, B01000010, B01000010, B00111101, B00111101, B00111110, B00111110, B00111111, B00111111,
                                  0, 0, 0, 0, B00111100, B00111100, 0, 0, 0, 0, 0, 0
                                  };

 //Variables
 int actualPin = 0;
 static bool sValue[] = {0, 0, 0}; // S0, S1, S2 values
 int noteVelocity [144];
 bool keyState[144];
 bool rowsRead []= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

 /**
  * Method to setup the pins and stuffs of the pianoduino.
  * @param none
  * @return void
  */
void setup() {
  int i;
  Serial.begin(115200);
  pinMode(muxAPin, OUTPUT);
  pinMode(muxBPin, OUTPUT);
  pinMode(muxCPin, OUTPUT);
  pinMode(inClkPin, OUTPUT);
  pinMode(loadPin, OUTPUT);
  pinMode(inEnPin, OUTPUT);
  pinMode(inReadPin, INPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(outClkPin, OUTPUT);
  for (i=0; i< sizeof(muxEn)/sizeof(int); i++) {
    pinMode(muxEn[i], OUTPUT);
  }
  for (i=0; i<sizeof(noteVelocity)/sizeof(int);i++){
    noteVelocity[i]=127;
  }
  for (i=0; i<sizeof(keyState)/sizeof(bool);i++){
    noteVelocity[i]=0;
  }
  digitalWrite(loadPin,HIGH); //On HIGH is read ready
  delay(1000);
}

/**
 * Method to select a pin of a mux
 * @param pPin: the mux pin that you want to write or read.
 * @param pMuxEn: the pin of the mux that you want to read from.
 * @return void
 */
void muxToPin(int pPin, int pMuxEn){
  sValue[0] = bitRead(pPin, 0);
  sValue[1] = bitRead(pPin, 1);
  sValue[2] = bitRead(pPin, 2);
  for(int i=0; i < sizeof(muxEn)/sizeof(int);i++){
    digitalWrite(muxEn[i], HIGH);
  }
  digitalWrite(pMuxEn, LOW);
  digitalWrite(muxAPin, sValue[0]);
  digitalWrite(muxBPin, sValue[1]);
  digitalWrite(muxCPin, sValue[2]);
}

/**
 * Method to shift the registers to a matrix column
 * @param pColumn the column you wish to shift to.
 * @return void
 */
void shiftToColumn(int pColumn){
  digitalWrite(latchPin, LOW);
  if(pColumn <8){
    shiftOut(dataPin, outClkPin, MSBFIRST, mask[pColumn]);
    shiftOut(dataPin, outClkPin, MSBFIRST, blank);
    shiftOut(dataPin, outClkPin, MSBFIRST, mask[pColumn]);
  }else{
    shiftOut(dataPin, outClkPin, MSBFIRST, mask[pColumn%8]);
    shiftOut(dataPin, outClkPin, MSBFIRST, mask[pColumn%8]);
    shiftOut(dataPin, outClkPin, MSBFIRST, blank);
  }
  digitalWrite(latchPin, HIGH);
  delayMicroseconds(5);
}

/**
 * Main loop method
 * @param none
 * @return void
 */
void loop() {
  /**for(int i=0; i<8; i++){
    Serial.print("Y");
    Serial.print(i);
    Serial.print(": ");
    muxToPin(i, muxEn[0]);
    delay(4000);
    Serial.println( (map(analogRead(muxReadPin), 0, 1023, 0, 127)));
    Serial.print(sValue[2]);
    Serial.print(" ");
    Serial.print(sValue[1]);
    Serial.print(" ");
    Serial.println(sValue[0]);
  }*/
  for (int i =0; i<16; i++){
    shiftToColumn(i);
    scanRows();
    for(int j = 0; j < sizeof(rowsRead)/sizeof(byte);j++){
      if(i<12){
        if(rowsRead[j]&&!keyState[i+12*j]){
            keyState[i+12*j] = 1;
            if((i+12*j)%2==0){
              keyState[i+12*j+1]=1;
            }else{
              keyState[i+12*j-1]=1;
            }
            updateVelocity(i+12*j);
            midiSend(noteOn, keyMidi[i+12*j], 127);
        }else{
          if(keyState[i+12*j]&&!rowsRead[j]){
            keyState[i+12*j] = 0;
            midiSend(noteOff, keyMidi[i+12*j], 0);
            noteVelocity[i+12*j]=0;
            if((i+12*j)%2==0){
              noteVelocity[i+12*j+1]=0;
            }else{
              noteVelocity[i+12*j-1]=0;
            }
          }
        }
      }
      else{
        //The other buttons..
      }
    }
  }
}

/**
 * Method that  updates the velocity of a note.
 * @param pPos the position of the note in the array.
 */
void updateVelocity(int pPos){
  return ;
}

/**
 * Method to scan the values of all the inputs of the shiftregisters
 */
void scanRows(){
  digitalWrite(loadPin, LOW); //On Low the parallel data is collected
  delayMicroseconds(5);
  digitalWrite(loadPin,HIGH); //On HIGH is read ready
  delayMicroseconds(5);
  digitalWrite(inEnPin, LOW); //Active Low
  shiftIn(inReadPin, inClkPin);
  digitalWrite(inEnPin, HIGH); //Active Low
}

/**
 * Shift in modification method to read varius shift registers.
 * @param pDatapin the pin to read.
 * @param pClk the shift registers clock pin.
 */
 void shiftIn(int pDatapin, int pClk){
  for (int i = sizeof(rowsRead)/sizeof(byte)-1; i >=0 ;i--)
  {
    digitalWrite(inClkPin, LOW);
    delayMicroseconds(5);
    rowsRead[i] = digitalRead(inReadPin);
    digitalWrite(inClkPin, HIGH);
  }
 }

/**
 * Method to send the midi messega.
 * @param pCmd the midi command code.
 * @param pPitch the pitch of the note.
 * @param pVelocity of the note.
 * @return void
 */
void midiSend(byte pCmd, byte pPitch, byte pVelocity) {
  Serial.write(pCmd);
  Serial.write(pPitch);
  Serial.write(pVelocity);
}

error: pathspec 'Pianoduino.ino' did not match any file(s) known to git


Update

Update

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Haellsigh/Quadcopter.git/'


add arduino digital matrix writter

add arduino digital matrix writter

const int sensorPin= A0;//The analog sensor is connected to analog pin 0 of the arduino

//ABCDEFG,dp
const int numeral[10]= {
B11111100, //0
B01100000, //1
B11011010, //2
B11110010, //3
B01100110, //4
B10110110, //5
B00111110, //6
B11100000, //7
B11111110, //8
B11100110, //9
};

//pins for decimal point and each segment
//dp, G, F, E, D, C, B, A
const int segmentPins[]= { 4, 7, 8, 6, 5, 3, 2, 9};
// Dx de la placa

const int numberofDigits=4;

const int digitPins[numberofDigits] = { 10, 11, 12, 13}; //digits 1, 2, 3, 4

void setup() {
  // put your setup code here, to run once:
  for (int i=0; i < 8; i++)
    pinMode(segmentPins[i], OUTPUT); //set segment and DP pins to output

  //sets the digit pins as outputs
  for (int i=0; i < numberofDigits; i++)
    pinMode(digitPins[i], OUTPUT);

  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  int value= analogRead(sensorPin);
  float temp = (value/1024.0)*5000;
  float cel = temp/10;
  showNumber(cel);
  //Serial.println(cel);
  //Serial.println(value);
  //delay(1000);
}

void showNumber (int number)
{
  if (number == 0)
    showDigit (0, numberofDigits-1); //display 0 in the rightmost digit
  else
  {
    for (int digit= numberofDigits-1; digit >=0; digit--)
    {
      if (number > 0)
      {
        showDigit(number % 10, digit);
        number= number/10;
      }
    }
  }
}

//Displays given number on a 7-segment display at the given digit position
void showDigit (int number, int digit)
{
  digitalWrite(digitPins[digit], HIGH);
  for (int segment= 1; segment < 8; segment++)
  {
    boolean isBitSet= bitRead(numeral[number], segment);

    isBitSet= ! isBitSet; //remove this line if common cathode display
    digitalWrite(segmentPins[segment], isBitSet);
  }
  delay(1);
  digitalWrite(digitPins[digit], LOW);
}

error: pathspec 'arduinosrc/write_digital_matrix/write_digital_segments.ino' did not match any file(s) known to git