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 /** @} */