/ Drivers / ring_buffer / ring_buffer.c
ring_buffer.c
  1  /*
  2  * This is an independent project of an individual developer. Dear PVS-Studio, please check it.
  3  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  4  */
  5  /* LINTLIBRARY */
  6  /**
  7    *********************************************************************************************************
  8    *
  9    *	This file is part of Devprodest Lib.
 10    *	
 11    *	  Devprodest Lib is free software: you can redistribute it and/or modify
 12    *	  it under the terms of the GNU General Public License as published by
 13    *	  the Free Software Foundation, either version 3 of the License, or
 14    *	  (at your option) any later version.
 15    *	
 16    *	  Devprodest Lib is distributed in the hope that it will be useful,
 17    *	  but WITHOUT ANY WARRANTY; without even the implied warranty of
 18    *	  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 19    *	  GNU General Public License for more details.
 20    *	
 21    *	  You should have received a copy of the GNU General Public License
 22    *	  along with Devprodest Lib.  If not, see <http://www.gnu.org/licenses/>.
 23    *	
 24    * @file ring_buffer.c
 25    * @brief Кольцевой буфер
 26    * @version 1.0
 27    * @authors Zaikin Denis (ZD)
 28    * @authors Potorochin Andrew (PA)
 29    * 
 30    * @copyright GNU General Public License
 31    *********************************************************************************************************
 32    */
 33  #include "ring_buffer.h"
 34  #include "stdint.h"
 35  #include <string.h>
 36  
 37  /** 
 38   * @defgroup CRC Функции вычисления циклической контрольной суммы
 39   * @{
 40   */
 41  
 42  /**
 43  @function RING_CRC16ccitt − Вычисление контрольной суммы.
 44  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
 45  @param uint16_t lenght − Сколько элементов буфера участвуют в подсчете.
 46  @param uint16_t position − С какого элемента начинать.
 47  @return uint16_t Результат вычисления контрольной суммы.
 48   */
 49  uint16_t RING_CRC16ccitt(const RING_buffer_t *buf, uint16_t lenght, uint16_t position)
 50  {
 51  	return RING_CRC16ccitt_Intermediate( buf, lenght, 0xFFFF, position);
 52  }
 53  
 54  /**
 55  @function RING_CRC16ccitt_Intermediate − Вычисление контрольной суммы с инициализацией.
 56  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
 57  @param uint16_t lenght − Сколько элементов буфера участвуют в подсчете.
 58  @param uint16_t tmpCrc − Начальное значение контрольной суммы.
 59  @param uint16_t position − С какого элемента начинать.
 60  @return uint16_t Результат вычисления контрольной суммы.
 61   */
 62  uint16_t RING_CRC16ccitt_Intermediate(const RING_buffer_t *buf, uint16_t lenght, uint16_t tmpCrc, uint16_t position)
 63  {
 64  	uint16_t crc = tmpCrc;
 65  	uint16_t crctab;
 66  	uint8_t byte;
 67  	
 68      while (lenght--)
 69      {
 70          crctab = 0x0000;
 71          byte = (RING_ShowSymbol(buf, lenght + position))^( crc >> 8 );
 72          if( byte & 0x01 ) crctab ^= 0x1021;
 73          if( byte & 0x02 ) crctab ^= 0x2042;
 74          if( byte & 0x04 ) crctab ^= 0x4084;
 75          if( byte & 0x08 ) crctab ^= 0x8108;
 76          if( byte & 0x10 ) crctab ^= 0x1231;
 77          if( byte & 0x20 ) crctab ^= 0x2462;
 78          if( byte & 0x40 ) crctab ^= 0x48C4;
 79          if( byte & 0x80 ) crctab ^= 0x9188;
 80          
 81          crc = ( ( (crc & 0xFF)^(crctab >> 8) ) << 8 ) | ( crctab & 0xFF );
 82      }
 83      return crc;
 84  }
 85  
 86  /** @} */
 87  
 88  /** 
 89   * @defgroup control Функции управления буфером
 90   * @{
 91   */
 92  
 93  
 94  /**
 95  @function RING_Init − Инициализация буфера.
 96  @param RING_buffer_t *ring − Указатель на кольцевой буфер.
 97  @param uint8_t *buf − Указатель на буфер хранения.
 98  @param uint16_t size − Сколько элементов в буфере.
 99  @return RING_ErrorStatus_t Результат инициализации @ref RING_ErrorStatus_t
100   */
101  RING_ErrorStatus_t RING_Init(RING_buffer_t *ring, uint8_t *buf, uint16_t size)
102  {
103      ring->size = size;
104      ring->buffer = buf;
105      RING_Clear( ring );
106  
107      return ( ring->buffer ? RING_SUCCESS : RING_ERROR ) ;
108  }
109  
110  /**
111  @function RING_GetCount − Количество полезных данных в буфере.
112  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
113  @return uint16_t Количество полезных данных в буфере.
114   */
115  uint16_t RING_GetCount(const RING_buffer_t *buf)
116  {
117      uint16_t retval = 0;
118      if (buf->idxIn < buf->idxOut) retval = buf->size + buf->idxIn - buf->idxOut;
119      else retval = buf->idxIn - buf->idxOut;
120      return retval;
121  }
122  
123  /**
124  @function RING_Clear − Очищает буфер.
125  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
126   */
127  void RING_Clear(RING_buffer_t* buf)
128  {
129      buf->idxIn = 0;
130      buf->idxOut = 0;
131      memset(buf->buffer, 0x0, buf->size);
132  }
133  
134  
135  /** @} */
136  
137  /** 
138   * @defgroup put Функции загрузки данных в буфер
139   * @{
140   */
141  
142  /**
143  @function RING_Put − Загружает элемент в буфер.
144  @param uint8_t symbol − Элемент для загрузки в буфер.
145  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
146   */
147  void RING_Put( RING_buffer_t* buf, uint8_t symbol)
148  {
149      buf->buffer[buf->idxIn++] = symbol;
150      if (buf->idxIn >= buf->size) buf->idxIn = 0;
151  }
152  
153  /**
154  @function RING_Put16 − Загружает элемент в буфер.
155  @param uint16_t symbol − Элемент для загрузки в буфер.
156  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
157   */
158  void RING_Put16( RING_buffer_t* buf, uint16_t symbol)
159  {
160      buf->buffer[buf->idxIn++] = symbol >> 8;
161      if (buf->idxIn >= buf->size) buf->idxIn = 0;
162      buf->buffer[buf->idxIn++] = symbol & 0xFF;
163      if (buf->idxIn >= buf->size) buf->idxIn = 0;
164  }
165  
166  /**
167  @function RING_PutBuffr − Загружает элементы из массива-источника в кольцевой буфер.
168  @param RING_buffer_t *ringbuf − Указатель на кольцевой буфер.
169  @param uint8_t *src − Указатель на массив-источник.
170  @param uint16_t len − количество загружаемых элементов.
171   */
172  void RING_PutBuffr(RING_buffer_t *ringbuf, uint8_t *src, uint16_t len)
173  {
174      while(len--) RING_Put(ringbuf, *(src++));
175  }
176  
177  /** 
178   * @defgroup pop Функции выгрузки данных из буфера
179   * @{
180   */
181  
182  /**
183  @function RING_Pop − Получает из буфера байт.
184  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
185  @return uint8_t Значение полученого элемента.
186   */
187  uint8_t RING_Pop(RING_buffer_t *buf)
188  {
189      uint8_t retval = buf->buffer[buf->idxOut++];
190      if (buf->idxOut >= buf->size) buf->idxOut = 0;
191      return retval;
192  }
193  
194  /**
195  @function RING_Pop16 − Получает из буфера 16-битное число.
196  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
197  @return uint16_t Значение полученого элемента.
198   */
199  uint16_t RING_Pop16(RING_buffer_t *buf)
200  {
201      uint16_t retval = RING_Pop(buf) << 8;
202      retval += RING_Pop(buf);
203      return retval;
204  }
205  
206  /**
207  @function RING_Pop32 − Получает из буфера 32-битное число.
208  @param RING_buffer_t *buf − Указатель на кольцевой буфер.
209  @return uint32_t Значение полученого элемента.
210   */
211  uint32_t RING_Pop32(RING_buffer_t *buf)
212  {
213      uint32_t retval  = RING_Pop(buf) << 8;
214      retval += RING_Pop(buf) << 8;
215      retval += RING_Pop(buf) << 8;
216      retval += RING_Pop(buf);
217      return retval;
218  }
219  
220  /**
221  @function RING_PopBuffr − Заполняет элементами кольцевого буфера массив.
222  @param RING_buffer_t *ringbuf − Указатель на кольцевой буфер.
223  @param uint8_t *destination − Указатель на массив.
224  @param uint16_t len − количество получаемых элементов.
225   */
226  void RING_PopBuffr(RING_buffer_t *ringbuf, uint8_t *destination, uint16_t len)
227  {
228      while(len--) *(destination++) = RING_Pop(ringbuf);
229  }
230  
231  /**
232  @function RING_PopString − Считывает нультерминальную строку из буфера в string
233  @param RING_buffer_t *ringbuf − Указатель на кольцевой буфер.
234  @param char *string − Указатель на массив.
235   */
236  void RING_PopString(RING_buffer_t *ringbuf, char *string)
237  {
238      
239      while(RING_ShowSymbol(ringbuf, 0) > 0) *(string++) = RING_Pop(ringbuf);
240  }
241  
242  
243  /** @} */
244  
245  /** 
246   * @defgroup other Другие функции
247   * @ingroup pop
248   * @{
249   */
250  
251  /**
252  @function RING_ShowSymbol − Показывает содержимое элемента без его удаления из буфера.
253  @param RING_buffer_t *ringbuf − Указатель на кольцевой буфер.
254  @param uint16_t symbolNumbe − Номер элемента.
255  @return int32_t Значение полученого элемента. -1 если ошибка.
256   */
257  int32_t RING_ShowSymbol(const RING_buffer_t *buf, uint16_t symbolNumber)
258  {
259      uint32_t pointer = buf->idxOut + symbolNumber;
260      int32_t  retval = -1;
261      if (symbolNumber < RING_GetCount(buf))
262      {
263          if (pointer > buf->size) pointer -= buf->size;
264          retval = buf->buffer[ pointer ] ;
265      }
266      return retval;
267  }
268  
269  /** @} */