DEVEL: First open source release
This commit is contained in:
809
driver/psi_ms_daq.c
Normal file
809
driver/psi_ms_daq.c
Normal file
@ -0,0 +1,809 @@
|
||||
/*############################################################################
|
||||
# Copyright (c) 2019 by Paul Scherrer Institute, Switzerland
|
||||
# All rights reserved.
|
||||
# Authors: Oliver Bruendler
|
||||
############################################################################*/
|
||||
|
||||
#include "psi_ms_daq.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
//*******************************************************************************
|
||||
// Types
|
||||
//*******************************************************************************
|
||||
typedef struct {
|
||||
uint8_t nr;
|
||||
bool isConfigured;
|
||||
uint8_t widthBytes;
|
||||
uint8_t windows;
|
||||
int8_t lastProcWin;
|
||||
uint32_t irqCalledWin;
|
||||
PsiMsDaqn_WinIrq_f* irqFctWin;
|
||||
PsiMsDaqn_StrIrq_f* irqFctStr;
|
||||
void* irqArg;
|
||||
PsiMsDaq_IpHandle ipHandle;
|
||||
uint32_t bufStart;
|
||||
uint32_t winSize;
|
||||
uint32_t postTrig;
|
||||
}PsiMsDaq_StrInst_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t baseAddr;
|
||||
uint8_t maxStreams;
|
||||
uint8_t maxWindows;
|
||||
uint32_t strAddrOffs;
|
||||
PsiMsDaq_StrInst_t* streams;
|
||||
PsiMsDaq_DataCopy_f* memcpyFct;
|
||||
PsiMsDaq_RegWrite_f* regWrFct;
|
||||
PsiMsDaq_RegRead_f* regRdFct;
|
||||
} PsiMsDaq_Inst_t;
|
||||
|
||||
//*******************************************************************************
|
||||
// Macros
|
||||
//*******************************************************************************
|
||||
#define SAFE_CALL(fctCall) { \
|
||||
PsiMsDaq_RetCode_t r = fctCall; \
|
||||
if (PsiMsDaq_RetCode_Success != r) {return r;}}
|
||||
|
||||
//*******************************************************************************
|
||||
// Private Functions
|
||||
//*******************************************************************************
|
||||
void PsiMsDaq_DataCopy_Standard(void* dst, void* src, size_t n)
|
||||
{
|
||||
memcpy(dst, src, n);
|
||||
}
|
||||
|
||||
void PsiMsDaq_RegWrite_Standard(const uint32_t addr, const uint32_t value)
|
||||
{
|
||||
volatile uint32_t* addr_p = (volatile uint32_t *)(size_t)addr;
|
||||
*addr_p = value;
|
||||
}
|
||||
|
||||
uint32_t PsiMsDaq_RegRead_Standard(const uint32_t addr)
|
||||
{
|
||||
volatile uint32_t* addr_p = (volatile uint32_t *)(size_t)addr;
|
||||
return *addr_p;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t CheckStrDisabled( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint8_t streamNr)
|
||||
{
|
||||
uint32_t strEna;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, PSI_MS_DAQ_REG_STRENA, &strEna));
|
||||
if (strEna & (1 << streamNr)) {
|
||||
return PsiMsDaq_RetCode_StrNotDisabled;
|
||||
}
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t CheckStrNr( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint8_t streamNr)
|
||||
{
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*) ipHandle;
|
||||
if (streamNr >= inst_p->maxStreams) {
|
||||
return PsiMsDaq_RetCode_IllegalStrNr;
|
||||
}
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t CheckWinNr( PsiMsDaq_StrHandle strHandle,
|
||||
const uint8_t winNr)
|
||||
{
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHandle;
|
||||
if (winNr >= inst_p->windows) {
|
||||
return PsiMsDaq_RetCode_IllegalWinNr;
|
||||
}
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
uint32_t Log2(const uint32_t x)
|
||||
{
|
||||
uint32_t v = x;
|
||||
uint32_t r = 0;
|
||||
while (v > 1) {
|
||||
v = v/2;
|
||||
r = r+1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t Log2Ceil(const uint32_t x)
|
||||
{
|
||||
if (0 == x) {
|
||||
return 0;
|
||||
}
|
||||
return Log2(x);
|
||||
}
|
||||
|
||||
uint32_t Pow(const uint32_t x, const uint32_t y)
|
||||
{
|
||||
uint32_t r = x;
|
||||
for (uint32_t i = 1; i < y; i ++) {
|
||||
r *= x;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// IP Wide Functions
|
||||
//*******************************************************************************
|
||||
PsiMsDaq_IpHandle PsiMsDaq_Init( const uint32_t baseAddr,
|
||||
const uint8_t maxStreams,
|
||||
const uint8_t maxWindows,
|
||||
const PsiMsDaq_AccessFct_t* const accessFct_p)
|
||||
{
|
||||
//Initialization and allocation
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*) malloc(sizeof(PsiMsDaq_Inst_t));
|
||||
inst_p->baseAddr = baseAddr;
|
||||
inst_p->streams = (PsiMsDaq_StrInst_t*) malloc(sizeof(PsiMsDaq_StrInst_t)*maxStreams);
|
||||
inst_p->maxWindows = maxWindows;
|
||||
inst_p->maxStreams = maxStreams;
|
||||
inst_p->strAddrOffs = Pow(2, Log2Ceil(maxWindows))*0x10;
|
||||
//Standard access functions
|
||||
if (NULL == accessFct_p) {
|
||||
inst_p->memcpyFct = PsiMsDaq_DataCopy_Standard;
|
||||
inst_p->regWrFct = PsiMsDaq_RegWrite_Standard;
|
||||
inst_p->regRdFct = PsiMsDaq_RegRead_Standard;
|
||||
}
|
||||
else {
|
||||
inst_p->memcpyFct = accessFct_p->dataCopy;
|
||||
inst_p->regWrFct = accessFct_p->regWrite;
|
||||
inst_p->regRdFct = accessFct_p->regRead;
|
||||
}
|
||||
//Disable complete IP (all streams, IRQs, etc.)
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_GCFG, 0);
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_STRENA, 0);
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_IRQENA, 0);
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_IRQVEC, 0xFFFFFFFF);
|
||||
//Reset values for all streams
|
||||
for (int str = 0; str < maxStreams; str++) {
|
||||
//Clear stream maximum level
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_MAXLVL(str), 0);
|
||||
//Mark windows as free
|
||||
for (int win = 0; win < maxWindows; win++) {
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_WIN_WINCNT(str, win, inst_p->strAddrOffs), 0);
|
||||
}
|
||||
//Initialize data structure
|
||||
inst_p->streams[str].nr = str;
|
||||
inst_p->streams[str].isConfigured = false;
|
||||
inst_p->streams[str].irqFctWin = NULL;
|
||||
inst_p->streams[str].irqFctStr = NULL;
|
||||
inst_p->streams[str].irqArg = NULL;
|
||||
inst_p->streams[str].ipHandle = (PsiMsDaq_IpHandle) inst_p;
|
||||
inst_p->streams[str].lastProcWin = -1;
|
||||
inst_p->streams[str].irqCalledWin = 0;
|
||||
}
|
||||
//Set general Enables (never touched later)
|
||||
PsiMsDaq_RegWrite(inst_p, PSI_MS_DAQ_REG_GCFG, PSI_MS_DAQ_REG_GCFG_BIT_ENA | PSI_MS_DAQ_REG_GCFG_BIT_IRQENA);
|
||||
return (PsiMsDaq_IpHandle) inst_p;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_GetStrHandle( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint8_t streamNr,
|
||||
PsiMsDaq_StrHandle* const strHndl_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*) ipHandle;
|
||||
//Checks
|
||||
SAFE_CALL(CheckStrNr(ipHandle, streamNr));
|
||||
//Implementation
|
||||
*strHndl_p = (PsiMsDaq_StrHandle) &inst_p->streams[streamNr];
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
void PsiMsDaq_HandleIrq(PsiMsDaq_IpHandle ipHandle)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*) ipHandle;
|
||||
|
||||
//Check which stream caused the IRQ and acknowledge it
|
||||
uint32_t strWithIrq;
|
||||
PsiMsDaq_RegRead(ipHandle, PSI_MS_DAQ_REG_IRQVEC, &strWithIrq);
|
||||
PsiMsDaq_RegWrite(ipHandle, PSI_MS_DAQ_REG_IRQVEC, strWithIrq);
|
||||
|
||||
//Call handler for all streams with new windows pending
|
||||
for (int str = 0; str < inst_p->maxStreams; str++) {
|
||||
//Get stream handle
|
||||
PsiMsDaq_StrInst_t* str_p = &inst_p->streams[str];
|
||||
PsiMsDaq_StrHandle strHandle = (PsiMsDaq_StrHandle) str_p;
|
||||
|
||||
//Continue if stream has no IRQ pending
|
||||
if (0 == (strWithIrq & (1 << str))){
|
||||
continue;
|
||||
}
|
||||
|
||||
//IRQ Handling Type: Stream
|
||||
if (NULL != str_p->irqFctStr) {
|
||||
str_p->irqFctStr(strHandle, str_p->irqArg);
|
||||
}
|
||||
|
||||
|
||||
//IRQ Handling Type: Window
|
||||
if (NULL != str_p->irqFctWin) {
|
||||
|
||||
uint8_t lastWin;
|
||||
PsiMsDaq_Str_GetLastWrittenWin(strHandle, &lastWin);
|
||||
|
||||
//Call user callbacks for new windows
|
||||
int8_t win = str_p->lastProcWin;
|
||||
do {
|
||||
//Check if new data arrived and clear stream IRQ
|
||||
PsiMsDaq_RegWrite(ipHandle, PSI_MS_DAQ_REG_IRQVEC, (1 << str));
|
||||
PsiMsDaq_Str_GetLastWrittenWin(strHandle, &lastWin);
|
||||
//Choose next window
|
||||
win = (win + 1) % str_p->windows;
|
||||
//Stopp if this window was not yet marked as free by the user
|
||||
if (str_p->irqCalledWin & (1 << win)) {
|
||||
break;
|
||||
}
|
||||
str_p->irqCalledWin |= (1 << win);
|
||||
//Call user IRQ
|
||||
PsiMsDaq_WinInfo_t winInfo;
|
||||
winInfo.ipHandle = ipHandle;
|
||||
winInfo.strHandle = strHandle;
|
||||
winInfo.winNr = win;
|
||||
if (str_p->irqFctWin != NULL) {
|
||||
str_p->irqFctWin(winInfo, str_p->irqArg);
|
||||
}
|
||||
//Update State
|
||||
str_p->lastProcWin = win;
|
||||
} while (win != lastWin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// Stream Related Functions
|
||||
//*******************************************************************************
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_Configure( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaq_StrConfig_t* const config_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
PsiMsDaq_Inst_t* ipInst_p = (PsiMsDaq_Inst_t*) ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Checks
|
||||
if (0 != (config_p->streamWidthBits % 8)){
|
||||
return PsiMsDaq_RetCode_IllegalStrWidth;
|
||||
}
|
||||
if (config_p->winCnt > ipInst_p->maxWindows) {
|
||||
return PsiMsDaq_RetCode_IllegalWinCnt;
|
||||
}
|
||||
if (0 != (config_p->winSize % (config_p->streamWidthBits/8))) {
|
||||
return PsiMsDaq_RetCode_WinSizeMustBeMultipleOfSamples;
|
||||
}
|
||||
SAFE_CALL(CheckStrDisabled(ipHandle, strNr));
|
||||
//Set register values
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle,
|
||||
PSI_MS_DAQ_REG_POSTTRIG(strNr),
|
||||
config_p->postTrigSamples));
|
||||
SAFE_CALL(PsiMsDaq_RegSetField( ipHandle,
|
||||
PSI_MS_DAQ_REG_MODE(strNr),
|
||||
PSI_MS_DAQ_REG_MODE_LSB_RECM,
|
||||
PSI_MS_DAQ_REG_MODE_MSB_RECM,
|
||||
config_p->recMode));
|
||||
SAFE_CALL(PsiMsDaq_RegSetBit( ipHandle,
|
||||
PSI_MS_DAQ_CTX_SCFG(strNr),
|
||||
PSI_MS_DAQ_CTX_SCFG_BIT_RINGBUF,
|
||||
config_p->winAsRingbuf));
|
||||
SAFE_CALL(PsiMsDaq_RegSetBit( ipHandle,
|
||||
PSI_MS_DAQ_CTX_SCFG(strNr),
|
||||
PSI_MS_DAQ_CTX_SCFG_BIT_OVERWRITE,
|
||||
config_p->winOverwrite));
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle,
|
||||
PSI_MS_DAQ_CTX_BUFSTART(strNr),
|
||||
config_p->bufStartAddr));
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle,
|
||||
PSI_MS_DAQ_CTX_WINSIZE(strNr),
|
||||
config_p->winSize));
|
||||
SAFE_CALL(PsiMsDaq_RegSetField( ipHandle,
|
||||
PSI_MS_DAQ_CTX_SCFG(strNr),
|
||||
PSI_MS_DAQ_CTX_SCFG_LSB_WINCNT,
|
||||
PSI_MS_DAQ_CTX_SCFG_MSB_WINCNT,
|
||||
config_p->winCnt-1));
|
||||
//Set data structure values
|
||||
inst_p->widthBytes = config_p->streamWidthBits/8;
|
||||
inst_p->isConfigured = true;
|
||||
inst_p->windows = config_p->winCnt;
|
||||
inst_p->bufStart = config_p->bufStartAddr;
|
||||
inst_p->postTrig = config_p->postTrigSamples;
|
||||
inst_p->winSize = config_p->winSize;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetEnable( PsiMsDaq_StrHandle strHndl,
|
||||
const bool enable)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation
|
||||
const uint32_t msk = (1 << strNr);
|
||||
SAFE_CALL(PsiMsDaq_RegSetBit(ipHandle, PSI_MS_DAQ_REG_STRENA, msk, enable));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqCallbackWin( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaqn_WinIrq_f* irqCb,
|
||||
void* arg_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Checks
|
||||
if (NULL != inst_p->irqFctStr) {
|
||||
return PsiMsDaq_RetCode_IrqSchemesWinAndStrAreExclusive;
|
||||
}
|
||||
//Implementation
|
||||
inst_p->irqFctWin = irqCb;
|
||||
inst_p->irqArg = arg_p;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqCallbackStr( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaqn_StrIrq_f* irqCb,
|
||||
void* arg_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Checks
|
||||
if (NULL != inst_p->irqFctWin) {
|
||||
return PsiMsDaq_RetCode_IrqSchemesWinAndStrAreExclusive;
|
||||
}
|
||||
//Implementation
|
||||
inst_p->irqFctStr = irqCb;
|
||||
inst_p->irqArg = arg_p;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqEnable( PsiMsDaq_StrHandle strHndl,
|
||||
const bool irqEna)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation
|
||||
const uint32_t msk = (1 << strNr);
|
||||
SAFE_CALL(PsiMsDaq_RegSetBit(ipHandle, PSI_MS_DAQ_REG_IRQENA, msk, irqEna));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_Arm(PsiMsDaq_StrHandle strHndl)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegSetBit(ipHandle, PSI_MS_DAQ_REG_MODE(strNr), PSI_MS_DAQ_REG_MODE_BIT_ARM, true));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetMaxLvl( PsiMsDaq_StrHandle strHndl,
|
||||
uint32_t* const maxLvl_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, PSI_MS_DAQ_REG_MAXLVL(strNr), maxLvl_p));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetFreeWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const freeWindows_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*) ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation (looping is not very efficient but safe and simple)
|
||||
uint8_t freeWin = 0;
|
||||
for (int win = inst_p->windows-1; win > 0; win--) {
|
||||
uint32_t cnt;
|
||||
SAFE_CALL(PsiMsDaq_RegGetField( ipHandle,
|
||||
PSI_MS_DAQ_WIN_WINCNT(strNr, win, ip_p->strAddrOffs),
|
||||
PSI_MS_DAQ_WIN_WINCNT_LSB_CNT,
|
||||
PSI_MS_DAQ_WIN_WINCNT_MSB_CNT,
|
||||
&cnt))
|
||||
if (0 == cnt) {
|
||||
freeWin++;
|
||||
}
|
||||
}
|
||||
*freeWindows_p = freeWin;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetUsedWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const usedWindows_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
uint8_t freeWin;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetFreeWindows(strHndl, &freeWin));
|
||||
*usedWindows_p = inst_p->windows-freeWin;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetTotalWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const windows_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
*windows_p = inst_p->windows;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetIpHandle( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaq_IpHandle* ipHandle_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
*ipHandle_p = inst_p->ipHandle;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetStrNr( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* strNr_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
*strNr_p = inst_p->nr;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
//*******************************************************************************
|
||||
// Window Related Functions
|
||||
//*******************************************************************************
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfBytes( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const noOfBytes_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*) winInfo.strHandle;
|
||||
//Implementation
|
||||
uint32_t samples;
|
||||
SAFE_CALL(PsiMsDaq_StrWin_GetNoOfSamples(winInfo, &samples));
|
||||
*noOfBytes_p = samples*str_p->widthBytes;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const noOfSamples_p)
|
||||
{
|
||||
//Pointer Case
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*)winInfo.ipHandle;
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*)winInfo.strHandle;
|
||||
//Setup
|
||||
uint8_t strNr;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetStrNr(winInfo.strHandle, &strNr));
|
||||
//Checks
|
||||
SAFE_CALL(CheckStrNr(winInfo.ipHandle, strNr))
|
||||
SAFE_CALL(CheckWinNr(winInfo.strHandle, winInfo.winNr))
|
||||
//Implementation
|
||||
uint32_t noOfBytes;
|
||||
SAFE_CALL(PsiMsDaq_RegGetField( winInfo.ipHandle,
|
||||
PSI_MS_DAQ_WIN_WINCNT(strNr, winInfo.winNr, ip_p->strAddrOffs),
|
||||
PSI_MS_DAQ_WIN_WINCNT_LSB_CNT,
|
||||
PSI_MS_DAQ_WIN_WINCNT_MSB_CNT,
|
||||
&noOfBytes));
|
||||
*noOfSamples_p = noOfBytes / str_p->widthBytes;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetPreTrigSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const preTrigSamples_p)
|
||||
{
|
||||
//Setup
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*) winInfo.strHandle;
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*)winInfo.ipHandle;
|
||||
//Checks
|
||||
bool containsTrig;
|
||||
SAFE_CALL(PsiMsDaq_RegGetBit( winInfo.ipHandle,
|
||||
PSI_MS_DAQ_WIN_WINCNT(str_p->nr, winInfo.winNr, ip_p->strAddrOffs),
|
||||
PSI_MS_DAQ_WIN_WINCNT_BIT_ISTRIG,
|
||||
&containsTrig))
|
||||
if (!containsTrig) {
|
||||
return PsiMsDaq_RetCode_NoTrigInWin;
|
||||
}
|
||||
//Implementation
|
||||
uint32_t samples;
|
||||
SAFE_CALL(PsiMsDaq_StrWin_GetNoOfSamples(winInfo, &samples));
|
||||
*preTrigSamples_p = samples-str_p->postTrig;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetTimestamp( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint64_t* const timestamp_p)
|
||||
{
|
||||
//Setup
|
||||
uint8_t strNr;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetStrNr(winInfo.strHandle, &strNr));
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*)winInfo.ipHandle;
|
||||
//Checks
|
||||
bool containsTrig;
|
||||
SAFE_CALL(PsiMsDaq_RegGetBit( winInfo.ipHandle,
|
||||
PSI_MS_DAQ_WIN_WINCNT(strNr, winInfo.winNr, ip_p->strAddrOffs),
|
||||
PSI_MS_DAQ_WIN_WINCNT_BIT_ISTRIG,
|
||||
&containsTrig))
|
||||
if (!containsTrig) {
|
||||
return PsiMsDaq_RetCode_NoTrigInWin;
|
||||
}
|
||||
//Implementation
|
||||
uint32_t tsLo;
|
||||
uint32_t tsHi;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(winInfo.ipHandle, PSI_MS_DAQ_WIN_TSLO(strNr, winInfo.winNr, ip_p->strAddrOffs), &tsLo));
|
||||
SAFE_CALL(PsiMsDaq_RegRead(winInfo.ipHandle, PSI_MS_DAQ_WIN_TSHI(strNr, winInfo.winNr, ip_p->strAddrOffs), &tsHi));
|
||||
*timestamp_p = (((uint64_t)tsHi) << 32) + tsLo;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetDataUnwrapped( PsiMsDaq_WinInfo_t winInfo,
|
||||
const uint32_t preTrigSamples,
|
||||
const uint32_t postTrigSamples, //including trigger
|
||||
void* const buffer_p,
|
||||
const size_t bufferSize)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*) winInfo.strHandle;
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*) winInfo.ipHandle;
|
||||
|
||||
//Setup
|
||||
const uint32_t samples = preTrigSamples+postTrigSamples;
|
||||
const uint32_t bytes = samples*str_p->widthBytes;
|
||||
uint32_t preTrig;
|
||||
SAFE_CALL(PsiMsDaq_StrWin_GetPreTrigSamples(winInfo, &preTrig));
|
||||
|
||||
//Checks
|
||||
if (bufferSize < bytes) {
|
||||
return PsiMsDaq_RetCode_BufferTooSmall;
|
||||
}
|
||||
if (postTrigSamples > str_p->postTrig) {
|
||||
return PsiMsDaq_RetCode_MorePostTrigThanConfigured;
|
||||
}
|
||||
if (preTrigSamples > preTrig) {
|
||||
return PsiMsDaq_RetCode_MorePreTrigThanAvailable;
|
||||
}
|
||||
|
||||
//Calculate window addresses
|
||||
const uint32_t winStart = str_p->bufStart + str_p->winSize*winInfo.winNr;
|
||||
const uint32_t winLast = winStart + str_p->winSize - 1;
|
||||
|
||||
//Calculate address of last byte and trigger byte (with regard to wrapping)
|
||||
uint32_t lastSplAddr;
|
||||
SAFE_CALL(PsiMsDaq_StrWin_GetLastSplAddr(winInfo, &lastSplAddr));
|
||||
uint32_t trigByteAddr = lastSplAddr - (str_p->postTrig+1)*str_p->widthBytes; //+1 because trigger is not included in postTrigger
|
||||
if (trigByteAddr < winStart) {
|
||||
trigByteAddr += str_p->winSize;
|
||||
}
|
||||
uint32_t lastByteAddr = trigByteAddr + postTrigSamples*str_p->widthBytes + str_p->widthBytes-1;
|
||||
if (lastByteAddr > winLast) {
|
||||
lastByteAddr -= str_p->winSize;
|
||||
}
|
||||
|
||||
|
||||
//If all bytes are written without wrap, copy directly
|
||||
const uint32_t firstByteLinear = lastByteAddr - bytes + 1;
|
||||
if (firstByteLinear >= winStart) {
|
||||
ip_p->memcpyFct(buffer_p, (void*)(size_t)firstByteLinear, bytes);
|
||||
}
|
||||
//Do unwrapping else
|
||||
else {
|
||||
const uint32_t secondChunkSize = lastByteAddr - winStart + 1;
|
||||
const uint32_t firstChunkSize = bytes-secondChunkSize;
|
||||
const uint32_t firstChunkStartAddr = winLast-firstChunkSize+1;
|
||||
ip_p->memcpyFct(buffer_p, (void*)(size_t)firstChunkStartAddr, firstChunkSize);
|
||||
ip_p->memcpyFct(buffer_p+firstChunkSize, (void*)(size_t)winStart, secondChunkSize);
|
||||
}
|
||||
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_MarkAsFree( PsiMsDaq_WinInfo_t winInfo)
|
||||
{
|
||||
//Setup
|
||||
uint8_t strNr;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetStrNr(winInfo.strHandle, &strNr));
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*) winInfo.ipHandle;
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*) winInfo.strHandle;
|
||||
//Implementation
|
||||
str_p->irqCalledWin &= ~(1 << winInfo.winNr);
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(winInfo.ipHandle, PSI_MS_DAQ_WIN_WINCNT(strNr, winInfo.winNr, ip_p->strAddrOffs), 0));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetLastSplAddr( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const lastSplAddr_p)
|
||||
{
|
||||
//Setup
|
||||
uint8_t strNr;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetStrNr(winInfo.strHandle, &strNr));
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*) winInfo.ipHandle;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegRead(winInfo.ipHandle, PSI_MS_DAQ_WIN_LAST(strNr, winInfo.winNr, ip_p->strAddrOffs), lastSplAddr_p));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// Advanced Functions (only required for close control)
|
||||
//*******************************************************************************
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_IsRecording( PsiMsDaq_StrHandle strHndl,
|
||||
bool* const isRecording_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegGetBit( inst_p->ipHandle,
|
||||
PSI_MS_DAQ_REG_MODE(inst_p->nr),
|
||||
PSI_MS_DAQ_REG_MODE_BIT_REC,
|
||||
isRecording_p));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_CurrentWin( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const currentWin_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
uint32_t field;
|
||||
SAFE_CALL(PsiMsDaq_RegGetField( inst_p->ipHandle,
|
||||
PSI_MS_DAQ_CTX_SCFG(inst_p->nr),
|
||||
PSI_MS_DAQ_CTX_SCFG_LSB_WINCUR,
|
||||
PSI_MS_DAQ_CTX_SCFG_MSB_WINCUR,
|
||||
&field))
|
||||
*currentWin_p = field;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_CurrentPtr( PsiMsDaq_StrHandle strHndl,
|
||||
uint32_t* const currentPtr_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegRead(inst_p->ipHandle, PSI_MS_DAQ_CTX_PTR(inst_p->nr), currentPtr_p));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetLastWrittenWin( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const lastWrittenWin_p)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
//Implementation
|
||||
uint32_t reg;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(inst_p->ipHandle, PSI_MS_DAQ_REG_LASTWIN(inst_p->nr), ®));
|
||||
*lastWrittenWin_p = reg;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegWrite( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t value)
|
||||
{
|
||||
//Cast pointer
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*)ipHandle;
|
||||
//Execute access
|
||||
inst_p->regWrFct(inst_p->baseAddr+addr, value);
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegRead( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
uint32_t* const value_p)
|
||||
{
|
||||
//Cast pointer
|
||||
PsiMsDaq_Inst_t* inst_p = (PsiMsDaq_Inst_t*)ipHandle;
|
||||
//Execute access
|
||||
*value_p = inst_p->regRdFct(inst_p->baseAddr+addr);
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegSetField( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint8_t lsb,
|
||||
const uint8_t msb,
|
||||
const uint32_t value)
|
||||
{
|
||||
//Execute access
|
||||
uint32_t reg;
|
||||
uint32_t msk = (1 << (msb+1))-1;
|
||||
uint32_t mskSft = msk << lsb;
|
||||
uint32_t valSft = ((value & msk) << lsb);
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, addr, ®));
|
||||
reg &= ~mskSft;
|
||||
reg |= valSft;
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle, addr, reg));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegGetField( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint8_t lsb,
|
||||
const uint8_t msb,
|
||||
uint32_t* const value_p)
|
||||
{
|
||||
//Execute access
|
||||
uint32_t reg;
|
||||
uint32_t msk = (1 << (msb+1))-1;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, addr, ®));
|
||||
*value_p = (reg >> lsb) & msk;
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegSetBit( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t mask,
|
||||
const bool value)
|
||||
{
|
||||
//Execute access
|
||||
uint32_t reg;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, addr, ®));
|
||||
reg &= ~mask;
|
||||
if (value) {
|
||||
reg |= mask;
|
||||
}
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle, addr, reg));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegGetBit( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t mask,
|
||||
bool* const value_p)
|
||||
{
|
||||
//Execute access
|
||||
uint32_t reg;
|
||||
SAFE_CALL(PsiMsDaq_RegRead(ipHandle, addr, ®));
|
||||
*value_p = (0 != (reg & mask));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
704
driver/psi_ms_daq.h
Normal file
704
driver/psi_ms_daq.h
Normal file
@ -0,0 +1,704 @@
|
||||
/*############################################################################
|
||||
# Copyright (c) 2019 by Paul Scherrer Institute, Switzerland
|
||||
# All rights reserved.
|
||||
# Authors: Oliver Bruendler
|
||||
############################################################################*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//*******************************************************************************
|
||||
// Documentation
|
||||
//*******************************************************************************
|
||||
/**
|
||||
* @mainpage
|
||||
*
|
||||
* @section ip_functionality IP Core Functionality
|
||||
*
|
||||
* The functionality of the IP-Core is not covered in detail here, however for using
|
||||
* the driver it may beneficial to understand what the IP-Core does. To get this
|
||||
* information, refer to the <a href="../../psi_multi_stream_daq.pdf"><b>IP-Core documentation</b></a>
|
||||
*
|
||||
* @section thread_safety Thread Safety
|
||||
*
|
||||
* The driver is not thread-safe in general. If API functions are used in more
|
||||
* than one thread (e.g. in main and IRQs), these API functions must be protected (e.g. by disabling IRQs
|
||||
* while the function is executing).
|
||||
*
|
||||
* In the simplest case, the IP core is configured before IRQs are enabled and afterwards data is only read
|
||||
* from IRQs. In this case, no protection is required.
|
||||
*
|
||||
* Why is the IRQ disabling not implemented in the driver itself? Well, what IRQs must be disabled depends
|
||||
* on what IRQs the driver API is used from. There may also other protection schemes be used (e.g. mutexes of a RTOS).
|
||||
* As a result there is not single true protection mechanism that can be implemented within the driver.
|
||||
*
|
||||
* @section irq_handling IRQ Handling
|
||||
*
|
||||
* The driver supports two ways of handling IRQs. One of them (<i>Window based IRQ</i>) is a bit more elaborate and easy to use
|
||||
* but it only covers the case, that each recorded window is processed by software. This is true
|
||||
* in general but the IP-core also allows special configurations where data can be overwritten
|
||||
* even if it was not processed. Since the handling of IRQs becomes more specific in this case,
|
||||
* a special IRQ handling scheme called <i>Stream based IRQ </i> is implemented. In this case the
|
||||
* user is responsible for implementing all actions to be taken in IRQs.
|
||||
*
|
||||
* In all IRQ handling schemes, the user is responsible for calling the function PsiMsDaq_HandleIrq() whenever the IP core
|
||||
* asserts its interrupt (level sensitive, high active).
|
||||
*
|
||||
* Only one IRQ handlig scheme can be used per stream (not both at the same time for the same stream).
|
||||
*
|
||||
* @subsection window_irq Window based IRQ
|
||||
*
|
||||
* In this handling scheme, the driver ensures that the user callback gets called exactly once for every window that is recorded.
|
||||
* Spurious interrupts (IRQs getting detected after the data was already processed) are suppressed by the driver. All information
|
||||
* about the window which was completed is automatically passed to the user callback.
|
||||
*
|
||||
* This handling scheme only works if each window is really processed by the user and protected against being overwritten until
|
||||
* the user acknowledged the processing. Implementationwise this means that window overwriting must be disable (config.overwrite = false)
|
||||
* and that the user must acknowledge the processing of each window before new data can be recorded into it (by calling PsiMsDaq_StrWin_MarkAsFree()).
|
||||
*
|
||||
* Benefits of this scheme is simplicity, drawback is that the driver assumes that the user processes each window which may not
|
||||
* be the case in special cases.
|
||||
*
|
||||
* @subsection stream_irq Stream based IRQ
|
||||
*
|
||||
* In this handling scheme, the driver does only detect which stream fired an IRQ and calls the user callback function.
|
||||
* The callback function is called regardless of how many new windows were recorded. The user can do whatever processing
|
||||
* of the IRQ he wants. This allows fine grained control over the IP core in special cases but it also means that the user
|
||||
* is fully on his own. Therefore this option should only be used if there are good reasons for not using Window based IRQ.
|
||||
*
|
||||
* @section example_code Example Code
|
||||
*
|
||||
* This section contains a little code example to show how the driver is used.
|
||||
*
|
||||
* @code{.c}
|
||||
* // *** Static Variables ***
|
||||
* static PsiMsDaq_IpHandle daqHandle;
|
||||
* static PsiMsDaq_StrHandle daqStrHandle;
|
||||
*
|
||||
* // *** System ISR ***
|
||||
* //ISR that is called by the OS/baremetal drivers if an IRQ is asserted
|
||||
* void PsiMsDaqIrqHandler(void* arg)
|
||||
* {
|
||||
* //We assume the handle to the psi_ms_daq driver is passed as callback argument
|
||||
* PsiMsDaq_IpHandle ipHandle = (PsiMsDaq_IpHandle) arg;
|
||||
* //Call IP-handling function
|
||||
* PsiMsDaq_HandleIrq(ipHandle);
|
||||
* }
|
||||
*
|
||||
* // *** IP User ISR ***
|
||||
* void UserDaqIsr(PsiMsDaq_WinInfo_t winInfo, void* arg)
|
||||
* {
|
||||
* //Invalidate cache, example code is for xilinx devices
|
||||
* Xil_DCacheInvalidateRange(<recodingLocation>, <recordingSize>);
|
||||
* //Get recorded data
|
||||
* PsiMsDaq_StrWin_GetDataUnwrapped(winInfo, <preTriggerSize>, <postTriggerSize>, <targetBuffer>, sizeof(<targetBuffer>));
|
||||
* //Acknowledge processing of the data
|
||||
* PsiMsDaq_StrWin_MarkAsFree(winInfo);
|
||||
* }
|
||||
*
|
||||
* // *** Main function containing intialization ***
|
||||
* int main()
|
||||
* {
|
||||
* //Initialize IP
|
||||
* daqHandle = PsiMsDaq_Init(<baseAddress>, <streams>, <maxWindows>, NULL);
|
||||
* PsiMsDaq_GetStrHandle(daqHandle, 0, &daqStrHandle);
|
||||
*
|
||||
* //Configure Stream
|
||||
* PsiMsDaq_StrConfig_t cfg = {
|
||||
* .postTrigSamples = <postTriggerSamplesToRecord>,
|
||||
* .recMode = <mode>,
|
||||
* .winAsRingbuf = true,
|
||||
* .winOverwrite = false,
|
||||
* .winCnt = <numberOfWindowsForThisStream>,
|
||||
* .bufStartAddr = <recodingLocation>,
|
||||
* .winSize = <sizePerWindow>, //in bytes
|
||||
* .streamWidthBits = <widthInBits>
|
||||
* };
|
||||
* PsiMsDaq_Str_Configure(daqHandle, &cfg);
|
||||
* //Register ballback
|
||||
* PsiMsDaq_Str_SetIrqCallbackWin(daqHandle, UserDaqIsr, NULL);
|
||||
* //Enable IRQ
|
||||
* PsiMsDaq_Str_SetIrqEnable(daqHandle, true);
|
||||
* //Enable recorder for stream
|
||||
* PsiMsDaq_Str_SetEnable(daqHandle, true);
|
||||
*
|
||||
* //Wait in endless loop for IRQs comming in
|
||||
* while(1){};
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
//*******************************************************************************
|
||||
// Includes
|
||||
//*******************************************************************************
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
//*******************************************************************************
|
||||
// Constants
|
||||
//*******************************************************************************
|
||||
|
||||
/// @cond
|
||||
//ACQCONF Registers - General
|
||||
#define PSI_MS_DAQ_REG_GCFG 0x000
|
||||
#define PSI_MS_DAQ_REG_GCFG_BIT_ENA (1 << 0)
|
||||
#define PSI_MS_DAQ_REG_GCFG_BIT_IRQENA (1 << 8)
|
||||
#define PSI_MS_DAQ_REG_GSTAT 0x004
|
||||
#define PSI_MS_DAQ_REG_IRQVEC 0x010
|
||||
#define PSI_MS_DAQ_REG_IRQENA 0x014
|
||||
#define PSI_MS_DAQ_REG_STRENA 0x020
|
||||
//ACQCONF Registers - Per Stream
|
||||
#define PSI_MS_DAQ_REG_MAXLVL(n) (0x200+0x10*(n))
|
||||
#define PSI_MS_DAQ_REG_POSTTRIG(n) (0x204+0x10*(n))
|
||||
#define PSI_MS_DAQ_REG_MODE(n) (0x208+0x10*(n))
|
||||
#define PSI_MS_DAQ_REG_MODE_LSB_RECM 0
|
||||
#define PSI_MS_DAQ_REG_MODE_MSB_RECM 1
|
||||
#define PSI_MS_DAQ_REG_MODE_BIT_ARM (1 << 8)
|
||||
#define PSI_MS_DAQ_REG_MODE_BIT_REC (1 << 16)
|
||||
#define PSI_MS_DAQ_REG_LASTWIN(n) (0x20C+0x10*(n))
|
||||
//CTXMEM for Stream n
|
||||
#define PSI_MS_DAQ_CTX_SCFG(n) (0x1000+0x20*(n))
|
||||
#define PSI_MS_DAQ_CTX_SCFG_BIT_RINGBUF (1 << 0)
|
||||
#define PSI_MS_DAQ_CTX_SCFG_BIT_OVERWRITE (1 << 8)
|
||||
#define PSI_MS_DAQ_CTX_SCFG_LSB_WINCNT 16
|
||||
#define PSI_MS_DAQ_CTX_SCFG_MSB_WINCNT 20
|
||||
#define PSI_MS_DAQ_CTX_SCFG_LSB_WINCUR 24
|
||||
#define PSI_MS_DAQ_CTX_SCFG_MSB_WINCUR 28
|
||||
#define PSI_MS_DAQ_CTX_BUFSTART(n) (0x1004+0x20*(n))
|
||||
#define PSI_MS_DAQ_CTX_WINSIZE(n) (0x1008+0x20*(n))
|
||||
#define PSI_MS_DAQ_CTX_PTR(n) (0x100C+0x20*(n))
|
||||
#define PSI_MS_DAQ_CTX_WINEND(n) (0x1010+0x20*(n))
|
||||
//WNDW Window w for Stream n
|
||||
#define PSI_MS_DAQ_WIN_WINCNT(n, w, so) (0x4000+(so)*(n)+0x10*(w))
|
||||
#define PSI_MS_DAQ_WIN_WINCNT_LSB_CNT 0
|
||||
#define PSI_MS_DAQ_WIN_WINCNT_MSB_CNT 30
|
||||
#define PSI_MS_DAQ_WIN_WINCNT_BIT_ISTRIG (1 << 31)
|
||||
#define PSI_MS_DAQ_WIN_LAST(n, w, so) (0x4004+(so)*(n)+0x10*(w))
|
||||
#define PSI_MS_DAQ_WIN_TSLO(n, w, so) (0x4008+(so)*(n)+0x10*(w))
|
||||
#define PSI_MS_DAQ_WIN_TSHI(n, w, so) (0x400C+(so)*(n)+0x10*(w))
|
||||
/// @endcond
|
||||
|
||||
//*******************************************************************************
|
||||
// Types
|
||||
//*******************************************************************************
|
||||
|
||||
//*** Handles ***
|
||||
typedef void* PsiMsDaq_IpHandle; ///< Handle to an instance of the driver for a complete IP
|
||||
typedef void* PsiMsDaq_StrHandle; ///< Handle to a specific stream of the driver
|
||||
|
||||
//*** Functions for access to data of the IP core ***
|
||||
/**
|
||||
* @brief Copy used to copy data recorded to other memory locations in PsiMsDaq_StrWin_GetDataUnwrapped()
|
||||
*
|
||||
* @param src Source memory address (exactly the way the IP sees the address space)
|
||||
* @param dst Desitnation memory address (as the CPU sees it)
|
||||
* @param n Number of bytes to copy
|
||||
*/
|
||||
typedef void PsiMsDaq_DataCopy_f(void* dst, void* src, size_t n);
|
||||
|
||||
/**
|
||||
* @brief Write an IP-register
|
||||
*
|
||||
* @param addr Address to write (byte address)
|
||||
* @param value Value to write
|
||||
*/
|
||||
typedef void PsiMsDaq_RegWrite_f(const uint32_t addr, const uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Read an IP-register
|
||||
*
|
||||
* @param addr Address to read from (byte address)
|
||||
* @return Read value
|
||||
*/
|
||||
typedef uint32_t PsiMsDaq_RegRead_f(const uint32_t addr);
|
||||
|
||||
/**
|
||||
* @brief Window definition struct, used for more compact passing of common parameters
|
||||
* @note This is not a handle and this struct is allocated on the stack, so it is only valid
|
||||
* until the function returns!
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t winNr; ///< Window number
|
||||
PsiMsDaq_IpHandle ipHandle; ///< Handle of the IP the window belongs to
|
||||
PsiMsDaq_StrHandle strHandle; ///< Handle of the stream the window belongs to
|
||||
}PsiMsDaq_WinInfo_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt callback function for the window based IRQ scheme.
|
||||
* In this IRQ scheme, one callback function is called for each window that arrives.
|
||||
* This IRQ scheme is only usable if window-overwrite is disable (config.onverwrite = false).
|
||||
* After the window data is processed, it must be freed by calling PsiMsDaq_StrWin_MarkAsFree().
|
||||
*
|
||||
* @param winInfo Window information struct (allocated on stack!)
|
||||
* @param arg User argument list
|
||||
*/
|
||||
typedef void PsiMsDaqn_WinIrq_f(PsiMsDaq_WinInfo_t winInfo, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Interrupt callback function for the stream based IRQ scheme.
|
||||
* In this IRQ scheme, one callback function is called whenever the IP fires an IRQ.
|
||||
* This IRQ scheme is always usable but usually only required if window-overwrite is used (since the
|
||||
* more elaborate window based IRQ scheme is not usable in this case).
|
||||
*
|
||||
* @param strHandle Handle of the stream that fired the IRQ
|
||||
* @param arg User argument list
|
||||
*/
|
||||
typedef void PsiMsDaqn_StrIrq_f(PsiMsDaq_StrHandle strHandle, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Recorder mode (see documentation)
|
||||
*/
|
||||
typedef enum {
|
||||
PsiMsDaqn_RecMode_Continuous = 0, ///< Continuous recording
|
||||
PsiMsDaqn_RecMode_TriggerMask = 1, ///< Continuously record pre-trigger data but only detect triggers after PsiMsDaq_Str_Arm() was called
|
||||
PsiMsDaqn_RecMode_SingleShot = 2, ///< Only record pre-trigger after PsiMsDaq_Str_Arm() was called and stop recording after one trigger
|
||||
PsiMsDaqn_RecMode_Manual = 3, ///< Manaully control the recording by setting and clearing the arm bit
|
||||
} PsiMsDaq_RecMode_t;
|
||||
|
||||
/**
|
||||
* @brief Stream configuration struct
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t postTrigSamples; ///< Number of post trigger samples (incl. Trigger sample)
|
||||
PsiMsDaq_RecMode_t recMode; ///< Recording mode
|
||||
bool winAsRingbuf; ///< Use individual windows as ring-buffers (true=ringbuffer mode, false=linear mode)
|
||||
bool winOverwrite; ///< If true, windows are overwritten even if they contain data. Usually set false here.
|
||||
uint8_t winCnt; ///< Number of windows to use
|
||||
uint32_t bufStartAddr; ///< Start address of the buffer for this stream
|
||||
uint32_t winSize; ///< Size of the windows
|
||||
uint16_t streamWidthBits; ///< Width od the stream in bits (must be a multiple of 8)
|
||||
} PsiMsDaq_StrConfig_t;
|
||||
|
||||
/**
|
||||
* @brief Memory access functions struct
|
||||
*/
|
||||
typedef struct {
|
||||
PsiMsDaq_DataCopy_f* dataCopy; ///< Data copy function to use
|
||||
PsiMsDaq_RegWrite_f* regWrite; ///< Register write function to use
|
||||
PsiMsDaq_RegRead_f* regRead; ///< Register read function to use
|
||||
} PsiMsDaq_AccessFct_t;
|
||||
|
||||
/**
|
||||
* @brief Return codes
|
||||
*/
|
||||
typedef enum {
|
||||
PsiMsDaq_RetCode_Success = 0, ///< No error, everything OK
|
||||
PsiMsDaq_RetCode_IllegalStrNr = -1, ///< Illegal stream number passed
|
||||
PsiMsDaq_RetCode_IllegalStrWidth = -2, ///< Illegal steram width selected
|
||||
PsiMsDaq_RetCode_StrNotDisabled = -3, ///< This function is only allowed if the stream is disbled but it was enabled
|
||||
PsiMsDaq_RetCode_IllegalWinCnt = -4, ///< Illegal window count passed
|
||||
PsiMsDaq_RetCode_IllegalWinNr = -5, ///< Illegal window number passed
|
||||
PsiMsDaq_RetCode_NoTrigInWin = -6, ///< This window does not contain a trigger as required for this function call
|
||||
PsiMsDaq_RetCode_BufferTooSmall = -7, ///< The buffer passed is too small to contain all data
|
||||
PsiMsDaq_RetCode_MorePostTrigThanConfigured = -8, ///< More post trigger data requested than configured to be recorded
|
||||
PsiMsDaq_RetCode_MorePreTrigThanAvailable = -9, ///< More pre-trigger data requested than available
|
||||
PsiMsDaq_RetCode_WinSizeMustBeMultipleOfSamples = -10, ///< Window size must be a multiple of the sample size
|
||||
PsiMsDaq_RetCode_IrqSchemesWinAndStrAreExclusive = -11 ///< Only one IRQ scheme (...Str or ...Win) can be used
|
||||
} PsiMsDaq_RetCode_t;
|
||||
|
||||
//*******************************************************************************
|
||||
// IP Wide Functions
|
||||
//*******************************************************************************
|
||||
|
||||
/**
|
||||
* @brief Initialize the psi_ms_daq IP-Core
|
||||
*
|
||||
* @param baseAddr Base address of the IP core to access
|
||||
* @param maxStreams Maximum number of streams supported by this IP (must match setting in Vivado IPI)
|
||||
* @param maxWindows Maximum number of windows per stream supported by this IP (must match setting in Vivado IPI)
|
||||
* @param accessFct_p Memory access functions to use (pass NULL to use the default functions)
|
||||
* @return Driver Handle
|
||||
*/
|
||||
PsiMsDaq_IpHandle PsiMsDaq_Init( const uint32_t baseAddr,
|
||||
const uint8_t maxStreams,
|
||||
const uint8_t maxWindows,
|
||||
const PsiMsDaq_AccessFct_t* const accessFct_p);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a handle to a specific stream number
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param streamNr Stream number to get handle for
|
||||
* @param strHndl_p Pointer to write the stream handle to
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_GetStrHandle( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint8_t streamNr,
|
||||
PsiMsDaq_StrHandle* const strHndl_p);
|
||||
|
||||
|
||||
void PsiMsDaq_HandleIrq(PsiMsDaq_IpHandle inst_p);
|
||||
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// Stream Related Functions
|
||||
//*******************************************************************************
|
||||
|
||||
/**
|
||||
* @brief Configure stream.
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param config_p Struct containing all settings
|
||||
* @return Return Code
|
||||
*
|
||||
* @note This function is only allwed if the corresponding stream is disabled
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_Configure( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaq_StrConfig_t* const config_p);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable a stream
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param enable true for enable, false for disable
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetEnable( PsiMsDaq_StrHandle strHndl,
|
||||
const bool enable);
|
||||
|
||||
/**
|
||||
* @brief Set window based interrupt callback function for a stream to be called whenever a new
|
||||
* windows is recorded.
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param irqCb Callback function. Pass NULL to unregister the callback.
|
||||
* @param arg_p Arguments passed to the user callback function
|
||||
* @return Return Code
|
||||
*
|
||||
* @note Only one IRQ scheme (...Win or ...Str) can be used. Usually ...Win is
|
||||
* used if window overwriting is disabled (config.overwrite = false) and ...Str
|
||||
* otherwise.
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqCallbackWin( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaqn_WinIrq_f* irqCb,
|
||||
void* arg_p);
|
||||
|
||||
/**
|
||||
* @brief Set stream based interrupt callback function for a stream to be called whenever a new
|
||||
* windows is recorded. Usually PsiMsDaq_Str_SetIrqCallbackWin() is used instead of this
|
||||
* function. So without special reasons, use PsiMsDaq_Str_SetIrqCallbackWin().
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param irqCb Callback function. Pass NULL to unregister the callback.
|
||||
* @param arg_p Arguments passed to the user callback function
|
||||
* @return Return Code
|
||||
*
|
||||
* @note Only one IRQ scheme (...Win or ...Str) can be used. Usually ...Win is
|
||||
* used if window overwriting is disabled (config.overwrite = false) and ...Str
|
||||
* otherwise.
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqCallbackStr( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaqn_StrIrq_f* irqCb,
|
||||
void* arg_p);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable IRQ for a stream
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param irqEna true for enable, false for disable
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_SetIrqEnable( PsiMsDaq_StrHandle strHndl,
|
||||
const bool irqEna);
|
||||
|
||||
/**
|
||||
* @brief Arm the recorder for a given stream
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_Arm(PsiMsDaq_StrHandle strHndl);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get maximum input buffer fill level
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param maxLvl_p Pointer to write the level into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetMaxLvl( PsiMsDaq_StrHandle strHndl,
|
||||
uint32_t* const maxLvl_p);
|
||||
|
||||
/**
|
||||
* @brief Get the number of free windows.
|
||||
*
|
||||
* This function is implemented by looping over all windows and checking if they
|
||||
* contain any unacknowledged data. This is quite slow but the only safe approach.
|
||||
* So do not use this function excessively.
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param freeWindows_p Pointer to write the number of free windows into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetFreeWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const freeWindows_p);
|
||||
|
||||
/**
|
||||
* @brief Get the number of used (non-free) windows.
|
||||
*
|
||||
* This function is implemented by looping over all windows and checking if they
|
||||
* contain any unacknowledged data. This is quite slow but the only safe approach.
|
||||
* So do not use this function excessively.
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param usedWindows_p Pointer to write the number of used windows into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetUsedWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const usedWindows_p);
|
||||
|
||||
/**
|
||||
* @brief Get the number of windows configured to be used for a given stream
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param windows_p Pointer to write the number of windows into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetTotalWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const windows_p);
|
||||
|
||||
/**
|
||||
* @brief Get the IP Handle of the IP a stream belongs to
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param ipHandle_p Pointer to write the IP handle into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetIpHandle( PsiMsDaq_StrHandle strHndl,
|
||||
PsiMsDaq_IpHandle* ipHandle_p);
|
||||
|
||||
/**
|
||||
* @brief Get the stream number from a stream handle
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param strNr_p Pointer to write the stream number into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetStrNr( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* strNr_p);
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// Window Related Functions
|
||||
//*******************************************************************************
|
||||
|
||||
/**
|
||||
* @brief Get number of valid and unacknowledged bytes in a window
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param noOfBytes_p Pointer to write number of bytes into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfBytes( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const noOfBytes_p);
|
||||
|
||||
/**
|
||||
* @brief Get number of valid and unacknowledged samples in a window
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param noOfSamples_p Pointer to write number of samples into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const noOfSamples_p);
|
||||
|
||||
/**
|
||||
* @brief Get the number of pre-trigger samples in a window (post trigger samples are known by config)
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param preTrigSamples_p Pointer to write number of pre-trigger samples into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetPreTrigSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const preTrigSamples_p);
|
||||
|
||||
/**
|
||||
* @brief Get the timestamp of a window
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param timestamp_p Pointer to write the timestamp to
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetTimestamp( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint64_t* const timestamp_p);
|
||||
|
||||
/**
|
||||
* @brief Get unwrapped copy of the data in a window.
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param preTrigSamples Number of pre trigger samples to read
|
||||
* @param postTrigSamples Number of post trigger samples to read (including the trigger sample)
|
||||
* @param buffer_p Buffer to copy the data into
|
||||
* @param bufferSize Size of buffer_p
|
||||
* @return Return Code
|
||||
*
|
||||
* @note This function does not acknowledge the reading of the data. To do so, use PsiMsDaq_StrWin_MarkAsFree()
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetDataUnwrapped( PsiMsDaq_WinInfo_t winInfo,
|
||||
const uint32_t preTrigSamples,
|
||||
const uint32_t postTrigSamples, //including trigger
|
||||
void* const buffer_p,
|
||||
const size_t bufferSize);
|
||||
|
||||
/**
|
||||
* @brief Mark a window as free so it can receive new data. This function must be called after the window data is read
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_MarkAsFree( PsiMsDaq_WinInfo_t winInfo);
|
||||
|
||||
/**
|
||||
* @brief Get the address of the last sample (not byte) written into a window
|
||||
*
|
||||
* @param winInfo Window information
|
||||
* @param lastSplAddr_p Pointer to write the address of the last sample into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetLastSplAddr( PsiMsDaq_WinInfo_t winInfo,
|
||||
uint32_t* const lastSplAddr_p);
|
||||
|
||||
//*******************************************************************************
|
||||
// Advanced Functions (only required for close control)
|
||||
//*******************************************************************************
|
||||
|
||||
/**
|
||||
* @brief Check if the recorder of a given stream is currently recording data
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param isRecording_p Pointer to write the result into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_IsRecording( PsiMsDaq_StrHandle strHndl,
|
||||
bool* const isRecording_p);
|
||||
|
||||
/**
|
||||
* @brief Get the currently used recorder window
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param currentWin_p Pointer to write the result into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_CurrentWin( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const currentWin_p);
|
||||
|
||||
/**
|
||||
* @brief Get the current write pointer of the recording logic
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param currentPtr_p Pointer to write the result into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_CurrentPtr( PsiMsDaq_StrHandle strHndl,
|
||||
uint32_t* const currentPtr_p);
|
||||
|
||||
/**
|
||||
* @brief Get the number of the last window that was written to memory completely
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @param lastWrittenWin_p Pointer to write the result into
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetLastWrittenWin( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const lastWrittenWin_p);
|
||||
|
||||
/**
|
||||
* @brief Write to a register
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param value Value to write
|
||||
* @return Return Code
|
||||
*
|
||||
* @note This function should only be used for debugging purposes!
|
||||
* Otherwise the driver might not work.
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegWrite( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Read a register
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param value_p Read value
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegRead( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
uint32_t* const value_p);
|
||||
|
||||
/**
|
||||
* @brief Set a field in a register (RMW)
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param lsb Least significant bit number of the field
|
||||
* @param msb Most significant bit number of the field
|
||||
* @param value Value to write
|
||||
* @return Return Code
|
||||
*
|
||||
* @note This function should only be used for debugging purposes!
|
||||
* Otherwise the driver might not work.
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegSetField( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint8_t lsb,
|
||||
const uint8_t msb,
|
||||
const uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Read a field from a register
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param lsb Least significant bit number of the field
|
||||
* @param msb Most significant bit number of the field
|
||||
* @param value_p Read value
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegGetField( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint8_t lsb,
|
||||
const uint8_t msb,
|
||||
uint32_t* const value_p);
|
||||
|
||||
/**
|
||||
* @brief Set a bit in a register (RMW)
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param mask Bitmask
|
||||
* @param value Value to write
|
||||
* @return Return Code
|
||||
*
|
||||
* @note This function should only be used for debugging purposes!
|
||||
* Otherwise the driver might not work.
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegSetBit( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t mask,
|
||||
const bool value);
|
||||
|
||||
/**
|
||||
* @brief Read a bit from a register
|
||||
*
|
||||
* @param ipHandle Driver handle for the whole IP
|
||||
* @param addr Register address
|
||||
* @param mask Bitmask
|
||||
* @param value_p Read value
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_RegGetBit( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t mask,
|
||||
bool* const value_p);
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user