Skip to content

Commit ad7b8e2

Browse files
ALF: Add SCA_WRITE_SEQUENCE RPC service
1 parent 733ee06 commit ad7b8e2

File tree

8 files changed

+139
-43
lines changed

8 files changed

+139
-43
lines changed

src/CommandLineUtilities/AliceLowlevelFrontend/AliceLowlevelFrontend.h

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ inline void setDataString(const std::string& string, DimObject& dimObject, bool
5252
dimObject.setData(buffer.data(), buffer.size());
5353
}
5454

55+
template <typename DimObject>
56+
inline void setDataBuffer(std::vector<char>& buffer, DimObject& dimObject)
57+
{
58+
dimObject.setData(buffer.data(), buffer.size());
59+
}
60+
5561
inline std::string successPrefix()
5662
{
5763
return "success:";
@@ -98,7 +104,7 @@ class DimRpcInfoWrapper
98104
{
99105
}
100106

101-
void setString(std::string string)
107+
void setString(const std::string& string)
102108
{
103109
setDataString(string, getDimRpcInfo());
104110
}
@@ -113,6 +119,15 @@ class DimRpcInfoWrapper
113119
return string;
114120
}
115121

122+
template <typename T>
123+
std::vector<T> getBlob()
124+
{
125+
auto data = reinterpret_cast<T*>(mRpcInfo->getData());
126+
auto size = mRpcInfo->getSize();
127+
std::vector<T> buffer(data, data + (size / sizeof(T)));
128+
return buffer;
129+
}
130+
116131
DimRpcInfo& getDimRpcInfo() const {
117132
return *mRpcInfo.get();
118133
}
@@ -171,8 +186,8 @@ class RegisterReadRpc: DimRpcInfoWrapper
171186

172187
uint32_t readRegister(uint64_t registerAddress)
173188
{
174-
setString((boost::format("%u") % registerAddress).str());
175-
return boost::lexical_cast<uint32_t>(stripPrefix(getString()));
189+
setString((boost::format("0x%x") % registerAddress).str());
190+
return convertHexString(stripPrefix(getString()));
176191
}
177192
};
178193

@@ -186,22 +201,7 @@ class RegisterWriteRpc: DimRpcInfoWrapper
186201

187202
void writeRegister(uint64_t registerAddress, uint32_t registerValue)
188203
{
189-
setString((boost::format("%u,%u") % registerAddress % registerValue).str());
190-
getString();
191-
}
192-
};
193-
194-
class RegisterWriteBlockRpc: DimRpcInfoWrapper
195-
{
196-
public:
197-
RegisterWriteBlockRpc(const std::string& serviceName)
198-
: DimRpcInfoWrapper(serviceName)
199-
{
200-
}
201-
202-
void writeRegister(uint64_t registerAddress, uint32_t registerValue)
203-
{
204-
setString((boost::format("%u,%u") % registerAddress % registerValue).str());
204+
setString((boost::format("0x%x,0x%x") % registerAddress % registerValue).str());
205205
getString();
206206
}
207207
};
@@ -266,6 +266,32 @@ class ScaGpioReadRpc: DimRpcInfoWrapper
266266
}
267267
};
268268

269+
class ScaWriteSequence: DimRpcInfoWrapper
270+
{
271+
public:
272+
ScaWriteSequence(const std::string& serviceName)
273+
: DimRpcInfoWrapper(serviceName)
274+
{
275+
}
276+
277+
std::string write(const std::string& buffer)
278+
{
279+
setString(buffer);
280+
return getString();
281+
}
282+
283+
std::string write(const std::vector<std::pair<uint32_t, uint32_t>>& sequence)
284+
{
285+
std::stringstream buffer;
286+
for (size_t i = 0; i < sequence.size(); ++i) {
287+
buffer << sequence[i].first << ',' << sequence[i].second;
288+
if (i + 1 < sequence.size()) {
289+
buffer << ';';
290+
}
291+
}
292+
return write(buffer.str());
293+
}
294+
};
269295

270296
class StringRpcServer: public DimRpc
271297
{

src/CommandLineUtilities/AliceLowlevelFrontend/ProgramAliceLowlevelFrontendClient.cxx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class ProgramAliceLowlevelFrontendClient: public Program
7171
Alf::ScaWriteRpc scaWriteRpc(names.scaWrite());
7272
Alf::ScaGpioReadRpc scaGpioReadRpc(names.scaGpioRead());
7373
Alf::ScaGpioWriteRpc scaGpioWriteRpc(names.scaGpioWrite());
74+
Alf::ScaWriteSequence scaWriteSequence(names.scaWriteSequence());
7475
Alf::PublishRpc publishRpc(names.publishStartCommandRpc());
7576

7677
publishRpc.publish("ALF/TEST/1", 1.0, {0x1fc});
@@ -83,21 +84,29 @@ class ProgramAliceLowlevelFrontendClient: public Program
8384
cout << " result: " << scaGpioReadRpc.read() << endl;
8485
}
8586

86-
// for (int i = 0; i < 10; ++i) {
87-
// auto transactionId = i + 0x10000;
88-
// cout << "SCA write" << endl;
89-
// cout << " result: " << scaWriteRpc.write(0xffff + transactionId, i) << endl;
90-
// cout << "SCA read" << endl;
91-
// cout << " result: " << scaReadRpc.read() << endl;
92-
// }
93-
94-
cout << "1k writes to 0x1fc..." << endl;
95-
for (int i = 0; i < 1000; ++i) {
96-
readRpc.readRegister(0x1fc);
87+
{
88+
cout << "1k writes to 0x1fc..." << endl;
89+
for (int i = 0; i < 1000; ++i) {
90+
readRpc.readRegister(0x1fc);
91+
}
92+
cout << "Done!" << endl;
93+
}
94+
95+
{
96+
size_t numInts = 4;
97+
cout << "Writing blob of " << numInts << " pairs of 32-bit ints..." << endl;
98+
std::vector<std::pair<uint32_t, uint32_t>> buffer(numInts);
99+
for (size_t i = 0; i < buffer.size(); ++i) {
100+
buffer[i] = {i * 2, i * 2 + 1};
101+
}
102+
103+
std::string result = scaWriteSequence.write(buffer);
104+
cout << "Done!" << endl;
105+
cout << "Got result: \n";
106+
cout << " " << result << '\n';
97107
}
98-
cout << "Done!" << endl;
99108

100-
while (!isSigInt())
109+
while (false)//!isSigInt())
101110
{
102111
cout << "-------------------------------------\n";
103112
cout << "Temperature = " << gTemperature << endl;

src/CommandLineUtilities/AliceLowlevelFrontend/ProgramAliceLowlevelFrontendServer.cxx

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
#include <mutex>
1313
#include <boost/algorithm/string.hpp>
1414
#include <boost/lexical_cast.hpp>
15+
#include <boost/tokenizer.hpp>
1516
#include <boost/variant.hpp>
1617
#include <InfoLogger/InfoLogger.hxx>
1718
#include <dim/dis.hxx>
1819
#include "AliceLowlevelFrontend.h"
1920
#include "AlfException.h"
2021
#include "folly/ProducerConsumerQueue.h"
22+
#include "Utilities/Util.h"
2123
#include "ReadoutCard/Parameters.h"
2224
#include "ReadoutCard/ChannelFactory.h"
2325
#include "Sca.h"
@@ -243,6 +245,8 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
243245
[&](auto parameter){return scaRead(parameter, bar2);});
244246
auto serverScaWrite = makeServer(names.scaWrite(),
245247
[&](auto parameter){return scaWrite(parameter, bar2);});
248+
auto serverScaWriteSequence = makeServer(names.scaWriteSequence(),
249+
[&](auto parameter){return scaBlobWrite(parameter, bar2);});
246250
auto serverScaGpioRead = makeServer(names.scaGpioRead(),
247251
[&](auto parameter){return scaGpioRead(parameter, bar2);});
248252
auto serverScaGpioWrite = makeServer(names.scaGpioWrite(),
@@ -287,14 +291,14 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
287291
/// RPC handler for register reads
288292
static std::string registerRead(const std::string& parameter, ChannelSharedPtr channel)
289293
{
290-
auto address = b::lexical_cast<uint64_t>(parameter);
294+
auto address = convertHexString(parameter);
291295
checkAddress(address);
292296

293297
uint32_t value = channel->readRegister(address / 4);
294298

295299
// getInfoLogger() << "READ " << Common::makeRegisterString(address, value) << endm;
296300

297-
return std::to_string(value);
301+
return (b::format("0x%x") % value).str();
298302
}
299303

300304
/// RPC handler for register writes
@@ -306,8 +310,8 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
306310
BOOST_THROW_EXCEPTION(AlfException() << ErrorInfo::Message("Write RPC call did not have 2 parameters"));
307311
}
308312

309-
auto address = b::lexical_cast<uint64_t>(params[0]);
310-
auto value = b::lexical_cast<uint32_t>(params[1]);
313+
auto address = convertHexString(params[0]);;
314+
auto value = convertHexString(params[1]);;
311315
checkAddress(address);
312316

313317
// getInfoLogger() << "WRITE " << Common::makeRegisterString(address, value) << endm;
@@ -354,7 +358,7 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
354358
{
355359
getInfoLogger() << "SCA_READ" << endm;
356360
auto result = Sca(*bar2, bar2->getCardType()).read();
357-
return (b::format("0x%x,0x%x") % result.data % result.command).str();
361+
return (b::format("0x%x,0x%x") % result.command % result.data).str();
358362
}
359363

360364
static std::string scaWrite(const std::string& parameter, ChannelSharedPtr bar2)
@@ -382,6 +386,37 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
382386
return "";
383387
}
384388

389+
static std::string scaBlobWrite(const std::string& parameter, ChannelSharedPtr bar2)
390+
{
391+
getInfoLogger() << "SCA_BLOB_WRITE size=" << parameter.size() << " bytes" << endm;
392+
393+
// We first split on ; to get the pairs of SCA command and SCA data
394+
// Since this can be an enormous list of pairs, we walk through it using the tokenizer
395+
auto commandDataPairs = split(parameter, ";");
396+
using tokenizer = boost::tokenizer<boost::char_separator<char>>;
397+
boost::char_separator<char> sep(";", "", boost::drop_empty_tokens); // Drop ";" delimiters, keep none
398+
std::stringstream resultBuffer;
399+
auto sca = Sca(*bar2, bar2->getCardType());
400+
for (std::string token : tokenizer(parameter, sep)) {
401+
// Walk through the tokens, these should be the pairs. The pairs are comma-separated, so we split those.
402+
std::vector<std::string> pair = split(token, ",");
403+
if (pair.size() != 2) {
404+
BOOST_THROW_EXCEPTION(AlfException() << ErrorInfo::Message("SCA command-data pair not formatted correctly"));
405+
}
406+
auto command = convertHexString(pair[0]);
407+
auto data = convertHexString(pair[1]);
408+
sca.write(command, data);
409+
auto result = sca.read();
410+
getInfoLogger() << (b::format("cmd=0x%x data=0x%x result=0x%x") % command % data % result.data).str() << endm;
411+
resultBuffer << std::hex << result.data << ';';
412+
}
413+
auto result = resultBuffer.str();
414+
if (result.size() > 0) {
415+
result.pop_back(); // Pop the last ';'
416+
}
417+
return result;
418+
}
419+
385420
int mSerialNumber = 0;
386421
CommandQueue mCommandQueue;
387422
double mTemperature = 40;

src/CommandLineUtilities/AliceLowlevelFrontend/README.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ Some of the services are RPC calls.
1717
* When the argument must contain multiple values, they must be comma-separated.
1818
* The return string will contain an 8-byte prefix indicating success or failure "success:" or "failure:",
1919
optionally followed by a return value or error message.
20-
* Numbers and addresses are all in base-10.
20+
* Numbers and addresses are all in base-16. A '0x' prefix for numbers is accepted, but unnecessary for the parameters.
21+
The '0x' prefix is omitted for return values.
2122

22-
For example: a register write call could have the argument string "504,42" meaning write value 42 to address 504.
23+
For example: a register write call could have the argument string "0x504,0x4" meaning write value 0x42 to address 0x4.
2324
The return string could be "success:" or "failure:Address out of range".
2425

2526
## Service description
@@ -41,15 +42,38 @@ A basic read from the SCA
4142
* Service type: RPC call
4243
* Service name: SCA_READ
4344
* Parameters: empty
44-
* Return: SCA data, SCA command
45+
* Return: SCA command, SCA data
4546

4647
#### SCA write
4748
A basic write to the SCA
4849
* Service type: RPC call
4950
* Service name: SCA_WRITE
50-
* Parameters: SCA data, SCA command
51+
* Parameters: SCA command, SCA data
5152
* Return: empty
5253

54+
#### SCA write sequence
55+
Write a sequence of values to the SCA
56+
* Service type: RPC call
57+
* Service name: SCA_SEQUENCE_WRITE
58+
* Parameters: A sequence of pairs of SCA command and data. The pairs are separated by semicolon, the command and data by
59+
comma:
60+
~~~
61+
[command 0],[data 0];[command 1],[data 1]; ...
62+
~~~
63+
For example:
64+
~~~
65+
10,11;20,21;30,31
66+
~~~
67+
* Return: A sequence of SCA read return values corresponding to the commands from the input sequence:
68+
~~~
69+
[value 0];[value 1]; ...
70+
~~~
71+
For example:
72+
~~~
73+
42;123;555
74+
~~~
75+
76+
5377
#### SCA GPIO read
5478
Read the GPIO pins
5579
* Service type: RPC call

src/CommandLineUtilities/AliceLowlevelFrontend/Sca.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ auto Sca::read() -> ReadResult
7171
auto command = barRead(Registers::READ_COMMAND);
7272
// printf("Sca::read DATA=0x%x CH=0x%x TR=0x%x CMD=0x%x\n", data, command >> 24, (command >> 16) & 0xff, command & 0xff);
7373
checkError(command);
74-
return { data, command };
74+
return { command, data };
7575
}
7676

7777
void Sca::checkError(uint32_t command)

src/CommandLineUtilities/AliceLowlevelFrontend/Sca.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class Sca
2828

2929
struct ReadResult
3030
{
31-
uint32_t data;
3231
uint32_t command;
32+
uint32_t data;
3333
};
3434

3535
Sca(RegisterReadWriteInterface& bar2, CardType::type cardType);

src/CommandLineUtilities/AliceLowlevelFrontend/ServiceNames.cxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ DEFSERVICENAME(publishStartCommandRpc, "PUBLISH_SERVICE")
2323
DEFSERVICENAME(publishStopCommandRpc, "PUBLISH_SERVICE_STOP")
2424
DEFSERVICENAME(scaRead, "SCA_READ")
2525
DEFSERVICENAME(scaWrite, "SCA_WRITE")
26+
DEFSERVICENAME(scaWriteSequence, "SCA_WRITE_SEQUENCE")
2627
DEFSERVICENAME(scaGpioWrite, "SCA_GPIO_WRITE")
2728
DEFSERVICENAME(scaGpioRead, "SCA_GPIO_READ")
2829
DEFSERVICENAME(temperature, "TEMPERATURE")

src/CommandLineUtilities/AliceLowlevelFrontend/ServiceNames.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ServiceNames
2626
std::string publishStartCommandRpc() const;
2727
std::string publishStopCommandRpc() const;
2828
std::string scaWrite() const;
29+
std::string scaWriteSequence() const;
2930
std::string scaRead() const;
3031
std::string scaGpioWrite() const;
3132
std::string scaGpioRead() const;

0 commit comments

Comments
 (0)