Skip to content

Commit 0278ad0

Browse files
grownseedthinkyhead
authored andcommitted
Add ESP32 WiFi interface (MarlinFirmware#11209)
1 parent c03df89 commit 0278ad0

File tree

93 files changed

+915
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+915
-22
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ env:
2323
#- TEST_PLATFORM="STM32F1"
2424
- TEST_PLATFORM="teensy35"
2525
- TEST_PLATFORM="linux_native"
26+
- TEST_PLATFORM="esp32"
2627

2728
addons:
2829
apt:

Marlin/Configuration_adv.h

+2
Original file line numberDiff line numberDiff line change
@@ -2228,6 +2228,8 @@
22282228
#if ENABLED(WIFISUPPORT)
22292229
#define WIFI_SSID "Wifi SSID"
22302230
#define WIFI_PWD "Wifi Password"
2231+
//#define WEBSUPPORT // Start a webserver with auto-discovery
2232+
//#define OTASUPPORT // Support over-the-air firmware updates
22312233
#endif
22322234

22332235
/**

Marlin/src/HAL/HAL_ESP32/HAL.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@
3434
#include "../../inc/MarlinConfigPre.h"
3535

3636
#if ENABLED(WIFISUPPORT)
37-
#include "ota.h"
37+
#include <ESPAsyncWebServer.h>
38+
#include "wifi.h"
39+
#if ENABLED(OTASUPPORT)
40+
#include "ota.h"
41+
#endif
42+
#if ENABLED(WEBSUPPORT)
43+
#include "web.h"
44+
#endif
3845
#endif
3946

4047
// --------------------------------------------------------------------------
@@ -83,14 +90,21 @@ esp_adc_cal_characteristics_t characteristics;
8390

8491
void HAL_init(void) {
8592
#if ENABLED(WIFISUPPORT)
86-
OTA_init();
93+
wifi_init();
94+
#if ENABLED(OTASUPPORT)
95+
OTA_init();
96+
#endif
97+
#if ENABLED(WEBSUPPORT)
98+
web_init();
99+
#endif
100+
server.begin();
87101
#endif
88102

89103
i2s_init();
90104
}
91105

92106
void HAL_idletask(void) {
93-
#if ENABLED(WIFISUPPORT)
107+
#if ENABLED(OTASUPPORT)
94108
OTA_handle();
95109
#endif
96110
}

Marlin/src/HAL/HAL_ESP32/HAL.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,17 @@
4747

4848
#include "HAL_timers_ESP32.h"
4949

50+
#include "WebSocketSerial.h"
51+
5052
// --------------------------------------------------------------------------
5153
// Defines
5254
// --------------------------------------------------------------------------
5355

5456
extern portMUX_TYPE spinlock;
5557

56-
#define NUM_SERIAL 1
58+
#define NUM_SERIAL 2
5759
#define MYSERIAL0 Serial
60+
#define MYSERIAL1 webSocketSerial
5861

5962
#define CRITICAL_SECTION_START portENTER_CRITICAL(&spinlock)
6063
#define CRITICAL_SECTION_END portEXIT_CRITICAL(&spinlock)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/**
2+
* Marlin 3D Printer Firmware
3+
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4+
*
5+
* Based on Sprinter and grbl.
6+
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
#ifdef ARDUINO_ARCH_ESP32
23+
24+
#include "../../inc/MarlinConfig.h"
25+
26+
#if ENABLED(WIFISUPPORT)
27+
28+
#include "WebSocketSerial.h"
29+
#include "wifi.h"
30+
31+
#include <AsyncTCP.h>
32+
#include <ESPAsyncWebServer.h>
33+
34+
struct ring_buffer_r {
35+
unsigned char buffer[RX_BUFFER_SIZE];
36+
volatile ring_buffer_pos_t head, tail;
37+
};
38+
39+
struct ring_buffer_t {
40+
unsigned char buffer[256];
41+
volatile uint8_t head, tail;
42+
};
43+
44+
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
45+
ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
46+
47+
static bool _written;
48+
49+
#if ENABLED(EMERGENCY_PARSER)
50+
static EmergencyParser::State emergency_state; // = EP_RESET
51+
#endif
52+
53+
AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws
54+
55+
FORCE_INLINE int next_rx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1); }
56+
FORCE_INLINE int next_tx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(TX_BUFFER_SIZE - 1); }
57+
58+
static void addToBuffer(uint8_t * const data, const size_t len) {
59+
for (size_t i = 0; i < len; i++) {
60+
ring_buffer_pos_t h = rx_buffer.head;
61+
const ring_buffer_pos_t t = rx_buffer.tail, n = next_rx_index(h);
62+
63+
if (n != t) { rx_buffer.buffer[h] = data[i]; h = n; }
64+
65+
// TODO: buffer is full, handle?
66+
67+
rx_buffer.head = h;
68+
}
69+
}
70+
71+
// Handle WebSocket event
72+
static void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
73+
switch (type) {
74+
case WS_EVT_CONNECT: client->ping(); break; // client connected
75+
case WS_EVT_DISCONNECT: // client disconnected
76+
case WS_EVT_ERROR: // error was received from the other end
77+
case WS_EVT_PONG: break; // pong message was received (in response to a ping request maybe)
78+
case WS_EVT_DATA: { // data packet
79+
AwsFrameInfo * info = (AwsFrameInfo*)arg;
80+
if (info->opcode == WS_TEXT || info->message_opcode == WS_TEXT)
81+
addToBuffer(data, len);
82+
}
83+
}
84+
}
85+
86+
// Public Methods
87+
void WebSocketSerial::begin(const long baud_setting) {
88+
ws.onEvent(onEvent);
89+
server.addHandler(&ws); // attach AsyncWebSocket
90+
}
91+
92+
void WebSocketSerial::end() { }
93+
94+
int WebSocketSerial::peek(void) {
95+
const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
96+
return v;
97+
}
98+
99+
int WebSocketSerial::read(void) {
100+
const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
101+
if (h == t) return -1; // Nothing to read? Return now
102+
103+
const int v = rx_buffer.buffer[t];
104+
105+
rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1); // Advance tail
106+
107+
return v;
108+
}
109+
110+
bool WebSocketSerial::available(void) {
111+
const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
112+
return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
113+
}
114+
115+
void WebSocketSerial::flush(void) {
116+
ws.textAll("flush");
117+
rx_buffer.tail = rx_buffer.head;
118+
}
119+
120+
#if TX_BUFFER_SIZE
121+
122+
void WebSocketSerial::write(const uint8_t c) {
123+
_written = true;
124+
125+
const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
126+
127+
// Store new char. head is always safe to move
128+
tx_buffer.buffer[tx_buffer.head] = c;
129+
tx_buffer.head = i;
130+
131+
if (c == '\n') {
132+
ws.textAll(tx_buffer.buffer, tx_buffer.head);
133+
tx_buffer.head = 0;
134+
}
135+
}
136+
137+
void WebSocketSerial::flushTx(void) {
138+
ws.textAll("flushTx");
139+
if (!_written) return;
140+
}
141+
142+
#else
143+
144+
//void WebSocketSerial::write(const uint8_t c) { _written = true; }
145+
//void WebSocketSerial::flushTx(void) { if (!_written) return; }
146+
147+
#endif
148+
149+
/**
150+
* Imports from print.h
151+
*/
152+
153+
void WebSocketSerial::print(char c, int base) { print((long)c, base); }
154+
void WebSocketSerial::print(unsigned char b, int base) { print((unsigned long)b, base); }
155+
void WebSocketSerial::print(int n, int base) { print((long)n, base); }
156+
void WebSocketSerial::print(unsigned int n, int base) { print((unsigned long)n, base); }
157+
void WebSocketSerial::print(long n, int base) {
158+
if (base == 0)
159+
write(n);
160+
else if (base == 10) {
161+
if (n < 0) { print('-'); n = -n; }
162+
printNumber(n, 10);
163+
}
164+
else
165+
printNumber(n, base);
166+
}
167+
168+
void WebSocketSerial::print(unsigned long n, int base) {
169+
if (base == 0) write(n); else printNumber(n, base);
170+
}
171+
172+
void WebSocketSerial::print(double n, int digits) { printFloat(n, digits); }
173+
174+
void WebSocketSerial::println(void) { print('\r'); print('\n'); }
175+
void WebSocketSerial::println(const String& s) { print(s); println(); }
176+
void WebSocketSerial::println(const char c[]) { print(c); println(); }
177+
void WebSocketSerial::println(char c, int base) { print(c, base); println(); }
178+
void WebSocketSerial::println(unsigned char b, int base) { print(b, base); println(); }
179+
void WebSocketSerial::println(int n, int base) { print(n, base); println(); }
180+
void WebSocketSerial::println(unsigned int n, int base) { print(n, base); println(); }
181+
void WebSocketSerial::println(long n, int base) { print(n, base); println(); }
182+
void WebSocketSerial::println(unsigned long n, int base) { print(n, base); println(); }
183+
void WebSocketSerial::println(double n, int digits) { print(n, digits); println(); }
184+
185+
// Private Methods
186+
187+
void WebSocketSerial::printNumber(unsigned long n, uint8_t base) {
188+
if (n) {
189+
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
190+
int8_t i = 0;
191+
while (n) {
192+
buf[i++] = n % base;
193+
n /= base;
194+
}
195+
while (i--)
196+
print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
197+
}
198+
else
199+
print('0');
200+
}
201+
202+
void WebSocketSerial::printFloat(double number, uint8_t digits) {
203+
// Handle negative numbers
204+
if (number < 0.0) { print('-'); number = -number; }
205+
206+
// Round correctly so that print(1.999, 2) prints as "2.00"
207+
// Use a lookup table for performance
208+
constexpr double rounds[] = { 0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005 };
209+
number += rounds[digits];
210+
211+
//number += pow(10, -(digits + 1)); // slower single-line equivalent
212+
213+
// Extract the integer part of the number and print it
214+
unsigned long int_part = (unsigned long)number;
215+
print(int_part);
216+
217+
// Print the decimal point, but only if there are digits beyond
218+
double remainder = number - (double)int_part;
219+
if (digits) {
220+
print('.');
221+
// Extract digits from the remainder one at a time
222+
while (digits--) {
223+
remainder *= 10.0;
224+
const int toPrint = int(remainder);
225+
print(toPrint);
226+
remainder -= toPrint;
227+
}
228+
}
229+
}
230+
231+
#endif // WIFISUPPORT
232+
#endif // ARDUINO_ARCH_ESP32

0 commit comments

Comments
 (0)