Idf 5.1.4/Arduino 3.0.4 porting for esp32 (#1046)

* Update WebSocket library
* Update SSDP library
* Update TFT_eSPI library
* Update EspLuaEngine library
* Update SDFat library
* Change to pioarduino
* Make ESP3DMessageFIFO and ESP3DMessage  more thread safe
* Fix sanity checks for BT
* Add some C6 support
* Refactor ethernet code
* Split Ethernet Sta / WiFi sta ESP Commands  and settings
* Simplify wait and wdtFeed code
* Set C3 with 4MB by default in platformio.ini
* Apply Disable brown out only on ESP32 to avoid crash e.g:ESP32S3
* Add missing entries in platformio.ini
This commit is contained in:
Luc 2024-09-05 16:27:47 +08:00 committed by GitHub
parent 8deab1f06c
commit 93312ff8b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1965 changed files with 37800 additions and 139618 deletions

View File

@ -12,7 +12,7 @@ echo "Clone esp32 core"
cd $HOME/arduino_ide/hardware
mkdir esp32
cd esp32
git clone -b 2.0.8 https://github.com/espressif/arduino-esp32.git esp32
git clone -b 3.0.4 https://github.com/espressif/arduino-esp32.git esp32
cd esp32
git submodule update --init
cd tools

View File

@ -6,13 +6,13 @@ shopt -s globstar
ls $HOME
# Make sure we are inside the github workspace
cd $GITHUB_WORKSPACE
cp -r ./libraries/ESP32SSDP-1.2.1 $HOME/arduino_ide/libraries/
cp -r ./libraries/arduinoWebSockets-2.3.6 $HOME/arduino_ide/libraries/
cp -r ./libraries/ESP32SSDP-2.0.2 $HOME/arduino_ide/libraries/
cp -r ./libraries/arduinoWebSockets-2.5.2 $HOME/arduino_ide/libraries/
cp -r ./libraries/DHT_sensor_library_for_ESPx-1.0.6 $HOME/arduino_ide/libraries/
cp -r ./libraries/esp8266-oled-ssd1306-4.3.0 $HOME/arduino_ide/libraries/
cp -r ./libraries/TFT_eSPI-2.4.72 $HOME/arduino_ide/libraries/
cp -r ./libraries/TFT_eSPI-2.5.43 $HOME/arduino_ide/libraries/
cp -r ./libraries/lvgl-8.2.0 $HOME/arduino_ide/libraries/
cp -r ./libraries/EspLuaEngine-1.0.1 $HOME/arduino_ide/libraries/
cp -r ./libraries/EspLuaEngine-1.0.2 $HOME/arduino_ide/libraries/
cp -r ./libraries/BMx280MI-1.2.0 $HOME/arduino_ide/libraries/
#TODO add SDFat libraries according version and target

View File

@ -1,7 +0,0 @@
cd %~dp0esp3d
astyle --recursive --style=otbs *.h *.cpp *.ino
del /S *.ori
dir
cd ..
pause

View File

@ -1,7 +0,0 @@
#!/bin/bash
cd `dirname "$0"`
cd esp3d
astyle --recursive --style=otbs '*.h' '*.cpp' '*.ino'
rm -r -v *.ori
cd ..
read -p "Press any key to continue ..."

View File

@ -44,6 +44,24 @@ AP_IP = 192.168.0.1
#AP channel 1~14
AP_channel = 11
#Ethernet STA IP Mode DHCP / STATIC
ETH_STA_IP_mode = DHCP
#Ethernet STA static IP
ETH_STA_IP = 192.168.0.2
#Ethernet STA static gateway
ETH_STA_GW = 192.168.0.1
#Ethernet STA static mask
ETH_STA_MSK = 255.255.255.0
#Ethernet STA static dns
ETH_STA_DNS = 192.168.0.1
#Ethernet fallback mode BT, OFF
eth_sta_fallback = OFF
[services]
#Active or not Serial Bridge Yes / No
Serial_Bridge_active = Yes

View File

@ -119,7 +119,7 @@
/* Use Ethernet
* Enable ethernet communications
*/
// #define ETH_FEATURE
//#define ETH_FEATURE
// Ethernet type (Check ETH.h eth_phy_type_t)
// TYPE_ETH_PHY_LAN8720
@ -136,20 +136,20 @@
// MODE_ETH_CLOCK_GPIO0_OUT
// MODE_ETH_CLOCK_GPIO16_OUT
// MODE_ETH_CLOCK_GPIO17_OUT
#define ESP3D_ETH_CLK_MODE MODE_ETH_CLOCK_GPIO17_OUT
#define ESP3D_ETH_CLK_MODE MODE_ETH_CLOCK_GPIO0_IN
// Pins of ethernet board
#define ESP3D_ETH_PHY_POWER_PIN 12
// #define ESP3D_ETH_PHY_MDC_PIN 23
// #define ESP3D_ETH_PHY_MDIO_PIN 18
#define ESP3D_ETH_PHY_POWER_PIN 16
#define ESP3D_ETH_PHY_MDC_PIN 23
#define ESP3D_ETH_PHY_MDIO_PIN 18
// Address of ethernet board
// #define ESP3D_ETH_PHY_ADDR 0
#define ESP3D_ETH_PHY_ADDR 1
/* Use Bluetooth
* Enable serial bluetooth communications
*/
// #define BLUETOOTH_FEATURE
//#define BLUETOOTH_FEATURE
/************************************
*
@ -283,14 +283,15 @@
* ESP_SHARED_SD //Printer SD Card is also connected to ESP3D
* Does your system has SD card and how it is connected to your ESP3D
*/
// #define SD_DEVICE_CONNECTION ESP_SHARED_SD
//#define SD_DEVICE_CONNECTION ESP_DIRECT_SD
/* SD card library
* ESP_SD_NATIVE //esp32 / esp8266
* ESP_SDIO //esp32 only
* ESP_SDFAT2 //esp8266 / esp32
*/
// #define SD_DEVICE ESP_SD_NATIVE
//#define SD_DEVICE ESP_SDFAT2
// #define SD_CARD_TYPE ESP_FYSETC_WIFI_PRO_SDCARD
@ -299,7 +300,7 @@
* SD_ONE_BIT_MODE
* SD_FOUR_BIT_MODE
*/
// #define SDIO_BIT_MODE SD_ONE_BIT_MODE
//#define SDIO_BIT_MODE SD_ONE_BIT_MODE
/* Enable date/time on files
* Set date/time on files using SNTP or last webui connection
@ -335,7 +336,13 @@
/* SD card CS pin
* The pin used to select SD card in SPI mode
*/
// #define ESP_SD_CS_PIN 5
//#define ESP_SD_CS_PIN 21
//#define ESP_SD_MISO_PIN 8
//#define ESP_SD_MOSI_PIN 9
//#define ESP_SD_SCK_PIN 7
//#define ESP_SDIO_CMD_PIN 38
//#define ESP_SDIO_D0_PIN 40
//#define ESP_SDIO_CLK_PIN 39
/************************************
*
@ -383,7 +390,7 @@
* The pin used to reset ESP3D setting if set to low for more than 1 second at
* start
*/
#define ESP3D_RESET_PIN 0
//#define ESP3D_RESET_PIN 0
/************************************
*
@ -505,9 +512,10 @@
* CAMERA_MODEL_ESP32S2_CAM_BOARD
* CAMERA_MODEL_ESP32S3_CAM_LCD
* CAMERA_MODEL_ESP32S3_EYE
* CAMERA_MODEL_XIAO_ESP32S3
* Camera connected to ESP board, only ones with PSRAM are supported
*/
// #define CAMERA_DEVICE CAMERA_MODEL_AI_THINKER
// #define CAMERA_DEVICE CAMERA_MODEL_XIAO_ESP32S3
/* Flip vertically
* Flip camera vertically
@ -621,9 +629,9 @@
// LOG_OUTPUT_SERIAL2
// LOG_OUTPUT_TELNET
// LOG_OUTPUT_WEBSOCKET
// #define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
//#define ESP_LOG_FEATURE LOG_OUTPUT_SERIAL0
// #define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
//#define ESP3D_DEBUG_LEVEL LOG_LEVEL_DEBUG
#ifdef ESP_LOG_FEATURE
#define LOG_ESP3D_BAUDRATE 115200

View File

@ -26,15 +26,11 @@ const char* help[] = {
"[ESP100](SSID) - display/set STA SSID",
"[ESP101](Password) - set STA password",
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
"[ESP102](Mode) - display/set STA IP mode (DHCP/STATIC)",
"[ESP103](IP=xxxx MSK=xxxx GW=xxxx) - display/set STA IP/Mask/GW",
#endif // WIFI_FEATURE || ETH_FEATURE
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
"[ESP104](State) - display/set sta fallback mode which can be BT, SETUP, "
"OFF",
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE
#if defined(WIFI_FEATURE)
"[ESP105](SSID) - display/set AP SSID",
"[ESP106](Password) - set AP password",
"[ESP107](IP) - display/set AP IP",
@ -53,6 +49,11 @@ const char* help[] = {
"[ESP115](State) - display/set immediate Network state which can be ON, "
"OFF",
#endif // WIFI_FEATURE || ETH_FEATURE || BT_FEATURE
#if defined(ETH_FEATURE)
"[ESP116](Mode) - display/set ETH STA IP mode (DHCP/STATIC)",
"[ESP117](IP=xxxx MSK=xxxx GW=xxxx) - display/set ETH STA IP/Mask/GW",
"[ESP118](State) - display/set eth sta fallback mode which can be BT, Off",
#endif // ETH_FEATURE
#if defined(HTTP_FEATURE)
"[ESP120](State) - display/set HTTP state which can be ON, OFF",
"[ESP121](Port) - display/set HTTP port ",
@ -196,13 +197,9 @@ const uint cmdlist[] = {
#if defined(WIFI_FEATURE)
100, 101,
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
102, 103,
#endif // WIFI_FEATURE || ETH_FEATURE
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
104,
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE
#if defined(WIFI_FEATURE)
102, 103,
104,
105, 106, 107, 108,
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
@ -214,6 +211,9 @@ const uint cmdlist[] = {
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE) || defined(BT_FEATURE)
112, 114, 115,
#endif // WIFI_FEATURE || ETH_FEATURE || BT_FEATURE
#if defined(ETH_FEATURE)
116, 117, 118,
#endif // ETH_FEATURE
#if defined(HTTP_FEATURE)
120, 121,
#endif // HTTP_FEATURE

View File

@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
#include "../esp3d_settings.h"
@ -26,9 +26,6 @@
#if defined(WIFI_FEATURE)
#include "../../modules/wifi/wificonfig.h"
#endif // WIFI_FEATURE
#if defined(ETH_FEATURE)
#include "../../modules/ethernet/ethconfig.h"
#endif // ETH_FEATURE
#include "../../modules/authentication/authentication_service.h"
#define COMMAND_ID 102
// Change STA IP mode (DHCP/STATIC)
@ -97,4 +94,4 @@ void ESP3DCommands::ESP102(int cmd_params_pos, ESP3DMessage* msg) {
}
}
#endif // WIFI_FEATURE || ETH_FEATURE
#endif // WIFI_FEATURE

View File

@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
#include "../esp3d_settings.h"
@ -26,9 +26,6 @@
#if defined(WIFI_FEATURE)
#include "../../modules/wifi/wificonfig.h"
#endif // WIFI_FEATURE
#if defined(ETH_FEATURE)
#include "../../modules/ethernet/ethconfig.h"
#endif // ETH_FEATURE
#include "../../modules/authentication/authentication_service.h"
#define COMMAND_ID 103
// Change STA IP/Mask/GW
@ -121,4 +118,4 @@ void ESP3DCommands::ESP103(int cmd_params_pos, ESP3DMessage* msg) {
}
}
#endif // WIFI_FEATURE || ETH_FEATURE
#endif // WIFI_FEATURE

View File

@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
#include "../../modules/authentication/authentication_service.h"
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
@ -54,11 +54,6 @@ void ESP3DCommands::ESP104(int cmd_params_pos, ESP3DMessage* msg) {
ok_msg = "BT";
} else
#endif // BLUETOOTH_FEATURE
#if defined(WIFI_FEATURE)
if (byteValue == (uint8_t)ESP_AP_SETUP) {
ok_msg = "CONFIG";
} else
#endif // WIFI_FEATURE
if (byteValue == (uint8_t)ESP_NO_NETWORK) {
ok_msg = "OFF";
} else {
@ -76,11 +71,6 @@ void ESP3DCommands::ESP104(int cmd_params_pos, ESP3DMessage* msg) {
byteValue = (uint8_t)ESP_BT;
} else
#endif // BLUETOOTH_FEATURE
#if defined(WIFI_FEATURE)
if (tmpstr == "CONFIG") {
byteValue = (uint8_t)ESP_AP_SETUP;
} else
#endif // WIFI_FEATURE
if (tmpstr == "OFF") {
byteValue = (uint8_t)ESP_NO_NETWORK;
} else {

View File

@ -0,0 +1,94 @@
/*
ESP116.cpp - ESP3D command class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This code 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 code 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 code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(ETH_FEATURE)
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
#include "../esp3d_settings.h"
#include "../../modules/ethernet/ethconfig.h"
#include "../../modules/authentication/authentication_service.h"
#define COMMAND_ID 116
// Change ETH STA IP mode (DHCP/STATIC)
//[ESP116]<mode>[json=no] [pwd=<admin password>]
void ESP3DCommands::ESP116(int cmd_params_pos, ESP3DMessage* msg) {
ESP3DClientType target = msg->origin;
ESP3DRequest requestId = msg->request_id;
(void)requestId;
msg->target = target;
msg->origin = ESP3DClientType::command;
bool hasError = false;
String error_msg = "Invalid parameters";
String ok_msg = "ok";
bool json = hasTag(msg, cmd_params_pos, "json");
String tmpstr;
uint8_t byteValue = (uint8_t)-1;
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level == ESP3DAuthenticationLevel::guest) {
msg->authentication_level = ESP3DAuthenticationLevel::not_authenticated;
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
byteValue = ESP3DSettings::readByte(ESP_ETH_STA_IP_MODE);
if (byteValue == static_cast<uint8_t>(DHCP_MODE)) {
ok_msg = "DHCP";
} else if (byteValue == static_cast<uint8_t>(STATIC_IP_MODE)) {
ok_msg = "STATIC";
} else {
ok_msg = "Unknown:" + String(byteValue);
}
} else {
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level != ESP3DAuthenticationLevel::admin) {
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
if (tmpstr == "DHCP") {
byteValue = static_cast<uint8_t>(DHCP_MODE);
} else if (tmpstr == "STATIC") {
byteValue = static_cast<uint8_t>(STATIC_IP_MODE);
} else {
byteValue = (uint8_t)-1; // unknow flag so put outof range value
}
esp3d_log("got %s param for a value of %d, is valid %d", tmpstr.c_str(),
byteValue,
ESP3DSettings::isValidByteSetting(byteValue, ESP_ETH_STA_IP_MODE));
if (ESP3DSettings::isValidByteSetting(byteValue, ESP_ETH_STA_IP_MODE)) {
esp3d_log("Value %d is valid", byteValue);
if (!ESP3DSettings::writeByte(ESP_ETH_STA_IP_MODE, byteValue)) {
hasError = true;
error_msg = "Set value failed";
}
} else {
hasError = true;
error_msg = "Invalid parameter";
}
}
if (!dispatchAnswer(msg, COMMAND_ID, json, hasError,
hasError ? error_msg.c_str() : ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");
}
}
#endif // ETH_FEATURE

View File

@ -0,0 +1,118 @@
/*
ESP117.cpp - ESP3D command class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This code 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 code 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 code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(ETH_FEATURE)
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
#include "../esp3d_settings.h"
#include "../../modules/ethernet/ethconfig.h"
#include "../../modules/authentication/authentication_service.h"
#define COMMAND_ID 117
// Change ETH STA IP/Mask/GW
//[ESP117]IP=<IP> MSK=<IP> GW=<IP> DNS=<IP> [json=no] [pwd=<admin password>
void ESP3DCommands::ESP117(int cmd_params_pos, ESP3DMessage* msg) {
ESP3DClientType target = msg->origin;
ESP3DRequest requestId = msg->request_id;
(void)requestId;
msg->target = target;
msg->origin = ESP3DClientType::command;
bool hasError = false;
String error_msg = "Invalid parameters";
String ok_msg = "ok";
bool json = hasTag(msg, cmd_params_pos, "json");
String tmpstr;
const char* cmdList[] = {"IP=", "MSK=", "GW=", "DNS="};
uint8_t cmdListSize = sizeof(cmdList) / sizeof(char*);
const ESP3DSettingIndex settingIndex[] = {
ESP_ETH_STA_IP_VALUE, ESP_ETH_STA_MASK_VALUE, ESP_ETH_STA_GATEWAY_VALUE,
ESP_ETH_STA_DNS_VALUE};
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level == ESP3DAuthenticationLevel::guest) {
msg->authentication_level = ESP3DAuthenticationLevel::not_authenticated;
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
if (json) {
ok_msg = "{\"ip\":\"";
} else {
ok_msg = "IP: ";
}
ok_msg += ESP3DSettings::readIPString(ESP_ETH_STA_IP_VALUE);
if (json) {
ok_msg += "\",\"gw\":\"";
} else {
ok_msg += ", GW: ";
}
ok_msg += ESP3DSettings::readIPString(ESP_ETH_STA_GATEWAY_VALUE);
if (json) {
ok_msg += "\",\"msk\":\"";
} else {
ok_msg += ", MSK: ";
}
ok_msg += ESP3DSettings::readIPString(ESP_ETH_STA_MASK_VALUE);
if (json) {
ok_msg += "\",\"dns\":\"";
} else {
ok_msg += ", DNS: ";
}
ok_msg += ESP3DSettings::readIPString(ESP_ETH_STA_DNS_VALUE);
if (json) {
ok_msg += "\"}";
}
} else {
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level != ESP3DAuthenticationLevel::admin) {
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
bool hasParam = false;
for (uint8_t i = 0; i < cmdListSize; i++) {
tmpstr = get_param(msg, cmd_params_pos, cmdList[i]);
if (tmpstr.length() != 0) {
hasParam = true;
if (ESP3DSettings::isValidIPStringSetting(tmpstr.c_str(),
settingIndex[i])) {
esp3d_log("Value %s is valid", tmpstr.c_str());
if (!ESP3DSettings::writeIPString(settingIndex[i], tmpstr.c_str())) {
hasError = true;
error_msg = "Set value failed";
}
} else {
hasError = true;
error_msg = "Invalid parameter";
}
}
}
if (!hasParam && !hasError) {
hasError = true;
error_msg = "Invalid parameter";
}
}
if (!dispatchAnswer(msg, COMMAND_ID, json, hasError,
hasError ? error_msg.c_str() : ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");
}
}
#endif // ETH_FEATURE

View File

@ -0,0 +1,101 @@
/*
ESP118.cpp - ESP3D command class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This code 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 code 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 code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#if defined(ETH_FEATURE)
#include "../../modules/authentication/authentication_service.h"
#include "../../modules/network/netconfig.h"
#include "../esp3d_commands.h"
#include "../esp3d_settings.h"
#define COMMAND_ID 118
// Set ETH STA fallback mode state at boot which can be BT, WIFI-SETUP, OFF
//[ESP118]<state> json=<no> pwd=<admin password>
void ESP3DCommands::ESP118(int cmd_params_pos, ESP3DMessage* msg) {
ESP3DClientType target = msg->origin;
ESP3DRequest requestId = msg->request_id;
(void)requestId;
msg->target = target;
msg->origin = ESP3DClientType::command;
bool hasError = false;
String error_msg = "Invalid parameters";
String ok_msg = "ok";
bool json = hasTag(msg, cmd_params_pos, "json");
String tmpstr;
uint8_t byteValue = (uint8_t)-1;
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level == ESP3DAuthenticationLevel::guest) {
msg->authentication_level = ESP3DAuthenticationLevel::not_authenticated;
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
byteValue = ESP3DSettings::readByte(ESP_ETH_STA_FALLBACK_MODE);
#if defined(BLUETOOTH_FEATURE)
if (byteValue == (uint8_t)ESP_BT) {
ok_msg = "BT";
} else
#endif // BLUETOOTH_FEATURE
if (byteValue == (uint8_t)ESP_NO_NETWORK) {
ok_msg = "OFF";
} else {
ok_msg = "Unknown";
}
} else {
#if defined(AUTHENTICATION_FEATURE)
if (msg->authentication_level != ESP3DAuthenticationLevel::admin) {
dispatchAuthenticationError(msg, COMMAND_ID, json);
return;
}
#endif // AUTHENTICATION_FEATURE
#if defined(BLUETOOTH_FEATURE)
if (tmpstr == "BT") {
byteValue = (uint8_t)ESP_BT;
} else
#endif // BLUETOOTH_FEATURE
if (tmpstr == "OFF") {
byteValue = (uint8_t)ESP_NO_NETWORK;
} else {
byteValue = (uint8_t)-1; // unknow flag so put outof range value
}
esp3d_log(
"got %s param for a value of %d, is valid %d", tmpstr.c_str(),
byteValue,
ESP3DSettings::isValidByteSetting(byteValue, ESP_ETH_STA_FALLBACK_MODE));
if (ESP3DSettings::isValidByteSetting(byteValue, ESP_ETH_STA_FALLBACK_MODE)) {
esp3d_log("Value %d is valid", byteValue);
if (!ESP3DSettings::writeByte(ESP_ETH_STA_FALLBACK_MODE, byteValue)) {
hasError = true;
error_msg = "Set value failed";
}
} else {
hasError = true;
error_msg = "Invalid parameter";
}
}
if (!dispatchAnswer(msg, COMMAND_ID, json, hasError,
hasError ? error_msg.c_str() : ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");
}
}
#endif // ETH_FEATURE

View File

@ -51,23 +51,40 @@ void ESP3DCommands::ESP301(int cmd_params_pos, ESP3DMessage* msg) {
#endif // AUTHENTICATION_FEATURE
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
String error = esp3d_lua_interpreter.getLastError();
if (!esp3d_lua_interpreter.isScriptRunning()) {
if (json) {
ok_msg = "{\"status\":\"idle\"}";
ok_msg = "{\"status\":\"idle\"";
if (error.length() > 0) {
ok_msg += ",\"error\":\"" + error + "\"";
}
ok_msg+="}";
} else {
ok_msg = "idle";
if (error.length() > 0) {
ok_msg += ", error: " + error;
}
}
} else {
String status =
esp3d_lua_interpreter.isScriptPaused() ? "paused" : "running";
if (error.length() > 0) {
status = "error";
}
String scriptName = esp3d_lua_interpreter.getCurrentScriptName();
String duration = esp3d_string::formatDuration(
esp3d_lua_interpreter.getExecutionTime());
if (json) {
String errorMsg = error.length() > 0 ? ",\"error\":\"" + error + "\"" : "";
ok_msg = "{\"status\":\"" + status + "\",\"script\":\"" + scriptName +
"\",\"duration\":\"" + duration + "\"}";
"\",\"duration\":\"" + duration + "\"" + errorMsg + "}";
} else {
ok_msg = status + ", " + scriptName + ", duration " + duration;
ok_msg = status;
if (error.length() > 0) {
ok_msg += ": " + error;
}
ok_msg += ", " + scriptName + ", duration " + duration;
}
}
} else {
@ -113,7 +130,7 @@ void ESP3DCommands::ESP301(int cmd_params_pos, ESP3DMessage* msg) {
}
}
} else if (tmpstr == "ABORT") {
esp3d_lua_interpreter.abortCurrentScript();
esp3d_lua_interpreter.abortScript();
ok_msg = "Script aborted";
}
} else {

View File

@ -91,6 +91,19 @@ const char* FallbackValues[] = {"0"
#endif // BLUETOOTH_FEATURE
};
const char* EthFallbackValues[] = {"0"
#ifdef BLUETOOTH_FEATURE
,
"3"
#endif // BLUETOOTH_FEATURE
};
const char* EthFallbackLabels[] = {"none"
#ifdef BLUETOOTH_FEATURE
,
"bt"
#endif // BLUETOOTH_FEATURE
};
const char* FirmwareLabels[] = {"Unknown", "Grbl", "Marlin", "Smoothieware",
"Repetier"};
@ -204,6 +217,30 @@ void ESP3DCommands::ESP400(int cmd_params_pos, ESP3DMessage* msg) {
dispatchSetting(json, "network/network", ESP_BOOT_RADIO_STATE, "radio_boot",
YesNoValues, YesNoLabels, sizeof(YesNoValues) / sizeof(char*),
-1, -1, -1, NULL, true, target, requestId);
#if defined(ETH_FEATURE)
// Ethernet STA IP mode
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_IP_MODE, "ip mode", IpModeValues,
IpModeLabels, sizeof(IpModeLabels) / sizeof(char*), -1, -1,
-1, nullptr, true, target, requestId);
// Ethernet STA static IP
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_IP_VALUE, "ip", nullptr, nullptr,
-1, -1, -1, -1, nullptr, true, target, requestId);
// Ethernet STA static Gateway
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_GATEWAY_VALUE, "gw", nullptr,
nullptr, -1, -1, -1, -1, nullptr, true, target, requestId);
// Ethernet STA static Mask
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_MASK_VALUE, "msk", nullptr,
nullptr, -1, -1, -1, -1, nullptr, true, target, requestId);
// Ethernet STA static DNS
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_DNS_VALUE, "DNS", nullptr,
nullptr, -1, -1, -1, -1, nullptr, true, target, requestId);
// Ethernet Sta fallback mode
dispatchSetting(json, "network/eth-sta", ESP_ETH_STA_FALLBACK_MODE,
"sta fallback mode", EthFallbackValues, EthFallbackLabels,
sizeof(EthFallbackValues) / sizeof(char*), -1, -1, -1, nullptr,
true, target, requestId);
#endif // ETH_FEATURE
#ifdef WIFI_FEATURE
// STA SSID network/sta
dispatchSetting(json, "network/sta", ESP_STA_SSID, "SSID", nullptr, nullptr,
@ -214,7 +251,7 @@ void ESP3DCommands::ESP400(int cmd_params_pos, ESP3DMessage* msg) {
nullptr, 64, 8, 0, -1, nullptr, true, target, requestId);
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
// STA IP mode
dispatchSetting(json, "network/sta", ESP_STA_IP_MODE, "ip mode", IpModeValues,
IpModeLabels, sizeof(IpModeLabels) / sizeof(char*), -1, -1,
@ -233,15 +270,15 @@ void ESP3DCommands::ESP400(int cmd_params_pos, ESP3DMessage* msg) {
dispatchSetting(json, "network/sta", ESP_STA_DNS_VALUE, "DNS", nullptr,
nullptr, -1, -1, -1, -1, nullptr, true, target, requestId);
#endif // WIFI_FEATURE || ETH_FEATURE
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE) || defined(BT_FEATURE)
#if defined(WIFI_FEATURE)
// Sta fallback mode
dispatchSetting(json, "network/sta", ESP_STA_FALLBACK_MODE,
"sta fallback mode", FallbackValues, FallbackLabels,
sizeof(FallbackValues) / sizeof(char*), -1, -1, -1, nullptr,
true, target, requestId);
#endif // WIFI_FEATURE || ETH_FEATURE || BT_FEATURE
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE)
// AP SSID network/ap
dispatchSetting(json, "network/ap", ESP_AP_SSID, "SSID", nullptr, nullptr, 32,

View File

@ -157,6 +157,14 @@ void ESP3DCommands::ESP420(int cmd_params_pos, ESP3DMessage* msg) {
// FW architecture
tmpstr = ESP3DSettings::TargetBoard();
#ifdef ARDUINO_ARCH_ESP32
tmpstr = ESP.getChipModel();
tmpstr+="-";
tmpstr+=ESP.getChipRevision();
tmpstr+="-";
tmpstr+=ESP.getChipCores();
tmpstr+="@";
#endif // ARDUINO_ARCH_ESP32
if (!dispatchIdValue(json, "FW arch", tmpstr.c_str(), target, requestId,
false)) {
return;
@ -389,6 +397,7 @@ void ESP3DCommands::ESP420(int cmd_params_pos, ESP3DMessage* msg) {
return;
}
// IP mode
esp3d_log_d("IP mode %d", NetConfig::isIPModeDHCP(ESP_ETH_STA));
tmpstr = (NetConfig::isIPModeDHCP(ESP_ETH_STA)) ? "dhcp" : "static";
if (!dispatchIdValue(json, "ip mode", tmpstr.c_str(), target, requestId,
false)) {
@ -418,6 +427,11 @@ void ESP3DCommands::ESP420(int cmd_params_pos, ESP3DMessage* msg) {
false)) {
return;
}
} else {
if (!dispatchIdValue(json, "ethernet", "OFF", target, requestId,
false)) {
return;
}
}
#endif // ETH_FEATURE
#if defined(WIFI_FEATURE)

View File

@ -56,7 +56,7 @@ void ESP3DCommands::ESP710(int cmd_params_pos, ESP3DMessage* msg) {
} else {
if (formatfs) {
ok_msg = "Starting formating...";
endMsg = ESP3DMessageManager::copyMsgInfos(*msg);
endMsg = esp3d_message_manager.copyMsgInfos(*msg);
} else {
hasError = true;
error_msg = "Invalid parameter";

View File

@ -57,7 +57,7 @@ void ESP3DCommands::ESP715(int cmd_params_pos, ESP3DMessage* msg) {
if (formatsd) {
if (ESP_SD::getState() != ESP_SDCARD_BUSY) {
ok_msg = "Starting formating...";
endMsg = ESP3DMessageManager::copyMsgInfos(*msg);
endMsg = esp3d_message_manager.copyMsgInfos(*msg);
} else {
hasError = true;
error_msg = "SD card busy";

View File

@ -49,7 +49,11 @@ void ESP3DCommands::ESP720(int cmd_params_pos, ESP3DMessage* msg) {
#endif // AUTHENTICATION_FEATURE
ESP3DMessage msgInfo;
ESP3DMessageManager::copyMsgInfos(&msgInfo, *msg);
esp3d_log("Copy msg infos");
if (!esp3d_message_manager.copyMsgInfos(&msgInfo, *msg)) {
esp3d_log_e("Error copying msg infos");
return;
}
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
@ -104,7 +108,7 @@ void ESP3DCommands::ESP720(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -156,7 +160,7 @@ void ESP3DCommands::ESP720(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -202,7 +206,7 @@ void ESP3DCommands::ESP720(int cmd_params_pos, ESP3DMessage* msg) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
newMsg->type = ESP3DMessageType::tail;
if (!dispatch(newMsg, ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");

View File

@ -49,7 +49,7 @@ void ESP3DCommands::ESP740(int cmd_params_pos, ESP3DMessage* msg) {
#endif // AUTHENTICATION_FEATURE
ESP3DMessage msgInfo;
ESP3DMessageManager::copyMsgInfos(&msgInfo, *msg);
esp3d_message_manager.copyMsgInfos(&msgInfo, *msg);
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
@ -118,7 +118,7 @@ void ESP3DCommands::ESP740(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -170,7 +170,7 @@ void ESP3DCommands::ESP740(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -216,7 +216,7 @@ void ESP3DCommands::ESP740(int cmd_params_pos, ESP3DMessage* msg) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
newMsg->type = ESP3DMessageType::tail;
if (!dispatch(newMsg, ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");

View File

@ -49,7 +49,7 @@ void ESP3DCommands::ESP780(int cmd_params_pos, ESP3DMessage* msg) {
#endif // AUTHENTICATION_FEATURE
ESP3DMessage msgInfo;
ESP3DMessageManager::copyMsgInfos(&msgInfo, *msg);
esp3d_message_manager.copyMsgInfos(&msgInfo, *msg);
tmpstr = get_clean_param(msg, cmd_params_pos);
if (tmpstr.length() == 0) {
@ -105,7 +105,7 @@ void ESP3DCommands::ESP780(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -157,7 +157,7 @@ void ESP3DCommands::ESP780(int cmd_params_pos, ESP3DMessage* msg) {
if (!json) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
if (newMsg) {
newMsg->type = ESP3DMessageType::core;
if (!dispatch(newMsg, ok_msg.c_str())) {
@ -203,7 +203,7 @@ void ESP3DCommands::ESP780(int cmd_params_pos, ESP3DMessage* msg) {
ok_msg += "\n";
}
ESP3DMessage* newMsg = ESP3DMessageManager::copyMsgInfos(msgInfo);
ESP3DMessage* newMsg = esp3d_message_manager.copyMsgInfos(msgInfo);
newMsg->type = ESP3DMessageType::tail;
if (!dispatch(newMsg, ok_msg.c_str())) {
esp3d_log_e("Error sending response to clients");

View File

@ -55,6 +55,9 @@
#endif // SD_UPDATE_FEATURE
#include "../modules/boot_delay/boot_delay.h"
#include "esp3d_message.h"
#ifdef ESP_LUA_INTERPRETER_FEATURE
#include "../modules/lua_interpreter/lua_interpreter_service.h"
#endif // ESP_LUA_INTERPRETER_FEATURE
bool Esp3D::restart = false;
@ -179,6 +182,10 @@ void Esp3D::handle() {
#if defined(GCODE_HOST_FEATURE)
esp3d_gcode_host.handle();
#endif // GCODE_HOST_FEATURE
#ifdef ESP_LUA_INTERPRETER_FEATURE
esp3d_lua_interpreter.handle();
#endif // ESP_LUA_INTERPRETER_FEATURE
}
bool Esp3D::started() { return _started; }

View File

@ -388,7 +388,7 @@ void ESP3DCommands::execute_internal_command(int cmd, int cmd_params_pos,
ESP101(cmd_params_pos, msg);
break;
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
// Change STA IP mode (DHCP/STATIC)
//[ESP102]<mode>pwd=<admin password>
case 102:
@ -399,15 +399,11 @@ void ESP3DCommands::execute_internal_command(int cmd, int cmd_params_pos,
case 103:
ESP103(cmd_params_pos, msg);
break;
#endif // WIFI_FEATURE ||ETH_FEATURE
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
// Set fallback mode which can be BT, WIFI-AP, OFF
//[ESP104]<state>pwd=<admin password>
case 104:
ESP104(cmd_params_pos, msg);
break;
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE)
#if defined(WIFI_FEATURE)
// AP SSID
//[ESP105]<SSID>[pwd=<admin password>]
case 105:
@ -465,6 +461,24 @@ void ESP3DCommands::execute_internal_command(int cmd, int cmd_params_pos,
break;
#endif // WIFI_FEATURE|| ETH_FEATURE || BT_FEATURE
#if defined(ETH_FEATURE)
// Change ETH STA IP mode (DHCP/STATIC)
//[ESP116]<mode>pwd=<admin password>
case 116:
ESP102(cmd_params_pos, msg);
break;
// Change ETH STA IP/Mask/GW
//[ESP117]IP=<IP> MSK=<IP> GW=<IP> pwd=<admin password>
case 117:
ESP117(cmd_params_pos, msg);
break;
// Set fallback mode which can be BT, OFF
//[ESP118]<state>pwd=<admin password>
case 118:
ESP118(cmd_params_pos, msg);
break;
#endif // ETH_FEATURE
#ifdef HTTP_FEATURE
// Set HTTP state which can be ON, OFF
//[ESP120]<state>pwd=<admin password>
@ -1165,9 +1179,9 @@ void ESP3DCommands::process(ESP3DMessage *msg) {
esp3d_log("Execute internal command %d", cmdId);
execute_internal_command(cmdId, espcmdpos, msg);
} else {
esp3d_log("Dispatch command, len %d, from %d(%s) to %d(%s)", msg->size,
/*esp3d_log("Dispatch command, len %d, from %d(%s) to %d(%s)", msg->size,
static_cast<uint8_t>(msg->origin), GETCLIENTSTR(msg->origin),
static_cast<uint8_t>(msg->target), GETCLIENTSTR(msg->target));
static_cast<uint8_t>(msg->target), GETCLIENTSTR(msg->target));*/
// Work around to avoid to dispatch single \n or \r to everyone as it is
// part of previous ESP3D command
@ -1177,10 +1191,11 @@ void ESP3DCommands::process(ESP3DMessage *msg) {
lastIsESP3D = false;
// delete message
esp3d_log("Delete message");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
return;
}
lastIsESP3D = false;
esp3d_log("Dispatch message: %s", msg->data);
dispatch(msg);
}
}
@ -1206,25 +1221,25 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg, uint8_t *sbuf, size_t len) {
}
tmpstr += '\n';
esp3d_log("update command success: *%s*", tmpstr.c_str());
if (!ESP3DMessageManager::setDataContent(msg, (uint8_t *)tmpstr.c_str(),
if (!esp3d_message_manager.setDataContent(msg, (uint8_t *)tmpstr.c_str(),
tmpstr.length())) {
esp3d_log_e("set data content failed");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
return false;
}
} else {
esp3d_log("format command success, no need to update");
if (!ESP3DMessageManager::setDataContent(msg, sbuf, len)) {
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
esp3d_log_e("set data content failed");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
return false;
}
}
} else {
esp3d_log("not unique or tail message");
if (!ESP3DMessageManager::setDataContent(msg, sbuf, len)) {
if (!esp3d_message_manager.setDataContent(msg, sbuf, len)) {
esp3d_log_e("set data content failed");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
return false;
}
}
@ -1235,7 +1250,7 @@ bool ESP3DCommands::dispatch(uint8_t *sbuf, size_t size, ESP3DClientType target,
ESP3DRequest requestId, ESP3DMessageType type,
ESP3DClientType origin,
ESP3DAuthenticationLevel authentication_level) {
ESP3DMessage *newMsgPtr = ESP3DMessageManager::newMsg(origin, target);
ESP3DMessage *newMsgPtr = esp3d_message_manager.newMsg(origin, target);
if (newMsgPtr) {
newMsgPtr->request_id = requestId;
newMsgPtr->type = type;
@ -1249,7 +1264,7 @@ bool ESP3DCommands::dispatch(const char *sbuf, ESP3DClientType target,
ESP3DRequest requestId, ESP3DMessageType type,
ESP3DClientType origin,
ESP3DAuthenticationLevel authentication_level) {
ESP3DMessage *newMsgPtr = ESP3DMessageManager::newMsg(origin, target);
ESP3DMessage *newMsgPtr = esp3d_message_manager.newMsg(origin, target);
if (newMsgPtr) {
newMsgPtr->request_id = requestId;
newMsgPtr->type = type;
@ -1281,7 +1296,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
switch (msg->target) {
case ESP3DClientType::no_client:
esp3d_log("No client message");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
break;
#if COMMUNICATION_PROTOCOL == RAW_SERIAL
case ESP3DClientType::serial:
@ -1303,7 +1318,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
MYSERIAL1.write('\n');
}
}
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
break;
case ESP3DClientType::socket_serial:
@ -1413,7 +1428,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
tmp.replace("\n", " ");
tmp.replace("\r", "");
tmp += "\n";
if (ESP3DMessageManager::setDataContent(msg, (uint8_t *)tmp.c_str(),
if (esp3d_message_manager.setDataContent(msg, (uint8_t *)tmp.c_str(),
tmp.length())) {
return dispatch(msg);
}
@ -1432,7 +1447,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::remote_screen;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::remote_screen;
dispatch(copy_msg);
@ -1451,7 +1466,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::lua_script;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::lua_script;
dispatch(copy_msg);
@ -1471,7 +1486,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->request_id.id = ESP_OUTPUT_STATUS;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::rendering;
copy_msg->request_id.id = ESP_OUTPUT_STATUS;
@ -1491,7 +1506,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::echo_serial;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::echo_serial;
dispatch(copy_msg);
@ -1509,7 +1524,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::serial_bridge;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::serial_bridge;
dispatch(copy_msg);
@ -1528,7 +1543,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::bluetooth;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::bluetooth;
dispatch(copy_msg);
@ -1547,7 +1562,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::telnet;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::telnet;
dispatch(copy_msg);
@ -1570,7 +1585,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::webui_websocket;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::webui_websocket;
dispatch(copy_msg);
@ -1592,7 +1607,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
msg->target = ESP3DClientType::websocket;
} else {
// duplicate message because current is already pending
ESP3DMessage *copy_msg = ESP3DMessageManager::copyMsg(*msg);
ESP3DMessage *copy_msg = esp3d_message_manager.copyMsg(*msg);
if (copy_msg) {
copy_msg->target = ESP3DClientType::websocket;
dispatch(copy_msg);
@ -1624,7 +1639,7 @@ bool ESP3DCommands::dispatch(ESP3DMessage *msg) {
// clear message
if (!sendOk) {
esp3d_log_e("Send msg failed");
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
}
return sendOk;
}

View File

@ -53,14 +53,10 @@ class ESP3DCommands {
void ESP100(int cmd_params_pos, ESP3DMessage* msg);
void ESP101(int cmd_params_pos, ESP3DMessage* msg);
#endif // WIFI_FEATURE
#if defined(WIFI_FEATURE) || defined(ETH_FEATURE)
#if defined(WIFI_FEATURE)
void ESP102(int cmd_params_pos, ESP3DMessage* msg);
void ESP103(int cmd_params_pos, ESP3DMessage* msg);
#endif // WIFI_FEATURE ||ETH_FEATURE
#if defined(WIFI_FEATURE) || defined(BLUETOOTH_FEATURE) || defined(ETH_FEATURE)
void ESP104(int cmd_params_pos, ESP3DMessage* msg);
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE
#if defined(WIFI_FEATURE)
void ESP105(int cmd_params_pos, ESP3DMessage* msg);
void ESP106(int cmd_params_pos, ESP3DMessage* msg);
void ESP107(int cmd_params_pos, ESP3DMessage* msg);
@ -77,6 +73,11 @@ class ESP3DCommands {
void ESP114(int cmd_params_pos, ESP3DMessage* msg);
void ESP115(int cmd_params_pos, ESP3DMessage* msg);
#endif // WIFI_FEATURE || BLUETOOTH_FEATURE || ETH_FEATURE
#if defined(ETH_FEATURE)
void ESP116(int cmd_params_pos, ESP3DMessage* msg);
void ESP117(int cmd_params_pos, ESP3DMessage* msg);
void ESP118(int cmd_params_pos, ESP3DMessage* msg);
#endif // ETH_FEATURE
#if defined(HTTP_FEATURE)
void ESP120(int cmd_params_pos, ESP3DMessage* msg);
void ESP121(int cmd_params_pos, ESP3DMessage* msg);

View File

@ -34,9 +34,13 @@
#endif // __has_include ("rtc_wdt.h")
#endif // CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#include <WiFi.h>
#include <driver/adc.h>
#include <esp_adc/adc_continuous.h>
#include <esp_adc/adc_oneshot.h>
#include <esp_task_wdt.h>
#if !CONFIG_IDF_TARGET_ESP32C6
#include <soc/rtc_cntl_reg.h>
#endif // !CONFIG_IDF_TARGET_ESP32C6
TaskHandle_t ESP3DHal::xHandle = nullptr;
#endif // ARDUINO_ARCH_ESP32
@ -135,10 +139,7 @@ void ESP3DHal::analogRange(uint32_t range) {
// Setup
bool ESP3DHal::begin() {
#if defined(ARDUINO_ARCH_ESP32) && defined(CAMERA_DEVICE)
esp3d_log("Disable brown out");
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
#endif // ARDUINO_ARCH_ESP32 && CAMERA_DEVICE
checkTWDT();
// Clear all wifi state
WiFi.persistent(false);
WiFi.disconnect(true);
@ -160,47 +161,61 @@ bool ESP3DHal::begin() {
// End ESP3D
void ESP3DHal::end() {}
void ESP3DHal::checkTWDT() {
// ESP32-C6 Seems not working with esp_task_wdt_reset()
// I itinitally though it was wrong initialization of TWDT
// doing esp_task_wdt_init() is not working
// but esp_task_wdt_reconfigure() is working
// unfortunately it is still not working with esp_task_wdt_reset()
// so because doing esp_task_wdt_reconfigure and not do not change the
// behavior so I comment it for now as note Instead I use vTaskDelay(1) to
// feed the WDT and seems ok delay(1) seems also ok
/*
#if CONFIG_IDF_TARGET_ESP32C6
//ESP32-C6
esp_err_t err = esp_task_wdt_status(NULL);
if (err == ESP_ERR_NOT_FOUND) {
esp3d_log_e("WDT was never initialized");
esp_task_wdt_config_t twdt_config = {
.timeout_ms = 2 * 1000,
.idle_core_mask = (1 << 0),
.trigger_panic = true,
};
err = esp_task_wdt_reconfigure(&twdt_config);
if (err == ESP_ERR_INVALID_STATE) {
esp3d_log_e("WDT already initialized");
} else if (err != ESP_OK) {
esp3d_log_e("WDT cannot be setup");
} else {
esp3d_log("WDT setup ok");
}
}
#endif // CONFIG_IDF_TARGET_ESP32C6
*/
}
// Watchdog feeder
void ESP3DHal::wdtFeed() {
#ifdef ARDUINO_ARCH_ESP32
vTaskDelay(1);
return;
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
ESP.wdtFeed();
#endif // ARDUINO_ARCH_ESP8266
#ifdef ARDUINO_ARCH_ESP32
static uint64_t lastYield = 0;
uint64_t now = millis();
if ((now - lastYield) > 2000) {
lastYield = now;
vTaskDelay(5); // delay 1 RTOS tick
}
#if !defined(DISABLE_WDT_ESP3DLIB_TASK) && !defined(DISABLE_WDT_CORE_0)
#if CONFIG_IDF_TARGET_ESP32
// FIXME: not implemented
rtc_wdt_feed();
#endif // CONFIG_IDF_TARGET_ESP32S2
#endif //! defined(DISABLE_WDT_ESP3DLIB_TASK) && !defined(DISABLE_WDT_CORE_0)
#ifndef DISABLE_WDT_ESP3DLIB_TASK
if (xHandle && esp_task_wdt_status(xHandle) == ESP_OK) {
if (esp_task_wdt_reset() != ESP_OK) {
esp3d_log_e("WDT Reset failed");
}
}
#endif // DISABLE_WDT_ESP3DLIB_TASK
#endif // ARDUINO_ARCH_ESP32
}
// wait function
void ESP3DHal::wait(uint32_t milliseconds) {
#if defined(ASYNCWEBSERVER)
#ifdef ARDUINO_ARCH_ESP32
uint32_t timeout = millis();
while ((millis() - timeout) < milliseconds) {
wdtFeed();
}
#else // !(ASYNCWEBSERVER
wdtFeed();
// before 0 was acceptable, now it seems need to put 5 to have some effect if
// on esp32 core 0
delay(milliseconds < 5 ? 5 : milliseconds);
#endif // !ASYNCWEBSERVER
#endif // CONFIG_IDF_TARGET_ESP32
#ifdef ARDUINO_ARCH_ESP8266
delay(milliseconds);
#endif // ARDUINO_ARCH_ESP8266
}
uint16_t ESP3DHal::getChipID() {

View File

@ -49,6 +49,7 @@ class ESP3DHal {
static void analogWriteFreq(uint32_t freq);
static void analogRange(uint32_t range);
static const char * arduinoVersion();
static void checkTWDT();
#if defined(ARDUINO_ARCH_ESP32)
static TaskHandle_t xHandle;
#endif // ARDUINO_ARCH_ESP32

View File

@ -24,28 +24,67 @@
ESP3DRequest no_id{.id = 0};
ESP3DMessageManager esp3d_message_manager;
ESP3DMessageManager::ESP3DMessageManager() {
_mutex = xSemaphoreCreateMutex();
#if defined(ESP_LOG_FEATURE)
int msg_counting = 0;
_msg_counting = 0;
#endif // ESP_LOG_FEATURE
}
ESP3DMessageManager::~ESP3DMessageManager() { vSemaphoreDelete(_mutex); }
bool ESP3DMessageManager::deleteMsg(ESP3DMessage* message) {
if (!message) return false;
esp3d_log("Delete msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
bool result = _deleteMsg(message);
xSemaphoreGive(_mutex);
esp3d_log("Delete msg done");
return result;
} else {
esp3d_log_e("Mutex not taken");
}
return false;
}
bool ESP3DMessageManager::_deleteMsg(ESP3DMessage* message) {
esp3d_log("_Delete msg");
if (!message) {
esp3d_log_e("Message is null");
return false;
}
if (message->data) {
esp3d_log("Free data");
free(message->data);
}
free(message);
message = NULL;
#if defined(ESP_LOG_FEATURE)
esp3d_log("Deletion : Now we have %ld msg", --msg_counting);
esp3d_log("Deletion : Now we have %ld msg", --_msg_counting);
#endif // ESP_LOG_FEATURE
return true;
}
ESP3DMessage* ESP3DMessageManager::newMsg() {
esp3d_log("New msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr = nullptr;
newMsgPtr = _newMsg();
xSemaphoreGive(_mutex);
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_newMsg() {
esp3d_log("_New msg");
ESP3DMessage* newMsgPtr = (ESP3DMessage*)malloc(sizeof(ESP3DMessage));
if (newMsgPtr) {
#if defined(ESP_LOG_FEATURE)
esp3d_log("Creation : Now we have %ld msg", ++msg_counting);
esp3d_log("Creation : Now we have %ld msg", ++_msg_counting);
#endif // ESP_LOG_FEATURE
newMsgPtr->data = nullptr;
newMsgPtr->size = 0;
@ -57,45 +96,113 @@ ESP3DMessage* ESP3DMessageManager::newMsg() {
} else {
esp3d_log_e("Out of memory");
}
esp3d_log("Message created");
return newMsgPtr;
}
ESP3DMessage* ESP3DMessageManager::newMsg(ESP3DRequest requestId) {
ESP3DMessage* newMsgPtr = newMsg();
esp3d_log("New msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr = nullptr;
newMsgPtr = _newMsg(requestId);
xSemaphoreGive(_mutex);
esp3d_log("New msg done");
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_newMsg(ESP3DRequest requestId) {
esp3d_log("_New msg");
ESP3DMessage* newMsgPtr = _newMsg();
if (newMsgPtr) {
esp3d_log("New msg done");
newMsgPtr->origin = ESP3DClientType::command;
newMsgPtr->request_id = requestId;
} else {
esp3d_log_e("newMsgPtr is null");
}
return newMsgPtr;
}
bool ESP3DMessageManager::copyMsgInfos(ESP3DMessage* newMsgPtr,
ESP3DMessage msg) {
esp3d_log("Copy msg infos");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
bool result = _copyMsgInfos(newMsgPtr, msg);
xSemaphoreGive(_mutex);
esp3d_log("Copy msg infos done");
return result;
} else {
esp3d_log_e("Mutex not taken");
}
return NULL;
}
bool ESP3DMessageManager::_copyMsgInfos(ESP3DMessage* newMsgPtr,
ESP3DMessage msg) {
esp3d_log("_Copy msg infos");
if (!newMsgPtr) {
esp3d_log_e("newMsgPtr is null");
return false;
}
esp3d_log("Copying msg infos");
newMsgPtr->origin = msg.origin;
newMsgPtr->target = msg.target;
newMsgPtr->authentication_level = msg.authentication_level;
newMsgPtr->request_id = msg.request_id;
newMsgPtr->type = msg.type;
return true;
}
ESP3DMessage* ESP3DMessageManager::copyMsgInfos(ESP3DMessage msg) {
ESP3DMessage* newMsgPtr = newMsg();
esp3d_log("Copy msg infos");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr = _copyMsgInfos(msg);
xSemaphoreGive(_mutex);
esp3d_log("Copy msg infos done");
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_copyMsgInfos(ESP3DMessage msg) {
esp3d_log("_Copy msg infos");
ESP3DMessage* newMsgPtr = _newMsg();
if (newMsgPtr) {
copyMsgInfos(newMsgPtr, msg);
_copyMsgInfos(newMsgPtr, msg);
} else {
esp3d_log_e("newMsg is null");
}
return newMsgPtr;
}
ESP3DMessage* ESP3DMessageManager::copyMsg(ESP3DMessage msg) {
ESP3DMessage* newMsgPtr = newMsg(msg.origin, msg.target, msg.data, msg.size,
esp3d_log("Copy msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr = _copyMsg(msg);
xSemaphoreGive(_mutex);
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_copyMsg(ESP3DMessage msg) {
esp3d_log("_Copy msg");
ESP3DMessage* newMsgPtr = _newMsg(msg.origin, msg.target, msg.data, msg.size,
msg.authentication_level);
if (newMsgPtr) {
newMsgPtr->request_id = msg.request_id;
newMsgPtr->type = msg.type;
} else {
esp3d_log_e("newMsgPtr is null");
}
return newMsgPtr;
}
@ -103,15 +210,36 @@ ESP3DMessage* ESP3DMessageManager::copyMsg(ESP3DMessage msg) {
ESP3DMessage* ESP3DMessageManager::newMsg(
ESP3DClientType origin, ESP3DClientType target, const uint8_t* data,
size_t length, ESP3DAuthenticationLevel authentication_level) {
ESP3DMessage* newMsgPtr = newMsg(origin, target, authentication_level);
esp3d_log("New msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr =
_newMsg(origin, target, data, length, authentication_level);
xSemaphoreGive(_mutex);
esp3d_log("New msg done");
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_newMsg(
ESP3DClientType origin, ESP3DClientType target, const uint8_t* data,
size_t length, ESP3DAuthenticationLevel authentication_level) {
ESP3DMessage* newMsgPtr = _newMsg(origin, target, authentication_level);
esp3d_log("_New msg");
if (newMsgPtr) {
if (!setDataContent(newMsgPtr, data, length)) {
deleteMsg(newMsgPtr);
if (!_setDataContent(newMsgPtr, data, length)) {
_deleteMsg(newMsgPtr);
newMsgPtr = nullptr;
esp3d_log_e("newMsg failed for origin %d, target %d, data %s",
(uint8_t)origin, (uint8_t)target,
data ? (char*)data : "null");
} else {
esp3d_log("Message created");
}
} else {
esp3d_log_e("newMsgPtr is null");
}
return newMsgPtr;
}
@ -119,17 +247,51 @@ ESP3DMessage* ESP3DMessageManager::newMsg(
ESP3DMessage* ESP3DMessageManager::newMsg(
ESP3DClientType origin, ESP3DClientType target,
ESP3DAuthenticationLevel authentication_level) {
ESP3DMessage* newMsgPtr = newMsg();
esp3d_log("New msg");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
ESP3DMessage* newMsgPtr = _newMsg(origin, target, authentication_level);
xSemaphoreGive(_mutex);
esp3d_log("New msg done");
return newMsgPtr;
} else {
esp3d_log_e("Mutex not taken");
}
return nullptr;
}
ESP3DMessage* ESP3DMessageManager::_newMsg(
ESP3DClientType origin, ESP3DClientType target,
ESP3DAuthenticationLevel authentication_level) {
esp3d_log("_New msg");
ESP3DMessage* newMsgPtr = _newMsg();
if (newMsgPtr) {
newMsgPtr->origin = origin;
newMsgPtr->target = target;
newMsgPtr->authentication_level = authentication_level;
} else {
esp3d_log_e("newMsgPtr is null");
}
esp3d_log("_New msg done");
return newMsgPtr;
}
bool ESP3DMessageManager::setDataContent(ESP3DMessage* msg, const uint8_t* data,
size_t length) {
esp3d_log("Set data content");
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
bool result = _setDataContent(msg, data, length);
xSemaphoreGive(_mutex);
esp3d_log("Set data content done");
return result;
} else {
esp3d_log_e("Mutex not taken");
}
return false;
}
bool ESP3DMessageManager::_setDataContent(ESP3DMessage* msg,
const uint8_t* data, size_t length) {
esp3d_log("_Set data content");
if (!msg) {
esp3d_log_e("no valid msg container");
return false;

View File

@ -25,8 +25,7 @@
#define ESP_STATE_DISCONNECTED 0
#ifndef _ESP3DOUTPUT_H
#define _ESP3DOUTPUT_H
#pragma once
#include "../include/esp3d_config.h"
@ -43,6 +42,23 @@ class WebServer;
#include "../modules/authentication/authentication_level_types.h"
#include "esp3d_client_types.h"
#if defined(ARDUINO_ARCH_ESP32)
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#endif // ARDUINO_ARCH_ESP32
#if defined(ARDUINO_ARCH_ESP8266)
//To avoid compilation error on ESP8266
// and to use many ifdefs
#ifndef pdTRUE
#define pdTRUE true
#define xSemaphoreTake(A, B) true
#define xSemaphoreGive(A)
#define xSemaphoreCreateMutex(A) 0
#define vSemaphoreDelete(A)
#define SemaphoreHandle_t void*
#endif //pdTRUE
#endif //ESP8266
enum class ESP3DMessageType : uint8_t { head, core, tail, unique };
@ -68,21 +84,44 @@ struct ESP3DMessage {
class ESP3DMessageManager final {
public:
static ESP3DMessage *newMsg();
static ESP3DMessage *newMsg(ESP3DRequest requestId);
static bool deleteMsg(ESP3DMessage *message);
static bool copyMsgInfos(ESP3DMessage *newMsgPtr, ESP3DMessage msg);
static ESP3DMessage *copyMsgInfos(ESP3DMessage msg);
static ESP3DMessage *copyMsg(ESP3DMessage msg);
static ESP3DMessage *newMsg(ESP3DClientType origin, ESP3DClientType target,
ESP3DMessageManager();
~ESP3DMessageManager();
ESP3DMessage *newMsg();
ESP3DMessage *newMsg(ESP3DRequest requestId);
bool deleteMsg(ESP3DMessage *message);
bool copyMsgInfos(ESP3DMessage *newMsgPtr, ESP3DMessage msg);
ESP3DMessage *copyMsgInfos(ESP3DMessage msg);
ESP3DMessage *copyMsg(ESP3DMessage msg);
ESP3DMessage *newMsg(ESP3DClientType origin, ESP3DClientType target,
const uint8_t *data, size_t length,
ESP3DAuthenticationLevel authentication_level =
ESP3DAuthenticationLevel::guest);
static ESP3DMessage *newMsg(ESP3DClientType origin, ESP3DClientType target,
ESP3DMessage *newMsg(ESP3DClientType origin, ESP3DClientType target,
ESP3DAuthenticationLevel authentication_level =
ESP3DAuthenticationLevel::guest);
static bool setDataContent(ESP3DMessage *msg, const uint8_t *data,
size_t length);
bool setDataContent(ESP3DMessage *msg, const uint8_t *data, size_t length);
private:
bool _deleteMsg(ESP3DMessage *message);
ESP3DMessage *_newMsg();
ESP3DMessage *_newMsg(ESP3DRequest requestId);
bool _copyMsgInfos(ESP3DMessage *newMsgPtr, ESP3DMessage msg);
ESP3DMessage *_copyMsgInfos(ESP3DMessage msg);
ESP3DMessage *_copyMsg(ESP3DMessage msg);
ESP3DMessage *_newMsg(ESP3DClientType origin, ESP3DClientType target,
const uint8_t *data, size_t length,
ESP3DAuthenticationLevel authentication_level =
ESP3DAuthenticationLevel::guest);
ESP3DMessage *_newMsg(ESP3DClientType origin, ESP3DClientType target,
ESP3DAuthenticationLevel authentication_level =
ESP3DAuthenticationLevel::guest);
bool _setDataContent(ESP3DMessage *msg, const uint8_t *data, size_t length);
SemaphoreHandle_t _mutex;
#if defined(ESP_LOG_FEATURE)
int _msg_counting;
#endif // ESP_LOG_FEATURE
};
#endif //_ESP3DOUTPUT_H
extern ESP3DMessageManager esp3d_message_manager;

View File

@ -1,5 +1,5 @@
/*
esp3d_messageFifo.h - class for handeling message
esp3d_messageFifo.h - class for managing messages list, thread safe
Copyright (c) 2014 Luc Lebosse. All rights reserved.
@ -19,77 +19,149 @@
*/
#if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP8285)
#include "esp3d_message.h"
#include "../include/esp3d_config.h"
#include <Arduino.h>
#include <queue>
#include "../include/esp3d_config.h"
#include "esp3d_message.h"
#if defined(ARDUINO_ARCH_ESP32)
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#endif // ARDUINO_ARCH_ESP32
#if defined(ARDUINO_ARCH_ESP8266)
// To avoid compilation error on ESP8266
// and to use many ifdefs
#ifndef pdTRUE
#define pdTRUE true
#define xSemaphoreTake(A, B) true
#define xSemaphoreGive(A)
#define xSemaphoreCreateMutex(A) 0
#define vSemaphoreDelete(A)
#define SemaphoreHandle_t void*
#endif // pdTRUE
#endif // ESP8266
class ESP3DMessageFIFO {
public:
ESP3DMessageFIFO(size_t maxSize = 5) : maxSize(maxSize) {
mutex = xSemaphoreCreateMutex();
public:
ESP3DMessageFIFO(size_t maxSize = 5) {
_mutex = xSemaphoreCreateMutex();
_maxSize = maxSize;
}
~ESP3DMessageFIFO() {
clear();
vSemaphoreDelete(mutex);
vSemaphoreDelete(_mutex);
}
void setId(String id) { _id = id; }
String getId() { return _id; }
void setMaxSize(size_t maxSize) { _maxSize = maxSize; }
size_t getMaxSize() { return _maxSize; }
void push(ESP3DMessage* message) {
xSemaphoreTake(mutex, portMAX_DELAY);
if (fifo.size() >= maxSize) {
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
esp3d_log("push to list [%s] size: %d", _id.c_str(), fifo.size());
if (fifo.size() >= _maxSize && _maxSize != 0) {
esp3d_log("remove oldest message to make room for new one");
ESP3DMessage* oldestMessage = fifo.front();
fifo.pop();
ESP3DMessageManager::deleteMsg(oldestMessage);
esp3d_message_manager.deleteMsg(oldestMessage);
esp3d_log("oldest message removed, list [%s] size: %d", _id.c_str(),
fifo.size());
}
fifo.push(message);
xSemaphoreGive(mutex);
esp3d_log("push to list [%s] size: %d", _id.c_str(), fifo.size());
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("push to list [%s] failed, list size: %d", _id.c_str(),
fifo.size());
esp3d_log_e("Delete message");
esp3d_message_manager.deleteMsg(message);
}
}
ESP3DMessage* pop() {
ESP3DMessage* message = nullptr;
xSemaphoreTake(mutex, portMAX_DELAY);
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
if (!fifo.empty()) {
esp3d_log("pop from list [%s] size: %d", _id.c_str(), fifo.size());
message = fifo.front();
fifo.pop();
esp3d_log("Now list [%s] size: %d", _id.c_str(), fifo.size());
esp3d_log("Message: %s", (const char*)message->data);
}
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("pop from list [%s] failed, list size: %d", _id.c_str(),
fifo.size());
}
xSemaphoreGive(mutex);
return message;
}
bool isEmpty() {
bool empty;
xSemaphoreTake(mutex, portMAX_DELAY);
bool empty = true;
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
empty = fifo.empty();
xSemaphoreGive(mutex);
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("Mutex not taken");
}
return empty;
}
size_t size() {
size_t s;
xSemaphoreTake(mutex, portMAX_DELAY);
size_t s = 0;
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
s = fifo.size();
xSemaphoreGive(mutex);
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("Mutex not taken");
}
return s;
}
void clear() {
xSemaphoreTake(mutex, portMAX_DELAY);
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
while (!fifo.empty()) {
ESP3DMessage* message = fifo.front();
fifo.pop();
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
}
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("Mutex not taken");
}
xSemaphoreGive(mutex);
}
private:
bool applyToEach(std::function<bool(ESP3DMessage*)> fn,
bool stopOnFalse = true) {
bool result = false;
if (xSemaphoreTake(_mutex, portMAX_DELAY) == pdTRUE) {
result = true;
size_t size = fifo.size();
for (size_t i = 0; i < size; ++i) {
ESP3DMessage* message = fifo.front();
bool result = fn(message);
fifo.pop();
if (!result && stopOnFalse) {
result = false;
break;
}
}
xSemaphoreGive(_mutex);
} else {
esp3d_log_e("Mutex not taken");
}
return result;
}
private:
std::queue<ESP3DMessage*> fifo;
SemaphoreHandle_t mutex;
const size_t maxSize;
SemaphoreHandle_t _mutex;
size_t _maxSize;
String _id;
};
#endif // !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP8285)

View File

@ -75,6 +75,12 @@
#define MIN_SERVER_ADDRESS_LENGTH 0
// default byte values
#ifdef ETH_FEATURE
#define DEFAULT_ETH_STA_FALLBACK_MODE STRING(ESP_NO_NETWORK)
#else
#define DEFAULT_ETH_STA_FALLBACK_MODE STRING(ESP_NO_NETWORK)
#endif // ETH_FEATURE
#ifdef WIFI_FEATURE
#define DEFAULT_STA_FALLBACK_MODE STRING(ESP_AP_SETUP)
#if defined(STATION_WIFI_SSID) && defined(STATION_WIFI_PASSWORD)
@ -192,6 +198,12 @@ uint16_t ESP3DSettingsData[] = {ESP_RADIO_MODE,
ESP_STA_DNS_VALUE,
ESP_AP_IP_VALUE,
ESP_STA_IP_MODE,
ESP_ETH_STA_FALLBACK_MODE,
ESP_ETH_STA_IP_VALUE,
ESP_ETH_STA_GATEWAY_VALUE,
ESP_ETH_STA_MASK_VALUE,
ESP_ETH_STA_DNS_VALUE,
ESP_ETH_STA_IP_MODE,
ESP_SETTINGS_VERSION,
ESP_NOTIFICATION_TYPE,
ESP_CALIBRATION,
@ -240,7 +252,6 @@ uint16_t ESP3DSettingsData[] = {ESP_RADIO_MODE,
ESP_FTP_DATA_PASSIVE_PORT,
ESP_WEBDAV_PORT,
ESP_SERIAL_BRIDGE_BAUD
};
#if defined(SD_DEVICE)
const uint8_t SupportedSPIDivider[] = {1, 2, 4, 6, 8, 16, 32};
@ -714,6 +725,8 @@ const char *ESP3DSettings::TargetBoard() {
#define TYPE_BOARD "ESP32-S3"
#elif CONFIG_IDF_TARGET_ESP32C3
#define TYPE_BOARD "ESP32-C3"
#elif CONFIG_IDF_TARGET_ESP32C6
#define TYPE_BOARD "ESP32-C6"
#endif
#ifdef BOARD_HAS_PSRAM
#define IS_PSRAM " (PSRAM)"
@ -960,12 +973,19 @@ bool ESP3DSettings::isValidByteSetting(uint8_t value,
return true;
}
break;
#ifdef ETH_FEATURE
case ESP_ETH_STA_IP_MODE:
if (value == DHCP_MODE || value == STATIC_IP_MODE) {
return true;
}
break;
#endif // ETH_FEATURE
#if defined(WIFI_FEATURE)
case ESP_STA_IP_MODE:
if (value == DHCP_MODE || value == STATIC_IP_MODE) {
return true;
}
break;
#if defined(WIFI_FEATURE)
case ESP_AP_CHANNEL:
for (uint8_t i = 0; i < SupportedApChannelsSize; i++) {
if (value == SupportedApChannels[i]) {
@ -1012,11 +1032,9 @@ bool ESP3DSettings::isValidByteSetting(uint8_t value,
// 0 means no timeout so it is ok to have 0
return true;
break;
case ESP_STA_FALLBACK_MODE:
#ifdef ETH_FEATURE
case ESP_ETH_STA_FALLBACK_MODE:
if (value == ESP_NO_NETWORK
#if defined(WIFI_FEATURE)
|| value == ESP_AP_SETUP
#endif // WIFI_FEATURE
#if defined(BT_FEATURE)
|| value == ESP_BT
#endif // BT_FEATURE
@ -1024,7 +1042,20 @@ bool ESP3DSettings::isValidByteSetting(uint8_t value,
return true;
}
break;
#endif // ETH_FEATURE
#if defined(WIFI_FEATURE)
case ESP_STA_FALLBACK_MODE:
if (value == ESP_NO_NETWORK
|| value == ESP_AP_SETUP
#if defined(BT_FEATURE)
|| value == ESP_BT
#endif // BT_FEATURE
) {
return true;
}
break;
#endif // WIFI_FEATURE
default:
return false;
}
@ -1117,8 +1148,10 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
case ESP_SECURE_SERIAL:
case ESP_BOOT_RADIO_STATE:
case ESP_STA_FALLBACK_MODE:
case ESP_ETH_STA_FALLBACK_MODE:
case ESP_SERIAL_BRIDGE_ON:
case ESP_STA_IP_MODE:
case ESP_ETH_STA_IP_MODE:
setting.type = ESP3DSettingType::byte_t; // byte
break;
@ -1144,6 +1177,10 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
case ESP_STA_GATEWAY_VALUE:
case ESP_STA_MASK_VALUE:
case ESP_STA_DNS_VALUE:
case ESP_ETH_STA_IP_VALUE:
case ESP_ETH_STA_GATEWAY_VALUE:
case ESP_ETH_STA_MASK_VALUE:
case ESP_ETH_STA_DNS_VALUE:
case ESP_AP_IP_VALUE:
setting.type = ESP3DSettingType::ip_t; // ip = 4 bytes
@ -1197,11 +1234,17 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
case ESP_WEBDAV_ON:
case ESP_SECURE_SERIAL:
case ESP_BOOT_RADIO_STATE:
case ESP_ETH_STA_FALLBACK_MODE:
case ESP_STA_FALLBACK_MODE:
case ESP_SERIAL_BRIDGE_ON:
case ESP_ETH_STA_IP_MODE:
case ESP_STA_IP_MODE:
setting.size = 1; // 1 byte
break;
case ESP_ETH_STA_IP_VALUE:
case ESP_ETH_STA_GATEWAY_VALUE:
case ESP_ETH_STA_MASK_VALUE:
case ESP_ETH_STA_DNS_VALUE:
case ESP_STA_IP_VALUE:
case ESP_STA_GATEWAY_VALUE:
case ESP_STA_MASK_VALUE:
@ -1278,6 +1321,8 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
// default value of setting in string
switch (index) {
case ESP_ETH_STA_IP_MODE:
case ESP_STA_IP_MODE:
setting.default_val = DEFAULT_STA_IP_MODE;
break;
@ -1350,6 +1395,9 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
case ESP_BOOT_RADIO_STATE:
setting.default_val = DEFAULT_BOOT_RADIO_STATE;
break;
case ESP_ETH_STA_FALLBACK_MODE:
setting.default_val = DEFAULT_ETH_STA_FALLBACK_MODE;
break;
case ESP_STA_FALLBACK_MODE:
setting.default_val = DEFAULT_STA_FALLBACK_MODE;
break;
@ -1401,15 +1449,19 @@ const ESP3DSettingDescription *ESP3DSettings::getSettingPtr(
case ESP_TIME_ZONE:
setting.default_val = DEFAULT_TIME_ZONE;
break;
case ESP_ETH_STA_IP_VALUE:
case ESP_STA_IP_VALUE:
setting.default_val = DEFAULT_STA_IP_VALUE;
break;
case ESP_ETH_STA_GATEWAY_VALUE:
case ESP_STA_GATEWAY_VALUE:
setting.default_val = DEFAULT_STA_GATEWAY_VALUE;
break;
case ESP_ETH_STA_MASK_VALUE:
case ESP_STA_MASK_VALUE:
setting.default_val = DEFAULT_STA_MASK_VALUE;
break;
case ESP_ETH_STA_DNS_VALUE:
case ESP_STA_DNS_VALUE:
setting.default_val = DEFAULT_STA_DNS_VALUE;
break;

View File

@ -119,7 +119,7 @@ typedef uint ESP3DSettingIndex;
#define ESP_SETUP 1192 // 1 byte = flag
// #define FREE 1193 // 1 byte = flag
// #define FREE 1194 // 1 byte = flag
// #define FREE 1195 // 1 byte = flag
#define ESP_ETH_STA_FALLBACK_MODE 1195 // 1 byte = flag
#define ESP_FTP_CTRL_PORT 1196 // 4 bytes = int
#define ESP_FTP_DATA_ACTIVE_PORT 1200 // 4 bytes = int
#define ESP_FTP_DATA_PASSIVE_PORT 1204 // 4 bytes = int
@ -133,9 +133,13 @@ typedef uint ESP3DSettingIndex;
#define ESP_BOOT_RADIO_STATE 1221 // 1 byte = flag
#define ESP_STA_FALLBACK_MODE 1222 // 1 byte = flag
#define ESP_SERIAL_BRIDGE_ON 1223 // 1 byte = flag
// #define FREE 1224 // 1 byte = flag
#define ESP_ETH_STA_IP_MODE 1224 // 1 byte = flag
#define ESP_SERIAL_BRIDGE_BAUD 1225 // 4 bytes= int
#define ESP_TIME_ZONE 1229 // 7 bytes 6+1 = string
#define ESP_ETH_STA_IP_VALUE 1237 // 4 bytes xxx.xxx.xxx.xxx
#define ESP_ETH_STA_MASK_VALUE 1240 // 4 bytes xxx.xxx.xxx.xxx
#define ESP_ETH_STA_GATEWAY_VALUE 1244 // 4 bytes xxx.xxx.xxx.xxx
#define ESP_ETH_STA_DNS_VALUE 1248 // 4 bytes xxx.xxx.xxx.xxx
// Hidden password
#define HIDDEN_PASSWORD "********"
@ -313,14 +317,36 @@ typedef uint ESP3DSettingIndex;
#define MODE_ETH_CLOCK_GPIO16_OUT 2
#define MODE_ETH_CLOCK_GPIO17_OUT 3
// Ethernet type (Check ETH.h eth_phy_type_t)
// Ethernet type (Check ETH.h eth_phy_type_t because it enum with #ifdef CONFIG_....)
#define TYPE_ETH_PHY_LAN8720 0
#define TYPE_ETH_PHY_TLK110 1
#define TYPE_ETH_PHY_RTL8201 2
#define TYPE_ETH_PHY_DP83848 3
#define TYPE_ETH_PHY_DM9051 4
#define TYPE_ETH_PHY_KSZ8041 5
#define TYPE_ETH_PHY_KSZ8081 6
#define TYPE_ETH_PHY_KSZ8041 4
#define TYPE_ETH_PHY_KSZ8081 5
#define TYPE_ETH_PHY_DM9051 6
#define TYPE_ETH_PHY_W5500 7
#define TYPE_ETH_PHY_KSZ8851 8
//SPI pis for ethernet
#ifndef ETH_PHY_CS
#define ETH_PHY_CS 15
#endif // ETH_PHY_CS
#ifndef ETH_PHY_IRQ
#define ETH_PHY_IRQ 4
#endif // ETH_PHY_IRQ
#ifndef ETH_PHY_RST
#define ETH_PHY_RST 5
#endif // ETH_PHY_RST
#ifndef ETH_SPI_SCK
#define ETH_SPI_SCK 14
#endif // ETH_SPI_SCK
#ifndef ETH_SPI_MISO
#define ETH_SPI_MISO 12
#endif // ETH_SPI_MISO
#ifndef ETH_SPI_MOSI
#define ETH_SPI_MOSI 13
#endif // ETH_SPI_MOSI
// Host path
#define ESP3D_HOST_PATH "/"

View File

@ -77,8 +77,8 @@
/**************************
* Bluetooth
* ***********************/
#if defined(BLUETOOTH_FEATURE) && defined(ARDUINO_ARCH_ESP8266)
#error Bluetooth is not available in ESP8266
#if (defined(BLUETOOTH_FEATURE) && !defined(ARDUINO_ARCH_ESP32)) || (defined(BLUETOOTH_FEATURE) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)))
#error Bluetooth is only available for ESP32
#endif
/**************************

View File

@ -25,7 +25,7 @@
#ifdef BLUETOOTH_FEATURE
#include "../../core/esp3d_commands.h"
#include "../../core/esp3d_settings.h"
#include "../../esp3d_string.h"
#include "../../core/esp3d_string.h"
#include "../network/netconfig.h"
#include "BT_service.h"
#include "BluetoothSerial.h"
@ -192,7 +192,7 @@ ESP3DAuthenticationLevel BTService::getAuthentication() { return _auth; }
void BTService::flushbuffer() {
_buffer[_buffer_size] = 0x0;
// dispatch command
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::bluetooth, esp3d_commands.getOutputClient(), _buffer,
_buffer_size, _auth);
if (msg) {
@ -288,7 +288,7 @@ bool BTService::dispatch(ESP3DMessage *message) {
if (sentcnt != message->size) {
return false;
}
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}

View File

@ -242,8 +242,10 @@ int Camera::command(const char *param, const char *value) {
bool Camera::initHardware() {
_initialised = false;
#if !(CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
esp3d_log("Disable brown out");
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
#endif // !(CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
stopHardware();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;

View File

@ -52,7 +52,7 @@ bool Display::dispatch(ESP3DMessage* message) {
break;
}
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}
return false;

View File

@ -29,62 +29,39 @@
#endif // ARDUINO_ARCH_ESP8266
#include "../../core/esp3d_commands.h"
#include "../../core/esp3d_settings.h"
#include "../../core/esp3d_string.h"
#include "../network/netconfig.h"
#include "ethconfig.h"
#if defined(GCODE_HOST_FEATURE)
#include "../gcode_host/gcode_host.h"
#endif // GCODE_HOST_FEATURE
bool EthConfig::_started = false;
bool EthConfig::_connected = false;
uint8_t EthConfig::_ipMode = DHCP_MODE;
const uint8_t DEFAULT_AP_MASK_VALUE[] = {255, 255, 255, 0};
bool EthConfig::StartSTA() {
bool res = true;
if ((ESP3DSettings::readByte(ESP_STA_IP_MODE) != DHCP_MODE)) {
int32_t IP = ESP3DSettings::read_IP(ESP_STA_IP_VALUE);
int32_t GW = ESP3DSettings::read_IP(ESP_STA_GATEWAY_VALUE);
int32_t MK = ESP3DSettings::read_IP(ESP_STA_MASK_VALUE);
int32_t DNS = ESP3DSettings::read_IP(ESP_STA_DNS_VALUE);
if (_ipMode == STATIC_IP_MODE) {
int32_t IP = ESP3DSettings::read_IP(ESP_ETH_STA_IP_VALUE);
int32_t GW = ESP3DSettings::read_IP(ESP_ETH_STA_GATEWAY_VALUE);
int32_t MK = ESP3DSettings::read_IP(ESP_ETH_STA_MASK_VALUE);
int32_t DNS = ESP3DSettings::read_IP(ESP_ETH_STA_DNS_VALUE);
IPAddress ip(IP), mask(MK), gateway(GW), dns(DNS);
res = ETH.config(ip, gateway, mask, dns);
}
return res;
}
/*bool EthConfig::StartSRV()
{
bool res = true;
//static IP
int32_t IP = ESP3DSettings::read_IP(ESP_AP_IP_VALUE);
IPAddress ip(IP), mask(DEFAULT_AP_MASK_VALUE), gateway(IP);
if (!ETH.config(ip, gateway,mask)) {
res = false;
esp3d_log_e("Set static IP error");
}
//start DHCP server
if(res) {
dhcps_lease_t lease;
lease.enable = true;
lease.start_ip.addr = static_cast<uint32_t>(IP) + (1 << 24);
lease.end_ip.addr = static_cast<uint32_t>(IP) + (11 << 24);
tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_ETH);
tcpip_adapter_dhcps_option(
(tcpip_adapter_option_mode_t)TCPIP_ADAPTER_OP_SET,
(tcpip_adapter_option_id_t)REQUESTED_IP_ADDRESS,
(void*)&lease, sizeof(dhcps_lease_t)
);
if (tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_ETH) != ESP_OK){
res = false;
esp3d_log_e("Start DHCP server failed");
}
}
return res;
}*/
bool EthConfig::linkUp() { return _connected; }
bool EthConfig::linkUp() {
#if defined(ESP_IDF_VERSION_MAJOR)
// patch for https://github.com/espressif/arduino-esp32/issues/6105
return _connected;
#else
return ETH.linkUp();
#endif
uint8_t EthConfig::ipMode(bool fromsettings) {
if (fromsettings) {
_ipMode = (ESP3DSettings::readByte(ESP_ETH_STA_IP_MODE) != DHCP_MODE);
}
return _ipMode;
}
/**
@ -92,9 +69,33 @@ bool EthConfig::linkUp() {
*/
bool EthConfig::begin(int8_t& espMode) {
bool res = false;
ipMode(true);
end();
if (ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_LAN8720) {
esp3d_log_d("ETH PHY Type %d", ESP3D_ETH_PHY_TYPE);
_started = ETH.begin();
} else {
if (ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_TLK110 ||
ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_RTL8201 ||
ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_DP83848 ||
ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_KSZ8041 ||
ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_KSZ8081) {
esp3d_log_d("ETH PHY Type %d", ESP3D_ETH_PHY_TYPE);
_started = ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_POWER,
ETH_PHY_MDC, ETH_PHY_MDIO, ETH_CLK_MODE);
} else {
if (ESP3D_ETH_PHY_TYPE == TYPE_ETH_PHY_W5500) {
esp3d_log_d("ETH spi PHY Type %d", ESP3D_ETH_PHY_TYPE);
SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI);
_started = ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS,
ETH_PHY_IRQ, ETH_PHY_RST, SPI);
} else {
esp3d_log("Ethernet PHY type not supported");
return false;
}
}
}
if (_started) {
if (ESP3DSettings::isVerboseBoot()) {
esp3d_commands.dispatch("Starting ethernet", ESP3DClientType::all_clients,
@ -104,7 +105,7 @@ bool EthConfig::begin(int8_t& espMode) {
}
res = true;
} else {
esp3d_commands.dispatch("Failed starting ethernet write failed",
esp3d_commands.dispatch("Failed starting ethernet failed",
ESP3DClientType::all_clients, no_id,
ESP3DMessageType::unique, ESP3DClientType::system,
ESP3DAuthenticationLevel::admin);
@ -120,7 +121,7 @@ bool EthConfig::begin(int8_t& espMode) {
ESP3DMessageType::unique, ESP3DClientType::system,
ESP3DAuthenticationLevel::admin);
}
espMode = ESP3DSettings::readByte(ESP_STA_FALLBACK_MODE);
espMode = ESP3DSettings::readByte(ESP_ETH_STA_FALLBACK_MODE);
res = true;
} else {
if (ESP3DSettings::isVerboseBoot()) {
@ -130,20 +131,9 @@ bool EthConfig::begin(int8_t& espMode) {
ESP3DAuthenticationLevel::admin);
}
}
} else {
// if(!StartSRV()){
// res = false;
//
// } else {
//
// }
}
// if ((ESP3DSettings::readByte(ESP_STA_IP_MODE) != DHCP_MODE) || (espMode
// == ESP_ETH_SRV)){
if ((ESP3DSettings::readByte(ESP_STA_IP_MODE) != DHCP_MODE)) {
// as no event to display static IP
// Static IP or DHCP client ?
if ((ESP3DSettings::readByte(ESP_ETH_STA_IP_MODE) != DHCP_MODE)) {
esp3d_commands.dispatch(ETH.localIP().toString().c_str(),
ESP3DClientType::all_clients, no_id,
ESP3DMessageType::unique, ESP3DClientType::system,
@ -158,8 +148,10 @@ bool EthConfig::begin(int8_t& espMode) {
*/
void EthConfig::end() {
// esp_eth_disable();
// ETH.end();
_started = false;
_ipMode = DHCP_MODE;
_connected = false;
}
bool EthConfig::started() { return _started; }

View File

@ -55,12 +55,13 @@ class EthConfig {
static void handle();
static bool started();
static void setConnected(bool connected) { _connected = connected; }
static uint8_t ipMode(bool fromsettings = false);
static bool linkUp();
private:
static bool _started;
static bool _connected;
static uint8_t _ipMode;
};
#endif //_ETH_CONFIG_H

View File

@ -127,27 +127,11 @@ uint8_t ESP_SD::getState(bool refresh) {
ESP_SD_MOSI_PIN != -1 ? ESP_SD_MOSI_PIN : MOSI,
ESP_SD_SCK_PIN != -1 ? ESP_SD_SCK_PIN : SCK);
// refresh content if card was removed
#if !(defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1)
if (xPortGetCoreID() == 0) {
disableCore0WDT();
} else {
disableCore1WDT();
}
#endif // !(defined(ESP_SD_DETECT_PIN)
if (SD.begin((ESP_SD_CS_PIN == -1) ? SS : ESP_SD_CS_PIN,
SD_SCK_MHZ(FREQMZ / _spi_speed_divider))) {
csd_t m_csd;
if (SD.card()->readCSD(&m_csd) && sdCardCapacity(&m_csd) > 0) {
_state = ESP_SDCARD_IDLE;
}
}
#if !(defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1)
if (xPortGetCoreID() == 0) {
enableCore0WDT();
} else {
enableCore1WDT();
}
#endif // !(defined(ESP_SD_DETECT_PIN)
return _state;
}

View File

@ -123,12 +123,7 @@ uint8_t ESP_SD::getState(bool refresh) {
if (SD.begin((ESP_SD_CS_PIN == -1) ? SS : ESP_SD_CS_PIN,
SD_SCK_HZ(F_CPU / _spi_speed_divider))) {
esp3d_log("Init SD State ok");
csd_t m_csd;
if (SD.card()->readCSD(&m_csd) && sdCardCapacity(&m_csd) > 0) {
_state = ESP_SDCARD_IDLE;
} else {
esp3d_log_e("Cannot get card size");
}
} else {
esp3d_log_e("Init SD State failed");
}
@ -463,6 +458,9 @@ ESP_SDFile::ESP_SDFile(void* handle, bool isdir, bool iswritemode,
}
// todo need also to add short filename
const char* ESP_SDFile::shortname() const {
#if SDFAT_FILE_TYPE != 1
return _name.c_str();
#else
static char sname[13];
File ftmp = SD.open(_filename.c_str());
if (ftmp) {
@ -475,6 +473,7 @@ const char* ESP_SDFile::shortname() const {
} else {
return _name.c_str();
}
#endif
}
void ESP_SDFile::close() {

View File

@ -31,8 +31,8 @@
#ifndef FTP_SERVER_H
#define FTP_SERVER_H
class WiFiServer;
class WiFiClient;
#include <WiFiClient.h>
#include <WiFiServer.h>
#ifndef FF_MAX_LFN
#define FF_MAX_LFN 255
#endif

View File

@ -317,7 +317,7 @@ void GcodeHost::processCommand() {
bool isESPcmd = esp3d_commands.is_esp_command(
(uint8_t *)_currentCommand.c_str(), _currentCommand.length());
if (isESPcmd) {
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::no_client, esp3d_commands.getOutputClient(),
(uint8_t *)_currentCommand.c_str(), _currentCommand.length(), _auth);
if (msg) {
@ -331,7 +331,7 @@ void GcodeHost::processCommand() {
}
} else {
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::stream, esp3d_commands.getOutputClient(),
(uint8_t *)_currentCommand.c_str(), _currentCommand.length(), _auth);
if (msg) {

View File

@ -74,7 +74,7 @@ void HTTP_Server::handle_web_command() {
}
esp3d_log("Web Command: %s", cmd.c_str());
if (esp3d_commands.is_esp_command((uint8_t *)cmd.c_str(), cmd.length())) {
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::http, esp3d_commands.getOutputClient(),
(uint8_t *)cmd.c_str(), cmd.length(), auth_level);
if (msg) {

View File

@ -39,7 +39,7 @@ void HTTP_Server::handle_config() {
if (_webserver->hasArg("json")) {
cmd += " json=" + _webserver->arg("json");
}
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::http, ESP3DClientType::http, (uint8_t *)cmd.c_str(),
cmd.length(), auth_level);
if (msg) {

View File

@ -289,7 +289,7 @@ bool HTTP_Server::dispatch(ESP3DMessage* msg) {
_webserver->sendContent("");
}
}
ESP3DMessageManager::deleteMsg(msg);
esp3d_message_manager.deleteMsg(msg);
return true;
}
return false;
@ -346,13 +346,7 @@ void HTTP_Server::end() {
void HTTP_Server::handle() {
if (_started) {
if (_webserver) {
#ifdef DISABLE_WDT_CORE_0
disableCore0WDT();
#endif // DISABLE_WDT_CORE_0
_webserver->handleClient();
#ifdef DISABLE_WDT_CORE_0
enableCore0WDT();
#endif // DISABLE_WDT_CORE_0
}
}
}

View File

@ -20,12 +20,15 @@
#include "../../include/esp3d_config.h"
#ifdef ESP_LUA_INTERPRETER_FEATURE
#if defined(ESP_LUA_INTERPRETER_FEATURE) && defined(ARDUINO_ARCH_ESP32)
#include "../../core/esp3d_commands.h"
#include "../../core/esp3d_hal.h"
#include "../../core/esp3d_settings.h"
#include "lua_interpreter_service.h"
#if defined(NOTIFICATION_FEATURE)
#include "../notifications/notifications_service.h"
#endif // NOTIFICATION_FEATURE
#if defined(FILESYSTEM_FEATURE)
#include "../filesystem/esp_filesystem.h"
#endif // FILESYSTEM_FEATURE
@ -39,20 +42,21 @@ LuaInterpreter esp3d_lua_interpreter;
LuaInterpreter::LuaInterpreter() {
_scriptTask = NULL;
_isRunning = false;
_isPaused = false;
_pauseTime = 0;
_pauseSemaphore = xSemaphoreCreateBinary();
_luaFSType = Lua_Filesystem_Type::none;
xSemaphoreGive(_pauseSemaphore); // Initialize as available
setupFunctions();
registerConstants();
_scriptBuffer = nullptr;
_stateMutex = xSemaphoreCreateMutex();
_messageInFIFO.setMaxSize(10); // no limit
_messageInFIFO.setId("in");
_messageOutFIFO.setMaxSize(0); // no limit
_messageOutFIFO.setId("out");
}
LuaInterpreter::~LuaInterpreter() {
deleteScriptTask();
vSemaphoreDelete(_pauseSemaphore);
vSemaphoreDelete(_stateMutex);
}
bool LuaInterpreter::dispatch(ESP3DMessage *message) {
@ -60,90 +64,105 @@ bool LuaInterpreter::dispatch(ESP3DMessage *message) {
return false;
}
if (message->size > 0 && message->data) {
_messageFIFO.push(message);
_messageInFIFO.push(message);
return true;
}
return false;
}
const char *LuaInterpreter::getLastError() {
esp3d_log("getLastError %s %s", _lastError.c_str(), _luaEngine.getLastError());
if (_lastError.length() == 0) {
return _luaEngine.getLastError();
}
return _lastError.c_str();
}
bool LuaInterpreter::createScriptTask() {
if (_scriptTask != NULL) {
deleteScriptTask();
}
BaseType_t xReturned = xTaskCreate(scriptExecutionTask, "LuaScriptTask", 8192,
this, tskIDLE_PRIORITY + 1, &_scriptTask);
_lastError = "";
BaseType_t xReturned = xTaskCreatePinnedToCore(
scriptExecutionTask, /* Task function. */
"LuaScriptTask", /* name of task. */
8192, /* Stack size of task */
this, /* parameter of the task = is main or bridge*/
1, /* priority of the task */
&_scriptTask, /* Task handle to keep track of created task */
1 /* Core to run the task */
);
if (xReturned != pdPASS) {
_lastError = "Failed to create script task";
if (_lastError.length() == 0) _lastError = "Failed to create script task";
return false;
}
_isRunning = true;
_isPaused = false;
_startTime = millis();
return true;
}
bool LuaInterpreter::executeScriptAsync(const char *script) {
bool result = true;
if (_isRunning) {
_lastError = "A script is already running";
if (_luaEngine.isRunning()) {
if (_lastError.length() == 0) _lastError = "A script is already running";
return false;
}
_currentScriptName = script;
if (!createScriptTask()) {
_lastError = "Failed to create script task";
if (_lastError.length() == 0) _lastError = "Failed to create script task";
result = false;
}
return result;
}
void LuaInterpreter::abortCurrentScript() {
if (_isRunning && _scriptTask != NULL) {
deleteScriptTask();
_lastError = "Script aborted";
void LuaInterpreter::abortScript() {
if (_luaEngine.isRunning() && _scriptTask != NULL) {
if (_lastError.length() == 0) _lastError = "Script aborted";
_luaEngine.stopExecution();
}
}
bool LuaInterpreter::pauseScript() {
if (_isRunning && !_isPaused) {
_isPaused = true;
if (_luaEngine.isRunning() && !_luaEngine.isPaused()) {
_luaEngine.pauseExecution();
_pauseTime = millis();
xSemaphoreTake(_pauseSemaphore, 0);
return true;
}
return false;
}
bool LuaInterpreter::resumeScript() {
if (_isRunning && _isPaused) {
_isPaused = false;
if (_luaEngine.isRunning() && _luaEngine.isPaused()) {
_luaEngine.resumeExecution();
_startTime += (millis() - _pauseTime);
xSemaphoreGive(_pauseSemaphore);
return true;
}
return false;
}
void LuaInterpreter::resetLuaEnvironment() {
_luaEngine.resetState();
setupFunctions();
registerConstants();
}
void LuaInterpreter::deleteScriptTask() {
if (_scriptTask != NULL) {
vTaskDelete(_scriptTask);
_scriptTask = NULL;
}
esp3d_log("Delete script task start");
if (_scriptBuffer) {
esp3d_log("Free script buffer");
free(_scriptBuffer);
_scriptBuffer = nullptr;
}
_isRunning = false;
_isPaused = false;
esp3d_log("Reset lua environment");
_luaFSType = Lua_Filesystem_Type::none;
}
void LuaInterpreter::checkPause() {
if (_isPaused) {
xSemaphoreTake(_pauseSemaphore, portMAX_DELAY);
xSemaphoreGive(_pauseSemaphore);
if (_lastError != "") resetLuaEnvironment();
if (_scriptTask != NULL) {
esp3d_log("Delete script task");
TaskHandle_t tmpTask = _scriptTask;
_scriptTask = NULL;
vTaskDelete(tmpTask);
}
}
@ -152,6 +171,7 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
String scriptName = self->_currentScriptName;
if (self->_scriptBuffer) {
free(self->_scriptBuffer);
self->_scriptBuffer = nullptr;
}
self->_lastError = "";
size_t fileSize = 0;
@ -175,8 +195,9 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
fileSize = FSfileHandle.size();
esp3d_log("File %s opened, size is %d", scriptName.c_str(), fileSize);
if (fileSize > ESP_LUA_MAX_SCRIPT_SIZE) {
if (self->_lastError.length() == 0)
self->_lastError = "File size is too large";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "File size is too large");
} else {
// allocate memory for the script
self->_scriptBuffer = (char *)malloc(fileSize + 1);
@ -188,24 +209,28 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
esp3d_log("File %s read into buffer", scriptName.c_str());
// check if the read is ok
if (readSize != fileSize) {
if (self->_lastError.length() == 0)
self->_lastError = "Failed to read file";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", self->_lastError.c_str());
} else {
self->_luaFSType = Lua_Filesystem_Type::fLash;
}
} else {
if (self->_lastError.length() == 0)
self->_lastError = "Failed to allocate memory for script";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "Failed to allocate memory for script");
}
}
FSfileHandle.close();
} else {
if (self->_lastError.length() == 0)
self->_lastError = "File is not open: " + scriptName;
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", self->_lastError.c_str());
}
} else {
if (self->_lastError.length() == 0)
self->_lastError = "File not found: " + scriptName;
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "File is not open: " + scriptName);
}
}
#endif // FILESYSTEM_FEATURE
@ -216,12 +241,13 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
esp3d_log("Processing SD file %s", scriptName.c_str());
// Check if the SD file system is available
if (!ESP_SD::accessFS()) {
if (self->_lastError.length() == 0)
self->_lastError = "SD file system not found";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "SD file system not found");
} else {
if (ESP_SD::getState(true) == ESP_SDCARD_NOT_PRESENT) {
self->_lastError = "SD card not present";
esp3d_log_e(% s, self->_lastError.c_str());
if (self->_lastError.length() == 0) self->_lastError = "SD card not present";
esp3d_log_e("%s", "SD card not present");
} else {
ESP_SD::setState(ESP_SDCARD_BUSY);
// Check script name exists
@ -232,8 +258,9 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
// Check script file size is under 2048 bytes
fileSize = SDfileHandle.size();
if (fileSize > ESP_LUA_MAX_SCRIPT_SIZE) {
if (self->_lastError.length() == 0)
self->_lastError = "File size is too large";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "File size is too large");
} else {
// allocate memory for the script
self->_scriptBuffer = (char *)malloc(fileSize + 1);
@ -245,25 +272,29 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
esp3d_log("File %s read into buffer", scriptName.c_str());
// check if the read is ok
if (readSize != fileSize) {
if (self->_lastError.length() == 0)
self->_lastError = "Failed to read file";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "Failed to read file");
} else {
self->_luaFSType = Lua_Filesystem_Type::sd;
}
} else {
if (self->_lastError.length() == 0)
self->_lastError = "Failed to allocate memory for script";
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "Failed to allocate memory for script");
}
}
// close the file
SDfileHandle.close();
} else {
self->_lastError = "File is not open: " + scriptName;
esp3d_log_e(% s, self->_lastError.c_str());
if (self->_lastError.length() == 0) self->_lastError =
"File is not open: " + scriptName;
esp3d_log_e("%s", "File is not open: " + scriptName);
}
} else {
if (self->_lastError.length() == 0)
self->_lastError = "File not found: " + scriptName;
esp3d_log_e(% s, self->_lastError.c_str());
esp3d_log_e("%s", "File not found: " + scriptName);
}
}
ESP_SD::releaseFS();
@ -271,30 +302,76 @@ void LuaInterpreter::scriptExecutionTask(void *parameter) {
}
#endif // SD_DEVICE
// Check if the file system type is not determined
if (self->_luaFSType == Lua_Filesystem_Type::none &&
self->_lastError.length() == 0) {
esp3d_log("Check state");
if (self->_luaFSType == Lua_Filesystem_Type::none) {
if (self->_lastError.length() == 0)
self->_lastError = "Cannot determine file system type";
esp3d_log_e(% s, self->_lastError.c_str());
}
esp3d_log_e("%s", "Cannot determine file system type");
} else {
// Execute the script
esp3d_log("Execute script");
if (self->_luaFSType != Lua_Filesystem_Type::none && self->_scriptBuffer) {
if (!self->_luaEngine.executeScript(self->_scriptBuffer)) {
if (self->_lastError.length() == 0) {
self->_lastError = "Script execution failed";
esp3d_log_e(% s, self->_lastError.c_str());
}
esp3d_log_e("%s", "Script execution failed");
}
}
}
esp3d_log("Delete script task");
self->deleteScriptTask();
}
unsigned long LuaInterpreter::getExecutionTime() const {
if (!_isRunning) return 0;
if (_isPaused) return _pauseTime - _startTime;
bool LuaInterpreter::begin() {
end();
return true;
}
void LuaInterpreter::end() { deleteScriptTask(); }
void LuaInterpreter::handle() {
static bool notificationSent = false;
if (_luaEngine.isRunning() && notificationSent) {
notificationSent = false;
}
if (_messageOutFIFO.size() > 0 || _luaEngine.hasError()) {
if (xSemaphoreTake(_stateMutex, portMAX_DELAY) == pdTRUE) {
// Check if the script is in error state and if still running
if (_luaEngine.hasError()) {
_lastError = _luaEngine.getLastError();
#ifdef NOTIFICATION_FEATURE
if (!notificationSent) {
String errorMsg = "Error: " + _lastError;
notificationsservice.sendAutoNotification(errorMsg.c_str());
notificationSent = true;
}
#endif // NOTIFICATION_FEATURE
}
if (_messageOutFIFO.size() > 0) {
esp3d_log("lua_interpreter message size %d", _messageOutFIFO.size());
}
ESP3DMessage *msg = _messageOutFIFO.pop();
if (msg) {
esp3d_log("Processing message: %s", msg->data);
esp3d_commands.process(msg);
}
xSemaphoreGive(_stateMutex);
} else {
esp3d_log_e("Mutex not taken");
}
}
}
uint64_t LuaInterpreter::getExecutionTime() {
if (!_luaEngine.isRunning()) return 0;
if (_luaEngine.isPaused()) return _pauseTime - _startTime;
return millis() - _startTime;
}
bool LuaInterpreter::isScriptRunning() const { return _isRunning; }
bool LuaInterpreter::isScriptRunning() { return _luaEngine.isRunning(); }
bool LuaInterpreter::isScriptPaused() const { return _isPaused; }
bool LuaInterpreter::isScriptPaused() { return _luaEngine.isPaused(); }
void LuaInterpreter::setupFunctions() {
_luaEngine.registerFunction("pinMode", l_pinMode);
@ -304,9 +381,10 @@ void LuaInterpreter::setupFunctions() {
_luaEngine.registerFunction("analogRead", l_analogRead);
_luaEngine.registerFunction("available", l_available, this);
_luaEngine.registerFunction("readData", l_readData, this);
_luaEngine.registerFunction("delay", l_delay);
_luaEngine.registerFunction("delay", l_delay, this);
_luaEngine.registerFunction("yield", l_yield);
_luaEngine.registerFunction("millis", l_millis);
_luaEngine.registerFunction("print", l_print, this);
}
void LuaInterpreter::registerConstants() {
@ -354,21 +432,45 @@ int LuaInterpreter::l_analogRead(lua_State *L) {
return 1;
}
int l_print(lua_State *L) {
int LuaInterpreter::l_print(lua_State *L) {
esp3d_log("lua_interpreter output");
LuaInterpreter *self =
(LuaInterpreter *)lua_touserdata(L, lua_upvalueindex(1));
String dataString;
dataString = "";
int nargs = lua_gettop(L);
// esp3d_log("lua_interpreter output args %d", nargs);
for (int i = 1; i <= nargs; i++) {
// esp3d_log("lua_interpreter output arg %d", i);
if (lua_isstring(L, i)) {
dataString += lua_tostring(L, i);
} else if (lua_isnumber(L, i)) {
dataString += String(lua_tonumber(L, i));
} else if (lua_isboolean(L, i)) {
dataString += lua_toboolean(L, i) ? "true" : "false";
} else if (lua_isnil(L, i)) {
dataString += "nil";
} else {
dataString += lua_typename(L, lua_type(L, i));
}
}
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
if (!dataString.endsWith("\n")) {
dataString += "\n";
}
esp3d_log("lua_interpreter output %s", dataString.c_str());
esp3d_log("Message Creation");
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::lua_script, esp3d_commands.getOutputClient(),
(uint8_t *)dataString.c_str(), dataString.length(),
ESP3DAuthenticationLevel::admin);
esp3d_log("Message created");
if (msg) {
// process command
esp3d_commands.process(msg);
msg->type = ESP3DMessageType::unique;
esp3d_log("Message sent to fifo list");
// push to FIFO
self->_messageOutFIFO.push(msg);
} else {
esp3d_log_e("Cannot create message");
}
@ -378,17 +480,17 @@ int l_print(lua_State *L) {
int LuaInterpreter::l_available(lua_State *L) {
LuaInterpreter *self =
(LuaInterpreter *)lua_touserdata(L, lua_upvalueindex(1));
lua_pushinteger(L, self->_messageFIFO.size());
lua_pushinteger(L, self->_messageInFIFO.size());
return 1;
}
int LuaInterpreter::l_readData(lua_State *L) {
LuaInterpreter *self =
(LuaInterpreter *)lua_touserdata(L, lua_upvalueindex(1));
ESP3DMessage *message = self->_messageFIFO.pop();
ESP3DMessage *message = self->_messageInFIFO.pop();
if (message) {
lua_pushlstring(L, (const char *)message->data, message->size);
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
} else {
lua_pushnil(L);
}
@ -396,8 +498,27 @@ int LuaInterpreter::l_readData(lua_State *L) {
}
int LuaInterpreter::l_delay(lua_State *L) {
LuaInterpreter *self =
(LuaInterpreter *)lua_touserdata(L, lua_upvalueindex(1));
int ms = luaL_checkinteger(L, 1);
vTaskDelay(pdMS_TO_TICKS(ms));
TickType_t delayTicks = pdMS_TO_TICKS(ms);
// Check if during delay the script is aborted or paused
while (delayTicks > 0) {
TickType_t delayThis = (delayTicks > ESP_LUA_CHECK_INTERVAL)
? ESP_LUA_CHECK_INTERVAL
: delayTicks;
vTaskDelay(delayThis);
delayTicks -= delayThis;
while (self->_luaEngine.isPaused()) {
vTaskDelay(ESP_LUA_CHECK_INTERVAL);
}
if (!(self->_luaEngine.isRunning())) {
if (self->_lastError.length() == 0)
self->_lastError = "Execution stopped";
luaL_error(L, "Execution stopped");
}
}
return 0;
}

View File

@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#if defined(ARDUINO_ARCH_ESP32)
#include <Arduino.h>
#include <EspLuaEngine.h>
@ -39,28 +39,30 @@ class LuaInterpreter {
~LuaInterpreter();
bool executeScriptAsync(const char* script);
void abortCurrentScript();
void abortScript();
bool pauseScript();
bool resumeScript();
const char* getCurrentScriptName() { return _currentScriptName.c_str(); }
unsigned long getExecutionTime() const;
bool isScriptRunning() const;
bool isScriptPaused() const;
const char* getLastError() const;
uint64_t getExecutionTime();
bool isScriptRunning();
bool isScriptPaused();
const char* getLastError();
bool dispatch(ESP3DMessage* message);
bool begin();
void end();
void handle();
private:
EspLuaEngine _luaEngine;
TaskHandle_t _scriptTask;
char* _scriptBuffer;
SemaphoreHandle_t _pauseSemaphore;
ESP3DMessageFIFO _messageFIFO;
SemaphoreHandle_t _stateMutex;
ESP3DMessageFIFO _messageInFIFO;
ESP3DMessageFIFO _messageOutFIFO;
Lua_Filesystem_Type _luaFSType;
String _currentScriptName;
unsigned long _startTime;
unsigned long _pauseTime;
bool _isRunning;
bool _isPaused;
String _lastError;
static void scriptExecutionTask(void* parameter);
@ -68,7 +70,7 @@ class LuaInterpreter {
void registerConstants();
bool createScriptTask();
void deleteScriptTask();
void checkPause();
void resetLuaEnvironment();
// Wrappers
static int l_print(lua_State* L);
@ -85,3 +87,5 @@ class LuaInterpreter {
};
extern LuaInterpreter esp3d_lua_interpreter;
#endif // defined(ARDUINO_ARCH_ESP32)

View File

@ -252,7 +252,7 @@ const char* mDNS_Service::answerIP(uint16_t index) {
return "";
}
#if defined(ARDUINO_ARCH_ESP32)
tmp = MDNS.IP(index).toString();
tmp = MDNS.address(index).toString();
#endif // ARDUINO_ARCH_ESP32
#if defined(ARDUINO_ARCH_ESP8266)

View File

@ -120,7 +120,7 @@ bool MKSService::dispatch(ESP3DMessage *message) {
}
if (message->size > 0 && message->data) {
if (sendGcodeFrame((const char *)message->data)) {
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}
}

View File

@ -48,6 +48,10 @@
#include "../gcode_host/gcode_host.h"
#endif // GCODE_HOST_FEATURE
#if defined(ARDUINO_ARCH_ESP32)
esp_netif_t *get_esp_interface_netif(esp_interface_t interface);
#endif // ARDUINO_ARCH_ESP32
String NetConfig::_hostname = "";
bool NetConfig::_needReconnect2AP = false;
bool NetConfig::_events_registered = false;
@ -231,11 +235,12 @@ void NetConfig::onWiFiEvent(WiFiEvent_t event) {
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
if (_started) {
_needReconnect2AP = true;
esp3d_log("WiFi STA lost IP");
}
break;
#ifdef ETH_FEATURE
case ARDUINO_EVENT_ETH_START: {
EthConfig::setConnected(false);
esp3d_log("Ethernet started");
if (ESP3DSettings::isVerboseBoot()) {
esp3d_commands.dispatch(
"Checking connection", ESP3DClientType::all_clients, no_id,
@ -248,18 +253,24 @@ void NetConfig::onWiFiEvent(WiFiEvent_t event) {
no_id, ESP3DMessageType::unique,
ESP3DClientType::system,
ESP3DAuthenticationLevel::admin);
esp3d_log("Ethernet connected");
EthConfig::setConnected(true);
} break;
case ARDUINO_EVENT_ETH_DISCONNECTED: {
esp3d_log("Ethernet disconnected");
esp3d_commands.dispatch("Cable disconnected",
ESP3DClientType::all_clients, no_id,
ESP3DMessageType::unique, ESP3DClientType::system,
ESP3DAuthenticationLevel::admin);
EthConfig::setConnected(false);
} break;
case ARDUINO_EVENT_ETH_LOST_IP:
esp3d_log("Ethernet lost IP");
break;
case ARDUINO_EVENT_ETH_GOT_IP: {
#if COMMUNICATION_PROTOCOL != MKS_SERIAL
#if defined(ESP_GOT_IP_HOOK) && defined(GCODE_HOST_FEATURE)
ESP3DHal::wait(500);
String ipMsg = esp3d_string::expandString(ESP_GOT_IP_HOOK);
esp3d_log("Got IP, sending hook: %s", ipMsg.c_str());
esp3d_gcode_host.processScript(ipMsg.c_str(),
@ -268,7 +279,9 @@ void NetConfig::onWiFiEvent(WiFiEvent_t event) {
#endif // #if COMMUNICATION_PROTOCOL == MKS_SERIAL
EthConfig::setConnected(true);
} break;
case ARDUINO_EVENT_ETH_STOP:
esp3d_log("Ethernet stopped");
EthConfig::setConnected(false);
break;
#endif // ETH_FEATURE
@ -523,12 +536,20 @@ void NetConfig::handle() {
bool NetConfig::isIPModeDHCP(uint8_t mode) {
bool started = false;
#ifdef ARDUINO_ARCH_ESP32
tcpip_adapter_dhcp_status_t dhcp_status;
tcpip_adapter_dhcpc_get_status((mode == ESP_WIFI_STA) ? TCPIP_ADAPTER_IF_STA
: (mode == ESP_WIFI_AP) ? TCPIP_ADAPTER_IF_AP
: TCPIP_ADAPTER_IF_ETH,
if (mode == ESP_WIFI_STA || mode == ESP_WIFI_AP) {
esp_netif_dhcp_status_t dhcp_status;
esp_netif_dhcpc_get_status((mode == ESP_WIFI_STA) ? get_esp_interface_netif(ESP_IF_WIFI_STA)
: get_esp_interface_netif(ESP_IF_WIFI_AP),
&dhcp_status);
started = (dhcp_status == TCPIP_ADAPTER_DHCP_STARTED);
esp3d_log("DHCP Status %d", (int)dhcp_status);
started = (dhcp_status == ESP_NETIF_DHCP_STARTED);
}
#if defined(ETH_FEATURE)
if (mode == ESP_ETH_STA) {
started = (EthConfig::ipMode()==DHCP_MODE);
}
#endif // ETH_FEATURE
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
(void)mode;
@ -540,12 +561,13 @@ bool NetConfig::isIPModeDHCP(uint8_t mode) {
bool NetConfig::isDHCPServer(uint8_t mode) {
bool itis = false;
#ifdef ARDUINO_ARCH_ESP32
tcpip_adapter_dhcp_status_t dhcp_status;
tcpip_adapter_dhcps_get_status((mode == ESP_WIFI_STA) ? TCPIP_ADAPTER_IF_STA
: (mode == ESP_WIFI_AP) ? TCPIP_ADAPTER_IF_AP
: TCPIP_ADAPTER_IF_ETH,
//Fzor some reason esp_netif_dhcps_get_status() give always !DHCP_MODE for Ethernet even if it is set to DHCP
if (mode == ESP_WIFI_AP) {
esp_netif_dhcp_status_t dhcp_status;
esp_netif_dhcps_get_status(get_esp_interface_netif(ESP_IF_WIFI_AP),
&dhcp_status);
itis = (dhcp_status == TCPIP_ADAPTER_DHCP_STARTED);
itis = (dhcp_status == ESP_NETIF_DHCP_STARTED);
}
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
(void)mode;

View File

@ -35,6 +35,7 @@
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#include <esp_netif.h>
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
#include <ESP8266WiFi.h>

View File

@ -37,7 +37,7 @@ HardwareSerial *Serials[MAX_SERIAL] = {&Serial, &Serial1};
#if defined(ARDUINO_ARCH_ESP32)
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) ||defined(CONFIG_IDF_TARGET_ESP32S2)
#define MAX_SERIAL 2
HardwareSerial *Serials[MAX_SERIAL] = {&Serial, &Serial1};
#else
@ -293,7 +293,7 @@ void ESP3DSerialService::flushbuffer() {
// dispatch command
if (_started) {
ESP3DMessage *message = ESP3DMessageManager::newMsg(
ESP3DMessage *message = esp3d_message_manager.newMsg(
_origin,
_id == MAIN_SERIAL ? ESP3DClientType::all_clients
: esp3d_commands.getOutputClient(),
@ -550,7 +550,7 @@ bool ESP3DSerialService::dispatch(ESP3DMessage *message) {
if (writeBytes(message->data, message->size) == message->size) {
flush();
// Delete message now
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
done = true;
} else {
esp3d_log_e("Error while sending data");

View File

@ -167,7 +167,7 @@ void Serial_2_Socket::handle_flush() {
}
void Serial_2_Socket::flush(void) {
if (_TXbufferSize > 0 && _started && !_paused) {
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::socket_serial, ESP3DClientType::all_clients, _TXbuffer,
_TXbufferSize, _auth);
// dispatch command
@ -195,7 +195,7 @@ bool Serial_2_Socket::dispatch(ESP3DMessage *message) {
esp3d_log_e("Serial2Socket: cannot push all data");
return false;
}
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}
esp3d_log_e("Serial2Socket: no data in message");

View File

@ -22,8 +22,7 @@
#if defined(TELNET_FEATURE) || \
(defined(ESP_LOG_FEATURE) && ESP_LOG_FEATURE == LOG_OUTPUT_TELNET)
#include <WiFiClient.h>
#include <WiFiServer.h>
#include "../../core/esp3d_commands.h"
#include "../../core/esp3d_message.h"
@ -200,7 +199,7 @@ bool Telnet_Server::dispatch(ESP3DMessage *message) {
if (sentcnt != message->size) {
return false;
}
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}
return false;
@ -221,7 +220,7 @@ void Telnet_Server::flushbuffer() {
return;
}
_buffer[_buffer_size] = 0x0;
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
ESP3DClientType::telnet, esp3d_commands.getOutputClient(), _buffer,
_buffer_size, _auth);
if (msg) {

View File

@ -21,8 +21,9 @@
#ifndef _TELNET_SERVER_H
#define _TELNET_SERVER_H
class WiFiServer;
class WiFiClient;
#include <WiFiClient.h>
#include <WiFiServer.h>
#include "../../core/esp3d_message.h"
#define ESP3D_TELNET_BUFFER_SIZE 1200

View File

@ -63,11 +63,11 @@ const uint16_t ServstringKeysPos[] = {ESP_TIME_ZONE,
ESP_NOTIFICATION_TOKEN2,
ESP_NOTIFICATION_SETTINGS};
const char* IPKeysVal[] = {"STA_IP", "STA_GW", "STA_MSK", "STA_DNS", "AP_IP"};
const char* IPKeysVal[] = {"STA_IP", "STA_GW", "STA_MSK", "STA_DNS", "AP_IP","ETH_STA_IP", "ETH_STA_GW", "ETH_STA_MSK", "ETH_STA_DNS"};
const uint16_t IPKeysPos[] = {ESP_STA_IP_VALUE, ESP_STA_GATEWAY_VALUE,
ESP_STA_MASK_VALUE, ESP_STA_DNS_VALUE,
ESP_AP_IP_VALUE};
ESP_AP_IP_VALUE, ESP_ETH_STA_IP_VALUE, ESP_ETH_STA_GATEWAY_VALUE, ESP_ETH_STA_MASK_VALUE, ESP_ETH_STA_DNS_VALUE};
const char* ServintKeysVal[] = {
"Serial_Bridge_Baud"
@ -226,7 +226,7 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("OFF", value) == 0) {
b = ESP_NO_NETWORK;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}
@ -243,7 +243,23 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("OFF", value) == 0) {
b = ESP_NO_NETWORK;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}
// ETH STA fallback mode BT, OFF
if (!done) {
if (strcasecmp("eth_sta_fallback", key) == 0) {
T = 'B';
P = ESP_STA_FALLBACK_MODE;
done = true;
if (strcasecmp("BT", value) == 0) {
b = ESP_BT;
} else if (strcasecmp("OFF", value) == 0) {
b = ESP_NO_NETWORK;
} else {
P = -1; // invalid value
}
}
}
@ -259,10 +275,27 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("STATIC", key) == 0) {
b = STATIC_IP_MODE;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}
// ETH STA IP Mode DHCP / STATIC
if (!done) {
if (strcasecmp("ETH_STA_IP_mode", key) == 0) {
T = 'B';
P = ESP_ETH_STA_IP_MODE;
done = true;
if (strcasecmp("DHCP", value) == 0) {
b = DHCP_MODE;
} else if (strcasecmp("STATIC", key) == 0) {
b = STATIC_IP_MODE;
} else {
P = -1; // invalid value
}
}
}
} else if (strcasecmp("services", section) == 0) {
if (!done) {
done = processString(ServstringKeysVal, ServstringKeysPos,
@ -310,7 +343,7 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("HOMEASSISTANT", value) == 0) {
b = ESP_HOMEASSISTANT_NOTIFICATION;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}
@ -333,7 +366,7 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("BME280", key) == 0) {
b = BME280_DEVICE;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}
@ -366,7 +399,7 @@ bool processingFileFunction(const char* section, const char* key,
} else if (strcasecmp("SMOOTHIEWARE", value) == 0) {
b = SMOOTHIEWARE;
} else {
P = -1; // invalide value
P = -1; // invalid value
}
}
}

View File

@ -45,8 +45,8 @@ typedef ESP_SDFile WebDavFile;
typedef ESP_SD WebDavFS;
#endif // WEBDAV_FEATURE == FS_SD
class WiFiServer;
class WiFiClient;
#include <WiFiClient.h>
#include <WiFiServer.h>
class WebdavServer {
public:

View File

@ -64,7 +64,7 @@ bool WebSocket_Server::dispatch(ESP3DMessage *message) {
if (sentcnt != message->size) {
return false;
}
ESP3DMessageManager::deleteMsg(message);
esp3d_message_manager.deleteMsg(message);
return true;
}
return false;
@ -330,7 +330,7 @@ void WebSocket_Server::flushRXbuffer() {
return;
}
_RXbuffer[_RXbufferSize] = 0x0;
ESP3DMessage *msg = ESP3DMessageManager::newMsg(
ESP3DMessage *msg = esp3d_message_manager.newMsg(
_type, esp3d_commands.getOutputClient(), _RXbuffer, _RXbufferSize, _auth);
if (msg) {
// process command

View File

@ -22,6 +22,7 @@
#if defined(WIFI_FEATURE)
#ifdef ARDUINO_ARCH_ESP32
#include <esp_wifi.h>
#include <esp_wifi_ap_get_sta_list.h>
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
#endif // ARDUINO_ARCH_ESP8266
@ -30,6 +31,10 @@
#include "../network/netconfig.h"
#include "../wifi/wificonfig.h"
#if defined(ARDUINO_ARCH_ESP32)
esp_netif_t *get_esp_interface_netif(esp_interface_t interface);
#endif // ARDUINO_ARCH_ESP32
const uint8_t DEFAULT_AP_MASK_VALUE[] = {255, 255, 255, 0};
IPAddress WiFiConfig::_ap_gateway;
@ -468,8 +473,8 @@ const char* WiFiConfig::AP_Auth_String() {
const char* WiFiConfig::AP_Gateway_String() {
static String tmp;
#ifdef ARDUINO_ARCH_ESP32
tcpip_adapter_ip_info_t ip_AP;
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_AP);
esp_netif_ip_info_t ip_AP;
esp_netif_get_ip_info(get_esp_interface_netif(ESP_IF_WIFI_AP), &ip_AP);
tmp = IPAddress(ip_AP.gw.addr).toString();
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
@ -485,8 +490,8 @@ const char* WiFiConfig::AP_Gateway_String() {
const char* WiFiConfig::AP_Mask_String() {
static String tmp;
#ifdef ARDUINO_ARCH_ESP32
tcpip_adapter_ip_info_t ip_AP;
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_AP);
esp_netif_ip_info_t ip_AP;
esp_netif_get_ip_info(get_esp_interface_netif(ESP_IF_WIFI_STA), &ip_AP);
tmp = IPAddress(ip_AP.netmask.addr).toString();
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
@ -509,16 +514,22 @@ const char* WiFiConfig::getConnectedSTA(uint8_t* totalcount, bool reset) {
if (current > count) {
current = 0;
}
static wifi_sta_list_t station;
static tcpip_adapter_sta_list_t tcpip_sta_list;
static wifi_sta_list_t sta_list;
static wifi_sta_mac_ip_list_t tcpip_sta_list;
if (reset) {
count = 0;
}
if (count == 0) {
current = 0;
esp_wifi_ap_get_sta_list(&station);
tcpip_adapter_get_sta_list(&station, &tcpip_sta_list);
count = station.num;
if(esp_wifi_ap_get_sta_list(&sta_list)!=ESP_OK){
return "";
}
if (sta_list.num > 0) {
ESP_ERROR_CHECK(
esp_wifi_ap_get_sta_list_with_ip(&sta_list, &tcpip_sta_list));
}
count = sta_list.num;
}
if (count > 0) {
data = IPAddress(tcpip_sta_list.sta[current].ip.addr).toString();

View File

@ -44,6 +44,7 @@
#define AUTH_WPA_WPA2_PSK WIFI_AUTH_WPA_WPA2_PSK
#define ENC_TYPE_NONE AUTH_OPEN
#define WiFiMode_t wifi_mode_t
#include <esp_netif.h>
#endif // ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
#include <ESP8266WiFi.h>

View File

@ -1,215 +0,0 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg

View File

@ -1,50 +0,0 @@
2021-01-06
Run the SdErrorCode example to produce an updated list.
Code,Symbol - failed operation
0X00,SD_CARD_ERROR_NONE - No error
0X01,SD_CARD_ERROR_CMD0 - Card reset failed
0X02,SD_CARD_ERROR_CMD2 - SDIO read CID
0X03,SD_CARD_ERROR_CMD3 - SDIO publish RCA
0X04,SD_CARD_ERROR_CMD6 - Switch card function
0X05,SD_CARD_ERROR_CMD7 - SDIO card select
0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings
0X07,SD_CARD_ERROR_CMD9 - Read CSD data
0X08,SD_CARD_ERROR_CMD10 - Read CID data
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read
0X0A,SD_CARD_ERROR_CMD13 - Read card status
0X0B,SD_CARD_ERROR_CMD17 - Read single block
0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks
0X0D,SD_CARD_ERROR_CMD24 - Write single block
0X0E,SD_CARD_ERROR_CMD25 - Write multiple blocks
0X0F,SD_CARD_ERROR_CMD32 - Set first erase block
0X10,SD_CARD_ERROR_CMD33 - Set last erase block
0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks
0X12,SD_CARD_ERROR_CMD58 - Read OCR register
0X13,SD_CARD_ERROR_CMD59 - Set CRC mode
0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width
0X15,SD_CARD_ERROR_ACMD13 - Read extended status
0X16,SD_CARD_ERROR_ACMD23 - Set pre-erased count
0X17,SD_CARD_ERROR_ACMD41 - Activate card initialization
0X18,SD_CARD_ERROR_READ_TOKEN - Bad read data token
0X19,SD_CARD_ERROR_READ_CRC - Read CRC error
0X1A,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout
0X1B,SD_CARD_ERROR_READ_REG - Read CID or CSD failed.
0X1C,SD_CARD_ERROR_READ_START - Bad readStart argument
0X1D,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout
0X1E,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed
0X1F,SD_CARD_ERROR_TRANSFER_COMPLETE - SDIO transfer complete
0X20,SD_CARD_ERROR_WRITE_DATA - Write data not accepted
0X21,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout
0X22,SD_CARD_ERROR_WRITE_START - Bad writeStart argument
0X23,SD_CARD_ERROR_WRITE_PROGRAMMING - Flash programming
0X24,SD_CARD_ERROR_WRITE_TIMEOUT - Write timeout
0X25,SD_CARD_ERROR_DMA - DMA transfer failed
0X26,SD_CARD_ERROR_ERASE - Card did not accept erase commands
0X27,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase
0X28,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout
0X29,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized
0X2A,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config
0X2B,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command
0X2C,SD_CARD_ERROR_UNKNOWN - Unknown error

View File

@ -1,129 +0,0 @@
/*
* Example use of chdir(), ls(), mkdir(), and rmdir().
*/
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
// SD card chip select pin.
const uint8_t chipSelect = SS;
//------------------------------------------------------------------------------
// File system object.
SdFat sd;
// Directory file.
SdFile root;
// Use for file creation in folders.
SdFile file;
// Create a Serial output stream.
ArduinoOutStream cout(Serial);
// Buffer for Serial input.
char cinBuf[40];
// Create a serial input stream.
ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
//==============================================================================
// Error messages stored in flash.
#define error(msg) sd.errorHalt(F(msg))
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
delay(1000);
cout << F("Type any character to start\n");
// Wait for input line and discard.
cin.readline();
cout << endl;
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
sd.initErrorHalt();
}
if (sd.exists("Folder1")
|| sd.exists("Folder1/file1.txt")
|| sd.exists("Folder1/File2.txt")) {
error("Please remove existing Folder1, file1.txt, and File2.txt");
}
int rootFileCount = 0;
if (!root.open("/")) {
error("open root failed");
}
while (file.openNext(&root, O_RDONLY)) {
if (!file.isHidden()) {
rootFileCount++;
}
file.close();
if (rootFileCount > 10) {
error("Too many files in root. Please use an empty SD.");
}
}
if (rootFileCount) {
cout << F("\nPlease use an empty SD for best results.\n\n");
delay(1000);
}
// Create a new folder.
if (!sd.mkdir("Folder1")) {
error("Create Folder1 failed");
}
cout << F("Created Folder1\n");
// Create a file in Folder1 using a path.
if (!file.open("Folder1/file1.txt", O_WRONLY | O_CREAT)) {
error("create Folder1/file1.txt failed");
}
file.close();
cout << F("Created Folder1/file1.txt\n");
// Change volume working directory to Folder1.
if (!sd.chdir("Folder1")) {
error("chdir failed for Folder1.\n");
}
cout << F("chdir to Folder1\n");
// Create File2.txt in current directory.
if (!file.open("File2.txt", O_WRONLY | O_CREAT)) {
error("create File2.txt failed");
}
file.close();
cout << F("Created File2.txt in current directory\n");
cout << F("\nList of files on the SD.\n");
sd.ls("/", LS_R);
// Remove files from current directory.
if (!sd.remove("file1.txt") || !sd.remove("File2.txt")) {
error("remove failed");
}
cout << F("\nfile1.txt and File2.txt removed.\n");
// Change current directory to root.
if (!sd.chdir()) {
error("chdir to root failed.\n");
}
cout << F("\nList of files on the SD.\n");
sd.ls(LS_R);
// Remove Folder1.
if (!sd.rmdir("Folder1")) {
error("rmdir for Folder1 failed\n");
}
cout << F("\nFolder1 removed.\n");
cout << F("\nList of files on the SD.\n");
sd.ls(LS_R);
cout << F("Done!\n");
}
//------------------------------------------------------------------------------
// Nothing happens in loop.
void loop() {}

View File

@ -1,60 +0,0 @@
/*
* Print size, modify date/time, and name for all files in root.
*/
#include <SPI.h>
#include "SdFat.h"
// SD default chip select pin.
const uint8_t chipSelect = SS;
// file system object
SdFat sd;
SdFile root;
SdFile file;
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
Serial.println("Type any character to start");
while (!Serial.available()) {
yield();
}
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
sd.initErrorHalt();
}
if (!root.open("/")) {
sd.errorHalt("open root failed");
}
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while (file.openNext(&root, O_RDONLY)) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printModifyDateTime(&Serial);
Serial.write(' ');
file.printName(&Serial);
if (file.isDir()) {
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
if (root.getError()) {
Serial.println("openNext failed");
} else {
Serial.println("Done!");
}
}
//------------------------------------------------------------------------------
void loop() {}

View File

@ -1,161 +0,0 @@
// Quick hardware test for SPI card access.
//
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
//
// Set DISABLE_CHIP_SELECT to disable a second SPI device.
// For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
// to 10 to disable the Ethernet controller.
const int8_t DISABLE_CHIP_SELECT = -1;
//
// Test with reduced SPI speed for breadboards. SD_SCK_MHZ(4) will select
// the highest speed supported by the board that is not over 4 MHz.
// Change SPI_SPEED to SD_SCK_MHZ(50) for best performance.
#define SPI_SPEED SD_SCK_MHZ(4)
//------------------------------------------------------------------------------
// File system object.
SdFat sd;
// Serial streams
ArduinoOutStream cout(Serial);
// input buffer for line
char cinBuf[40];
ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
// SD card chip select
int chipSelect;
void cardOrSpeed() {
cout << F("Try another SD card or reduce the SPI bus speed.\n");
cout << F("Edit SPI_SPEED in this program to change it.\n");
}
void reformatMsg() {
cout << F("Try reformatting the card. For best results use\n");
cout << F("the SdFormatter program in SdFat/examples or download\n");
cout << F("and use SDFormatter from www.sdcard.org/downloads.\n");
}
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
cout << F("\nSPI pins:\n");
cout << F("MISO: ") << int(MISO) << endl;
cout << F("MOSI: ") << int(MOSI) << endl;
cout << F("SCK: ") << int(SCK) << endl;
cout << F("SS: ") << int(SS) << endl;
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
"a second SPI device. For example, with the Ethernet\n"
"shield, DISABLE_CHIP_SELECT should be set to 10\n"
"to disable the Ethernet controller.\n");
}
cout << F(
"\nSD chip select is the key hardware option.\n"
"Common values are:\n"
"Arduino Ethernet shield, pin 4\n"
"Sparkfun SD shield, pin 8\n"
"Adafruit SD shields and modules, pin 10\n");
}
bool firstTry = true;
void loop() {
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
if (!firstTry) {
cout << F("\nRestarting\n");
}
firstTry = false;
cout << F("\nEnter the chip select pin number: ");
while (!Serial.available()) {
yield();
}
cin.readline();
if (cin >> chipSelect) {
cout << chipSelect << endl;
} else {
cout << F("\nInvalid pin number\n");
return;
}
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
pinMode(DISABLE_CHIP_SELECT, OUTPUT);
digitalWrite(DISABLE_CHIP_SELECT, HIGH);
}
if (!sd.begin(chipSelect, SPI_SPEED)) {
if (sd.card()->errorCode()) {
cout << F(
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is chipSelect set to the correct value?\n"
"Does another SPI device need to be disabled?\n"
"Is there a wiring/soldering problem?\n");
cout << F("\nerrorCode: ") << hex << showbase;
cout << int(sd.card()->errorCode());
cout << F(", errorData: ") << int(sd.card()->errorData());
cout << dec << noshowbase << endl;
return;
}
if (sd.vol()->fatType() == 0) {
cout << F("Can't find a valid FAT16/FAT32 partition.\n");
reformatMsg();
return;
}
cout << F("begin failed, can't determine error type\n");
return;
}
cout << F("\nCard successfully initialized.\n");
cout << endl;
uint32_t size = sd.card()->cardSize();
if (size == 0) {
cout << F("Can't determine the card size.\n");
cardOrSpeed();
return;
}
uint32_t sizeMB = 0.000512 * size + 0.5;
cout << F("Card size: ") << sizeMB;
cout << F(" MB (MB = 1,000,000 bytes)\n");
cout << endl;
cout << F("Volume is FAT") << int(sd.vol()->fatType());
cout << F(", Cluster size (bytes): ") << 512L * sd.vol()->blocksPerCluster();
cout << endl << endl;
cout << F("Files found (date time size name):\n");
sd.ls(LS_R | LS_DATE | LS_SIZE);
if ((sizeMB > 1100 && sd.vol()->blocksPerCluster() < 64)
|| (sizeMB < 2200 && sd.vol()->fatType() == 32)) {
cout << F("\nThis card should be reformatted for best performance.\n");
cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n");
cout << F("Only cards larger than 2 GB should be formatted FAT32.\n");
reformatMsg();
return;
}
// Read any extra Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
cout << F("\nSuccess! Type any character to restart.\n");
while (!Serial.available()) {
yield();
}
}

View File

@ -1,552 +0,0 @@
/*
* This program will format an SD or SDHC card.
* Warning all data will be deleted!
*
* For SD/SDHC cards larger than 64 MB this
* program attempts to match the format
* generated by SDFormatter available here:
*
* http://www.sdcard.org/consumers/formatter/
*
* For smaller cards this program uses FAT16
* and SDFormatter uses FAT12.
*/
#error use new Version 2 SdFormatter
// Set USE_SDIO to zero for SPI card access.
#define USE_SDIO 0
//
// Change the value of chipSelect if your hardware does
// not use the default value, SS. Common values are:
// Arduino Ethernet shield: pin 4
// Sparkfun SD shield: pin 8
// Adafruit SD shields and modules: pin 10
const uint8_t chipSelect = SS;
// Initialize at highest supported speed not over 50 MHz.
// Reduce max speed if errors occur.
#define SPI_SPEED SD_SCK_MHZ(50)
// Print extra info for debug if DEBUG_PRINT is nonzero
#define DEBUG_PRINT 0
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
#if DEBUG_PRINT
#include "FreeStack.h"
#endif // DEBUG_PRINT
// Serial output stream
ArduinoOutStream cout(Serial);
#if USE_SDIO
// Use faster SdioCardEX
SdioCardEX card;
// SdioCard card;
#else // USE_SDIO
Sd2Card card;
#endif // USE_SDIO
uint32_t cardSizeBlocks;
uint32_t cardCapacityMB;
// cache for SD block
cache_t cache;
// MBR information
uint8_t partType;
uint32_t relSector;
uint32_t partSize;
// Fake disk geometry
uint8_t numberOfHeads;
uint8_t sectorsPerTrack;
// FAT parameters
uint16_t reservedSectors;
uint8_t sectorsPerCluster;
uint32_t fatStart;
uint32_t fatSize;
uint32_t dataStart;
// constants for file system structure
uint16_t const BU16 = 128;
uint16_t const BU32 = 8192;
// strings needed in file system structures
char noName[] = "NO NAME ";
char fat16str[] = "FAT16 ";
char fat32str[] = "FAT32 ";
//------------------------------------------------------------------------------
#define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();}
//------------------------------------------------------------------------------
void sdErrorHalt() {
if (card.errorCode()) {
cout << F("SD error: ") << hex << int(card.errorCode());
cout << ',' << int(card.errorData()) << dec << endl;
}
while (true) {}
}
//------------------------------------------------------------------------------
#if DEBUG_PRINT
void debugPrint() {
cout << F("FreeStack: ") << FreeStack() << endl;
cout << F("partStart: ") << relSector << endl;
cout << F("partSize: ") << partSize << endl;
cout << F("reserved: ") << reservedSectors << endl;
cout << F("fatStart: ") << fatStart << endl;
cout << F("fatSize: ") << fatSize << endl;
cout << F("dataStart: ") << dataStart << endl;
cout << F("clusterCount: ");
cout << ((relSector + partSize - dataStart)/sectorsPerCluster) << endl;
cout << endl;
cout << F("Heads: ") << int(numberOfHeads) << endl;
cout << F("Sectors: ") << int(sectorsPerTrack) << endl;
cout << F("Cylinders: ");
cout << cardSizeBlocks/(numberOfHeads*sectorsPerTrack) << endl;
}
#endif // DEBUG_PRINT
//------------------------------------------------------------------------------
// write cached block to the card
uint8_t writeCache(uint32_t lbn) {
return card.writeBlock(lbn, cache.data);
}
//------------------------------------------------------------------------------
// initialize appropriate sizes for SD capacity
void initSizes() {
if (cardCapacityMB <= 6) {
sdError("Card is too small.");
} else if (cardCapacityMB <= 16) {
sectorsPerCluster = 2;
} else if (cardCapacityMB <= 32) {
sectorsPerCluster = 4;
} else if (cardCapacityMB <= 64) {
sectorsPerCluster = 8;
} else if (cardCapacityMB <= 128) {
sectorsPerCluster = 16;
} else if (cardCapacityMB <= 1024) {
sectorsPerCluster = 32;
} else if (cardCapacityMB <= 32768) {
sectorsPerCluster = 64;
} else {
// SDXC cards
sectorsPerCluster = 128;
}
cout << F("Blocks/Cluster: ") << int(sectorsPerCluster) << endl;
// set fake disk geometry
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
if (cardCapacityMB <= 16) {
numberOfHeads = 2;
} else if (cardCapacityMB <= 32) {
numberOfHeads = 4;
} else if (cardCapacityMB <= 128) {
numberOfHeads = 8;
} else if (cardCapacityMB <= 504) {
numberOfHeads = 16;
} else if (cardCapacityMB <= 1008) {
numberOfHeads = 32;
} else if (cardCapacityMB <= 2016) {
numberOfHeads = 64;
} else if (cardCapacityMB <= 4032) {
numberOfHeads = 128;
} else {
numberOfHeads = 255;
}
}
//------------------------------------------------------------------------------
// zero cache and optionally set the sector signature
void clearCache(uint8_t addSig) {
memset(&cache, 0, sizeof(cache));
if (addSig) {
cache.mbr.mbrSig0 = BOOTSIG0;
cache.mbr.mbrSig1 = BOOTSIG1;
}
}
//------------------------------------------------------------------------------
// zero FAT and root dir area on SD
void clearFatDir(uint32_t bgn, uint32_t count) {
clearCache(false);
#if USE_SDIO
for (uint32_t i = 0; i < count; i++) {
if (!card.writeBlock(bgn + i, cache.data)) {
sdError("Clear FAT/DIR writeBlock failed");
}
if ((i & 0XFF) == 0) {
cout << '.';
}
}
#else // USE_SDIO
if (!card.writeStart(bgn, count)) {
sdError("Clear FAT/DIR writeStart failed");
}
for (uint32_t i = 0; i < count; i++) {
if ((i & 0XFF) == 0) {
cout << '.';
}
if (!card.writeData(cache.data)) {
sdError("Clear FAT/DIR writeData failed");
}
}
if (!card.writeStop()) {
sdError("Clear FAT/DIR writeStop failed");
}
#endif // USE_SDIO
cout << endl;
}
//------------------------------------------------------------------------------
// return cylinder number for a logical block number
uint16_t lbnToCylinder(uint32_t lbn) {
return lbn / (numberOfHeads * sectorsPerTrack);
}
//------------------------------------------------------------------------------
// return head number for a logical block number
uint8_t lbnToHead(uint32_t lbn) {
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
}
//------------------------------------------------------------------------------
// return sector number for a logical block number
uint8_t lbnToSector(uint32_t lbn) {
return (lbn % sectorsPerTrack) + 1;
}
//------------------------------------------------------------------------------
// format and write the Master Boot Record
void writeMbr() {
clearCache(true);
part_t* p = cache.mbr.part;
p->boot = 0;
uint16_t c = lbnToCylinder(relSector);
if (c > 1023) {
sdError("MBR CHS");
}
p->beginCylinderHigh = c >> 8;
p->beginCylinderLow = c & 0XFF;
p->beginHead = lbnToHead(relSector);
p->beginSector = lbnToSector(relSector);
p->type = partType;
uint32_t endLbn = relSector + partSize - 1;
c = lbnToCylinder(endLbn);
if (c <= 1023) {
p->endCylinderHigh = c >> 8;
p->endCylinderLow = c & 0XFF;
p->endHead = lbnToHead(endLbn);
p->endSector = lbnToSector(endLbn);
} else {
// Too big flag, c = 1023, h = 254, s = 63
p->endCylinderHigh = 3;
p->endCylinderLow = 255;
p->endHead = 254;
p->endSector = 63;
}
p->firstSector = relSector;
p->totalSectors = partSize;
if (!writeCache(0)) {
sdError("write MBR");
}
}
//------------------------------------------------------------------------------
// generate serial number from card size and micros since boot
uint32_t volSerialNumber() {
return (cardSizeBlocks << 8) + micros();
}
//------------------------------------------------------------------------------
// format the SD as FAT16
void makeFat16() {
uint32_t nc;
for (dataStart = 2 * BU16;; dataStart += BU16) {
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
fatSize = (nc + 2 + 255)/256;
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
if (dataStart < r) {
continue;
}
relSector = dataStart - r + BU16;
break;
}
// check valid cluster count for FAT16 volume
if (nc < 4085 || nc >= 65525) {
sdError("Bad cluster count");
}
reservedSectors = 1;
fatStart = relSector + reservedSectors;
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
if (partSize < 32680) {
partType = 0X01;
} else if (partSize < 65536) {
partType = 0X04;
} else {
partType = 0X06;
}
// write MBR
writeMbr();
clearCache(true);
fat_boot_t* pb = &cache.fbs;
pb->jump[0] = 0XEB;
pb->jump[1] = 0X00;
pb->jump[2] = 0X90;
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
pb->oemId[i] = ' ';
}
pb->bytesPerSector = 512;
pb->sectorsPerCluster = sectorsPerCluster;
pb->reservedSectorCount = reservedSectors;
pb->fatCount = 2;
pb->rootDirEntryCount = 512;
pb->mediaType = 0XF8;
pb->sectorsPerFat16 = fatSize;
pb->sectorsPerTrack = sectorsPerTrack;
pb->headCount = numberOfHeads;
pb->hidddenSectors = relSector;
pb->totalSectors32 = partSize;
pb->driveNumber = 0X80;
pb->bootSignature = EXTENDED_BOOT_SIG;
pb->volumeSerialNumber = volSerialNumber();
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
// write partition boot sector
if (!writeCache(relSector)) {
sdError("FAT16 write PBS failed");
}
// clear FAT and root directory
clearFatDir(fatStart, dataStart - fatStart);
clearCache(false);
cache.fat16[0] = 0XFFF8;
cache.fat16[1] = 0XFFFF;
// write first block of FAT and backup for reserved clusters
if (!writeCache(fatStart)
|| !writeCache(fatStart + fatSize)) {
sdError("FAT16 reserve failed");
}
}
//------------------------------------------------------------------------------
// format the SD as FAT32
void makeFat32() {
uint32_t nc;
relSector = BU32;
for (dataStart = 2 * BU32;; dataStart += BU32) {
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
fatSize = (nc + 2 + 127)/128;
uint32_t r = relSector + 9 + 2 * fatSize;
if (dataStart >= r) {
break;
}
}
// error if too few clusters in FAT32 volume
if (nc < 65525) {
sdError("Bad cluster count");
}
reservedSectors = dataStart - relSector - 2 * fatSize;
fatStart = relSector + reservedSectors;
partSize = nc * sectorsPerCluster + dataStart - relSector;
// type depends on address of end sector
// max CHS has lbn = 16450560 = 1024*255*63
if ((relSector + partSize) <= 16450560) {
// FAT32
partType = 0X0B;
} else {
// FAT32 with INT 13
partType = 0X0C;
}
writeMbr();
clearCache(true);
fat32_boot_t* pb = &cache.fbs32;
pb->jump[0] = 0XEB;
pb->jump[1] = 0X00;
pb->jump[2] = 0X90;
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
pb->oemId[i] = ' ';
}
pb->bytesPerSector = 512;
pb->sectorsPerCluster = sectorsPerCluster;
pb->reservedSectorCount = reservedSectors;
pb->fatCount = 2;
pb->mediaType = 0XF8;
pb->sectorsPerTrack = sectorsPerTrack;
pb->headCount = numberOfHeads;
pb->hidddenSectors = relSector;
pb->totalSectors32 = partSize;
pb->sectorsPerFat32 = fatSize;
pb->fat32RootCluster = 2;
pb->fat32FSInfo = 1;
pb->fat32BackBootBlock = 6;
pb->driveNumber = 0X80;
pb->bootSignature = EXTENDED_BOOT_SIG;
pb->volumeSerialNumber = volSerialNumber();
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
// write partition boot sector and backup
if (!writeCache(relSector)
|| !writeCache(relSector + 6)) {
sdError("FAT32 write PBS failed");
}
clearCache(true);
// write extra boot area and backup
if (!writeCache(relSector + 2)
|| !writeCache(relSector + 8)) {
sdError("FAT32 PBS ext failed");
}
fat32_fsinfo_t* pf = &cache.fsinfo;
pf->leadSignature = FSINFO_LEAD_SIG;
pf->structSignature = FSINFO_STRUCT_SIG;
pf->freeCount = 0XFFFFFFFF;
pf->nextFree = 0XFFFFFFFF;
// write FSINFO sector and backup
if (!writeCache(relSector + 1)
|| !writeCache(relSector + 7)) {
sdError("FAT32 FSINFO failed");
}
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
clearCache(false);
cache.fat32[0] = 0x0FFFFFF8;
cache.fat32[1] = 0x0FFFFFFF;
cache.fat32[2] = 0x0FFFFFFF;
// write first block of FAT and backup for reserved clusters
if (!writeCache(fatStart)
|| !writeCache(fatStart + fatSize)) {
sdError("FAT32 reserve failed");
}
}
//------------------------------------------------------------------------------
// flash erase all data
uint32_t const ERASE_SIZE = 262144L;
void eraseCard() {
cout << endl << F("Erasing\n");
uint32_t firstBlock = 0;
uint32_t lastBlock;
uint16_t n = 0;
do {
lastBlock = firstBlock + ERASE_SIZE - 1;
if (lastBlock >= cardSizeBlocks) {
lastBlock = cardSizeBlocks - 1;
}
if (!card.erase(firstBlock, lastBlock)) {
sdError("erase failed");
}
cout << '.';
if ((n++)%32 == 31) {
cout << endl;
}
firstBlock += ERASE_SIZE;
} while (firstBlock < cardSizeBlocks);
cout << endl;
if (!card.readBlock(0, cache.data)) {
sdError("readBlock");
}
cout << hex << showbase << setfill('0') << internal;
cout << F("All data set to ") << setw(4) << int(cache.data[0]) << endl;
cout << dec << noshowbase << setfill(' ') << right;
cout << F("Erase done\n");
}
//------------------------------------------------------------------------------
void formatCard() {
cout << endl;
cout << F("Formatting\n");
initSizes();
if (card.type() != SD_CARD_TYPE_SDHC) {
cout << F("FAT16\n");
makeFat16();
} else {
cout << F("FAT32\n");
makeFat32();
}
#if DEBUG_PRINT
debugPrint();
#endif // DEBUG_PRINT
cout << F("Format done\n");
}
//------------------------------------------------------------------------------
void setup() {
char c;
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
cout << F("Type any character to start\n");
while (!Serial.available()) {
yield();
}
// Discard any extra characters.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
cout << F(
"\n"
"This program can erase and/or format SD/SDHC cards.\n"
"\n"
"Erase uses the card's fast flash erase command.\n"
"Flash erase sets all data to 0X00 for most cards\n"
"and 0XFF for a few vendor's cards.\n"
"\n"
"Cards larger than 2 GB will be formatted FAT32 and\n"
"smaller cards will be formatted FAT16.\n"
"\n"
"Warning, all data on the card will be erased.\n"
"Enter 'Y' to continue: ");
while (!Serial.available()) {
yield();
}
c = Serial.read();
cout << c << endl;
if (c != 'Y') {
cout << F("Quiting, you did not enter 'Y'.\n");
return;
}
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
cout << F(
"\n"
"Options are:\n"
"E - erase the card and skip formatting.\n"
"F - erase and then format the card. (recommended)\n"
"Q - quick format the card without erase.\n"
"\n"
"Enter option: ");
while (!Serial.available()) {
yield();
}
c = Serial.read();
cout << c << endl;
if (!strchr("EFQ", c)) {
cout << F("Quiting, invalid option entered.") << endl;
return;
}
#if USE_SDIO
if (!card.begin()) {
sdError("card.begin failed");
}
#else // USE_SDIO
if (!card.begin(chipSelect, SPI_SPEED)) {
cout << F(
"\nSD initialization failure!\n"
"Is the SD card inserted correctly?\n"
"Is chip select correct at the top of this program?\n");
sdError("card.begin failed");
}
#endif
cardSizeBlocks = card.cardSize();
if (cardSizeBlocks == 0) {
sdError("cardSize");
}
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
cout << F("Card Size: ") << setprecision(0) << 1.048576*cardCapacityMB;
cout << F(" MB, (MB = 1,000,000 bytes)") << endl;
if (c == 'E' || c == 'F') {
eraseCard();
}
if (c == 'F' || c == 'Q') {
formatCard();
}
}
//------------------------------------------------------------------------------
void loop() {}

View File

@ -1,248 +0,0 @@
/*
* This program attempts to initialize an SD card and analyze its structure.
*/
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
#error Use new Version 2 SdInfo
// Set USE_SDIO to zero for SPI card access.
#define USE_SDIO 0
/*
* SD chip select pin. Common values are:
*
* Arduino Ethernet shield, pin 4.
* SparkFun SD shield, pin 8.
* Adafruit SD shields and modules, pin 10.
* Default SD chip select is the SPI SS pin.
*/
const uint8_t SD_CHIP_SELECT = SS;
/*
* Set DISABLE_CHIP_SELECT to disable a second SPI device.
* For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
* to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CHIP_SELECT = -1;
#if USE_SDIO
// Use faster SdioCardEX
SdFatSdioEX sd;
// SdFatSdio sd;
#else // USE_SDIO
SdFat sd;
#endif // USE_SDIO
// serial output steam
ArduinoOutStream cout(Serial);
// global for card size
uint32_t cardSize;
// global for card erase size
uint32_t eraseSize;
//------------------------------------------------------------------------------
// store error strings in flash
#define sdErrorMsg(msg) sd.errorPrint(F(msg));
//------------------------------------------------------------------------------
uint8_t cidDmp() {
cid_t cid;
if (!sd.card()->readCID(&cid)) {
sdErrorMsg("readCID failed");
return false;
}
cout << F("\nManufacturer ID: ");
cout << hex << int(cid.mid) << dec << endl;
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
cout << F("Product: ");
for (uint8_t i = 0; i < 5; i++) {
cout << cid.pnm[i];
}
cout << F("\nVersion: ");
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
cout << F("Serial number: ") << hex << cid.psn << dec << endl;
cout << F("Manufacturing date: ");
cout << int(cid.mdt_month) << '/';
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
cout << endl;
return true;
}
//------------------------------------------------------------------------------
uint8_t csdDmp() {
csd_t csd;
uint8_t eraseSingleBlock;
if (!sd.card()->readCSD(&csd)) {
sdErrorMsg("readCSD failed");
return false;
}
if (csd.v1.csd_ver == 0) {
eraseSingleBlock = csd.v1.erase_blk_en;
eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
} else if (csd.v2.csd_ver == 1) {
eraseSingleBlock = csd.v2.erase_blk_en;
eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
} else {
cout << F("csd version error\n");
return false;
}
eraseSize++;
cout << F("cardSize: ") << 0.000512*cardSize;
cout << F(" MB (MB = 1,000,000 bytes)\n");
cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n");
cout << F("eraseSingleBlock: ");
if (eraseSingleBlock) {
cout << F("true\n");
} else {
cout << F("false\n");
}
return true;
}
//------------------------------------------------------------------------------
// print partition table
uint8_t partDmp() {
mbr_t mbr;
if (!sd.card()->readBlock(0, (uint8_t*)&mbr)) {
sdErrorMsg("read MBR failed");
return false;
}
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &mbr.part[ip - 1];
if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) {
cout << F("\nNo MBR. Assuming Super Floppy format.\n");
return true;
}
}
cout << F("\nSD Partition Table\n");
cout << F("part,boot,type,start,length\n");
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &mbr.part[ip - 1];
cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type);
cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl;
}
return true;
}
//------------------------------------------------------------------------------
void volDmp() {
cout << F("\nVolume is FAT") << int(sd.vol()->fatType()) << endl;
cout << F("blocksPerCluster: ") << int(sd.vol()->blocksPerCluster()) << endl;
cout << F("clusterCount: ") << sd.vol()->clusterCount() << endl;
cout << F("freeClusters: ");
uint32_t volFree = sd.vol()->freeClusterCount();
cout << volFree << endl;
float fs = 0.000512*volFree*sd.vol()->blocksPerCluster();
cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n");
cout << F("fatStartBlock: ") << sd.vol()->fatStartBlock() << endl;
cout << F("fatCount: ") << int(sd.vol()->fatCount()) << endl;
cout << F("blocksPerFat: ") << sd.vol()->blocksPerFat() << endl;
cout << F("rootDirStart: ") << sd.vol()->rootDirStart() << endl;
cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
if (sd.vol()->dataStartBlock() % eraseSize) {
cout << F("Data area is not aligned on flash erase boundaries!\n");
cout << F("Download and use formatter from www.sdcard.org!\n");
}
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;
// F stores strings in flash to save RAM
cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
#if !USE_SDIO
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
pinMode(DISABLE_CHIP_SELECT, OUTPUT);
digitalWrite(DISABLE_CHIP_SELECT, HIGH);
}
cout << F("\nAssuming the SD chip select pin is: ") <<int(SD_CHIP_SELECT);
cout << F("\nEdit SD_CHIP_SELECT to change the SD chip select pin.\n");
#endif // !USE_SDIO
}
//------------------------------------------------------------------------------
void loop() {
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");
while (!Serial.available()) {
yield();
}
uint32_t t = millis();
#if USE_SDIO
if (!sd.cardBegin()) {
sdErrorMsg("\ncardBegin failed");
return;
}
#else // USE_SDIO
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.cardBegin(SD_CHIP_SELECT, SD_SCK_MHZ(50))) {
sdErrorMsg("cardBegin failed");
return;
}
#endif // USE_SDIO
t = millis() - t;
cardSize = sd.card()->cardSize();
if (cardSize == 0) {
sdErrorMsg("cardSize failed");
return;
}
cout << F("\ninit time: ") << t << " ms" << endl;
cout << F("\nCard type: ");
switch (sd.card()->type()) {
case SD_CARD_TYPE_SD1:
cout << F("SD1\n");
break;
case SD_CARD_TYPE_SD2:
cout << F("SD2\n");
break;
case SD_CARD_TYPE_SDHC:
if (cardSize < 70000000) {
cout << F("SDHC\n");
} else {
cout << F("SDXC\n");
}
break;
default:
cout << F("Unknown\n");
}
if (!cidDmp()) {
return;
}
if (!csdDmp()) {
return;
}
uint32_t ocr;
if (!sd.card()->readOCR(&ocr)) {
sdErrorMsg("\nreadOCR failed");
return;
}
cout << F("OCR: ") << hex << ocr << dec << endl;
if (!partDmp()) {
return;
}
if (!sd.fsBegin()) {
sdErrorMsg("\nFile System initialization failed.\n");
return;
}
volDmp();
}

View File

@ -1,59 +0,0 @@
// An example of the SdFatSoftSpi template class.
// This example is for an Adafruit Data Logging Shield on a Mega.
// Software SPI is required on Mega since this shield connects to pins 10-13.
// This example will also run on an Uno and other boards using software SPI.
//
#include <SPI.h>
#include "SdFat.h"
#error See Version 2 software SPI example
#if ENABLE_SOFTWARE_SPI_CLASS // Must be set in SdFat/SdFatConfig.h
//
// Pin numbers in templates must be constants.
const uint8_t SOFT_MISO_PIN = 12;
const uint8_t SOFT_MOSI_PIN = 11;
const uint8_t SOFT_SCK_PIN = 13;
//
// Chip select may be constant or RAM variable.
const uint8_t SD_CHIP_SELECT_PIN = 10;
// SdFat software SPI template
SdFatSoftSpi<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> sd;
// Test file.
SdFile file;
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
Serial.println("Type any character to start");
while (!Serial.available()) {
yield();
}
if (!sd.begin(SD_CHIP_SELECT_PIN)) {
sd.initErrorHalt();
}
if (!file.open("SoftSPI.txt", O_RDWR | O_CREAT)) {
sd.errorHalt(F("open failed"));
}
file.println(F("This line was printed using software SPI."));
file.rewind();
while (file.available()) {
Serial.write(file.read());
}
file.close();
Serial.println(F("Done."));
}
//------------------------------------------------------------------------------
void loop() {}
#else // ENABLE_SOFTWARE_SPI_CLASS
#error ENABLE_SOFTWARE_SPI_CLASS must be set non-zero in SdFat/SdFatConfig.h
#endif //ENABLE_SOFTWARE_SPI_CLASS

View File

@ -1,169 +0,0 @@
// Simple performance test for Teensy 3.5/3.6 SDHC.
// Demonstrates yield() efficiency.
// Warning SdFatSdio and SdFatSdioEX normally should
// not both be used in a program.
// Each has its own cache and member variables.
#include "SdFat.h"
#error See Version 2 SDIO example
// 32 KiB buffer.
const size_t BUF_DIM = 32768;
// 8 MiB file.
const uint32_t FILE_SIZE = 256UL*BUF_DIM;
SdFatSdio sd;
SdFatSdioEX sdEx;
File file;
uint8_t buf[BUF_DIM];
// buffer as uint32_t
uint32_t* buf32 = (uint32_t*)buf;
// Total usec in read/write calls.
uint32_t totalMicros = 0;
// Time in yield() function.
uint32_t yieldMicros = 0;
// Number of yield calls.
uint32_t yieldCalls = 0;
// Max busy time for single yield call.
uint32_t yieldMaxUsec = 0;
// Control access to the two versions of SdFat.
bool useEx = false;
//-----------------------------------------------------------------------------
bool sdBusy() {
return useEx ? sdEx.card()->isBusy() : sd.card()->isBusy();
}
//-----------------------------------------------------------------------------
void errorHalt(const char* msg) {
if (useEx) {
sdEx.errorHalt(msg);
} else {
sd.errorHalt(msg);
}
}
//------------------------------------------------------------------------------
uint32_t kHzSdClk() {
return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk();
}
//------------------------------------------------------------------------------
// Replace "weak" system yield() function.
void yield() {
// Only count cardBusy time.
if (!sdBusy()) {
return;
}
uint32_t m = micros();
yieldCalls++;
while (sdBusy()) {
// Do something here.
}
m = micros() - m;
if (m > yieldMaxUsec) {
yieldMaxUsec = m;
}
yieldMicros += m;
}
//-----------------------------------------------------------------------------
void runTest() {
// Zero Stats
totalMicros = 0;
yieldMicros = 0;
yieldCalls = 0;
yieldMaxUsec = 0;
if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) {
errorHalt("open failed");
}
Serial.println("\nsize,write,read");
Serial.println("bytes,KB/sec,KB/sec");
for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) {
file.truncate(0);
uint32_t nRdWr = FILE_SIZE/nb;
Serial.print(nb);
Serial.print(',');
uint32_t t = micros();
for (uint32_t n = 0; n < nRdWr; n++) {
// Set start and end of buffer.
buf32[0] = n;
buf32[nb/4 - 1] = n;
if (nb != file.write(buf, nb)) {
errorHalt("write failed");
}
}
t = micros() - t;
totalMicros += t;
Serial.print(1000.0*FILE_SIZE/t);
Serial.print(',');
file.rewind();
t = micros();
for (uint32_t n = 0; n < nRdWr; n++) {
if ((int)nb != file.read(buf, nb)) {
errorHalt("read failed");
}
// crude check of data.
if (buf32[0] != n || buf32[nb/4 - 1] != n) {
errorHalt("data check");
}
}
t = micros() - t;
totalMicros += t;
Serial.println(1000.0*FILE_SIZE/t);
}
file.close();
Serial.print("\ntotalMicros ");
Serial.println(totalMicros);
Serial.print("yieldMicros ");
Serial.println(yieldMicros);
Serial.print("yieldCalls ");
Serial.println(yieldCalls);
Serial.print("yieldMaxUsec ");
Serial.println(yieldMaxUsec);
Serial.print("kHzSdClk ");
Serial.println(kHzSdClk());
Serial.println("Done");
}
//-----------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
while (!Serial) {
}
Serial.println("SdFatSdioEX uses extended multi-block transfers without DMA.");
Serial.println("SdFatSdio uses a traditional DMA SDIO implementation.");
Serial.println("Note the difference is speed and busy yield time.\n");
}
//-----------------------------------------------------------------------------
void loop() {
do {
delay(10);
} while (Serial.available() && Serial.read());
Serial.println("Type '1' for SdFatSdioEX or '2' for SdFatSdio");
while (!Serial.available()) {
}
char c = Serial.read();
if (c != '1' && c != '2') {
Serial.println("Invalid input");
return;
}
if (c =='1') {
useEx = true;
if (!sdEx.begin()) {
sd.initErrorHalt("SdFatSdioEX begin() failed");
}
// make sdEx the current volume.
sdEx.chvol();
} else {
useEx = false;
if (!sd.begin()) {
sd.initErrorHalt("SdFatSdio begin() failed");
}
// make sd the current volume.
sd.chvol();
}
runTest();
}

View File

@ -1,222 +0,0 @@
/*
* This program is a simple binary write/read benchmark.
*/
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
#include "FreeStack.h"
// Set USE_SDIO to zero for SPI card access.
#define USE_SDIO 0
// SD chip select pin
const uint8_t chipSelect = SS;
// Size of read/write.
const size_t BUF_SIZE = 512;
// File size in MB where MB = 1,000,000 bytes.
const uint32_t FILE_SIZE_MB = 5;
// Write pass count.
const uint8_t WRITE_COUNT = 2;
// Read pass count.
const uint8_t READ_COUNT = 2;
//==============================================================================
// End of configuration constants.
//------------------------------------------------------------------------------
// File size in bytes.
const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB;
uint8_t buf[BUF_SIZE];
// file system
#if USE_SDIO
// Traditional DMA version.
// SdFatSdio sd;
// Faster version.
SdFatSdioEX sd;
#else // USE_SDIO
SdFat sd;
#endif // USE_SDIO
// Set ENABLE_EXTENDED_TRANSFER_CLASS to use extended SD I/O.
// Requires dedicated use of the SPI bus.
// SdFatEX sd;
// Set ENABLE_SOFTWARE_SPI_CLASS to use software SPI.
// Args are misoPin, mosiPin, sckPin.
// SdFatSoftSpi<6, 7, 5> sd;
// test file
SdFile file;
// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// Store error strings in flash to save RAM.
#define error(s) sd.errorHalt(F(s))
//------------------------------------------------------------------------------
void cidDmp() {
cid_t cid;
if (!sd.card()->readCID(&cid)) {
error("readCID failed");
}
cout << F("\nManufacturer ID: ");
cout << hex << int(cid.mid) << dec << endl;
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
cout << F("Product: ");
for (uint8_t i = 0; i < 5; i++) {
cout << cid.pnm[i];
}
cout << F("\nVersion: ");
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
cout << F("Serial number: ") << hex << cid.psn << dec << endl;
cout << F("Manufacturing date: ");
cout << int(cid.mdt_month) << '/';
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
cout << endl;
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
delay(1000);
cout << F("\nUse a freshly formatted SD for best performance.\n");
// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;
}
//------------------------------------------------------------------------------
void loop() {
float s;
uint32_t t;
uint32_t maxLatency;
uint32_t minLatency;
uint32_t totalLatency;
// Discard any input.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);
// F( stores strings in flash to save RAM
cout << F("Type any character to start\n");
while (!Serial.available()) {
yield();
}
cout << F("chipSelect: ") << int(chipSelect) << endl;
cout << F("FreeStack: ") << FreeStack() << endl;
#if USE_SDIO
if (!sd.begin()) {
sd.initErrorHalt();
}
#else // USE_SDIO
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
sd.initErrorHalt();
}
#endif // USE_SDIO
cout << F("Type is FAT") << int(sd.vol()->fatType()) << endl;
cout << F("Card size: ") << sd.card()->cardSize()*512E-9;
cout << F(" GB (GB = 1E9 bytes)") << endl;
cidDmp();
// open or create file - truncate existing file.
if (!file.open("bench.dat", O_RDWR | O_CREAT | O_TRUNC)) {
error("open failed");
}
// fill buf with known data
for (size_t i = 0; i < (BUF_SIZE-2); i++) {
buf[i] = 'A' + (i % 26);
}
buf[BUF_SIZE-2] = '\r';
buf[BUF_SIZE-1] = '\n';
cout << F("File size ") << FILE_SIZE_MB << F(" MB\n");
cout << F("Buffer size ") << BUF_SIZE << F(" bytes\n");
cout << F("Starting write test, please wait.") << endl << endl;
// do write test
uint32_t n = FILE_SIZE/sizeof(buf);
cout <<F("write speed and latency") << endl;
cout << F("speed,max,min,avg") << endl;
cout << F("KB/Sec,usec,usec,usec") << endl;
for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) {
file.truncate(0);
maxLatency = 0;
minLatency = 9999999;
totalLatency = 0;
t = millis();
for (uint32_t i = 0; i < n; i++) {
uint32_t m = micros();
if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
sd.errorPrint("write failed");
file.close();
return;
}
m = micros() - m;
if (maxLatency < m) {
maxLatency = m;
}
if (minLatency > m) {
minLatency = m;
}
totalLatency += m;
}
file.sync();
t = millis() - t;
s = file.fileSize();
cout << s/t <<',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency/n << endl;
}
cout << endl << F("Starting read test, please wait.") << endl;
cout << endl <<F("read speed and latency") << endl;
cout << F("speed,max,min,avg") << endl;
cout << F("KB/Sec,usec,usec,usec") << endl;
// do read test
for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
file.rewind();
maxLatency = 0;
minLatency = 9999999;
totalLatency = 0;
t = millis();
for (uint32_t i = 0; i < n; i++) {
buf[BUF_SIZE-1] = 0;
uint32_t m = micros();
int32_t nr = file.read(buf, sizeof(buf));
if (nr != sizeof(buf)) {
sd.errorPrint("read failed");
file.close();
return;
}
m = micros() - m;
if (maxLatency < m) {
maxLatency = m;
}
if (minLatency > m) {
minLatency = m;
}
totalLatency += m;
if (buf[BUF_SIZE-1] != '\n') {
error("data check");
}
}
s = file.fileSize();
t = millis() - t;
cout << s/t <<',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency/n << endl;
}
cout << endl << F("Done") << endl;
file.close();
}

View File

@ -1,106 +0,0 @@
/*
* This program demonstrates use of SdFile::rename()
* and SdFat::rename().
*/
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
// SD chip select pin
const uint8_t chipSelect = SS;
// file system
SdFat sd;
// Serial print stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt(F(s))
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
cout << F("Insert an empty SD. Type any character to start.") << endl;
while (!Serial.available()) {
yield();
}
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
sd.initErrorHalt();
}
// Remove file/dirs from previous run.
if (sd.exists("dir2/DIR3/NAME3.txt")) {
cout << F("Removing /dir2/DIR3/NAME3.txt") << endl;
if (!sd.remove("dir2/DIR3/NAME3.txt") ||
!sd.rmdir("dir2/DIR3/") ||
!sd.rmdir("dir2/")) {
error("remove/rmdir failed");
}
}
// create a file and write one line to the file
SdFile file("Name1.txt", O_WRONLY | O_CREAT);
if (!file.isOpen()) {
error("Name1.txt");
}
file.println("A test line for Name1.txt");
// rename the file name2.txt and add a line.
if (!file.rename("name2.txt")) {
error("name2.txt");
}
file.println("A test line for name2.txt");
// list files
cout << F("------") << endl;
sd.ls(LS_R);
// make a new directory - "Dir1"
if (!sd.mkdir("Dir1")) {
error("Dir1");
}
// move file into Dir1, rename it NAME3.txt and add a line
if (!file.rename("Dir1/NAME3.txt")) {
error("NAME3.txt");
}
file.println("A line for Dir1/NAME3.txt");
// list files
cout << F("------") << endl;
sd.ls(LS_R);
// make directory "dir2"
if (!sd.mkdir("dir2")) {
error("dir2");
}
// close file before rename(oldPath, newPath)
file.close();
// move Dir1 into dir2 and rename it DIR3
if (!sd.rename("Dir1", "dir2/DIR3")) {
error("dir2/DIR3");
}
// open file for append in new location and add a line
if (!file.open("dir2/DIR3/NAME3.txt", O_WRONLY | O_APPEND)) {
error("dir2/DIR3/NAME3.txt");
}
file.println("A line for dir2/DIR3/NAME3.txt");
file.close();
// list files
cout << F("------") << endl;
sd.ls(LS_R);
cout << F("Done") << endl;
}
void loop() {}

View File

@ -1,89 +0,0 @@
/**
* Copyright (c) 2011-2020 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "PrintBasic.h"
#include <math.h>
size_t PrintBasic::print(long n, uint8_t base) {
if (n < 0 && base == 10) {
return print('-') + printNum(-n, base);
}
return printNum(n, base);
}
size_t PrintBasic::printNum(unsigned long n, uint8_t base) {
const uint8_t DIM = 8*sizeof(long);
char buf[DIM];
char *str = &buf[DIM];
if (base < 2) return 0;
do {
char c = n%base;
n /= base;
*--str = c + (c < 10 ? '0' : 'A' - 10);
} while (n);
return write(str, &buf[DIM] - str);
}
size_t PrintBasic::printDouble(double n, uint8_t prec) {
// Max printable 32-bit floating point number. AVR uses 32-bit double.
const double maxfp = static_cast<double>(0XFFFFFF00UL);
size_t rtn = 0;
if (isnan(n)) {
return write("NaN");
}
if (n < 0) {
n = -n;
rtn += print('-');
}
if (isinf(n)) {
return rtn + write("Inf");
}
if (n > maxfp) {
return rtn + write("Ovf");
}
double round = 0.5;
for (uint8_t i = 0; i < prec; ++i) {
round *= 0.1;
}
n += round;
uint32_t whole = (uint32_t)n;
rtn += print(whole);
if (prec) {
rtn += print('.');
double fraction = n - static_cast<double>(whole);
for (uint8_t i = 0; i < prec; i++) {
fraction *= 10.0;
uint8_t digit = fraction;
rtn += print(digit);
fraction -= digit;
}
}
return rtn;
}

View File

@ -1,490 +0,0 @@
/**
* Copyright (c) 2011-2021 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef SdCardInfo_h
#define SdCardInfo_h
#include <stdint.h>
#include "../common/SysCall.h"
// Based on the document:
//
// SD Specifications
// Part 1
// Physical Layer
// Simplified Specification
// Version 5.00
// Aug 10, 2016
//
// https://www.sdcard.org/downloads/pls/
//------------------------------------------------------------------------------
// SD card errors
// See the SD Specification for command info.
#define SD_ERROR_CODE_LIST\
SD_CARD_ERROR(NONE, "No error")\
SD_CARD_ERROR(CMD0, "Card reset failed")\
SD_CARD_ERROR(CMD2, "SDIO read CID")\
SD_CARD_ERROR(CMD3, "SDIO publish RCA")\
SD_CARD_ERROR(CMD6, "Switch card function")\
SD_CARD_ERROR(CMD7, "SDIO card select")\
SD_CARD_ERROR(CMD8, "Send and check interface settings")\
SD_CARD_ERROR(CMD9, "Read CSD data")\
SD_CARD_ERROR(CMD10, "Read CID data")\
SD_CARD_ERROR(CMD12, "Stop multiple block read")\
SD_CARD_ERROR(CMD13, "Read card status")\
SD_CARD_ERROR(CMD17, "Read single block")\
SD_CARD_ERROR(CMD18, "Read multiple blocks")\
SD_CARD_ERROR(CMD24, "Write single block")\
SD_CARD_ERROR(CMD25, "Write multiple blocks")\
SD_CARD_ERROR(CMD32, "Set first erase block")\
SD_CARD_ERROR(CMD33, "Set last erase block")\
SD_CARD_ERROR(CMD38, "Erase selected blocks")\
SD_CARD_ERROR(CMD58, "Read OCR register")\
SD_CARD_ERROR(CMD59, "Set CRC mode")\
SD_CARD_ERROR(ACMD6, "Set SDIO bus width")\
SD_CARD_ERROR(ACMD13, "Read extended status")\
SD_CARD_ERROR(ACMD23, "Set pre-erased count")\
SD_CARD_ERROR(ACMD41, "Activate card initialization")\
SD_CARD_ERROR(READ_TOKEN, "Bad read data token")\
SD_CARD_ERROR(READ_CRC, "Read CRC error")\
SD_CARD_ERROR(READ_FIFO, "SDIO fifo read timeout")\
SD_CARD_ERROR(READ_REG, "Read CID or CSD failed.")\
SD_CARD_ERROR(READ_START, "Bad readStart argument")\
SD_CARD_ERROR(READ_TIMEOUT, "Read data timeout")\
SD_CARD_ERROR(STOP_TRAN, "Multiple block stop failed")\
SD_CARD_ERROR(TRANSFER_COMPLETE, "SDIO transfer complete")\
SD_CARD_ERROR(WRITE_DATA, "Write data not accepted")\
SD_CARD_ERROR(WRITE_FIFO, "SDIO fifo write timeout")\
SD_CARD_ERROR(WRITE_START, "Bad writeStart argument")\
SD_CARD_ERROR(WRITE_PROGRAMMING, "Flash programming")\
SD_CARD_ERROR(WRITE_TIMEOUT, "Write timeout")\
SD_CARD_ERROR(DMA, "DMA transfer failed")\
SD_CARD_ERROR(ERASE, "Card did not accept erase commands")\
SD_CARD_ERROR(ERASE_SINGLE_SECTOR, "Card does not support erase")\
SD_CARD_ERROR(ERASE_TIMEOUT, "Erase command timeout")\
SD_CARD_ERROR(INIT_NOT_CALLED, "Card has not been initialized")\
SD_CARD_ERROR(INVALID_CARD_CONFIG, "Invalid card config")\
SD_CARD_ERROR(FUNCTION_NOT_SUPPORTED, "Unsupported SDIO command")
enum {
#define SD_CARD_ERROR(e, m) SD_CARD_ERROR_##e,
SD_ERROR_CODE_LIST
#undef SD_CARD_ERROR
SD_CARD_ERROR_UNKNOWN
};
void printSdErrorSymbol(print_t* pr, uint8_t code);
void printSdErrorText(print_t* pr, uint8_t code);
//------------------------------------------------------------------------------
// card types
/** Standard capacity V1 SD card */
const uint8_t SD_CARD_TYPE_SD1 = 1;
/** Standard capacity V2 SD card */
const uint8_t SD_CARD_TYPE_SD2 = 2;
/** High Capacity SD card */
const uint8_t SD_CARD_TYPE_SDHC = 3;
//------------------------------------------------------------------------------
// SD operation timeouts
/** CMD0 retry count */
const uint8_t SD_CMD0_RETRY = 10;
/** command timeout ms */
const uint16_t SD_CMD_TIMEOUT = 300;
/** erase timeout ms */
const uint16_t SD_ERASE_TIMEOUT = 10000;
/** init timeout ms */
const uint16_t SD_INIT_TIMEOUT = 2000;
/** read timeout ms */
const uint16_t SD_READ_TIMEOUT = 300;
/** write time out ms */
const uint16_t SD_WRITE_TIMEOUT = 600;
//------------------------------------------------------------------------------
// SD card commands
/** GO_IDLE_STATE - init card in spi mode if CS low */
const uint8_t CMD0 = 0X00;
/** ALL_SEND_CID - Asks any card to send the CID. */
const uint8_t CMD2 = 0X02;
/** SEND_RELATIVE_ADDR - Ask the card to publish a new RCA. */
const uint8_t CMD3 = 0X03;
/** SWITCH_FUNC - Switch Function Command */
const uint8_t CMD6 = 0X06;
/** SELECT/DESELECT_CARD - toggles between the stand-by and transfer states. */
const uint8_t CMD7 = 0X07;
/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
const uint8_t CMD8 = 0X08;
/** SEND_CSD - read the Card Specific Data (CSD register) */
const uint8_t CMD9 = 0X09;
/** SEND_CID - read the card identification information (CID register) */
const uint8_t CMD10 = 0X0A;
/** VOLTAGE_SWITCH -Switch to 1.8V bus signaling level. */
const uint8_t CMD11 = 0X0B;
/** STOP_TRANSMISSION - end multiple sector read sequence */
const uint8_t CMD12 = 0X0C;
/** SEND_STATUS - read the card status register */
const uint8_t CMD13 = 0X0D;
/** READ_SINGLE_SECTOR - read a single data sector from the card */
const uint8_t CMD17 = 0X11;
/** READ_MULTIPLE_SECTOR - read multiple data sectors from the card */
const uint8_t CMD18 = 0X12;
/** WRITE_SECTOR - write a single data sector to the card */
const uint8_t CMD24 = 0X18;
/** WRITE_MULTIPLE_SECTOR - write sectors of data until a STOP_TRANSMISSION */
const uint8_t CMD25 = 0X19;
/** ERASE_WR_BLK_START - sets the address of the first sector to be erased */
const uint8_t CMD32 = 0X20;
/** ERASE_WR_BLK_END - sets the address of the last sector of the continuous
range to be erased*/
const uint8_t CMD33 = 0X21;
/** ERASE - erase all previously selected sectors */
const uint8_t CMD38 = 0X26;
/** APP_CMD - escape for application specific command */
const uint8_t CMD55 = 0X37;
/** READ_OCR - read the OCR register of a card */
const uint8_t CMD58 = 0X3A;
/** CRC_ON_OFF - enable or disable CRC checking */
const uint8_t CMD59 = 0X3B;
/** SET_BUS_WIDTH - Defines the data bus width for data transfer. */
const uint8_t ACMD6 = 0X06;
/** SD_STATUS - Send the SD Status. */
const uint8_t ACMD13 = 0X0D;
/** SET_WR_BLK_ERASE_COUNT - Set the number of write sectors to be
pre-erased before writing */
const uint8_t ACMD23 = 0X17;
/** SD_SEND_OP_COMD - Sends host capacity support information and
activates the card's initialization process */
const uint8_t ACMD41 = 0X29;
//==============================================================================
// CARD_STATUS
/** The command's argument was out of the allowed range for this card. */
const uint32_t CARD_STATUS_OUT_OF_RANGE = 1UL << 31;
/** A misaligned address which did not match the sector length. */
const uint32_t CARD_STATUS_ADDRESS_ERROR = 1UL << 30;
/** The transferred sector length is not allowed for this card. */
const uint32_t CARD_STATUS_SECTOR_LEN_ERROR = 1UL << 29;
/** An error in the sequence of erase commands occurred. */
const uint32_t CARD_STATUS_ERASE_SEQ_ERROR = 1UL <<28;
/** An invalid selection of write-sectors for erase occurred. */
const uint32_t CARD_STATUS_ERASE_PARAM = 1UL << 27;
/** Set when the host attempts to write to a protected sector. */
const uint32_t CARD_STATUS_WP_VIOLATION = 1UL << 26;
/** When set, signals that the card is locked by the host. */
const uint32_t CARD_STATUS_CARD_IS_LOCKED = 1UL << 25;
/** Set when a sequence or password error has been detected. */
const uint32_t CARD_STATUS_LOCK_UNLOCK_FAILED = 1UL << 24;
/** The CRC check of the previous command failed. */
const uint32_t CARD_STATUS_COM_CRC_ERROR = 1UL << 23;
/** Command not legal for the card state. */
const uint32_t CARD_STATUS_ILLEGAL_COMMAND = 1UL << 22;
/** Card internal ECC was applied but failed to correct the data. */
const uint32_t CARD_STATUS_CARD_ECC_FAILED = 1UL << 21;
/** Internal card controller error */
const uint32_t CARD_STATUS_CC_ERROR = 1UL << 20;
/** A general or an unknown error occurred during the operation. */
const uint32_t CARD_STATUS_ERROR = 1UL << 19;
// bits 19, 18, and 17 reserved.
/** Permanent WP set or attempt to change read only values of CSD. */
const uint32_t CARD_STATUS_CSD_OVERWRITE = 1UL <<16;
/** partial address space was erased due to write protect. */
const uint32_t CARD_STATUS_WP_ERASE_SKIP = 1UL << 15;
/** The command has been executed without using the internal ECC. */
const uint32_t CARD_STATUS_CARD_ECC_DISABLED = 1UL << 14;
/** out of erase sequence command was received. */
const uint32_t CARD_STATUS_ERASE_RESET = 1UL << 13;
/** The state of the card when receiving the command.
* 0 = idle
* 1 = ready
* 2 = ident
* 3 = stby
* 4 = tran
* 5 = data
* 6 = rcv
* 7 = prg
* 8 = dis
* 9-14 = reserved
* 15 = reserved for I/O mode
*/
const uint32_t CARD_STATUS_CURRENT_STATE = 0XF << 9;
/** Shift for current state. */
const uint32_t CARD_STATUS_CURRENT_STATE_SHIFT = 9;
/** Corresponds to buffer empty signaling on the bus. */
const uint32_t CARD_STATUS_READY_FOR_DATA = 1UL << 8;
// bit 7 reserved.
/** Extension Functions may set this bit to get host to deal with events. */
const uint32_t CARD_STATUS_FX_EVENT = 1UL << 6;
/** The card will expect ACMD, or the command has been interpreted as ACMD */
const uint32_t CARD_STATUS_APP_CMD = 1UL << 5;
// bit 4 reserved.
/** Error in the sequence of the authentication process. */
const uint32_t CARD_STATUS_AKE_SEQ_ERROR = 1UL << 3;
// bits 2,1, and 0 reserved for manufacturer test mode.
//==============================================================================
/** status for card in the ready state */
const uint8_t R1_READY_STATE = 0X00;
/** status for card in the idle state */
const uint8_t R1_IDLE_STATE = 0X01;
/** status bit for illegal command */
const uint8_t R1_ILLEGAL_COMMAND = 0X04;
/** start data token for read or write single sector*/
const uint8_t DATA_START_SECTOR = 0XFE;
/** stop token for write multiple sectors*/
const uint8_t STOP_TRAN_TOKEN = 0XFD;
/** start data token for write multiple sectors*/
const uint8_t WRITE_MULTIPLE_TOKEN = 0XFC;
/** mask for data response tokens after a write sector operation */
const uint8_t DATA_RES_MASK = 0X1F;
/** write data accepted token */
const uint8_t DATA_RES_ACCEPTED = 0X05;
//==============================================================================
/**
* \class CID
* \brief Card IDentification (CID) register.
*/
typedef struct CID {
// byte 0
/** Manufacturer ID */
unsigned char mid;
// byte 1-2
/** OEM/Application ID */
char oid[2];
// byte 3-7
/** Product name */
char pnm[5];
// byte 8
/** Product revision least significant digit */
unsigned char prv_m : 4;
/** Product revision most significant digit */
unsigned char prv_n : 4;
// byte 9-12
/** Product serial number */
uint32_t psn;
// byte 13
/** Manufacturing date year high digit */
unsigned char mdt_year_high : 4;
/** not used */
unsigned char reserved : 4;
// byte 14
/** Manufacturing date month */
unsigned char mdt_month : 4;
/** Manufacturing date year low digit */
unsigned char mdt_year_low : 4;
// byte 15
/** not used always 1 */
unsigned char always1 : 1;
/** CRC7 checksum */
unsigned char crc : 7;
} __attribute__((packed)) cid_t;
//==============================================================================
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/**
* \class CSDV1
* \brief CSD register for version 1.00 cards .
*/
typedef struct CSDV1 {
// byte 0
unsigned char reserved1 : 6;
unsigned char csd_ver : 2;
// byte 1
unsigned char taac;
// byte 2
unsigned char nsac;
// byte 3
unsigned char tran_speed;
// byte 4
unsigned char ccc_high;
// byte 5
unsigned char read_bl_len : 4;
unsigned char ccc_low : 4;
// byte 6
unsigned char c_size_high : 2;
unsigned char reserved2 : 2;
unsigned char dsr_imp : 1;
unsigned char read_blk_misalign : 1;
unsigned char write_blk_misalign : 1;
unsigned char read_bl_partial : 1;
// byte 7
unsigned char c_size_mid;
// byte 8
unsigned char vdd_r_curr_max : 3;
unsigned char vdd_r_curr_min : 3;
unsigned char c_size_low : 2;
// byte 9
unsigned char c_size_mult_high : 2;
unsigned char vdd_w_cur_max : 3;
unsigned char vdd_w_curr_min : 3;
// byte 10
unsigned char sector_size_high : 6;
unsigned char erase_blk_en : 1;
unsigned char c_size_mult_low : 1;
// byte 11
unsigned char wp_grp_size : 7;
unsigned char sector_size_low : 1;
// byte 12
unsigned char write_bl_len_high : 2;
unsigned char r2w_factor : 3;
unsigned char reserved3 : 2;
unsigned char wp_grp_enable : 1;
// byte 13
unsigned char reserved4 : 5;
unsigned char write_partial : 1;
unsigned char write_bl_len_low : 2;
// byte 14
unsigned char reserved5: 2;
unsigned char file_format : 2;
unsigned char tmp_write_protect : 1;
unsigned char perm_write_protect : 1;
unsigned char copy : 1;
/** Indicates the file format on the card */
unsigned char file_format_grp : 1;
// byte 15
unsigned char always1 : 1;
unsigned char crc : 7;
} __attribute__((packed)) csd1_t;
//==============================================================================
/**
* \class CSDV2
* \brief CSD register for version 2.00 cards.
*/
typedef struct CSDV2 {
// byte 0
unsigned char reserved1 : 6;
unsigned char csd_ver : 2;
// byte 1
/** fixed to 0X0E */
unsigned char taac;
// byte 2
/** fixed to 0 */
unsigned char nsac;
// byte 3
unsigned char tran_speed;
// byte 4
unsigned char ccc_high;
// byte 5
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
unsigned char read_bl_len : 4;
unsigned char ccc_low : 4;
// byte 6
/** not used */
unsigned char reserved2 : 4;
unsigned char dsr_imp : 1;
/** fixed to 0 */
unsigned char read_blk_misalign : 1;
/** fixed to 0 */
unsigned char write_blk_misalign : 1;
/** fixed to 0 - no partial read */
unsigned char read_bl_partial : 1;
// byte 7
/** high part of card size */
unsigned char c_size_high : 6;
/** not used */
unsigned char reserved3 : 2;
// byte 8
/** middle part of card size */
unsigned char c_size_mid;
// byte 9
/** low part of card size */
unsigned char c_size_low;
// byte 10
/** sector size is fixed at 64 KB */
unsigned char sector_size_high : 6;
/** fixed to 1 - erase single is supported */
unsigned char erase_blk_en : 1;
/** not used */
unsigned char reserved4 : 1;
// byte 11
unsigned char wp_grp_size : 7;
/** sector size is fixed at 64 KB */
unsigned char sector_size_low : 1;
// byte 12
/** write_bl_len fixed for 512 byte sectors */
unsigned char write_bl_len_high : 2;
/** fixed value of 2 */
unsigned char r2w_factor : 3;
/** not used */
unsigned char reserved5 : 2;
/** fixed value of 0 - no write protect groups */
unsigned char wp_grp_enable : 1;
// byte 13
unsigned char reserved6 : 5;
/** always zero - no partial sector read*/
unsigned char write_partial : 1;
/** write_bl_len fixed for 512 byte sectors */
unsigned char write_bl_len_low : 2;
// byte 14
unsigned char reserved7: 2;
/** Do not use always 0 */
unsigned char file_format : 2;
unsigned char tmp_write_protect : 1;
unsigned char perm_write_protect : 1;
unsigned char copy : 1;
/** Do not use always 0 */
unsigned char file_format_grp : 1;
// byte 15
/** not used always 1 */
unsigned char always1 : 1;
/** checksum */
unsigned char crc : 7;
} __attribute__((packed)) csd2_t;
//==============================================================================
/**
* \class csd_t
* \brief Union of old and new style CSD register.
*/
union csd_t {
csd1_t v1;
csd2_t v2;
};
//-----------------------------------------------------------------------------
inline uint32_t sdCardCapacity(csd_t* csd) {
if (csd->v1.csd_ver == 0) {
uint8_t read_bl_len = csd->v1.read_bl_len;
uint16_t c_size = (csd->v1.c_size_high << 10)
| (csd->v1.c_size_mid << 2) | csd->v1.c_size_low;
uint8_t c_size_mult = (csd->v1.c_size_mult_high << 1)
| csd->v1.c_size_mult_low;
return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
} else if (csd->v2.csd_ver == 1) {
return (((uint32_t)csd->v2.c_size_high << 16) +
((uint16_t)csd->v2.c_size_mid << 8) + csd->v2.c_size_low + 1) << 10;
} else {
return 0;
}
}
//-----------------------------------------------------------------------------
// fields are big endian
typedef struct SdStatus {
uint8_t busWidthSecureMode;
uint8_t reserved1;
uint8_t sdCardType[2];
uint8_t sizeOfProtectedArea[4];
uint8_t speedClass;
uint8_t performanceMove;
uint8_t auSize;
uint8_t eraseSize[2];
uint8_t eraseTimeoutOffset;
uint8_t uhsSpeedAuSize;
uint8_t videoSpeed;
uint8_t vscAuSize[2];
uint8_t susAddr[3];
uint8_t reserved2[3];
uint8_t reservedManufacturer[40];
} SdStatus_t;
#endif // DOXYGEN_SHOULD_SKIP_THIS
#endif // SdCardInfo_h

View File

@ -1,277 +0,0 @@
#ifndef SdioTeensy_h
#define SdioTeensy_h
// From Paul's SD.h driver.
#if defined(__IMXRT1062__)
#define MAKE_REG_MASK(m,s) (((uint32_t)(((uint32_t)(m) << s))))
#define MAKE_REG_GET(x,m,s) (((uint32_t)(((uint32_t)(x)>>s) & m)))
#define MAKE_REG_SET(x,m,s) (((uint32_t)(((uint32_t)(x) & m) << s)))
#define SDHC_BLKATTR_BLKSIZE_MASK MAKE_REG_MASK(0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size Mask
#define SDHC_BLKATTR_BLKSIZE(n) MAKE_REG_SET(n,0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size
#define SDHC_BLKATTR_BLKCNT_MASK MAKE_REG_MASK(0x1FFF,16) //((uint32_t)0x1FFF<<16)
#define SDHC_BLKATTR_BLKCNT(n) MAKE_REG_SET(n,0x1FFF,16) //(uint32_t)(((n) & 0x1FFF)<<16) // Blocks Count For Current Transfer
#define SDHC_XFERTYP_CMDINX(n) MAKE_REG_SET(n,0x3F,24) //(uint32_t)(((n) & 0x3F)<<24)// Command Index
#define SDHC_XFERTYP_CMDTYP(n) MAKE_REG_SET(n,0x3,22) //(uint32_t)(((n) & 0x3)<<22) // Command Type
#define SDHC_XFERTYP_DPSEL MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data Present Select
#define SDHC_XFERTYP_CICEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Command Index Check Enable
#define SDHC_XFERTYP_CCCEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command CRC Check Enable
#define SDHC_XFERTYP_RSPTYP(n) MAKE_REG_SET(n,0x3,16) //(uint32_t)(((n) & 0x3)<<16) // Response Type Select
#define SDHC_XFERTYP_MSBSEL MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Multi/Single Block Select
#define SDHC_XFERTYP_DTDSEL MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Data Transfer Direction Select
#define SDHC_XFERTYP_AC12EN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 Enable
#define SDHC_XFERTYP_BCEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Block Count Enable
#define SDHC_XFERTYP_DMAEN MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000001) // DMA Enable
#define SDHC_PRSSTAT_DLSL_MASK MAKE_REG_MASK(0xFF,24) //((uint32_t)0xFF000000) // DAT Line Signal Level
#define SDHC_PRSSTAT_CLSL MAKE_REG_MASK(0x1,23) //((uint32_t)0x00800000) // CMD Line Signal Level
#define SDHC_PRSSTAT_WPSPL MAKE_REG_MASK(0x1,19) //
#define SDHC_PRSSTAT_CDPL MAKE_REG_MASK(0x1,18) //
#define SDHC_PRSSTAT_CINS MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Card Inserted
#define SDHC_PRSSTAT_TSCD MAKE_REG_MASK(0x1,15)
#define SDHC_PRSSTAT_RTR MAKE_REG_MASK(0x1,12)
#define SDHC_PRSSTAT_BREN MAKE_REG_MASK(0x1,11) //((uint32_t)0x00000800) // Buffer Read Enable
#define SDHC_PRSSTAT_BWEN MAKE_REG_MASK(0x1,10) //((uint32_t)0x00000400) // Buffer Write Enable
#define SDHC_PRSSTAT_RTA MAKE_REG_MASK(0x1,9) //((uint32_t)0x00000200) // Read Transfer Active
#define SDHC_PRSSTAT_WTA MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Write Transfer Active
#define SDHC_PRSSTAT_SDOFF MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // SD Clock Gated Off Internally
#define SDHC_PRSSTAT_PEROFF MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // SDHC clock Gated Off Internally
#define SDHC_PRSSTAT_HCKOFF MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // System Clock Gated Off Internally
#define SDHC_PRSSTAT_IPGOFF MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Bus Clock Gated Off Internally
#define SDHC_PRSSTAT_SDSTB MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // SD Clock Stable
#define SDHC_PRSSTAT_DLA MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Data Line Active
#define SDHC_PRSSTAT_CDIHB MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Command Inhibit (DAT)
#define SDHC_PRSSTAT_CIHB MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Inhibit (CMD)
#define SDHC_PROTCT_NONEXACT_BLKRD MAKE_REG_MASK(0x1,30) //
#define SDHC_PROTCT_BURST_LENEN(n) MAKE_REG_SET(n,0x7,12) //
#define SDHC_PROCTL_WECRM MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Wakeup Event Enable On SD Card Removal
#define SDHC_PROCTL_WECINS MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Wakeup Event Enable On SD Card Insertion
#define SDHC_PROCTL_WECINT MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Wakeup Event Enable On Card Interrupt
#define SDHC_PROCTL_RD_DONE_NOBLK MAKE_REG_MASK(0x1,20) //
#define SDHC_PROCTL_IABG MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Interrupt At Block Gap
#define SDHC_PROCTL_RWCTL MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Read Wait Control
#define SDHC_PROCTL_CREQ MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Continue Request
#define SDHC_PROCTL_SABGREQ MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Stop At Block Gap Request
#define SDHC_PROCTL_DMAS(n) MAKE_REG_SET(n,0x3,8) //(uint32_t)(((n) & 0x3)<<8) // DMA Select
#define SDHC_PROCTL_CDSS MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Detect Signal Selection
#define SDHC_PROCTL_CDTL MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Detect Test Level
#define SDHC_PROCTL_EMODE(n) MAKE_REG_SET(n,0x3,4) //(uint32_t)(((n) & 0x3)<<4) // Endian Mode
#define SDHC_PROCTL_EMODE_MASK MAKE_REG_MASK(0x3,4) //(uint32_t)((0x3)<<4) // Endian Mode
#define SDHC_PROCTL_D3CD MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DAT3 As Card Detection Pin
#define SDHC_PROCTL_DTW(n) MAKE_REG_SET(n,0x3,1) //(uint32_t)(((n) & 0x3)<<1) // Data Transfer Width, 0=1bit, 1=4bit, 2=8bit
#define SDHC_PROCTL_DTW_MASK MAKE_REG_MASK(0x3,1) //((uint32_t)0x00000006)
#define SDHC_PROCTL_LCTL MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // LED Control
#define SDHC_SYSCTL_RSTT MAKE_REG_MASK(0x1,28) //
#define SDHC_SYSCTL_INITA MAKE_REG_MASK(0x1,27) //((uint32_t)0x08000000) // Initialization Active
#define SDHC_SYSCTL_RSTD MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Software Reset For DAT Line
#define SDHC_SYSCTL_RSTC MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Software Reset For CMD Line
#define SDHC_SYSCTL_RSTA MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Software Reset For ALL
#define SDHC_SYSCTL_DTOCV(n) MAKE_REG_SET(n,0xF,16) //(uint32_t)(((n) & 0xF)<<16) // Data Timeout Counter Value
#define SDHC_SYSCTL_DTOCV_MASK MAKE_REG_MASK(0xF,16) //((uint32_t)0x000F0000)
#define SDHC_SYSCTL_SDCLKFS(n) MAKE_REG_SET(n,0xFF,8) //(uint32_t)(((n) & 0xFF)<<8) // SDCLK Frequency Select
#define SDHC_SYSCTL_SDCLKFS_MASK MAKE_REG_MASK(0xFF,8) //((uint32_t)0x0000FF00)
#define SDHC_SYSCTL_DVS(n) MAKE_REG_SET(n,0xF,4) //(uint32_t)(((n) & 0xF)<<4) // Divisor
#define SDHC_SYSCTL_DVS_MASK MAKE_REG_MASK(0xF,4) //((uint32_t)0x000000F0)
#define SDHC_SYSCTL_SDCLKEN ((uint32_t)0x00000008) // SD Clock Enable
#define SDHC_SYSCTL_PEREN ((uint32_t)0x00000004) // Peripheral Clock Enable
#define SDHC_SYSCTL_HCKEN ((uint32_t)0x00000002) // System Clock Enable
#define SDHC_SYSCTL_IPGEN ((uint32_t)0x00000001) // IPG Clock Enable
#define SDHC_IRQSTAT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error
#define SDHC_IRQSTAT_TNE MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTAT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error
#define SDHC_IRQSTAT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error
#define SDHC_IRQSTAT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error
#define SDHC_IRQSTAT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error
#define SDHC_IRQSTAT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error
#define SDHC_IRQSTAT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error
#define SDHC_IRQSTAT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error
#define SDHC_IRQSTAT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error
#define SDHC_IRQSTAT_TP MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTAT_RTE MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTAT_CINT MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt
#define SDHC_IRQSTAT_CRM MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal
#define SDHC_IRQSTAT_CINS MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion
#define SDHC_IRQSTAT_BRR MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready
#define SDHC_IRQSTAT_BWR MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready
#define SDHC_IRQSTAT_DINT MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt
#define SDHC_IRQSTAT_BGE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event
#define SDHC_IRQSTAT_TC MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete
#define SDHC_IRQSTAT_CC MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete
#define SDHC_IRQSTATEN_DMAESEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Status Enable
#define SDHC_IRQSTATEN_TNESEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTATEN_AC12ESEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Status Enable
#define SDHC_IRQSTATEN_DEBESEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Status Enable
#define SDHC_IRQSTATEN_DCESEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Status Enable
#define SDHC_IRQSTATEN_DTOESEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Status Enable
#define SDHC_IRQSTATEN_CIESEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Status Enable
#define SDHC_IRQSTATEN_CEBESEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Status Enable
#define SDHC_IRQSTATEN_CCESEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Status Enable
#define SDHC_IRQSTATEN_CTOESEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Status Enable
#define SDHC_IRQSTATEN_TPSEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTATEN_RTESEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTATEN_CINTSEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Status Enable
#define SDHC_IRQSTATEN_CRMSEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Status Enable
#define SDHC_IRQSTATEN_CINSEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Status Enable
#define SDHC_IRQSTATEN_BRRSEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Status Enable
#define SDHC_IRQSTATEN_BWRSEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Status Enable
#define SDHC_IRQSTATEN_DINTSEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Status Enable
#define SDHC_IRQSTATEN_BGESEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Status Enable
#define SDHC_IRQSTATEN_TCSEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Status Enable
#define SDHC_IRQSTATEN_CCSEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Status Enable
#define SDHC_IRQSIGEN_DMAEIEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Interrupt Enable
#define SDHC_IRQSIGEN_TNEIEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSIGEN_AC12EIEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Interrupt Enable
#define SDHC_IRQSIGEN_DEBEIEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_DCEIEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_DTOEIEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_CIEIEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Interrupt Enable
#define SDHC_IRQSIGEN_CEBEIEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_CCEIEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_CTOEIEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_TPIEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSIGEN_RTEIEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSIGEN_CINTIEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_CRMIEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Interrupt Enable
#define SDHC_IRQSIGEN_CINSIEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Interrupt Enable
#define SDHC_IRQSIGEN_BRRIEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Interrupt Enable
#define SDHC_IRQSIGEN_BWRIEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Interrupt Enable
#define SDHC_IRQSIGEN_DINTIEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_BGEIEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Interrupt Enable
#define SDHC_IRQSIGEN_TCIEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Interrupt Enable
#define SDHC_IRQSIGEN_CCIEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Interrupt Enable
#define SDHC_AC12ERR_SMPLCLK_SEL MAKE_REG_MASK(0x1,23) //
#define SDHC_AC12ERR_EXEC_TUNING MAKE_REG_MASK(0x1,22) //
#define SDHC_AC12ERR_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Command Not Issued By Auto CMD12 Error
#define SDHC_AC12ERR_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Auto CMD12 Index Error
#define SDHC_AC12ERR_AC12CE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Auto CMD12 CRC Error
#define SDHC_AC12ERR_AC12EBE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 End Bit Error
#define SDHC_AC12ERR_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Auto CMD12 Timeout Error
#define SDHC_AC12ERR_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Auto CMD12 Not Executed
#define SDHC_HTCAPBLT_VS18 MAKE_REG_MASK(0x1,26) //
#define SDHC_HTCAPBLT_VS30 MAKE_REG_MASK(0x1,25) //
#define SDHC_HTCAPBLT_VS33 MAKE_REG_MASK(0x1,24) //
#define SDHC_HTCAPBLT_SRS MAKE_REG_MASK(0x1,23) //
#define SDHC_HTCAPBLT_DMAS MAKE_REG_MASK(0x1,22) //
#define SDHC_HTCAPBLT_HSS MAKE_REG_MASK(0x1,21) //
#define SDHC_HTCAPBLT_ADMAS MAKE_REG_MASK(0x1,20) //
#define SDHC_HTCAPBLT_MBL_VAL MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x7,16) //
#define SDHC_HTCAPBLT_RETUN_MODE MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x3,14) //
#define SDHC_HTCAPBLT_TUNE_SDR50 MAKE_REG_MASK(0x1,13) //
#define SDHC_HTCAPBLT_TIME_RETUN(n) MAKE_REG_SET(n,0xF,8) //
#define SDHC_WML_WR_BRSTLEN_MASK MAKE_REG_MASK(0x1F,24) //
#define SDHC_WML_RD_BRSTLEN_MASK MAKE_REG_MASK(0x1F,8) //
#define SDHC_WML_WR_WML_MASK MAKE_REG_MASK(0xFF,16) //
#define SDHC_WML_RD_WML_MASK MAKE_REG_MASK(0xFF,0) //
#define SDHC_WML_WR_BRSTLEN(n) MAKE_REG_SET(n,0x1F,24) //(uint32_t)(((n) & 0x7F)<<16) // Write Burst Len
#define SDHC_WML_RD_BRSTLEN(n) MAKE_REG_SET(n,0x1F,8) //(uint32_t)(((n) & 0x7F)<<0) // Read Burst Len
#define SDHC_WML_WR_WML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RD_WML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
#define SDHC_WML_WRWML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RDWML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
// Teensy 4.0 only
#define SDHC_MIX_CTRL_DMAEN MAKE_REG_MASK(0x1,0) //
#define SDHC_MIX_CTRL_BCEN MAKE_REG_MASK(0x1,1) //
#define SDHC_MIX_CTRL_AC12EN MAKE_REG_MASK(0x1,2) //
#define SDHC_MIX_CTRL_DDR_EN MAKE_REG_MASK(0x1,3) //
#define SDHC_MIX_CTRL_DTDSEL MAKE_REG_MASK(0x1,4) //
#define SDHC_MIX_CTRL_MSBSEL MAKE_REG_MASK(0x1,5) //
#define SDHC_MIX_CTRL_NIBBLE_POS MAKE_REG_MASK(0x1,6) //
#define SDHC_MIX_CTRL_AC23EN MAKE_REG_MASK(0x1,7) //
#define SDHC_FEVT_CINT MAKE_REG_MASK(0x1,31) //((uint32_t)0x80000000) // Force Event Card Interrupt
#define SDHC_FEVT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // Force Event DMA Error
#define SDHC_FEVT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Force Event Auto CMD12 Error
#define SDHC_FEVT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Force Event Data End Bit Error
#define SDHC_FEVT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Force Event Data CRC Error
#define SDHC_FEVT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Force Event Data Timeout Error
#define SDHC_FEVT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Force Event Command Index Error
#define SDHC_FEVT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Force Event Command End Bit Error
#define SDHC_FEVT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Force Event Command CRC Error
#define SDHC_FEVT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Force Event Command Timeout Error
#define SDHC_FEVT_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Force Event Command Not Executed By Auto Command 12 Error
#define SDHC_FEVT_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Force Event Auto Command 12 Index Error
#define SDHC_FEVT_AC12EBE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Force Event Auto Command 12 End Bit Error
#define SDHC_FEVT_AC12CE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Force Event Auto Command 12 CRC Error
#define SDHC_FEVT_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Force Event Auto Command 12 Time Out Error
#define SDHC_FEVT_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Force Event Auto Command 12 Not Executed
#define SDHC_ADMAES_ADMADCE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008)
#define SDHC_ADMAES_ADMALME MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004)
#define SDHC_ADMAES_ADMAES_MASK MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000003)
#define SDHC_MMCBOOT_BOOTBLKCNT(n) MAKE_REG_MASK(0xFF,16) //(uint32_t)(((n) & 0xFFF)<<16) // stop at block gap value of automatic mode
#define SDHC_MMCBOOT_AUTOSABGEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // enable auto stop at block gap function
#define SDHC_MMCBOOT_BOOTEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Boot Mode Enable
#define SDHC_MMCBOOT_BOOTMODE MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Boot Mode Select
#define SDHC_MMCBOOT_BOOTACK MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Boot Ack Mode Select
#define SDHC_MMCBOOT_DTOCVACK(n) MAKE_REG_MASK(0xF,0) //(uint32_t)(((n) & 0xF)<<0) // Boot ACK Time Out Counter Value
//#define SDHC_HOSTVER (*(volatile uint32_t*)0x400B10FC) // Host Controller Version
#define CCM_ANALOG_PFD_528_PFD0_FRAC_MASK 0x3f
#define CCM_ANALOG_PFD_528_PFD0_FRAC(n) ((n) & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD1_FRAC_MASK (0x3f<<8)
#define CCM_ANALOG_PFD_528_PFD1_FRAC(n) (((n)<<8) & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD2_FRAC_MASK (0x3f<<16)
#define CCM_ANALOG_PFD_528_PFD2_FRAC(n) (((n)<<16) & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD3_FRAC_MASK ((0x3f<<24)
#define CCM_ANALOG_PFD_528_PFD3_FRAC(n) (((n)<<24) & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK)
#define SDHC_DSADDR (USDHC1_DS_ADDR ) // DMA System Address register
#define SDHC_BLKATTR (USDHC1_BLK_ATT) // Block Attributes register
#define SDHC_CMDARG (USDHC1_CMD_ARG) // Command Argument register
#define SDHC_XFERTYP (USDHC1_CMD_XFR_TYP) // Transfer Type register
#define SDHC_CMDRSP0 (USDHC1_CMD_RSP0) // Command Response 0
#define SDHC_CMDRSP1 (USDHC1_CMD_RSP1) // Command Response 1
#define SDHC_CMDRSP2 (USDHC1_CMD_RSP2) // Command Response 2
#define SDHC_CMDRSP3 (USDHC1_CMD_RSP3) // Command Response 3
#define SDHC_DATPORT (USDHC1_DATA_BUFF_ACC_PORT) // Buffer Data Port register
#define SDHC_PRSSTAT (USDHC1_PRES_STATE) // Present State register
#define SDHC_PROCTL (USDHC1_PROT_CTRL) // Protocol Control register
#define SDHC_SYSCTL (USDHC1_SYS_CTRL) // System Control register
#define SDHC_IRQSTAT (USDHC1_INT_STATUS) // Interrupt Status register
#define SDHC_IRQSTATEN (USDHC1_INT_STATUS_EN) // Interrupt Status Enable register
#define SDHC_IRQSIGEN (USDHC1_INT_SIGNAL_EN) // Interrupt Signal Enable register
#define SDHC_AC12ERR (USDHC1_AUTOCMD12_ERR_STATUS) // Auto CMD12 Error Status Register
#define SDHC_HTCAPBLT (USDHC1_HOST_CTRL_CAP) // Host Controller Capabilities
#define SDHC_WML (USDHC1_WTMK_LVL) // Watermark Level Register
#define SDHC_MIX_CTRL (USDHC1_MIX_CTRL) // Mixer Control
#define SDHC_FEVT (USDHC1_FORCE_EVENT) // Force Event register
#define SDHC_ADMAES (USDHC1_ADMA_ERR_STATUS) // ADMA Error Status register
#define SDHC_ADSADDR (USDHC1_ADMA_SYS_ADDR) // ADMA System Addressregister
#define SDHC_VENDOR (USDHC1_VEND_SPEC) // Vendor Specific register
#define SDHC_MMCBOOT (USDHC1_MMC_BOOT) // MMC Boot register
#define SDHC_VENDOR2 (USDHC2_VEND_SPEC2) // Vendor Specific2 register
//
#define IRQ_SDHC IRQ_SDHC1
#define SDHC_MAX_DVS (0xF + 1U)
#define SDHC_MAX_CLKFS (0xFF + 1U)
#define SDHC_PREV_DVS(x) ((x) -= 1U)
#define SDHC_PREV_CLKFS(x, y) ((x) >>= (y))
#define CCM_CSCDR1_USDHC1_CLK_PODF_MASK (0x7<<11)
#define CCM_CSCDR1_USDHC1_CLK_PODF(n) (((n)&0x7)<<11)
#define IOMUXC_SW_PAD_CTL_PAD_SRE ((0x1<)<0)
#define IOMUXC_SW_PAD_CTL_PAD_PKE ((0x1)<<12)
#define IOMUXC_SW_PAD_CTL_PAD_PUE ((0x1)<<13)
#define IOMUXC_SW_PAD_CTL_PAD_HYS ((0x1)<<16)
#define IOMUXC_SW_PAD_CTL_PAD_SPEED(n) (((n)&0x3)<<6)
#define IOMUXC_SW_PAD_CTL_PAD_PUS(n) (((n)&0x3)<<14)
#define IOMUXC_SW_PAD_CTL_PAD_PUS_MASK ((0x3)<<14)
#define IOMUXC_SW_PAD_CTL_PAD_DSE(n) (((n)&0x7)<<3)
#define IOMUXC_SW_PAD_CTL_PAD_DSE_MASK ((0x7)<<3)
#endif // defined(__IMXRT1062__)
#endif // SdioTeensy_h

View File

@ -1,582 +0,0 @@
/**
* Copyright (c) 2011-2021 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef SdFat_h
#define SdFat_h
/**
* \file
* \brief main SdFs include file.
*/
#include "common/SysCall.h"
#include "SdCard/SdCard.h"
#include "ExFatLib/ExFatLib.h"
#include "FatLib/FatLib.h"
#include "FsLib/FsLib.h"
#if INCLUDE_SDIOS
#include "sdios.h"
#endif // INCLUDE_SDIOS
//------------------------------------------------------------------------------
/** SdFat version for cpp use. */
#define SD_FAT_VERSION 20102
/** SdFat version as string. */
#define SD_FAT_VERSION_STR "2.1.2"
//==============================================================================
/**
* \class SdBase
* \brief base SD file system template class.
*/
template <class Vol, class Fmt>
class SdBase : public Vol
{
public:
//----------------------------------------------------------------------------
/** Initialize SD card and file system.
*
* \param[in] csPin SD card chip select pin.
* \return true for success or false for failure.
*/
bool begin(SdCsPin_t csPin = SS)
{
#ifdef BUILTIN_SDCARD
if (csPin == BUILTIN_SDCARD) {
return begin(SdioConfig(FIFO_SDIO));
}
#endif // BUILTIN_SDCARD
return begin(SdSpiConfig(csPin, SHARED_SPI));
}
//----------------------------------------------------------------------------
/** Initialize SD card and file system.
*
* \param[in] csPin SD card chip select pin.
* \param[in] maxSck Maximum SCK frequency.
* \return true for success or false for failure.
*/
bool begin(SdCsPin_t csPin, uint32_t maxSck)
{
return begin(SdSpiConfig(csPin, SHARED_SPI, maxSck));
}
//----------------------------------------------------------------------------
/** Initialize SD card and file system for SPI mode.
*
* \param[in] spiConfig SPI configuration.
* \return true for success or false for failure.
*/
bool begin(SdSpiConfig spiConfig)
{
return cardBegin(spiConfig) && Vol::begin(m_card);
}
//---------------------------------------------------------------------------
/** Initialize SD card and file system for SDIO mode.
*
* \param[in] sdioConfig SDIO configuration.
* \return true for success or false for failure.
*/
bool begin(SdioConfig sdioConfig)
{
return cardBegin(sdioConfig) && Vol::begin(m_card);
}
//----------------------------------------------------------------------------
/** \return Pointer to SD card object. */
SdCard* card()
{
return m_card;
}
//----------------------------------------------------------------------------
/** Initialize SD card in SPI mode.
*
* \param[in] spiConfig SPI configuration.
* \return true for success or false for failure.
*/
bool cardBegin(SdSpiConfig spiConfig)
{
m_card = m_cardFactory.newCard(spiConfig);
return m_card && !m_card->errorCode();
}
//----------------------------------------------------------------------------
/** Initialize SD card in SDIO mode.
*
* \param[in] sdioConfig SDIO configuration.
* \return true for success or false for failure.
*/
bool cardBegin(SdioConfig sdioConfig)
{
m_card = m_cardFactory.newCard(sdioConfig);
return m_card && !m_card->errorCode();
}
//----------------------------------------------------------------------------
/** End use of card. */
void end()
{
Vol::end();
if (m_card) {
m_card->end();
}
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] pr Print destination.
*/
void errorHalt(print_t* pr)
{
if (sdErrorCode()) {
pr->print(F("SdError: 0X"));
pr->print(sdErrorCode(), HEX);
pr->print(F(",0X"));
pr->println(sdErrorData(), HEX);
} else if (!Vol::fatType()) {
pr->println(F("Check SD format."));
}
while (true) {}
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void errorHalt(print_t* pr, const char* msg)
{
pr->print(F("error: "));
pr->println(msg);
errorHalt(pr);
}
//----------------------------------------------------------------------------
/** %Print msg and halt.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void errorHalt(print_t* pr, const __FlashStringHelper* msg)
{
pr->print(F("error: "));
pr->println(msg);
errorHalt(pr);
}
//----------------------------------------------------------------------------
/** Format SD card
*
* \param[in] pr Print destination.
* \return true for success else false.
*/
bool format(print_t* pr = nullptr)
{
Fmt fmt;
uint8_t* mem = Vol::end();
if (!mem) {
return false;
}
bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi();
if (switchSpi && !setDedicatedSpi(true)) {
return 0;
}
bool rtn = fmt.format(card(), mem, pr);
if (switchSpi && !setDedicatedSpi(false)) {
return 0;
}
return rtn;
}
//----------------------------------------------------------------------------
/** \return the free cluster count. */
uint32_t freeClusterCount()
{
bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi();
if (switchSpi && !setDedicatedSpi(true)) {
return 0;
}
uint32_t rtn = Vol::freeClusterCount();
if (switchSpi && !setDedicatedSpi(false)) {
return 0;
}
return rtn;
}
//----------------------------------------------------------------------------
/** \return true if can be in dedicated SPI state */
bool hasDedicatedSpi()
{
return m_card ? m_card->hasDedicatedSpi() : false;
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] pr Print destination.
*/
void initErrorHalt(print_t* pr)
{
initErrorPrint(pr);
while (true) {}
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void initErrorHalt(print_t* pr, const char* msg)
{
pr->println(msg);
initErrorHalt(pr);
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void initErrorHalt(print_t* pr, const __FlashStringHelper* msg)
{
pr->println(msg);
initErrorHalt(pr);
}
//----------------------------------------------------------------------------
/** Print error details after begin() fails.
*
* \param[in] pr Print destination.
*/
void initErrorPrint(print_t* pr)
{
pr->println(F("begin() failed"));
if (sdErrorCode()) {
pr->println(F("Do not reformat the SD."));
if (sdErrorCode() == SD_CARD_ERROR_CMD0) {
pr->println(F("No card, wrong chip select pin, or wiring error?"));
}
}
errorPrint(pr);
}
//----------------------------------------------------------------------------
/** \return true if in dedicated SPI state. */
bool isDedicatedSpi()
{
return m_card ? m_card->isDedicatedSpi() : false;
}
//----------------------------------------------------------------------------
/** %Print volume FAT/exFAT type.
*
* \param[in] pr Print destination.
*/
void printFatType(print_t* pr)
{
if (Vol::fatType() == FAT_TYPE_EXFAT) {
pr->print(F("exFAT"));
} else {
pr->print(F("FAT"));
pr->print(Vol::fatType());
}
}
//----------------------------------------------------------------------------
/** %Print SD errorCode and errorData.
*
* \param[in] pr Print destination.
*/
void errorPrint(print_t* pr)
{
if (sdErrorCode()) {
pr->print(F("SdError: 0X"));
pr->print(sdErrorCode(), HEX);
pr->print(F(",0X"));
pr->println(sdErrorData(), HEX);
} else if (!Vol::fatType()) {
pr->println(F("Check SD format."));
}
}
//----------------------------------------------------------------------------
/** %Print msg, any SD error code.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void errorPrint(print_t* pr, char const* msg)
{
pr->print(F("error: "));
pr->println(msg);
errorPrint(pr);
}
/** %Print msg, any SD error code.
*
* \param[in] pr Print destination.
* \param[in] msg Message to print.
*/
void errorPrint(print_t* pr, const __FlashStringHelper* msg)
{
pr->print(F("error: "));
pr->println(msg);
errorPrint(pr);
}
//----------------------------------------------------------------------------
/** %Print error info and return.
*
* \param[in] pr Print destination.
*/
void printSdError(print_t* pr)
{
if (sdErrorCode()) {
if (sdErrorCode() == SD_CARD_ERROR_CMD0) {
pr->println(F("No card, wrong chip select pin, or wiring error?"));
}
pr->print(F("SD error: "));
printSdErrorSymbol(pr, sdErrorCode());
pr->print(F(" = 0x"));
pr->print(sdErrorCode(), HEX);
pr->print(F(",0x"));
pr->println(sdErrorData(), HEX);
} else if (!Vol::fatType()) {
pr->println(F("Check SD format."));
}
}
//----------------------------------------------------------------------------
/** \return SD card error code. */
uint8_t sdErrorCode()
{
if (m_card) {
return m_card->errorCode();
}
return SD_CARD_ERROR_INVALID_CARD_CONFIG;
}
//----------------------------------------------------------------------------
/** \return SD card error data. */
uint8_t sdErrorData()
{
return m_card ? m_card->errorData() : 0;
}
//----------------------------------------------------------------------------
/** Set SPI sharing state
* \param[in] value desired state.
* \return true for success else false;
*/
bool setDedicatedSpi(bool value)
{
if (m_card) {
return m_card->setDedicatedSpi(value);
}
return false;
}
//----------------------------------------------------------------------------
/** \return pointer to base volume */
Vol* vol()
{
return reinterpret_cast<Vol*>(this);
}
//----------------------------------------------------------------------------
/** Initialize file system after call to cardBegin.
*
* \return true for success or false for failure.
*/
bool volumeBegin()
{
return Vol::begin(m_card);
}
#if ENABLE_ARDUINO_SERIAL
/** Print error details after begin() fails. */
void initErrorPrint()
{
initErrorPrint(&Serial);
}
//----------------------------------------------------------------------------
/** %Print msg to Serial and halt.
*
* \param[in] msg Message to print.
*/
void errorHalt(const __FlashStringHelper* msg)
{
errorHalt(&Serial, msg);
}
//----------------------------------------------------------------------------
/** %Print error info to Serial and halt. */
void errorHalt()
{
errorHalt(&Serial);
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] msg Message to print.
*/
void errorHalt(const char* msg)
{
errorHalt(&Serial, msg);
}
//----------------------------------------------------------------------------
/** %Print error info and halt. */
void initErrorHalt()
{
initErrorHalt(&Serial);
}
//----------------------------------------------------------------------------
/** %Print msg, any SD error code.
*
* \param[in] msg Message to print.
*/
void errorPrint(const char* msg)
{
errorPrint(&Serial, msg);
}
/** %Print msg, any SD error code.
*
* \param[in] msg Message to print.
*/
void errorPrint(const __FlashStringHelper* msg)
{
errorPrint(&Serial, msg);
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] msg Message to print.
*/
void initErrorHalt(const char* msg)
{
initErrorHalt(&Serial, msg);
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] msg Message to print.
*/
void initErrorHalt(const __FlashStringHelper* msg)
{
initErrorHalt(&Serial, msg);
}
#endif // ENABLE_ARDUINO_SERIAL
//----------------------------------------------------------------------------
private:
SdCard* m_card = nullptr;
SdCardFactory m_cardFactory;
};
//------------------------------------------------------------------------------
/**
* \class SdFat32
* \brief SD file system class for FAT volumes.
*/
class SdFat32 : public SdBase<FatVolume, FatFormatter>
{
public:
};
//------------------------------------------------------------------------------
/**
* \class SdExFat
* \brief SD file system class for exFAT volumes.
*/
class SdExFat : public SdBase<ExFatVolume, ExFatFormatter>
{
public:
};
//------------------------------------------------------------------------------
/**
* \class SdFs
* \brief SD file system class for FAT16, FAT32, and exFAT volumes.
*/
class SdFs : public SdBase<FsVolume, FsFormatter>
{
public:
};
//------------------------------------------------------------------------------
#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN)
/** Select type for SdFat. */
typedef SdFat32 SdFat;
/** Select type for SdBaseFile. */
typedef FatFile SdBaseFile;
#elif SDFAT_FILE_TYPE == 2
typedef SdExFat SdFat;
typedef ExFatFile SdBaseFile;
#elif SDFAT_FILE_TYPE == 3
typedef SdFs SdFat;
typedef FsBaseFile SdBaseFile;
#else // SDFAT_FILE_TYPE
#error Invalid SDFAT_FILE_TYPE
#endif // SDFAT_FILE_TYPE
//
// Only define File if FS.h is not included.
// Line with test for __has_include must not have operators or parentheses.
#if defined __has_include
#if __has_include(<FS.h>)
#define HAS_INCLUDE_FS_H
//#warning File not defined because __has_include(FS.h)
#endif // __has_include(<FS.h>)
#endif // defined __has_include
#ifndef HAS_INCLUDE_FS_H
#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN)
/** Select type for File. */
typedef File32 File;
#elif SDFAT_FILE_TYPE == 2
typedef ExFile File;
#elif SDFAT_FILE_TYPE == 3
typedef FsFile File;
#endif // SDFAT_FILE_TYPE
#endif // HAS_INCLUDE_FS_H
/**
* \class SdFile
* \brief FAT16/FAT32 file with Print.
*/
class SdFile : public PrintFile<SdBaseFile>
{
public:
SdFile() {}
/** Create an open SdFile.
* \param[in] path path for file.
* \param[in] oflag open flags.
*/
SdFile(const char* path, oflag_t oflag)
{
open(path, oflag);
}
/** Set the date/time callback function
*
* \param[in] dateTime The user's call back function. The callback
* function is of the form:
*
* \code
* void dateTime(uint16_t* date, uint16_t* time) {
* uint16_t year;
* uint8_t month, day, hour, minute, second;
*
* // User gets date and time from GPS or real-time clock here
*
* // return date using FS_DATE macro to format fields
* *date = FS_DATE(year, month, day);
*
* // return time using FS_TIME macro to format fields
* *time = FS_TIME(hour, minute, second);
* }
* \endcode
*
* Sets the function that is called when a file is created or when
* a file's directory entry is modified by sync(). All timestamps,
* access, creation, and modify, are set when a file is created.
* sync() maintains the last access date and last modify date/time.
*
*/
static void dateTimeCallback(
void (*dateTime)(uint16_t* date, uint16_t* time))
{
FsDateTime::setCallback(dateTime);
}
/** Cancel the date/time callback function. */
static void dateTimeCallbackCancel()
{
FsDateTime::clearCallback();
}
};
#endif // SdFat_h

View File

@ -1,115 +0,0 @@
/**
* Copyright (c) 2011-2021 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "FsUtf.h"
namespace FsUtf {
//----------------------------------------------------------------------------
char* cpToMb(uint32_t cp, char* str, char* end) {
size_t n = end - str;
if (cp < 0X80) {
if (n < 1) goto fail;
*(str++) = static_cast<uint8_t>(cp);
} else if (cp < 0X800) {
if (n < 2) goto fail;
*(str++) = static_cast<uint8_t>((cp >> 6) | 0XC0);
*(str++) = static_cast<uint8_t>((cp & 0X3F) | 0X80);
} else if (cp < 0X10000) {
if (n < 3) goto fail;
*(str++) = static_cast<uint8_t>((cp >> 12) | 0XE0);
*(str++) = static_cast<uint8_t>(((cp >> 6) & 0X3F) | 0X80);
*(str++) = static_cast<uint8_t>((cp & 0X3F) | 0X80);
} else {
if (n < 4) goto fail;
*(str++) = static_cast<uint8_t>((cp >> 18) | 0XF0);
*(str++) = static_cast<uint8_t>(((cp >> 12) & 0X3F)| 0X80);
*(str++) = static_cast<uint8_t>(((cp >> 6) & 0X3F) | 0X80);
*(str++) = static_cast<uint8_t>((cp & 0X3F) | 0X80);
}
return str;
fail:
return nullptr;
}
//----------------------------------------------------------------------------
// to do? improve error check
const char* mbToCp(const char* str, const char* end, uint32_t* rtn) {
size_t n;
uint32_t cp;
if (str >= end) {
return nullptr;
}
uint8_t ch = str[0];
if ((ch & 0X80) == 0) {
*rtn = ch;
return str + 1;
}
if ((ch & 0XE0) == 0XC0) {
cp = ch & 0X1F;
n = 2;
} else if ((ch & 0XF0) == 0XE0) {
cp = ch & 0X0F;
n = 3;
} else if ((ch & 0XF8) == 0XF0) {
cp = ch & 0X07;
n = 4;
} else {
return nullptr;
}
if ((str + n) > end) {
return nullptr;
}
for (size_t i = 1; i < n; i++) {
ch = str[i];
if ((ch & 0XC0) != 0X80) {
return nullptr;
}
cp <<= 6;
cp |= ch & 0X3F;
}
// Don't allow over long as ASCII.
if (cp < 0X80 || !isValidCp(cp)) {
return nullptr;
}
*rtn = cp;
return str + n;
}
//----------------------------------------------------------------------------
const char* mbToU16(const char* str,
const char* end, uint16_t* hs, uint16_t* ls) {
uint32_t cp;
const char* ptr = mbToCp(str, end, &cp);
if (!ptr) {
return nullptr;
}
if (cp <= 0XFFFF) {
*hs = cp;
*ls = 0;
} else {
*hs = highSurrogate(cp);
*ls = lowSurrogate(cp);
}
return ptr;
}
} // namespace FsUtf

View File

@ -1,109 +0,0 @@
/**
* Copyright (c) 2011-2021 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef FsUtf_h
#define FsUtf_h
/**
* \file
* \brief Unicode Transformation Format functions.
*/
#include <stdint.h>
#include <stddef.h>
namespace FsUtf {
/** High surrogate for a code point.
* \param{in} cp code point.
* \return high surrogate.
*/
inline uint16_t highSurrogate(uint32_t cp) {
return (cp >> 10) + (0XD800 - (0X10000 >> 10));
}
/** Low surrogate for a code point.
* \param{in} cp code point.
* \return low surrogate.
*/
inline uint16_t lowSurrogate(uint32_t cp) {
return (cp & 0X3FF) + 0XDC00;
}
/** Check for a valid code point.
* \param[in] cp code point.
* \return true if valid else false.
*/
inline bool isValidCp(uint32_t cp) {
return cp <= 0x10FFFF && (cp < 0XD800 || cp > 0XDFFF);
}
/** Check for UTF-16 surrogate.
* \param[in] c UTF-16 unit.
* \return true if c is a surrogate else false.
*/
inline bool isSurrogate(uint16_t c) {
return 0XD800 <= c && c <= 0XDFFF;
}
/** Check for UTF-16 high surrogate.
* \param[in] c UTF-16 unit..
* \return true if c is a high surrogate else false.
*/
inline bool isHighSurrogate(uint16_t c) {
return 0XD800 <= c && c <= 0XDBFF;
}
/** Check for UTF-16 low surrogate.
* \param[in] c UTF-16 unit..
* \return true if c is a low surrogate else false.
*/
inline bool isLowSurrogate(uint16_t c) {
return 0XDC00 <= c && c <= 0XDFFF;
}
/** Convert UFT-16 surrogate pair to code point.
* \param[in] hs high surrogate.
* \param[in] ls low surrogate.
* \return code point.
*/
inline uint32_t u16ToCp(uint16_t hs, uint16_t ls) {
return 0X10000 + (((hs & 0X3FF) << 10) | (ls & 0X3FF));
}
/** Encodes a 32 bit code point as a UTF-8 sequence.
* \param[in] cp code point to encode.
* \param[out] str location for UTF-8 sequence.
* \param[in] end location following last character of str.
* \return location one beyond last encoded character.
*/
char* cpToMb(uint32_t cp, char* str, char* end);
/** Get next code point from a UTF-8 sequence.
* \param[in] str location for UTF-8 sequence.
* \param[in] end location following last character of str.
* May be nullptr if str is zero terminated.
* \param[out] rtn location for the code point.
* \return location of next UTF-8 character in str of nullptr for error.
*/
const char* mbToCp(const char* str, const char* end, uint32_t* rtn);
/** Get next code point from a UTF-8 sequence as UTF-16.
* \param[in] str location for UTF-8 sequence.
* \param[in] end location following last character of str.
* \param[out] hs location for the code point or high surrogate.
* \param[out] ls location for zero or high surrogate.
* \return location of next UTF-8 character in str of nullptr for error.
*/
const char* mbToU16(const char* str,
const char* end, uint16_t* hs, uint16_t* ls);
} // namespace FsUtf
#endif // FsUtf_h

View File

@ -0,0 +1,36 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Icon must ends with two \r.
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes

View File

@ -1,8 +1,8 @@
### Warning: This is SdFat Version 2.
File copy constructors and file assignment operators have been made private by
default in 2.2.3 to prevent call by value and multiple copies of file instances.
Earlier releases of Version 1 are here:
https://github.com/greiman/SdFat/releases
SdFatConfig.h has options to make file constructors and assignment operators
public.
UTF-8 encoded filenames are supported in v2.1.0 or later.

View File

@ -1,4 +1,4 @@
# Doxyfile 1.9.2
# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@ -12,6 +12,16 @@
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#
# Note:
#
# Use doxygen to compare the used configuration file with the template
# configuration file:
# doxygen -x [configFile]
# Use doxygen to compare the used configuration file with the template
# configuration file without replacing the environment variables or CMake type
# replacement variables:
# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
@ -60,16 +70,28 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = .
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format
# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
# Controls the number of sub-directories that will be created when
# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
# number of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
CREATE_SUBDIRS_LEVEL = 8
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
@ -81,14 +103,14 @@ ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
# English messages), Korean, Korean-en (Korean with English messages), Latvian,
# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
@ -452,7 +474,7 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
@ -546,7 +568,8 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# will also hide undocumented C++ concepts if enabled. This option has no effect
# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
@ -577,14 +600,15 @@ INTERNAL_DOCS = NO
# filesystem is case sensitive (i.e. it supports files in the same directory
# whose names only differ in casing), the option must be set to YES to properly
# deal with such files in case they appear in the input. For filesystems that
# are not case sensitive the option should be be set to NO to properly deal with
# are not case sensitive the option should be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# The default value is: system dependent.
# Possible values are: SYSTEM, NO and YES.
# The default value is: SYSTEM.
CASE_SENSE_NAMES = NO
@ -836,6 +860,14 @@ WARN_IF_INCOMPLETE_DOC = YES
WARN_NO_PARAMDOC = YES
# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
# undocumented enumeration values. If set to NO, doxygen will accept
# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: NO.
WARN_IF_UNDOC_ENUM_VAL = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
@ -851,13 +883,27 @@ WARN_AS_ERROR = NO
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# In the $text part of the WARN_FORMAT command it is possible that a reference
# to a more specific place is given. To make it easier to jump to this place
# (outside of doxygen) the user can define a custom "cut" / "paste" string.
# Example:
# WARN_LINE_FORMAT = "'vi $file +$line'"
# See also: WARN_FORMAT
# The default value is: at line $line of file $file.
WARN_LINE_FORMAT = "at line $line of file $file"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
# error (stderr). In case the file specified cannot be opened for writing the
# warning and error messages are written to standard error. When as file - is
# specified the warning and error messages are written to standard output
# (stdout).
WARN_LOGFILE =
@ -887,10 +933,21 @@ INPUT = ../src \
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# This tag can be used to specify the character encoding of the source files
# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
# character encoding on a per file pattern basis. Doxygen will compare the file
# name with each pattern and apply the encoding instead of the default
# INPUT_ENCODING) if there is a match. The character encodings are a list of the
# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
# "INPUT_ENCODING" for further information on supported encodings.
INPUT_FILE_ENCODING =
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
@ -981,7 +1038,7 @@ EXCLUDE_PATTERNS =
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
@ -1029,6 +1086,11 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that doxygen will use the data processed and written to standard output
# for further processing, therefore nothing else, like debug statements or used
# commands (so in case of a Windows batch file always use @echo OFF), should be
# written to standard output.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
@ -1070,6 +1132,15 @@ FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
# The Fortran standard specifies that for fixed formatted Fortran code all
# characters from position 72 are to be considered as comment. A common
# extension is to allow longer lines before the automatic comment starts. The
# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
# be processed before the automatic comment starts.
# Minimum value: 7, maximum value: 10000, default value: 72.
FORTRAN_COMMENT_AFTER = 72
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
@ -1207,10 +1278,11 @@ CLANG_DATABASE_PATH =
ALPHABETICAL_INDEX = NO
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
# that should be ignored while generating the index headers. The IGNORE_PREFIX
# tag works for classes, function and member names. The entity will be placed in
# the alphabetical list under the first letter of the entity name that remains
# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
@ -1289,7 +1361,12 @@ HTML_STYLESHEET =
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# list).
# Note: Since the styling of scrollbars can currently not be overruled in
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
# one or more extra stylesheets have been specified. So if scrollbar
# customization is desired it has to be added explicitly. For an example see the
# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
@ -1304,6 +1381,19 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
# should be rendered with a dark or light theme.
# Possible values are: LIGHT always generate light mode output, DARK always
# generate dark mode output, AUTO_LIGHT automatically set the mode according to
# the user preference, use light mode if no preference is set (the default),
# AUTO_DARK automatically set the mode according to the user preference, use
# dark mode if no preference is set and TOGGLE allow to user to switch between
# light and dark mode via a button.
# The default value is: AUTO_LIGHT.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE = AUTO_LIGHT
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a color-wheel, see
@ -1398,6 +1488,13 @@ GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag determines the URL of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDURL =
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@ -1602,7 +1699,7 @@ GENERATE_TREEVIEW = NO
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATOR_TREEVIEW or
# project logo, title, and description. If either GENERATE_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@ -1633,6 +1730,13 @@ TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
# addresses.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
OBFUSCATE_EMAILS = YES
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
@ -1653,17 +1757,6 @@ HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
@ -2258,7 +2351,8 @@ SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
@ -2354,15 +2448,6 @@ EXTERNAL_PAGES = YES
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
@ -2395,35 +2480,50 @@ HAVE_DOT = YES
DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
# subgraphs. When you want a differently looking font in the dot files that
# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
# Edge and Graph Attributes specification</a> You need to make sure dot is able
# to find the font, which can be done by putting it in a standard location or by
# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font. Default graphviz fontsize is 14.
# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
# arrows shapes.</a>
# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
# around nodes set 'shape=plain' or 'shape=plaintext' <a
# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
# The default value is: shape=box,height=0.2,width=0.4.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
# You can set the path where dot can find font specified with fontname in
# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
# graph for each documented class showing the direct and indirect inheritance
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
# to TEXT the direct and indirect inheritance relations will be shown as texts /
# links.
# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
@ -2437,7 +2537,8 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# groups, showing the direct groups dependencies. See also the chapter Grouping
# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
@ -2552,6 +2653,13 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
# of child directories generated in directory dependency graphs by dot.
# Minimum value: 1, maximum value: 25, default value: 1.
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
DIR_GRAPH_MAX_DEPTH = 1
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
@ -2605,10 +2713,10 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
# path where java can find the plantuml.jar file or to the filename of jar file
# to be used. If left blank, it is assumed PlantUML is not used or called during
# a preprocessing step. Doxygen will generate a warning when it encounters a
# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
@ -2646,18 +2754,6 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = YES
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
@ -2670,6 +2766,8 @@ DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.

View File

@ -0,0 +1,51 @@
2022-07-01
Run the SdErrorCode example to produce an updated list.
Code,Symbol - failed operation
0X00,SD_CARD_ERROR_NONE - No error
0X01,SD_CARD_ERROR_CMD0 - Card reset failed
0X02,SD_CARD_ERROR_CMD2 - SDIO read CID
0X03,SD_CARD_ERROR_CMD3 - SDIO publish RCA
0X04,SD_CARD_ERROR_CMD6 - Switch card function
0X05,SD_CARD_ERROR_CMD7 - SDIO card select
0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings
0X07,SD_CARD_ERROR_CMD9 - Read CSD data
0X08,SD_CARD_ERROR_CMD10 - Read CID data
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read
0X0A,SD_CARD_ERROR_CMD13 - Read card status
0X0B,SD_CARD_ERROR_CMD17 - Read single block
0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks
0X0D,SD_CARD_ERROR_CMD24 - Write single block
0X0E,SD_CARD_ERROR_CMD25 - Write multiple blocks
0X0F,SD_CARD_ERROR_CMD32 - Set first erase block
0X10,SD_CARD_ERROR_CMD33 - Set last erase block
0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks
0X12,SD_CARD_ERROR_CMD58 - Read OCR register
0X13,SD_CARD_ERROR_CMD59 - Set CRC mode
0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width
0X15,SD_CARD_ERROR_ACMD13 - Read extended status
0X16,SD_CARD_ERROR_ACMD23 - Set pre-erased count
0X17,SD_CARD_ERROR_ACMD41 - Activate card initialization
0X18,SD_CARD_ERROR_ACMD51 - Read SCR data
0X19,SD_CARD_ERROR_READ_TOKEN - Bad read data token
0X1A,SD_CARD_ERROR_READ_CRC - Read CRC error
0X1B,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout
0X1C,SD_CARD_ERROR_READ_REG - Read CID or CSD failed.
0X1D,SD_CARD_ERROR_READ_START - Bad readStart argument
0X1E,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout
0X1F,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed
0X20,SD_CARD_ERROR_TRANSFER_COMPLETE - SDIO transfer complete
0X21,SD_CARD_ERROR_WRITE_DATA - Write data not accepted
0X22,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout
0X23,SD_CARD_ERROR_WRITE_START - Bad writeStart argument
0X24,SD_CARD_ERROR_WRITE_PROGRAMMING - Flash programming
0X25,SD_CARD_ERROR_WRITE_TIMEOUT - Write timeout
0X26,SD_CARD_ERROR_DMA - DMA transfer failed
0X27,SD_CARD_ERROR_ERASE - Card did not accept erase commands
0X28,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase
0X29,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout
0X2A,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized
0X2B,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config
0X2C,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command
0X2D,SD_CARD_ERROR_UNKNOWN - Unknown error

Binary file not shown.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2011-2021 Bill Greiman
* Copyright (c) 2011-2024 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License

View File

@ -3,7 +3,8 @@
const size_t BLOCK_SIZE = 64;
//------------------------------------------------------------------------------
// First block of file.
const size_t PIN_NUM_DIM = BLOCK_SIZE - 3*sizeof(uint32_t) - 2*sizeof(uint8_t);
const size_t PIN_NUM_DIM =
BLOCK_SIZE - 3 * sizeof(uint32_t) - 2 * sizeof(uint8_t);
struct metadata_t {
uint32_t adcFrequency; // ADC clock frequency
uint32_t cpuFrequency; // CPU clock frequency
@ -14,7 +15,7 @@ struct metadata_t {
};
//------------------------------------------------------------------------------
// Data block for 8-bit ADC mode.
const size_t DATA_DIM8 = (BLOCK_SIZE - 2*sizeof(uint16_t))/sizeof(uint8_t);
const size_t DATA_DIM8 = (BLOCK_SIZE - 2 * sizeof(uint16_t)) / sizeof(uint8_t);
struct block8_t {
uint16_t count; // count of data values
uint16_t overrun; // count of overruns since last block
@ -22,7 +23,8 @@ struct block8_t {
};
//------------------------------------------------------------------------------
// Data block for 10-bit ADC mode.
const size_t DATA_DIM16 = (BLOCK_SIZE - 2*sizeof(uint16_t))/sizeof(uint16_t);
const size_t DATA_DIM16 =
(BLOCK_SIZE - 2 * sizeof(uint16_t)) / sizeof(uint16_t);
struct block16_t {
unsigned short count; // count of data values
unsigned short overrun; // count of overruns since last block

View File

@ -20,10 +20,11 @@
*/
#ifdef __AVR__
#include <SPI.h>
#include "SdFat.h"
#include "AvrAdcLogger.h"
#include "BufferedPrint.h"
#include "FreeStack.h"
#include "AvrAdcLogger.h"
#include "SdFat.h"
// Save SRAM if 328.
#ifdef __AVR_ATmega328P__
@ -73,7 +74,7 @@ const float SAMPLE_RATE = 5000; // Must be 0.25 or greater.
// constant instead of being calculated from SAMPLE_RATE. SAMPLE_RATE is not
// used in the code below. For example, setting SAMPLE_INTERVAL = 2.0e-4
// will result in a 200 microsecond sample interval.
const float SAMPLE_INTERVAL = 1.0/SAMPLE_RATE;
const float SAMPLE_INTERVAL = 1.0 / SAMPLE_RATE;
// Setting ROUND_SAMPLE_INTERVAL non-zero will cause the sample interval to
// be rounded to a a multiple of the ADC clock period and will reduce sample
@ -109,11 +110,11 @@ const size_t NAME_DIM = 40;
#elif RAMEND < 0X10FF
const size_t FIFO_SIZE_BYTES = 512;
#elif RAMEND < 0X20FF
const size_t FIFO_SIZE_BYTES = 4*512;
const size_t FIFO_SIZE_BYTES = 4 * 512;
#elif RAMEND < 0X40FF
const size_t FIFO_SIZE_BYTES = 12*512;
const size_t FIFO_SIZE_BYTES = 12 * 512;
#else // RAMEND
const size_t FIFO_SIZE_BYTES = 16*512;
const size_t FIFO_SIZE_BYTES = 16 * 512;
#endif // RAMEND
//------------------------------------------------------------------------------
// ADC clock rate.
@ -136,7 +137,7 @@ const size_t FIFO_SIZE_BYTES = 16*512;
#define TMP_FILE_NAME "tmp_adc.bin"
// Number of analog pins to log.
const uint8_t PIN_COUNT = sizeof(PIN_LIST)/sizeof(PIN_LIST[0]);
const uint8_t PIN_COUNT = sizeof(PIN_LIST) / sizeof(PIN_LIST[0]);
// Minimum ADC clock cycles per sample interval
const uint16_t MIN_ADC_CYCLES = 15;
@ -151,6 +152,7 @@ const uint32_t MAX_FILE_SIZE = MAX_FILE_SIZE_MiB << 20;
// Max SPI rate for AVR is 10 MHz for F_CPU 20 MHz, 8 MHz for F_CPU 16 MHz.
#define SPI_CLOCK SD_SCK_MHZ(10)
// Select fastest interface.
#if ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
@ -180,15 +182,15 @@ file_t csvFile;
char binName[] = LOG_FILE_NAME;
#if RECORD_EIGHT_BITS
const size_t BLOCK_MAX_COUNT = PIN_COUNT*(DATA_DIM8/PIN_COUNT);
const size_t BLOCK_MAX_COUNT = PIN_COUNT * (DATA_DIM8 / PIN_COUNT);
typedef block8_t block_t;
#else // RECORD_EIGHT_BITS
const size_t BLOCK_MAX_COUNT = PIN_COUNT*(DATA_DIM16/PIN_COUNT);
const size_t BLOCK_MAX_COUNT = PIN_COUNT * (DATA_DIM16 / PIN_COUNT);
typedef block16_t block_t;
#endif // RECORD_EIGHT_BITS
// Size of FIFO in blocks.
size_t const FIFO_DIM = FIFO_SIZE_BYTES/sizeof(block_t);
size_t const FIFO_DIM = FIFO_SIZE_BYTES / sizeof(block_t);
block_t* fifoData;
volatile size_t fifoCount = 0; // volatile - shared, ISR and background.
size_t fifoHead = 0; // Only accessed by ISR during logging.
@ -277,7 +279,7 @@ ISR(TIMER1_COMPB_vect) {
}
//==============================================================================
// Error messages stored in flash.
#define error(msg) (Serial.println(F(msg)),errorHalt())
#define error(msg) (Serial.println(F(msg)), errorHalt())
#define assert(e) ((e) ? (void)0 : error("assert: " #e))
//------------------------------------------------------------------------------
//
@ -336,12 +338,13 @@ void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
#error unexpected ADC prescaler bits
#endif
//------------------------------------------------------------------------------
inline bool adcActive() {return (1 << ADIE) & ADCSRA;}
inline bool adcActive() { return (1 << ADIE) & ADCSRA; }
//------------------------------------------------------------------------------
// initialize ADC and timer1
void adcInit(metadata_t* meta) {
uint8_t adps; // prescaler bits for ADCSRA
uint32_t ticks = F_CPU*SAMPLE_INTERVAL + 0.5; // Sample interval cpu cycles.
uint32_t ticks =
F_CPU * SAMPLE_INTERVAL + 0.5; // Sample interval cpu cycles.
if (ADC_REF & ~((1 << REFS0) | (1 << REFS1))) {
error("Invalid ADC reference");
@ -353,7 +356,7 @@ void adcInit(metadata_t* meta) {
adps = ADC_PRESCALER;
#else // ADC_PRESCALER
// Allow extra cpu cycles to change ADC settings if more than one pin.
int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT - ISR_SETUP_ADC;
int32_t adcCycles = (ticks - ISR_TIMER0) / PIN_COUNT - ISR_SETUP_ADC;
for (adps = 7; adps > 0; adps--) {
if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
@ -410,19 +413,19 @@ void adcInit(metadata_t* meta) {
// no prescale, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
tshift = 0;
} else if (ticks < 0X10000*8) {
} else if (ticks < 0X10000 * 8) {
// prescale 8, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
tshift = 3;
} else if (ticks < 0X10000*64) {
} else if (ticks < 0X10000 * 64) {
// prescale 64, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10);
tshift = 6;
} else if (ticks < 0X10000*256) {
} else if (ticks < 0X10000 * 256) {
// prescale 256, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12);
tshift = 8;
} else if (ticks < 0X10000*1024) {
} else if (ticks < 0X10000 * 1024) {
// prescale 1024, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10);
tshift = 10;
@ -442,7 +445,7 @@ void adcInit(metadata_t* meta) {
// Sample interval in CPU clock ticks.
meta->sampleInterval = ticks;
meta->cpuFrequency = F_CPU;
float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
float sampleRate = (float)meta->cpuFrequency / meta->sampleInterval;
Serial.print(F("Sample pins:"));
for (uint8_t i = 0; i < meta->pinCount; i++) {
Serial.print(' ');
@ -452,11 +455,11 @@ void adcInit(metadata_t* meta) {
Serial.print(F("ADC bits: "));
Serial.println(meta->recordEightBits ? 8 : 10);
Serial.print(F("ADC clock kHz: "));
Serial.println(meta->adcFrequency/1000);
Serial.println(meta->adcFrequency / 1000);
Serial.print(F("Sample Rate: "));
Serial.println(sampleRate);
Serial.print(F("Sample interval usec: "));
Serial.println(1000000.0/sampleRate);
Serial.println(1000000.0 / sampleRate);
}
//------------------------------------------------------------------------------
// enable ADC and timer1 interrupts
@ -508,7 +511,7 @@ void binaryToCsv() {
if (nb < 0) {
error("read binFile failed");
}
size_t nd = nb/sizeof(block_t);
size_t nd = nb / sizeof(block_t);
if (nd < 1) {
break;
}
@ -519,7 +522,8 @@ void binaryToCsv() {
error("Invalid pinCount");
}
bp.print(F("Interval,"));
float intervalMicros = 1.0e6*pm->sampleInterval/(float)pm->cpuFrequency;
float intervalMicros =
1.0e6 * pm->sampleInterval / (float)pm->cpuFrequency;
bp.print(intervalMicros, 4);
bp.println(F(",usec"));
for (uint8_t i = 0; i < PIN_COUNT; i++) {
@ -541,14 +545,15 @@ void binaryToCsv() {
}
for (size_t j = 0; j < pd->count; j += PIN_COUNT) {
for (size_t i = 0; i < PIN_COUNT; i++) {
if (!bp.printField(pd->data[i + j], i == (PIN_COUNT-1) ? '\n' : ',')) {
if (!bp.printField(pd->data[i + j],
i == (PIN_COUNT - 1) ? '\n' : ',')) {
error("printField failed");
}
}
}
}
if ((millis() - tPct) > 1000) {
uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
uint8_t pct = binFile.curPosition() / (binFile.fileSize() / 100);
if (pct != lastPct) {
tPct = millis();
lastPct = pct;
@ -561,7 +566,7 @@ void binaryToCsv() {
error("close csvFile failed");
}
Serial.print(F("Done: "));
Serial.print(0.001*(millis() - t0));
Serial.print(0.001 * (millis() - t0));
Serial.println(F(" Seconds"));
}
//------------------------------------------------------------------------------
@ -619,7 +624,7 @@ bool createCsvFile() {
error("no dot in binName");
}
strcpy(dot + 1, "csv");
if (!csvFile.open(csvName, O_WRONLY|O_CREAT|O_TRUNC)) {
if (!csvFile.open(csvName, O_WRONLY | O_CREAT | O_TRUNC)) {
error("open csvFile failed");
}
Serial.print(F("Writing: "));
@ -632,7 +637,7 @@ bool createCsvFile() {
void logData() {
uint32_t t0;
uint32_t t1;
uint32_t overruns =0;
uint32_t overruns = 0;
uint32_t count = 0;
uint32_t maxLatencyUsec = 0;
size_t maxFifoUse = 0;
@ -676,7 +681,7 @@ void logData() {
if (m > maxLatencyUsec) {
maxLatencyUsec = m;
}
if (tmpFifoCount >maxFifoUse) {
if (tmpFifoCount > maxFifoUse) {
maxFifoUse = tmpFifoCount;
}
count += pBlock->count;
@ -726,9 +731,9 @@ void logData() {
Serial.print(F("Max write latency usec: "));
Serial.println(maxLatencyUsec);
Serial.print(F("Record time sec: "));
Serial.println(0.001*(t1 - t0), 3);
Serial.println(0.001 * (t1 - t0), 3);
Serial.print(F("Sample count: "));
Serial.println(count/PIN_COUNT);
Serial.println(count / PIN_COUNT);
Serial.print(F("Overruns: "));
Serial.println(overruns);
Serial.print(F("FIFO_DIM: "));
@ -767,13 +772,13 @@ void printData() {
return;
}
binFile.rewind();
if (binFile.read(&buf , sizeof(buf)) != sizeof(buf)) {
if (binFile.read(&buf, sizeof(buf)) != sizeof(buf)) {
error("Read metadata failed");
}
Serial.println(F("Type any character to stop"));
delay(1000);
while (!Serial.available() &&
binFile.read(&buf , sizeof(buf)) == sizeof(buf)) {
binFile.read(&buf, sizeof(buf)) == sizeof(buf)) {
if (buf.count == 0) {
break;
}
@ -783,7 +788,7 @@ void printData() {
}
for (size_t i = 0; i < buf.count; i++) {
Serial.print(buf.data[i], DEC);
if ((i+1)%PIN_COUNT) {
if ((i + 1) % PIN_COUNT) {
Serial.print(',');
} else {
Serial.println();
@ -795,7 +800,7 @@ void printData() {
//------------------------------------------------------------------------------
bool serialReadLine(char* str, size_t size) {
size_t n = 0;
while(!Serial.available()) {
while (!Serial.available()) {
}
while (true) {
int c = Serial.read();
@ -806,7 +811,8 @@ bool serialReadLine(char* str, size_t size) {
return false;
}
uint32_t m = millis();
while (!Serial.available() && (millis() - m) < 100){}
while (!Serial.available() && (millis() - m) < 100) {
}
if (!Serial.available()) break;
}
str[n] = 0;
@ -818,9 +824,11 @@ void setup(void) {
pinMode(ERROR_LED_PIN, OUTPUT);
}
Serial.begin(9600);
while(!Serial) {}
while (!Serial) {
}
Serial.println(F("Type any character to begin."));
while(!Serial.available()) {}
while (!Serial.available()) {
}
FillStack();
@ -828,8 +836,8 @@ void setup(void) {
analogRead(PIN_LIST[0]);
#if !ENABLE_DEDICATED_SPI
Serial.println(F(
"\nFor best performance edit SdFatConfig.h\n"
Serial.println(
F("\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
#endif // !ENABLE_DEDICATED_SPI
// Initialize SD.
@ -864,7 +872,7 @@ void loop(void) {
Serial.println(F("p - print data to Serial"));
Serial.println(F("r - record ADC data"));
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
char c = tolower(Serial.read());

View File

@ -28,7 +28,8 @@ File myFile;
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
#if USE_SD_H
Serial.println(F("Using SD.h. Set USE_SD_H zero to use SdFat.h."));

View File

@ -1,12 +1,12 @@
// Test and benchmark of the fast bufferedPrint class.
//
// Mainly for AVR but may improve print performance with other CPUs.
#include "SdFat.h"
#include "BufferedPrint.h"
#include "SdFat.h"
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 0
#define SD_FAT_TYPE 3
/*
Change the value of SD_CS_PIN if you are using SPI and
your hardware does not use the default value, SS.
@ -71,7 +71,7 @@ void benchmark() {
bp.begin(&file);
}
uint32_t t = millis();
switch(test) {
switch (test) {
case 0:
Serial.println(F("Test of println(uint16_t)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
@ -103,17 +103,16 @@ void benchmark() {
case 4:
Serial.println(F("Test of println(double)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println((double)0.01*i);
file.println((double)0.01 * i);
}
break;
case 5:
Serial.println(F("Test of printField(double, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField((double)0.01*i, '\n');
bp.printField((double)0.01 * i, '\n');
}
break;
}
if (test & 1) {
bp.sync();
@ -125,13 +124,13 @@ void benchmark() {
file.close();
t = millis() - t;
Serial.print(F("Time "));
Serial.print(0.001*t, 3);
Serial.print(0.001 * t, 3);
Serial.println(F(" sec"));
Serial.print(F("File size "));
Serial.print(0.001*s);
Serial.print(0.001 * s);
Serial.println(F(" KB"));
Serial.print(F("Write "));
Serial.print(s/t);
Serial.print(s / t);
Serial.println(F(" KB/sec"));
Serial.println();
}
@ -216,9 +215,11 @@ void testMemberFunctions() {
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
Serial.println("Type any character to begin.");
while(!Serial.available()) {}
while (!Serial.available()) {
}
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
@ -226,10 +227,10 @@ void setup() {
Serial.println(F("Test member funcions:"));
testMemberFunctions();
Serial.println();
Serial.println(F("Benchmark performance for uint16_t, uint32_t, and double:"));
Serial.println(
F("Benchmark performance for uint16_t, uint32_t, and double:"));
benchmark();
Serial.println("Done");
}
//------------------------------------------------------------------------------
void loop() {
}
void loop() {}

View File

@ -6,7 +6,7 @@
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 0
#define SD_FAT_TYPE 3
/*
Change the value of SD_CS_PIN if you are using SPI and
your hardware does not use the default value, SS.
@ -18,14 +18,14 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
const uint8_t SD_CS_PIN = 4;
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
const uint8_t SD_CS_PIN = 4;
#endif // SDCARD_SS_PIN
// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
#define SPI_CLOCK SD_SCK_MHZ(50)
#define SPI_CLOCK SD_SCK_MHZ(16)
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
@ -78,9 +78,8 @@ void setup() {
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
if (sd.exists("Folder1")
|| sd.exists("Folder1/file1.txt")
|| sd.exists("Folder1/File2.txt")) {
if (sd.exists("Folder1") || sd.exists("Folder1/file1.txt") ||
sd.exists("Folder1/File2.txt")) {
error("Please remove existing Folder1, file1.txt, and File2.txt");
}

View File

@ -3,9 +3,9 @@
//
// The maximum data rate will depend on the quality of your SD,
// the size of the FIFO, and using dedicated SPI.
#include "SdFat.h"
#include "FreeStack.h"
#include "ExFatLogger.h"
#include "FreeStack.h"
#include "SdFat.h"
//------------------------------------------------------------------------------
// This example was designed for exFAT but will support FAT16/FAT32.
// Note: Uno will not support SD_FAT_TYPE = 3.
@ -131,7 +131,7 @@ const uint64_t PREALLOCATE_SIZE = (uint64_t)PREALLOCATE_SIZE_MiB << 20;
// Max length of file name including zero byte.
#define FILE_NAME_DIM 40
// Max number of records to buffer while SD is busy.
const size_t FIFO_DIM = 512*FIFO_SIZE_SECTORS/sizeof(data_t);
const size_t FIFO_DIM = 512 * FIFO_SIZE_SECTORS / sizeof(data_t);
#if SD_FAT_TYPE == 0
typedef SdFat sd_t;
@ -197,16 +197,16 @@ void binaryToCsv() {
printRecord(&csvFile, nullptr);
while (!Serial.available() && binFile.available()) {
int nb = binFile.read(binData, sizeof(binData));
if (nb <= 0 ) {
if (nb <= 0) {
error("read binFile failed");
}
size_t nr = nb/sizeof(data_t);
size_t nr = nb / sizeof(data_t);
for (size_t i = 0; i < nr; i++) {
printRecord(&csvFile, &binData[i]);
}
if ((millis() - tPct) > 1000) {
uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
uint8_t pct = binFile.curPosition() / (binFile.fileSize() / 100);
if (pct != lastPct) {
tPct = millis();
lastPct = pct;
@ -221,7 +221,7 @@ void binaryToCsv() {
}
csvFile.close();
Serial.print(F("Done: "));
Serial.print(0.001*(millis() - t0));
Serial.print(0.001 * (millis() - t0));
Serial.println(F(" Seconds"));
}
//------------------------------------------------------------------------------
@ -302,7 +302,7 @@ void logData() {
uint16_t overrun = 0;
uint16_t maxOverrun = 0;
uint32_t totalOverrun = 0;
uint32_t fifoBuf[128*FIFO_SIZE_SECTORS];
uint32_t fifoBuf[128 * FIFO_SIZE_SECTORS];
data_t* fifoData = (data_t*)fifoBuf;
// Write dummy sector to start multi-block write.
@ -315,7 +315,8 @@ void logData() {
Serial.println(F("Type any character to stop"));
// Wait until SD is not busy.
while (sd.card()->isBusy()) {}
while (sd.card()->isBusy()) {
}
// Start time for log file.
uint32_t m = millis();
@ -370,9 +371,9 @@ void logData() {
if (!sd.card()->isBusy()) {
size_t nw = fifoHead > fifoTail ? fifoCount : FIFO_DIM - fifoTail;
// Limit write time by not writing more than 512 bytes.
const size_t MAX_WRITE = 512/sizeof(data_t);
const size_t MAX_WRITE = 512 / sizeof(data_t);
if (nw > MAX_WRITE) nw = MAX_WRITE;
size_t nb = nw*sizeof(data_t);
size_t nb = nw * sizeof(data_t);
uint32_t usec = micros();
if (nb != binFile.write(fifoData + fifoTail, nb)) {
error("write binFile failed");
@ -392,7 +393,7 @@ void logData() {
}
}
Serial.print(F("\nLog time: "));
Serial.print(0.001*(millis() - m));
Serial.print(0.001 * (millis() - m));
Serial.println(F(" Seconds"));
binFile.truncate();
binFile.sync();
@ -469,7 +470,7 @@ void printUnusedStack() {
//------------------------------------------------------------------------------
bool serialReadLine(char* str, size_t size) {
size_t n = 0;
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
while (true) {
@ -481,7 +482,8 @@ bool serialReadLine(char* str, size_t size) {
return false;
}
uint32_t m = millis();
while (!Serial.available() && (millis() - m) < 100){}
while (!Serial.available() && (millis() - m) < 100) {
}
if (!Serial.available()) break;
}
str[n] = 0;
@ -525,8 +527,8 @@ void setup() {
}
FillStack();
#if !ENABLE_DEDICATED_SPI
Serial.println(F(
"\nFor best performance edit SdFatConfig.h\n"
Serial.println(
F("\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
#endif // !ENABLE_DEDICATED_SPI
@ -567,7 +569,7 @@ void loop() {
Serial.println(F("p - print data to Serial"));
Serial.println(F("r - record data"));
Serial.println(F("t - test without logging"));
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
char c = tolower(Serial.read());

View File

@ -14,7 +14,8 @@ File file;
#include "SdFat.h"
// Setting ENABLE_DEDICATED_SPI to zero saves over 200 more bytes.
#if ENABLE_DEDICATED_SPI
#warning "Set ENABLE_DEDICATED_SPI zero in SdFat/src/SdFatConfig.h for minimum size"
#warning \
"Set ENABLE_DEDICATED_SPI zero in SdFat/src/SdFatConfig.h for minimum size"
#endif // ENABLE_DEDICATED_SPI
// Insure FAT16/FAT32 only.
SdFat32 SD;
@ -24,17 +25,19 @@ FatFile file;
void error(const char* msg) {
Serial.println(msg);
while(true);
while (true) {
}
}
void setup() {
int n;
char buf[4];
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
Serial.println("Type any character to begin");
while (!Serial.available()) {}
while (!Serial.available()) {
}
if (!SD.begin(CS_PIN)) error("SD.begin");
@ -49,10 +52,9 @@ void setup() {
while ((n = file.read(buf, sizeof(buf)))) {
Serial.write(buf, n);
}
// close() is only needed if you write to the file. For example, read
// config data, modify the data, rewind the file and write the data.
// file.close();
// close() is only needed if you write to the file. For example, read
// config data, modify the data, rewind the file and write the data.
// file.close();
}
void loop() {
}
void loop() {}

View File

@ -5,7 +5,7 @@
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 0
#define SD_FAT_TYPE 3
/*
Change the value of SD_CS_PIN if you are using SPI and
your hardware does not use the default value, SS.
@ -17,14 +17,14 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
const uint8_t SD_CS_PIN = 4;
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
const uint8_t SD_CS_PIN = 4;
#endif // SDCARD_SS_PIN
// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
#define SPI_CLOCK SD_SCK_MHZ(50)
#define SPI_CLOCK SD_SCK_MHZ(30)
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
@ -75,8 +75,12 @@ void setup() {
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
}
//------------------------------------------------------------------------------
void loop() {
// Open root directory
if (!dir.open("/")){
if (!dir.open("/")) {
error("dir.open failed");
}
// Open next file in root.
@ -100,6 +104,7 @@ void setup() {
} else {
Serial.println("Done!");
}
}
//------------------------------------------------------------------------------
void loop() {}
dir.close();
delay(2000);
}

Some files were not shown because too many files have changed in this diff Show More