-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSDLog.cpp
More file actions
232 lines (215 loc) · 6.18 KB
/
Copy pathSDLog.cpp
File metadata and controls
232 lines (215 loc) · 6.18 KB
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include "global.h"
#include "SDlog.h"
#define SD_CS_PIN 10 //CS pin of the SD card
#define INDEX_FILE_NAME F("i")
#define RECS_PER_FILE 1000 //records per file
#define MAX_FILES_COUNT 4000 //this results in less than 1 gig in the total files size and stores data for 10 years of continous operation - seems appropriate
#define DEBUG
File file;
//number of current file being written, initial value means it's not initialized yet
uint16_t curFileNum = 0xFFFF;
uint32_t lastLogIdx = 0xFFFFFFFF;
bool updateIndexFile()
{
SD.remove(INDEX_FILE_NAME);
file = SD.open(INDEX_FILE_NAME, FILE_WRITE);
if (!file) {
#ifdef DEBUG
Serial.println(F("SD: error index writing"));
#endif
return false;
}
file.write((uint8_t*)&curFileNum,2);
file.close();
return true;
}
bool ensureInit() {
if (curFileNum == 0xFFFF) {
#ifdef DEBUG
Serial.println(F("SD: initializing"));
#endif
if (!SD.begin(SD_CS_PIN)) {
#ifdef DEBUG
Serial.println(F("SD: init error"));
#endif
return false;
}
if (!SD.exists(INDEX_FILE_NAME)) {
#ifdef DEBUG
Serial.println(F("SD: no index file, initializing"));
#endif
curFileNum = 0;
if (!updateIndexFile()) {
return false;
}
} else {
#ifdef DEBUG
Serial.println(F("SD: read index file"));
#endif
file = SD.open(INDEX_FILE_NAME, FILE_READ);
if (!file) {
#ifdef DEBUG
Serial.println(F("SD: error index reading"));
#endif
return false;
}
file.read(&curFileNum,2);
file.close();
#ifdef DEBUG
Serial.print(F("SD: index read:"));Serial.println(curFileNum);
#endif
}
}
return true;
}
bool writeLog(DLog* rec)
{
if (!ensureInit()) {
return false;
}
String fname = String(curFileNum);
long filesize = 0;
if (SD.exists(fname)) {
file = SD.open(fname,FILE_READ);
if (!file) {
#ifdef DEBUG
Serial.print(F("SD: error opening log "));Serial.println(curFileNum);
#endif
return false;
}
filesize = file.size();
file.close();
if (filesize >= sizeof(DLog)*RECS_PER_FILE) {
//assume file counter never overruns. once data is written every 10 seconds and single file has 10000 records, 16-bit number should overrun in almost 200 years of continous operation
curFileNum++;
fname = String(curFileNum);
if (SD.exists(fname)) {
SD.remove(fname);
}
filesize = 0;
#ifdef DEBUG
Serial.print(F("SD: increasing file count to "));Serial.println(curFileNum);
#endif
if (!updateIndexFile()) {
return false;
}
#ifdef DEBUG
Serial.print(F("SD: checking file count "));Serial.print(curFileNum);Serial.print('/');Serial.println(MAX_FILES_COUNT);
#endif
if (curFileNum >= MAX_FILES_COUNT) {
#ifdef DEBUG
Serial.print(F("SD: removing tail file "));Serial.println(curFileNum - MAX_FILES_COUNT);
#endif
if (!SD.remove(String(curFileNum - MAX_FILES_COUNT))) {
#ifdef DEBUG
Serial.println(F("SD: error removing tail file"));
#endif
}
}
}//end if file overrun
}//end if file exists
file = SD.open(fname,FILE_WRITE);
if (!file) {
#ifdef DEBUG
Serial.print(F("SD: error writing log "));Serial.println(curFileNum);
#endif
return false;
}
file.write((uint8_t*)rec, sizeof(DLog));
file.close();
lastLogIdx = curFileNum * RECS_PER_FILE + filesize / sizeof(DLog);
#ifdef DEBUG
Serial.print(F("SD: written rec #"));Serial.print(lastLogIdx);Serial.print(F(" to file #"));Serial.println(curFileNum);
#endif
return true;
}
//resets file number so that all previous content of SD card starts being overwritten anew
void sdReset() {
curFileNum = 0;
updateIndexFile();
String fname = String(curFileNum);
if (SD.exists(fname)) {
SD.remove(fname);
}
#ifdef DEBUG
Serial.println(F("SD: reset done "));
#endif
}
void sdTransmitData() {
uint32_t cIdx = *((uint32_t*) (buf + 3));
uint32_t toIdx = *((uint32_t*) (buf + 7));
int fileIdx = cIdx / RECS_PER_FILE;
int recIdx = cIdx % RECS_PER_FILE;
#ifdef DEBUG
Serial.print(F("SD: read data request"));Serial.print(cIdx);Serial.print('-');Serial.print(toIdx);Serial.print(F(", file/rec="));Serial.print(fileIdx);Serial.print('/');Serial.println(recIdx);
#endif
//once I uncomment one of these lines below, the receiving data by bluetooth stops working!
//I don't know WTF is here
if (lastLogIdx == 0xFFFFFFFF) {
#ifdef DEBUG
// Serial.println(F("SD: read data request rejected, no data (yet)"));
#endif
// return;
}
lcd.clear();
btSerial.write(buf,11);
long lastmst = millis() - 10000;
bool firstRecord = true;
String fname = String(fileIdx);
while (cIdx <= toIdx) {
if (firstRecord) {
// the very first record for transmitting
#ifdef DEBUG
// Serial.print(F("SD: opening first file / at pos:"));Serial.print(fname);Serial.print('/');Serial.println(recIdx * sizeof(DLog));
#endif
file = SD.open(fname, FILE_READ);
if (!file) {
#ifdef DEBUG
Serial.print(F("SD: error opening file for transmitting: "));Serial.println(fname);
#endif
return;
}
if (!file.seek(recIdx * sizeof(DLog))) {
#ifdef DEBUG
Serial.print(F("SD: error seeking file to "));Serial.println(recIdx * sizeof(DLog));
#endif
return;
}
}
firstRecord = false;
//transmitting the record
if (file.read(buf, sizeof(DLog))) {
btSerial.write(buf, sizeof(DLog));
if (millis() > lastmst + 500) {
lcd.setCursor(0,0);
lcd.print(cIdx);lcd.print('/');lcd.print(toIdx);
lastmst = millis();
}
} else {
#ifdef DEBUG
Serial.print(F("SD: error reading file "));Serial.println(fname);
#endif
return;
}
recIdx++;
if (recIdx >= RECS_PER_FILE) {
//jumping to the next file
file.close();
fileIdx++;
fname = String(fileIdx);
file = SD.open(fname, FILE_READ);
recIdx = 0;
#ifdef DEBUG
// Serial.print(F("SD: Jumping to next file "));Serial.println(fname);
#endif
}
cIdx++;
}
file.close();
#ifdef DEBUG
// Serial.println(F("SD: Transmission done "));
#endif
}