1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

Merge branch 'esp8266' of https://github.com/esp8266/Arduino into esp8266

This commit is contained in:
Matt Jenkins
2015-05-12 20:39:05 +01:00
29 changed files with 1871 additions and 585 deletions

View File

@ -172,6 +172,7 @@ int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogReference(uint8_t mode);
void analogWrite(uint8_t, int);
void analogWriteFreq(uint32_t freq);
unsigned long millis(void);
unsigned long micros(void);

View File

@ -118,24 +118,14 @@ int uart_get_debug();
void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) {
// -------------- UART 0 --------------
uint32_t status = U0IS;
if(Serial.isRxEnabled()) {
if(status & (1 << UIFF)) {
while(true) {
int rx_count = (U0S >> USTXC) & 0xff;
if(!rx_count)
break;
while(rx_count--) {
char c = U0F & 0xff;
Serial._rx_complete_irq(c);
}
}
while(U0IS & (1 << UIFF)) {
Serial._rx_complete_irq((char)(U0F & 0xff));
U0IC = (1 << UIFF);
}
}
if(Serial.isTxEnabled()) {
if(status & (1 << UIFE)) {
if(U0IS & (1 << UIFE)) {
U0IC = (1 << UIFE);
Serial._tx_empty_irq();
}
@ -143,25 +133,14 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) {
// -------------- UART 1 --------------
status = U1IS;
if(Serial1.isRxEnabled()) {
if(status & (1 << UIFF)) {
while(true) {
int rx_count = (U1S >> USTXC) & 0xff;
if(!rx_count)
break;
while(rx_count--) {
char c = U1F & 0xff;
Serial1._rx_complete_irq(c);
}
}
while(U1IS & (1 << UIFF)) {
Serial1._rx_complete_irq((char)(U1F & 0xff));
U1IC = (1 << UIFF);
}
}
if(Serial1.isTxEnabled()) {
status = U1IS;
if(status & (1 << UIFE)) {
if(U1IS & (1 << UIFE)) {
U1IC = (1 << UIFE);
Serial1._tx_empty_irq();
}

View File

@ -30,6 +30,10 @@ void timer1_isr_handler(void *para){
if(timer1_user_cb) timer1_user_cb();
}
void timer1_isr_init(){
ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL);
}
void timer1_attachInterrupt(void (*userFunc)(void)) {
timer1_user_cb = userFunc;
ETS_FRC1_INTR_ENABLE();
@ -55,7 +59,3 @@ void timer1_disable(){
T1C = 0;
T1I = 0;
}
void timer1_isr_init(){
ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL);
}

View File

@ -75,6 +75,7 @@ void delayMicroseconds(unsigned int us) {
void init() {
initPins();
timer1_isr_init();
os_timer_setfn(&micros_overflow_timer, (os_timer_func_t*) &micros_overflow_tick, 0);
os_timer_arm(&micros_overflow_timer, 60000, REPEAT);
}

View File

@ -33,18 +33,19 @@ uint16_t pwm_steps[17];
uint8_t pwm_steps_len = 0;
uint32_t pwm_steps_mask[17];
int pwm_sort_asc(const void* a, const void* b){
return (*((uint16_t*)a) > *((uint16_t*)b)) - (*((uint16_t*)a) < *((uint16_t*)b));
}
int pwm_sort_array(uint16_t a[], uint16_t al){
qsort(a, al, sizeof(uint16_t), pwm_sort_asc);
int i;
int bl = 1;
for(i = 1; i < al; i++){
if(a[i] != a[i-1]) a[bl++] = a[i];
}
return bl;
uint16_t i, j;
for (i = 1; i < al; i++) {
uint16_t tmp = a[i];
for (j = i; j >= 1 && tmp < a[j-1]; j--)
a[j] = a[j-1];
a[j] = tmp;
}
int bl = 1;
for(i = 1; i < al; i++){
if(a[i] != a[i-1]) a[bl++] = a[i];
}
return bl;
}
uint32_t pwm_get_mask(uint16_t value){
@ -139,4 +140,10 @@ extern void __analogWrite(uint8_t pin, int value) {
}
}
extern void __analogWriteFreq(uint32_t freq){
pwm_freq = freq;
prep_pwm_steps();
}
extern void analogWrite(uint8_t pin, int val) __attribute__ ((weak, alias("__analogWrite")));
extern void analogWriteFreq(uint32_t freq) __attribute__ ((weak, alias("__analogWriteFreq")));

View File

@ -175,6 +175,9 @@ char* ICACHE_FLASH_ATTR strtok_r(char * str, const char * delimiters, char ** te
uint32_t size = 0;
if(str == NULL) {
if(temp == NULL) {
return NULL;
}
start = *temp;
} else {
start = str;
@ -184,6 +187,10 @@ char* ICACHE_FLASH_ATTR strtok_r(char * str, const char * delimiters, char ** te
return NULL;
}
if(delimiters == NULL) {
return NULL;
}
end = start;
while(1) {
@ -211,7 +218,9 @@ char* ICACHE_FLASH_ATTR strtok_r(char * str, const char * delimiters, char ** te
}
char* ICACHE_FLASH_ATTR strtok(char * str, const char * delimiters) {
return strtok_r(str, delimiters, NULL);
static char * ret = NULL;
ret = strtok_r(str, delimiters, &ret);
return ret;
}
int strcasecmp(const char * str1, const char * str2) {

View File

@ -69,6 +69,5 @@ void setup(void){
}
void loop(void){
mdns.update();
server.handleClient();
}

View File

@ -23,8 +23,10 @@
File extensions with more than 3 charecters are not supported by the SD Library
File Names longer than 8 charecters will be truncated by the SD library, so keep filenames shorter
index.htm is the default index (works on subfolders as well)
*/
upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
@ -32,8 +34,8 @@
#include <SPI.h>
#include <SD.h>
//do not go larger than 1460 bytes as that is the maximum that could fit in a packet
#define WWW_BUF_SIZE 1460
#define DBG_OUTPUT_PORT Serial
const char* ssid = "**********";
const char* password = "**********";
@ -45,31 +47,36 @@ ESP8266WebServer server(80);
static bool hasSD = false;
File uploadFile;
void handleFileUpload(){
if(server.uri() != "/upload") return;
HTTPUpload upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
Serial.print("Upload: START, filename:");
Serial.println(upload.filename);
if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str());
uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
} else if(upload.status == UPLOAD_FILE_WRITE){
Serial.print("Upload: WRITE, Bytes:");
Serial.println(upload.buflen);
if(uploadFile) uploadFile.write(upload.buf, upload.buflen);
} else if(upload.status == UPLOAD_FILE_END){
Serial.print("Upload: END, Size:");
Serial.println(upload.size);
if(uploadFile) uploadFile.close();
}
void returnOK(){
WiFiClient client = server.client();
String message = "HTTP/1.1 200 OK\r\n";
message += "Content-Type: text/plain\r\n";
message += "Connection: close\r\n";
message += "Access-Control-Allow-Origin: *\r\n";
message += "\r\n";
client.print(message);
message = 0;
client.stop();
}
void returnFail(String msg){
WiFiClient client = server.client();
String message = "HTTP/1.1 500 Fail\r\n";
message += "Content-Type: text/plain\r\n";
message += "Connection: close\r\n";
message += "Access-Control-Allow-Origin: *\r\n";
message += "\r\n";
message += msg;
message += "\r\n";
client.print(message);
message = 0;
client.stop();
}
bool loadFromSdCard(String path){
String dataType = "text/plain";
//handle default index
if(path.endsWith("/")) path += "index.htm";
//set proper Content-Type for the most common extensions
if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
else if(path.endsWith(".htm")) dataType = "text/html";
else if(path.endsWith(".css")) dataType = "text/css";
@ -82,121 +89,224 @@ bool loadFromSdCard(String path){
else if(path.endsWith(".pdf")) dataType = "application/pdf";
else if(path.endsWith(".zip")) dataType = "application/zip";
//Try to open the file
File dataFile = SD.open(path.c_str());
//if it's a folder, try to open the default index
if(dataFile && dataFile.isDirectory()){
if(dataFile.isDirectory()){
path += "/index.htm";
dataType = "text/html";
dataFile = SD.open(path.c_str());
}
//and finally if the file exists, stream the content to the client
if(server.hasArg("download")) dataType = "application/octet-stream";
if (dataFile) {
WiFiClient client = server.client();
//send the file headers
String head = "HTTP/1.1 200 OK\r\nContent-Type: ";
head += dataType;
head += "\r\nContent-Length: ";
head += dataFile.size();
head += "\r\nConnection: close";
head += "\r\nAccess-Control-Allow-Origin: *";
head += "\r\n\r\n";
client.print(head);
dataType = 0;
path = 0;
//partition the data packets to fit in a TCP packet (1460 bytes MAX)
uint8_t obuf[WWW_BUF_SIZE];
while (dataFile.available() > WWW_BUF_SIZE){
dataFile.read(obuf, WWW_BUF_SIZE);
if(client.write(obuf, WWW_BUF_SIZE) != WWW_BUF_SIZE){
Serial.println("Sent less data than expected!");
DBG_OUTPUT_PORT.println("Sent less data than expected!");
dataFile.close();
return true;
}
}
//stream the last data left (size is at most WWW_BUF_SIZE bytes)
uint16_t leftLen = dataFile.available();
dataFile.read(obuf, leftLen);
if(client.write(obuf, leftLen) != leftLen){
Serial.println("Sent less data than expected!");
DBG_OUTPUT_PORT.println("Sent less data than expected!");
dataFile.close();
return true;
}
dataFile.close();
client.stop();
return true;
}
return false;
}
void tryLoadFromSdCard(){
String message = "FileNotFound\n\n";
if(hasSD){
//try to load the URL from SD Card
if(loadFromSdCard(server.uri())) return;
void handleFileUpload(){
if(server.uri() != "/edit") return;
HTTPUpload upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str());
uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename);
} else if(upload.status == UPLOAD_FILE_WRITE){
if(uploadFile) uploadFile.write(upload.buf, upload.buflen);
DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.buflen);
} else if(upload.status == UPLOAD_FILE_END){
if(uploadFile) uploadFile.close();
DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.size);
}
}
void deleteRecursive(String path){
File file = SD.open((char *)path.c_str());
if(!file.isDirectory()){
file.close();
SD.remove((char *)path.c_str());
return;
}
file.rewindDirectory();
File entry;
String entryPath;
while(true) {
entry = file.openNextFile();
if (!entry) break;
entryPath = path + "/" +entry.name();
if(entry.isDirectory()){
entry.close();
deleteRecursive(entryPath);
} else {
entry.close();
SD.remove((char *)entryPath.c_str());
}
entryPath = 0;
yield();
}
SD.rmdir((char *)path.c_str());
path = 0;
file.close();
}
void handleDelete(){
if(server.args() == 0) return returnFail("BAD ARGS");
String path = server.arg(0);
if(path == "/" || !SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
deleteRecursive(path);
returnOK();
path = 0;
}
void handleCreate(){
if(server.args() == 0) return returnFail("BAD ARGS");
String path = server.arg(0);
if(path == "/" || SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
if(path.indexOf('.') > 0){
File file = SD.open((char *)path.c_str(), FILE_WRITE);
if(file){
file.write((const char *)0);
file.close();
}
} else {
message = "SDCARD Not Detected\n\n";
SD.mkdir((char *)path.c_str());
}
returnOK();
path = 0;
}
void printDirectory() {
if(!server.hasArg("dir")) return returnFail("BAD ARGS");
String path = server.arg("dir");
if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
File dir = SD.open((char *)path.c_str());
path = 0;
if(!dir.isDirectory()){
dir.close();
return returnFail("NOT DIR");
}
dir.rewindDirectory();
File entry;
WiFiClient client = server.client();
client.print("HTTP/1.1 200 OK\r\nContent-Type: text/json\r\n\r\n");
String output = "[";
while(true) {
entry = dir.openNextFile();
if (!entry) break;
if(output != "[") output += ',';
output += "{\"type\":\"";
output += (entry.isDirectory())?"dir":"file";
output += "\",\"name\":\"";
output += entry.name();
output += "\"";
output += "}";
entry.close();
if(output.length() > 1460){
client.write(output.substring(0, 1460).c_str(), 1460);
output = output.substring(1460);
}
}
dir.close();
output += "]";
client.write(output.c_str(), output.length());
client.stop();
output = 0;
}
void handleNotFound(){
if(hasSD && loadFromSdCard(server.uri())) return;
String message = "SDCARD Not Detected\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
DBG_OUTPUT_PORT.print(message);
}
void setup(void){
uint8_t i = 0;
Serial.begin(115200);
//setup WiFi
WiFi.begin(ssid, password);
Serial.print("\nConnecting to ");
Serial.println(ssid);
//wait for WiFi to connect
while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
//check if we have connected?
void setup(void){
DBG_OUTPUT_PORT.begin(115200);
DBG_OUTPUT_PORT.setDebugOutput(true);
DBG_OUTPUT_PORT.print("\n");
WiFi.begin(ssid, password);
DBG_OUTPUT_PORT.print("Connecting to ");
DBG_OUTPUT_PORT.println(ssid);
// Wait for connection
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) {//wait 10 seconds
delay(500);
}
if(i == 21){
Serial.print("Could not connect to");
Serial.println(ssid);
//stop execution and wait forever
DBG_OUTPUT_PORT.print("Could not connect to");
DBG_OUTPUT_PORT.println(ssid);
while(1) delay(500);
}
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
//start mDNS Server
DBG_OUTPUT_PORT.print("Connected! IP address: ");
DBG_OUTPUT_PORT.println(WiFi.localIP());
/*
if (mdns.begin(hostname, WiFi.localIP())) {
Serial.println("MDNS responder started");
Serial.print("You can now connect to http://");
Serial.print(hostname);
Serial.println(".local");
DBG_OUTPUT_PORT.println("MDNS responder started");
DBG_OUTPUT_PORT.print("You can now connect to http://");
DBG_OUTPUT_PORT.print(hostname);
DBG_OUTPUT_PORT.println(".local");
}
*/
//Attach handler
server.onNotFound(tryLoadFromSdCard);
//Attach Upload handler
server.on("/list", HTTP_GET, printDirectory);
server.on("/edit", HTTP_DELETE, handleDelete);
server.on("/edit", HTTP_PUT, handleCreate);
server.on("/edit", HTTP_POST, [](){ returnOK(); });
server.onNotFound(handleNotFound);
server.onFileUpload(handleFileUpload);
//Attach handler for the Upload location
server.on("/upload", HTTP_POST, [](){
WiFiClient client = server.client();
String message = "HTTP/1.1 200 OK\r\n";
message += "Content-Type: text/plain\r\n";
message += "Access-Control-Allow-Origin: *\r\n";
message += "\r\n";
client.print(message);
});
//start server
server.begin();
Serial.println("HTTP server started");
DBG_OUTPUT_PORT.println("HTTP server started");
//init SD Card
if (SD.begin(SS)){
Serial.println("SD Card initialized.");
DBG_OUTPUT_PORT.println("SD Card initialized.");
hasSD = true;
}
}
void loop(void){
mdns.update();
server.handleClient();
}
}

View File

@ -0,0 +1,670 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>SD Editor</title>
<style type="text/css" media="screen">
.contextMenu {
z-index: 300;
position: absolute;
left: 5px;
border: 1px solid #444;
background-color: #F5F5F5;
display: none;
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
font-size: 12px;
font-family: sans-serif;
font-weight:bold;
}
.contextMenu ul {
list-style: none;
top: 0;
left: 0;
margin: 0;
padding: 0;
}
.contextMenu li {
position: relative;
min-width: 60px;
cursor: pointer;
}
.contextMenu span {
color: #444;
display: inline-block;
padding: 6px;
}
.contextMenu li:hover { background: #444; }
.contextMenu li:hover span { color: #EEE; }
.css-treeview ul, .css-treeview li {
padding: 0;
margin: 0;
list-style: none;
}
.css-treeview input {
position: absolute;
opacity: 0;
}
.css-treeview {
font: normal 11px Verdana, Arial, Sans-serif;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
}
.css-treeview span {
color: #00f;
cursor: pointer;
}
.css-treeview span:hover {
text-decoration: underline;
}
.css-treeview input + label + ul {
margin: 0 0 0 22px;
}
.css-treeview input ~ ul {
display: none;
}
.css-treeview label, .css-treeview label::before {
cursor: pointer;
}
.css-treeview input:disabled + label {
cursor: default;
opacity: .6;
}
.css-treeview input:checked:not(:disabled) ~ ul {
display: block;
}
.css-treeview label, .css-treeview label::before {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
}
.css-treeview label, .css-treeview span, .css-treeview label::before {
display: inline-block;
height: 16px;
line-height: 16px;
vertical-align: middle;
}
.css-treeview label {
background-position: 18px 0;
}
.css-treeview label::before {
content: "";
width: 16px;
margin: 0 22px 0 0;
vertical-align: middle;
background-position: 0 -32px;
}
.css-treeview input:checked + label::before {
background-position: 0 -16px;
}
/* webkit adjacent element selector bugfix */
@media screen and (-webkit-min-device-pixel-ratio:0)
{
.css-treeview{
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
}
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
{
from {
padding: 0;
}
to {
padding: 0;
}
}
}
#uploader {
position: absolute;
top: 0;
right: 0;
left: 0;
height:28px;
line-height: 24px;
padding-left: 10px;
background-color: #444;
color:#EEE;
}
#tree {
position: absolute;
top: 28px;
bottom: 0;
left: 0;
width:200px;
padding: 8px;
}
#editor, #preview {
position: absolute;
top: 28px;
right: 0;
bottom: 0;
left: 200px;
}
#preview {
background-color: #EEE;
padding:5px;
}
</style>
<script>
function createFileUploader(element, tree, editor){
var xmlHttp;
var input = document.createElement("input");
input.type = "file";
input.multiple = false;
input.name = "data";
document.getElementById(element).appendChild(input);
var path = document.createElement("input");
path.id = "upload-path";
path.type = "text";
path.name = "path";
path.defaultValue = "/";
document.getElementById(element).appendChild(path);
var button = document.createElement("button");
button.innerHTML = 'Upload';
document.getElementById(element).appendChild(button);
var mkdir = document.createElement("button");
mkdir.innerHTML = 'MkDir';
document.getElementById(element).appendChild(mkdir);
var mkfile = document.createElement("button");
mkfile.innerHTML = 'MkFile';
document.getElementById(element).appendChild(mkfile);
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
else {
tree.refreshPath(path.value);
}
}
}
function createPath(p){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("path", p);
xmlHttp.open("PUT", "/edit");
xmlHttp.send(formData);
}
mkfile.onclick = function(e){
if(path.value.indexOf(".") === -1) return;
createPath(path.value);
editor.loadUrl(path.value);
};
mkdir.onclick = function(e){
if(path.value.length < 2) return;
var dir = path.value
if(dir.indexOf(".") !== -1){
if(dir.lastIndexOf("/") === 0) return;
dir = dir.substring(0, dir.lastIndexOf("/"));
}
createPath(dir);
};
button.onclick = function(e){
if(input.files.length === 0){
return;
}
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", input.files[0], path.value);
xmlHttp.open("POST", "/edit");
xmlHttp.send(formData);
}
input.onchange = function(e){
if(input.files.length === 0) return;
var filename = input.files[0].name;
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
var name = /(.*)\.[^.]+$/.exec(filename)[1];
if(typeof name !== undefined){
if(name.length > 8) name = name.substring(0, 8);
filename = name;
}
if(typeof ext !== undefined){
if(ext === "html") ext = "htm";
else if(ext === "jpeg") ext = "jpg";
filename = filename + "." + ext;
}
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
path.value = "/"+filename;
} else {
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
}
}
}
function createTree(element, editor){
var preview = document.getElementById("preview");
var treeRoot = document.createElement("div");
treeRoot.className = "css-treeview";
document.getElementById(element).appendChild(treeRoot);
function loadDownload(path){
document.getElementById('download-frame').src = path+"?download=true";
}
function loadPreview(path){
document.getElementById("editor").style.display = "none";
preview.style.display = "block";
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
}
function fillFolderMenu(el, path){
var list = document.createElement("ul");
el.appendChild(list);
var action = document.createElement("li");
list.appendChild(action);
var isChecked = document.getElementById(path).checked;
var expnd = document.createElement("li");
list.appendChild(expnd);
if(isChecked){
expnd.innerHTML = "<span>Collapse</span>";
expnd.onclick = function(e){
document.getElementById(path).checked = false;
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var refrsh = document.createElement("li");
list.appendChild(refrsh);
refrsh.innerHTML = "<span>Refresh</span>";
refrsh.onclick = function(e){
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
} else {
expnd.innerHTML = "<span>Expand</span>";
expnd.onclick = function(e){
document.getElementById(path).checked = true;
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
var upload = document.createElement("li");
list.appendChild(upload);
upload.innerHTML = "<span>Upload</span>";
upload.onclick = function(e){
var pathEl = document.getElementById("upload-path");
if(pathEl){
var subPath = pathEl.value;
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
}
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var delFile = document.createElement("li");
list.appendChild(delFile);
delFile.innerHTML = "<span>Delete</span>";
delFile.onclick = function(e){
httpDelete(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
function fillFileMenu(el, path){
var list = document.createElement("ul");
el.appendChild(list);
var action = document.createElement("li");
list.appendChild(action);
if(isTextFile(path)){
action.innerHTML = "<span>Edit</span>";
action.onclick = function(e){
editor.loadUrl(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
} else if(isImageFile(path)){
action.innerHTML = "<span>Preview</span>";
action.onclick = function(e){
loadPreview(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
var download = document.createElement("li");
list.appendChild(download);
download.innerHTML = "<span>Download</span>";
download.onclick = function(e){
loadDownload(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
var delFile = document.createElement("li");
list.appendChild(delFile);
delFile.innerHTML = "<span>Delete</span>";
delFile.onclick = function(e){
httpDelete(path);
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
};
}
function showContextMenu(e, path, isfile){
var divContext = document.createElement("div");
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
var left = event.clientX + scrollLeft;
var top = event.clientY + scrollTop;
divContext.className = 'contextMenu';
divContext.style.display = 'block';
divContext.style.left = left + 'px';
divContext.style.top = top + 'px';
if(isfile) fillFileMenu(divContext, path);
else fillFolderMenu(divContext, path);
document.body.appendChild(divContext);
var width = divContext.offsetWidth;
var height = divContext.offsetHeight;
divContext.onmouseout = function(e){
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
}
};
}
function createTreeLeaf(path, name, size){
var leaf = document.createElement("li");
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
var label = document.createElement("span");
label.innerText = name.toLowerCase();
leaf.appendChild(label);
leaf.onclick = function(e){
if(isTextFile(leaf.id)){
editor.loadUrl(leaf.id);
} else if(isImageFile(leaf.id)){
loadPreview(leaf.id);
}
};
leaf.oncontextmenu = function(e){
e.preventDefault();
e.stopPropagation();
showContextMenu(e, leaf.id, true);
};
return leaf;
}
function createTreeBranch(path, name, disabled){
var leaf = document.createElement("li");
var check = document.createElement("input");
check.type = "checkbox";
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
leaf.appendChild(check);
var label = document.createElement("label");
label.for = check.id;
label.innerText = name.toLowerCase();
leaf.appendChild(label);
check.onchange = function(e){
if(check.checked){
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, check.id);
}
};
label.onclick = function(e){
if(!check.checked){
check.checked = true;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, check.id);
} else {
check.checked = false;
}
};
leaf.oncontextmenu = function(e){
e.preventDefault();
e.stopPropagation();
showContextMenu(e, check.id, false);
}
return leaf;
}
function addList(parent, path, items){
var list = document.createElement("ul");
parent.appendChild(list);
var ll = items.length;
for(var i = 0; i < ll; i++){
var item = items[i];
var itemEl;
if(item.type === "file"){
itemEl = createTreeLeaf(path, item.name, item.size);
} else {
itemEl = createTreeBranch(path, item.name);
}
list.appendChild(itemEl);
}
}
function isTextFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt":
case "htm":
case "js":
case "c":
case "cpp":
case "css":
case "xml":
return true;
}
}
return false;
}
function isImageFile(path){
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
if(typeof ext !== undefined){
switch(ext){
case "png":
case "jpg":
case "gif":
return true;
}
}
return false;
}
this.refreshPath = function(path){
if(path.lastIndexOf('/') < 1){
path = '/';
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
} else {
path = path.substring(0, path.lastIndexOf('/'));
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
}
};
function delCb(path){
return function(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200){
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
} else {
if(path.lastIndexOf('/') < 1){
path = '/';
treeRoot.removeChild(treeRoot.childNodes[0]);
httpGet(treeRoot, "/");
} else {
path = path.substring(0, path.lastIndexOf('/'));
var leaf = document.getElementById(path).parentNode;
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
httpGet(leaf, path);
}
}
}
}
}
function httpDelete(filename){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = delCb(filename);
var formData = new FormData();
formData.append("path", filename);
xmlHttp.open("DELETE", "/edit");
xmlHttp.send(formData);
}
function getCb(parent, path){
return function(){
if (xmlHttp.readyState == 4){
//clear loading
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
}
}
}
function httpGet(parent, path){
xmlHttp = new XMLHttpRequest(parent, path);
xmlHttp.onreadystatechange = getCb(parent, path);
xmlHttp.open("GET", "/list?dir="+path, true);
xmlHttp.send(null);
//start loading
}
httpGet(treeRoot, "/");
return this;
}
function createEditor(element, file, lang, theme, type){
function getLangFromFilename(filename){
var lang = "plain";
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
if(typeof ext !== undefined){
switch(ext){
case "txt": lang = "plain"; break;
case "htm": lang = "html"; break;
case "js": lang = "javascript"; break;
case "c": lang = "c_cpp"; break;
case "cpp": lang = "c_cpp"; break;
case "css":
case "scss":
case "php":
case "html":
case "json":
case "xml":
lang = ext;
}
}
return lang;
}
if(typeof file === "undefined") file = "/index.htm";
if(typeof lang === "undefined"){
lang = getLangFromFilename(file);
}
if(typeof theme === "undefined") theme = "textmate";
if(typeof type === "undefined"){
type = "text/"+lang;
if(lang === "c_cpp") type = "text/plain";
}
var xmlHttp = null;
var editor = ace.edit(element);
//post
function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
}
}
function httpPost(filename, data, type){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpPostProcessRequest;
var formData = new FormData();
formData.append("data", new Blob([data], { type: type }), filename);
xmlHttp.open("POST", "/edit");
xmlHttp.send(formData);
}
//get
function httpGetProcessRequest(){
if (xmlHttp.readyState == 4){
document.getElementById("preview").style.display = "none";
document.getElementById("editor").style.display = "block";
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
else editor.setValue("");
editor.clearSelection();
}
}
function httpGet(theUrl){
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = httpGetProcessRequest;
xmlHttp.open("GET", theUrl, true);
xmlHttp.send(null);
}
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
editor.setTheme("ace/theme/"+theme);
editor.$blockScrolling = Infinity;
editor.getSession().setUseSoftTabs(true);
editor.getSession().setTabSize(2);
editor.setHighlightActiveLine(true);
editor.setShowPrintMargin(false);
editor.commands.addCommand({
name: 'saveCommand',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function(editor) {
httpPost(file, editor.getValue()+"", type);
},
readOnly: false
});
editor.commands.addCommand({
name: 'undoCommand',
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().undo(false);
},
readOnly: false
});
editor.commands.addCommand({
name: 'redoCommand',
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
exec: function(editor) {
editor.getSession().getUndoManager().redo(false);
},
readOnly: false
});
httpGet(file);
editor.loadUrl = function(filename){
file = filename;
lang = getLangFromFilename(file);
type = "text/"+lang;
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
httpGet(file);
}
return editor;
}
function onBodyLoad(){
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
var tree = createTree("tree", editor);
createFileUploader("uploader", tree, editor);
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
</head>
<body onload="onBodyLoad();">
<div id="uploader"></div>
<div id="tree"></div>
<div id="editor"></div>
<div id="preview" style="display:none;"></div>
<iframe id=download-frame style='display:none;'></iframe>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>ESP Index</title>
<style>
body {
background-color:black;
color:white;
}
</style>
<script type="text/javascript">
function onBodyLoad(){
console.log("we are loaded!!");
}
</script>
</head>
<body id="index" onload="onBodyLoad()">
<h1>ESP8266 Pin Functions</h1>
<img src="pins.png" />
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

View File

@ -152,7 +152,7 @@ void ESP8266WebServer::handleClient()
String formData;
//bellow is needed only when POST type request
if(method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH){
if(method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){
String boundaryStr;
String headerName;
String headerValue;
@ -391,7 +391,8 @@ void ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
line = client.readStringUntil('\r');
client.readStringUntil('\n');
if(line.startsWith("--"+boundary)) break;
argValue += line+"\n";
if(argValue.length() > 0) argValue += "\n";
argValue += line;
}
#ifdef DEBUG
DEBUG_OUTPUT.print("PostArg Value: ");
@ -441,8 +442,6 @@ readfile:
argByte = client.read();
if(argByte == 0x0A){
line = client.readStringUntil(0x0D);
client.readStringUntil(0x0A);
#ifdef DEBUG
DEBUG_OUTPUT.print("Write File: ");
DEBUG_OUTPUT.println(_currentUpload.buflen);
@ -450,7 +449,28 @@ readfile:
if(_fileUploadHandler) _fileUploadHandler();
_currentUpload.size += _currentUpload.buflen;
_currentUpload.buflen = 0;
if(line.startsWith("--"+boundary)){
argByte = client.read();
if((char)argByte != '-'){
//continue reading the file
_currentUpload.buf[_currentUpload.buflen++] = 0x0D;
_currentUpload.buf[_currentUpload.buflen++] = 0x0A;
goto readfile;
} else {
argByte = client.read();
if((char)argByte != '-'){
//continue reading the file
_currentUpload.buf[_currentUpload.buflen++] = 0x0D;
_currentUpload.buf[_currentUpload.buflen++] = 0x0A;
_currentUpload.buf[_currentUpload.buflen++] = (uint8_t)('-');
goto readfile;
}
}
uint8_t endBuf[boundary.length()];
client.readBytes(endBuf, boundary.length());
if(strstr((const char*)endBuf, (const char*)(boundary.c_str())) != NULL){
_currentUpload.status = UPLOAD_FILE_END;
#ifdef DEBUG
DEBUG_OUTPUT.print("End File: ");
@ -461,7 +481,9 @@ readfile:
DEBUG_OUTPUT.println(_currentUpload.size);
#endif
if(_fileUploadHandler) _fileUploadHandler();
if(line == ("--"+boundary+"--")){
line = client.readStringUntil(0x0D);
client.readStringUntil(0x0A);
if(line == "--"){
#ifdef DEBUG
DEBUG_OUTPUT.println("Done Parsing POST");
#endif
@ -471,10 +493,9 @@ readfile:
} else {
_currentUpload.buf[_currentUpload.buflen++] = 0x0D;
_currentUpload.buf[_currentUpload.buflen++] = 0x0A;
const char * lineChars = line.c_str();
uint32_t i = 0;
while(i < os_strlen(lineChars)){
_currentUpload.buf[_currentUpload.buflen++] = lineChars[i++];
while(i < boundary.length()){
_currentUpload.buf[_currentUpload.buflen++] = endBuf[i++];
if(_currentUpload.buflen == 1460){
#ifdef DEBUG
DEBUG_OUTPUT.println("Write File: 1460");

View File

@ -0,0 +1,90 @@
/*
WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the ESP8266WiFi library for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <ESP8266WiFi.h>
//how many clients should be able to telnet to this ESP8266
#define MAX_SRV_CLIENTS 1
const char* ssid = "**********";
const char* password = "**********";
WiFiServer server(21);
WiFiClient serverClients[MAX_SRV_CLIENTS];
void setup() {
Serial1.begin(115200);
WiFi.begin(ssid, password);
Serial1.print("\nConnecting to "); Serial1.println(ssid);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
if(i == 21){
Serial1.print("Could not connect to"); Serial1.println(ssid);
while(1) delay(500);
}
//start UART and the server
Serial.begin(115200);
server.begin();
server.setNoDelay(true);
Serial1.print("Ready! Use 'telnet ");
Serial1.print(WiFi.localIP());
Serial1.println(" 21' to connect");
}
void loop() {
uint8_t i;
//check if there are any new clients
if (server.hasClient()){
for(i = 0; i < MAX_SRV_CLIENTS; i++){
//find free/disconnected spot
if (!serverClients[i] || !serverClients[i].connected()){
if(serverClients[i]) serverClients[i].stop();
serverClients[i] = server.available();
Serial1.print("New client: "); Serial1.print(i);
continue;
}
}
//no free/disconnected spot so reject
WiFiClient serverClient = server.available();
serverClient.stop();
}
//check clients for data
for(i = 0; i < MAX_SRV_CLIENTS; i++){
if (serverClients[i] && serverClients[i].connected()){
if(serverClients[i].available()){
//get data from the telnet client and push it to the UART
while(serverClients[i].available()) Serial.write(serverClients[i].read());
}
}
}
//check UART for data
if(Serial.available()){
size_t len = Serial.available();
uint8_t sbuf[len];
Serial.readBytes(sbuf, len);
//push UART data to all connected telnet clients
for(i = 0; i < MAX_SRV_CLIENTS; i++){
if (serverClients[i] && serverClients[i].connected()){
serverClients[i].write(sbuf, len);
delay(1);
}
}
}
}

View File

@ -73,8 +73,24 @@ void WiFiServer::begin()
tcp_arg(listen_pcb, (void*) this);
}
void WiFiServer::setNoDelay(bool nodelay){
if(!_pcb) return;
if(nodelay) tcp_nagle_disable(_pcb);
else tcp_nagle_enable(_pcb);
}
bool WiFiServer::getNoDelay(){
if(!_pcb) return false;
return tcp_nagle_disabled(_pcb);
}
extern "C" uint32_t esp_micros_at_task_start();
bool WiFiServer::hasClient(){
if (_unclaimed) return true;
return false;
}
WiFiClient WiFiServer::available(byte* status)
{
static uint32_t lastPollTime = 0;

View File

@ -44,7 +44,10 @@ private:
public:
WiFiServer(uint16_t port);
WiFiClient available(uint8_t* status = NULL);
bool hasClient();
void begin();
void setNoDelay(bool nodelay);
bool getNoDelay();
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
uint8_t status();

View File

@ -21,7 +21,8 @@
*/
#define LWIP_INTERNAL
#include <functional>
extern "C"
{
#include "include/wl_definitions.h"
@ -168,7 +169,6 @@ int WiFiUDP::endPacket()
return 0;
_ctx->send();
_ctx->disconnect();
return 1;
}

View File

@ -39,7 +39,39 @@ class ClientContext {
tcp_sent(pcb, &_s_sent);
tcp_err(pcb, &_s_error);
}
err_t abort(){
if(_pcb) {
DEBUGV(":abort\r\n");
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_abort(_pcb);
_pcb = 0;
}
return ERR_ABRT;
}
err_t close(){
err_t err = ERR_OK;
if(_pcb) {
DEBUGV(":close\r\n");
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
err = tcp_close(_pcb);
if(err != ERR_OK) {
DEBUGV(":tc err %d\r\n", err);
tcp_abort(_pcb);
err = ERR_ABRT;
}
_pcb = 0;
}
return err;
}
~ClientContext() {
}
@ -58,26 +90,26 @@ class ClientContext {
}
void unref() {
err_t err;
DEBUGV(":ur %d\r\n", _refcnt);
if(--_refcnt == 0) {
flush();
if(_pcb) {
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
err = tcp_close(_pcb);
if(err != ERR_OK) {
DEBUGV(":tc err %d\r\n", err);
tcp_abort(_pcb);
}
_pcb = 0;
}
close();
if(_discard_cb) _discard_cb(_discard_cb_arg, this);
delete this;
}
}
void setNoDelay(bool nodelay){
if(!_pcb) return;
if(nodelay) tcp_nagle_disable(_pcb);
else tcp_nagle_enable(_pcb);
}
bool getNoDelay(){
if(!_pcb) return false;
return tcp_nagle_disabled(_pcb);
}
uint32_t getRemoteAddress() {
if(!_pcb) return 0;
@ -179,6 +211,13 @@ class ClientContext {
private:
err_t _sent(tcp_pcb* pcb, uint16_t len) {
DEBUGV(":sent %d\r\n", len);
_size_sent -= len;
if(_size_sent == 0 && _send_waiting) esp_schedule();
return ERR_OK;
}
void _consume(size_t size) {
ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size;
if(left > 0) {
@ -204,21 +243,8 @@ class ClientContext {
if(pb == 0) // connection closed
{
DEBUGV(":rcl\r\n");
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_err(pcb, NULL);
// int error = tcp_close(pcb);
// if (error != ERR_OK)
{
DEBUGV(":rcla\r\n");
tcp_abort(pcb);
_pcb = 0;
return ERR_ABRT;
}
_pcb = 0;
return ERR_OK;
DEBUGV(":rcla\r\n");
return abort();
}
if(_rx_buf) {
@ -231,27 +257,12 @@ class ClientContext {
_rx_buf = pb;
_rx_buf_offset = 0;
}
// tcp_recved(pcb, received);
// pbuf_free(pb);
return ERR_OK;
}
void _error(err_t err) {
DEBUGV(":er %d\r\n", err);
if(_pcb) {
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
err = tcp_close(_pcb);
if(err != ERR_OK) {
DEBUGV(":tc err %d\r\n", err);
tcp_abort(_pcb);
}
}
_pcb = 0;
close();
if(_size_sent && _send_waiting) {
esp_schedule();
}
@ -261,13 +272,6 @@ class ClientContext {
return ERR_OK;
}
err_t _sent(tcp_pcb* pcb, uint16_t len) {
DEBUGV(":sent %d\r\n", len);
_size_sent -= len;
if(_size_sent == 0 && _send_waiting) esp_schedule();
return ERR_OK;
}
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) {
return reinterpret_cast<ClientContext*>(arg)->_recv(tpcb, pb, err);
}

View File

@ -28,9 +28,13 @@ extern "C" void esp_schedule();
#define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN);
#define GET_UDP_HDR(pb) reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN);
class UdpContext
{
public:
typedef std::function<void(void)> rxhandler_t;
UdpContext()
: _pcb(0)
, _rx_buf(0)
@ -40,8 +44,11 @@ public:
, _tx_buf_head(0)
, _tx_buf_cur(0)
, _tx_buf_offset(0)
, _multicast_ttl(1)
, _dest_port(0)
{
_pcb = udp_new();
_dest_addr.addr = 0;
}
~UdpContext()
@ -79,8 +86,9 @@ public:
bool connect(ip_addr_t addr, uint16_t port)
{
err_t err = udp_connect(_pcb, &addr, port);
return err == ERR_OK;
_dest_addr = addr;
_dest_port = port;
return true;
}
bool listen(ip_addr_t addr, uint16_t port)
@ -107,7 +115,13 @@ public:
// newer versions of lwip have an additional field (mcast_ttl) for this purpose
// and a macro to set it instead of direct field access
// udp_set_multicast_ttl(_pcb, ttl);
_pcb->ttl = ttl;
_multicast_ttl = ttl;
}
// warning: handler is called from tcp stack context
// esp_yield and non-reentrant functions which depend on it will fail
void onRx(rxhandler_t handler) {
_on_rx = handler;
}
size_t getSize() const
@ -173,10 +187,10 @@ public:
return _rx_buf != 0;
}
char read()
int read()
{
if (!_rx_buf || _rx_buf->len == _rx_buf_offset)
return 0;
return -1;
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
_consume(1);
@ -190,7 +204,7 @@ public:
size_t max_size = _rx_buf->len - _rx_buf_offset;
size = (size < max_size) ? size : max_size;
DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset);
DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset);
os_memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, size);
_consume(size);
@ -257,10 +271,19 @@ public:
}
}
if (addr)
udp_sendto(_pcb, _tx_buf_head, addr, port);
else
udp_send(_pcb, _tx_buf_head);
if (!addr) {
addr = &_dest_addr;
port = _dest_port;
}
uint16_t old_ttl = _pcb->ttl;
if (ip_addr_ismulticast(addr)) {
_pcb->ttl = _multicast_ttl;
}
udp_sendto(_pcb, _tx_buf_head, addr, port);
_pcb->ttl = old_ttl;
for (pbuf* p = _tx_buf_head; p; p = p->next)
{
@ -281,7 +304,7 @@ private:
void _reserve(size_t size)
{
const size_t pbuf_unit_size = 1024;
const size_t pbuf_unit_size = 512;
if (!_tx_buf_head)
{
_tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
@ -317,16 +340,19 @@ private:
{
// there is some unread data
// chain the new pbuf to the existing one
DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
DEBUGV(":urch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
pbuf_cat(_rx_buf, pb);
}
else
{
DEBUGV(":rn %d\r\n", pb->tot_len);
DEBUGV(":urn %d\r\n", pb->tot_len);
_first_buf_taken = false;
_rx_buf = pb;
_rx_buf_offset = 0;
}
if (_on_rx) {
_on_rx();
}
}
@ -341,6 +367,11 @@ private:
int _refcnt;
udp_pcb* _pcb;
ip_addr_t _dest_addr;
uint16_t _dest_port;
uint16_t _multicast_ttl;
bool _first_buf_taken;
pbuf* _rx_buf;
size_t _rx_buf_offset;
@ -348,6 +379,8 @@ private:
pbuf* _tx_buf_head;
pbuf* _tx_buf_cur;
size_t _tx_buf_offset;
rxhandler_t _on_rx;
};

View File

@ -30,7 +30,27 @@ License (MIT license):
// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt
// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt
#define LWIP_INTERNAL
#include "ESP8266mDNS.h"
#include <functional>
extern "C"
{
#include "osapi.h"
#include "ets_sys.h"
}
#include "debug.h"
#include "WiFiUdp.h"
#include "lwip/opt.h"
#include "lwip/udp.h"
#include "lwip/inet.h"
#include "lwip/igmp.h"
#include "lwip/mem.h"
#include "include/UdpContext.h"
// #define MDNS_DEBUG
@ -42,6 +62,10 @@ License (MIT license):
#define TTL_OFFSET 4
#define IP_OFFSET 10
static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251);
static const int MDNS_MULTICAST_TTL = 1;
static const int MDNS_PORT = 5353;
MDNSResponder::MDNSResponder()
: _expected(NULL)
@ -49,6 +73,7 @@ MDNSResponder::MDNSResponder()
, _response(NULL)
, _responseLen(0)
, _index(0)
, _conn(0)
{ }
MDNSResponder::~MDNSResponder() {
@ -149,21 +174,37 @@ bool MDNSResponder::begin(const char* domain, IPAddress addr, uint32_t ttlSecond
records[IP_OFFSET + 0] = (uint8_t) ipAddress;
// Open the MDNS socket if it isn't already open.
if (!_mdnsConn) {
if (!_mdnsConn.beginMulticast(addr, IPAddress(224, 0, 0, 251), 5353)) {
if (!_conn) {
ip_addr_t ifaddr;
ifaddr.addr = (uint32_t) addr;
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR;
if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
return false;
}
}
_conn = new UdpContext;
_conn->ref();
if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) {
return false;
}
_conn->setMulticastInterface(ifaddr);
_conn->setMulticastTTL(MDNS_MULTICAST_TTL);
_conn->onRx(std::bind(&MDNSResponder::update, this));
_conn->connect(multicast_addr, MDNS_PORT);
}
return true;
}
void MDNSResponder::update() {
if (!_mdnsConn.parsePacket())
return;
if (!_conn->next()) {
return;
}
// Read available data.
int n = _mdnsConn.available();
int n = _conn->getSize();
_index = 0;
@ -172,7 +213,7 @@ void MDNSResponder::update() {
#endif
// Look for domain name in request and respond with canned response if found.
for (int i = 0; i < n; ++i) {
uint8_t ch = tolower(_mdnsConn.read());
uint8_t ch = tolower(_conn->read());
#ifdef MDNS_DEBUG
String str(ch, 16);
@ -191,9 +232,12 @@ void MDNSResponder::update() {
Serial.print("responding, i=");
Serial.println(i);
#endif
_mdnsConn.beginPacketMulticast(IPAddress(224, 0, 0, 251), 5353, _localAddr);
_mdnsConn.write(_response, _responseLen);
_mdnsConn.endPacket();
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR;
_conn->append(reinterpret_cast<const char*>(_response), _responseLen);
_conn->send();
_index = 0;
}
}

View File

@ -46,6 +46,9 @@ License (MIT license):
#include "ESP8266WiFi.h"
#include "WiFiUdp.h"
class UdpContext;
class MDNSResponder {
public:
MDNSResponder();
@ -63,7 +66,7 @@ private:
uint8_t* _response;
int _responseLen;
// Socket for MDNS communication
WiFiUDP _mdnsConn;
UdpContext* _conn;
// local IP Address
IPAddress _localAddr;
};

View File

@ -68,9 +68,6 @@ void setup(void)
void loop(void)
{
// Check for any mDNS queries and send responses
mdns.update();
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {

View File

@ -36,6 +36,7 @@ typedef union {
SPIClass SPI;
SPIClass::SPIClass() {
useHwCs = false;
}
void SPIClass::begin() {
@ -54,9 +55,26 @@ void SPIClass::end() {
pinMode(SCK, INPUT);
pinMode(MISO, INPUT);
pinMode(MOSI, INPUT);
if(useHwCs) {
pinMode(SS, INPUT);
}
}
void SPIClass::setHwCs(bool use) {
if(use) {
pinMode(SS, SPECIAL); ///< GPIO15
SPI1U |= (SPIUCSSETUP | SPIUCSHOLD);
} else {
if(useHwCs) {
pinMode(SS, INPUT);
SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD);
}
}
useHwCs = use;
}
void SPIClass::beginTransaction(SPISettings settings) {
while(SPI1CMD & SPIBUSY) {}
setFrequency(settings._clock);
setBitOrder(settings._bitOrder);
setDataMode(settings._dataMode);
@ -198,13 +216,19 @@ void SPIClass::setClockDivider(uint32_t clockDiv) {
SPI1CLK = clockDiv;
}
inline void SPIClass::setDataBits(uint16_t bits) {
const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
bits--;
SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO)));
}
uint8_t SPIClass::transfer(uint8_t data) {
while(SPI1CMD & SPIBUSY)
;
while(SPI1CMD & SPIBUSY) {}
// reset to 8Bit mode
setDataBits(8);
SPI1W0 = data;
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY)
;
while(SPI1CMD & SPIBUSY) {}
return (uint8_t) (SPI1W0 & 0xff);
}
@ -230,3 +254,177 @@ uint16_t SPIClass::transfer16(uint16_t data) {
return out.val;
}
void SPIClass::write(uint8_t data) {
while(SPI1CMD & SPIBUSY) {}
// reset to 8Bit mode
setDataBits(8);
SPI1W0 = data;
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {}
}
void SPIClass::write16(uint16_t data) {
write16(data, !(SPI1C & (SPICWBO | SPICRBO)));
}
void SPIClass::write16(uint16_t data, bool msb) {
while(SPI1CMD & SPIBUSY) {}
// Set to 16Bits transfer
setDataBits(16);
if(msb) {
// MSBFIRST Byte first
SPI1W0 = (data >> 8) | (data << 8);
SPI1CMD |= SPIBUSY;
} else {
// LSBFIRST Byte first
SPI1W0 = data;
SPI1CMD |= SPIBUSY;
}
while(SPI1CMD & SPIBUSY) {}
}
void SPIClass::write32(uint32_t data) {
write32(data, !(SPI1C & (SPICWBO | SPICRBO)));
}
void SPIClass::write32(uint32_t data, bool msb) {
while(SPI1CMD & SPIBUSY) {}
// Set to 32Bits transfer
setDataBits(32);
if(msb) {
union {
uint32_t l;
uint8_t b[4];
} data_;
data_.l = data;
// MSBFIRST Byte first
SPI1W0 = (data_.b[3] | (data_.b[2] << 8) | (data_.b[1] << 16) | (data_.b[0] << 24));
SPI1CMD |= SPIBUSY;
} else {
// LSBFIRST Byte first
SPI1W0 = data;
SPI1CMD |= SPIBUSY;
}
while(SPI1CMD & SPIBUSY) {}
}
void SPIClass::writeBytes(uint8_t * data, uint32_t size) {
while(size) {
if(size > 64) {
writeBytes_(data, 64);
size -= 64;
data += 64;
} else {
writeBytes_(data, size);
size = 0;
}
}
}
void SPIClass::writeBytes_(uint8_t * data, uint8_t size) {
while(SPI1CMD & SPIBUSY) {}
// Set Bits to transfer
setDataBits(size * 8);
volatile uint32_t * fifoPtr = &SPI1W0;
uint32_t * dataPtr = (uint32_t*) data;
uint8_t dataSize = ((size + 3) / 4);
while(dataSize--) {
*fifoPtr = *dataPtr;
dataPtr++;
fifoPtr++;
}
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {}
}
void SPIClass::writePattern(uint8_t * data, uint8_t size, uint32_t repeat) {
if(size > 64) return; //max Hardware FIFO
uint32_t byte = (size * repeat);
uint8_t r = (64 / size);
while(byte) {
if(byte > 64) {
writePattern_(data, size, r);
byte -= 64;
} else {
writePattern_(data, size, (byte / size));
byte = 0;
}
}
}
void SPIClass::writePattern_(uint8_t * data, uint8_t size, uint8_t repeat) {
uint8_t bytes = (size * repeat);
uint8_t buffer[64];
uint8_t * bufferPtr = &buffer[0];
uint8_t * dataPtr;
uint8_t dataSize = bytes;
for(uint8_t i = 0; i < repeat; i++) {
dataSize = size;
dataPtr = data;
while(dataSize--) {
*bufferPtr = *dataPtr;
dataPtr++;
bufferPtr++;
}
}
writeBytes(&buffer[0], bytes);
}
void SPIClass::transferBytes(uint8_t * out, uint8_t * in, uint32_t size) {
while(size) {
if(size > 64) {
transferBytes_(out, in, 64);
size -= 64;
if(out) out += 64;
if(in) in += 64;
} else {
transferBytes_(out, in, size);
size = 0;
}
}
}
void SPIClass::transferBytes_(uint8_t * out, uint8_t * in, uint8_t size) {
while(SPI1CMD & SPIBUSY) {}
// Set in/out Bits to transfer
setDataBits(size * 8);
volatile uint32_t * fifoPtr = &SPI1W0;
uint8_t dataSize = ((size + 3) / 4);
if(out) {
uint32_t * dataPtr = (uint32_t*) out;
while(dataSize--) {
*fifoPtr = *dataPtr;
dataPtr++;
fifoPtr++;
}
} else {
// no out data only read fill with dummy data!
while(dataSize--) {
*fifoPtr = 0xFFFFFFFF;
fifoPtr++;
}
}
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {}
if(in) {
volatile uint8_t * fifoPtr8 = (volatile uint8_t *) &SPI1W0;
dataSize = size;
while(dataSize--) {
*in = *fifoPtr8;
in++;
fifoPtr8++;
}
}
}

View File

@ -64,6 +64,7 @@ public:
SPIClass();
void begin();
void end();
void setHwCs(bool use);
void setBitOrder(uint8_t bitOrder);
void setDataMode(uint8_t dataMode);
void setFrequency(uint32_t freq);
@ -71,7 +72,21 @@ public:
void beginTransaction(SPISettings settings);
uint8_t transfer(uint8_t data);
uint16_t transfer16(uint16_t data);
void write(uint8_t data);
void write16(uint16_t data);
void write16(uint16_t data, bool msb);
void write32(uint32_t data);
void write32(uint32_t data, bool msb);
void writeBytes(uint8_t * data, uint32_t size);
void writePattern(uint8_t * data, uint8_t size, uint32_t repeat);
void transferBytes(uint8_t * out, uint8_t * in, uint32_t size);
void endTransaction(void);
private:
bool useHwCs;
void writeBytes_(uint8_t * data, uint8_t size);
void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat);
void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size);
inline void setDataBits(uint16_t bits);
};
extern SPIClass SPI;

View File

@ -23,7 +23,7 @@ compiler.S.flags=-c -g -x assembler-with-cpp -MMD
compiler.c.elf.ldscript=eagle.app.v6.ld
compiler.c.elf.flags=-nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{compiler.c.elf.ldscript}"
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lm -lc -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -std=c++11 -MMD

View File

@ -11,6 +11,8 @@
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
Modified 09 May 2015 by Markus Sattler - rewrite the code add ESP8266 support and many optimizations now 220% fastet (320% total)
****************************************************/
#include "Adafruit_ILI9341.h"
@ -24,6 +26,16 @@
#include "wiring_private.h"
#include <SPI.h>
#ifdef ESP8266
#define hwSPI true
#endif
#define writeCmdDataTmp(cmd, ...) { \
const uint8_t tmp##cmd##_[] = { __VA_ARGS__ }; \
writeCmdData(cmd, (uint8_t *) &tmp##cmd##_[0], sizeof(tmp##cmd##_)); \
}
#ifndef ESP8266
// Constructor when using software SPI. All output pins are configurable.
Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi,
@ -40,15 +52,40 @@ Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi,
// Constructor when using hardware SPI. Faster, but must use SPI pins
// specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.)
Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
_cs = cs;
#if defined(ILI9341_USE_HW_CS) || defined(ILI9341_USE_NO_CS)
Adafruit_ILI9341::Adafruit_ILI9341(int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
_dc = dc;
_rst = rst;
hwSPI = true;
#ifndef ESP8266
#ifdef ESP8266
_dcMask = digitalPinToBitMask(_dc);
_rstMask = digitalPinToBitMask(_rst);
#else
_mosi = _sclk = 0;
#endif
}
#else
Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
_cs = cs;
_dc = dc;
_rst = rst;
#ifdef ESP8266
_csMask = digitalPinToBitMask(_cs);
_dcMask = digitalPinToBitMask(_dc);
_rstMask = digitalPinToBitMask(_rst);
#else
hwSPI = true;
_mosi = _sclk = 0;
#endif
}
#endif
#ifdef ESP8266
void Adafruit_ILI9341::spiwrite16(uint16_t c) {
SPI.write16(c, true);
}
#endif
void Adafruit_ILI9341::spiwrite(uint8_t c) {
@ -63,7 +100,7 @@ void Adafruit_ILI9341::spiwrite(uint8_t c) {
while(!(SPSR & _BV(SPIF)));
SPCR = backupSPCR;
#elif defined(TEENSYDUINO) || defined(ESP8266)
SPI.transfer(c);
SPI.write(c);
#elif defined (__arm__)
SPI.setClockDivider(11); // 8-ish MHz (full! speed!)
SPI.setBitOrder(MSBFIRST);
@ -90,73 +127,143 @@ void Adafruit_ILI9341::spiwrite(uint8_t c) {
#endif
}
void Adafruit_ILI9341::spiwriteBytes(uint8_t * data, uint8_t size) {
#ifdef ESP8266
SPI.writeBytes(data, size);
#else
while(size--) {
spiwrite(*data);
data++;
}
#endif
}
void Adafruit_ILI9341::writecommand(uint8_t c) {
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, LOW);
void Adafruit_ILI9341::spiwritePattern(uint8_t * data, uint8_t size, uint32_t repeat) {
#ifdef ESP8266
SPI.writePattern(data, size, repeat);
#else
uint8_t * ptr;
uint8_t i;
while(repeat--) {
ptr = data;
i = size;
while(i--) {
spiwrite(*ptr);
ptr++;
}
}
#endif
}
inline void Adafruit_ILI9341::spiCsLow(void) {
#ifdef ILI9341_USE_DIGITAL_WRITE
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOC = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
#else
*dcport &= ~dcpinmask;
//*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
//digitalWrite(_sclk, LOW);
*csport &= ~cspinmask;
#if !defined(ILI9341_USE_HW_CS) && !defined(ILI9341_USE_NO_CS)
GPOC = _csMask;
#endif
#endif
spiwrite(c);
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
*csport &= ~cspinmask;
#endif
#endif
}
void Adafruit_ILI9341::writedata(uint8_t c) {
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
#else
*dcport |= dcpinmask;
//*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
//digitalWrite(_sclk, LOW);
*csport &= ~cspinmask;
#endif
#endif
spiwrite(c);
#ifdef USE_DIGITAL_WRITE
inline void Adafruit_ILI9341::spiCsHigh(void) {
#ifdef ILI9341_USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#if !defined(ILI9341_USE_HW_CS) && !defined(ILI9341_USE_NO_CS)
GPOS = _csMask;
#endif
#else
*csport |= cspinmask;
*csport |= cspinmask;
#endif
#endif
}
inline void Adafruit_ILI9341::spiDcLow(void){
#ifdef ILI9341_USE_DIGITAL_WRITE
digitalWrite(_dc, LOW);
#else
#ifdef ESP8266
#ifndef USE_HW_CS
GPOC = _dcMask;
#endif
#else
*dcport &= ~dcpinmask;
#endif
#endif
}
inline void Adafruit_ILI9341::spiDcHigh(void) {
#ifdef ILI9341_USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
#else
#ifdef ESP8266
GPOS = _dcMask;
#else
*dcport |= dcpinmask;
#endif
#endif
}
void Adafruit_ILI9341::writecommand(uint8_t c) {
spiDcLow();
spiCsLow();
spiwrite(c);
spiCsHigh();
}
void Adafruit_ILI9341::writedata(uint8_t c) {
spiDcHigh();
spiCsLow();
spiwrite(c);
spiCsHigh();
}
void Adafruit_ILI9341::writedata(uint8_t * data, uint8_t size) {
spiDcHigh();
spiCsLow();
spiwriteBytes(data, size);
spiCsHigh();
}
void Adafruit_ILI9341::writeCmdData(uint8_t cmd, uint8_t * data, uint8_t size) {
spiDcLow();
spiCsLow();
spiwrite(cmd);
spiDcHigh();
spiwriteBytes(data, size);
spiCsHigh();
}
// If the SPI library has transaction support, these functions
// establish settings and protect from interference from other
// libraries. Otherwise, they simply do nothing.
#ifdef SPI_HAS_TRANSACTION
#ifdef ESP8266
SPISettings spiSettings = SPISettings(F_CPU, MSBFIRST, SPI_MODE0);
#else
SPISettings spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
#endif
static inline void spi_begin(void) __attribute__((always_inline));
static inline void spi_begin(void) {
#ifdef ESP8266
SPI.beginTransaction(SPISettings(80000000, MSBFIRST, SPI_MODE0));
#else
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
#endif
SPI.beginTransaction(spiSettings);
}
static inline void spi_end(void) __attribute__((always_inline));
static inline void spi_end(void) {
@ -202,15 +309,17 @@ void Adafruit_ILI9341::commandList(uint8_t *addr) {
void Adafruit_ILI9341::begin(void) {
if (_rst > 0) {
if (_rst > NOT_A_PIN) {
pinMode(_rst, OUTPUT);
digitalWrite(_rst, LOW);
}
pinMode(_dc, OUTPUT);
#ifndef USE_HW_CS
pinMode(_cs, OUTPUT);
#endif
#ifndef ESP8266
#ifndef USE_DIGITAL_WRITE
#ifndef ILI9341_USE_DIGITAL_WRITE
csport = portOutputRegister(digitalPinToPort(_cs));
cspinmask = digitalPinToBitMask(_cs);
dcport = portOutputRegister(digitalPinToPort(_dc));
@ -236,6 +345,9 @@ void Adafruit_ILI9341::begin(void) {
SPI.setDataMode(SPI_MODE0);
#elif defined (ESP8266)
SPI.begin();
#ifdef USE_HW_CS
SPI.setHwCs(true);
#endif
#endif
#ifndef ESP8266
} else {
@ -251,7 +363,7 @@ void Adafruit_ILI9341::begin(void) {
}
#endif
// toggle RST low to reset
if (_rst > 0) {
if (_rst > NOT_A_PIN) {
digitalWrite(_rst, HIGH);
delay(5);
digitalWrite(_rst, LOW);
@ -275,108 +387,47 @@ void Adafruit_ILI9341::begin(void) {
//if(cmdList) commandList(cmdList);
if (hwSPI) spi_begin();
writecommand(0xEF);
writedata(0x03);
writedata(0x80);
writedata(0x02);
writecommand(0xCF);
writedata(0x00);
writedata(0XC1);
writedata(0X30);
writeCmdDataTmp(0xEF, 0x03, 0x80, 0x02);
writeCmdDataTmp(0xCF, 0x00, 0XC1, 0X30);
writeCmdDataTmp(0xED, 0x64, 0x03, 0X12, 0X81);
writeCmdDataTmp(0xE8, 0x85, 0x00, 0x78);
writeCmdDataTmp(0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02);
writeCmdDataTmp(0xF7, 0x20);
writeCmdDataTmp(0xEA, 0x00, 0x00);
writecommand(0xED);
writedata(0x64);
writedata(0x03);
writedata(0X12);
writedata(0X81);
writecommand(0xE8);
writedata(0x85);
writedata(0x00);
writedata(0x78);
//Powercontrol
//VRH[5:0]
writeCmdDataTmp(ILI9341_PWCTR1, 0x23);
writecommand(0xCB);
writedata(0x39);
writedata(0x2C);
writedata(0x00);
writedata(0x34);
writedata(0x02);
writecommand(0xF7);
writedata(0x20);
//Powercontrol
//SAP[2:0];BT[3:0]
writeCmdDataTmp(ILI9341_PWCTR2, 0x10);
writecommand(0xEA);
writedata(0x00);
writedata(0x00);
writecommand(ILI9341_PWCTR1); //Power control
writedata(0x23); //VRH[5:0]
writecommand(ILI9341_PWCTR2); //Power control
writedata(0x10); //SAP[2:0];BT[3:0]
writecommand(ILI9341_VMCTR1); //VCM control
writedata(0x3e); //<2F>Աȶȵ<C8B6><C8B5><EFBFBD>
writedata(0x28);
//VCMcontrol
writeCmdDataTmp(ILI9341_VMCTR1, 0x3e, 0x28);
//VCMcontrol2
writeCmdDataTmp(ILI9341_VMCTR2, 0x86);
//MemoryAccessControl
writeCmdDataTmp(ILI9341_MADCTL, 0x48);
writeCmdDataTmp(ILI9341_PIXFMT, 0x55);
writeCmdDataTmp(ILI9341_FRMCTR1, 0x00, 0x18);
//DisplayFunctionControl
writeCmdDataTmp(ILI9341_DFUNCTR, 0x08, 0x82, 0x27);
//3GammaFunctionDisable
writeCmdDataTmp(0xF2, 0x00);
writecommand(ILI9341_VMCTR2); //VCM control2
writedata(0x86); //--
writecommand(ILI9341_MADCTL); // Memory Access Control
writedata(0x48);
writecommand(ILI9341_PIXFMT);
writedata(0x55);
//Gammacurveselected
writeCmdDataTmp(ILI9341_GAMMASET, 0x01);
writecommand(ILI9341_FRMCTR1);
writedata(0x00);
writedata(0x18);
writecommand(ILI9341_DFUNCTR); // Display Function Control
writedata(0x08);
writedata(0x82);
writedata(0x27);
writecommand(0xF2); // 3Gamma Function Disable
writedata(0x00);
writecommand(ILI9341_GAMMASET); //Gamma curve selected
writedata(0x01);
writecommand(ILI9341_GMCTRP1); //Set Gamma
writedata(0x0F);
writedata(0x31);
writedata(0x2B);
writedata(0x0C);
writedata(0x0E);
writedata(0x08);
writedata(0x4E);
writedata(0xF1);
writedata(0x37);
writedata(0x07);
writedata(0x10);
writedata(0x03);
writedata(0x0E);
writedata(0x09);
writedata(0x00);
writecommand(ILI9341_GMCTRN1); //Set Gamma
writedata(0x00);
writedata(0x0E);
writedata(0x14);
writedata(0x03);
writedata(0x11);
writedata(0x07);
writedata(0x31);
writedata(0xC1);
writedata(0x48);
writedata(0x08);
writedata(0x0F);
writedata(0x0C);
writedata(0x31);
writedata(0x36);
writedata(0x0F);
//SetGamma
writeCmdDataTmp(ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00);
writeCmdDataTmp(ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F);
writecommand(ILI9341_SLPOUT); //Exit Sleep
if (hwSPI) spi_end();
@ -387,217 +438,161 @@ void Adafruit_ILI9341::begin(void) {
}
void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
spiCsLow();
setAddrWindow_(x0, y0, x1, y1);
spiCsHigh();
}
void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1,
uint16_t y1) {
void Adafruit_ILI9341::setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
writecommand(ILI9341_CASET); // Column addr set
writedata(x0 >> 8);
writedata(x0 & 0xFF); // XSTART
writedata(x1 >> 8);
writedata(x1 & 0xFF); // XEND
uint8_t buffC[] = { (uint8_t) (x0 >> 8), (uint8_t) x0, (uint8_t) (x1 >> 8), (uint8_t) x1 };
uint8_t buffP[] = { (uint8_t) (y0 >> 8), (uint8_t) y0, (uint8_t) (y1 >> 8), (uint8_t) y1 };
writecommand(ILI9341_PASET); // Row addr set
writedata(y0>>8);
writedata(y0); // YSTART
writedata(y1>>8);
writedata(y1); // YEND
spiDcLow();
spiwrite(ILI9341_CASET);
spiDcHigh();
spiwriteBytes(&buffC[0], sizeof(buffC));
spiDcLow();
spiwrite(ILI9341_PASET);
spiDcHigh();
spiwriteBytes(&buffP[0], sizeof(buffP));
spiDcLow();
spiwrite(ILI9341_RAMWR);
spiDcHigh();
writecommand(ILI9341_RAMWR); // write to RAM
}
void Adafruit_ILI9341::pushColor(uint16_t color) {
if (hwSPI) spi_begin();
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
spiDcHigh();
spiCsLow();
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
spiwrite16(color);
#else
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#endif
#endif
spiwrite(color >> 8);
spiwrite(color);
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
#endif
#endif
spiCsHigh();
if (hwSPI) spi_end();
}
void Adafruit_ILI9341::drawPixel(int16_t x, int16_t y, uint16_t color) {
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) {
return;
}
if(hwSPI) {
spi_begin();
}
spiCsLow();
setAddrWindow_(x, y, x + 1, y + 1);
if (hwSPI) spi_begin();
setAddrWindow(x,y,x+1,y+1);
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
spiwrite16(color);
#else
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#endif
spiwrite(color >> 8);
spiwrite(color);
#endif
spiwrite(color >> 8);
spiwrite(color);
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
#endif
#endif
if (hwSPI) spi_end();
spiCsHigh();
if(hwSPI) {
spi_end();
}
}
void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h,
uint16_t color) {
void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
// Rudimentary clipping
if((x >= _width) || (y >= _height)) return;
// Rudimentary clipping
if((x >= _width) || (y >= _height)) return;
if((y + h - 1) >= _height) h = _height - y;
if((y+h-1) >= _height)
h = _height-y;
if(hwSPI) {
spi_begin();
}
if (hwSPI) spi_begin();
setAddrWindow(x, y, x, y+h-1);
spiCsLow();
uint8_t hi = color >> 8, lo = color;
setAddrWindow_(x, y, x, (y + h - 1));
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
#else
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#endif
#endif
uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
spiwritePattern(&colorBin[0], 2, h);
while (h--) {
spiwrite(hi);
spiwrite(lo);
}
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
#endif
#endif
if (hwSPI) spi_end();
spiCsHigh();
if(hwSPI) {
spi_end();
}
}
void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w,
uint16_t color) {
// Rudimentary clipping
if((x >= _width) || (y >= _height)) return;
if((x+w-1) >= _width) w = _width-x;
// Rudimentary clipping
if((x >= _width) || (y >= _height)) return;
if((x+w-1) >= _width) w = _width-x;
if (hwSPI) spi_begin();
setAddrWindow(x, y, x+w-1, y);
if(hwSPI) {
spi_begin();
}
uint8_t hi = color >> 8, lo = color;
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
#else
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#endif
#endif
while (w--) {
spiwrite(hi);
spiwrite(lo);
}
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
#endif
#endif
if (hwSPI) spi_end();
spiDcHigh();
spiCsLow();
setAddrWindow_(x, y, (x + w - 1), y);
uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
spiwritePattern(&colorBin[0], 2, w);
spiCsHigh();
if(hwSPI) {
spi_end();
}
}
void Adafruit_ILI9341::fillScreen(uint16_t color) {
fillRect(0, 0, _width, _height, color);
fillRect(0, 0, _width, _height, color);
}
// fill a rectangle
void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
uint16_t color) {
void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
// rudimentary clipping (drawChar w/big text requires this)
if((x >= _width) || (y >= _height)) return;
if((x + w - 1) >= _width) w = _width - x;
if((y + h - 1) >= _height) h = _height - y;
// rudimentary clipping (drawChar w/big text requires this)
if((x >= _width) || (y >= _height))
return;
if((x + w - 1) >= _width)
w = _width - x;
if((y + h - 1) >= _height)
h = _height - y;
if (hwSPI) spi_begin();
setAddrWindow(x, y, x+w-1, y+h-1);
uint8_t hi = color >> 8, lo = color;
#ifdef USE_DIGITAL_WRITE
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_dc);
GPOC = digitalPinToBitMask(_cs);
#else
*dcport |= dcpinmask;
*csport &= ~cspinmask;
#endif
#endif
for(y=h; y>0; y--) {
for(x=w; x>0; x--) {
spiwrite(hi);
spiwrite(lo);
if(hwSPI) {
spi_begin();
}
spiCsLow();
setAddrWindow_(x, y, x + w - 1, y + h - 1);
uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
spiwritePattern(&colorBin[0], 2, (w * h));
spiCsHigh();
if(hwSPI) {
spi_end();
}
}
#ifdef USE_DIGITAL_WRITE
digitalWrite(_cs, HIGH);
#else
#ifdef ESP8266
GPOS = digitalPinToBitMask(_cs);
#else
*csport |= cspinmask;
#endif
#endif
if (hwSPI) spi_end();
}
@ -675,9 +670,7 @@ uint8_t Adafruit_ILI9341::spiread(void) {
SPI.setDataMode(SPI_MODE0);
r = SPI.transfer(0x00);
#else
spi_begin();
r = SPI.transfer(0x00);
spi_end();
#endif
} else {
#ifndef ESP8266
@ -695,40 +688,40 @@ uint8_t Adafruit_ILI9341::spiread(void) {
return r;
}
uint8_t Adafruit_ILI9341::readdata(void) {
digitalWrite(_dc, HIGH);
digitalWrite(_cs, LOW);
uint8_t r = spiread();
digitalWrite(_cs, HIGH);
return r;
uint8_t Adafruit_ILI9341::readdata(void) {
if(hwSPI) spi_begin();
spiCsLow();
spiDcLow();
uint8_t r = spiread();
spiCsHigh();
if(hwSPI) spi_end();
return r;
}
uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) {
if (hwSPI) spi_begin();
digitalWrite(_dc, LOW); // command
digitalWrite(_cs, LOW);
spiwrite(0xD9); // woo sekret command?
digitalWrite(_dc, HIGH); // data
spiwrite(0x10 + index);
digitalWrite(_cs, HIGH);
if(hwSPI) spi_begin();
spiCsLow();
spiDcLow();
spiwrite(0xD9); // woo sekret command?
spiDcHigh();
spiwrite(0x10 + index);
digitalWrite(_dc, LOW);
#ifndef ESP8266
digitalWrite(_sclk, LOW);
digitalWrite(_sclk, LOW);
#endif
digitalWrite(_cs, LOW);
spiwrite(c);
digitalWrite(_dc, HIGH);
uint8_t r = spiread();
digitalWrite(_cs, HIGH);
if (hwSPI) spi_end();
return r;
spiDcLow();
spiwrite(c);
spiDcHigh();
uint8_t r = spiread();
spiCsHigh();
if(hwSPI) spi_end();
return r;
}
/*

View File

@ -110,7 +110,12 @@
#define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define ILI9341_PINK 0xF81F
//#define USE_DIGITAL_WRITE
//#define ILI9341_USE_DIGITAL_WRITE
//#define ILI9341_USE_NO_CS
#ifdef ESP8266
//not working
//#define ILI9341_USE_HW_CS
#endif
class Adafruit_ILI9341 : public Adafruit_GFX {
@ -119,8 +124,11 @@ class Adafruit_ILI9341 : public Adafruit_GFX {
Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
int8_t _RST, int8_t _MISO);
#endif
#if defined(USE_HW_CS) || defined(USE_NO_CS)
Adafruit_ILI9341(int8_t _DC, int8_t _RST = -1);
#else
Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1);
#endif
void begin(void),
setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),
pushColor(uint16_t color),
@ -134,25 +142,51 @@ class Adafruit_ILI9341 : public Adafruit_GFX {
invertDisplay(boolean i);
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
/* These are not for current use, 8-bit protocol only! */
uint8_t readdata(void),
readcommand8(uint8_t reg, uint8_t index = 0);
/*
uint16_t readcommand16(uint8_t);
uint32_t readcommand32(uint8_t);
void dummyclock(void);
*/
void commandList(uint8_t *addr);
void spiwrite(uint8_t),
writecommand(uint8_t c),
writedata(uint8_t d),
commandList(uint8_t *addr);
uint8_t spiread(void);
/* These are not for current use, 8-bit protocol only! */
uint8_t readdata(void),
readcommand8(uint8_t reg, uint8_t index = 0);
/*
uint16_t readcommand16(uint8_t);
uint32_t readcommand32(uint8_t);
void dummyclock(void);
*/
void writecommand(uint8_t c);
void writedata(uint8_t d);
void writedata(uint8_t * data, uint8_t size);
void writeCmdData(uint8_t cmd, uint8_t * data, uint8_t size);
private:
uint8_t tabcolor;
uint8_t spiread(void);
#ifdef ESP8266
inline void spiwrite(uint8_t data);
inline void spiwrite16(uint16_t data);
inline void spiwriteBytes(uint8_t * data, uint8_t size);
inline void spiwritePattern(uint8_t * data, uint8_t size, uint32_t repeat);
inline void setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
#else
void spiwrite(uint8_t);
void spiwrite16(uint16_t data);
void spiwriteBytes(uint8_t * data, uint8_t size);
void spiwritePattern(uint8_t * data, uint8_t size, uint8_t repeat);
void setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
#endif
inline void spiCsHigh(void);
inline void spiCsLow(void);
inline void spiDcHigh(void);
inline void spiDcLow(void);
uint8_t tabcolor;
#ifndef ESP8266
boolean hwSPI;
#endif
#if defined (__AVR__) || defined(TEENSYDUINO)
uint8_t mySPCR;
volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport;
@ -163,7 +197,12 @@ class Adafruit_ILI9341 : public Adafruit_GFX {
uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk;
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
#elif defined (ESP8266)
uint32_t _cs, _dc, _rst;
#ifndef USE_HW_CS
int8_t _cs;
uint32_t _csMask;
#endif
int8_t _dc, _rst;
uint32_t _dcMask, _rstMask;
#endif
};

View File

@ -332,7 +332,7 @@ boolean callback_rmdir(SdFile& parentDir, char *filePathComponent,
boolean SDClass::begin(uint8_t csPin) {
boolean SDClass::begin(uint8_t csPin, uint32_t speed) {
/*
Performs the initialisation required by the sdfatlib library.
@ -340,13 +340,11 @@ boolean SDClass::begin(uint8_t csPin) {
Return true if initialization succeeds, false otherwise.
*/
return card.init(SPI_HALF_SPEED, csPin) &&
return card.init(speed, csPin) &&
volume.init(card) &&
root.openRoot(volume);
}
// this little helper is used to traverse paths
SdFile SDClass::getParentDir(const char *filepath, int *index) {
// get parent directory

View File

@ -65,8 +65,8 @@ private:
public:
// This needs to be called to set up the connection to the SD card
// before other methods are used.
boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN, uint32_t speed = SPI_HALF_SPEED);
// Open the specified file/directory with the supplied mode (e.g. read or
// write, etc). Returns a File object for interacting with the file.
// Note that currently only one file can be open at a time.

View File

@ -33,9 +33,13 @@ static void spiSend(uint8_t b) {
SPDR = b;
while (!(SPSR & (1 << SPIF)))
;
#else
#ifdef ESP8266
SPI.write(b);
#else
SPI.transfer(b);
#endif
#endif
}
/** Receive a byte from the card */
static uint8_t spiRec(void) {
@ -116,8 +120,14 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// send command
spiSend(cmd | 0x40);
#ifdef ESP8266
// send argument
SPI.write32(arg, true);
#else
// send argument
for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
#endif
// send CRC
uint8_t crc = 0xFF;
@ -424,7 +434,14 @@ uint8_t Sd2Card::readData(uint32_t block,
dst[n] = SPDR;
#else // OPTIMIZE_HARDWARE_SPI
#ifdef ESP8266
// skip data before offset
SPI.transferBytes(NULL, NULL, offset_);
// transfer data
SPI.transferBytes(NULL, dst, count);
#else
// skip data before offset
for (;offset_ < offset; offset_++) {
spiRec();
@ -433,6 +450,7 @@ uint8_t Sd2Card::readData(uint32_t block,
for (uint16_t i = 0; i < count; i++) {
dst[i] = spiRec();
}
#endif
#endif // OPTIMIZE_HARDWARE_SPI
offset_ += count;
@ -463,7 +481,11 @@ void Sd2Card::readEnd(void) {
while (!(SPSR & (1 << SPIF)))
;
#else // OPTIMIZE_HARDWARE_SPI
#ifdef ESP8266
SPI.transferBytes(NULL, NULL, (514-offset_));
#else
while (offset_++ < 514) spiRec();
#endif
#endif // OPTIMIZE_HARDWARE_SPI
chipSelectHigh();
inBlock_ = 0;
@ -479,7 +501,11 @@ uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) {
}
if (!waitStartBlock()) goto fail;
// transfer data
#ifdef ESP8266
SPI.transferBytes(NULL, dst, 16);
#else
for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
#endif
spiRec(); // get first crc byte
spiRec(); // get second crc byte
chipSelectHigh();
@ -646,13 +672,21 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) {
#else // OPTIMIZE_HARDWARE_SPI
spiSend(token);
#ifdef ESP8266
// send argument
SPI.writeBytes((uint8_t *)src, 512);
#else
for (uint16_t i = 0; i < 512; i++) {
spiSend(src[i]);
}
#endif
#endif // OPTIMIZE_HARDWARE_SPI
#ifdef ESP8266
SPI.write16(0xFFFF, true);
#else
spiSend(0xff); // dummy crc
spiSend(0xff); // dummy crc
#endif
status_ = spiRec();
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
error(SD_CARD_ERROR_WRITE);