Skip to content

Commit d3442a4

Browse files
authored
Merge pull request #104 from LeeLeahy2/webserver
Add the WebServer test sketch
2 parents 31db4df + 29a6527 commit d3442a4

File tree

4 files changed

+512
-0
lines changed

4 files changed

+512
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
const int pin_microSD_CS = 25;
2+
3+
typedef struct struct_settings {
4+
bool enableSD = true;
5+
uint16_t spiFrequency = 16; //By default, use 16MHz SPI
6+
} Settings;
7+
8+
Settings settings;
9+
10+
const TickType_t fatSemaphore_shortWait_ms = 10 / portTICK_PERIOD_MS;
11+
const TickType_t fatSemaphore_longWait_ms = 200 / portTICK_PERIOD_MS;
12+
SemaphoreHandle_t xFATSemaphore;
13+
14+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
15+
void displaySDFail(uint16_t displayTime)
16+
{
17+
Serial.println ("SD card failed to initialize!");
18+
}
19+
20+
//Create a test file in file structure to make sure we can
21+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
22+
bool createTestFile()
23+
{
24+
SdFile testFile;
25+
char testFileName[40] = "testfile.txt";
26+
27+
if (xFATSemaphore == NULL)
28+
{
29+
log_d("xFATSemaphore is Null");
30+
return (false);
31+
}
32+
33+
//Attempt to write to file system. This avoids collisions with file writing from other functions like recordSystemSettingsToFile() and F9PSerialReadTask()
34+
if (xSemaphoreTake(xFATSemaphore, fatSemaphore_shortWait_ms) == pdPASS)
35+
{
36+
if (testFile.open(testFileName, O_CREAT | O_APPEND | O_WRITE) == true)
37+
{
38+
testFile.close();
39+
40+
if (sd.exists(testFileName))
41+
sd.remove(testFileName);
42+
xSemaphoreGive(xFATSemaphore);
43+
return (true);
44+
}
45+
xSemaphoreGive(xFATSemaphore);
46+
}
47+
48+
return (false);
49+
}
50+
51+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
52+
void beginSD()
53+
{
54+
pinMode(pin_microSD_CS, OUTPUT);
55+
digitalWrite(pin_microSD_CS, HIGH); //Be sure SD is deselected
56+
57+
if (settings.enableSD == true)
58+
{
59+
//Do a quick test to see if a card is present
60+
int tries = 0;
61+
int maxTries = 5;
62+
while (tries < maxTries)
63+
{
64+
if (sdPresent() == true) break;
65+
log_d("SD present failed. Trying again %d out of %d", tries + 1, maxTries);
66+
67+
//Max power up time is 250ms: https://www.kingston.com/datasheets/SDCIT-specsheet-64gb_en.pdf
68+
//Max current is 200mA average across 1s, peak 300mA
69+
delay(10);
70+
tries++;
71+
}
72+
if (tries == maxTries) return;
73+
74+
//If an SD card is present, allow SdFat to take over
75+
log_d("SD card detected");
76+
77+
if (settings.spiFrequency > 16)
78+
{
79+
Serial.println("Error: SPI Frequency out of range. Default to 16MHz");
80+
settings.spiFrequency = 16;
81+
}
82+
83+
if (sd.begin(SdSpiConfig(pin_microSD_CS, SHARED_SPI, SD_SCK_MHZ(settings.spiFrequency))) == false)
84+
{
85+
tries = 0;
86+
maxTries = 1;
87+
for ( ; tries < maxTries ; tries++)
88+
{
89+
log_d("SD init failed. Trying again %d out of %d", tries + 1, maxTries);
90+
91+
delay(250); //Give SD more time to power up, then try again
92+
if (sd.begin(SdSpiConfig(pin_microSD_CS, SHARED_SPI, SD_SCK_MHZ(settings.spiFrequency))) == true) break;
93+
}
94+
95+
if (tries == maxTries)
96+
{
97+
Serial.println(F("SD init failed. Is card present? Formatted?"));
98+
digitalWrite(pin_microSD_CS, HIGH); //Be sure SD is deselected
99+
online.microSD = false;
100+
return;
101+
}
102+
}
103+
104+
//Change to root directory. All new file creation will be in root.
105+
if (sd.chdir() == false)
106+
{
107+
Serial.println(F("SD change directory failed"));
108+
online.microSD = false;
109+
return;
110+
}
111+
112+
//Setup FAT file access semaphore
113+
if (xFATSemaphore == NULL)
114+
{
115+
xFATSemaphore = xSemaphoreCreateMutex();
116+
if (xFATSemaphore != NULL)
117+
xSemaphoreGive(xFATSemaphore); //Make the file system available for use
118+
}
119+
120+
if (createTestFile() == false)
121+
{
122+
Serial.println(F("Failed to create test file. Format SD card with 'SD Card Formatter'."));
123+
displaySDFail(5000);
124+
online.microSD = false;
125+
return;
126+
}
127+
128+
online.microSD = true;
129+
130+
Serial.println(F("microSD online"));
131+
}
132+
else
133+
{
134+
online.microSD = false;
135+
}
136+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
void printIpAddress(IPAddress ip) {
2+
3+
// Display the IP address
4+
Serial.println(ip);
5+
}
6+
7+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
8+
void printWiFiGatewayIp() {
9+
10+
// Display the subnet mask
11+
Serial.print ("Gateway: ");
12+
IPAddress ip = WiFi.gatewayIP();
13+
printIpAddress(ip);
14+
}
15+
16+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
17+
void printWiFiIpAddress() {
18+
19+
// Display the IP address
20+
Serial.print ("IP Address: ");
21+
IPAddress ip = WiFi.localIP();
22+
printIpAddress(ip);
23+
}
24+
25+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
26+
void printWiFiMacAddress() {
27+
// Display the MAC address
28+
byte mac[6];
29+
WiFi.macAddress(mac);
30+
Serial.print("MAC address: ");
31+
Serial.print(mac[5], HEX);
32+
Serial.print(":");
33+
Serial.print(mac[4], HEX);
34+
Serial.print(":");
35+
Serial.print(mac[3], HEX);
36+
Serial.print(":");
37+
Serial.print(mac[2], HEX);
38+
Serial.print(":");
39+
Serial.print(mac[1], HEX);
40+
Serial.print(":");
41+
Serial.println(mac[0], HEX);
42+
}
43+
44+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
45+
void printWiFiNetwork() {
46+
47+
// Display the SSID
48+
Serial.print("SSID: ");
49+
Serial.println(WiFi.SSID());
50+
51+
// Display the receive signal strength
52+
long rssi = WiFi.RSSI();
53+
Serial.print("Signal strength (RSSI):");
54+
Serial.println(rssi);
55+
}
56+
57+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
58+
void printWiFiSubnetMask() {
59+
60+
// Display the subnet mask
61+
Serial.print ("Subnet Mask: ");
62+
IPAddress ip = WiFi.subnetMask();
63+
printIpAddress(ip);
64+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
These are low level functions to aid in detecting whether a card is present or not.
3+
Because of ESP32 v2 core, SdFat can only operate using Shared SPI. This makes the sd.begin test take over 1s
4+
which causes the RTK product to boot slowly. To circumvent this, we will ping the SD card directly to see if it responds.
5+
Failures take 2ms, successes take 1ms.
6+
7+
From Prototype puzzle: https://github.com/sparkfunX/ThePrototype/blob/master/Firmware/TestSketches/sdLocker/sdLocker.ino
8+
License: Public domain. This code is based on Karl Lunt's work: https://www.seanet.com/~karllunt/sdlocker2.html
9+
*/
10+
11+
//Define commands for the SD card
12+
#define SD_GO_IDLE (0x40 + 0) // CMD0 - go to idle state
13+
#define SD_INIT (0x40 + 1) // CMD1 - start initialization
14+
#define SD_SEND_IF_COND (0x40 + 8) // CMD8 - send interface (conditional), works for SDHC only
15+
#define SD_SEND_STATUS (0x40 + 13) // CMD13 - send card status
16+
#define SD_SET_BLK_LEN (0x40 + 16) // CMD16 - set length of block in bytes
17+
#define SD_LOCK_UNLOCK (0x40 + 42) // CMD42 - lock/unlock card
18+
#define CMD55 (0x40 + 55) // multi-byte preface command
19+
#define SD_READ_OCR (0x40 + 58) // read OCR
20+
#define SD_ADV_INIT (0xc0 + 41) // ACMD41, for SDHC cards - advanced start initialization
21+
22+
//Define options for accessing the SD card's PWD (CMD42)
23+
#define MASK_ERASE 0x08 //erase the entire card
24+
#define MASK_LOCK_UNLOCK 0x04 //lock or unlock the card with password
25+
#define MASK_CLR_PWD 0x02 //clear password
26+
#define MASK_SET_PWD 0x01 //set password
27+
28+
//Define bit masks for fields in the lock/unlock command (CMD42) data structure
29+
#define SET_PWD_MASK (1<<0)
30+
#define CLR_PWD_MASK (1<<1)
31+
#define LOCK_UNLOCK_MASK (1<<2)
32+
#define ERASE_MASK (1<<3)
33+
34+
//Begin initialization by sending CMD0 and waiting until SD card
35+
//responds with In Idle Mode (0x01). If the response is not 0x01
36+
//within a reasonable amount of time, there is no SD card on the bus.
37+
//Returns false if not card is detected
38+
//Returns true if a card responds
39+
bool sdPresent(void)
40+
{
41+
byte response = 0;
42+
43+
SPI.begin();
44+
SPI.setClockDivider(SPI_CLOCK_DIV2);
45+
SPI.setDataMode(SPI_MODE0);
46+
SPI.setBitOrder(MSBFIRST);
47+
pinMode(pin_microSD_CS, OUTPUT);
48+
49+
//Sending clocks while card power stabilizes...
50+
deselectCard(); // always make sure
51+
for (byte i = 0; i < 30; i++) // send several clocks while card power stabilizes
52+
xchg(0xff);
53+
54+
//Sending CMD0 - GO IDLE...
55+
for (byte i = 0; i < 0x10; i++) //Attempt to go idle
56+
{
57+
response = sdSendCommand(SD_GO_IDLE, 0); // send CMD0 - go to idle state
58+
if (response == 1) break;
59+
}
60+
if (response != 1) return (false); //Card failed to respond to idle
61+
62+
return (true);
63+
}
64+
65+
/*
66+
sdSendCommand send raw command to SD card, return response
67+
68+
This routine accepts a single SD command and a 4-byte argument. It sends
69+
the command plus argument, adding the appropriate CRC. It then returns
70+
the one-byte response from the SD card.
71+
72+
For advanced commands (those with a command byte having bit 7 set), this
73+
routine automatically sends the required preface command (CMD55) before
74+
sending the requested command.
75+
76+
Upon exit, this routine returns the response byte from the SD card.
77+
Possible responses are:
78+
0xff No response from card; card might actually be missing
79+
0x01 SD card returned 0x01, which is OK for most commands
80+
0x?? other responses are command-specific
81+
*/
82+
byte sdSendCommand(byte command, unsigned long arg)
83+
{
84+
byte response;
85+
86+
if (command & 0x80) // special case, ACMD(n) is sent as CMD55 and CMDn
87+
{
88+
command &= 0x7f; // strip high bit for later
89+
response = sdSendCommand(CMD55, 0); // send first part (recursion)
90+
if (response > 1) return (response);
91+
}
92+
93+
deselectCard();
94+
xchg(0xFF);
95+
selectCard(); // enable CS
96+
xchg(0xFF);
97+
98+
xchg(command | 0x40); // command always has bit 6 set!
99+
xchg((byte)(arg >> 24)); // send data, starting with top byte
100+
xchg((byte)(arg >> 16));
101+
xchg((byte)(arg >> 8));
102+
xchg((byte)(arg & 0xFF));
103+
104+
byte crc = 0x01; // good for most cases
105+
if (command == SD_GO_IDLE) crc = 0x95; // this will be good enough for most commands
106+
if (command == SD_SEND_IF_COND) crc = 0x87; // special case, have to use different CRC
107+
xchg(crc); // send final byte
108+
109+
for (int i = 0; i < 30; i++) // loop until timeout or response
110+
{
111+
response = xchg(0xFF);
112+
if ((response & 0x80) == 0) break; // high bit cleared means we got a response
113+
}
114+
115+
/*
116+
We have issued the command but the SD card is still selected. We
117+
only deselectCard the card if the command we just sent is NOT a command
118+
that requires additional data exchange, such as reading or writing
119+
a block.
120+
*/
121+
if ((command != SD_READ_OCR) &&
122+
(command != SD_SEND_STATUS) &&
123+
(command != SD_SEND_IF_COND) &&
124+
(command != SD_LOCK_UNLOCK))
125+
{
126+
deselectCard(); // all done
127+
xchg(0xFF); // close with eight more clocks
128+
}
129+
130+
return (response); // let the caller sort it out
131+
}
132+
133+
//Select (enable) the SD card
134+
void selectCard(void)
135+
{
136+
digitalWrite(pin_microSD_CS, LOW);
137+
}
138+
139+
//Deselect (disable) the SD card
140+
void deselectCard(void)
141+
{
142+
digitalWrite(pin_microSD_CS, HIGH);
143+
}
144+
145+
//Exchange a byte of data with the SD card via host's SPI bus
146+
byte xchg(byte val)
147+
{
148+
byte receivedVal = SPI.transfer(val);
149+
return receivedVal;
150+
}

0 commit comments

Comments
 (0)