Skip to content

Commit 75a6993

Browse files
Change SCA and register publish format to string
1 parent 0d551dd commit 75a6993

File tree

2 files changed

+60
-51
lines changed

2 files changed

+60
-51
lines changed

src/CommandLineUtilities/AliceLowlevelFrontend/ProgramAliceLowlevelFrontendServer.cxx

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
///
1515
/// \author Pascal Boeschoten ([email protected])
1616

17+
#define __STDC_WANT_LIB_EXT1__ 1
18+
#include <string>
19+
1720
#include "Common/Program.h"
1821
#include "CommandLineUtilities/Common.h"
1922
#include <chrono>
@@ -103,6 +106,16 @@ static std::vector<T> lexicalCastVector(const std::vector<U>& items)
103106
return result;
104107
}
105108

109+
size_t strlenMax(char* string, size_t max)
110+
{
111+
for (size_t i = 0; i < max; ++i) {
112+
if (string[i] == '\0') {
113+
return i;
114+
}
115+
};
116+
return max;
117+
}
118+
106119
struct LinkInfo
107120
{
108121
int serial;
@@ -141,8 +154,8 @@ struct Service
141154

142155
ServiceDescription description;
143156
std::chrono::steady_clock::time_point nextUpdate;
144-
std::vector<uint32_t> registerValues;
145157
std::unique_ptr<DimService> dimService;
158+
std::vector<char> buffer; ///< Needed for DIM
146159
};
147160

148161
/// Thread-safe queue for commands
@@ -337,25 +350,24 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
337350
service->nextUpdate = std::chrono::steady_clock::now();
338351
Visitor::apply(service->description.type,
339352
[&](const ServiceDescription::Register& type){
340-
service->registerValues.resize(type.addresses.size());
341-
353+
// Estimate max needed size. I'm not sure DIM can handle reallocations of this buffer, so we avoid that...
354+
service->buffer.resize(type.addresses.size()*20 + 512);
342355
getLogger() << "Starting register publisher '" << service->description.dnsName << "' with "
343356
<< type.addresses.size() << " address(es) at interval "
344357
<< service->description.interval.count() << "ms" << endm;
345358
},
346359
[&](const ServiceDescription::ScaSequence& type){
347-
service->registerValues.resize(type.commandDataPairs.size() * 2); // Two result 32-bit integers per pair
348-
360+
// Estimate max needed size. I'm not sure DIM can handle reallocations of this buffer, so we avoid that...
361+
service->buffer.resize(type.commandDataPairs.size()*20 + 512);
349362
getLogger() << "Starting SCA publisher '" << service->description.dnsName << "' with "
350363
<< type.commandDataPairs.size() << " commands(s) at interval "
351364
<< service->description.interval.count() << "ms" << endm;
352365
}
353366
);
354367

355-
auto format = (b::format("I:%1%") % service->registerValues.size()).str();
356-
service->dimService = std::make_unique<DimService>(service->description.dnsName.c_str(), format.c_str(),
357-
service->registerValues.data(), service->registerValues.size());
358-
368+
std::fill(service->buffer.begin(), service->buffer.end(), '\0');
369+
service->dimService = std::make_unique<DimService>(service->description.dnsName.c_str(), "C",
370+
service->buffer.data(), strlenMax(service->buffer.data(), service->buffer.size()));
359371
mServices.insert(std::make_pair(serviceDescription.dnsName, std::move(service)));
360372
}
361373

@@ -371,37 +383,30 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
371383
{
372384
getLogger() << "Updating '" << service.description.dnsName << "'" << endm;
373385

386+
std::string result;
387+
374388
Visitor::apply(service.description.type,
375389
[&](const ServiceDescription::Register& type){
390+
std::stringstream ss;
376391
auto& bar0 = *(mBars.at(service.description.linkInfo.serial).at(0));
377392
for (size_t i = 0; i < type.addresses.size(); ++i) {
378393
auto index = type.addresses[i] / 4;
379394
auto value = bar0.readRegister(index);
380-
service.registerValues.at(i) = value;
395+
ss << std::hex << value << '\n';
381396
}
397+
result = ss.str();
382398
},
383399
[&](const ServiceDescription::ScaSequence& type){
384400
auto& bar2 = *(mBars.at(service.description.linkInfo.serial).at(2));
385-
std::fill(service.registerValues.begin(), service.registerValues.end(), 0); // Reset array in case of aborts
386401
auto sca = Sca(bar2, bar2.getCardType(), service.description.linkInfo.link);
387-
for (size_t i = 0; i < type.commandDataPairs.size(); ++i) {
388-
try {
389-
const auto& pair = type.commandDataPairs[i];
390-
sca.write(pair);
391-
auto result = sca.read();
392-
service.registerValues[i*2] = result.command;
393-
service.registerValues[i*2 + 1] = result.data;
394-
} catch (const ScaException &e) {
395-
// If an SCA error occurs, we stop executing the sequence of commands and set the error value
396-
service.registerValues[i*2] = 0xffffffff;
397-
service.registerValues[i*2 + 1] = 0xffffffff;
398-
break;
399-
}
400-
}
402+
result = writeScaSequence(type.commandDataPairs, sca, service.description.linkInfo);
401403
}
402404
);
403405

404-
service.dimService->updateService();
406+
// Reset and copy into the persistent buffer because I don't trust DIM with the non-persistent std::string
407+
std::fill(service.buffer.begin(), service.buffer.end(), '\0');
408+
std::copy(result.begin(), result.end(), service.buffer.begin());
409+
service.dimService->updateService(service.buffer.data(), result.size() + 1);
405410
}
406411

407412
/// Checks if the address is in range
@@ -456,6 +461,31 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
456461
return commandData;
457462
};
458463

464+
/// Writes an SCA sequence and returns a string of the read results separated by newline
465+
static std::string writeScaSequence(const std::vector<Sca::CommandData>& commandDataPairs, Sca& sca,
466+
LinkInfo linkInfo)
467+
{
468+
std::stringstream resultBuffer;
469+
for (const auto& commandData : commandDataPairs) {
470+
try {
471+
sca.write(commandData);
472+
auto result = sca.read();
473+
getLogger() << (b::format("cmd=0x%x data=0x%x result=0x%x") % commandData.command % commandData.data %
474+
result.data).str() << endm;
475+
resultBuffer << std::hex << result.data << '\n';
476+
} catch (const ScaException &e) {
477+
// If an SCA error occurs, we stop executing the sequence of commands and return the results as far as we got
478+
// them, plus the error message.
479+
getLogger() << InfoLogger::InfoLogger::Error
480+
<< (b::format("SCA_SEQUENCE cmd=0x%x data=0x%x serial=%d link=%d error='%s'") % commandData.command
481+
% commandData.data % linkInfo.serial % linkInfo.link % e.what()).str() << endm;
482+
resultBuffer << e.what();
483+
break;
484+
}
485+
}
486+
return resultBuffer.str();
487+
}
488+
459489
/// RPC handler for register reads
460490
static std::string registerRead(const std::string& parameter, BarSharedPtr channel)
461491
{
@@ -627,29 +657,8 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
627657
// We split on \n to get the pairs of SCA command and SCA data
628658
auto lines = split(parameter, argumentSeparator());
629659
auto commandDataPairs = linesToCommandDataVector(lines.begin(), lines.end());
630-
631-
std::stringstream resultBuffer;
632660
auto sca = Sca(*bar2, bar2->getCardType(), linkInfo.link);
633-
634-
for (const auto& commandData : commandDataPairs) {
635-
try {
636-
sca.write(commandData);
637-
auto result = sca.read();
638-
getLogger() << (b::format("cmd=0x%x data=0x%x result=0x%x") % commandData.command % commandData.data %
639-
result.data).str() << endm;
640-
resultBuffer << std::hex << result.data << '\n';
641-
} catch (const ScaException &e) {
642-
// If an SCA error occurs, we stop executing the sequence of commands and return the results as far as we got
643-
// them, plus the error message.
644-
getLogger() << InfoLogger::InfoLogger::Error
645-
<< (b::format("SCA_SEQUENCE cmd=0x%x data=0x%x serial=%d link=%d error='%s'") % commandData.command
646-
% commandData.data % linkInfo.serial % linkInfo.link % e.what()).str() << endm;
647-
resultBuffer << e.what();
648-
break;
649-
}
650-
}
651-
652-
return resultBuffer.str();
661+
return writeScaSequence(commandDataPairs, sca, linkInfo);
653662
}
654663

655664
/// Command queue for passing commands from DIM RPC calls (which are in separate threads) to the main program loop

src/CommandLineUtilities/AliceLowlevelFrontend/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Set enabled the selected GPIO pins
9595
9696
#### PUBLISH_REGISTERS_START
9797
Starts a service that publishes the contents of the given register addresses at the specified interval.
98-
Values are published as array of 32 bit unsigned integers.
98+
Values are published as newline separated integers.
9999
The service will have the DNS name: `ALF/SERIAL_[serial number]/LINK_[link]/PUBLISH_REGISTERS/[service name]`.
100100
* Service type: RPC call
101101
* Parameters:
@@ -113,14 +113,14 @@ Stops a service started with PUBLISH_REGISTERS_START.
113113
114114
#### PUBLISH_SCA_SEQUENCE_START
115115
Starts a service that executes and publishes the results of the given SCA sequence at the specified interval.
116-
Values are published as array of 32 bit unsigned integers (for format, see SCA_SEQUENCE).
116+
Values are published in the same format as the SCA_SEQUENCE return format.
117117
If an error occurred, the corresponding result will be set to 0xffffffff and the rest of the sequence is aborted.
118118
The service will have the DNS name: `ALF/SERIAL_[serial number]/LINK_[link]/PUBLISH_SCA_SEQUENCE/[service name]`.
119119
* Service type: RPC call
120120
* Parameters:
121121
* Service name
122122
* Interval in seconds. The server supports intervals with millisecond precision
123-
* SCA sequence (for format, see SCA_SEQUENCE)
123+
* SCA sequence (for format, see SCA_SEQUENCE parameter format)
124124
* Return: empty
125125
126126
#### PUBLISH_SCA_SEQUENCE_STOP

0 commit comments

Comments
 (0)