chry_ringbuffer.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Copyright (c) 2022, Egahp
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <string.h>
  7. #include "chry_ringbuffer.h"
  8. /*****************************************************************************
  9. * @brief init ringbuffer
  10. *
  11. * @param[in] rb ringbuffer instance
  12. * @param[in] pool memory pool address
  13. * @param[in] size memory size in byte,
  14. * must be power of 2 !!!
  15. *
  16. * @retval int 0:Success -1:Error
  17. *****************************************************************************/
  18. int chry_ringbuffer_init(chry_ringbuffer_t *rb, void *pool, uint32_t size)
  19. {
  20. if (NULL == rb) {
  21. return -1;
  22. }
  23. if (NULL == pool) {
  24. return -1;
  25. }
  26. if ((size < 2) || (size & (size - 1))) {
  27. return -1;
  28. }
  29. rb->in = 0;
  30. rb->out = 0;
  31. rb->mask = size - 1;
  32. rb->pool = pool;
  33. return 0;
  34. }
  35. /*****************************************************************************
  36. * @brief reset ringbuffer, clean all data,
  37. * should be add lock in multithread
  38. *
  39. * @param[in] rb ringbuffer instance
  40. *
  41. *****************************************************************************/
  42. void chry_ringbuffer_reset(chry_ringbuffer_t *rb)
  43. {
  44. rb->in = 0;
  45. rb->out = 0;
  46. }
  47. /*****************************************************************************
  48. * @brief reset ringbuffer, clean all data,
  49. * should be add lock in multithread,
  50. * in single read thread not need lock
  51. *
  52. * @param[in] rb ringbuffer instance
  53. *
  54. *****************************************************************************/
  55. void chry_ringbuffer_reset_read(chry_ringbuffer_t *rb)
  56. {
  57. rb->out = rb->in;
  58. }
  59. /*****************************************************************************
  60. * @brief get ringbuffer total size in byte
  61. *
  62. * @param[in] rb ringbuffer instance
  63. *
  64. * @retval uint32_t total size in byte
  65. *****************************************************************************/
  66. uint32_t chry_ringbuffer_get_size(chry_ringbuffer_t *rb)
  67. {
  68. return rb->mask + 1;
  69. }
  70. /*****************************************************************************
  71. * @brief get ringbuffer used size in byte
  72. *
  73. * @param[in] rb ringbuffer instance
  74. *
  75. * @retval uint32_t used size in byte
  76. *****************************************************************************/
  77. uint32_t chry_ringbuffer_get_used(chry_ringbuffer_t *rb)
  78. {
  79. return rb->in - rb->out;
  80. }
  81. /*****************************************************************************
  82. * @brief get ringbuffer free size in byte
  83. *
  84. * @param[in] rb ringbuffer instance
  85. *
  86. * @retval uint32_t free size in byte
  87. *****************************************************************************/
  88. uint32_t chry_ringbuffer_get_free(chry_ringbuffer_t *rb)
  89. {
  90. return (rb->mask + 1) - (rb->in - rb->out);
  91. }
  92. /*****************************************************************************
  93. * @brief check if ringbuffer is full
  94. *
  95. * @param[in] rb ringbuffer instance
  96. *
  97. * @retval true full
  98. * @retval false not full
  99. *****************************************************************************/
  100. bool chry_ringbuffer_check_full(chry_ringbuffer_t *rb)
  101. {
  102. return chry_ringbuffer_get_used(rb) > rb->mask;
  103. }
  104. /*****************************************************************************
  105. * @brief check if ringbuffer is empty
  106. *
  107. * @param[in] rb ringbuffer instance
  108. *
  109. * @retval true empty
  110. * @retval false not empty
  111. *****************************************************************************/
  112. bool chry_ringbuffer_check_empty(chry_ringbuffer_t *rb)
  113. {
  114. return rb->in == rb->out;
  115. }
  116. /*****************************************************************************
  117. * @brief write one byte to ringbuffer,
  118. * should be add lock in multithread,
  119. * in single write thread not need lock
  120. *
  121. * @param[in] rb ringbuffer instance
  122. * @param[in] byte data
  123. *
  124. * @retval true Success
  125. * @retval false ringbuffer is full
  126. *****************************************************************************/
  127. bool chry_ringbuffer_write_byte(chry_ringbuffer_t *rb, uint8_t byte)
  128. {
  129. if (chry_ringbuffer_check_full(rb)) {
  130. return false;
  131. }
  132. ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
  133. rb->in++;
  134. return true;
  135. }
  136. /*****************************************************************************
  137. * @brief overwrite one byte to ringbuffer, drop oldest data,
  138. * should be add lock always
  139. *
  140. * @param[in] rb ringbuffer instance
  141. * @param[in] byte data
  142. *
  143. * @retval true Success
  144. * @retval false always return true
  145. *****************************************************************************/
  146. bool chry_ringbuffer_overwrite_byte(chry_ringbuffer_t *rb, uint8_t byte)
  147. {
  148. if (chry_ringbuffer_check_full(rb)) {
  149. rb->out++;
  150. }
  151. ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
  152. rb->in++;
  153. return true;
  154. }
  155. /*****************************************************************************
  156. * @brief peek one byte from ringbuffer,
  157. * should be add lock in multithread,
  158. * in single read thread not need lock
  159. *
  160. * @param[in] rb ringbuffer instance
  161. * @param[in] byte pointer to save data
  162. *
  163. * @retval true Success
  164. * @retval false ringbuffer is empty
  165. *****************************************************************************/
  166. bool chry_ringbuffer_peek_byte(chry_ringbuffer_t *rb, uint8_t *byte)
  167. {
  168. if (chry_ringbuffer_check_empty(rb)) {
  169. return false;
  170. }
  171. *byte = ((uint8_t *)(rb->pool))[rb->out & rb->mask];
  172. return true;
  173. }
  174. /*****************************************************************************
  175. * @brief read one byte from ringbuffer,
  176. * should be add lock in multithread,
  177. * in single read thread not need lock
  178. *
  179. * @param[in] rb ringbuffer instance
  180. * @param[in] byte pointer to save data
  181. *
  182. * @retval true Success
  183. * @retval false ringbuffer is empty
  184. *****************************************************************************/
  185. bool chry_ringbuffer_read_byte(chry_ringbuffer_t *rb, uint8_t *byte)
  186. {
  187. bool ret;
  188. ret = chry_ringbuffer_peek_byte(rb, byte);
  189. rb->out += ret;
  190. return ret;
  191. }
  192. /*****************************************************************************
  193. * @brief drop one byte from ringbuffer,
  194. * should be add lock in multithread,
  195. * in single read thread not need lock
  196. *
  197. * @param[in] rb ringbuffer instance
  198. *
  199. * @retval true Success
  200. * @retval false ringbuffer is empty
  201. *****************************************************************************/
  202. bool chry_ringbuffer_drop_byte(chry_ringbuffer_t *rb)
  203. {
  204. if (chry_ringbuffer_check_empty(rb)) {
  205. return false;
  206. }
  207. rb->out += 1;
  208. return true;
  209. }
  210. /*****************************************************************************
  211. * @brief write data to ringbuffer,
  212. * should be add lock in multithread,
  213. * in single write thread not need lock
  214. *
  215. * @param[in] rb ringbuffer instance
  216. * @param[in] data data pointer
  217. * @param[in] size size in byte
  218. *
  219. * @retval uint32_t actual write size in byte
  220. *****************************************************************************/
  221. uint32_t chry_ringbuffer_write(chry_ringbuffer_t *rb, void *data, uint32_t size)
  222. {
  223. uint32_t unused;
  224. uint32_t offset;
  225. uint32_t remain;
  226. unused = (rb->mask + 1) - (rb->in - rb->out);
  227. if (size > unused) {
  228. size = unused;
  229. }
  230. offset = rb->in & rb->mask;
  231. remain = rb->mask + 1 - offset;
  232. remain = remain > size ? size : remain;
  233. memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
  234. memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
  235. rb->in += size;
  236. return size;
  237. }
  238. /*****************************************************************************
  239. * @brief write data to ringbuffer,
  240. * should be add lock always
  241. *
  242. * @param[in] rb ringbuffer instance
  243. * @param[in] data data pointer
  244. * @param[in] size size in byte
  245. *
  246. * @retval uint32_t actual write size in byte
  247. *****************************************************************************/
  248. uint32_t chry_ringbuffer_overwrite(chry_ringbuffer_t *rb, void *data, uint32_t size)
  249. {
  250. uint32_t unused;
  251. uint32_t offset;
  252. uint32_t remain;
  253. unused = (rb->mask + 1) - (rb->in - rb->out);
  254. if (size > unused) {
  255. if (size > (rb->mask + 1)) {
  256. size = rb->mask + 1;
  257. }
  258. rb->out += size - unused;
  259. }
  260. offset = rb->in & rb->mask;
  261. remain = rb->mask + 1 - offset;
  262. remain = remain > size ? size : remain;
  263. memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
  264. memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
  265. rb->in += size;
  266. return size;
  267. }
  268. /*****************************************************************************
  269. * @brief peek data from ringbuffer
  270. * should be add lock in multithread,
  271. * in single read thread not need lock
  272. *
  273. * @param[in] rb ringbuffer instance
  274. * @param[in] data data pointer
  275. * @param[in] size size in byte
  276. *
  277. * @retval uint32_t actual peek size in byte
  278. *****************************************************************************/
  279. uint32_t chry_ringbuffer_peek(chry_ringbuffer_t *rb, void *data, uint32_t size)
  280. {
  281. uint32_t used;
  282. uint32_t offset;
  283. uint32_t remain;
  284. used = rb->in - rb->out;
  285. if (size > used) {
  286. size = used;
  287. }
  288. offset = rb->out & rb->mask;
  289. remain = rb->mask + 1 - offset;
  290. remain = remain > size ? size : remain;
  291. memcpy(data, ((uint8_t *)(rb->pool)) + offset, remain);
  292. memcpy((uint8_t *)data + remain, rb->pool, size - remain);
  293. return size;
  294. }
  295. /*****************************************************************************
  296. * @brief read data from ringbuffer
  297. * should be add lock in multithread,
  298. * in single read thread not need lock
  299. *
  300. * @param[in] rb ringbuffer instance
  301. * @param[in] data data pointer
  302. * @param[in] size size in byte
  303. *
  304. * @retval uint32_t actual read size in byte
  305. *****************************************************************************/
  306. uint32_t chry_ringbuffer_read(chry_ringbuffer_t *rb, void *data, uint32_t size)
  307. {
  308. size = chry_ringbuffer_peek(rb, data, size);
  309. rb->out += size;
  310. return size;
  311. }
  312. /*****************************************************************************
  313. * @brief drop data from ringbuffer
  314. * should be add lock in multithread,
  315. * in single read thread not need lock
  316. *
  317. * @param[in] rb ringbuffer instance
  318. * @param[in] size size in byte
  319. *
  320. * @retval uint32_t actual drop size in byte
  321. *****************************************************************************/
  322. uint32_t chry_ringbuffer_drop(chry_ringbuffer_t *rb, uint32_t size)
  323. {
  324. uint32_t used;
  325. used = rb->in - rb->out;
  326. if (size > used) {
  327. size = used;
  328. }
  329. rb->out += size;
  330. return size;
  331. }
  332. /*****************************************************************************
  333. * @brief linear write setup, get write pointer and max linear size.
  334. *
  335. * @param[in] rb ringbuffer instance
  336. * @param[in] size pointer to store max linear size in byte
  337. *
  338. * @retval void* write memory pointer
  339. *****************************************************************************/
  340. void *chry_ringbuffer_linear_write_setup(chry_ringbuffer_t *rb, uint32_t *size)
  341. {
  342. uint32_t unused;
  343. uint32_t offset;
  344. uint32_t remain;
  345. unused = (rb->mask + 1) - (rb->in - rb->out);
  346. offset = rb->in & rb->mask;
  347. remain = rb->mask + 1 - offset;
  348. remain = remain > unused ? unused : remain;
  349. if (remain) {
  350. *size = remain;
  351. return ((uint8_t *)(rb->pool)) + offset;
  352. } else {
  353. *size = unused - remain;
  354. return rb->pool;
  355. }
  356. }
  357. /*****************************************************************************
  358. * @brief linear read setup, get read pointer and max linear size.
  359. *
  360. * @param[in] rb ringbuffer instance
  361. * @param[in] size pointer to store max linear size in byte
  362. *
  363. * @retval void*
  364. *****************************************************************************/
  365. void *chry_ringbuffer_linear_read_setup(chry_ringbuffer_t *rb, uint32_t *size)
  366. {
  367. uint32_t used;
  368. uint32_t offset;
  369. uint32_t remain;
  370. used = rb->in - rb->out;
  371. offset = rb->out & rb->mask;
  372. remain = rb->mask + 1 - offset;
  373. remain = remain > used ? used : remain;
  374. if (remain) {
  375. *size = remain;
  376. return ((uint8_t *)(rb->pool)) + offset;
  377. } else {
  378. *size = used - remain;
  379. return rb->pool;
  380. }
  381. }
  382. /*****************************************************************************
  383. * @brief linear write done, add write pointer only
  384. *
  385. * @param[in] rb ringbuffer instance
  386. * @param[in] size write size in byte
  387. *
  388. * @retval uint32_t actual write size in byte
  389. *****************************************************************************/
  390. uint32_t chry_ringbuffer_linear_write_done(chry_ringbuffer_t *rb, uint32_t size)
  391. {
  392. uint32_t unused;
  393. unused = (rb->mask + 1) - (rb->in - rb->out);
  394. if (size > unused) {
  395. size = unused;
  396. }
  397. rb->in += size;
  398. return size;
  399. }
  400. /*****************************************************************************
  401. * @brief linear read done, add read pointer only
  402. *
  403. * @param[in] rb ringbuffer instance
  404. * @param[in] size read size in byte
  405. *
  406. * @retval uint32_t actual read size in byte
  407. *****************************************************************************/
  408. uint32_t chry_ringbuffer_linear_read_done(chry_ringbuffer_t *rb, uint32_t size)
  409. {
  410. return chry_ringbuffer_drop(rb, size);
  411. }