diff --git a/hal/src/main/native/include/MockData/I2CData.h b/hal/src/main/native/include/MockData/I2CData.h new file mode 100644 index 0000000000..cc4595393f --- /dev/null +++ b/hal/src/main/native/include/MockData/I2CData.h @@ -0,0 +1,39 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "HAL/HAL.h" +#include "NotifyListener.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void HALSIM_ResetI2CData(int32_t index); + +int32_t HALSIM_RegisterI2CInitializedCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify); +void HALSIM_CancelI2CInitializedCallback(int32_t index, int32_t uid); +HAL_Bool HALSIM_GetI2CInitialized(int32_t index); +void HALSIM_SetI2CInitialized(int32_t index, HAL_Bool initialized); + +int32_t HALSIM_RegisterI2CReadCallback(int32_t index, + HAL_BufferCallback callback, + void* param); +void HALSIM_CancelI2CReadCallback(int32_t index, int32_t uid); + +int32_t HALSIM_RegisterI2CWriteCallback(int32_t index, + HAL_BufferCallback callback, + void* param); +void HALSIM_CancelI2CWriteCallback(int32_t index, int32_t uid); + +#ifdef __cplusplus +} +#endif diff --git a/hal/src/main/native/include/MockData/NotifyListener.h b/hal/src/main/native/include/MockData/NotifyListener.h index 38eed619fe..42c6aed8cf 100644 --- a/hal/src/main/native/include/MockData/NotifyListener.h +++ b/hal/src/main/native/include/MockData/NotifyListener.h @@ -12,15 +12,21 @@ typedef void (*HAL_NotifyCallback)(const char* name, void* param, const struct HAL_Value* value); +typedef void (*HAL_BufferCallback)(const char* name, void* param, + unsigned char* buffer, unsigned int count); + namespace hal { -struct NotifyListener { - NotifyListener() = default; - NotifyListener(void* param_, HAL_NotifyCallback callback_) + +template +struct HalCallbackListener { + HalCallbackListener() = default; + HalCallbackListener(void* param_, CallbackFunction callback_) : callback(callback_), param(param_) {} explicit operator bool() const { return callback != nullptr; } - HAL_NotifyCallback callback; + CallbackFunction callback; void* param; }; + } // namespace hal diff --git a/hal/src/main/native/include/MockData/NotifyListenerVector.h b/hal/src/main/native/include/MockData/NotifyListenerVector.h index 76e62f29fc..59303fd7b6 100644 --- a/hal/src/main/native/include/MockData/NotifyListenerVector.h +++ b/hal/src/main/native/include/MockData/NotifyListenerVector.h @@ -17,52 +17,121 @@ namespace hal { // Vector which provides an integrated freelist for removal and reuse of // individual elements. -class NotifyListenerVector { + +template +class HalCallbackListenerVectorImpl { struct private_init {}; public: - typedef typename std::vector::size_type size_type; + typedef typename std::vector>::size_type + size_type; // Constructor for creating copies of the vector - NotifyListenerVector(const NotifyListenerVector*, const private_init&); + HalCallbackListenerVectorImpl(const HalCallbackListenerVectorImpl* copyFrom, + const private_init&); // Delete all default constructors so they cannot be used - NotifyListenerVector& operator=(const NotifyListenerVector&) = delete; - NotifyListenerVector() = delete; - NotifyListenerVector(const NotifyListenerVector&) = delete; + HalCallbackListenerVectorImpl& operator=( + const HalCallbackListenerVectorImpl&) = delete; + HalCallbackListenerVectorImpl() = delete; + HalCallbackListenerVectorImpl(const HalCallbackListenerVectorImpl&) = delete; // Create a new vector with a single callback inside of it - NotifyListenerVector(void* param, HAL_NotifyCallback callback, - unsigned int* newUid); + HalCallbackListenerVectorImpl(void* param, ListenerType callback, + unsigned int* newUid) { + *newUid = emplace_back_impl(param, callback); + } size_type size() const { return m_vector.size(); } - NotifyListener& operator[](size_type i) { return m_vector[i]; } - const NotifyListener& operator[](size_type i) const { return m_vector[i]; } + HalCallbackListener& operator[](size_type i) { + return m_vector[i]; + } + const HalCallbackListener& operator[](size_type i) const { + return m_vector[i]; + } // Add a new NotifyListener to a copy of the vector. If there are elements on // the freelist, // reuses the last one; otherwise adds to the end of the vector. // Returns the resulting element index (+1). - std::shared_ptr emplace_back( - void* param, HAL_NotifyCallback callback, unsigned int* newUid); + std::shared_ptr> emplace_back( + void* param, ListenerType callback, unsigned int* newUid); // Removes the identified element by replacing it with a default-constructed // one. The element is added to the freelist for later reuse. Returns a copy - std::shared_ptr erase(unsigned int uid); + std::shared_ptr> erase( + unsigned int uid); private: - std::vector m_vector; + std::vector> m_vector; std::vector m_free; // Add a new NotifyListener to the vector. If there are elements on the // freelist, // reuses the last one; otherwise adds to the end of the vector. // Returns the resulting element index (+1). - unsigned int emplace_back_impl(void* param, HAL_NotifyCallback callback); + unsigned int emplace_back_impl(void* param, ListenerType callback); // Removes the identified element by replacing it with a default-constructed // one. The element is added to the freelist for later reuse. void erase_impl(unsigned int uid); }; +template +HalCallbackListenerVectorImpl::HalCallbackListenerVectorImpl( + const HalCallbackListenerVectorImpl* copyFrom, + const private_init&) + : m_vector(copyFrom->m_vector), m_free(copyFrom->m_free) {} + +template +std::shared_ptr> +HalCallbackListenerVectorImpl::emplace_back( + void* param, ListenerType callback, unsigned int* newUid) { + auto newVector = + std::make_shared>( + this, private_init()); + newVector->m_vector = m_vector; + newVector->m_free = m_free; + *newUid = newVector->emplace_back_impl(param, callback); + return newVector; +} + +template +std::shared_ptr> +HalCallbackListenerVectorImpl::erase(unsigned int uid) { + auto newVector = + std::make_shared>( + this, private_init()); + newVector->m_vector = m_vector; + newVector->m_free = m_free; + newVector->erase_impl(uid); + return newVector; +} + +template +unsigned int HalCallbackListenerVectorImpl::emplace_back_impl( + void* param, ListenerType callback) { + unsigned int uid; + if (m_free.empty()) { + uid = m_vector.size(); + m_vector.emplace_back(param, callback); + } else { + uid = m_free.back(); + m_free.pop_back(); + m_vector[uid] = HalCallbackListener(param, callback); + } + return uid + 1; +} + +template +void HalCallbackListenerVectorImpl::erase_impl(unsigned int uid) { + --uid; + if (uid >= m_vector.size() || !m_vector[uid]) return; + m_free.push_back(uid); + m_vector[uid] = HalCallbackListener(); +} + +typedef HalCallbackListenerVectorImpl NotifyListenerVector; +typedef HalCallbackListenerVectorImpl BufferListenerVector; + } // namespace hal diff --git a/hal/src/main/native/include/MockData/SPIData.h b/hal/src/main/native/include/MockData/SPIData.h new file mode 100644 index 0000000000..109cfbf797 --- /dev/null +++ b/hal/src/main/native/include/MockData/SPIData.h @@ -0,0 +1,52 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "HAL/HAL.h" +#include "NotifyListener.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void HALSIM_ResetSPIData(int32_t index); + +int32_t HALSIM_RegisterSPIInitializedCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify); +void HALSIM_CancelSPIInitializedCallback(int32_t index, int32_t uid); +HAL_Bool HALSIM_GetSPIInitialized(int32_t index); +void HALSIM_SetSPIInitialized(int32_t index, HAL_Bool initialized); + +int32_t HALSIM_RegisterSPIReadCallback(int32_t index, + HAL_BufferCallback callback, + void* param); +void HALSIM_CancelSPIReadCallback(int32_t index, int32_t uid); + +int32_t HALSIM_RegisterSPIWriteCallback(int32_t index, + HAL_BufferCallback callback, + void* param); +void HALSIM_CancelSPIWriteCallback(int32_t index, int32_t uid); + +int32_t HALSIM_RegisterSPIResetAccumulatorCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify); +void HALSIM_CancelSPIResetAccumulatorCallback(int32_t index, int32_t uid); + +int32_t HALSIM_RegisterSPISetAccumulatorCallback(int32_t index, + HAL_BufferCallback callback, + void* param); +void HALSIM_CancelSPISetAccumulatorCallback(int32_t index, int32_t uid); +void HALSIM_SetSPISetAccumulatorValue(int32_t index, int64_t value); +int64_t HALSIM_GetSPIGetAccumulatorValue(int32_t index); + +#ifdef __cplusplus +} +#endif diff --git a/hal/src/main/native/sim/I2C.cpp b/hal/src/main/native/sim/I2C.cpp index d31d0734f4..68c827c76c 100644 --- a/hal/src/main/native/sim/I2C.cpp +++ b/hal/src/main/native/sim/I2C.cpp @@ -7,20 +7,30 @@ #include "HAL/I2C.h" +#include "MockData/I2CDataInternal.h" + +using namespace hal; + extern "C" { -void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {} +void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) { + SimI2CData[port].SetInitialized(true); +} int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* dataToSend, int32_t sendSize, uint8_t* dataReceived, int32_t receiveSize) { + SimI2CData[port].Write(deviceAddress, dataToSend, sendSize); + SimI2CData[port].Read(deviceAddress, dataReceived, receiveSize); return 0; } int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* dataToSend, int32_t sendSize) { + SimI2CData[port].Write(deviceAddress, dataToSend, sendSize); return 0; } int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer, int32_t count) { + SimI2CData[port].Read(deviceAddress, buffer, count); return 0; } -void HAL_CloseI2C(HAL_I2CPort port) {} +void HAL_CloseI2C(HAL_I2CPort port) { SimI2CData[port].SetInitialized(false); } } // extern "C" diff --git a/hal/src/main/native/sim/MockData/I2CData.cpp b/hal/src/main/native/sim/MockData/I2CData.cpp new file mode 100644 index 0000000000..18bd99d2ec --- /dev/null +++ b/hal/src/main/native/sim/MockData/I2CData.cpp @@ -0,0 +1,151 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include + +#include "../PortsInternal.h" +#include "I2CDataInternal.h" +#include "NotifyCallbackHelpers.h" + +using namespace hal; + +I2CData hal::SimI2CData[2]; + +void I2CData::ResetData() { + m_initialized = false; + m_initializedCallbacks = nullptr; + m_readCallbacks = nullptr; +} + +I2CData::I2CData() {} +I2CData::~I2CData() {} + +/////////////////////////////////////////// +// Initialize +/////////////////////////////////////////// +int32_t I2CData::RegisterInitializedCallback(HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_initializedCallbacks = RegisterCallback( + m_initializedCallbacks, "Initialized", callback, param, &newUid); + } + if (initialNotify) { + // We know that the callback is not null because of earlier null check + HAL_Value value = MakeBoolean(GetInitialized()); + callback("Initialized", param, &value); + } + return newUid; +} + +void I2CData::CancelInitializedCallback(int32_t uid) { + m_initializedCallbacks = CancelCallback(m_initializedCallbacks, uid); +} + +void I2CData::InvokeInitializedCallback(HAL_Value value) { + InvokeCallback(m_initializedCallbacks, "Initialized", &value); +} + +HAL_Bool I2CData::GetInitialized() { return m_initialized; } + +void I2CData::SetInitialized(HAL_Bool initialized) { + HAL_Bool oldValue = m_initialized.exchange(initialized); + if (oldValue != initialized) { + InvokeInitializedCallback(MakeBoolean(initialized)); + } +} + +int32_t I2CData::RegisterReadCallback(HAL_BufferCallback callback, + void* param) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_readCallbacks = + RegisterCallback(m_readCallbacks, "Read", callback, param, &newUid); + } + return newUid; +} + +void I2CData::CancelReadCallback(int32_t uid) { + m_readCallbacks = CancelCallback(m_readCallbacks, uid); +} + +int32_t I2CData::RegisterWriteCallback(HAL_BufferCallback callback, + void* param) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_writeCallbacks = + RegisterCallback(m_writeCallbacks, "Write", callback, param, &newUid); + } + return newUid; +} + +void I2CData::CancelWriteCallback(int32_t uid) { + m_writeCallbacks = CancelCallback(m_writeCallbacks, uid); +} + +void I2CData::Write(int32_t deviceAddress, uint8_t* dataToSend, + int32_t sendSize) { + std::lock_guard lock(m_dataMutex); + InvokeCallback(m_writeCallbacks, "Write", dataToSend, sendSize); +} +void I2CData::Read(int32_t deviceAddress, uint8_t* buffer, int32_t count) { + std::lock_guard lock(m_dataMutex); + InvokeCallback(m_readCallbacks, "Read", buffer, count); +} + +extern "C" { +void HALSIM_ResetI2CData(int32_t index) { SimI2CData[index].ResetData(); } + +int32_t HALSIM_RegisterI2CInitializedCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + return SimI2CData[index].RegisterInitializedCallback(callback, param, + initialNotify); +} + +void HALSIM_CancelI2CInitializedCallback(int32_t index, int32_t uid) { + SimI2CData[index].CancelInitializedCallback(uid); +} + +HAL_Bool HALSIM_GetI2CInitialized(int32_t index) { + return SimI2CData[index].GetInitialized(); +} + +void HALSIM_SetI2CInitialized(int32_t index, HAL_Bool initialized) { + SimI2CData[index].SetInitialized(initialized); +} + +int32_t HALSIM_RegisterI2CReadCallback(int32_t index, + HAL_BufferCallback callback, + void* param) { + return SimI2CData[index].RegisterReadCallback(callback, param); +} +void HALSIM_CancelI2CReadCallback(int32_t index, int32_t uid) { + SimI2CData[index].CancelReadCallback(uid); +} + +int32_t HALSIM_RegisterI2CWriteCallback(int32_t index, + HAL_BufferCallback callback, + void* param) { + return SimI2CData[index].RegisterWriteCallback(callback, param); +} +void HALSIM_CancelI2CWriteCallback(int32_t index, int32_t uid) { + SimI2CData[index].CancelWriteCallback(uid); +} + +} // extern c diff --git a/hal/src/main/native/sim/MockData/I2CDataInternal.h b/hal/src/main/native/sim/MockData/I2CDataInternal.h new file mode 100644 index 0000000000..2c9550435a --- /dev/null +++ b/hal/src/main/native/sim/MockData/I2CDataInternal.h @@ -0,0 +1,50 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +#include "MockData/I2CData.h" +#include "MockData/NotifyListenerVector.h" + +namespace hal { +class I2CData { + public: + I2CData(); + ~I2CData(); + + int32_t RegisterInitializedCallback(HAL_NotifyCallback callback, void* param, + HAL_Bool initialNotify); + void CancelInitializedCallback(int32_t uid); + void InvokeInitializedCallback(HAL_Value value); + HAL_Bool GetInitialized(); + void SetInitialized(HAL_Bool initialized); + + int32_t RegisterReadCallback(HAL_BufferCallback callback, void* param); + void CancelReadCallback(int32_t uid); + + int32_t RegisterWriteCallback(HAL_BufferCallback callback, void* param); + void CancelWriteCallback(int32_t uid); + + void Write(int32_t deviceAddress, uint8_t* dataToSend, int32_t sendSize); + void Read(int32_t deviceAddress, uint8_t* buffer, int32_t count); + + void ResetData(); + + private: + std::mutex m_registerMutex; + std::mutex m_dataMutex; + std::atomic m_initialized{false}; + std::shared_ptr m_initializedCallbacks = nullptr; + std::shared_ptr m_readCallbacks = nullptr; + std::shared_ptr m_writeCallbacks = nullptr; +}; +extern I2CData SimI2CData[]; +} // namespace hal diff --git a/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.cpp b/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.cpp index c07a9e5a49..567d3f8f76 100644 --- a/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.cpp +++ b/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.cpp @@ -9,12 +9,13 @@ using namespace hal; -std::shared_ptr RegisterCallback( - std::shared_ptr currentVector, const char* name, - HAL_NotifyCallback callback, void* param, int32_t* newUid) { - std::shared_ptr newCallbacks; +template +std::shared_ptr RegisterCallbackImpl( + std::shared_ptr currentVector, const char* name, + CallbackType callback, void* param, int32_t* newUid) { + std::shared_ptr newCallbacks; if (currentVector == nullptr) { - newCallbacks = std::make_shared( + newCallbacks = std::make_shared( param, callback, reinterpret_cast(newUid)); } else { newCallbacks = currentVector->emplace_back( @@ -23,13 +24,27 @@ std::shared_ptr RegisterCallback( return newCallbacks; } -std::shared_ptr CancelCallback( - std::shared_ptr currentVector, int32_t uid) { +template +std::shared_ptr CancelCallbackImpl( + std::shared_ptr currentVector, int32_t uid) { // Create a copy of the callbacks to erase from auto newCallbacks = currentVector->erase(uid); return newCallbacks; } +std::shared_ptr RegisterCallback( + std::shared_ptr currentVector, const char* name, + HAL_NotifyCallback callback, void* param, int32_t* newUid) { + return RegisterCallbackImpl( + currentVector, name, callback, param, newUid); +} + +std::shared_ptr CancelCallback( + std::shared_ptr currentVector, int32_t uid) { + return CancelCallbackImpl( + currentVector, uid); +} + void InvokeCallback(std::shared_ptr currentVector, const char* name, const HAL_Value* value) { // Return if no callbacks are assigned @@ -42,3 +57,29 @@ void InvokeCallback(std::shared_ptr currentVector, listener.callback(name, listener.param, value); } } + +std::shared_ptr RegisterCallback( + std::shared_ptr currentVector, const char* name, + HAL_BufferCallback callback, void* param, int32_t* newUid) { + return RegisterCallbackImpl( + currentVector, name, callback, param, newUid); +} + +std::shared_ptr CancelCallback( + std::shared_ptr currentVector, int32_t uid) { + return CancelCallbackImpl( + currentVector, uid); +} + +void InvokeCallback(std::shared_ptr currentVector, + const char* name, uint8_t* buffer, int32_t count) { + // Return if no callbacks are assigned + if (currentVector == nullptr) return; + // Get a copy of the shared_ptr, then iterate and callback listeners + auto newCallbacks = currentVector; + for (size_t i = 0; i < newCallbacks->size(); ++i) { + if (!(*newCallbacks)[i]) continue; // removed + auto listener = (*newCallbacks)[i]; + listener.callback(name, listener.param, buffer, count); + } +} diff --git a/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.h b/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.h index 4f8e9e4cea..7e598a481f 100644 --- a/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.h +++ b/hal/src/main/native/sim/MockData/NotifyCallbackHelpers.h @@ -20,3 +20,13 @@ std::shared_ptr CancelCallback( void InvokeCallback(std::shared_ptr currentVector, const char* name, const HAL_Value* value); + +std::shared_ptr RegisterCallback( + std::shared_ptr currentVector, const char* name, + HAL_BufferCallback callback, void* param, int32_t* newUid); + +std::shared_ptr CancelCallback( + std::shared_ptr currentVector, int32_t uid); + +void InvokeCallback(std::shared_ptr currentVector, + const char* name, uint8_t* buffer, int32_t count); diff --git a/hal/src/main/native/sim/MockData/NotifyListenerVector.cpp b/hal/src/main/native/sim/MockData/NotifyListenerVector.cpp deleted file mode 100644 index e92d51aaa7..0000000000 --- a/hal/src/main/native/sim/MockData/NotifyListenerVector.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) 2017 FIRST. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -#include "MockData/NotifyListenerVector.h" - -using namespace hal; - -NotifyListenerVector::NotifyListenerVector(const NotifyListenerVector* copyFrom, - const private_init&) - : m_vector(copyFrom->m_vector), m_free(copyFrom->m_free) {} - -NotifyListenerVector::NotifyListenerVector(void* param, - HAL_NotifyCallback callback, - unsigned int* newUid) { - *newUid = emplace_back_impl(param, callback); -} - -std::shared_ptr NotifyListenerVector::emplace_back( - void* param, HAL_NotifyCallback callback, unsigned int* newUid) { - auto newVector = std::make_shared(this, private_init()); - newVector->m_vector = m_vector; - newVector->m_free = m_free; - *newUid = newVector->emplace_back_impl(param, callback); - return newVector; -} - -std::shared_ptr NotifyListenerVector::erase( - unsigned int uid) { - auto newVector = std::make_shared(this, private_init()); - newVector->m_vector = m_vector; - newVector->m_free = m_free; - newVector->erase_impl(uid); - return newVector; -} - -unsigned int NotifyListenerVector::emplace_back_impl( - void* param, HAL_NotifyCallback callback) { - unsigned int uid; - if (m_free.empty()) { - uid = m_vector.size(); - m_vector.emplace_back(param, callback); - } else { - uid = m_free.back(); - m_free.pop_back(); - m_vector[uid] = NotifyListener(param, callback); - } - return uid + 1; -} - -void NotifyListenerVector::erase_impl(unsigned int uid) { - --uid; - if (uid >= m_vector.size() || !m_vector[uid]) return; - m_free.push_back(uid); - m_vector[uid] = NotifyListener(); -} diff --git a/hal/src/main/native/sim/MockData/SPIData.cpp b/hal/src/main/native/sim/MockData/SPIData.cpp new file mode 100644 index 0000000000..8ab0aec223 --- /dev/null +++ b/hal/src/main/native/sim/MockData/SPIData.cpp @@ -0,0 +1,247 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include + +#include "../PortsInternal.h" +#include "NotifyCallbackHelpers.h" +#include "SPIDataInternal.h" + +using namespace hal; + +SPIData hal::SimSPIData[5]; + +void SPIData::ResetData() { + m_initialized = false; + m_accumulatorValue = 0; + m_initializedCallbacks = nullptr; + m_readCallbacks = nullptr; + m_writeCallbacks = nullptr; + m_resetAccumulatorCallback = nullptr; + m_setAccumulatorCallback = nullptr; +} + +SPIData::SPIData() {} +SPIData::~SPIData() {} + +int32_t SPIData::RegisterInitializedCallback(HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_initializedCallbacks = RegisterCallback( + m_initializedCallbacks, "Initialized", callback, param, &newUid); + } + if (initialNotify) { + // We know that the callback is not null because of earlier null check + HAL_Value value = MakeBoolean(GetInitialized()); + callback("Initialized", param, &value); + } + return newUid; +} + +void SPIData::CancelInitializedCallback(int32_t uid) { + m_initializedCallbacks = CancelCallback(m_initializedCallbacks, uid); +} + +void SPIData::InvokeInitializedCallback(HAL_Value value) { + InvokeCallback(m_initializedCallbacks, "Initialized", &value); +} + +HAL_Bool SPIData::GetInitialized() { return m_initialized; } + +void SPIData::SetInitialized(HAL_Bool initialized) { + HAL_Bool oldValue = m_initialized.exchange(initialized); + if (oldValue != initialized) { + InvokeInitializedCallback(MakeBoolean(initialized)); + } +} + +int32_t SPIData::RegisterReadCallback(HAL_BufferCallback callback, + void* param) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_readCallbacks = + RegisterCallback(m_readCallbacks, "Read", callback, param, &newUid); + } + + return newUid; +} + +void SPIData::CancelReadCallback(int32_t uid) { + m_readCallbacks = CancelCallback(m_readCallbacks, uid); +} + +int32_t SPIData::RegisterWriteCallback(HAL_BufferCallback callback, + void* param) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_writeCallbacks = + RegisterCallback(m_writeCallbacks, "Write", callback, param, &newUid); + } + + return newUid; +} + +void SPIData::CancelWriteCallback(int32_t uid) { + m_writeCallbacks = CancelCallback(m_writeCallbacks, uid); +} + +int32_t SPIData::RegisterResetAccumulatorCallback(HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_resetAccumulatorCallback = + RegisterCallback(m_resetAccumulatorCallback, "ResetAccumulator", + callback, param, &newUid); + } + if (initialNotify) { + // We know that the callback is not null because of earlier null check + HAL_Value value = MakeBoolean(GetInitialized()); + callback("ResetAccumulator", param, &value); + } + return newUid; +} + +void SPIData::CancelResetAccumulatorCallback(int32_t uid) { + m_resetAccumulatorCallback = CancelCallback(m_resetAccumulatorCallback, uid); +} + +int32_t SPIData::RegisterAccumulatorCallback(HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + // Must return -1 on a null callback for error handling + if (callback == nullptr) return -1; + int32_t newUid = 0; + { + std::lock_guard lock(m_registerMutex); + m_setAccumulatorCallback = RegisterCallback( + m_setAccumulatorCallback, "SetAccumulator", callback, param, &newUid); + } + if (initialNotify) { + // We know that the callback is not null because of earlier null check + HAL_Value value = MakeInt(GetAccumulatorValue()); + callback("SetAccumulator", param, &value); + } + return newUid; +} + +void SPIData::CancelAccumulatorCallback(int32_t uid) { + m_setAccumulatorCallback = CancelCallback(m_setAccumulatorCallback, uid); +} + +void SPIData::InvokeSetAccumulatorCallback(HAL_Value value) { + InvokeCallback(m_setAccumulatorCallback, "SetAccumulator", &value); +} + +void SPIData::SetAccumulatorValue(int64_t value) { + int64_t oldValue = m_accumulatorValue.exchange(value); + if (oldValue != value) { + InvokeSetAccumulatorCallback(MakeLong(value)); + } +} + +int64_t SPIData::GetAccumulatorValue() { return m_accumulatorValue; } + +int32_t SPIData::Read(uint8_t* buffer, int32_t count) { + std::lock_guard lock(m_dataMutex); + InvokeCallback(m_readCallbacks, "Read", buffer, count); + + return count; +} + +int32_t SPIData::Write(uint8_t* dataToSend, int32_t sendSize) { + std::lock_guard lock(m_dataMutex); + InvokeCallback(m_writeCallbacks, "Write", dataToSend, sendSize); + + return sendSize; +} + +int32_t SPIData::Transaction(uint8_t* dataToSend, uint8_t* dataReceived, + int32_t size) { + std::lock_guard lock(m_dataMutex); + return size; +} + +void SPIData::ResetAccumulator() { + HAL_Value value = MakeInt(0); + InvokeCallback(m_resetAccumulatorCallback, "ResetAccumulator", &value); +} + +extern "C" { +void HALSIM_ResetSPIData(int32_t index) { SimSPIData[index].ResetData(); } + +int32_t HALSIM_RegisterSPIInitializedCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + return SimSPIData[index].RegisterInitializedCallback(callback, param, + initialNotify); +} + +void HALSIM_CancelSPIInitializedCallback(int32_t index, int32_t uid) { + SimSPIData[index].CancelInitializedCallback(uid); +} + +HAL_Bool HALSIM_GetSPIInitialized(int32_t index) { + return SimSPIData[index].GetInitialized(); +} + +void HALSIM_SetSPIInitialized(int32_t index, HAL_Bool initialized) { + SimSPIData[index].SetInitialized(initialized); +} + +int32_t HALSIM_RegisterSPIReadCallback(int32_t index, + HAL_BufferCallback callback, + void* param) { + return SimSPIData[index].RegisterReadCallback(callback, param); +} +void HALSIM_CancelSPIReadCallback(int32_t index, int32_t uid) { + SimSPIData[index].CancelReadCallback(uid); +} + +int32_t HALSIM_RegisterSPIWriteCallback(int32_t index, + HAL_BufferCallback callback, + void* param) { + return SimSPIData[index].RegisterWriteCallback(callback, param); +} +void HALSIM_CancelSPIWriteCallback(int32_t index, int32_t uid) { + SimSPIData[index].CancelWriteCallback(uid); +} + +int32_t HALSIM_RegisterSPIResetAccumulatorCallback(int32_t index, + HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify) { + return SimSPIData[index].RegisterResetAccumulatorCallback(callback, param, + initialNotify); +} +void HALSIM_CancelSPIResetAccumulatorCallback(int32_t index, int32_t uid) { + SimSPIData[index].CancelResetAccumulatorCallback(uid); +} + +void HALSIM_SetSPISetAccumulatorValue(int32_t index, int64_t value) { + SimSPIData[index].SetAccumulatorValue(value); +} +int64_t HALSIM_GetSPIGetAccumulatorValue(int32_t index) { + return SimSPIData[index].GetAccumulatorValue(); +} + +} // extern c diff --git a/hal/src/main/native/sim/MockData/SPIDataInternal.h b/hal/src/main/native/sim/MockData/SPIDataInternal.h new file mode 100644 index 0000000000..eeefdef0e7 --- /dev/null +++ b/hal/src/main/native/sim/MockData/SPIDataInternal.h @@ -0,0 +1,66 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2017 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +#include "MockData/NotifyListenerVector.h" +#include "MockData/SPIData.h" + +namespace hal { +class SPIData { + public: + SPIData(); + ~SPIData(); + + int32_t RegisterInitializedCallback(HAL_NotifyCallback callback, void* param, + HAL_Bool initialNotify); + void CancelInitializedCallback(int32_t uid); + void InvokeInitializedCallback(HAL_Value value); + HAL_Bool GetInitialized(); + void SetInitialized(HAL_Bool initialized); + + int32_t RegisterReadCallback(HAL_BufferCallback callback, void* param); + void CancelReadCallback(int32_t uid); + + int32_t RegisterWriteCallback(HAL_BufferCallback callback, void* param); + void CancelWriteCallback(int32_t uid); + + int32_t RegisterResetAccumulatorCallback(HAL_NotifyCallback callback, + void* param, HAL_Bool initialNotify); + void CancelResetAccumulatorCallback(int32_t uid); + + int32_t RegisterAccumulatorCallback(HAL_NotifyCallback callback, void* param, + HAL_Bool initialNotify); + void CancelAccumulatorCallback(int32_t uid); + void InvokeSetAccumulatorCallback(HAL_Value value); + void SetAccumulatorValue(int64_t value); + int64_t GetAccumulatorValue(); + + int32_t Read(uint8_t* buffer, int32_t count); + int32_t Write(uint8_t* dataToSend, int32_t sendSize); + int32_t Transaction(uint8_t* dataToSend, uint8_t* dataReceived, int32_t size); + void ResetAccumulator(); + + void ResetData(); + + private: + std::mutex m_registerMutex; + std::mutex m_dataMutex; + std::atomic m_initialized{false}; + std::atomic m_accumulatorValue{false}; + std::shared_ptr m_initializedCallbacks = nullptr; + std::shared_ptr m_readCallbacks = nullptr; + std::shared_ptr m_writeCallbacks = nullptr; + std::shared_ptr m_resetAccumulatorCallback = nullptr; + std::shared_ptr m_setAccumulatorCallback = nullptr; +}; +extern SPIData SimSPIData[]; +} // namespace hal diff --git a/hal/src/main/native/sim/SPI.cpp b/hal/src/main/native/sim/SPI.cpp index ab307f6236..8339cadd94 100644 --- a/hal/src/main/native/sim/SPI.cpp +++ b/hal/src/main/native/sim/SPI.cpp @@ -7,18 +7,24 @@ #include "HAL/SPI.h" -void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) {} +#include "MockData/SPIDataInternal.h" + +using namespace hal; + +void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { + SimSPIData[port].SetInitialized(true); +} int32_t HAL_TransactionSPI(HAL_SPIPort port, uint8_t* dataToSend, uint8_t* dataReceived, int32_t size) { - return 0; + return SimSPIData[port].Transaction(dataToSend, dataReceived, size); } int32_t HAL_WriteSPI(HAL_SPIPort port, uint8_t* dataToSend, int32_t sendSize) { - return 0; + return SimSPIData[port].Write(dataToSend, sendSize); } int32_t HAL_ReadSPI(HAL_SPIPort port, uint8_t* buffer, int32_t count) { - return 0; + return SimSPIData[port].Read(buffer, count); } -void HAL_CloseSPI(HAL_SPIPort port) {} +void HAL_CloseSPI(HAL_SPIPort port) { SimSPIData[port].SetInitialized(false); } void HAL_SetSPISpeed(HAL_SPIPort port, int32_t speed) {} void HAL_SetSPIOpts(HAL_SPIPort port, HAL_Bool msbFirst, HAL_Bool sampleOnTrailing, HAL_Bool clkIdleHigh) {} @@ -33,7 +39,9 @@ void HAL_InitSPIAccumulator(HAL_SPIPort port, int32_t period, int32_t cmd, int32_t dataSize, HAL_Bool isSigned, HAL_Bool bigEndian, int32_t* status) {} void HAL_FreeSPIAccumulator(HAL_SPIPort port, int32_t* status) {} -void HAL_ResetSPIAccumulator(HAL_SPIPort port, int32_t* status) {} +void HAL_ResetSPIAccumulator(HAL_SPIPort port, int32_t* status) { + SimSPIData[port].ResetAccumulator(); +} void HAL_SetSPIAccumulatorCenter(HAL_SPIPort port, int32_t center, int32_t* status) {} void HAL_SetSPIAccumulatorDeadband(HAL_SPIPort port, int32_t deadband, @@ -42,7 +50,7 @@ int32_t HAL_GetSPIAccumulatorLastValue(HAL_SPIPort port, int32_t* status) { return 0; } int64_t HAL_GetSPIAccumulatorValue(HAL_SPIPort port, int32_t* status) { - return 0; + return SimSPIData[port].GetAccumulatorValue(); } int64_t HAL_GetSPIAccumulatorCount(HAL_SPIPort port, int32_t* status) { return 0;