Soldered SD Card Arduino Library 1.0.0
Easily read and write files to and form the SD card breakout! A fork of the original SDFat library by Bill Greiman.
Loading...
Searching...
No Matches
RingBuf.h
Go to the documentation of this file.
1
25#ifndef RingBuf_h
26#define RingBuf_h
31#include "Arduino.h"
32#include "common/FmtNumber.h"
33
34#ifndef DOXYGEN_SHOULD_SKIP_THIS
35// Teensy 3.5/3.6 has hard fault at 0x20000000 for unaligned memcpy.
36#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
37inline bool is_aligned(const void *ptr, uintptr_t alignment)
38{
39 auto iptr = reinterpret_cast<uintptr_t>(ptr);
40 return !(iptr % alignment);
41}
42inline void memcpyBuf(void *dst, const void *src, size_t len)
43{
44 const uint8_t *b = reinterpret_cast<const uint8_t *>(0X20000000UL);
45 uint8_t *d = reinterpret_cast<uint8_t *>(dst);
46 const uint8_t *s = reinterpret_cast<const uint8_t *>(src);
47 if ((is_aligned(d, 4) && is_aligned(s, 4) && (len & 3) == 0) ||
48 !((d < b && b <= (d + len)) || (s < b && b <= (s + len))))
49 {
50 memcpy(dst, src, len);
51 }
52 else
53 {
54 while (len--)
55 {
56 *d++ = *s++;
57 }
58 }
59}
60#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
61inline void memcpyBuf(void *dst, const void *src, size_t len)
62{
63 memcpy(dst, src, len);
64}
65#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
66#endif // DOXYGEN_SHOULD_SKIP_THIS
79template <class F, size_t Size> class RingBuf : public Print
80{
81 public:
86 {
87 }
92 void begin(F *file)
93 {
94 m_file = file;
95 m_count = 0;
96 m_head = 0;
97 m_tail = 0;
98 clearWriteError();
99 }
104 size_t bytesFree() const
105 {
106 size_t count;
107 noInterrupts();
108 count = m_count;
109 interrupts();
110 return Size - count;
111 }
115 size_t bytesFreeIsr() const
116 {
117 return Size - m_count;
118 }
122 size_t bytesUsed() const
123 {
124 size_t count;
125 noInterrupts();
126 count = m_count;
127 interrupts();
128 return count;
129 }
133 size_t bytesUsedIsr() const
134 {
135 return m_count;
136 }
149 size_t memcpyIn(const void *buf, size_t count)
150 {
151 const uint8_t *src = (const uint8_t *)buf;
152 size_t n = Size - m_count;
153 if (count > n)
154 {
155 count = n;
156 }
157 size_t nread = 0;
158 while (nread != count)
159 {
160 n = minSize(Size - m_head, count - nread);
161 memcpyBuf(m_buf + m_head, src + nread, n);
162 m_head = advance(m_head, n);
163 nread += n;
164 }
165 m_count += nread;
166 return nread;
167 }
180 size_t memcpyOut(void *buf, size_t count)
181 {
182 uint8_t *dst = reinterpret_cast<uint8_t *>(buf);
183 size_t nwrite = 0;
184 size_t n = m_count;
185 if (count > n)
186 {
187 count = n;
188 }
189 while (nwrite != count)
190 {
191 n = minSize(Size - m_tail, count - nwrite);
192 memcpyBuf(dst + nwrite, m_buf + m_tail, n);
193 m_tail = advance(m_tail, n);
194 nwrite += n;
195 }
196 m_count -= nwrite;
197 return nwrite;
198 }
205 size_t printField(double value, char term, uint8_t prec = 2)
206 {
207 char buf[24];
208 char *str = buf + sizeof(buf);
209 if (term)
210 {
211 *--str = term;
212 if (term == '\n')
213 {
214 *--str = '\r';
215 }
216 }
217 str = fmtDouble(str, value, prec, false);
218 return write(str, buf + sizeof(buf) - str);
219 }
226 size_t printField(float value, char term, uint8_t prec = 2)
227 {
228 return printField(static_cast<double>(value), term, prec);
229 }
235 template <typename Type> size_t printField(Type value, char term)
236 {
237 char sign = 0;
238 char buf[3 * sizeof(Type) + 3];
239 char *str = buf + sizeof(buf);
240
241 if (term)
242 {
243 *--str = term;
244 if (term == '\n')
245 {
246 *--str = '\r';
247 }
248 }
249 if (value < 0)
250 {
251 value = -value;
252 sign = '-';
253 }
254 if (sizeof(Type) < 4)
255 {
256 str = fmtBase10(str, (uint16_t)value);
257 }
258 else
259 {
260 str = fmtBase10(str, (uint32_t)value);
261 }
262 if (sign)
263 {
264 *--str = sign;
265 }
266 return write((const uint8_t *)str, &buf[sizeof(buf)] - str);
267 }
279 size_t readIn(size_t count)
280 {
281 size_t nread = 0;
282 size_t n = bytesFree(); // Protected from interrupts.
283 if (count > n)
284 {
285 count = n;
286 }
287 while (nread != count)
288 {
289 n = minSize(Size - m_head, count - nread);
290 if ((size_t)m_file->read(m_buf + m_head, n) != n)
291 {
292 return nread;
293 }
294 m_head = advance(m_head, n);
295 nread += n;
296 }
297 noInterrupts();
298 m_count += nread;
299 interrupts();
300 return nread;
301 }
307 bool sync()
308 {
309 size_t n = bytesUsed();
310 return writeOut(n) == n;
311 }
324 size_t write(const void *buf, size_t count)
325 {
326 if (count > bytesFree())
327 {
328 setWriteError();
329 }
330 return memcpyIn(buf, count);
331 }
339 size_t write(const uint8_t *buf, size_t count) override
340 {
341 return write((const void *)buf, count);
342 }
348 size_t write(uint8_t data) override
349 {
350 return write(&data, 1);
351 }
364 size_t writeOut(size_t count)
365 {
366 size_t n = bytesUsed(); // Protected from interrupts;
367 if (count > n)
368 {
369 count = n;
370 }
371 size_t nwrite = 0;
372 while (nwrite != count)
373 {
374 n = minSize(Size - m_tail, count - nwrite);
375 if (m_file->write(m_buf + m_tail, n) != n)
376 {
377 break;
378 }
379 m_tail = advance(m_tail, n);
380 nwrite += n;
381 }
382 noInterrupts();
383 m_count -= nwrite;
384 interrupts();
385 return nwrite;
386 }
387
388 private:
389 uint8_t __attribute__((aligned(4))) m_buf[Size];
390 F *m_file = nullptr;
391 volatile size_t m_count;
392 size_t m_head;
393 size_t m_tail;
394
395 size_t advance(size_t index, size_t n)
396 {
397 index += n;
398 return index < Size ? index : index - Size;
399 }
400 // avoid macro MIN
401 size_t minSize(size_t a, size_t b)
402 {
403 return a < b ? a : b;
404 }
405};
406#endif // RingBuf_h
char * fmtDouble(char *str, double num, uint8_t prec, bool altFmt)
Definition FmtNumber.cpp:262
char * fmtBase10(char *str, uint16_t n)
Definition FmtNumber.cpp:163
bool is_aligned(const void *ptr, uintptr_t alignment)
Definition RingBuf.h:37
void memcpyBuf(void *dst, const void *src, size_t len)
Definition RingBuf.h:42
size_t memcpyIn(const void *buf, size_t count)
Definition RingBuf.h:149
void begin(F *file)
Definition RingBuf.h:92
RingBuf()
Definition RingBuf.h:85
size_t writeOut(size_t count)
Definition RingBuf.h:364
size_t bytesFree() const
Definition RingBuf.h:104
size_t write(uint8_t data) override
Definition RingBuf.h:348
size_t readIn(size_t count)
Definition RingBuf.h:279
size_t write(const void *buf, size_t count)
Definition RingBuf.h:324
size_t minSize(size_t a, size_t b)
Definition RingBuf.h:401
size_t bytesUsedIsr() const
Definition RingBuf.h:133
size_t printField(Type value, char term)
Definition RingBuf.h:235
size_t printField(float value, char term, uint8_t prec=2)
Definition RingBuf.h:226
size_t printField(double value, char term, uint8_t prec=2)
Definition RingBuf.h:205
size_t bytesUsed() const
Definition RingBuf.h:122
size_t memcpyOut(void *buf, size_t count)
Definition RingBuf.h:180
bool sync()
Definition RingBuf.h:307
uint8_t __attribute__((aligned(4))) m_buf[Size]
size_t write(const uint8_t *buf, size_t count) override
Definition RingBuf.h:339
size_t bytesFreeIsr() const
Definition RingBuf.h:115
static bool value
Definition DigitalPin.h:210