SPI and I2C simulator (#662)

* Creating SPI and I2C simulation abilities

* Update the callback helpers to support different function callback
types
* Create callback type that uses a buffer
* Created I2C/SPI data classes that manage the callbacks and don't do
much of anything else

* Ran format, cleaned up some issues
This commit is contained in:
PJ Reiniger
2017-10-19 02:01:58 -04:00
committed by Peter Johnson
parent be77f9cb26
commit 3c842d8234
13 changed files with 784 additions and 94 deletions

View File

@@ -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

View File

@@ -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 <typename CallbackFunction>
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

View File

@@ -17,52 +17,121 @@
namespace hal {
// Vector which provides an integrated freelist for removal and reuse of
// individual elements.
class NotifyListenerVector {
template <typename ListenerType>
class HalCallbackListenerVectorImpl {
struct private_init {};
public:
typedef typename std::vector<NotifyListener>::size_type size_type;
typedef typename std::vector<HalCallbackListener<ListenerType>>::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<ListenerType>& operator[](size_type i) {
return m_vector[i];
}
const HalCallbackListener<ListenerType>& 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<NotifyListenerVector> emplace_back(
void* param, HAL_NotifyCallback callback, unsigned int* newUid);
std::shared_ptr<HalCallbackListenerVectorImpl<ListenerType>> 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<NotifyListenerVector> erase(unsigned int uid);
std::shared_ptr<HalCallbackListenerVectorImpl<ListenerType>> erase(
unsigned int uid);
private:
std::vector<NotifyListener> m_vector;
std::vector<HalCallbackListener<ListenerType>> m_vector;
std::vector<unsigned int> 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 <typename ListenerType>
HalCallbackListenerVectorImpl<ListenerType>::HalCallbackListenerVectorImpl(
const HalCallbackListenerVectorImpl<ListenerType>* copyFrom,
const private_init&)
: m_vector(copyFrom->m_vector), m_free(copyFrom->m_free) {}
template <typename ListenerType>
std::shared_ptr<HalCallbackListenerVectorImpl<ListenerType>>
HalCallbackListenerVectorImpl<ListenerType>::emplace_back(
void* param, ListenerType callback, unsigned int* newUid) {
auto newVector =
std::make_shared<HalCallbackListenerVectorImpl<ListenerType>>(
this, private_init());
newVector->m_vector = m_vector;
newVector->m_free = m_free;
*newUid = newVector->emplace_back_impl(param, callback);
return newVector;
}
template <typename ListenerType>
std::shared_ptr<HalCallbackListenerVectorImpl<ListenerType>>
HalCallbackListenerVectorImpl<ListenerType>::erase(unsigned int uid) {
auto newVector =
std::make_shared<HalCallbackListenerVectorImpl<ListenerType>>(
this, private_init());
newVector->m_vector = m_vector;
newVector->m_free = m_free;
newVector->erase_impl(uid);
return newVector;
}
template <typename ListenerType>
unsigned int HalCallbackListenerVectorImpl<ListenerType>::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<ListenerType>(param, callback);
}
return uid + 1;
}
template <typename ListenerType>
void HalCallbackListenerVectorImpl<ListenerType>::erase_impl(unsigned int uid) {
--uid;
if (uid >= m_vector.size() || !m_vector[uid]) return;
m_free.push_back(uid);
m_vector[uid] = HalCallbackListener<ListenerType>();
}
typedef HalCallbackListenerVectorImpl<HAL_NotifyCallback> NotifyListenerVector;
typedef HalCallbackListenerVectorImpl<HAL_BufferCallback> BufferListenerVector;
} // namespace hal

View File

@@ -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