···11# pkg_add makeesparduino
2233-# targeting the adafruit feather huzzah esp8266
44-BOARD = huzzah
55-63# default of -w supresses all warnings
74COMP_WARNINGS = -Wall -Wextra
85
-189
MCP23S18.cpp
···11-/*
22- * MCP23S18 16-bit I/O Expander
33- * Copyright (c) 2021 joshua stein <jcs@jcs.org>
44- *
55- * Permission to use, copy, modify, and distribute this software for any
66- * purpose with or without fee is hereby granted, provided that the above
77- * copyright notice and this permission notice appear in all copies.
88- *
99- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616- */
1717-1818-#include "MCP23S18.h"
1919-#include <SPI.h>
2020-2121-/*
2222- .---._.---.
2323- VSS | 1 28 | NC
2424- NC | 2 27 | GPA7
2525- GPB0 | 3 26 | GPA6
2626- GPB1 | 4 25 | GPA5
2727- GPB2 | 5 24 | GPA4
2828- GPB3 | 6 23 | GPA3
2929- GPB4 | 7 22 | GPA2
3030- GPB5 | 8 21 | GPA1
3131- GPB6 | 9 20 | GPA0
3232- GPB7 | 10 19 | INTA
3333- VDD | 11 18 | INTB
3434- CS | 12 17 | NC
3535- SCK | 13 16 | RESET
3636- MOSI | 14 15 | MISO
3737- `---------'
3838-*/
3939-4040-#define WRITE 0
4141-#define READ 1
4242-4343-void
4444-MCP23S18::begin(uint8_t _cs_pin)
4545-{
4646- cs_pin = _cs_pin;
4747- ::pinMode(cs_pin, OUTPUT);
4848- ::digitalWrite(cs_pin, HIGH);
4949-5050- SPI.begin();
5151-5252- /*
5353- * Disable Sequential Operation Mode and set BANK=1, but use the IOCON
5454- * register at the address it's at when in BANK=0 as it is at power-on
5555- */
5656- writeRegister(MCP23S18_IOCON_INIT,
5757- MCP23S18_IOCON_SEQOP | MCP23S18_IOCON_BANK);
5858-}
5959-6060-uint8_t
6161-MCP23S18::readGPIO(uint8_t bank_b)
6262-{
6363- return readRegister(MCP23S18_GPIO + (bank_b ? MCP23S18_BANKB : 0));
6464-}
6565-6666-void
6767-MCP23S18::writeGPIO(uint8_t bank_b, uint8_t val)
6868-{
6969- writeRegister(MCP23S18_GPIO + (bank_b ? MCP23S18_BANKB : 0), val);
7070-}
7171-7272-uint16_t
7373-MCP23S18::readGPIOAB(void)
7474-{
7575- return (readRegister(MCP23S18_BANKB + MCP23S18_GPIO) << 8) |
7676- readRegister(MCP23S18_GPIO);
7777-}
7878-7979-void
8080-MCP23S18::updateRegisterBit(uint8_t reg, uint8_t bit, bool set)
8181-{
8282- uint8_t val = readRegister(reg);
8383-8484- if (set)
8585- val |= (1 << bit);
8686- else
8787- val &= ~(1 << bit);
8888-8989- writeRegister(reg, val);
9090-}
9191-9292-void
9393-MCP23S18::pinMode(uint8_t pin, uint8_t dir)
9494-{
9595- updateRegisterBit(regForPin(MCP23S18_IODIR, pin), bitForPin(pin),
9696- dir == INPUT ? MCP23S18_IODIR_INPUT : MCP23S18_IODIR_OUTPUT);
9797-}
9898-9999-void
100100-MCP23S18::bankPinMode(uint8_t bank, uint8_t dir)
101101-{
102102- writeRegister(MCP23S18_IODIR + (bank ? MCP23S18_BANKB : 0),
103103- dir == OUTPUT ? 0 : 0xff);
104104-}
105105-106106-uint8_t
107107-MCP23S18::digitalRead(uint8_t pin)
108108-{
109109- uint8_t val = readRegister(regForPin(MCP23S18_GPIO, pin));
110110- return (val & (1 << bitForPin(pin))) ? HIGH : LOW;
111111-}
112112-113113-void
114114-MCP23S18::digitalWrite(uint8_t pin, uint8_t level)
115115-{
116116- uint8_t val = readRegister(regForPin(MCP23S18_OLAT, pin));
117117-118118- if (level == HIGH)
119119- val |= (1 << bitForPin(pin));
120120- else
121121- val &= ~(1 << bitForPin(pin));
122122-123123- writeRegister(regForPin(MCP23S18_OLAT, pin), val);
124124-}
125125-126126-void
127127-MCP23S18::pullUp(uint8_t pin, uint8_t level)
128128-{
129129- updateRegisterBit(regForPin(MCP23S18_GPPU, pin), bitForPin(pin),
130130- level == HIGH ? 1 : 0);
131131-}
132132-133133-void
134134-MCP23S18::bankPullUp(uint8_t bank, uint8_t level)
135135-{
136136- writeRegister(MCP23S18_GPPU + (bank ? MCP23S18_BANKB : 0),
137137- level == HIGH ? 0xff : 0);
138138-}
139139-140140-uint8_t
141141-MCP23S18::readRegister(uint8_t reg)
142142-{
143143- uint8_t val;
144144-145145- beginSend(READ);
146146- SPI.transfer(reg);
147147- val = SPI.transfer(0x0);
148148- endSend();
149149- return val;
150150-}
151151-152152-void
153153-MCP23S18::writeRegister(uint8_t reg, uint8_t b)
154154-{
155155- beginSend(WRITE);
156156- SPI.transfer(reg);
157157- SPI.transfer(b);
158158- endSend();
159159-}
160160-161161-void
162162-MCP23S18::beginSend(uint8_t mode)
163163-{
164164- /* 5Mhz */
165165- SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));
166166- ::digitalWrite(cs_pin, LOW);
167167-168168- /* 7-bit address is 0x20, shift in the read/write bit */
169169- SPI.transfer((0x20 << 1) | mode);
170170-}
171171-172172-void
173173-MCP23S18::endSend(void)
174174-{
175175- ::digitalWrite(cs_pin, HIGH);
176176- SPI.endTransaction();
177177-}
178178-179179-inline uint8_t
180180-MCP23S18::regForPin(uint8_t reg, uint8_t pin)
181181-{
182182- return reg + (pin > MCP23S18_BANKA_MAX_PIN ? MCP23S18_BANKB : 0);
183183-}
184184-185185-inline uint8_t
186186-MCP23S18::bitForPin(uint8_t pin)
187187-{
188188- return pin % 8;
189189-}
-81
MCP23S18.h
···11-/*
22- * MCP23S18 16-bit I/O Expander
33- * Copyright (c) 2021 joshua stein <jcs@jcs.org>
44- *
55- * Permission to use, copy, modify, and distribute this software for any
66- * purpose with or without fee is hereby granted, provided that the above
77- * copyright notice and this permission notice appear in all copies.
88- *
99- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616- */
1717-1818-#ifndef _MCP23S018_H_
1919-#define _MCP23S018_H_
2020-2121-#include <Arduino.h>
2222-#include <Wire.h>
2323-2424-class MCP23S18 {
2525-public:
2626- uint8_t cs_pin;
2727- uint16_t pin_states;
2828-2929- void begin(uint8_t _cs_pin);
3030-3131- uint8_t readGPIO(uint8_t bank_b);
3232- uint16_t readGPIOAB(void);
3333- void writeGPIO(uint8_t bank_b, uint8_t val);
3434-3535- uint8_t readRegister(uint8_t reg);
3636- void writeRegister(uint8_t addr, uint8_t b);
3737- void updateRegisterBit(uint8_t reg, uint8_t bit, bool set);
3838- void pinMode(uint8_t pin, uint8_t dir);
3939- void bankPinMode(uint8_t bank, uint8_t dir);
4040-4141- uint8_t digitalRead(uint8_t b);
4242- void digitalWrite(uint8_t pin, uint8_t level);
4343- void pullUp(uint8_t pin, uint8_t level);
4444- void bankPullUp(uint8_t bank, uint8_t level);
4545-4646-private:
4747- inline uint8_t regForPin(uint8_t reg, uint8_t pin);
4848- inline uint8_t bitForPin(uint8_t pin);
4949- void beginSend(uint8_t mode);
5050- void endSend(void);
5151-};
5252-5353-/* IOCON.BANK = 0 */
5454-#define MCP23S18_IOCON_INIT 0x0A
5555-5656-/* IOCON.BANK = 1 */
5757-#define MCP23S18_IODIR 0x00 /* I/O DIRECTION */
5858-#define MCP23S18_IODIR_OUTPUT 0x0
5959-#define MCP23S18_IODIR_INPUT 0x1
6060-#define MCP23S18_IPOL 0x01 /* INPUT POLARITY */
6161-#define MCP23S18_GPINTEN 0x02 /* INTERRUPT-ON-CHANGE CONTROL */
6262-#define MCP23S18_DEFVAL 0x03 /* DEFAULT COMPARE REGISTER FOR INTERRUPT-ON-CHANGE */
6363-#define MCP23S18_INTCON 0x04 /* INTERRUPT CONTROL */
6464-#define MCP23S18_IOCON 0x05 /* CONFIGURATION */
6565-#define MCP23S18_IOCON_INTCC (1 << 0) /* Interrupt Clearing Control */
6666-#define MCP23S18_IOCON_INTPOL (1 << 1) /* polarity of the INT output */
6767-#define MCP23S18_IOCON_ODR (1 << 2) /* INT pin as an open-drain output */
6868-#define MCP23S18_IOCON_SEQOP (1 << 5) /* Sequential Operation mode */
6969-#define MCP23S18_IOCON_MIRROR (1 << 6) /* INT pins mirror */
7070-#define MCP23S18_IOCON_BANK (1 << 7) /* how the registers are addressed */
7171-#define MCP23S18_GPPU 0x06 /* PULL-UP RESISTOR CONFIGURATION */
7272-#define MCP23S18_INTF 0x07 /* INTERRUPT FLAG */
7373-#define MCP23S18_INTCAP 0x08 /* INTERRUPT CAPTURE */
7474-#define MCP23S18_GPIO 0x09 /* PORT */
7575-#define MCP23S18_OLAT 0x0A /* OUTPUT LATCH */
7676-7777-#define MCP23S18_BANKA 0x00
7878-#define MCP23S18_BANKA_MAX_PIN 7
7979-#define MCP23S18_BANKB 0x10
8080-8181-#endif
-269
http.cpp
···11-/*
22- * WiFiStation
33- * Copyright (c) 2021 joshua stein <jcs@jcs.org>
44- *
55- * Permission to use, copy, modify, and distribute this software for any
66- * purpose with or without fee is hereby granted, provided that the above
77- * copyright notice and this permission notice appear in all copies.
88- *
99- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616- */
1717-1818-#include <ESP8266WebServer.h>
1919-#include "wifistation.h"
2020-2121-std::unique_ptr<ESP8266WebServer> http = NULL;
2222-2323-static const char html_wrapper[] PROGMEM = R"END(<!doctype html>
2424-<html>
2525-<head>
2626- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
2727- <title>WiFiStation at %s</title>
2828- <style type="text/css">
2929- body {
3030- background-color: #fffff8;
3131- font-family: sans-serif;
3232- font-size: 12pt;
3333- padding: 1em;
3434- }
3535- h3 {
3636- margin: 0;
3737- }
3838- </style>
3939-</head>
4040-<body>
4141-<h3>WiFiStation %s</h3>
4242-<p>
4343-%s
4444-</body>
4545-</html>
4646-)END";
4747-4848-static unsigned int upload_size = 0;
4949-static unsigned int delivered_bytes = 0;
5050-5151-void
5252-http_process(void)
5353-{
5454- if (!settings->http_server)
5555- return;
5656-5757- http->handleClient();
5858-}
5959-6060-void
6161-http_send_result(int status, bool include_home, const char *body, ...)
6262-{
6363- va_list arg;
6464- const char *accept = http->header("Accept").c_str();
6565- int len;
6666- char *doc = NULL;
6767-6868- /* expand body format */
6969- va_start(arg, body);
7070- len = vasprintf(&doc, body, arg);
7171- va_end(arg);
7272-7373- if (len == -1)
7474- goto fail;
7575-7676- /* if Accept header starts with text/html, client prefers html */
7777- if (accept && strncmp(accept, "text/html", 9) == 0) {
7878- char *tmp;
7979-8080- /* append home link to body */
8181- if (include_home) {
8282- len = asprintf(&tmp, "%s"
8383- "<p>"
8484- "<a href=\"/\">Home</a>", doc);
8585- if (len == -1)
8686- goto fail;
8787- free(doc);
8888- doc = tmp;
8989- }
9090-9191- /* insert body into html template */
9292- len = asprintf(&tmp, html_wrapper,
9393- WiFi.localIP().toString().c_str(), WIFISTATION_VERSION,
9494- doc);
9595- if (len == -1)
9696- goto fail;
9797- free(doc);
9898- doc = tmp;
9999-100100- http->send(status, "text/html", doc);
101101- } else {
102102- /* append newline since this is probably going to a terminal */
103103- doc = (char *)realloc(doc, len + 2);
104104- doc[len] = '\n';
105105- doc[len + 1] = '\0';
106106- http->send(status, "text/plain", doc);
107107- }
108108-109109- free(doc);
110110- return;
111111-112112-fail:
113113- if (doc != NULL)
114114- free(doc);
115115- http->send(500, "text/plain", "out of memory :(");
116116- return;
117117-}
118118-119119-void
120120-http_setup(void)
121121-{
122122- if (settings->http_server) {
123123- if (http)
124124- return;
125125-126126- http.reset(new ESP8266WebServer(80));
127127- } else {
128128- if (http)
129129- http = NULL;
130130-131131- return;
132132- }
133133-134134- http->collectHeaders(F("Accept"));
135135-136136- http->on("/", HTTP_GET, []() {
137137- http_send_result(200, false, R"END(
138138-<form action="/upload" method="POST" enctype="multipart/form-data">
139139-<p>
140140-Binary to execute on MailStation (<em>maximum size is %d bytes</em>):
141141-<p>
142142-<input type="file" name="file" maxlength="%d" size="%d">
143143-<br>
144144-<p>
145145-Ensure the WSLoader application is running on the MailStation ready to accept
146146-the upload.
147147-<p>
148148-<input type="submit" value="Upload">
149149-</form>
150150-)END",
151151- MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE);
152152- });
153153-154154- /*
155155- * This measure step is because we don't get the total size of the
156156- * upload until we read the whole thing, but we need to send the file
157157- * size to the MailStation before sending any data. So to avoid
158158- * caching the entire upload, we process the upload and just count the
159159- * bytes being passed through, then send a 307 redirect to the actual
160160- * upload endpoint with the total size. Browsers follow a 307 with a
161161- * POST, so at /upload we'll have the actual size before it sends us
162162- * the same data.
163163- */
164164- http->on("/upload", HTTP_POST, []() {
165165- http_send_result(400, true, "Failed receiving file.");
166166- }, []() {
167167- HTTPUpload& upload = http->upload();
168168- char tmp[32];
169169-170170- switch (upload.status) {
171171- case UPLOAD_FILE_START:
172172- upload_size = 0;
173173- break;
174174- case UPLOAD_FILE_WRITE:
175175- upload_size += upload.currentSize;
176176- break;
177177- case UPLOAD_FILE_ABORTED:
178178- upload_size = 0;
179179- /* FALLTHROUGH */
180180- case UPLOAD_FILE_END:
181181- if (upload_size == 0) {
182182- http_send_result(400, true,
183183- "Failed receiving file.");
184184- return;
185185- }
186186-187187- if (upload_size > MAX_UPLOAD_SIZE) {
188188- http_send_result(400, true,
189189- "File upload cannot be larger than %d "
190190- "bytes.", MAX_UPLOAD_SIZE);
191191- return;
192192- }
193193-194194- snprintf(tmp, sizeof(tmp), "/upload_measured?size=%d",
195195- upload_size);
196196- http->sendHeader("Location", tmp);
197197- http->send(307);
198198- break;
199199- }
200200- });
201201-202202- http->on("/upload_measured", HTTP_POST, []() {
203203- http_send_result(400, true, "Failed receiving file.");
204204- }, []() {
205205- HTTPUpload& upload = http->upload();
206206-207207- switch (upload.status) {
208208- case UPLOAD_FILE_START:
209209- delivered_bytes = 0;
210210-211211- if (!(upload_size = atoi(http->arg("size").c_str()))) {
212212- http_send_result(400, true, "No size "
213213- "parameter passed. Perhaps your browser "
214214- "failed to follow the 307 redirect "
215215- "properly.");
216216- return;
217217- }
218218-219219- if (upload_size > MAX_UPLOAD_SIZE) {
220220- http_send_result(400, true,
221221- "File upload cannot be larger than %d "
222222- "bytes.", MAX_UPLOAD_SIZE);
223223- return;
224224- }
225225-226226- if (ms_write(upload_size & 0xff) != 0 ||
227227- ms_write((upload_size >> 8) & 0xff) != 0) {
228228- http_send_result(400, true,
229229- "Failed sending size bytes "
230230- "(<tt>0x%x</tt>, <tt>0x%x</tt>) to "
231231- "MailStation. Is the WSLoader program "
232232- "running?",
233233- upload_size & 0xff,
234234- (upload_size >> 8) & 0xff);
235235- return;
236236- }
237237- break;
238238- case UPLOAD_FILE_WRITE:
239239- for (int i = 0; i < (int)upload.currentSize; i++) {
240240- delivered_bytes++;
241241- if (ms_write(upload.buf[i]) == -1) {
242242- http_send_result(400, true,
243243- "Failed uploading to MailStation "
244244- "at byte %d/%d.",
245245- delivered_bytes, upload_size);
246246- return;
247247- }
248248- yield();
249249- delayMicroseconds(500);
250250- }
251251- break;
252252- case UPLOAD_FILE_END:
253253- http_send_result(200, true,
254254- "Successfully uploaded %d byte%s to MailStation.",
255255- delivered_bytes, delivered_bytes == 1 ? "" : "s");
256256- return;
257257- case UPLOAD_FILE_ABORTED:
258258- http_send_result(400, true,
259259- "Aborted upload to MailStation.");
260260- return;
261261- }
262262- });
263263-264264- http->onNotFound([]() {
265265- http_send_result(404, true, "404");
266266- });
267267-268268- http->begin();
269269-}
-246
mailstation.cpp
···11-/*
22- * WiFiStation
33- * Copyright (c) 2021 joshua stein <jcs@jcs.org>
44- *
55- * Permission to use, copy, modify, and distribute this software for any
66- * purpose with or without fee is hereby granted, provided that the above
77- * copyright notice and this permission notice appear in all copies.
88- *
99- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1010- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1111- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1212- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1313- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1414- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616- */
1717-1818-#include "MCP23S18.h"
1919-#include "wifistation.h"
2020-2121-/* millis to consider a read/write timed out */
2222-#define MAILSTATION_TIMEOUT 2500
2323-2424-/*
2525- * ESP8266 default SPI pins:
2626- *
2727- * GPIO 12: MISO
2828- * GPIO 13: MOSI
2929- * GPIO 14: SCK
3030- *
3131- * Custom pins will be:
3232- * GPIO 4: CS
3333- * GPIO 16: Reset
3434- */
3535-3636-#define GPIO_CS 4
3737-#define GPIO_RESET 16
3838-3939-/* these are pins on the MCP23S18 */
4040-const int pData0 = 0;
4141-const int pData1 = 1;
4242-const int pData2 = 2;
4343-const int pData3 = 3;
4444-const int pData4 = 4;
4545-const int pData5 = 5;
4646-const int pData6 = 6;
4747-const int pData7 = 7;
4848-4949-const int pBusy = 8; /* input from mailstation pin 1 (strobe) */
5050-const int pAck = 9; /* input from mailstation pin 14 (linefeed) */
5151-5252-const int pLineFeed = 10; /* output to mailstation pin 10 (ack) */
5353-const int pStrobe = 11; /* output to mailstation pin 11 (busy) */
5454-5555-MCP23S18 mcp;
5656-5757-/* cache data pin direction */
5858-int data_mode = -1;
5959-6060-void
6161-ms_init(void)
6262-{
6363- /* reset the MCP23S18 */
6464- pinMode(GPIO_RESET, OUTPUT);
6565- digitalWrite(GPIO_RESET, LOW);
6666- delay(100);
6767- digitalWrite(GPIO_RESET, HIGH);
6868- delay(100);
6969-7070- mcp.begin(GPIO_CS);
7171-7272- /* data lines will flip between input/output, start in output mode */
7373- ms_datadir(OUTPUT);
7474-7575- /* strobe (control) */
7676- mcp.pinMode(pStrobe, OUTPUT);
7777- mcp.pullUp(pStrobe, HIGH);
7878- mcp.digitalWrite(pStrobe, LOW);
7979-8080- /* linefeed (control) */
8181- mcp.pinMode(pLineFeed, OUTPUT);
8282- mcp.pullUp(pLineFeed, HIGH);
8383- mcp.digitalWrite(pLineFeed, LOW);
8484-8585- /* ack (status) */
8686- mcp.pinMode(pAck, INPUT);
8787- mcp.pullUp(pAck, LOW);
8888-8989- /* busy (status) */
9090- mcp.pinMode(pBusy, INPUT);
9191- mcp.pullUp(pBusy, LOW);
9292-}
9393-9494-void
9595-ms_setup(void)
9696-{
9797- uint8_t iocon;
9898-9999- for (int i = 0; i < 10; i++) {
100100- ms_init();
101101- iocon = mcp.readRegister(MCP23S18_IOCON);
102102-103103- if (iocon == 0xff || iocon == 0x0) {
104104- error_flash();
105105- ms_init();
106106- } else
107107- break;
108108- }
109109-}
110110-111111-void
112112-ms_datadir(uint8_t which)
113113-{
114114- if (data_mode == which)
115115- return;
116116-117117- mcp.bankPinMode(0, which);
118118- mcp.bankPullUp(0, which == OUTPUT ? HIGH : LOW);
119119- data_mode = which;
120120-}
121121-122122-int
123123-ms_read(void)
124124-{
125125- unsigned long t;
126126- char c;
127127-128128- /* sender raises strobe (busy) to signal a write */
129129- if (mcp.digitalRead(pBusy) == LOW)
130130- return -1;
131131-132132- /* but when both lines are high, something's not right */
133133- if (mcp.digitalRead(pAck) == HIGH) {
134134- /*
135135- * Both pins will be raised during a reboot, so in that case
136136- * stop talking.
137137- */
138138- mailstation_alive = false;
139139- return -1;
140140- }
141141-142142- ms_datadir(INPUT);
143143-144144- /* raise linefeed (ack) to signal ready to receive */
145145- mcp.digitalWrite(pLineFeed, HIGH);
146146-147147- /* sender sees raised ack and writes data */
148148-149149- /* sender lowers strobe (busy) once data is ready */
150150- t = millis();
151151- while (mcp.digitalRead(pBusy) == HIGH) {
152152- if (millis() - t > MAILSTATION_TIMEOUT) {
153153- mcp.digitalWrite(pLineFeed, LOW);
154154- error_flash();
155155- return -1;
156156- }
157157- ESP.wdtFeed();
158158- }
159159-160160- c = mcp.readGPIO(0);
161161-162162- /* lower linefeed (ack) when we're done reading */
163163- mcp.digitalWrite(pLineFeed, LOW);
164164-165165- return c;
166166-}
167167-168168-uint16_t
169169-ms_status(void)
170170-{
171171- return mcp.readGPIOAB();
172172-}
173173-174174-int
175175-ms_write(char c)
176176-{
177177- unsigned long t;
178178-179179- ms_datadir(OUTPUT);
180180-181181- /* raise strobe (busy on receiver) to signal write */
182182- mcp.digitalWrite(pStrobe, HIGH);
183183-184184- /* wait for receiver to raise ack (linefeed on receiver) */
185185- t = millis();
186186- while (mcp.digitalRead(pAck) == LOW &&
187187- mcp.digitalRead(pLineFeed) == LOW) {
188188- if (millis() - t > MAILSTATION_TIMEOUT) {
189189- mcp.digitalWrite(pStrobe, LOW);
190190- error_flash();
191191- mailstation_alive = false;
192192- return -1;
193193- }
194194- ESP.wdtFeed();
195195- }
196196-197197- /* ack is high, write data */
198198- ms_writedata(c);
199199-200200- /* lower strobe (busy on receiver) to indicate we're done writing */
201201- mcp.digitalWrite(pStrobe, LOW);
202202-203203- /* wait for receiver to read and lower ack (busy on their end) */
204204- t = millis();
205205- while (mcp.digitalRead(pAck) == HIGH) {
206206- if (millis() - t > MAILSTATION_TIMEOUT) {
207207- error_flash();
208208- return -1;
209209- }
210210- ESP.wdtFeed();
211211- }
212212-213213- return 0;
214214-}
215215-216216-int
217217-ms_print(String str)
218218-{
219219- size_t len = str.length();
220220- int ret;
221221-222222- for (size_t i = 0; i < len; i++)
223223- if ((ret = ms_write(str.charAt(i))) != 0)
224224- return ret;
225225-226226- return 0;
227227-}
228228-229229-int
230230-ms_print(char *string)
231231-{
232232- size_t len = strlen(string);
233233- int ret;
234234-235235- for (size_t i = 0; i < len; i++)
236236- if ((ret = ms_write(string[i])) != 0)
237237- return ret;
238238-239239- return 0;
240240-}
241241-242242-void
243243-ms_writedata(char c)
244244-{
245245- mcp.writeGPIO(0, c);
246246-}
+1-1
telnet.cpp
···1515 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616 */
17171818-#include "wifistation.h"
1818+#include "wifippp.h"
19192020WiFiClient telnet;
2121