├── .gitignore ├── html.h ├── img ├── espcon1.PNG ├── espcon2.PNG ├── networkPort.PNG ├── setupWIFI.PNG ├── virtualJoy1.png ├── virtualJoy2.png ├── webSerial.PNG ├── esp8266setup.PNG ├── oseppBlockNetworkPort.PNG ├── oseppBlockNetworkUpload.PNG └── oseppBlock_connect2Serial.PNG ├── data ├── netstat.html ├── serial.html └── joy.html ├── stk500.h ├── readme.md └── EspUnoWifi.ino /.gitignore: -------------------------------------------------------------------------------- 1 | readme.markdown 2 | -------------------------------------------------------------------------------- /html.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/html.h -------------------------------------------------------------------------------- /img/espcon1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/espcon1.PNG -------------------------------------------------------------------------------- /img/espcon2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/espcon2.PNG -------------------------------------------------------------------------------- /img/networkPort.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/networkPort.PNG -------------------------------------------------------------------------------- /img/setupWIFI.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/setupWIFI.PNG -------------------------------------------------------------------------------- /img/virtualJoy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/virtualJoy1.png -------------------------------------------------------------------------------- /img/virtualJoy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/virtualJoy2.png -------------------------------------------------------------------------------- /img/webSerial.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/webSerial.PNG -------------------------------------------------------------------------------- /img/esp8266setup.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/esp8266setup.PNG -------------------------------------------------------------------------------- /img/oseppBlockNetworkPort.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/oseppBlockNetworkPort.PNG -------------------------------------------------------------------------------- /img/oseppBlockNetworkUpload.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/oseppBlockNetworkUpload.PNG -------------------------------------------------------------------------------- /img/oseppBlock_connect2Serial.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DIYOSEPP/EspUnoWiFi/HEAD/img/oseppBlock_connect2Serial.PNG -------------------------------------------------------------------------------- /data/netstat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OSEPP Esp8266 Uploder for Uno 6 | 39 | 40 | 41 |
42 | 43 | 44 | 45 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 57 | 58 |
AP SSID 46 |
AP PSWD 51 |
  56 |
59 |
60 |
61 |
62 | 63 | 64 | 65 | 73 | 74 | 75 | 76 | 78 | 79 | 80 | 81 | 83 | 84 |
WIFI SSID 66 |
67 | 70 | 71 |
72 |
WIFI Password 77 |
  82 |
85 |
86 |
87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
Local IP%s
subnetMask%s
gateway%s
dns%s
105 | 106 | 107 | -------------------------------------------------------------------------------- /stk500.h: -------------------------------------------------------------------------------- 1 | //**** ATMEL AVR - A P P L I C A T I O N N O T E ************************ 2 | //* 3 | //* Title: AVR061 - STK500 Communication Protocol 4 | //* Filename: command.h 5 | //* Version: 1.0 6 | //* Last updated: 09.09.2002 7 | //* 8 | //* Support E-mail: avr@atmel.com 9 | //* 10 | //************************************************************************** 11 | 12 | // *****************[ STK Message constants ]*************************** 13 | 14 | #define STK_SIGN_ON_MESSAGE "AVR STK" // Sign on string for Cmnd_STK_GET_SIGN_ON 15 | 16 | // *****************[ STK Response constants ]*************************** 17 | 18 | #define Resp_STK_OK 0x10 // ' ' 19 | #define Resp_STK_FAILED 0x11 // ' ' 20 | #define Resp_STK_UNKNOWN 0x12 // ' ' 21 | #define Resp_STK_NODEVICE 0x13 // ' ' 22 | #define Resp_STK_INSYNC 0x14 // ' ' 23 | #define Resp_STK_NOSYNC 0x15 // ' ' 24 | 25 | #define Resp_ADC_CHANNEL_ERROR 0x16 // ' ' 26 | #define Resp_ADC_MEASURE_OK 0x17 // ' ' 27 | #define Resp_PWM_CHANNEL_ERROR 0x18 // ' ' 28 | #define Resp_PWM_ADJUST_OK 0x19 // ' ' 29 | 30 | // *****************[ STK Special constants ]*************************** 31 | 32 | #define Sync_CRC_EOP 0x20 // 'SPACE' 33 | 34 | // *****************[ STK Command constants ]*************************** 35 | 36 | #define Cmnd_STK_GET_SYNC 0x30 // ' ' 37 | #define Cmnd_STK_GET_SIGN_ON 0x31 // ' ' 38 | 39 | #define Cmnd_STK_SET_PARAMETER 0x40 // ' ' 40 | #define Cmnd_STK_GET_PARAMETER 0x41 // ' ' 41 | #define Cmnd_STK_SET_DEVICE 0x42 // ' ' 42 | #define Cmnd_STK_SET_DEVICE_EXT 0x45 // ' ' 43 | 44 | #define Cmnd_STK_ENTER_PROGMODE 0x50 // ' ' 45 | #define Cmnd_STK_LEAVE_PROGMODE 0x51 // ' ' 46 | #define Cmnd_STK_CHIP_ERASE 0x52 // ' ' 47 | #define Cmnd_STK_CHECK_AUTOINC 0x53 // ' ' 48 | #define Cmnd_STK_LOAD_ADDRESS 0x55 // ' ' 49 | #define Cmnd_STK_UNIVERSAL 0x56 // ' ' 50 | #define Cmnd_STK_UNIVERSAL_MULTI 0x57 // ' ' 51 | 52 | #define Cmnd_STK_PROG_FLASH 0x60 // ' ' 53 | #define Cmnd_STK_PROG_DATA 0x61 // ' ' 54 | #define Cmnd_STK_PROG_FUSE 0x62 // ' ' 55 | #define Cmnd_STK_PROG_LOCK 0x63 // ' ' 56 | #define Cmnd_STK_PROG_PAGE 0x64 // ' ' 57 | #define Cmnd_STK_PROG_FUSE_EXT 0x65 // ' ' 58 | 59 | #define Cmnd_STK_READ_FLASH 0x70 // ' ' 60 | #define Cmnd_STK_READ_DATA 0x71 // ' ' 61 | #define Cmnd_STK_READ_FUSE 0x72 // ' ' 62 | #define Cmnd_STK_READ_LOCK 0x73 // ' ' 63 | #define Cmnd_STK_READ_PAGE 0x74 // ' ' 64 | #define Cmnd_STK_READ_SIGN 0x75 // ' ' 65 | #define Cmnd_STK_READ_OSCCAL 0x76 // ' ' 66 | #define Cmnd_STK_READ_FUSE_EXT 0x77 // ' ' 67 | #define Cmnd_STK_READ_OSCCAL_EXT 0x78 // ' ' 68 | 69 | // *****************[ STK Parameter constants ]*************************** 70 | 71 | #define Parm_STK_HW_VER 0x80 // ' ' - R 72 | #define Parm_STK_SW_MAJOR 0x81 // ' ' - R 73 | #define Parm_STK_SW_MINOR 0x82 // ' ' - R 74 | #define Parm_STK_LEDS 0x83 // ' ' - R/W 75 | #define Parm_STK_VTARGET 0x84 // ' ' - R/W 76 | #define Parm_STK_VADJUST 0x85 // ' ' - R/W 77 | #define Parm_STK_OSC_PSCALE 0x86 // ' ' - R/W 78 | #define Parm_STK_OSC_CMATCH 0x87 // ' ' - R/W 79 | #define Parm_STK_RESET_DURATION 0x88 // ' ' - R/W 80 | #define Parm_STK_SCK_DURATION 0x89 // ' ' - R/W 81 | 82 | #define Parm_STK_BUFSIZEL 0x90 // ' ' - R/W, Range {0..255} 83 | #define Parm_STK_BUFSIZEH 0x91 // ' ' - R/W, Range {0..255} 84 | #define Parm_STK_DEVICE 0x92 // ' ' - R/W, Range {0..255} 85 | #define Parm_STK_PROGMODE 0x93 // ' ' - 'P' or 'S' 86 | #define Parm_STK_PARAMODE 0x94 // ' ' - TRUE or FALSE 87 | #define Parm_STK_POLLING 0x95 // ' ' - TRUE or FALSE 88 | #define Parm_STK_SELFTIMED 0x96 // ' ' - TRUE or FALSE 89 | #define Param_STK500_TOPCARD_DETECT 0x98 // ' ' - Detect top-card attached 90 | 91 | // *****************[ STK status bit definitions ]*************************** 92 | 93 | #define Stat_STK_INSYNC 0x01 // INSYNC status bit, '1' - INSYNC 94 | #define Stat_STK_PROGMODE 0x02 // Programming mode, '1' - PROGMODE 95 | #define Stat_STK_STANDALONE 0x04 // Standalone mode, '1' - SM mode 96 | #define Stat_STK_RESET 0x08 // RESET button, '1' - Pushed 97 | #define Stat_STK_PROGRAM 0x10 // Program button, ' 1' - Pushed 98 | #define Stat_STK_LEDG 0x20 // Green LED status, '1' - Lit 99 | #define Stat_STK_LEDR 0x40 // Red LED status, '1' - Lit 100 | #define Stat_STK_LEDBLINK 0x80 // LED blink ON/OFF, '1' - Blink 101 | 102 | 103 | // *****************************[ End Of COMMAND.H ]************************** -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # esp8266 Uno Wifi 2 | 3 | This project runs on esp8266 and provides serial bridge services for uno,The first time you need to use the serial port to upload the sketch to esp8266.Then you can use WIFI SerialPort like using USB 4 | 5 | you can: 6 | 7 | + OTA(over the air) upload new sketch to esp8266 8 | + OTA(over the air) upload new sketch to UNO(without manual reset uno) 9 | + Access the serial port of the uno through web browser 10 | + Access uno serial port via TCP 11 | + Configuring access points and wifi using web browser 12 | + TCP channel(oseppBlock) and up to five WebSocket connections(Browser) receive data at the same time from the uno serial port 13 | + Control your robot using a web browser on any device anywhere 14 | 15 | ![ ](img/espcon1.PNG) 16 | 17 | ESP8266 will have two IP addresses,depending on your network connection 18 | If your esp8266 is connected to the router and your device is also connected to the router, then you should access it with the IP address assigned by the router to ESP8266. The format of the IP address is usually 192.168.1.? 19 | If your device accesses ESP8266's WIFI access point then you should use 192.168.4.1 to access it 20 | No matter how you connect, they are all equivalent 21 | 22 | ![ ](img/espcon2.PNG) 23 | 24 | 25 | 26 | 27 | 28 | - [esp8266 Uno Wifi](#esp8266-uno-wifi) 29 | - [1. setup esp8266](#1-setup-esp8266) 30 | - [2. setup Access point & connect to your router](#2-setup-access-point--connect-to-your-router) 31 | - [3. Connect esp8266 to uno](#3-connect-esp8266-to-uno) 32 | - [4. upload sketch to uno via OTA](#4-upload-sketch-to-uno-via-ota) 33 | - [5. upload sketch to esp8266(esp-01s) via OTA](#5-upload-sketch-to-esp8266esp-01s-via-ota) 34 | - [6. Web browser Serial monitor](#6-web-browser-serial-monitor) 35 | - [7. Using arduinoOTA and TCP Serial Monitors in oseppBlock](#7-using-arduinoota-and-tcp-serial-monitors-in-oseppblock) 36 | - [8. Virtual Joystick](#8-virtual-joystick) 37 | 38 | 39 | 40 | --- 41 | 42 | ## 1. setup esp8266 43 | 44 | + Load sketch **EspUnoWifi.ino** using arduino IDE 45 | + [install ESP8266 into your Arduino IDE](http://esp8266.github.io/Arduino/versions/2.0.0/doc/installing.html) 46 | + install[arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets)Arduino Libraries 47 | Sketch -> Include Library -> Manage Libraries 48 | Search websockets and install **WebSockets by Markus Sattler** 49 | *[How to Install a Library](https://www.arduino.cc/en/guide/libraries)* 50 | + Set your router SSID and password in the sketch(*You can skip this step and then setting it in web browser*) 51 | `const char default_router_ssid[] = "YourRouterSSID";//your router ssid` 52 | `const char default_router_pswd[] = "YourRouterPassword";//your router password` 53 | + upload this project to ESP8266 via Serial port 54 | You need a UNO, don't switch on the power first,Connect them like this 55 | 56 | | ESP-01S | UNO | 57 | | :-----: | :---------: | 58 | | RX | RX | 59 | | TX | TX | 60 | | IO0 | GND | 61 | | GND | GND | 62 | | 3V3 | 3V3 | 63 | | | Reset-->GND | 64 | 65 | Now connect UNO and computer via USB.Since we connect UNO's Reset to GND, UNO is now bypassed.Esp-01's IO0 is connected to GND, so ESP01 enters the bootloader,use arduino IDE to upload the program will enter esp-01 66 | + Tool->Board->**Generic ESP8266 Module** 67 | + Tool->Flash Size->**1M(no SPIFFS)** 68 | + Tool->Port->**your serial com port** 69 | + click **upload** 70 | + If you fail, it may be that esp8266 does not enter bootloader mode, unplug the 3V3 from Uno, inserts it again after about 3 seconds, and then **upload** again 71 | 72 | ## 2. setup Access point & connect to your router 73 | 74 | If you have already set the router SSID and password in step 1, you can skip this step 75 | 76 | + Connect the power supply for ESP8266(just 3v3,gnd,rx,tx) 77 | + Log in to the access point **WIFI-ESP-SERIAL-xxxxxx** with any wifi-capable device and use the password **oseppesp** 78 | + Use a web browser to open URL: 79 | + Select **your router access point** at `WIFI SSID` and fill your router password in `WIFI Password` and chick nearby **update** button,esp8266 will restart so you will lose wifi connection,Wait a moment then re-Connect to the access point open URL: again.For unknown reasons, usually you will see the IP address is 0.0.0.0, then you need to manually reset the ESP8266 to make it connect to the route correctly... 80 | + If ESP8266 has successfully connected to your router then it will show an IP address at the bottom of the page. 81 | + Set a new esp8266 access point name and password for security,Fill in **AP SSID**, and **AP PSWD**,Password is at least 8 letters or it will not work,Click nearby **update** button. 82 | ![ ](img/setupWIFI.PNG) 83 | 84 | ## 3. Connect esp8266 to uno 85 | 86 | | ESP-01s | uno | 87 | | ------: | ----- | 88 | | RX | TX | 89 | | TX | RX | 90 | | 3V3 | 3v3 | 91 | | GND | GND | 92 | | IO2 | reset | 93 | 94 | | Nodemcu | uno | 95 | | ------: | ----- | 96 | | RX | TX | 97 | | TX | RX | 98 | | VIN | 5V | 99 | | GND | GND | 100 | | D4 | reset | 101 | 102 | ## 4. upload sketch to uno via OTA 103 | 104 | + Tool->Board->**Arduino Uno WiFi** 105 | *You can't use `Uno WiFi` features just to be able to use arduino OTA* 106 | + Tool->Port->Network ports->**your network device** 107 | + click **upload** 108 | + If you see the following text, the upload was successful 109 | > Resetting the board 110 | Waiting for the upload to start 111 | OSEPP Esp8266 for UnoOTA, SYNC OK!184705 112 | Uploading the sketch 113 | Upload done! Flash used:2806 bytes 114 | Sketch uploaded successfully 115 | Resetting the board 116 | ![ ](img/networkPort.PNG) 117 | 118 | ## 5. upload sketch to esp8266(esp-01s) via OTA 119 | 120 | + Tool->Board->**Generic ESP8266 Module** 121 | + Tool->Flash Size->**1M(no SPIFFS)** 122 | + Tool->Port->Network ports->**network device** 123 | + click **upload** 124 | + ![ ](img/esp8266setup.PNG) 125 | 126 | ## 6. Web browser Serial monitor 127 | 128 | + Open the URL in web browser:`http://[esp8266 ip you see in port list or 192.168.4.1]?baudrate=115200` 129 | *note:You can specify the baud rate of the serial port by appending **?baudrate=nnnnn** to any url.* 130 | + Upload a sketch with serial output to UNO,[according to #4](#4-upload-sketch-to-uno-via-ota) 131 | 132 | ```arduino 133 | void setup() { 134 | // put your setup code here, to run once: 135 | Serial.begin(115200); 136 | } 137 | 138 | void loop() { 139 | // put your main code here, to run repeatedly: 140 | Serial.println(millis()); 141 | delay(1000); 142 | } 143 | ``` 144 | 145 | + You will see the serial data displayed in the web browser 146 | + You can try to send msg to uno, reset uno 147 | + ![ ](img/webSerial.PNG) 148 | 149 | ## 7. Using arduinoOTA and TCP Serial Monitors in oseppBlock 150 | 151 | + Select the network device in the port list, or fill in the IP address.![ ](img/oseppBlockNetworkPort.PNG) 152 | + Click on the upload icon to upload the sketch to UNO via OTA![ ](img/oseppBlockNetworkUpload.PNG) 153 | + Click on the connection icon, you can see the following window, the same as the USB connection![ ](img/oseppBlock_connect2Serial.PNG) 154 | 155 | 156 | ## 8. Virtual Joystick 157 | 158 | + Open `http://[esp8266 ip address]/joy` in web browser *phone, ipad, computer, any browser supporting HTML5* 159 | + Add `?baudrate=nnnnnn` at the end of the URL to set the baud rate you want like `http://192.168.0.88/joy?baudrate=115200` 160 | + Use mouse, or touch the screen with your finger and drag, support multi-touch (2 points) 161 | + In oseppBlock, you can use Block 162 | **Remote [Joy Channel]** 163 | **Remote Timeout[*]** 164 | To receive data and processing 165 | + In the Arduino IDE, you can use our OseppRemote library 166 | 167 | ![ ](img/virtualJoy1.png) 168 | ![ ](img/virtualJoy2.png) 169 | -------------------------------------------------------------------------------- /data/serial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Serial Monitor 9 | 10 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
130 |
    131 |
  • 132 | 138 |
  • 139 |
  • 140 | 141 | 142 | 143 |
  • 144 |
  • 145 | 146 | 147 | 148 |
  • 149 |
150 |
    151 |
  • Baudrate:
  • 152 |
  • 153 | 154 | 173 | 174 | 175 |
  • 176 |
  • Message:
  • 177 |
178 |
    179 |
  • 180 | 181 |
  • 182 |
183 | 184 |
185 |
186 |
187 | 280 | 281 | 282 | 283 | -------------------------------------------------------------------------------- /data/joy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 35 | 36 | 37 | 38 |
39 | Virtual Joystick 40 |
41 | 42 |
43 | 44 |
45 | 46 |
47 | 48 |
49 | 50 |
51 | 52 |
53 | 54 |
55 | 56 |
57 | 58 |
59 | 60 |
61 | 493 | 494 | 495 | -------------------------------------------------------------------------------- /EspUnoWifi.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This program is free software; you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License as published by 4 | the Free Software Foundation; either version 2 of the License, or 5 | (at your option) any later version. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program. If not, see . 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "html.h" 27 | 28 | const char default_router_ssid[] = ""; // your router ssid 29 | const char default_router_pswd[] = ""; // your router password 30 | 31 | #define eeprom_size 512 32 | #pragma pack(push) 33 | #pragma pack(1) 34 | typedef struct { 35 | char flag[2]; 36 | char ssid[32]; 37 | char pswd[32]; 38 | char apssid[32]; 39 | char appswd[32]; 40 | unsigned int bardrate; 41 | unsigned int bardrate_isp; 42 | } EEPROM_CONFIG; 43 | EEPROM_CONFIG econfig; 44 | #pragma pack(pop) 45 | 46 | const int resetPin = 2; // GPIO2-->UNO reset pin 47 | void resetTarget() { 48 | pinMode(resetPin, OUTPUT_OPEN_DRAIN); 49 | digitalWrite(resetPin, LOW); 50 | delay(10); 51 | digitalWrite(resetPin, HIGH); 52 | } 53 | 54 | unsigned char read_page_buff[128]; 55 | unsigned char write_page_buff[sizeof(read_page_buff)]; 56 | int address = 0; 57 | int baseaddr = 0; 58 | int total_write = 0; 59 | uint8_t dity = 0; 60 | 61 | WiFiServer avrOTA(80); 62 | WiFiClient avrOTA_Clients[8]; 63 | unsigned int avrOTA_Client_LastIndex = 0; 64 | 65 | WiFiServer msgserver(8080); 66 | WiFiClient msgclient; 67 | 68 | WiFiUDP Udp; 69 | IPAddress udp_address; 70 | unsigned int udp_port = 0; 71 | unsigned long udp_last = 0; 72 | 73 | WebSocketsServer webSocket = WebSocketsServer(81); 74 | 75 | //#define debug(fmt, ...) 76 | // if(msgclient)if(msgclient.connected())msgclient.printf(fmt, ##__VA_ARGS__) 77 | #define debug(...) 78 | 79 | inline uint8_t ctoh(char c) { 80 | return (c & 0x10) ? /*0-9*/ c & 0xf : /*A-F, a-f*/ (c & 0xf) + 9; 81 | } 82 | const char *head_frm = 83 | "HTTP/1.1 %d OK\r\nContent-Type: " 84 | "text/html\r\nAccess-Control-Allow-Origin:*\r\nContent-Length: " 85 | "%d\r\nConnection : close\r\n\r\n"; 86 | 87 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, 88 | size_t lenght) { 89 | switch (type) { 90 | case WStype_DISCONNECTED: 91 | break; 92 | case WStype_CONNECTED: 93 | break; 94 | case WStype_TEXT: 95 | case WStype_BIN: 96 | Serial.write(payload, lenght); 97 | break; 98 | } 99 | } 100 | 101 | void save_eeprom() { 102 | EEPROM.put(0, econfig); 103 | EEPROM.commit(); 104 | } 105 | 106 | void load_eeprom() { 107 | EEPROM.get(0, econfig); 108 | 109 | if (econfig.flag[0] != 0xaa || econfig.flag[1] != 0x55) { 110 | memset(&econfig, 0, sizeof(econfig)); 111 | econfig.flag[0] = 0xaa; 112 | econfig.flag[1] = 0x55; 113 | save_eeprom(); 114 | } 115 | if (econfig.bardrate == 0 || econfig.bardrate > 2000000) 116 | econfig.bardrate = 115200; 117 | if (econfig.bardrate_isp == 0 || econfig.bardrate_isp > 2000000) 118 | econfig.bardrate_isp = 115200; 119 | if (strlen(econfig.apssid) == 0) { 120 | sprintf_P(econfig.apssid, PSTR("WIFI-ESP-SERIAL-%06x"), 121 | ESP.getChipId()); 122 | strcpy_P(econfig.appswd, PSTR("oseppesp")); 123 | } 124 | 125 | if (strlen(econfig.ssid) == 0) { 126 | strcpy(econfig.ssid, default_router_ssid); 127 | strcpy(econfig.pswd, default_router_pswd); 128 | } 129 | } 130 | 131 | void setup() { 132 | EEPROM.begin(eeprom_size); 133 | load_eeprom(); 134 | Serial.begin(econfig.bardrate); 135 | Serial.print("ssid:"); 136 | Serial.println(econfig.ssid); 137 | Serial.print("pswd:"); 138 | Serial.println(econfig.pswd); 139 | WiFi.mode(WIFI_AP_STA); 140 | if (strlen(econfig.apssid)) { 141 | if (strlen(econfig.appswd) < 8) 142 | WiFi.softAP(econfig.apssid); 143 | else 144 | WiFi.softAP(econfig.apssid, econfig.appswd); 145 | } 146 | if (strlen(econfig.ssid)) { 147 | if (strlen(econfig.pswd)) 148 | WiFi.begin(econfig.ssid, econfig.pswd); 149 | else 150 | WiFi.begin(econfig.ssid); 151 | 152 | if (WiFi.status() != WL_CONNECTED) delay(500); 153 | } 154 | resetTarget(); 155 | ArduinoOTA.begin(false); 156 | 157 | avrOTA.begin(); 158 | msgserver.begin(); 159 | 160 | webSocket.begin(); 161 | webSocket.onEvent(webSocketEvent); 162 | 163 | Udp.begin(82); 164 | } 165 | 166 | void joy_html(WiFiClient wc) { 167 | wc.printf(head_frm, 200, sizeof(joy_text)); 168 | wc.write_P(joy_text, sizeof(joy_text)); 169 | } 170 | 171 | void serial_html(WiFiClient wc) { 172 | wc.printf(head_frm, 200, sizeof(serial_text)); 173 | wc.write_P(serial_text, sizeof(serial_text)); 174 | } 175 | 176 | void netstat_html(WiFiClient wc) { 177 | wc.setTimeout(10000); 178 | int dlen = strlen(econfig.apssid) + strlen(econfig.ssid) - 4; 179 | 180 | int n = WiFi.scanNetworks(); 181 | String wifi_option = ""; 182 | for (int i = 0; i < n; ++i) { 183 | wifi_option += "\r\n"; 185 | } 186 | 187 | dlen = wifi_option.length() - 2; 188 | 189 | String localip = WiFi.localIP().toString(); 190 | dlen += localip.length() - 2; 191 | 192 | String subnet = WiFi.subnetMask().toString(); 193 | dlen += subnet.length() - 2; 194 | 195 | String gateway = WiFi.gatewayIP().toString(); 196 | dlen += gateway.length() - 2; 197 | 198 | String dns = WiFi.dnsIP().toString(); 199 | dlen += dns.length() - 2; 200 | 201 | wc.printf(head_frm, 200, strlen_P(index_text) + dlen); 202 | wc.printf_P(index_text, econfig.apssid, wifi_option.c_str(), econfig.ssid, 203 | localip.c_str(), subnet.c_str(), gateway.c_str(), dns.c_str()); 204 | } 205 | 206 | void setssid(byte isAP, WiFiClient wc) { 207 | String line; 208 | int contentLen = 0; 209 | do { 210 | line = wc.readStringUntil('\n'); 211 | line.toLowerCase(); 212 | if (line.indexOf("content-length") >= 0) { 213 | contentLen = line.substring(line.indexOf(':') + 1).toInt(); 214 | } 215 | } while (line != String("\r")); 216 | 217 | char key[256]; 218 | int pos = 0; 219 | char *value = NULL; 220 | char tssid[32]; 221 | char tpswd[32]; 222 | memset(tssid, 0, sizeof(tssid)); 223 | memset(tpswd, 0, sizeof(tpswd)); 224 | while (contentLen) { 225 | char c = wc.read(); 226 | contentLen--; 227 | if (c == '&' || contentLen == 0) { 228 | if (c != '&') key[pos++] = c; 229 | key[pos] = '\0'; 230 | if (strstr_P(key, PSTR("ssid"))) { 231 | if (value) { 232 | for (int i = 0; i < sizeof(tssid) - 1; i++) { 233 | tssid[i] = value[i]; 234 | if (value[i] == '\0') break; 235 | } 236 | } 237 | } else if (strstr_P(key, PSTR("pswd"))) { 238 | if (value) { 239 | for (int i = 0; i < sizeof(tpswd) - 1; i++) { 240 | tpswd[i] = value[i]; 241 | if (value[i] == '\0') break; 242 | } 243 | } 244 | } 245 | pos = 0; 246 | key[0] = '\0'; 247 | value = NULL; 248 | } else if (c == '%') { 249 | c = ctoh(wc.read()); 250 | c <<= 4; 251 | c |= ctoh(wc.read()) & 0x0f; 252 | contentLen -= 2; 253 | key[pos++] = c; 254 | } else if (c == '=') { 255 | key[pos++] = '\0'; 256 | value = key + pos; 257 | } else if ((c != '\r') && (c != '\n')) { 258 | key[pos++] = c; 259 | } 260 | if (pos == sizeof(key)) break; 261 | } 262 | 263 | wc.printf(head_frm, 200, sizeof(redir_text)); 264 | wc.write_P(redir_text, sizeof(redir_text)); 265 | save_eeprom(); 266 | if (isAP) { 267 | strcpy(econfig.apssid, tssid); 268 | strcpy(econfig.appswd, tpswd); 269 | WiFi.softAPdisconnect(); 270 | if (strlen(tssid)) { 271 | if (strlen(tpswd) < 7) 272 | WiFi.softAP(tssid); 273 | else 274 | WiFi.softAP(tssid, tpswd); 275 | } 276 | } else { 277 | strcpy(econfig.ssid, tssid); 278 | strcpy(econfig.pswd, tpswd); 279 | WiFi.disconnect(); 280 | if (strlen(tssid)) { 281 | if (strlen(tpswd)) 282 | WiFi.begin(tssid); 283 | else 284 | WiFi.begin(tssid, tpswd); 285 | } 286 | } 287 | MDNS.notifyAPChange(); 288 | MDNS.update(); 289 | save_eeprom(); 290 | while (wc.availableForWrite()) wc.flush(); 291 | ESP.reset(); 292 | } 293 | 294 | byte msgPipeBuff[512]; 295 | unsigned long last_time_tx = 0; 296 | int last_time_tx_available = 0; 297 | unsigned long last_time_tx_pass_tick = 0; 298 | void loop() { 299 | static bool msdn_inited = false; 300 | if (!msdn_inited && WiFi.status() == WL_CONNECTED) { 301 | if (MDNS.begin(econfig.apssid)) { 302 | MDNS.enableArduino(8266); 303 | MDNS.addService("websock", "tcp", 81); 304 | MDNS.addService("message", "tcp", 8080); 305 | MDNS.addService("http", "tcp", 80); 306 | MDNS.addService("remotecontrol", "udp", 82); 307 | MDNS.update(); 308 | msdn_inited = true; 309 | } 310 | } 311 | if (msdn_inited) MDNS.update(); 312 | ArduinoOTA.handle(); 313 | 314 | webSocket.loop(); 315 | int n = 0; 316 | n = Udp.parsePacket(); 317 | if (n) { 318 | while (n) { 319 | int len = Udp.read( 320 | msgPipeBuff, n > sizeof(msgPipeBuff) ? sizeof(msgPipeBuff) : n); 321 | Serial.write(msgPipeBuff, n); 322 | n -= len; 323 | delay(0); 324 | } 325 | udp_port = Udp.remotePort(); 326 | udp_address = Udp.remoteIP(); 327 | udp_last = millis(); 328 | } else { 329 | if ((unsigned long)(millis() - udp_last) > 500) udp_port = 0; 330 | } 331 | 332 | if (msgserver.hasClient()) { 333 | if (msgclient) msgclient.stop(); 334 | msgclient = msgserver.available(); 335 | msgclient.setNoDelay(true); 336 | } 337 | 338 | if (msgclient && msgclient.connected()) { 339 | while (n = msgclient.available()) { 340 | n = msgclient.readBytes( 341 | msgPipeBuff, n > sizeof(msgPipeBuff) ? sizeof(msgPipeBuff) : n); 342 | Serial.write(msgPipeBuff, n); 343 | delay(0); 344 | } 345 | } 346 | n = Serial.available(); 347 | if (n != last_time_tx_available) { 348 | last_time_tx_pass_tick = millis(); 349 | last_time_tx_available = n; 350 | } 351 | bool tx = (millis() - last_time_tx > 30); 352 | tx = tx || (millis() - last_time_tx_pass_tick > 2); 353 | tx = tx && n; 354 | tx = tx || (n > sizeof(msgPipeBuff) / 2); 355 | if (tx) { 356 | do { 357 | n = Serial.available(); 358 | n = Serial.readBytes( 359 | msgPipeBuff, n > sizeof(msgPipeBuff) ? sizeof(msgPipeBuff) : n); 360 | if (msgclient && msgclient.connected()) 361 | msgclient.write(msgPipeBuff, n); 362 | webSocket.broadcastBIN(msgPipeBuff, n); 363 | if (udp_port) { 364 | Udp.beginPacket(udp_address, udp_port); 365 | Udp.write(msgPipeBuff, n); 366 | Udp.endPacket(); 367 | } 368 | delay(0); 369 | } while (Serial.available() > sizeof(msgPipeBuff) / 4); 370 | last_time_tx = millis(); 371 | } 372 | 373 | if (avrOTA.hasClient()) { 374 | avrOTA_Client_LastIndex++; 375 | int index; 376 | for (int i = 0; i < sizeof(avrOTA_Clients) / sizeof(avrOTA_Clients[0]); 377 | i++, avrOTA_Client_LastIndex++) { 378 | index = avrOTA_Client_LastIndex % 379 | (sizeof(avrOTA_Clients) / sizeof(avrOTA_Clients[0])); 380 | if (!avrOTA_Clients[index]) break; 381 | if (!avrOTA_Clients[index].connected()) break; 382 | } 383 | 384 | avrOTA_Client_LastIndex %= 385 | (sizeof(avrOTA_Clients) / sizeof(avrOTA_Clients[0])); 386 | if (avrOTA_Clients[avrOTA_Client_LastIndex]) 387 | avrOTA_Clients[avrOTA_Client_LastIndex].stop(); 388 | avrOTA_Clients[avrOTA_Client_LastIndex] = avrOTA.available(); 389 | avrOTA_Clients[avrOTA_Client_LastIndex].setNoDelay(true); 390 | } 391 | for (int i = 1; i <= sizeof(avrOTA_Clients) / sizeof(avrOTA_Clients[0]); 392 | i++) { 393 | WiFiClient avrOTA_client = 394 | avrOTA_Clients[(avrOTA_Client_LastIndex + i) % 395 | (sizeof(avrOTA_Clients) / 396 | sizeof(avrOTA_Clients[0]))]; 397 | if (avrOTA_client && avrOTA_client.connected() && 398 | avrOTA_client.available()) { 399 | String s = avrOTA_client.readStringUntil('\n'); 400 | s.toLowerCase(); 401 | 402 | int pos = s.lastIndexOf("baudrate="); 403 | if (pos > 0) { 404 | while (s[pos++] != '=') 405 | ; 406 | unsigned int trate = 0; 407 | while (s[pos] >= '0' && s[pos] <= '9') { 408 | trate *= 10; 409 | trate += s[pos] - '0'; 410 | pos++; 411 | } 412 | if (trate > 0 && trate <= 2000000) { 413 | if (econfig.bardrate != trate) { 414 | econfig.bardrate = trate; 415 | save_eeprom(); 416 | Serial.begin(trate); 417 | } 418 | } 419 | } 420 | pos = s.lastIndexOf("baudrateisp="); 421 | if (pos > 0) { 422 | while (s[pos++] != '=') 423 | ; 424 | unsigned int trate = 0; 425 | while (s[pos] >= '0' && s[pos] <= '9') { 426 | trate *= 10; 427 | trate += s[pos] - '0'; 428 | pos++; 429 | } 430 | if (trate > 0 && trate <= 2000000) { 431 | if (econfig.bardrate_isp != trate) { 432 | econfig.bardrate_isp = trate; 433 | save_eeprom(); 434 | } 435 | } 436 | } 437 | if (s.indexOf("sync") > 0) { 438 | String respone("OSEPP Esp8266 for UnoOTA, SYNC OK!"); 439 | respone += millis(); 440 | if (s.indexOf("post") >= 0) { 441 | avrOTA_client.printf(head_frm, 204, respone.length()); 442 | avrOTA_client.print(respone); 443 | } else { 444 | avrOTA_client.printf(head_frm, 200, respone.length()); 445 | avrOTA_client.print(respone); 446 | } 447 | } else if (s.indexOf("reset") > 0) { 448 | resetTarget(); 449 | String respone("Reset OK!"); 450 | respone += millis(); 451 | avrOTA_client.printf(head_frm, 200, respone.length()); 452 | avrOTA_client.print(respone); 453 | } else if (s.indexOf("upload") > 0) { 454 | String line; 455 | int hexLen = 0; 456 | do { 457 | if (!avrOTA_client.available()) break; 458 | line = avrOTA_client.readStringUntil('\n'); 459 | line.toLowerCase(); 460 | if (line.indexOf("content-length") >= 0) { 461 | hexLen = line.substring(line.indexOf(':') + 1).toInt(); 462 | } 463 | } while (line != String("\r")); 464 | extern int handleHex(WiFiClient client, int hexlen); 465 | int handLen = handleHex(avrOTA_client, hexLen); 466 | Serial.begin(econfig.bardrate); 467 | if (handLen != hexLen) { 468 | String respone("Upload Error!"); 469 | if (handLen < 0) { 470 | respone += " can't entry bootloader!"; 471 | } else { 472 | respone += " at Hex File(byte):"; 473 | respone += handLen; 474 | respone += " total:"; 475 | respone += hexLen; 476 | respone += ","; 477 | respone += total_write; 478 | respone += " bytes have been written"; 479 | } 480 | avrOTA_client.printf(head_frm, 404, respone.length()); 481 | avrOTA_client.print(respone); 482 | } else { 483 | String respone("Upload done! Flash used:"); 484 | respone += total_write; 485 | respone += " bytes"; 486 | avrOTA_client.printf(head_frm, 200, respone.length()); 487 | avrOTA_client.print(respone); 488 | } 489 | } else if ((s.indexOf("setap") > 0) && (s.indexOf("post") >= 0)) { 490 | setssid(1, avrOTA_client); 491 | } else if ((s.indexOf("setwf") > 0) && (s.indexOf("post") >= 0)) { 492 | setssid(0, avrOTA_client); 493 | } else if (s.indexOf("netstat") > 0) { 494 | netstat_html(avrOTA_client); 495 | } else if (s.indexOf("getbaudrate") > 0) { 496 | String respone(econfig.bardrate); 497 | avrOTA_client.printf(head_frm, 200, respone.length()); 498 | avrOTA_client.print(respone); 499 | } else if (s.indexOf("joy") > 0) { 500 | joy_html(avrOTA_client); 501 | } else if ((s.indexOf("index") > 0) || (s.indexOf(" / ") > 0) || 502 | (s.indexOf("serial") > 0)) { 503 | serial_html(avrOTA_client); 504 | } else { 505 | avrOTA_client.printf(head_frm, 404, 0); 506 | } 507 | avrOTA_client.flush(); 508 | // avrOTA_client.stop(); 509 | } 510 | } 511 | } 512 | 513 | #include "stk500.h" 514 | 515 | #define MAX_SYNC_ATTEMPTS 10 516 | 517 | static int stk500_send(unsigned char *buf, size_t len) { 518 | Serial.write(buf, len); 519 | return len; 520 | } 521 | static int stk500_send(unsigned char data) { 522 | Serial.write(data); 523 | return 1; 524 | } 525 | 526 | static int stk500_recv(unsigned char *buf, size_t len) { 527 | int i = 200; 528 | while (i && Serial.available() < (int)len) { 529 | delay(1); 530 | i--; 531 | } 532 | int rv = Serial.readBytes(buf, len); 533 | if (rv < 0) { 534 | debug("stk500_recv(): programmer is not responding\n"); 535 | return -1; 536 | } 537 | 538 | return 0; 539 | } 540 | 541 | int stk500_drain() { 542 | while (Serial.available()) Serial.read(); 543 | return 0; 544 | } 545 | 546 | int stk500_getsync() { 547 | unsigned char buf[32], resp[32]; 548 | int attempt; 549 | 550 | /* get in sync */ 551 | buf[0] = Cmnd_STK_GET_SYNC; 552 | buf[1] = Sync_CRC_EOP; 553 | 554 | /* 555 | First send and drain a few times to get rid of line noise 556 | */ 557 | 558 | stk500_send(buf, 2); 559 | stk500_drain(); 560 | stk500_send(buf, 2); 561 | stk500_drain(); 562 | 563 | for (attempt = 0; attempt < MAX_SYNC_ATTEMPTS; attempt++) { 564 | stk500_send(buf, 2); 565 | stk500_recv(resp, 1); 566 | if (resp[0] == Resp_STK_INSYNC) { 567 | break; 568 | } 569 | debug("stk500_getsync() attempt %d of %d: not in sync: resp=0x%02x\n", 570 | attempt + 1, MAX_SYNC_ATTEMPTS, resp[0]); 571 | } 572 | if (attempt == MAX_SYNC_ATTEMPTS) { 573 | stk500_drain(); 574 | return -1; 575 | } 576 | 577 | if (stk500_recv(resp, 1) < 0) return -1; 578 | if (resp[0] != Resp_STK_OK) { 579 | debug("stk500_getsync(): can't communicate with device: resp=0x%02x\n", 580 | resp[0]); 581 | return -1; 582 | } 583 | 584 | return 0; 585 | } 586 | 587 | static int stk500_loadaddr(unsigned int addr) { 588 | unsigned char buf[16]; 589 | int tries; 590 | tries = 0; 591 | retry: 592 | tries++; 593 | buf[0] = Cmnd_STK_LOAD_ADDRESS; 594 | buf[1] = addr & 0xff; 595 | buf[2] = (addr >> 8) & 0xff; 596 | buf[3] = Sync_CRC_EOP; 597 | 598 | stk500_send(buf, 4); 599 | 600 | if (stk500_recv(buf, 1) < 0) return -1; 601 | if (buf[0] == Resp_STK_NOSYNC) { 602 | if (tries > 33) { 603 | debug("stk500_loadaddr(): can't get into sync\n"); 604 | return -1; 605 | } 606 | if (stk500_getsync() < 0) return -1; 607 | goto retry; 608 | } else if (buf[0] != Resp_STK_INSYNC) { 609 | debug( 610 | "stk500_loadaddr(): (a) protocol error, expect=0x%02x, " 611 | "resp=0x%02x\n", 612 | Resp_STK_INSYNC, buf[0]); 613 | return -1; 614 | } 615 | 616 | if (stk500_recv(buf, 1) < 0) return -1; 617 | if (buf[0] == Resp_STK_OK) { 618 | return 0; 619 | } 620 | 621 | debug("loadaddr(): (b) protocol error, expect=0x%02x, resp=0x%02x\n", 622 | Resp_STK_INSYNC, buf[0]); 623 | 624 | return -1; 625 | } 626 | 627 | static int stk500_paged_write(unsigned int addr, unsigned int n_bytes, 628 | unsigned char *data) { 629 | unsigned char buf[16]; 630 | 631 | int a_div; 632 | int block_size; 633 | int tries; 634 | unsigned int n; 635 | 636 | a_div = 2; 637 | block_size = 128; 638 | 639 | n = addr + n_bytes; 640 | 641 | for (; addr < n; addr += block_size) { 642 | tries = 0; 643 | retry: 644 | tries++; 645 | stk500_loadaddr(addr / a_div); 646 | stk500_send(Cmnd_STK_PROG_PAGE); 647 | stk500_send((block_size >> 8) & 0xff); 648 | stk500_send(block_size & 0xff); 649 | stk500_send('F'); 650 | stk500_send(data, block_size); 651 | stk500_send(Sync_CRC_EOP); 652 | data += block_size; 653 | if (stk500_recv(buf, 1) < 0) return -1; 654 | if (buf[0] == Resp_STK_NOSYNC) { 655 | if (tries > 33) { 656 | debug("stk500_paged_write(): can't get into sync\n"); 657 | return -3; 658 | } 659 | if (stk500_getsync() < 0) return -1; 660 | goto retry; 661 | } else if (buf[0] != Resp_STK_INSYNC) { 662 | debug( 663 | "stk500_paged_write(): (a) protocol error, expect=0x%02x, " 664 | "resp=0x%02x\n", 665 | Resp_STK_INSYNC, buf[0]); 666 | return -4; 667 | } 668 | 669 | if (stk500_recv(buf, 1) < 0) return -1; 670 | if (buf[0] != Resp_STK_OK) { 671 | debug( 672 | "stk500_paged_write(): (a) protocol error, expect=0x%02x, " 673 | "resp=0x%02x\n", 674 | Resp_STK_INSYNC, buf[0]); 675 | return -5; 676 | } 677 | } 678 | return n_bytes; 679 | } 680 | 681 | static int stk500_paged_load(unsigned int addr, unsigned int n_bytes, 682 | unsigned char *data) { 683 | unsigned char buf[16]; 684 | int a_div; 685 | int tries; 686 | unsigned int n; 687 | int block_size; 688 | 689 | a_div = 2; 690 | block_size = 128; 691 | 692 | n = addr + n_bytes; 693 | for (; addr < n; addr += block_size) { 694 | tries = 0; 695 | retry: 696 | tries++; 697 | stk500_loadaddr(addr / a_div); 698 | stk500_send(Cmnd_STK_READ_PAGE); 699 | stk500_send((block_size >> 8) & 0xff); 700 | stk500_send(block_size & 0xff); 701 | stk500_send('F'); 702 | stk500_send(Sync_CRC_EOP); 703 | 704 | if (stk500_recv(buf, 1) < 0) return -1; 705 | if (buf[0] == Resp_STK_NOSYNC) { 706 | if (tries > 33) { 707 | debug("stk500_paged_load(): can't get into sync\n"); 708 | return -3; 709 | } 710 | if (stk500_getsync() < 0) return -1; 711 | goto retry; 712 | } else if (buf[0] != Resp_STK_INSYNC) { 713 | debug( 714 | "stk500_paged_load(): (a) protocol error, " 715 | "expect=0x%02x, resp=0x%02x\n", 716 | Resp_STK_INSYNC, buf[0]); 717 | return -4; 718 | } 719 | 720 | if (stk500_recv(data, block_size) < 0) return -1; 721 | data += block_size; 722 | if (stk500_recv(buf, 1) < 0) return -1; 723 | 724 | if (buf[0] != Resp_STK_OK) { 725 | debug( 726 | "stk500_paged_load(): (a) protocol error, expect=0x%02x, " 727 | "resp=0x%02x\n", 728 | Resp_STK_OK, buf[0]); 729 | return -5; 730 | } 731 | } 732 | return n_bytes; 733 | } 734 | 735 | int pageCheck(int curAddress) { 736 | int page = address / sizeof(write_page_buff); 737 | int curpage = curAddress / sizeof(write_page_buff); 738 | if (page != curpage) { 739 | if (dity) { 740 | debug("write page:%04X\n", page * sizeof(write_page_buff)); 741 | int wb = 742 | stk500_paged_write(page * sizeof(write_page_buff), 743 | sizeof(write_page_buff), write_page_buff); 744 | if (wb != sizeof(write_page_buff)) return -1; 745 | int rb = stk500_paged_load(page * sizeof(write_page_buff), 746 | sizeof(read_page_buff), read_page_buff); 747 | if (rb != sizeof(write_page_buff)) return -1; 748 | int err = 0; 749 | for (unsigned int ck = 0; ck < sizeof(write_page_buff); ck++) 750 | if (read_page_buff[ck] != write_page_buff[ck]) err++; 751 | if (err) return -1; 752 | } 753 | address = curAddress; 754 | memset(read_page_buff, 0xff, sizeof(read_page_buff)); 755 | memset(write_page_buff, 0xff, sizeof(write_page_buff)); 756 | dity = 0; 757 | } 758 | return 0; 759 | } 760 | 761 | int entryBootloader() { 762 | Serial.begin(econfig.bardrate_isp); 763 | resetTarget(); 764 | delay(500); 765 | int i = 0; 766 | while (1) { 767 | while (Serial.available()) Serial.read(); 768 | Serial.write(0x30); 769 | Serial.write(0x20); 770 | delay(10); 771 | i++; 772 | if (i > 500 / 10) { 773 | return 0; 774 | } 775 | if (Serial.available() > 1) { 776 | if (Serial.read() != 0x14) continue; 777 | if (Serial.read() != 0x10) continue; 778 | return 1; 779 | } 780 | } 781 | } 782 | 783 | int sigleRecord(uint8_t *data, int len) { 784 | uint8_t cs = 0; 785 | uint8_t recsize = ctoh(*data++); 786 | recsize <<= 4; 787 | recsize |= ctoh(*data++); 788 | cs = recsize; 789 | 790 | if ((recsize * 2 + (1 + 2 + 1 + 1) * 2) != len) return -1; 791 | 792 | uint16_t addr = ctoh(*data++); 793 | addr <<= 4; 794 | addr |= ctoh(*data++); 795 | cs += (uint8_t)addr; 796 | 797 | addr <<= 4; 798 | addr |= ctoh(*data++); 799 | addr <<= 4; 800 | addr |= ctoh(*data++); 801 | cs += (uint8_t)(addr & 0xff); 802 | 803 | uint8_t rectype = ctoh(*data++); 804 | rectype <<= 4; 805 | rectype |= ctoh(*data++); 806 | cs += rectype; 807 | debug("addr:%04X :", addr); 808 | uint8_t *phexdata = data; 809 | for (int i = 0; i < recsize; i++) { 810 | uint8_t d = ctoh(*data++); 811 | d <<= 4; 812 | d |= ctoh(*data++); 813 | cs += d; 814 | phexdata[i] = d; 815 | } 816 | uint8_t csd = ctoh(*data++); 817 | csd <<= 4; 818 | csd |= ctoh(*data++); 819 | cs += csd; 820 | if (cs) return -3; 821 | 822 | switch (rectype) { 823 | case 0: 824 | for (int i = 0; i < recsize; i++) { 825 | if (pageCheck(baseaddr + addr + i)) return -2; 826 | write_page_buff[(baseaddr + addr + i) % 827 | sizeof(write_page_buff)] = phexdata[i]; 828 | } 829 | debug("\n"); 830 | if (recsize) dity = 1; 831 | total_write += recsize; 832 | break; 833 | case 1: 834 | if (pageCheck(address + sizeof(write_page_buff))) return -1; 835 | break; 836 | case 2: 837 | baseaddr = (phexdata[0] << 8 | phexdata[1]) << 4; 838 | return 0; 839 | case 3: 840 | return 0; 841 | case 4: 842 | baseaddr = (phexdata[0] << 8 | phexdata[1]) << 16; 843 | return 0; 844 | case 5: 845 | return 0; 846 | default: 847 | return rectype; 848 | break; 849 | } 850 | return rectype; 851 | } 852 | 853 | uint8_t lineBuff[128]; 854 | int handleHex(WiFiClient client, int hexlen) { 855 | while (client.connected() && client.available() == 0) { 856 | delay(1); 857 | } 858 | if (client.read() != ':') return 0; 859 | int totalLen = 0; 860 | address = -1; 861 | baseaddr = 0; 862 | dity = 0; 863 | total_write = 0; 864 | memset(read_page_buff, 0xff, sizeof(read_page_buff)); 865 | memset(write_page_buff, 0xff, sizeof(write_page_buff)); 866 | if (!entryBootloader()) 867 | if (!entryBootloader()) 868 | if (!entryBootloader()) return -1; 869 | while (client.connected()) { 870 | ArduinoOTA.handle(); 871 | if (avrOTA.hasClient()) break; 872 | int rl = client.readBytesUntil( 873 | ':', lineBuff, 874 | min((int)sizeof(lineBuff) - 1, hexlen - totalLen - 1)); 875 | int dlen = rl; 876 | if (dlen < 10) break; 877 | if (lineBuff[rl - 1] == '\n') dlen--; 878 | if (lineBuff[rl - 2] == '\r') dlen--; 879 | if (dlen < 10) break; 880 | if (dlen & 1) break; 881 | totalLen += rl + 1; 882 | if (sigleRecord(lineBuff, dlen)) break; 883 | } 884 | return totalLen; 885 | } 886 | --------------------------------------------------------------------------------