#pragma once
#include <wpi/mutex.h>
#include "hal/ChipObject.h"
#include "hal/Types.h"
namespace hal {
struct DIOSetProxy {
DIOSetProxy(tDIO::tOutputEnable setOutputDirReg,
tDIO::tOutputEnable unsetOutputDirReg,
tDIO::tDO setOutputStateReg, tDIO::tDO unsetOutputStateReg,
tDIO* dio)
: m_setOutputDirReg{setOutputDirReg},
m_unsetOutputDirReg{unsetOutputDirReg},
m_setOutputStateReg{setOutputStateReg},
m_unsetOutputStateReg{unsetOutputStateReg},
m_dio{dio} {}
DIOSetProxy(const DIOSetProxy&) = delete;
DIOSetProxy(DIOSetProxy&&) = delete;
DIOSetProxy& operator=(const DIOSetProxy&) = delete;
DIOSetProxy& operator=(DIOSetProxy&&) = delete;
void SetOutputMode(int32_t* status) {
m_dio->writeOutputEnable(m_setOutputDirReg, status);
}
void SetInputMode(int32_t* status) {
m_dio->writeOutputEnable(m_unsetOutputDirReg, status);
}
void SetOutputTrue(int32_t* status) {
m_dio->writeDO(m_setOutputStateReg, status);
}
void SetOutputFalse(int32_t* status) {
m_dio->writeDO(m_unsetOutputStateReg, status);
}
tDIO::tOutputEnable m_setOutputDirReg;
tDIO::tOutputEnable m_unsetOutputDirReg;
tDIO::tDO m_setOutputStateReg;
tDIO::tDO m_unsetOutputStateReg;
tDIO* m_dio;
};
namespace detail {
wpi::mutex& UnsafeGetDIOMutex();
tDIO* UnsafeGetDigitalSystem();
int32_t ComputeDigitalMask(HAL_DigitalHandle handle, int32_t* status);
}
template <typename Functor>
void UnsafeManipulateDIO(HAL_DigitalHandle handle, int32_t* status,
Functor func) {
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
wpi::mutex& dioMutex = detail::UnsafeGetDIOMutex();
tDIO* dSys = detail::UnsafeGetDigitalSystem();
auto mask = detail::ComputeDigitalMask(handle, status);
if (*status != 0) {
return;
}
std::scoped_lock lock(dioMutex);
tDIO::tOutputEnable enableOE = dSys->readOutputEnable(status);
enableOE.value |= mask;
auto disableOE = enableOE;
disableOE.value &= ~mask;
tDIO::tDO enableDO = dSys->readDO(status);
enableDO.value |= mask;
auto disableDO = enableDO;
disableDO.value &= ~mask;
DIOSetProxy dioData{enableOE, disableOE, enableDO, disableDO, dSys};
func(dioData);
}
}