CbcInterface.cc 32.9 KB
Newer Older
npierre's avatar
npierre committed
1
2
/*

3
4
5
6
7
8
        FileName :                     CbcInterface.cc
        Content :                      User Interface to the Cbcs
        Programmer :                   Lorenzo BIDEGAIN, Nicolas PIERRE, Georg AUZINGER
        Version :                      1.0
        Date of creation :             10/07/14
        Support :                      mail to : lorenzo.bidegain@gmail.com, nico.pierre@icloud.com
npierre's avatar
npierre committed
9

10
 */
11

12
#include "CbcInterface.h"
13
#include "../Utils/ChannelGroupHandler.h"
Fabio Ravera's avatar
Fabio Ravera committed
14
#include "../Utils/ConsoleColor.h"
15
#include "../Utils/Container.h"
16
#include <bitset>
Lorenzo Bidegain's avatar
Lorenzo Bidegain committed
17
18
19

#define DEV_FLAG 0

20
using namespace Ph2_HwDescription;
21

22
23
namespace Ph2_HwInterface
{
Fabio Ravera's avatar
Fabio Ravera committed
24
CbcInterface::CbcInterface(const BeBoardFWMap& pBoardMap) : ReadoutChipInterface(pBoardMap) { fActiveChannels.reset(); }
25

Fabio Ravera's avatar
Fabio Ravera committed
26
CbcInterface::~CbcInterface() {}
27

Fabio Ravera's avatar
Fabio Ravera committed
28
29
30
31
32
33
bool CbcInterface::ConfigureChip(Chip* pCbc, bool pVerifLoop, uint32_t pBlockSize)
{
    // std::cout << __PRETTY_FUNCTION__ << __LINE__ << std::endl;
    // std::cout << __PRETTY_FUNCTION__ << "!!!!!!!!!!!!!!!!" << std::endl;
    // first, identify the correct BeBoardFWInterface
    setBoard(pCbc->getBeBoardId());
34

Fabio Ravera's avatar
Fabio Ravera committed
35
36
    // vector to encode all the registers into
    std::vector<uint32_t> cVec;
37

Fabio Ravera's avatar
Fabio Ravera committed
38
    // Deal with the ChipRegItems and encode them
39

Fabio Ravera's avatar
Fabio Ravera committed
40
    ChipRegMap cCbcRegMap = pCbc->getRegMap();
41

Fabio Ravera's avatar
Fabio Ravera committed
42
43
44
45
46
47
48
49
50
51
    for(auto& cRegItem: cCbcRegMap)
    {
        // this is to protect from readback errors during Configure as the BandgapFuse and ChipIDFuse registers should
        // be e-fused in the CBC3
        if(cRegItem.first != "BandgapFuse" || cRegItem.first.find("ChipIDFuse") == std::string::npos)
        {
            // if( cRegItem.second.fPage == 0 )
            // LOG (DEBUG) << BOLDBLUE << "Writing 0x" << std::hex << +cRegItem.second.fValue << std::dec << " to " <<
            // cRegItem.first <<  " : register address 0x" << std::hex << +cRegItem.second.fAddress << std::dec << " on
            // page " << +cRegItem.second.fPage <<  RESET;
52
            fBoardFW->EncodeReg(cRegItem.second, pCbc->getHybridId(), pCbc->getId(), cVec, pVerifLoop, true);
Fabio Ravera's avatar
Fabio Ravera committed
53
54
55
56
57
#ifdef COUNT_FLAG
            fRegisterCount++;
#endif
        }
    }
58

Fabio Ravera's avatar
Fabio Ravera committed
59
60
61
62
63
64
65
    // write the registers, the answer will be in the same cVec
    // the number of times the write operation has been attempted is given by cWriteAttempts
    uint8_t cWriteAttempts = 0;
    bool    cSuccess       = fBoardFW->WriteChipBlockReg(cVec, cWriteAttempts, pVerifLoop);
#ifdef COUNT_FLAG
    fTransactionCount++;
#endif
66

Fabio Ravera's avatar
Fabio Ravera committed
67
68
    return cSuccess;
}
69

Fabio Ravera's avatar
Fabio Ravera committed
70
bool CbcInterface::enableInjection(ReadoutChip* pChip, bool inject, bool pVerifLoop) { return this->WriteChipReg(pChip, "TestPulse", (int)inject, pVerifLoop); }
71

Fabio Ravera's avatar
Fabio Ravera committed
72
bool CbcInterface::setInjectionAmplitude(ReadoutChip* pChip, uint8_t injectionAmplitude, bool pVerifLoop) { return this->WriteChipReg(pChip, "TestPulsePotNodeSel", injectionAmplitude, pVerifLoop); }
73

Fabio Ravera's avatar
Fabio Ravera committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
bool CbcInterface::setInjectionSchema(ReadoutChip* pCbc, const ChannelGroupBase* group, bool pVerifLoop)
{
    // std::bitset<NCHANNELS> baseInjectionChannel (std::string(CBC_CHANNEL_GROUP_BITSET));
    // uint8_t channelGroup = 0;
    // for(; channelGroup<=8; ++channelGroup)
    // {
    //     if(static_cast<const ChannelGroup<NCHANNELS>*>(group)->getBitset() == baseInjectionChannel)
    //     {
    //         break;
    //     }
    //     baseInjectionChannel = baseInjectionChannel<<2;
    // }
    // if(channelGroup == 8)
    //     throw Exception( "bool CbcInterface::setInjectionSchema (ReadoutChip* pCbc, const ChannelGroupBase *group,
    //     bool pVerifLoop): CBC is not able to inject the channel pattern" );

    // uint8_t groupLookupTable[8] = {0x0, 0x4, 0x2, 0x6, 0x1, 0x5, 0x3, 0x7};
    // return this->WriteChipReg ( pCbc, "TestPulseGroup", groupLookupTable[channelGroup], pVerifLoop );

    std::bitset<NCHANNELS> cBitset = std::bitset<NCHANNELS>(static_cast<const ChannelGroup<NCHANNELS>*>(group)->getBitset());
    if(cBitset.count() == 0) // no mask set... so do nothing
        return true;
    // LOG (DEBUG) << BOLDBLUE << "Setting injection scheme for " << std::bitset<NCHANNELS>(cBitset) << RESET;
    uint16_t cFirstHit;
    for(cFirstHit = 0; cFirstHit < NCHANNELS; cFirstHit++)
99
    {
Fabio Ravera's avatar
Fabio Ravera committed
100
        if(cBitset[cFirstHit] != 0) break;
101
    }
Fabio Ravera's avatar
Fabio Ravera committed
102
103
104
105
106
107
108
109
110
    uint8_t cGroupId = std::floor((cFirstHit % 16) / 2);
    // LOG (DEBUG) << BOLDBLUE << "First unmasked channel in position " << +cFirstHit << " --- i.e. in TP group " <<
    // +cGroupId << RESET;
    if(cGroupId > 7)
        throw Exception("bool CbcInterface::setInjectionSchema (ReadoutChip* pCbc, const ChannelGroupBase *group, bool "
                        "pVerifLoop): CBC is not able to inject the channel pattern");
    // write register which selects group
    return this->WriteChipReg(pCbc, "TestPulseGroup", cGroupId, pVerifLoop);
}
111

Fabio Ravera's avatar
Fabio Ravera committed
112
113
114
115
bool CbcInterface::maskChannelsGroup(ReadoutChip* pCbc, const ChannelGroupBase* group, bool pVerifLoop)
{
    const ChannelGroup<NCHANNELS>* originalMask = static_cast<const ChannelGroup<NCHANNELS>*>(pCbc->getChipOriginalMask());
    const ChannelGroup<NCHANNELS>* groupToMask  = static_cast<const ChannelGroup<NCHANNELS>*>(group);
116
    LOG(DEBUG) << BOLDBLUE << "\t... Applying mask to CBC" << +pCbc->getId() << " with " << group->getNumberOfEnabledChannels()
Fabio Ravera's avatar
Fabio Ravera committed
117
118
119
120
121
122
123
124
               << " enabled channels\t... mask : " << std::bitset<NCHANNELS>(groupToMask->getBitset()) << RESET;

    fActiveChannels = groupToMask->getBitset();
    // auto  a = static_cast<const ChannelGroup<NCHANNELS,1>*>(groupToMask);
    std::vector<std::pair<std::string, uint16_t>> cRegVec;
    cRegVec.clear();
    std::bitset<NCHANNELS> tmpBit(255);
    for(uint8_t maskGroup = 0; maskGroup < 32; ++maskGroup)
125
    {
Fabio Ravera's avatar
Fabio Ravera committed
126
127
128
        uint16_t cValue = (uint16_t)((originalMask->getBitset() & fActiveChannels) >> (maskGroup << 3) & tmpBit).to_ulong();
        LOG(DEBUG) << BOLDBLUE << "\t...Group" << +maskGroup << " : " << std::bitset<8>(cValue) << RESET;
        cRegVec.push_back(make_pair(fChannelMaskMapCBC3[maskGroup], (uint16_t)((originalMask->getBitset() & fActiveChannels) >> (maskGroup << 3) & tmpBit).to_ulong()));
129
    }
Fabio Ravera's avatar
Fabio Ravera committed
130
131
    return WriteChipMultReg(pCbc, cRegVec, pVerifLoop);
}
132

Fabio Ravera's avatar
Fabio Ravera committed
133
134
135
bool CbcInterface::maskChannelsAndSetInjectionSchema(ReadoutChip* pChip, const ChannelGroupBase* group, bool mask, bool inject, bool pVerifLoop)
{
    bool success = true;
Fabio Ravera's avatar
Fabio Ravera committed
136
137
    if(mask) success &= maskChannelsGroup(pChip, group, pVerifLoop);
    if(inject) success &= setInjectionSchema(pChip, group, pVerifLoop);
Fabio Ravera's avatar
Fabio Ravera committed
138
139
    return success;
}
140

Fabio Ravera's avatar
Fabio Ravera committed
141
142
143
144
145
bool CbcInterface::ConfigureChipOriginalMask(ReadoutChip* pCbc, bool pVerifLoop, uint32_t pBlockSize)
{
    ChannelGroup<NCHANNELS> allChannelEnabledGroup;
    return CbcInterface::maskChannelsGroup(pCbc, &allChannelEnabledGroup, pVerifLoop);
}
146

Fabio Ravera's avatar
Fabio Ravera committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
std::vector<uint8_t> CbcInterface::createHitListFromStubs(uint8_t pSeed, bool pSeedLayer)
{
    std::vector<uint8_t> cChannelList(0);
    uint32_t             cSeedStrip = std::floor(pSeed / 2.0); // counting from 1
    LOG(DEBUG) << BOLDMAGENTA << "Seed of " << +pSeed << " means first hit is in strip " << +cSeedStrip << RESET;
    size_t cNumberOfChannels = 1 + (pSeed % 2 != 0);
    for(size_t cIndex = 0; cIndex < cNumberOfChannels; cIndex++)
    {
        uint32_t cSeedChannel = 2 * (cSeedStrip - 1) + !pSeedLayer + 2 * cIndex;
        LOG(DEBUG) << BOLDMAGENTA << ".. need to unmask channel " << +cSeedChannel << RESET;
        cChannelList.push_back(static_cast<uint32_t>(cSeedChannel));
    }
    return cChannelList;
}
std::vector<uint8_t> CbcInterface::stubInjectionPattern(uint8_t pStubAddress, int pStubBend, bool pLayerSwap)
{
    LOG(DEBUG) << BOLDBLUE << "Injecting... stub in position " << +pStubAddress << " [half strips] with a bend of " << pStubBend << " [half strips]." << RESET;
    std::vector<uint8_t> cSeedHits = createHitListFromStubs(pStubAddress, !pLayerSwap);
    // correlation layer
    uint8_t              cCorrelated     = pStubAddress + pStubBend; // start counting strips from 0
    std::vector<uint8_t> cCorrelatedHits = createHitListFromStubs(cCorrelated, pLayerSwap);
    // merge two lists and unmask
    cSeedHits.insert(cSeedHits.end(), cCorrelatedHits.begin(), cCorrelatedHits.end());
    return cSeedHits;
}
std::vector<uint8_t> CbcInterface::stubInjectionPattern(ReadoutChip* pChip, uint8_t pStubAddress, int pStubBend)
{
    bool cLayerSwap = (this->ReadChipReg(pChip, "LayerSwap") == 1);
    return stubInjectionPattern(pStubAddress, pStubBend, cLayerSwap);
}
bool CbcInterface::injectStubs(ReadoutChip* pCbc, std::vector<uint8_t> pStubAddresses, std::vector<int> pStubBends, bool pUseNoise)
{
    setBoard(pCbc->getBeBoardId());
    if(pUseNoise)
    {
        uint16_t cVcth = 1023;
183
        // LOG (DEBUG) << BOLDBLUE << "Injecting stubs in CBC" << +pCbc->getId() << RESET;
Fabio Ravera's avatar
Fabio Ravera committed
184
185
186
187
188
189
190
191
        // LOG (DEBUG) << BOLDBLUE << "Starting by lowering threshold on this CBC and masking all channels." << RESET;
        this->WriteChipReg(pCbc, "VCth", cVcth);
    }
    ChannelGroup<NCHANNELS, 1> cChannelMask;
    cChannelMask.disableAllChannels();
    for(size_t cIndex = 0; cIndex < pStubAddresses.size(); cIndex += 1)
    {
        std::vector<uint8_t> cPattern = this->stubInjectionPattern(pCbc, pStubAddresses[cIndex], pStubBends[cIndex]);
Fabio Ravera's avatar
Fabio Ravera committed
192
        for(auto cChannel: cPattern) cChannelMask.enableChannel(cChannel);
Fabio Ravera's avatar
Fabio Ravera committed
193
194
195
196
197
198
199
    }
    if(!pUseNoise)
    {
        uint16_t               cFirstHit = 0;
        std::bitset<NCHANNELS> cBitset   = std::bitset<NCHANNELS>(cChannelMask.getBitset());
        LOG(DEBUG) << BOLDMAGENTA << "Bitset for this mask is " << cBitset << RESET;
        for(cFirstHit = 0; cFirstHit < NCHANNELS; cFirstHit++)
200
        {
Fabio Ravera's avatar
Fabio Ravera committed
201
            if(cBitset[cFirstHit] != 0) break;
202
        }
Fabio Ravera's avatar
Fabio Ravera committed
203
204
        uint8_t cGroupId = std::floor((cFirstHit % 16) / 2);
        LOG(INFO) << BOLDBLUE << "First unmasked channel in position " << +cFirstHit << " --- i.e. in TP group " << +cGroupId << RESET;
205
        if(cGroupId > 7)
Fabio Ravera's avatar
Fabio Ravera committed
206
207
            throw Exception("bool CbcInterface::setInjectionSchema (ReadoutChip* pCbc, const ChannelGroupBase *group, "
                            "bool pVerifLoop): CBC is not able to inject the channel pattern");
208
        // write register which selects group
Fabio Ravera's avatar
Fabio Ravera committed
209
        this->WriteChipReg(pCbc, "TestPulseGroup", cGroupId);
210
    }
Fabio Ravera's avatar
Fabio Ravera committed
211
212
213
214
215
216
217
    return this->maskChannelsGroup(pCbc, &cChannelMask);
}
std::vector<uint8_t> CbcInterface::readLUT(ReadoutChip* pCbc)
{
    setBoard(pCbc->getBeBoardId());
    std::vector<uint8_t> cBendCodes(30, 0); // bend registers are 0 -- 14. Each register encodes 2 codes
    for(size_t cIndex = 0; cIndex < 15; cIndex += 1)
Fabio Ravera's avatar
Fabio Ravera committed
218
    {
Fabio Ravera's avatar
Fabio Ravera committed
219
220
221
222
223
224
225
226
        const size_t cLength = (cIndex < 10) ? 5 : 6;
        char         cBuffer[20];
        sprintf(cBuffer, "Bend%d", static_cast<int>(cIndex));
        std::string cRegName(cBuffer, cLength);
        LOG(DEBUG) << BOLDBLUE << "Reading bend register " << cRegName << RESET;
        uint16_t cValue            = this->ReadChipReg(pCbc, cRegName);
        cBendCodes[cIndex * 2]     = (cValue & 0x0F);
        cBendCodes[cIndex * 2 + 1] = (cValue & 0xF0) >> 4;
Fabio Ravera's avatar
Fabio Ravera committed
227
    }
Fabio Ravera's avatar
Fabio Ravera committed
228
229
    return cBendCodes;
}
Fabio Ravera's avatar
Fabio Ravera committed
230

Fabio Ravera's avatar
Fabio Ravera committed
231
232
233
234
235
236
237
238
239
uint16_t CbcInterface::readErrorRegister(ReadoutChip* pCbc)
{
    // read I2c register with error flags
    ChipRegItem cRegItem;
    cRegItem.fPage    = 0x01;
    cRegItem.fAddress = 0x1D;

    setBoard(pCbc->getBeBoardId());
    std::vector<uint32_t> cVecReq;
240
    fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
241
242
243
244
245
246
247
248
249
250
251
252
    fBoardFW->ReadChipBlockReg(cVecReq);
    // bools to find the values of failed and read
    bool    cFailed = false;
    bool    cRead;
    uint8_t cChipId;
    fBoardFW->DecodeReg(cRegItem, cChipId, cVecReq[0], cRead, cFailed);
    std::pair<bool, uint16_t> cReadBack = std::make_pair(!cFailed, cRegItem.fValue);
    if(cReadBack.first)
        return cReadBack.second;
    else
        return 0xFF;
}
253

Fabio Ravera's avatar
Fabio Ravera committed
254
255
256
257
258
259
260
261
262
263
264
265
bool CbcInterface::selectLogicMode(ReadoutChip* pCbc, std::string pModeSelect, bool pForHits, bool pForStubs, bool pVerifLoop)
{
    uint8_t pMode;
    if(pModeSelect == "Sampled")
        pMode = 0;
    else if(pModeSelect == "OR")
        pMode = 1;
    else if(pModeSelect == "HIP")
        pMode = 2;
    else if(pModeSelect == "Latched")
        pMode = 3;
    else
266
    {
Fabio Ravera's avatar
Fabio Ravera committed
267
268
        LOG(INFO) << BOLDYELLOW << "Invalid mode selected! Valid modes are Sampled/OR/Latched/HIP" << RESET;
        return false;
269
    }
Fabio Ravera's avatar
Fabio Ravera committed
270
271
272
273
274
275
276
277
    std::vector<std::pair<std::string, uint16_t>> cRegVec;
    setBoard(pCbc->getBeBoardId());
    std::string cRegName       = "Pipe&StubInpSel&Ptwidth";
    uint16_t    cOriginalValue = this->ReadChipReg(pCbc, cRegName);
    uint16_t    cMask          = 0xFF - ((3 * pForHits << 6) | (3 * pForStubs << 4));
    uint16_t    cRegValue      = (cOriginalValue & cMask) | (pMode * pForHits << 6) | (pMode * pForStubs << 4);
    // LOG (DEBUG) << BOLDBLUE << "Original register value : 0x" << std::hex << cOriginalValue << std::dec << "\t logic
    // register set to 0x" << std::hex << +cRegValue << std::dec << " to select " << pModeSelect << " mode on CBC" <<
278
    // +pCbc->getId() << RESET;
Fabio Ravera's avatar
Fabio Ravera committed
279
280
281
282
283
    return WriteChipSingleReg(pCbc, cRegName, cRegValue, pVerifLoop);
    // WriteChipSingleReg
    // uint8_t cMask = (uint8_t)(~(((3*pForHits) << 6) | ((3*pForStubs) << 4)));
    // uint8_t cValue = (((pMode*pForHits) << 6) | ((pMode*pForStubs) << 4)) | (cOriginalValue & cMask);
    // LOG (DEBUG) << BOLDBLUE << "Settinng logic selection register to 0x" << std::hex << +cValue << std::dec << " to
284
    // select " << pModeSelect << " mode on CBC" << +pCbc->getId() << RESET; cRegVec.emplace_back (cRegName, cValue);
Fabio Ravera's avatar
Fabio Ravera committed
285
286
    // return WriteChipMultReg (pCbc, cRegVec, pVerifLoop);
}
Georg Auzinger's avatar
Georg Auzinger committed
287

Fabio Ravera's avatar
Fabio Ravera committed
288
289
290
291
292
293
bool CbcInterface::enableHipSuppression(ReadoutChip* pCbc, bool pForHits, bool pForStubs, uint8_t pClocks, bool pVerifLoop)
{
    std::vector<std::pair<std::string, uint16_t>> cRegVec;
    setBoard(pCbc->getBeBoardId());
    // configure logic mode
    if(!this->selectLogicMode(pCbc, "HIP", pForHits, pForStubs, pVerifLoop))
294
    {
Fabio Ravera's avatar
Fabio Ravera committed
295
296
        LOG(INFO) << BOLDYELLOW << "Could not select HIP mode..." << RESET;
        return false;
297
    }
Fabio Ravera's avatar
Fabio Ravera committed
298
299
300
301
302
303
304
305
    // configure hip logic
    std::string cRegName       = "HIP&TestMode";
    uint8_t     cOriginalValue = this->ReadChipReg(pCbc, cRegName);
    uint8_t     cMask          = 0x0F;
    bool        cEnableHips    = true;
    uint8_t     cMaxClocks     = 7;
    uint8_t     cValue         = (((pClocks << 5) & (cMaxClocks << 5)) & (!cEnableHips << 4)) | (cOriginalValue & cMask);
    // LOG (DEBUG) << BOLDBLUE << "Settinng HIP configuration register to 0x" << std::hex << +cValue << std::dec << " to
306
    // enable max. " << +pClocks << " clocks on CBC" << +pCbc->getId() << RESET;
Fabio Ravera's avatar
Fabio Ravera committed
307
308
309
310
311
312
313
314
    cRegVec.emplace_back(cRegName, cValue);
    return WriteChipMultReg(pCbc, cRegVec, pVerifLoop);
}

bool CbcInterface::MaskAllChannels(ReadoutChip* pCbc, bool mask, bool pVerifLoop)
{
    ChannelGroup<NCHANNELS, 1> cChannelMask;
    if(mask)
315
        cChannelMask.disableAllChannels();
Fabio Ravera's avatar
Fabio Ravera committed
316
317
318
319
320
321
322
323
324
325
326
    else
        cChannelMask.enableAllChannels();
    // LOG (DEBUG)  << BOLDBLUE << "Mask to be set is " << std::bitset<254>( cChannelMask.getBitset() ) << RESET;
    return this->maskChannelsGroup(pCbc, &cChannelMask, pVerifLoop);
}

bool CbcInterface::WriteChipReg(Chip* pCbc, const std::string& dacName, uint16_t dacValue, bool pVerifLoop)
{
    if(dacName == "VCth")
    {
        if(pCbc->getFrontEndType() == FrontEndType::CBC3)
327
        {
Fabio Ravera's avatar
Fabio Ravera committed
328
329
330
            if(dacValue > 1023)
                LOG(ERROR) << "Error, Threshold for CBC3 can only be 10 bit max (1023)!";
            else
331
            {
Fabio Ravera's avatar
Fabio Ravera committed
332
333
334
335
336
337
338
                std::vector<std::pair<std::string, uint16_t>> cRegVec;
                // VCth1 holds bits 0-7 and VCth2 holds 8-9
                uint16_t cVCth1 = dacValue & 0x00FF;
                uint16_t cVCth2 = (dacValue & 0x0300) >> 8;
                cRegVec.emplace_back("VCth1", cVCth1);
                cRegVec.emplace_back("VCth2", cVCth2);
                return WriteChipMultReg(pCbc, cRegVec, pVerifLoop);
339
            }
340
        }
Fabio Ravera's avatar
Fabio Ravera committed
341
342
        else
            LOG(ERROR) << "Not a valid chip type!";
343
    }
Fabio Ravera's avatar
Fabio Ravera committed
344
    else if(dacName == "TriggerLatency")
345
    {
Fabio Ravera's avatar
Fabio Ravera committed
346
        if(pCbc->getFrontEndType() == FrontEndType::CBC3)
347
        {
Fabio Ravera's avatar
Fabio Ravera committed
348
349
350
            if(dacValue > 511)
                LOG(ERROR) << "Error, Threshold for CBC3 can only be 10 bit max (1023)!";
            else
351
            {
Fabio Ravera's avatar
Fabio Ravera committed
352
353
354
355
356
357
                std::vector<std::pair<std::string, uint16_t>> cRegVec;
                // TriggerLatency1 holds bits 0-7 and FeCtrl&TrgLate2 holds 8
                uint16_t cLat1 = dacValue & 0x00FF;
                uint16_t cLat2 = (pCbc->getReg("FeCtrl&TrgLat2") & 0xFE) | ((dacValue & 0x0100) >> 8);
                cRegVec.emplace_back("TriggerLatency1", cLat1);
                cRegVec.emplace_back("FeCtrl&TrgLat2", cLat2);
358
                LOG(DEBUG) << BOLDBLUE << "Setting latency on " << +pCbc->getId() << " to " << +dacValue << " 0x" << std::hex << +cLat1 << std::dec << " --- 0x" << std::hex << +cLat2 << std::dec
Fabio Ravera's avatar
Fabio Ravera committed
359
360
                           << RESET;
                return WriteChipMultReg(pCbc, cRegVec, pVerifLoop);
361
            }
362
        }
363
        else
Fabio Ravera's avatar
Fabio Ravera committed
364
            LOG(ERROR) << "Not a valid chip type!";
365
    }
Fabio Ravera's avatar
Fabio Ravera committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
    else if(dacName == "TestPulseDelay")
    {
        uint8_t cValue = pCbc->getReg("TestPulseDel&ChanGroup");
        uint8_t cGroup = cValue & 0x07;
        // groupId is reversed in this register
        std::bitset<5> cDelay  = dacValue;
        std::string    cSelect = cDelay.to_string();
        std::reverse(cSelect.begin(), cSelect.end());
        std::bitset<5> cTestPulseDelay(cSelect);
        uint8_t        cRegValue = (cGroup | (static_cast<uint8_t>(cTestPulseDelay.to_ulong()) << 3));
        LOG(DEBUG) << BOLDBLUE << "Setting test pulse delay for goup [rev.] " << std::bitset<3>(cGroup) << " to " << +dacValue << " --  register to  0x" << std::bitset<8>(+cRegValue) << std::dec
                   << RESET;
        return WriteChipSingleReg(pCbc, "TestPulseDel&ChanGroup", cRegValue, pVerifLoop);
    }
    else if(dacName == "TestPulseGroup")
    {
        uint8_t cValue = pCbc->getReg("TestPulseDel&ChanGroup");
        uint8_t cDelay = cValue & 0xF8;
        // groupId is reversed in this register
        std::bitset<3> cGroup  = dacValue;
        std::string    cSelect = cGroup.to_string();
        std::reverse(cSelect.begin(), cSelect.end());
        std::bitset<3> cTestPulseGroup(cSelect);
        uint8_t        cRegValue = (cDelay | (static_cast<uint8_t>(cTestPulseGroup.to_ulong())));
390
        LOG(DEBUG) << BOLDBLUE << "Setting test pulse register on CBC" << +pCbc->getId() << " to select group " << +dacValue << " --  register to  0x" << std::bitset<8>(+cRegValue) << std::dec
Fabio Ravera's avatar
Fabio Ravera committed
391
392
393
394
395
396
397
                   << RESET;
        return WriteChipSingleReg(pCbc, "TestPulseDel&ChanGroup", cRegValue, pVerifLoop);
    }
    else if(dacName == "AmuxOutput")
    {
        uint8_t cValue    = pCbc->getReg("MiscTestPulseCtrl&AnalogMux");
        uint8_t cRegValue = (cValue & 0xE0) | dacValue;
398
        LOG(DEBUG) << BOLDBLUE << "Setting AmuxOutput on Chip" << +pCbc->getId() << " to " << +dacValue << " - register set to : 0x" << std::hex << +cRegValue << std::dec << RESET;
Fabio Ravera's avatar
Fabio Ravera committed
399
400
401
402
403
404
405
406
407
408
409
410
        return WriteChipSingleReg(pCbc, "MiscTestPulseCtrl&AnalogMux", cRegValue, pVerifLoop);
    }
    else if(dacName == "TestPulse")
    {
        uint8_t cValue    = pCbc->getReg("MiscTestPulseCtrl&AnalogMux");
        uint8_t cRegValue = (cValue & 0xBF) | (dacValue << 6);
        return WriteChipSingleReg(pCbc, "MiscTestPulseCtrl&AnalogMux", cRegValue, pVerifLoop);
    }
    else if(dacName == "HitOr")
    {
        uint8_t cValue    = pCbc->getReg("40MhzClk&Or254");
        uint8_t cRegValue = (cValue & 0xBf) | (dacValue << 6);
411
        LOG(DEBUG) << BOLDBLUE << "Setting HITOr on Chip" << +pCbc->getId() << " from 0x" << std::hex << +cValue << std::dec << " to " << +dacValue << " - register set to : 0x" << std::hex
Fabio Ravera's avatar
Fabio Ravera committed
412
413
414
415
                   << +cRegValue << std::dec << RESET;
        return WriteChipSingleReg(pCbc, "40MhzClk&Or254", cRegValue, pVerifLoop);
    }
    else if(dacName == "DLL")
416
    {
Fabio Ravera's avatar
Fabio Ravera committed
417
418
419
420
421
422
423
        uint8_t cOriginalValue = pCbc->getReg("40MhzClk&Or254");
        // dll is reversed in this register
        std::bitset<5> cDelay  = dacValue;
        std::string    cSelect = cDelay.to_string();
        std::reverse(cSelect.begin(), cSelect.end());
        std::bitset<5> cClockDelay(cSelect);
        uint8_t        cNewRegValue = ((cOriginalValue & 0xE0) | static_cast<uint8_t>(cClockDelay.to_ulong()));
Fabio Ravera's avatar
Fabio Ravera committed
424
        LOG(DEBUG) << BOLDBLUE << "Setting clock delay on Chip" << +pCbc->getId() << " to " << std::bitset<5>(+dacValue) << " - register set to : 0x" << std::hex << +cNewRegValue << std::dec << RESET;
Fabio Ravera's avatar
Fabio Ravera committed
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
        return WriteChipSingleReg(pCbc, "40MhzClk&Or254", cNewRegValue, pVerifLoop);
    }
    else if(dacName == "PtCut")
    {
        uint8_t cValue    = pCbc->getReg("Pipe&StubInpSel&Ptwidth");
        uint8_t cRegValue = (cValue & 0xF0) | dacValue;
        return WriteChipSingleReg(pCbc, "Pipe&StubInpSel&Ptwidth", cRegValue, pVerifLoop);
    }
    else if(dacName == "EnableSLVS")
    {
        uint8_t cValue    = pCbc->getReg("HIP&TestMode");
        uint8_t cRegValue = (cValue & 0xFE) | !dacValue;
        if(dacValue == 1)
            LOG(DEBUG) << BOLDBLUE << "Enabling SLVS output on CBCs by setting register to " << std::bitset<8>(cRegValue) << RESET;
        else
            LOG(DEBUG) << BOLDBLUE << "Disabling SLVS output on CBCs by setting register to " << std::bitset<8>(cRegValue) << RESET;
        return WriteChipSingleReg(pCbc, "HIP&TestMode", cRegValue, pVerifLoop);
    }
    else
    {
        if(dacValue > 255)
            LOG(ERROR) << "Error, DAC " << dacName << " for CBC3 can only be 8 bit max (255)!";
        else
            return WriteChipSingleReg(pCbc, dacName, dacValue, pVerifLoop);
    }
    return false;
}
452

Fabio Ravera's avatar
Fabio Ravera committed
453
454
455
456
457
458
459
bool CbcInterface::WriteChipSingleReg(Chip* pCbc, const std::string& pRegNode, uint16_t pValue, bool pVerifLoop)
{
    if(pValue > 0xFF)
    {
        LOG(ERROR) << "Cbc register are 8 bits, impossible to write " << pValue << " on registed " << pRegNode;
        return false;
    }
460

Fabio Ravera's avatar
Fabio Ravera committed
461
462
    // first, identify the correct BeBoardFWInterface
    setBoard(pCbc->getBeBoardId());
463

Fabio Ravera's avatar
Fabio Ravera committed
464
465
466
    // next, get the reg item
    ChipRegItem cRegItem = pCbc->getRegItem(pRegNode);
    cRegItem.fValue      = pValue & 0xFF;
467

Fabio Ravera's avatar
Fabio Ravera committed
468
469
    // vector for transaction
    std::vector<uint32_t> cVec;
470

Fabio Ravera's avatar
Fabio Ravera committed
471
    // encode the reg specific to the FW, pVerifLoop decides if it should be read back, true means to write it
472
    fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVec, pVerifLoop, true);
Fabio Ravera's avatar
Fabio Ravera committed
473
474
475
476
    // write the registers, the answer will be in the same cVec
    // the number of times the write operation has been attempted is given by cWriteAttempts
    uint8_t cWriteAttempts = 0;
    bool    cSuccess       = fBoardFW->WriteChipBlockReg(cVec, cWriteAttempts, pVerifLoop);
477

Fabio Ravera's avatar
Fabio Ravera committed
478
    // update the HWDescription object
Fabio Ravera's avatar
Fabio Ravera committed
479
    if(cSuccess) pCbc->setReg(pRegNode, pValue);
480

Fabio Ravera's avatar
Fabio Ravera committed
481
482
483
484
#ifdef COUNT_FLAG
    fRegisterCount++;
    fTransactionCount++;
#endif
485

Fabio Ravera's avatar
Fabio Ravera committed
486
487
    return cSuccess;
}
488

Fabio Ravera's avatar
Fabio Ravera committed
489
490
491
492
bool CbcInterface::WriteChipMultReg(Chip* pCbc, const std::vector<std::pair<std::string, uint16_t>>& pVecReq, bool pVerifLoop)
{
    // first, identify the correct BeBoardFWInterface
    setBoard(pCbc->getBeBoardId());
493

Fabio Ravera's avatar
Fabio Ravera committed
494
    std::vector<uint32_t> cVec;
495

Fabio Ravera's avatar
Fabio Ravera committed
496
497
    // Deal with the ChipRegItems and encode them
    ChipRegItem cRegItem;
498

Fabio Ravera's avatar
Fabio Ravera committed
499
500
501
    for(const auto& cReg: pVecReq)
    {
        if(cReg.second > 0xFF)
502
        {
Fabio Ravera's avatar
Fabio Ravera committed
503
504
            LOG(ERROR) << "Cbc register are 8 bits, impossible to write " << cReg.second << " on registed " << cReg.first;
            continue;
505
        }
Fabio Ravera's avatar
Fabio Ravera committed
506
507
        cRegItem        = pCbc->getRegItem(cReg.first);
        cRegItem.fValue = cReg.second;
508
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVec, pVerifLoop, true);
Fabio Ravera's avatar
Fabio Ravera committed
509
510
511
512
#ifdef COUNT_FLAG
        fRegisterCount++;
#endif
    }
513

Fabio Ravera's avatar
Fabio Ravera committed
514
515
516
517
518
519
520
    // write the registers, the answer will be in the same cVec
    // the number of times the write operation has been attempted is given by cWriteAttempts
    uint8_t cWriteAttempts = 0;
    bool    cSuccess       = fBoardFW->WriteChipBlockReg(cVec, cWriteAttempts, pVerifLoop);
#ifdef COUNT_FLAG
    fTransactionCount++;
#endif
521

Fabio Ravera's avatar
Fabio Ravera committed
522
523
524
525
    // if the transaction is successfull, update the HWDescription object
    if(cSuccess)
    {
        for(const auto& cReg: pVecReq)
526
        {
Fabio Ravera's avatar
Fabio Ravera committed
527
528
            cRegItem = pCbc->getRegItem(cReg.first);
            pCbc->setReg(cReg.first, cReg.second);
529
        }
Fabio Ravera's avatar
Fabio Ravera committed
530
    }
531

Fabio Ravera's avatar
Fabio Ravera committed
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
    return cSuccess;
}
bool CbcInterface::WriteChipAllLocalReg(ReadoutChip* pCbc, const std::string& dacName, ChipContainer& localRegValues, bool pVerifLoop)
{
    setBoard(pCbc->getBeBoardId());
    assert(localRegValues.size() == pCbc->getNumberOfChannels());
    std::string dacTemplate;
    bool        isMask = false;

    if(dacName == "ChannelOffset")
        dacTemplate = "Channel%03d";
    else if(dacName == "Mask")
        isMask = true;
    else
        LOG(ERROR) << "Error, DAC " << dacName << " is not a Local DAC";

    std::vector<std::pair<std::string, uint16_t>> cRegVec;
    // std::vector<uint32_t> listOfChannelToUnMask;
    ChannelGroup<NCHANNELS, 1> channelToEnable;

    std::vector<uint32_t> cVec;
    cVec.clear();
    for(uint8_t iChannel = 0; iChannel < pCbc->getNumberOfChannels(); ++iChannel)
    {
        if(isMask)
557
        {
Fabio Ravera's avatar
Fabio Ravera committed
558
            if(localRegValues.getChannel<uint16_t>(iChannel))
559
            {
Fabio Ravera's avatar
Fabio Ravera committed
560
561
                channelToEnable.enableChannel(iChannel);
                // listOfChannelToUnMask.emplace_back(iChannel);
562
563
            }
        }
564
565
        else
        {
Fabio Ravera's avatar
Fabio Ravera committed
566
567
            char dacName1[20];
            sprintf(dacName1, dacTemplate.c_str(), iChannel + 1);
568
            // fBoardFW->EncodeReg ( cRegItem, pCbc->getHybridId(), pCbc->getId(), cVec, pVerifLoop, true );
569
            // #ifdef COUNT_FLAG
Fabio Ravera's avatar
Fabio Ravera committed
570
            //     fRegisterCount++;
571
            // #endif
Fabio Ravera's avatar
Fabio Ravera committed
572
            cRegVec.emplace_back(dacName1, localRegValues.getChannel<uint16_t>(iChannel));
573
574
        }
    }
575

Fabio Ravera's avatar
Fabio Ravera committed
576
    if(isMask) { return maskChannelsGroup(pCbc, &channelToEnable, pVerifLoop); }
Fabio Ravera's avatar
Fabio Ravera committed
577
    else
578
    {
Fabio Ravera's avatar
Fabio Ravera committed
579
580
581
582
583
584
585
586
587
        // uint8_t cWriteAttempts = 0 ;
        // bool cSuccess = fBoardFW->WriteChipBlockReg ( cVec, cWriteAttempts, pVerifLoop);
        // #ifdef COUNT_FLAG
        //     fTransactionCount++;
        // #endif
        // return cSuccess;
        return WriteChipMultReg(pCbc, cRegVec, pVerifLoop);
    }
}
npierre's avatar
npierre committed
588

Fabio Ravera's avatar
Fabio Ravera committed
589
590
591
592
593
594
595
596
597
598
uint16_t CbcInterface::ReadChipReg(Chip* pCbc, const std::string& pRegNode)
{
    ChipRegItem cRegItem;
    bool        cFailed = false;
    bool        cRead;
    uint8_t     cCbcId;
    setBoard(pCbc->getBeBoardId());
    std::vector<uint32_t> cVecReq;
    if(pRegNode == "VCth")
    {
599
600
        fBoardFW->EncodeReg(pCbc->getRegItem("VCth1"), pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
        fBoardFW->EncodeReg(pCbc->getRegItem("VCth2"), pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
601
602
603
604
605
606
        fBoardFW->ReadChipBlockReg(cVecReq);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);

        uint16_t cReg0 = cRegItem.fValue;
        pCbc->setReg("VCth1", cRegItem.fValue);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[1], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
607
        if(cFailed) return 0;
Fabio Ravera's avatar
Fabio Ravera committed
608
609
610
611
612
613
614
615

        pCbc->setReg("VCth2", cRegItem.fValue);
        uint16_t cReg1      = cRegItem.fValue;
        uint16_t cThreshold = ((cReg1 & 0x3) << 8) | cReg0;
        return cThreshold;
    }
    else if(pRegNode == "Threshold")
    {
616
617
        fBoardFW->EncodeReg(pCbc->getRegItem("VCth1"), pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
        fBoardFW->EncodeReg(pCbc->getRegItem("VCth2"), pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
618
619
620
621
622
623
        fBoardFW->ReadChipBlockReg(cVecReq);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);

        uint16_t cReg0 = cRegItem.fValue;
        pCbc->setReg("VCth1", cRegItem.fValue);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[1], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
624
        if(cFailed) return 0;
Fabio Ravera's avatar
Fabio Ravera committed
625
626
627
628
629
630
631
632
633

        pCbc->setReg("VCth2", cRegItem.fValue);
        uint16_t cReg1      = cRegItem.fValue;
        uint16_t cThreshold = ((cReg1 & 0x3) << 8) | cReg0;
        return cThreshold;
    }
    else if(pRegNode == "HitLogic")
    {
        cRegItem = pCbc->getRegItem("Pipe&StubInpSel&Ptwidth");
634
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
635
636
637
        fBoardFW->ReadChipBlockReg(cVecReq);
        // bools to find the values of failed and read
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
638
        if(!cFailed) pCbc->setReg("Pipe&StubInpSel&Ptwidth", cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
639
640
641
642
643
644

        return (cRegItem.fValue & 0xC0) >> 6;
    }
    else if(pRegNode == "StubLogic")
    {
        cRegItem = pCbc->getRegItem("Pipe&StubInpSel&Ptwidth");
645
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
646
647
648
        fBoardFW->ReadChipBlockReg(cVecReq);
        // bools to find the values of failed and read
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
649
        if(!cFailed) pCbc->setReg("Pipe&StubInpSel&Ptwidth", cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
650
651
652
653
654
655

        return (cRegItem.fValue & 0x30) >> 4;
    }
    else if(pRegNode == "HitOr")
    {
        cRegItem = pCbc->getRegItem("40MhzClk&Or254");
656
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
657
658
        fBoardFW->ReadChipBlockReg(cVecReq);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
659
        if(!cFailed) pCbc->setReg("40MhzClk&Or254", cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
660
661
662
663
664
        return (cRegItem.fValue & 0x40) >> 6;
    }
    else if(pRegNode == "LayerSwap")
    {
        cRegItem = pCbc->getRegItem("LayerSwap&CluWidth");
665
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
666
667
        fBoardFW->ReadChipBlockReg(cVecReq);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
668
        if(!cFailed) pCbc->setReg("LayerSwap&CluWidth", cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
669
670
671
672
673
        return (cRegItem.fValue & 0x08) >> 3;
    }
    else if(pRegNode == "PtCut")
    {
        cRegItem = pCbc->getRegItem("Pipe&StubInpSel&Ptwidth");
674
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
675
676
        fBoardFW->ReadChipBlockReg(cVecReq);
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
677
        if(!cFailed) pCbc->setReg("Pipe&StubInpSel&Ptwidth", cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
678
679
680
681
682
        return (cRegItem.fValue & 0x0F);
    }
    else
    {
        cRegItem = pCbc->getRegItem(pRegNode);
683
        fBoardFW->EncodeReg(cRegItem, pCbc->getHybridId(), pCbc->getId(), cVecReq, true, false);
Fabio Ravera's avatar
Fabio Ravera committed
684
685
686
        fBoardFW->ReadChipBlockReg(cVecReq);
        // bools to find the values of failed and read
        fBoardFW->DecodeReg(cRegItem, cCbcId, cVecReq[0], cRead, cFailed);
Fabio Ravera's avatar
Fabio Ravera committed
687
        if(!cFailed) pCbc->setReg(pRegNode, cRegItem.fValue);
Fabio Ravera's avatar
Fabio Ravera committed
688
689
690
691

        return cRegItem.fValue & 0xFF;
    }
}
Georg Auzinger's avatar
Georg Auzinger committed
692

693
void CbcInterface::WriteHybridBroadcastChipReg(const Hybrid* pHybrid, const std::string& pRegNode, uint16_t pValue)
Fabio Ravera's avatar
Fabio Ravera committed
694
695
696
{
    // first set the correct BeBoard
    setBoard(pHybrid->getBeBoardId());
697

Fabio Ravera's avatar
Fabio Ravera committed
698
699
    ChipRegItem cRegItem = static_cast<ReadoutChip*>(pHybrid->at(0))->getRegItem(pRegNode);
    cRegItem.fValue      = pValue;
700

Fabio Ravera's avatar
Fabio Ravera committed
701
702
    // vector for transaction
    std::vector<uint32_t> cVec;
703

Fabio Ravera's avatar
Fabio Ravera committed
704
705
706
707
    // encode the reg specific to the FW, pVerifLoop decides if it should be read back, true means to write it
    // the 1st boolean could be true if I acually wanted to read back from each CBC but this somehow does not make
    // sense!
    fBoardFW->BCEncodeReg(cRegItem, pHybrid->size(), cVec, false, true);
npierre's avatar
npierre committed
708

Fabio Ravera's avatar
Fabio Ravera committed
709
710
711
    // true is the readback bit - the IC FW just checks that the transaction was successful and the
    // Strasbourg FW does nothing
    bool cSuccess = fBoardFW->BCWriteChipBlockReg(cVec, true);
Georg Auzinger's avatar
Georg Auzinger committed
712

Fabio Ravera's avatar
Fabio Ravera committed
713
714
715
716
#ifdef COUNT_FLAG
    fRegisterCount++;
    fTransactionCount++;
#endif
717

Fabio Ravera's avatar
Fabio Ravera committed
718
719
    // update the HWDescription object -- not sure if the transaction was successfull
    if(cSuccess)
Fabio Ravera's avatar
Fabio Ravera committed
720
        for(auto cCbc: *pHybrid) static_cast<ReadoutChip*>(cCbc)->setReg(pRegNode, pValue);
Fabio Ravera's avatar
Fabio Ravera committed
721
}
722

723
void CbcInterface::WriteBroadcastCbcMultiReg(const Hybrid* pHybrid, const std::vector<std::pair<std::string, uint8_t>> pVecReg)
Fabio Ravera's avatar
Fabio Ravera committed
724
725
726
{
    // first set the correct BeBoard
    setBoard(pHybrid->getBeBoardId());
727

Fabio Ravera's avatar
Fabio Ravera committed
728
    std::vector<uint32_t> cVec;
729

Fabio Ravera's avatar
Fabio Ravera committed
730
731
    // Deal with the ChipRegItems and encode them
    ChipRegItem cRegItem;
732

Fabio Ravera's avatar
Fabio Ravera committed
733
734
735
736
    for(const auto& cReg: pVecReg)
    {
        cRegItem        = static_cast<ReadoutChip*>(pHybrid->at(0))->getRegItem(cReg.first);
        cRegItem.fValue = cReg.second;
737

Fabio Ravera's avatar
Fabio Ravera committed
738
739
740
741
742
        fBoardFW->BCEncodeReg(cRegItem, pHybrid->size(), cVec, false, true);
#ifdef COUNT_FLAG
        fRegisterCount++;
#endif
    }
743

Fabio Ravera's avatar
Fabio Ravera committed
744
745
    // write the registerss, the answer will be in the same cVec
    bool cSuccess = fBoardFW->BCWriteChipBlockReg(cVec, true);
746

Fabio Ravera's avatar
Fabio Ravera committed
747
748
749
#ifdef COUNT_FLAG
    fTransactionCount++;
#endif
Davide Di Croce's avatar
Davide Di Croce committed
750

Fabio Ravera's avatar
Fabio Ravera committed
751
752
753
754
755
756
757
758
    if(cSuccess)
        for(auto cCbc: *pHybrid)
            for(auto& cReg: pVecReg)
            {
                cRegItem = static_cast<ReadoutChip*>(cCbc)->getRegItem(cReg.first);
                static_cast<ReadoutChip*>(cCbc)->setReg(cReg.first, cReg.second);
            }
}
Davide Di Croce's avatar
Davide Di Croce committed
759

Fabio Ravera's avatar
Fabio Ravera committed
760
761
762
763
764
765
766
767
768
uint32_t CbcInterface::ReadCbcIDeFuse(Chip* pCbc)
{
    WriteChipReg(pCbc, "ChipIDFuse3", 8);
    uint8_t  IDa     = ReadChipReg(pCbc, "ChipIDFuse1");
    uint8_t  IDb     = ReadChipReg(pCbc, "ChipIDFuse2");
    uint8_t  IDc     = ReadChipReg(pCbc, "ChipIDFuse3");
    uint32_t IDeFuse = ((IDa)&0x000000FF) + (((IDb) << 8) & 0x0000FF00) + (((IDc) << 16) & 0x000F0000);
    LOG(INFO) << BOLDBLUE << " CHIP ID FUSE " << +IDeFuse << RESET;
    return IDeFuse;
769
}
Fabio Ravera's avatar
Fabio Ravera committed
770
771

} // namespace Ph2_HwInterface