diff --git a/Sts1CobcSw/Periphery/FramRingBuffer.cpp b/Sts1CobcSw/Periphery/FramRingBuffer.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Sts1CobcSw/Periphery/FramRingBuffer.hpp b/Sts1CobcSw/Periphery/FramRingBuffer.hpp new file mode 100644 index 00000000..9034bf4a --- /dev/null +++ b/Sts1CobcSw/Periphery/FramRingBuffer.hpp @@ -0,0 +1,101 @@ +#pragma once + + +#include + +#include +#include +#include +#include + + +namespace sts1cobcsw::fram +{ + +template +class RingBuffer +{ +public: + Address startAddress; + std::uint32_t writeIndex = 0; + std::uint32_t readIndex = 0; + std::uint32_t currentWrite = UINT32_MAX; + std::array vals; + +public: + std::uint64_t writeCnt = 0; + std::uint64_t readCnt = 0; + std::uint32_t occupiedCnt = 0; + + RingBuffer(Address startAddress) : startAddress(startAddress) + { + } + + T * getNextEntryToPut() + { + return &vals[writeIndex]; + } + + void put(T const & newdata) + { + currentWrite = writeIndex; + Address address = startAddress + writeIndex * sizeof(T); + + WriteTo(address, reinterpret_cast(&newdata), sizeof(T), 0); + writeIndex++; + + if(writeIndex >= poolSize) + { + writeIndex = 0; + } + if(occupiedCnt < poolSize) + { + occupiedCnt++; + } + writeCnt++; + currentWrite = UINT32_MAX; + } + + // Get next item + void get(T & fromRing) + { + // Jump the current being written record + if(readIndex == currentWrite) + { + readIndex++; + } + if(readIndex >= poolSize) + { + readIndex = 0; + } + + // readIndex should not pass write index if there is no data after it + if(writeCnt < poolSize && readIndex >= writeIndex) + { + readIndex = 0; + } + + Address address = startAddress + readIndex * sizeof(T); + std::array buffer; + ReadFrom(address, buffer, 0); + fromRing = *reinterpret_cast(buffer.data()); + + readIndex++; + if(readIndex >= poolSize) + { + readIndex = 0; + } + + if(occupiedCnt > 0) + { + occupiedCnt--; + } + readCnt++; + } + + int getLen() + { + return poolSize; + } +}; +} \ No newline at end of file diff --git a/Tests/UnitTests/CMakeLists.txt b/Tests/UnitTests/CMakeLists.txt index 53b5d70e..ceea962a 100644 --- a/Tests/UnitTests/CMakeLists.txt +++ b/Tests/UnitTests/CMakeLists.txt @@ -11,6 +11,9 @@ target_link_libraries( Sts1CobcSw_Utility ) +add_program(RingBuffer FramRingBuffer.test.cpp) +target_link_libraries(Sts1CobcSwTests_RingBuffer PRIVATE Catch2::Catch2WithMain) + # TODO: Enable again once problem with segmentation violation on CI is fixed add_program(LfsRam LfsRam.test.cpp) target_link_libraries(Sts1CobcSwTests_LfsRam PRIVATE Catch2::Catch2WithMain Sts1CobcSw_FileSystem) diff --git a/Tests/UnitTests/FramRingBuffer.test.cpp b/Tests/UnitTests/FramRingBuffer.test.cpp new file mode 100644 index 00000000..42fe8f64 --- /dev/null +++ b/Tests/UnitTests/FramRingBuffer.test.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + + +TEST_CASE("RODOS ringbuffer put and get operations") +{ + + RODOS::RingBuffer buffer; + + REQUIRE(buffer.getLen() == 10); + + int value = 42; + int result; + buffer.put(value); + buffer.get(result); + REQUIRE(value == result); +} + +TEST_CASE("RODOS ringbuffer overwrite") +{ + + RODOS::RingBuffer buffer; + REQUIRE(buffer.getLen() == 10); + + for(int i = 0; i < 15; i++) + { + buffer.put(i); + } + + int result; + for(int i = 10; i < 15; ++i) + { + buffer.get(result); + REQUIRE(result == i); + } +} + +TEST_CASE("RODOS ringbuffer wrapping") +{ + + RODOS::RingBuffer buffer; + for(int i = 0; i < 30; ++i) + { + buffer.put(i); + } + + int result; + for(int i = 20; i < 30; ++i) + { + buffer.get(result); + REQUIRE(result == i); + } + + +} + +// TODO: Split in differents tests or sections +TEST_CASE("RingBuffer put and get operations") +{ +} \ No newline at end of file