...
Gliffy Diagram |
---|
| |
---|
name | BlenFcom processBlob() |
---|
|
Anchor |
---|
| BSA_THREAD_TASK |
---|
| BSA_THREAD_TASK |
---|
|
Thread task in a continuous loop to deal with BSA storing and data being sent to the fast feedback system. It is in the file cpswStreamBSA.cpp.
...
As explained in Calculate the maximum current and signal sum, there is a thread responsible to store the data to the BSA Core as soon as the data is ready. The firmware sends the data to the software using a CPSW stream channel. The name of the stream channel is defined in the YAML file and must be informed to the BSA thread by the second parameter of the st.cmd function blenConfigure (explained before). Every time the data is ready, the firmware sends it asynchronously and the software must be prepared to read and process it. The complete data structure of this stream can be checked here. For what is in use by the current IOC application, this is the struct that is mapped to the stream packet:
Code Block |
---|
language | cpp |
---|
title | streamDataType.h |
---|
|
typedef struct {
epicsTimeStamp time;
epicsUInt32 mod[6];
epicsUInt32 edefAvgDoneMask;
epicsUInt32 edefMinorMask;
epicsUInt32 edefMajorMask;
epicsUInt32 edefInitMask;
} timing_header_t;
typedef struct {
epicsFloat32 sum;
epicsFloat32 iMax;
epicsFloat32 scaledTMIT;
epicsUInt32 status0;
epicsUInt32 status1;
// Seven 32-bit words reserved for future use
epicsUInt32 reservedWords[6];
} payload_t;
/* This structure represents the entire content of the BSA stream message that
* comes from the firmware. If the message content is changed, this structure
* must be updated */
typedef struct {
// Stream header is not described at the specification.
epicsUInt64 streamHeader;
epicsUInt32 headerWord;
timing_header_t timingHeader;
payload_t AMC0_Data;
payload_t AMC1_Data;
} stream_t; |
If you retake the BSA thread task activity diagram, the data receive some processing and is mapped to another data structure to make it easier to extract data to the BSA core. This is the structure:
Code Block |
---|
language | cpp |
---|
title | blenBSA.h |
---|
|
// Data to be sent to BSA channels
typedef struct bsaData_t {
epicsTimeStamp timeStamp;
double aImax;
double aSum;
BsaStat aStat;
BsaSevr aSevr;
double bImax;
double bSum;
BsaStat bStat;
BsaSevr bSevr;
} bsaData_t; |
Once this structure is filled, the last step is to send the data to the BSA channels:
Code Block |
---|
language | cpp |
---|
title | blenBSA.cpp |
---|
|
// bsaData is of type bsaData_t
void BlenBSA::sendData(bsaData_t* bsaData) {
BSA_StoreData(bsaChannels[0], bsaData->timeStamp, bsaData->aImax,
bsaData->aStat, bsaData->aSevr);
BSA_StoreData(bsaChannels[1], bsaData->timeStamp, bsaData->bImax,
bsaData->bStat, bsaData->bSevr);
BSA_StoreData(bsaChannels[2], bsaData->timeStamp, bsaData->aSum,
bsaData->aStat, bsaData->aSevr);
BSA_StoreData(bsaChannels[3], bsaData->timeStamp, bsaData->bSum,
bsaData->bStat, bsaData->bSevr);
} |
After this step, the internal arrays with timestamp aligned data are filled and ready to be accessed as PVs by the interested users. It was not mentioned before, but the BSA database should be loaded for the PVs to be made available. This loading is done in the file iocBoot/common/blenCommon.cmd, with a call to dbLoadRecords for each BSA channel:
Code Block |
---|
language | bash |
---|
title | iocBoot/common/blenCommon.cmd |
---|
|
# BSA records
dbLoadRecords("db/Bsa.db", "DEVICE=BLEN:${AREA}:${POS},ATRB=AIMAX, SINK_SIZE=1")
dbLoadRecords("db/Bsa.db", "DEVICE=BLEN:${AREA}:${POS},ATRB=BIMAX, SINK_SIZE=1")
dbLoadRecords("db/Bsa.db", "DEVICE=BLEN:${AREA}:${POS},ATRB=ARAW, SINK_SIZE=1")
dbLoadRecords("db/Bsa.db", "DEVICE=BLEN:${AREA}:${POS},ATRB=BRAW, SINK_SIZE=1") |
Algorithm description
Waveform and integration windows
...