Skip to content

Commit

Permalink
Use pimpl idiom in spi class
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilchmela committed Sep 20, 2024
1 parent e7de75c commit a0c12c5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 19 deletions.
71 changes: 64 additions & 7 deletions Sts1CobcSw/Hal/Spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,93 @@

namespace sts1cobcsw::hal
{
class Spi::Impl
{
public:
Impl(RODOS::SPI_IDX spiIndex,
RODOS::GPIO_PIN sckPin,
RODOS::GPIO_PIN misoPin,
RODOS::GPIO_PIN mosiPin)
: spi_(spiIndex, sckPin, misoPin, mosiPin, spiNssDummyPin)
{
this->transferEnd_.put(RODOS::END_OF_TIME);
}


auto PutTransferEnd(std::int64_t transferEnd) const -> void
{
this->transferEnd_.put(transferEnd);
}


auto GetTransferEnd(std::int64_t transferEnd) const -> void
{
this->transferEnd_.get(transferEnd);
}


auto Initialize(std::uint32_t baudRate) -> void
{
// spi.init() only returns -1 if the SPI_IDX is out of range. Since we can check that
// statically we do not need to report that error at runtime.
this->spi_.init(baudRate, /*slave=*/false, /*tiMode=*/false);
this->PutTransferEnd(RODOS::END_OF_TIME);
}


auto BaudRate() -> std::int32_t
{
return this->spi_.status(RODOS::SPI_STATUS_BAUDRATE);
}


template<typename T, std::size_t extent>
auto SpiWrite(std::span<T, extent> data) -> void
{
this->spi_.write(data.data(), data.size_bytes());
}


template<typename T, std::size_t extent>
auto SpiRead(std::span<T, extent> data) -> void
{
this->spi_.read(data.data(), data.size_bytes());
}


private:
RODOS::HAL_SPI spi_;
mutable RODOS::CommBuffer<std::int64_t> transferEnd_;
};

Spi::Spi(RODOS::SPI_IDX spiIndex,
RODOS::GPIO_PIN sckPin,
RODOS::GPIO_PIN misoPin,
RODOS::GPIO_PIN mosiPin)
: spi_(spiIndex, sckPin, misoPin, mosiPin, spiNssDummyPin)
: pimpl{std::make_unique<Impl>(spiIndex, sckPin, misoPin, mosiPin)}
{
transferEnd_.put(RODOS::END_OF_TIME);
}


auto Initialize(Spi * spi, std::uint32_t baudRate) -> void
{
// spi.init() only returns -1 if the SPI_IDX is out of range. Since we can check that statically
// we do not need to report that error at runtime.
spi->spi_.init(baudRate, /*slave=*/false, /*tiMode=*/false);
spi->transferEnd_.put(RODOS::END_OF_TIME);
spi->pimpl->Initialize(baudRate);
}


auto Spi::TransferEnd() const -> RodosTime
{
std::int64_t transferEnd = 0;
this->transferEnd_.get(transferEnd);
this->pimpl->GetTransferEnd(transferEnd);
return RodosTime(transferEnd);
}


auto Spi::BaudRate() -> std::int32_t
{
return this->spi_.status(RODOS::SPI_STATUS_BAUDRATE);
return this->pimpl->BaudRate();
}


Expand All @@ -47,4 +104,4 @@ auto Initialize(RODOS::HAL_SPI * spi, std::uint32_t baudRate) -> void
// we do not need to report that error at runtime.
spi->init(baudRate, /*slave=*/false, /*tiMode=*/false);
}
}
}
14 changes: 8 additions & 6 deletions Sts1CobcSw/Hal/Spi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

#include <cstddef>
#include <cstdint>
#include <memory>
#include <span>

#include "Sts1CobcSw/Utility/TimeTypes.hpp"
#include <experimental/propagate_const>


namespace sts1cobcsw::hal
Expand All @@ -34,21 +36,21 @@ class Spi


private:
RODOS::HAL_SPI spi_;
mutable RODOS::CommBuffer<std::int64_t> transferEnd_;
class Impl;
std::experimental::propagate_const<std::unique_ptr<Impl>> pimpl;
};


auto Initialize(RODOS::HAL_SPI * spi, std::uint32_t baudRate) -> void;
auto Initialize(Spi * spi, std::uint32_t baudRate) -> void;

// TODO: Maybe remove extent to reduce code bloat, or probably build time since it is just a single
// call to the Rodos function, which is trivial to inline.
template<typename T, std::size_t extent>
auto WriteTo(RODOS::HAL_SPI * spi, std::span<T const, extent> data) -> void;
auto WriteTo(Spi * spi, std::span<T const, extent> data) -> void;

template<typename T, std::size_t extent>
auto ReadFrom(RODOS::HAL_SPI * spi, std::span<T, extent> data) -> void;
auto ReadFrom(Spi * spi, std::span<T, extent> data) -> void;
}


#include <Sts1CobcSw/Hal/Spi.ipp> // IWYU pragma: keep
#include <Sts1CobcSw/Hal/Spi.ipp> // IWYU pragma: keep
12 changes: 6 additions & 6 deletions Sts1CobcSw/Hal/Spi.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ auto WriteTo(Spi * spi, std::span<T const, extent> data, Duration timeout) -> vo
// spi.write() only returns -1 or the given buffer length. It only returns -1 if the SPI is not
// initialized, which we can check/ensure statically. Therefore, we do not need to check the
// return value at runtime.
spi->transferEnd_.put(RODOS::NOW() + value_of(timeout));
spi->spi_.write(data.data(), data.size_bytes());
spi->transferEnd_.put(RODOS::END_OF_TIME);
spi->pimpl->PutTransferEnd(RODOS::NOW() + value_of(timeout));
spi->pimpl->SpiWrite(data);
spi->pimpl->PutTransferEnd(RODOS::END_OF_TIME);
}


Expand All @@ -28,9 +28,9 @@ auto ReadFrom(Spi * spi, std::span<T, extent> data, Duration timeout) -> void
// spi.read() only returns -1 or the given buffer length. It only returns -1 if the SPI is not
// initialized, which we can check/ensure statically. Therefore, we do not need to check the
// return value at runtime.
spi->transferEnd_.put(RODOS::NOW() + value_of(timeout));
spi->spi_.read(data.data(), data.size_bytes());
spi->transferEnd_.put(RODOS::END_OF_TIME);
spi->pimpl->PutTransferEnd(RODOS::NOW() + value_of(timeout));
spi->pimpl->SpiRead(data);
spi->pimpl->PutTransferEnd(RODOS::END_OF_TIME);
}


Expand Down

0 comments on commit a0c12c5

Please sign in to comment.