1 #include <string.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <csi_core.h>
5 #include "dev_ringbuf.h"
6
7 #define min(a, b) (((a) < (b)) ? (a) : (b))
8
9 /**
10 * \brief Removes the entire FIFO contents.
11 * \param [in] fifo: The fifo to be emptied.
12 * \return None.
13 */
dev_ringbuff_reset(dev_ringbuf_t * fifo)14 void dev_ringbuff_reset(dev_ringbuf_t *fifo)
15 {
16 uint32_t stat = csi_irq_save();
17 fifo->write = fifo->read = 0;
18 fifo->data_len = 0;
19 csi_irq_restore(stat);
20 }
21
22 /**
23 * \brief Returns the size of the FIFO in bytes.
24 * \param [in] fifo: The fifo to be used.
25 * \return The size of the FIFO.
26 */
ringbuffer_size(dev_ringbuf_t * fifo)27 static inline uint32_t ringbuffer_size(dev_ringbuf_t *fifo)
28 {
29 return fifo->size;
30 }
31
32 /**
33 * \brief Returns the number of used bytes in the FIFO.
34 * \param [in] fifo: The fifo to be used.
35 * \return The number of used bytes.
36 */
dev_ringbuf_len(dev_ringbuf_t * fifo)37 uint32_t dev_ringbuf_len(dev_ringbuf_t *fifo)
38 {
39 return fifo->data_len;
40 }
41
42 /**
43 * \brief Returns the number of bytes available in the FIFO.
44 * \param [in] fifo: The fifo to be used.
45 * \return The number of bytes available.
46 */
dev_ringbuf_avail(dev_ringbuf_t * fifo)47 uint32_t dev_ringbuf_avail(dev_ringbuf_t *fifo)
48 {
49 return ringbuffer_size(fifo) - dev_ringbuf_len(fifo);
50 }
51
52 /**
53 * \brief Is the FIFO empty?
54 * \param [in] fifo: The fifo to be used.
55 * \retval true: Yes.
56 * \retval false: No.
57 */
dev_ringbuf_is_empty(dev_ringbuf_t * fifo)58 bool dev_ringbuf_is_empty(dev_ringbuf_t *fifo)
59 {
60 return dev_ringbuf_len(fifo) == 0;
61 }
62
63 /**
64 * \brief Is the FIFO full?
65 * \param [in] fifo: The fifo to be used.
66 * \retval true: Yes.
67 * \retval false: No.
68 */
dev_ringbuf_is_full(dev_ringbuf_t * fifo)69 bool dev_ringbuf_is_full(dev_ringbuf_t *fifo)
70 {
71 return dev_ringbuf_avail(fifo) == 0;
72 }
73
74 /**
75 * \brief Puts some data into the FIFO.
76 * \param [in] fifo: The fifo to be used.
77 * \param [in] in: The data to be added.
78 * \param [in] len: The length of the data to be added.
79 * \return The number of bytes copied.
80 * \note This function copies at most @len bytes from the @in into
81 * the FIFO depending on the free space, and returns the number
82 * of bytes copied.
83 */
dev_ringbuf_in(dev_ringbuf_t * fifo,const void * datptr,uint32_t len)84 uint32_t dev_ringbuf_in(dev_ringbuf_t *fifo, const void *datptr, uint32_t len)
85 {
86 uint32_t writelen = 0, tmplen = 0;
87
88 if(dev_ringbuf_is_full(fifo))
89 return 0;
90
91 tmplen = fifo->size - fifo->data_len;
92 writelen = tmplen > len ? len : tmplen;
93
94 if(fifo->write < fifo->read) {
95 memcpy((void*)&fifo->buffer[fifo->write], (void*)datptr, writelen);
96 } else {
97 tmplen = fifo->size - fifo->write;
98 if(writelen <= tmplen) {
99 memcpy((void*)&fifo->buffer[fifo->write], (void*)datptr, writelen);
100 } else {
101 memcpy((void*)&fifo->buffer[fifo->write], (void*)datptr, tmplen);
102 memcpy((void*)fifo->buffer, (uint8_t*)datptr + tmplen, writelen - tmplen);
103 }
104 }
105
106 uint32_t stat = csi_irq_save();
107 fifo->write = (fifo->write + writelen) % fifo->size;
108 fifo->data_len += writelen;
109 csi_irq_restore(stat);
110
111 return writelen;
112 }
113
114 /**
115 * \brief Gets some data from the FIFO.
116 * \param [in] fifo: The fifo to be used.
117 * \param [in] out: Where the data must be copied.
118 * \param [in] len: The size of the destination buffer.
119 * \return The number of copied bytes.
120 * \note This function copies at most @len bytes from the FIFO into
121 * the @out and returns the number of copied bytes.
122 */
dev_ringbuf_out(dev_ringbuf_t * fifo,void * outbuf,uint32_t len)123 uint32_t dev_ringbuf_out(dev_ringbuf_t *fifo, void *outbuf, uint32_t len)
124 {
125 uint32_t readlen = 0, tmplen = 0;
126 if(dev_ringbuf_is_empty(fifo))
127 return 0;
128
129 uint32_t data_len = fifo->data_len;
130 readlen = len > data_len ? data_len : len;
131 tmplen = fifo->size - fifo->read;
132
133 if(NULL != outbuf) {
134 if(readlen <= tmplen) {
135 memcpy((void*)outbuf, (void*)&fifo->buffer[fifo->read], readlen);
136 } else {
137 memcpy((void*)outbuf,(void*)&fifo->buffer[fifo->read], tmplen);
138 memcpy((uint8_t*)outbuf + tmplen,(void*)fifo->buffer,readlen - tmplen);
139 }
140 }
141
142 uint32_t stat = csi_irq_save();
143 fifo->read = (fifo->read + readlen) % fifo->size;
144 fifo->data_len -= readlen;
145 csi_irq_restore(stat);
146
147 return readlen;
148 }
149
150