motor-control-sdk/source/dcl/misc/dcl_fdlog.h

239 lines
7.5 KiB
C
Raw Normal View History

/*
* Copyright (C) 2023 Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPgResS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DCL_FDLOG_H_
#define _DCL_FDLOG_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup DCL_API_MODULE APIs for Digital Control Library
* @{
*
* \file dcl_fdlog.h
* \brief Defines a 32-bit floating-point data logger strcture
* and related functions.
*
* \details The FDLOG structure describes a continuous memory block
* which is characterized by its start index pointer,
* current index pointer, and size of the buffer.
*
* Overfilling the data logger would result in a warp-around
* in a similar fashion as circular buffers.
*
* \code An example of initialization and use is shown below:
*
* uint32_t fdlog_size = 400;
* #pragma DATA_SECTION(r_Array, "DataLogSection") //Not unnecessary but helpful for debugging
* float32_t r_Array[fdlog_size];
* DCL_FDLOG rBuf;
*
* DCL_initLog(&rBuf, r_Array, fdlog_size);
* DCL_clearLog(&rBuf);
*
* DCL_writeFDLOG(&rBuf, some_results);
* output = readFDLOG(&rBuf);
* \endcode
*/
#include "../dcl_common.h"
//! \brief Defines the data logger strcture for 32-bit float
//!
typedef _DCL_VOLATILE struct dcl_fdlog
{
float32_t *fptr; //!< Pointer to first buffer element
float32_t *dptr; //!< Current data index pointer
uint32_t size; //!< The size of buffer
} DCL_FDLOG;
/******************** macro definitions ********************/
//! \brief Obtain the total size of buffer
//!
//! \param[in] buf Pointer to DCL_FDLOG
//! \return uint32_t size
//!
#define DCL_getLogSize(buf) ((buf)->size)
//! \brief Index of the current pointer (zero-indexed)
//!
//! \param[in] buf Pointer to DCL_FDLOG
//! \return uint32_t index
//!
#define DCL_getLogIndex(buf) ((uint32_t)((buf)->dptr - (buf)->fptr))
//! \brief Remaining space left from indexed pointer to end of buffer
//!
//! \param[in] buf Pointer to DCL_FDLOG
//! \return uint32_t remain
//!
#define DCL_getLogRemain(buf) ((buf)->size - DCL_getLogIndex(buf))
//! \brief Sets index of the current pointer (zero-indexed)
//!
//! \param[in] buf Pointer to DCL_FDLOG
//! \param[in] idx Index number
//!
_DCL_CODE_ACCESS
void DCL_setLogIndex(DCL_FDLOG *buf, uint32_t idx)
{
if(idx < buf->size)
{
buf->dptr = buf->fptr + idx;
}
}
/******************** inline functions ********************/
//! \brief Resets all structure pointers to null value
//!
//! \param[in] buf The DCL_FDLOG structure
//!
_DCL_CODE_ACCESS
void DCL_deleteLog(DCL_FDLOG *buf) { buf->dptr = buf->fptr = NULL; buf->size = 0; }
//! \brief Resets the data index pointer to start of buffer
//! \param[in] buf The DCL_FDLOG structure
//!
_DCL_CODE_ACCESS
void DCL_resetLog(DCL_FDLOG *buf) { buf->dptr = buf->fptr; }
//! \brief Fills the buffer with a given data value and resets the
//! data index pointer to the start of the buffer
//!
//! \param[in] buf The DCL_FDLOG structure
//! \param[in] data The fill data value
//!
_DCL_CODE_ACCESS
void DCL_fillLog(DCL_FDLOG *buf, float32_t data)
{
uint32_t length = DCL_getLogSize(buf);
float32_t* mem = buf->fptr;
DCL_resetLog(buf);
while (length--) *mem++ = data;
}
//! \brief Clears the buffer contents by writing 0 to all elements and
//! resets the data index pointer to the start of the buffer.
//!
#define DCL_clearLog(buf) DCL_fillLog(buf,0)
//! \brief Assigns the buffer pointers to a memory block or array and
//! sets the data index pointer to the first address
//!
//! \param[in] buf The DCL_FDLOG structure
//! \param[in] addr The start address of the memory block
//! \param[in] size The length of the memory block in 32-bit words
//!
_DCL_CODE_ACCESS
void DCL_initLog(DCL_FDLOG *buf, float32_t *addr, uint32_t size)
{
buf->fptr = addr;
buf->size = size;
DCL_resetLog(buf);
}
//! \brief Writes a data point into the buffer and advances the
//! indexing pointer, wrapping if necessary.
//! Returns the over-written data value for delay line or FIFO
//! implementation.
//!
//! \param[in] buf The DCL_FDLOG structure
//! \param[in] data The input data value
//! \return The over-written data value
//!
_DCL_CODE_ACCESS
float32_t DCL_writeLog(DCL_FDLOG *buf, float32_t data)
{
// save existing data
float32_t rv = *(buf->dptr);
// write new data to log
*(buf->dptr++) = data;
// check for end of buffer & wrap if necessary
if (DCL_getLogIndex(buf) > (buf->size - 1)) DCL_resetLog(buf);
return(rv);
}
//! \brief Reads a data point from the buffer and then advances the
//! indexing pointer, wrapping if necessary
//!
//! \param[in] buf The DCL_FDLOG structure
//! \return The indexed data value
//!
_DCL_CODE_ACCESS
float32_t DCL_readLog(DCL_FDLOG *buf)
{
float32_t rv = *(buf->dptr++);
// check for end of buffer & wrap if necessary
if (DCL_getLogIndex(buf) > (buf->size - 1)) DCL_resetLog(buf);
return(rv);
}
//! \brief Copies the contents of one log (src) into another (dst).
//! Both logs must have the same length.
//!
//! \param[in] src The destination DCL_FDLOG structure
//! \param[in] dst The source DCL_FDLOG structure
//!
_DCL_CODE_ACCESS
void DCL_copyLog(DCL_FDLOG *src, DCL_FDLOG *dst)
{
uint32_t length = DCL_getLogSize(src);
if (length != DCL_getLogSize(dst))
{
return;
}
float32_t* src_ptr = src->fptr;
float32_t* dst_ptr = dst->fptr;
while (length--) *(dst_ptr++) = *(src_ptr++);
DCL_setLogIndex(dst, DCL_getLogIndex(src));
}
/** @} */
#ifdef __cplusplus
}
#endif // extern "C"
#endif // _DCL_FDLOG_H_
/* end of file */