/*******************************************************************************
* TmsTestData.cpp TMS Test code for a Data Client
* T.Barnaby, BEAM Ltd, 2007-10-02
*******************************************************************************
*
* This is a simpe test program to fetch data from the TMS system.
* This example fetches the Sigma/DeltaX/DeltaY levels from all
* pickups.
*/
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/time.h>
#include <BFile.h>
#include <TmsD.h>
#include <TmsC.h>
#define DEBUG 0
#if DEBUG
#define dprintf(fmt, a...) printf(fmt, ##a);
#else
#define dprintf(fmt, a...)
#endif
using namespace Tms;
using namespace std;
const char* cycleType = "SimBeam3";
const char* testSignalFileName = "beam3-437000-8.psd";
// Get current time in seconds
double getTime()
{
struct timeval tp;
gettimeofday(&tp, NULL);
return ((double) tp.tv_sec + (double) tp.tv_usec * 1e-6);
}
void dumpData(Data& data, int dump){
BFile file(BString("data") + dump + ".txt", "w");
int n;
for(n = 0; n < data.numValues; n++){
file.printf("%d %d %d\n", n, data.dataValues[n].sigma, data.dataValues[n].time);
}
}
BError dataCheck(Data& data){
BError err;
BUInt32 c;
BUInt32 s;
BUInt32 b;
BUInt32 bunchValues[] = {8651, 7151, 6070, 4937};
BUInt32 timeStart = 400;
BUInt32 numSamples;
BUInt32 o;
BUInt32 t;
int numErrorSigma = 0;
int numErrorTime = 0;
int errorSample = -1;
static int dump = 0;
numSamples = data.numValues / data.numBunches / data.numChannels;
// Don't look at the last ms of sample sas a harmonic change may have occurred
numSamples -= 437;
dprintf("CheckData: NumValues: %d NumChannels: %d NumBunches: %d NumSamples: %d\n", data.numValues, data.numChannels, data.numBunches, numSamples);
for(c = 0; c < data.numChannels; c++){
for(s = 0; s < numSamples; s++){
for(b = 0; b < data.numBunches; b++){
o = (c * numSamples * data.numBunches) + (s * data.numBunches) + b;
t = timeStart + (s / 437);
// printf("%d,%d,%d: %d %d\n", c, b, s, data.dataValues[o].sigma, data.dataValues[o].time);
if((data.dataValues[o].sigma > (bunchValues[b] * 1.1)) || data.dataValues[o].sigma < (bunchValues[b] * 0.9)){
dprintf("Sigma out of range: (%d.%d.%d) %d should be: %d\n", c, s, b, data.dataValues[o].sigma, bunchValues[b]);
numErrorSigma++;
if(errorSample == -1)
errorSample = o;
}
if((data.dataValues[o].time > (t * 1.1)) || (data.dataValues[o].time < (t * 0.9))){
dprintf("Time out of range: (%d.%d.%d) %u should be: %u\n", c, s, b, data.dataValues[o].time, t);
numErrorTime++;
if(errorSample == -1)
errorSample = o;
}
}
}
}
if(numErrorSigma || numErrorTime){
printf("DataErrors: Dump: %d Sigma: %u Time: %u Sample: %d\n", dump, numErrorSigma, numErrorTime, errorSample);
dumpData(data, dump++);
err.set(1, "Data errors");
}
return err;
}
// Function to get information on Cycle
BError tmsInformation(TmsControl& tmsControl, TmsProcess& tmsProcess){
BError err;
UInt32 cn;
BString ct;
CycleInformation info;
BIter i;
// Get current cycle info
if(err = tmsProcess.getCycleInfo(cn, ct)){
return err.set(1, BString("Error: Getting Cycle Number: ") + err.getString());
}
printf("CycleNumber: %u CycleType: %s\n", cn, ct.retStr());
if(err = tmsProcess.getCycleInformation(cn, info)){
return err.set(1, BString("Error: Getting Cycle Information: ") + err.getString());
}
printf("CycleNumber: %u\n", info.cycleNumber);
printf("CycleType: %s\n", info.cycleType.retStr());
for(info.periods.start(i); !info.periods.isEnd(i); info.periods.next(i)){
printf("CyclePeriod: %u StartTime: %u EndTime: %u NumBunches: %u NumValues: %u\n",
info.periods[i].cyclePeriod, info.periods[i].startTime, info.periods[i].endTime, info.periods[i].numBunches, info.periods[i].numValues);
}
return err;
}
// Function to set system to use simulated timing and data
BError tmsSimData(TmsControl& tmsControl, TmsProcess& tmsProcess){
BError err;
UInt32 cn;
BString ct;
ConfigInfo configInfo;
PupeConfig pupeConfig;
unsigned int n;
BArray<UInt32> data;
BFile file;
int nb;
// Read the test signal file
if(err = file.open(testSignalFileName, "r")){
if(err = file.open(BString("/usr/tms/data/") + testSignalFileName, "r")){
return err.set(1, BString("Error: Opening file: ") + testSignalFileName);
}
}
data.resize(1024);
if((nb = file.read(&data[0], 1024 * sizeof(UInt32))) <= 0){
return err.set(1, BString("Error: Reading 1024 32bit data items from file: ") + testSignalFileName);
}
data.resize(nb / sizeof(UInt32));
// Sets the CycleType to match the data
// Get current cycle info
if(err = tmsProcess.getCycleInfo(cn, ct)){
return err.set(1, BString("Error: Getting Cycle Number: ") + err.getString());
}
// Set NextCycle type
if(err = tmsControl.setNextCycle(cn + 1, cycleType)){
return err.set(1, BString("Error: Setting Next Cycle: ") + err.getString());
}
if(err = tmsControl.getConfiguration(configInfo)){
return err.set(1, BString("Error: getting configuration TMS: ") + err.getString());
}
// Sets up the simulated timing system
pupeConfig.adcSysclkSync = 0;
// pupeConfig.internalTimingMask = 0x7D; // Expects CYCLE_START signal
pupeConfig.internalTimingMask = 0x7f; // Internal CYCLE_START signal
pupeConfig.disableBlr = 0;
for(n = 0; n < configInfo.puReferences.size(); n++){
if(err = tmsControl.setPupeConfig(configInfo.puReferences[n], pupeConfig)){
return err.set(1, err.getString());
}
if(err = tmsControl.setTestData(configInfo.puReferences[n], 1, data)){
return err.set(1, err.getString());
}
}
return err;
}
// Function to read some data
BError tmsTestSingle(TmsControl& tmsControl, TmsProcess& tmsProcess, int numSamples, int check, int channel){
BError err;
DataInfo dataInfo;
UInt32 cn = 0;
BString ct;
Data data;
double timeStart = 0;
double t1 = 0;
double t2 = 0;
double timeEnd = 0;
int i;
int repeat = 4;
double r;
if(numSamples == 0)
numSamples = 1024000;
// Find out the current cycle number and type
if(err = tmsProcess.getCycleInfo(cn, ct)){
return err.set(1, BString("Error: Getting Cycle Number: ") + err.getString());
}
printf("Getting data from pick-up %d for cycle: %u\n", channel, cn);
for(i = 0; i < repeat; i++){
dataInfo.cycleNumber = cn;
dataInfo.channel = channel;
dataInfo.cyclePeriod = CyclePeriodHarmonic0;
dataInfo.startTime = 0;
dataInfo.orbitNumber = 0;
dataInfo.bunchNumber = 0;
dataInfo.function = DataFunctionRaw;
dataInfo.argument = 0;
dataInfo.numValues = numSamples;
dataInfo.limitData = 1;
t1 = getTime();
if(err = tmsProcess.getData(dataInfo, data)){
return err.set(1, BString("Error: Getting Data: ") + err.getString());
}
t2 = getTime();
if(timeStart == 0.0)
timeStart = t2;
printf("CycleNum: %d Channel: %d Read: %d Time: %f\n", cn, dataInfo.channel, data.numValues, t2 - t1);
if(check){
if(err = dataCheck(data))
return err;
}
}
numSamples = data.numValues;
timeEnd = t2;
r = (sizeof(DataValue) * numSamples * (repeat - 1)) / (timeEnd - timeStart);
printf("Time to fetch data: %f DataRate: %fMBytes/sec\n", timeEnd - timeStart, r / (1024*1024));
return err;
}
// Function to read some data
BError tmsTestAllManual(TmsControl& tmsControl, TmsProcess& tmsProcess, int check){
BError err;
DataInfo dataInfo;
UInt32 cn = 0;
BString ct;
UInt32 numChans = 40;
UInt32 n;
Data data[numChans];
Data dataAll;
double timeStart = 0;
double t1 = 0;
double t2 = 0;
double timeEnd = 0;
int i;
int repeat = 4;
int numSamples = 20000;
double r;
ConfigInfo configInfo;
// Get configuration
if(err = tmsControl.getConfiguration(configInfo)){
return err.set(1, BString("Error: Getting Configuration: ") + err.getString());
}
numChans = configInfo.puReferences.size();
// Find out the current cycle number and type
if(err = tmsProcess.getCycleInfo(cn, ct)){
return err.set(1, BString("Error: Getting Cycle Number: ") + err.getString());
}
printf("Getting data from all pick-ups for cycle: %u\n", cn);
for(i = 0; i < repeat; i++){
for(n = 0; n < numChans; n += 1){
dataInfo.cycleNumber = cn;
dataInfo.channel = 1 + n;
dataInfo.cyclePeriod = CyclePeriodHarmonic0;
dataInfo.startTime = 0;
dataInfo.orbitNumber = 0;
dataInfo.bunchNumber = 0;
dataInfo.function = DataFunctionRaw;
dataInfo.argument = 0;
dataInfo.numValues = numSamples;
dataInfo.limitData = 1;
t1 = getTime();
if(err = tmsProcess.getData(dataInfo, data[n])){
return err.set(1, BString("Error: Getting Data: ") + err.getString());
}
t2 = getTime();
if(timeStart == 0.0)
timeStart = t2;
printf("CycleNum: %d Channel: %d Time: %f\n", cn, 1 + n, t2 - t1);
if(check){
#ifndef ZAP
if(err = dataCheck(data[n]))
return err;
#else
dataCheck(data[n]);
#endif
}
// usleep(100000);
}
}
numSamples = data[0].numValues;
timeEnd = getTime();
r = (sizeof(DataValue) * numSamples * numChans * (repeat - 1)) / (timeEnd - timeStart);
printf("Time to fetch data: %f DataRate: %fMBytes/sec\n", timeEnd - timeStart, r / (1024*1024));
return err;
}
// Function to reads some data
BError tmsTestAll(TmsControl& tmsControl, TmsProcess& tmsProcess, int numSamples, int check){
BError err;
DataInfo dataInfo;
UInt32 cn = 0;
BString ct;
UInt32 numChans = 40;
UInt32 n;
Data data;
double timeStart = 0;
double t1 = 0;
double t2 = 0;
double timeEnd = 0;
int i;
int repeat = 4;
double r;
ConfigInfo configInfo;
if(numSamples == 0)
numSamples = 300000;
// Get configuration
if(err = tmsControl.getConfiguration(configInfo)){
return err.set(1, BString("Error: Getting Configuration: ") + err.getString());
}
numChans = configInfo.puReferences.size();
// Find out the current cycle number and type
if(err = tmsProcess.getCycleInfo(cn, ct)){
return err.set(1, BString("Error: Getting Cycle Number: ") + err.getString());
}
printf("Getting data from %d pick-ups for cycle: %u\n", configInfo.puReferences.size(), cn);
for(i = 0; i < repeat; i++){
dataInfo.cycleNumber = cn;
dataInfo.channel = 0;
dataInfo.cyclePeriod = CyclePeriodHarmonic0;
dataInfo.startTime = 0;
dataInfo.orbitNumber = 0;
dataInfo.bunchNumber = 0;
dataInfo.function = DataFunctionRaw;
dataInfo.argument = 0;
dataInfo.numValues = numSamples;
dataInfo.limitData = 1;
t1 = getTime();
if(err = tmsProcess.getData(dataInfo, data)){
return err.set(1, BString("Error: Getting Data: ") + err.getString());
}
t2 = getTime();
if(timeStart == 0.0)
timeStart = t2;
printf("CycleNum: %d Time: %fs NumValues: %d\n", cn, t2 - t1, data.numValues);
if(check){
#ifndef ZAP
if(err = dataCheck(data))
return err;
#else
dataCheck(data);
#endif
}
// cn++;
// usleep(100000);
}
numSamples = data.numValues;
timeEnd = t2;
r = (sizeof(DataValue) * numSamples * (repeat - 1)) / (timeEnd - timeStart);
printf("Time to fetch data: %f DataRate: %fMBytes/sec\n", timeEnd - timeStart, r / (1024*1024));
return err;
}
void usage(void) {
cerr << "Usage:\ttmsTestData [options] hostname\n";
cerr << " -help - Help on command line parameters\n";
cerr << " -simdata - Set the system to use simulated timing signals and test data\n";
cerr << " -info - Prints information on the processing cycle\n";
cerr << " -numSamples <n> - The number of samples to read\n";
cerr << " -test <testName> - The Test to be performed: single - single channel all bunches, all - all bunches all channels\n";
cerr << " -check - Check the data for validity\n";
cerr << " -cont - Continuous\n";
cerr << " -channel <n> - Channel number\n";
}
static struct option options[] = {
{ "?", 0, NULL, 0 },
{ "h", 0, NULL, 0 },
{ "help", 0, NULL, 0 },
{ "simdata", 0, NULL, 0 },
{ "info", 0, NULL, 0 },
{ "check", 0, NULL, 0 },
{ "cont", 0, NULL, 0 },
{ "numSamples", 1, NULL, 0 },
{ "test", 1, NULL, 0 },
{ "channel", 1, NULL, 0 },
{ 0,0,0,0 }
};
int main(int argc, char** argv){
BError err;
BString hostName = "localhost";
TmsProcess tmsProcess;
TmsControl tmsControl;
int optIndex = 0;
int c;
BString s;
int simData = 0;
int info = 0;
int check = 0;
int cont = 0;
BString test;
int numSamples = 0;
int channel = 1;
while((c = getopt_long_only(argc, argv, "", options, &optIndex)) == 0){
s = options[optIndex].name;
if(s == "help" || s == "h" || s == "?"){
usage();
return 1;
}
else if(s == "simdata"){
simData = 1;
}
else if(s == "info"){
info = 1;
}
else if(s == "check"){
check = 1;
}
else if(s == "cont"){
cont = 1;
}
else if(s == "test"){
test = optarg;
}
else if(s == "numSamples"){
numSamples = strtol(optarg, 0, 0);
}
else if(s == "channel"){
channel = strtol(optarg, 0, 0);
}
else {
usage();
return 1;
}
}
if(optind == argc){
usage();
return 1;
}
hostName = argv[optind++];
// Connect to the Control service
if(err = tmsControl.connectService(BString("//") + hostName + "/tmsControl")){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
// Connect to the Process service
if(err = tmsProcess.connectService(BString("//") + hostName + "/tmsProcess")){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
if(simData){
if(err = tmsSimData(tmsControl, tmsProcess)){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
if(test != "")
sleep(3);
}
if(info){
if(err = tmsInformation(tmsControl, tmsProcess)){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
}
if(test == "single"){
// Run a normal data gathering cycle as a normal client would.
do {
if(err = tmsTestSingle(tmsControl, tmsProcess, numSamples, check, channel)){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
} while(cont);
}
else if(test == "all"){
do {
if(err = tmsTestAll(tmsControl, tmsProcess, numSamples, check)){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
} while(cont);
}
else if(test == "allManual"){
do {
if(err = tmsTestAllManual(tmsControl, tmsProcess, check)){
cerr << "Error: " << err.getString() << "\n";
return 1;
}
} while(cont);
}
return 0;
}