#include "ring_buf.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #define _size_w(n) sizeof(n) / sizeof(int) void rbuf32_init(rbuf_t *rbuf32, uint32_t *buffer, uint32_t size) { rbuf32->buf_ptr = buffer; rbuf32->size = size; rbuf32->read_index = 0; rbuf32->write_index = 0; } void rbuf64_init(rbuf_t *rbuf64, uint64_t *buffer, uint32_t size) { rbuf64->buf_ptr = (uint32_t *)buffer; rbuf64->size = size; rbuf64->read_index = 0; rbuf64->write_index = 0; } bool rbuf_isempty(rbuf_t *rbuf) { if (rbuf->read_index == rbuf->write_index) return true; else return false; } /** * @brief функция определения свободного места в циклическом буфере * (всегда остается одна свободная ячейка) * */ int32_t rbuf_free_space(rbuf_t *rbuf) { int32_t free_space = 0; if(rbuf->write_index == rbuf->read_index) free_space = rbuf->size; else if(rbuf->write_index > rbuf->read_index) free_space = rbuf->size - (rbuf->write_index - rbuf->read_index); else free_space = rbuf->read_index - rbuf->write_index; return free_space; } /** * @brief функция определения заполнения циклического буфера * (всегда остается одна свободная ячейка) * */ int32_t rbuf_full_space(rbuf_t *rbuf) { int32_t full_space = 0; if(rbuf->write_index == rbuf->read_index) full_space = 0; else if(rbuf->write_index > rbuf->read_index) full_space = rbuf->write_index - rbuf->read_index; else full_space = rbuf->size - (rbuf->read_index - rbuf->write_index); return full_space; } bool rbuf_isfull(rbuf_t *rbuf) { int r_tmp; if (rbuf->write_index == (rbuf->size - 1)) { r_tmp = rbuf->read_index + rbuf->size; } else r_tmp = rbuf->read_index; if (r_tmp - rbuf->write_index == 1) return true; else return false; } bool rbuf32_get(rbuf_t *rbuf32, uint32_t *data) { /* Check whether buffer is not empty */ if (!rbuf_isempty(rbuf32)) { *data = rbuf32->buf_ptr[rbuf32->read_index++]; /* swap the read pointer */ if (rbuf32->read_index == (rbuf32->size)) rbuf32->read_index = 0; return true; } else return false; } bool rbuf64_get(rbuf_t *rbuf64, uint64_t *data) { /* Check whether buffer is not empty */ if (!rbuf_isempty(rbuf64)) { *data = *((uint64_t*)rbuf64->buf_ptr + rbuf64->read_index); rbuf64->read_index++; /* swap the read pointer */ if (rbuf64->read_index == (rbuf64->size)) rbuf64->read_index = 0; return true; } else return false; } /* * Oldest data is overwriting when write_ptr reaches read_ptr - 1 (!). * For check use rbuf_isfull. */ bool rbuf32_put(rbuf_t *rbuf32, uint32_t data) { if(!rbuf_isfull(rbuf32)) { rbuf32->buf_ptr[rbuf32->write_index++] = data; /* swap the write pointer */ if (rbuf32->write_index == (rbuf32->size)) rbuf32->write_index = 0; return true; } else return false; } bool rbuf64_put(rbuf_t *rbuf64, uint64_t data) { uint32_t *data_ptr; char size_w = _size_w(data); if(!rbuf_isfull(rbuf64)) { data_ptr = rbuf64->buf_ptr + rbuf64->write_index * size_w; *(uint64_t*)data_ptr = data; rbuf64->write_index++; /* swap the write pointer */ if (rbuf64->write_index == rbuf64->size) rbuf64->write_index = 0; return true; } else return false; } /** * @brief тестовая функция для циклического буфера * */ bool buf_test(void) { rbuf_t rbuf32; rbuf_t rbuf64; uint32_t rbuf_data32[32]; uint64_t rbuf_data64[32]; int i; rbuf32_init(&rbuf32, rbuf_data32, 32); rbuf64_init(&rbuf64, rbuf_data64, 32); bool status_test = true; uint32_t put32 = 0, get32 = 0; uint64_t put64 = 0x5555555555555555, get64 = 0; volatile int j; //DBG printf("capacity 64 = %d\r\n", rbuf64.size); DBG printf("RBUF64 TEST:\r\n"); DBG printf("FULLNESS TEST:\r\n"); i = 0; while (rbuf64_put(&rbuf64, put64++)) { DBG printf("W%d: %.16llX \r\n", i, (long long)rbuf_data64[i]); i ++; j = 1000000; while (j--); } if(i != rbuf64.size - 1) { status_test = false; DBG printf("Failed: i = %d, rbuf64.size = %d\r\n", i, rbuf64.size); } DBG printf("EMPTYNESS TEST:\r\n"); i = 0; while (rbuf64_get(&rbuf64, &get64)) { if(get64 != rbuf_data64[i]) status_test = false; DBG printf("R%d: %.16llX \r\n", i++, (long long)get64); j = 1000000; while (j--); } if(i != rbuf64.size - 1) { status_test = false; DBG printf("Failed\r\n"); } i = 0; put64 = 0x4444444444444444; rbuf64_init(&rbuf64, rbuf_data64, 32); DBG printf("CYCLE TEST:\r\n"); for(i = 0; i < 2*rbuf64.size; i++) { if(rbuf64_put(&rbuf64, put64++)) DBG printf("W%d: %.16llX \r\n", i, (long long)rbuf_data64[i-32*(i/32)]); else { status_test = false; DBG printf("Failed\r\n"); } j = 1000000; while (j--); if(rbuf64_get(&rbuf64, &get64)) { if(get64 != rbuf_data64[i-32*(i/32)]) { status_test = false; DBG printf("Failed\r\n"); } DBG printf("R%d: %.16llX \r\n", i, (long long)get64); } else { status_test = false; DBG printf("Failed\r\n"); } j = 1000000; while (j--); } DBG printf("capacity 32 = %d\r\n", rbuf32.size); DBG printf("RBUF32 TEST:\r\n"); DBG printf("FULLNESS TEST:\r\n"); i = 0; while (rbuf32_put(&rbuf32, put32++)) { DBG printf("W%d: %.16lX \r\n", i, rbuf_data32[i]); i ++; j = 1000000; while (j--); } if(i != rbuf32.size - 1) { status_test = false; DBG printf("Failed\r\n"); } DBG printf("EMPTYNESS TEST:\r\n"); i = 0; while (rbuf32_get(&rbuf32, &get32)) { if(get32 != rbuf_data32[i]) { status_test = false; DBG printf("Failed\r\n"); } DBG printf("R%d: %.16lX \r\n", i++, get32); j = 1000000; while (j--); } if(i != rbuf32.size - 1) { status_test = false; DBG printf("Failed\r\n"); } i = 0; put32 = 0x44444444; rbuf32_init(&rbuf32, rbuf_data32, 32); DBG printf("CYCLE TEST:\r\n"); for(i = 0; i < 2*rbuf32.size; i++) { if(rbuf32_put(&rbuf32, put32++)) DBG printf("W%d: %.16lX \r\n", i, rbuf_data32[i-32*(i/32)]); else { status_test = false; DBG printf("Failed\r\n"); } j = 1000000; while (j--); if(rbuf32_get(&rbuf32, &get32)) { if(get32 != rbuf_data32[i-32*(i/32)]) { status_test = false; DBG printf("Failed\r\n"); } DBG printf("R%d: %.16lX \r\n", i, get32); } else { DBG printf("Failed\r\n"); status_test = false; } j = 1000000; while (j--); } if (status_test) { printf("Test OK\r\n"); } else printf("Test fail\r\n"); return status_test; }