-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRtc.cpp
145 lines (123 loc) · 4.4 KB
/
Rtc.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "Rtc.hpp"
#include <ESP8266WiFi.h>
extern rtc::RtcMem RTC{};
namespace rtc
{
/**
* @brief Calculates CRC from given data
*
* @param data_ptr - pointer to data, from which CRC code will be calculated
* @param length - size of data, from which CRC code will be calculated
* @return uint32_t with calculated crc code
*/
const uint32_t RtcMem::calcCRC32(const uint8_t *data_ptr, size_t length)
{
uint32_t crc = 0xffffffff;
while(length--)
{
uint8_t c = *data_ptr++;
for(uint32_t i = 0x80; i > 0; i >>= 1)
{
bool bit = crc & 0x80000000;
if(c & i)
{
bit = !bit;
}
crc <<= 1;
if(bit)
{
crc ^= 0x04c11db7;
}
}
}
return crc;
}
/**
* @brief Reads Data Saved in RTC Memory and overwrites current temporary rtc_data structure
* @note To check if data has been read succesfully - use RtcMem::isValid();
*/
void RtcMem::readMem()
{
#ifdef DEBUG
Serial.println("Reading RTC MEMORY");
#endif //DEBUG
is_rtc_valid = false;
if(ESP.rtcUserMemoryRead(0, (uint32_t*) &rtc_data, sizeof(rtc_data)))
{
uint32_t crc = calcCRC32(((uint8_t*) &rtc_data) + 4, sizeof( rtc_data ) - 4); //CRC for RTC MEMORY except 4 bytes with CRC itself
if( crc == rtc_data.crc32 )
{
is_rtc_valid = true;
}
}
}
/**
* @brief Save rtc_data(Current settings) in RTC Memory
* @return information if opeartion was done successfully
*/
const bool RtcMem::saveToMem()
{
#ifdef DEBUG
Serial.println("Saving to RTC MEMORY");
#endif //DEBUG
rtc_data.channel = WiFi.channel();
memcpy(rtc_data.bssid, WiFi.BSSID(), 6); // Copy 6 bytes of BSSID (Mac Address of AP)
rtc_data.crc32 = calcCRC32(((uint8_t*) &rtc_data) + 4, sizeof( rtc_data ) - 4); //CRC of data to save
return ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtc_data, sizeof(rtc_data));
}
/**
* @brief Save rtc_data(Current settings and data to be saved) in RTC Memory
* @param data - data that will be set as user last data in RTC Memory
* @return information if opeartion was done successfully
*/
const bool RtcMem::saveToMemData(const RTC_mem_t &data)
{
rtc_data.last_data = data;
return saveToMem();
}
/**
* @brief Performs operation of deepSleep after Error. Before that saves current settings to RTC Memory
* @param error_code - Sets last error. If there's no Error - use RtcMem::deepSleep()
* @param time_us - Sleep duration in microseconds. Default is 10 s - It's enough to wait for Watchdog to reset (if enabled).
*/
void RtcMem::deepSleepErr(const ErrorCode &error_code, const uint64_t time_us)
{
#ifdef DEBUG
Serial.print("Going to sleep: ");
Serial.print(time_us);
Serial.println("us");
#endif //DEBUG
rtc_data.last_error = error_code;
saveToMem();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin();
delay(1);
// ESP.deepSleep( time_us, WAKE_RF_DISABLED ); //That option should be more power saving. Unfortunately it took too much time in NodeMCU to reconnect after use that
ESP.deepSleep(time_us, WAKE_NO_RFCAL);
}
/**
* @brief Performs operation of deepSleep without any Error. Before that saves current settings to RTC Memory
* @param time_us - Sleep duration in microseconds. Default is 10 s - It's enough to wait for Watchdog to reset (if enabled).
*/
void RtcMem::deepSleep(const uint64_t time_us)
{
deepSleepErr(ErrorCode::NONE, time_us);
}
/**
* @brief Getter for RTC_Data_t struct
* @return read-only structure with RTC Data
*/
const RtcData_t RtcMem::getData() const
{
return rtc_data;
}
/**
* @brief Validation of RTC Data. This is used to make sure that Memory has been already and successfully read
* @return True if read RTC Memory is valid.
*/
const bool RtcMem::isValid() const
{
return is_rtc_valid;
}
}//namespace rtc