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