rtcfifo.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the
  13. * distribution.
  14. * - Neither the name of the copyright holders nor the names of
  15. * its contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  29. * OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * @author Bernd Meyer <bmeyer@dius.com.au>
  32. */
  33. #ifndef _RTCFIFO_H_
  34. #define _RTCFIFO_H_
  35. #include "rtcaccess.h"
  36. #include "rtctime.h"
  37. // 1: measurement alignment, in microseconds
  38. // 2: timestamp for next sample (seconds). For sensors which sense during the sleep phase. Set to
  39. // 0 to indicate no sample waiting. Simply do not use for sensors which deliver values prior to
  40. // deep sleep.
  41. // 3: Number of samples to take before doing a "real" boot. Decremented as samples are obtained
  42. // 4: Reload value for (10). Needs to be applied by the firmware in the real boot (rtc_restart_samples_to_take())
  43. //
  44. // 5: FIFO location. First FIFO address in bits 0:7, first non-FIFO address in bits 8:15.
  45. // Number of tag spaces in bits 16:23
  46. // 6: Number of samples in FIFO.
  47. // 7: FIFO tail (where next sample will be written. Increments by 1 for each sample)
  48. // 8: FIFO head (where next sample will be read. Increments by 1 for each sample)
  49. // 9: FIFO head timestamp. Used and maintained when pulling things off the FIFO. This is the timestamp of the
  50. // most recent sample pulled off; I.e. the head samples timestamp is this plus that sample's delta_t
  51. // 10: FIFO tail timestamp. Used and maintained when adding things to the FIFO. This is the timestamp of the
  52. // most recent sample to have been added. I.e. a new sample's delta-t is calculated relative to this
  53. // (9/10) are meaningless when (3) is zero
  54. //
  55. #define RTC_FIFO_BASE 10
  56. #define RTC_FIFO_MAGIC 0x44695553
  57. // RTCFIFO storage
  58. #define RTC_FIFO_MAGIC_POS (RTC_FIFO_BASE+0)
  59. #define RTC_ALIGNMENT_POS (RTC_FIFO_BASE+1)
  60. #define RTC_TIMESTAMP_POS (RTC_FIFO_BASE+2)
  61. #define RTC_SAMPLESTOTAKE_POS (RTC_FIFO_BASE+3)
  62. #define RTC_SAMPLESPERBOOT_POS (RTC_FIFO_BASE+4)
  63. #define RTC_FIFOLOC_POS (RTC_FIFO_BASE+5)
  64. #define RTC_FIFOCOUNT_POS (RTC_FIFO_BASE+6)
  65. #define RTC_FIFOTAIL_POS (RTC_FIFO_BASE+7)
  66. #define RTC_FIFOHEAD_POS (RTC_FIFO_BASE+8)
  67. #define RTC_FIFOTAIL_T_POS (RTC_FIFO_BASE+9)
  68. #define RTC_FIFOHEAD_T_POS (RTC_FIFO_BASE+10)
  69. // 32-127: FIFO space. Consisting of a number of tag spaces (see 4), followed by data entries.
  70. // Data entries consist of:
  71. // Bits 28:31 -> tag index. 0-15
  72. // Bits 25:27 -> decimals
  73. // Bits 16:24 -> delta-t in seconds from previous entry
  74. // Bits 0:15 -> sample value
  75. #define RTC_DEFAULT_FIFO_START 32
  76. #define RTC_DEFAULT_FIFO_END 128
  77. #define RTC_DEFAULT_TAGCOUNT 5
  78. #define RTC_DEFAULT_FIFO_LOC (RTC_DEFAULT_FIFO_START + (RTC_DEFAULT_FIFO_END<<8) + (RTC_DEFAULT_TAGCOUNT<<16))
  79. #ifndef RTCTIME_SLEEP_ALIGNED
  80. # define RTCTIME_SLEEP_ALIGNED rtc_time_deep_sleep_until_aligned
  81. #endif
  82. typedef struct
  83. {
  84. uint32_t timestamp;
  85. uint32_t value;
  86. uint32_t decimals;
  87. uint32_t tag;
  88. } sample_t;
  89. static inline void rtc_fifo_clear_content(void);
  90. static inline uint32_t rtc_fifo_get_tail(void)
  91. {
  92. return rtc_mem_read(RTC_FIFOTAIL_POS);
  93. }
  94. static inline void rtc_fifo_put_tail(uint32_t val)
  95. {
  96. rtc_mem_write(RTC_FIFOTAIL_POS,val);
  97. }
  98. static inline uint32_t rtc_fifo_get_head(void)
  99. {
  100. return rtc_mem_read(RTC_FIFOHEAD_POS);
  101. }
  102. static inline void rtc_fifo_put_head(uint32_t val)
  103. {
  104. rtc_mem_write(RTC_FIFOHEAD_POS,val);
  105. }
  106. static inline uint32_t rtc_fifo_get_tail_t(void)
  107. {
  108. return rtc_mem_read(RTC_FIFOTAIL_T_POS);
  109. }
  110. static inline void rtc_fifo_put_tail_t(uint32_t val)
  111. {
  112. rtc_mem_write(RTC_FIFOTAIL_T_POS,val);
  113. }
  114. static inline uint32_t rtc_fifo_get_head_t(void)
  115. {
  116. return rtc_mem_read(RTC_FIFOHEAD_T_POS);
  117. }
  118. static inline void rtc_fifo_put_head_t(uint32_t val)
  119. {
  120. rtc_mem_write(RTC_FIFOHEAD_T_POS,val);
  121. }
  122. static inline uint32_t rtc_fifo_get_count(void)
  123. {
  124. return rtc_mem_read(RTC_FIFOCOUNT_POS);
  125. }
  126. static inline void rtc_fifo_put_count(uint32_t val)
  127. {
  128. rtc_mem_write(RTC_FIFOCOUNT_POS,val);
  129. }
  130. static inline uint32_t rtc_fifo_get_tagcount(void)
  131. {
  132. return (rtc_mem_read(RTC_FIFOLOC_POS)>>16)&0xff;
  133. }
  134. static inline uint32_t rtc_fifo_get_tagpos(void)
  135. {
  136. return (rtc_mem_read(RTC_FIFOLOC_POS)>>0)&0xff;
  137. }
  138. static inline uint32_t rtc_fifo_get_last(void)
  139. {
  140. return (rtc_mem_read(RTC_FIFOLOC_POS)>>8)&0xff;
  141. }
  142. static inline uint32_t rtc_fifo_get_first(void)
  143. {
  144. return rtc_fifo_get_tagpos()+rtc_fifo_get_tagcount();
  145. }
  146. static inline void rtc_fifo_put_loc(uint32_t first, uint32_t last, uint32_t tagcount)
  147. {
  148. rtc_mem_write(RTC_FIFOLOC_POS,first+(last<<8)+(tagcount<<16));
  149. }
  150. static inline uint32_t rtc_fifo_normalise_index(uint32_t index)
  151. {
  152. if (index>=rtc_fifo_get_last())
  153. index=rtc_fifo_get_first();
  154. return index;
  155. }
  156. static inline void rtc_fifo_increment_count(void)
  157. {
  158. rtc_fifo_put_count(rtc_fifo_get_count()+1);
  159. }
  160. static inline void rtc_fifo_decrement_count(void)
  161. {
  162. rtc_fifo_put_count(rtc_fifo_get_count()-1);
  163. }
  164. static inline uint32_t rtc_get_samples_to_take(void)
  165. {
  166. return rtc_mem_read(RTC_SAMPLESTOTAKE_POS);
  167. }
  168. static inline void rtc_put_samples_to_take(uint32_t val)
  169. {
  170. rtc_mem_write(RTC_SAMPLESTOTAKE_POS,val);
  171. }
  172. static inline void rtc_decrement_samples_to_take(void)
  173. {
  174. uint32_t stt=rtc_get_samples_to_take();
  175. if (stt)
  176. rtc_put_samples_to_take(stt-1);
  177. }
  178. static inline void rtc_restart_samples_to_take(void)
  179. {
  180. rtc_put_samples_to_take(rtc_mem_read(RTC_SAMPLESPERBOOT_POS));
  181. }
  182. static inline uint32_t rtc_fifo_get_value(uint32_t entry)
  183. {
  184. return entry&0xffff;
  185. }
  186. static inline uint32_t rtc_fifo_get_decimals(uint32_t entry)
  187. {
  188. return (entry>>25)&0x07;
  189. }
  190. static inline uint32_t rtc_fifo_get_deltat(uint32_t entry)
  191. {
  192. return (entry>>16)&0x1ff;
  193. }
  194. static inline uint32_t rtc_fifo_get_tagindex(uint32_t entry)
  195. {
  196. return (entry>>28)&0x0f;
  197. }
  198. static inline uint32_t rtc_fifo_get_tag_from_entry(uint32_t entry)
  199. {
  200. uint32_t index=rtc_fifo_get_tagindex(entry);
  201. uint32_t tags_at=rtc_fifo_get_tagpos();
  202. return rtc_mem_read(tags_at+index);
  203. }
  204. static inline void rtc_fifo_fill_sample(sample_t* dst, uint32_t entry, uint32_t timestamp)
  205. {
  206. dst->timestamp=timestamp;
  207. dst->value=rtc_fifo_get_value(entry);
  208. dst->decimals=rtc_fifo_get_decimals(entry);
  209. dst->tag=rtc_fifo_get_tag_from_entry(entry);
  210. }
  211. // returns 1 if sample popped, 0 if not
  212. static inline int8_t rtc_fifo_pop_sample(sample_t* dst)
  213. {
  214. uint32_t count=rtc_fifo_get_count();
  215. if (count==0)
  216. return 0;
  217. uint32_t head=rtc_fifo_get_head();
  218. uint32_t timestamp=rtc_fifo_get_head_t();
  219. uint32_t entry=rtc_mem_read(head);
  220. timestamp+=rtc_fifo_get_deltat(entry);
  221. rtc_fifo_fill_sample(dst,entry,timestamp);
  222. head=rtc_fifo_normalise_index(head+1);
  223. rtc_fifo_put_head(head);
  224. rtc_fifo_put_head_t(timestamp);
  225. rtc_fifo_decrement_count();
  226. return 1;
  227. }
  228. // returns 1 if sample is available, 0 if not
  229. static inline int8_t rtc_fifo_peek_sample(sample_t* dst, uint32_t from_top)
  230. {
  231. if (rtc_fifo_get_count()<=from_top)
  232. return 0;
  233. uint32_t head=rtc_fifo_get_head();
  234. uint32_t entry=rtc_mem_read(head);
  235. uint32_t timestamp=rtc_fifo_get_head_t();
  236. timestamp+=rtc_fifo_get_deltat(entry);
  237. while (from_top--)
  238. {
  239. head=rtc_fifo_normalise_index(head+1);
  240. entry=rtc_mem_read(head);
  241. timestamp+=rtc_fifo_get_deltat(entry);
  242. }
  243. rtc_fifo_fill_sample(dst,entry,timestamp);
  244. return 1;
  245. }
  246. static inline void rtc_fifo_drop_samples(uint32_t from_top)
  247. {
  248. uint32_t count=rtc_fifo_get_count();
  249. if (count<=from_top)
  250. from_top=count;
  251. uint32_t head=rtc_fifo_get_head();
  252. uint32_t head_t=rtc_fifo_get_head_t();
  253. while (from_top--)
  254. {
  255. uint32_t entry=rtc_mem_read(head);
  256. head_t+=rtc_fifo_get_deltat(entry);
  257. head=rtc_fifo_normalise_index(head+1);
  258. rtc_fifo_decrement_count();
  259. }
  260. rtc_fifo_put_head(head);
  261. rtc_fifo_put_head_t(head_t);
  262. }
  263. static inline int rtc_fifo_find_tag_index(uint32_t tag)
  264. {
  265. uint32_t tags_at=rtc_fifo_get_tagpos();
  266. uint32_t count=rtc_fifo_get_tagcount();
  267. uint32_t i;
  268. for (i=0;i<count;i++)
  269. {
  270. uint32_t stag=rtc_mem_read(tags_at+i);
  271. if (stag==tag)
  272. return i;
  273. if (stag==0)
  274. {
  275. rtc_mem_write(tags_at+i,tag);
  276. return i;
  277. }
  278. }
  279. return -1;
  280. }
  281. static int32_t rtc_fifo_delta_t(uint32_t t, uint32_t ref_t)
  282. {
  283. uint32_t delta=t-ref_t;
  284. if (delta>0x1ff)
  285. return -1;
  286. return delta;
  287. }
  288. static uint32_t rtc_fifo_construct_entry(uint32_t val, uint32_t tagindex, uint32_t decimals, uint32_t deltat)
  289. {
  290. return (val & 0xffff) + ((deltat & 0x1ff) <<16) +
  291. ((decimals & 0x7)<<25) + ((tagindex & 0xf)<<28);
  292. }
  293. static inline void rtc_fifo_store_sample(const sample_t* s)
  294. {
  295. uint32_t head=rtc_fifo_get_head();
  296. uint32_t tail=rtc_fifo_get_tail();
  297. uint32_t count=rtc_fifo_get_count();
  298. int32_t tagindex=rtc_fifo_find_tag_index(s->tag);
  299. if (count==0)
  300. {
  301. rtc_fifo_put_head_t(s->timestamp);
  302. rtc_fifo_put_tail_t(s->timestamp);
  303. }
  304. uint32_t tail_t=rtc_fifo_get_tail_t();
  305. int32_t deltat=rtc_fifo_delta_t(s->timestamp,tail_t);
  306. if (tagindex<0 || deltat<0)
  307. { // We got something that doesn't fit into the scheme. Might be a long delay, might
  308. // be some sort of dynamic change. In order to go on, we need to start over....
  309. // ets_printf("deltat is %d, tagindex is %d\n",deltat,tagindex);
  310. rtc_fifo_clear_content();
  311. rtc_fifo_put_head_t(s->timestamp);
  312. rtc_fifo_put_tail_t(s->timestamp);
  313. head=rtc_fifo_get_head();
  314. tail=rtc_fifo_get_tail();
  315. count=rtc_fifo_get_count();
  316. tagindex=rtc_fifo_find_tag_index(s->tag); // This should work now
  317. if (tagindex<0)
  318. return; // Uh-oh! This should never happen
  319. }
  320. if (head==tail && count>0)
  321. { // Full! Need to remove a sample
  322. sample_t dummy;
  323. rtc_fifo_pop_sample(&dummy);
  324. }
  325. rtc_mem_write(tail++,rtc_fifo_construct_entry(s->value,tagindex,s->decimals,deltat));
  326. rtc_fifo_put_tail(rtc_fifo_normalise_index(tail));
  327. rtc_fifo_put_tail_t(s->timestamp);
  328. rtc_fifo_increment_count();
  329. }
  330. static uint32_t rtc_fifo_make_tag(const uint8_t* s)
  331. {
  332. uint32_t tag=0;
  333. int i;
  334. for (i=0;i<4;i++)
  335. {
  336. if (!s[i])
  337. break;
  338. tag+=((uint32_t)(s[i]&0xff))<<(i*8);
  339. }
  340. return tag;
  341. }
  342. static void rtc_fifo_tag_to_string(uint32_t tag, uint8_t s[5])
  343. {
  344. int i;
  345. s[4]=0;
  346. for (i=0;i<4;i++)
  347. s[i]=(tag>>(8*i))&0xff;
  348. }
  349. static inline uint32_t rtc_fifo_get_divisor(const sample_t* s)
  350. {
  351. uint8_t decimals=s->decimals;
  352. uint32_t div=1;
  353. while (decimals--)
  354. div*=10;
  355. return div;
  356. }
  357. static inline void rtc_fifo_clear_tags(void)
  358. {
  359. uint32_t tags_at=rtc_fifo_get_tagpos();
  360. uint32_t count=rtc_fifo_get_tagcount();
  361. while (count--)
  362. rtc_mem_write(tags_at++,0);
  363. }
  364. static inline void rtc_fifo_clear_content(void)
  365. {
  366. uint32_t first=rtc_fifo_get_first();
  367. rtc_fifo_put_tail(first);
  368. rtc_fifo_put_head(first);
  369. rtc_fifo_put_count(0);
  370. rtc_fifo_put_tail_t(0);
  371. rtc_fifo_put_head_t(0);
  372. rtc_fifo_clear_tags();
  373. }
  374. static inline void rtc_fifo_init(uint32_t first, uint32_t last, uint32_t tagcount)
  375. {
  376. rtc_fifo_put_loc(first,last,tagcount);
  377. rtc_fifo_clear_content();
  378. }
  379. static inline void rtc_fifo_init_default(uint32_t tagcount)
  380. {
  381. if (tagcount==0)
  382. tagcount=RTC_DEFAULT_TAGCOUNT;
  383. rtc_fifo_init(RTC_DEFAULT_FIFO_START,RTC_DEFAULT_FIFO_END,tagcount);
  384. }
  385. static inline uint8_t rtc_fifo_check_magic(void)
  386. {
  387. if (rtc_mem_read(RTC_FIFO_MAGIC_POS)==RTC_FIFO_MAGIC)
  388. return 1;
  389. return 0;
  390. }
  391. static inline void rtc_fifo_set_magic(void)
  392. {
  393. rtc_mem_write(RTC_FIFO_MAGIC_POS,RTC_FIFO_MAGIC);
  394. }
  395. static inline void rtc_fifo_unset_magic(void)
  396. {
  397. rtc_mem_write(RTC_FIFO_MAGIC_POS,0);
  398. }
  399. static inline void rtc_fifo_deep_sleep_until_sample(uint32_t min_sleep_us)
  400. {
  401. uint32_t align=rtc_mem_read(RTC_ALIGNMENT_POS);
  402. RTCTIME_SLEEP_ALIGNED(align,min_sleep_us);
  403. }
  404. static inline void rtc_fifo_prepare(uint32_t samples_per_boot, uint32_t us_per_sample, uint32_t tagcount)
  405. {
  406. rtc_mem_write(RTC_SAMPLESPERBOOT_POS,samples_per_boot);
  407. rtc_mem_write(RTC_ALIGNMENT_POS,us_per_sample);
  408. rtc_put_samples_to_take(0);
  409. rtc_fifo_init_default(tagcount);
  410. rtc_fifo_set_magic();
  411. }
  412. #endif