📄 updown.c
字号:
* Re-initialize trigger fields.
*/
uploadInfo.trigInfo.count = 0;
uploadInfo.trigInfo.haveOldTrigSigVal = FALSE;
/*
* Reset pre-trig counts for normal mode.
*/
uploadInfo.trigInfo.preTrig.count = 0;
/*
* Re-arm after all initialization. Make sure that trigInfo.state is
* set last since this routine may be interupted.
*/
uploadInfo.trigInfo.state = TRIGGER_ARMED;
} /* end UploadArmTrigger */
/* Function ====================================================================
* Terminate this data logging session by destroying the uploadInfo and
* setting the trigger backed to the unarmed state.
*/
PRIVATE void EndLoggingSession(void)
{
uploadInfo.trigInfo.state = TRIGGER_UNARMED;
UploadLogInfoTerm();
} /* end UploadEndLoggingSession */
/* Function ====================================================================
* Cancel this data logging session.
*/
PUBLIC void UploadCancelLogging(void)
{
switch(uploadInfo.trigInfo.state) {
case TRIGGER_UNARMED:
break;
case TRIGGER_HOLDING_OFF:
case TRIGGER_ARMED:
case TRIGGER_DELAYED:
case TRIGGER_FIRED:
/*
* Move to TRIGGER_TERMINATING and ensure that we are no longer in
* "normal" mode (TRIGMODE_NORMAL) so that the trigger does not get
* re-armed.
*/
uploadInfo.trigInfo.holdOff = TRIGMODE_ONESHOT;
uploadInfo.trigInfo.state = TRIGGER_TERMINATING;
#ifdef VXWORKS
/*
* Let upload server run to ensure that term msg is sent to host (needed
* for all but the TRIGGERED_FIRED case since the upload server is
* inactive).
*/
semGive(uploadSem);
#endif
break;
case TRIGGER_TERMINATING:
case TRIGGER_SENDING_TERM_MSG:
/*
* Ensure that we are no longer in "normal" mode (TRIGMODE_NORMAL) so
* that the trigger does not get re-armed.
*/
uploadInfo.trigInfo.holdOff = TRIGMODE_ONESHOT;
break;
}
} /* end UploadCancelLogEvent */
/* Function ====================================================================
* Called by ext_svr (background task), in order to perform tasks that need
* to be done after each time that data has been sent to the host. This
* includes:
*
* o move the tail for the specified buffer forward
* o detect the end of a data logging event so that the trigger state can
* be either set to unarmed (for one shot) or backed to armed (for normal
* mode).
*
* NOTE: UploadBufGetData and UploadBufMoveTail must be called in pairs where the
* UploadBufGetData call precedes the UploadBufMoveTail call.
*/
PUBLIC void UploadBufDataSent(const int_T tid)
{
CircularBuf *circBuf = &uploadInfo.circBufs[tid];
/*
* Move the tail forward. Since we are moving the tail forward, we know that
* head == tail represents an empty buffer and not a full buffer.
*/
circBuf->tail = circBuf->newTail;
circBuf->empty = (circBuf->tail == circBuf->head);
/*
* See if this is the end of the data logging event.
*/
if (uploadInfo.trigInfo.state == TRIGGER_SENDING_TERM_MSG) {
if (uploadInfo.trigInfo.holdOff == TRIGMODE_ONESHOT) {
EndLoggingSession();
} else {
uploadInfo.trigInfo.count = 0;
uploadInfo.trigInfo.state = TRIGGER_HOLDING_OFF;
}
}
} /* end UploadBufDataSent */
/*
* Macro =======================================================================
* Move the tail of a circular buffer forward by one time step - accounting for
* wrapping.
*/
#define MOVE_TAIL_ONESTEP(circBuf, end) \
{ \
int nBytesPassedEnd; \
int nBytesInStep; \
\
(void)memcpy(&nBytesInStep, (circBuf)->tail, sizeof(int32_T)); \
assert(nBytesInStep > 0); \
(circBuf)->tail += (nBytesInStep); \
nBytesPassedEnd = (circBuf)->tail - (end); \
if (nBytesPassedEnd >= 0) { \
(circBuf)->tail = (circBuf)->buf + nBytesPassedEnd; \
} \
} /* end MOVE_TAIL_ONESTEP */
/*
* Macro =======================================================================
* Copy data into the circular buffer.
*/
#define CIRCBUF_COPY_DATA(bufMem, data) \
{ \
(void)memcpy((bufMem).section1, (data), (uint16_T)((bufMem).nBytes1)); \
if ((bufMem).section2 != NULL) { \
char *tmp = ((char *)(data)) + (bufMem).nBytes1; \
(void)memcpy((bufMem).section2, tmp, (uint16_T)((bufMem).nBytes2)); \
} \
} /* end CIRCBUF_COPY_DATA */
/* Function ====================================================================
* Assign sections in the circular buffer for the requested number of bytes
* (i.e., fill in the bufMem struct). If there is no room in the circular
* buffer return an overflow error.
*
* NOTE: Do not move the CircularBuffers head forward in this function!
* Only move the tmpHead forward. The actual head is not advanced
* until the entire time point is successfully copied into the buffer.
*
* This function modifies tmpHead to point at the next available
* location.
*
* It is possible for tmpHead to equal the tail upon entry to this
* function. This does not necessarily mean that the buffer is
* empty (unwrapped). It could also mean that the buffer is exactly
* full (this is considered as wrapped).
*/
PRIVATE boolean_T UploadBufAssignMem(
CircularBuf *circBuf,
int_T nBytesToAdd,
char **tmpHead, /* in-out */
BufMem *bufMem) /* out */
{
int_T nBytesLeft;
boolean_T overFlow = FALSE;
char *end = circBuf->buf + circBuf->bufSize; /* 1 passed end */
if ((*tmpHead > circBuf->tail) || circBuf->empty) {
/* buffer not wrapped */
nBytesLeft = (end - *tmpHead) + (circBuf->tail - circBuf->buf);
if (nBytesLeft < nBytesToAdd) {
overFlow = TRUE;
goto EXIT_POINT;
}
if ((*tmpHead + nBytesToAdd) < end) {
/* still not wrapped */
bufMem->nBytes1 = nBytesToAdd;
bufMem->section1 = *tmpHead;
bufMem->nBytes2 = 0;
bufMem->section2 = NULL;
*tmpHead += nBytesToAdd;
} else {
/* now we're wrapped */
bufMem->nBytes1 = end - *tmpHead;
bufMem->section1 = *tmpHead;
bufMem->nBytes2 = nBytesToAdd - bufMem->nBytes1;
bufMem->section2 = (bufMem->nBytes2 > 0) ? circBuf->buf : NULL;
*tmpHead = circBuf->buf + bufMem->nBytes2;
}
} else {
/* wrapped */
nBytesLeft = circBuf->tail - *tmpHead;
if (nBytesLeft < nBytesToAdd) {
overFlow = TRUE;
goto EXIT_POINT;
}
bufMem->nBytes1 = nBytesToAdd;
bufMem->section1 = *tmpHead;
bufMem->nBytes2 = 0;
bufMem->section2 = NULL;
*tmpHead += nBytesToAdd;
}
EXIT_POINT:
return(overFlow);
} /* end UploadBufAssignMem */
/* Function ====================================================================
* Check the trigger signals for crossings. Return true if a trigger event is
* encountered. It is assumed that the trigger signals are real_T.
*/
PRIVATE boolean_T UploadCheckTriggerSignals(void)
{
int i;
TriggerInfo *trigInfo = &uploadInfo.trigInfo;
real_T *oldTrigSigVals = trigInfo->oldTrigSigVals;
real_T *oldSigPtr = oldTrigSigVals;
for (i=0; i<trigInfo->trigSignals.nSections; i++) {
BIOSection *section = &trigInfo->trigSignals.sections[i];
int_T nEls = section->nBytes / sizeof(real_T); /* xxx cache? */
/*
* If we have a previous signal value to check, then see if we had
* a crossing.
*/
if (trigInfo->haveOldTrigSigVal) {
int_T j;
real_T level = trigInfo->level;
real_T *rStart = (real_T *)section->start; /* gauranteed by host */
for (j=0; j<nEls; j++) {
if (trigInfo->lookForRising &&
(((rStart[j] >= level) && (oldSigPtr[j] < level)) ||
((rStart[j] > level) && (oldSigPtr[j] == level)))) {
return(TRUE);
}
if (trigInfo->lookForFalling &&
(((rStart[j] < level) && (oldSigPtr[j] >= level)) ||
((rStart[j] == level) && (oldSigPtr[j] > level)))) {
return(TRUE);
}
}
}
/*
* Update old signal values.
*/
(void)memcpy(oldSigPtr, section->start, (uint16_T)(section->nBytes));
oldSigPtr += section->nBytes;
}
assert(oldTrigSigVals + trigInfo->trigSignals.nBytes == oldSigPtr);
trigInfo->haveOldTrigSigVal = TRUE;
return(FALSE);
} /* end UploadCheckTriggerSignals */
/* Function ====================================================================
* If the trigger is in the TRIGGER_FIRED state or we are collecting data for
* pretriggering, add data, for each tid with a hit, to the upload buffers.
* This function is called from within the appropriate task, once per sample
* hit.
*
* The format of the message that is sent to the host is as follows:
*
* definitions:
* nBytes - total number of target bytes for this message (including the
* nBytes field). nBytes worth of data represents 1 full time
* step of the target simulation.
*
* msgType - A qualifier indicating any special action that needs to be
* taken (e.g., a termination flag following the last data point,
* or a flag indicating that it is the first data point after
* a trigger event).
*
* nSys - The number of systems for which this message contains data.
*
* tid - The tid with which this data is associated.
*
* t - simulation time
*
* sysId - The index into the BdUploadInfo.sysTables array so that we can
* map the target data back to the appropriate sytstem. This is
* NOT the descendent system index!
*
* data - the target simulation data (in target format)
*
* The message looks like:
* [nBytes msgType nSys tid t sysId [data] sysId [data]...]
* | | | | | |
* ----------------------- ----------- ------------
* msg header sys data sys data
*
* Ints are int32_T.
*/
PUBLIC void UploadBufAddTimePoint(int_T tid, real_T taskTime)
{
int_T preTrig;
TriggerInfo *trigInfo = &uploadInfo.trigInfo;
CircularBuf *circBuf = &uploadInfo.circBufs[tid];
int_T overFlow = FALSE;
/*
* Check for transitions from the TRIGGER_ARMED state to either the
* TRIGGER_FIRED_STATE or the TRIGGER_DELAYED state. We only do this
* if it is a sample hit for the trigger signal. Note that this
* is the only place in the whole world that the trigger state can
* move from TRIGGER_ARMED_STATE to TRIGGER_DELAYED or TRIGGER_FIRED.
*/
if ((tid == trigInfo->tid) && (trigInfo->state == TRIGGER_ARMED)) {
if ((trigInfo->trigSignals.nSections == 0) || /* manual trigger */
(UploadCheckTriggerSignals())) { /* trig signal crossing */
if (trigInfo->delay == 0) {
trigInfo->state = TRIGGER_FIRED;
trigInfo->count = (uint_T)trigInfo->preTrig.count; /* 0 unless pretrig */
} else {
trigInfo->state = TRIGGER_DELAYED;
assert(trigInfo->count == 0);
/* We will be skipping this step, so the delay count is 1. */
trigInfo->count = 1;
}
}
}
preTrig = (trigInfo->state == TRIGGER_ARMED) &&
(trigInfo->preTrig.duration > 0);
/*
* Handle adding data to the collection buffers - if needed.
*/
if (((trigInfo->state == TRIGGER_FIRED) || preTrig) &&
circBuf->bufSize != 0) { /* bufSize == 0 means no signals in this tid */
int_T i;
BufMem bufMem;
BufMem msgStart;
int_T size;
char_T *tmpHead = circBuf->head;
const int_T NBYTES_IDX = 0;
const int_T MSG_TYPE_IDX = 1;
const int_T NSYS_IDX = 2;
const int_T TID_IDX = 3;
int32_T intHdr[4] = {0,0,0,0};
if (preTrig && (trigInfo->preTrig.count==trigInfo->preTrig.duration)) {
/* Advance the tail (we don't need the oldest point anymore). */
char *end = circBuf->buf + circBuf->bufSize;
MOVE_TAIL_ONESTEP(circBuf, end);
trigInfo->preTrig.count--;
}
/*
* Save some space for the 4 integer values that make up the message
* header: [nBytes msgType nSys tid]. The values are filled in later.
*/
size = 4*sizeof(int32_T);
overFlow = UploadBufAssignMem(circBuf, size, &tmpHead, &msgStart);
if (overFlow) goto EXIT_POINT;
intHdr[NBYTES_IDX] += size;
/* time */
overFlow = UploadBufAssignMem(
circBuf, sizeof(real_T), &tmpHead, &bufMem);
if (overFlow) goto EXIT_POINT;
intHdr[NBYTES_IDX] += sizeof(real_T);
CIRCBUF_COPY_DATA(bufMem, &taskTime);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -