1 #include "FPGA_common.h"
2 #include "IConnection.h"
3 #include "LMS64CProtocol.h"
4 #include <ciso646>
5 #include <vector>
6 #include <map>
7 #include <math.h>
8 #include <assert.h>
9 #include <thread>
10 #include "Logger.h"
11 #include <algorithm>
12 using namespace std;
13 
14 namespace lime
15 {
16 
17 // 0x000A
18 const int RX_EN = 1; //controls both receiver and transmitter
19 const int TX_EN = 1 << 1; //used for wfm playback from fpga
20 const int STREAM_LOAD = 1 << 2;
21 
22 // 0x0009
23 const int SMPL_NR_CLR = 1; // rising edge clears
24 const int TXPCT_LOSS_CLR = 1 << 1; // 0 - normal operation, 1-clear
25 
26 const uint16_t PLLCFG_START = 0x1;
27 const uint16_t PHCFG_START = 0x2;
28 const uint16_t PLLRST_START = 0x4;
29 const uint16_t PHCFG_UPDN = 1 << 13;
30 const uint16_t PHCFG_MODE = 1 << 14;
31 
32 const uint16_t busyAddr = 0x0021;
33 
FPGA()34 FPGA::FPGA()
35 {
36     useCache = false;
37 }
38 
EnableValuesCache(bool enabled)39 void FPGA::EnableValuesCache(bool enabled)
40 {
41     useCache = enabled;
42     if (!useCache)
43         regsCache.clear();
44 }
45 
WriteRegister(uint32_t addr,uint32_t val)46 int FPGA::WriteRegister(uint32_t addr, uint32_t val)
47 {
48     return WriteRegisters(&addr, &val, 1);
49 }
50 
ReadRegister(uint32_t addr)51 int FPGA::ReadRegister(uint32_t addr)
52 {
53     uint32_t val;
54     return ReadRegisters(&addr, &val, 1) != 0 ? -1 : val;
55 }
56 
WriteRegisters(const uint32_t * addrs,const uint32_t * data,unsigned cnt)57 int FPGA::WriteRegisters(const uint32_t *addrs, const uint32_t *data, unsigned cnt)
58 {
59     if (useCache)
60     {
61         const int readonly_regs[] = {
62             0x000, 0x001, 0x002, 0x003, 0x021, 0x022, 0x065, 0x067, 0x069, 0x06A,
63             0x06B, 0x06C, 0x06D, 0x06F, 0x070, 0x071, 0x072, 0x073, 0x074, 0x076,
64             0x077, 0x078, 0x07A, 0x07B, 0x07C, 0x0C2, 0x100, 0x101, 0x102, 0x103,
65             0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B, 0x10C, 0x10D,
66             0x10E, 0x10F, 0x110, 0x111, 0x114};
67 
68         std::vector<uint32_t> reg_addr;
69         std::vector<uint32_t> reg_val;
70         for (unsigned i = 0; i < cnt; i++)
71         {
72             auto endptr = readonly_regs + sizeof(readonly_regs)/sizeof(*readonly_regs);
73             if (std::find(readonly_regs, endptr, addrs[i])!=endptr)
74                 continue;
75 
76             auto result = regsCache.find(addrs[i]);
77             if (result != regsCache.end() && result->second == data[i])
78                 continue;
79             reg_addr.push_back(addrs[i]);
80             reg_val.push_back(data[i]);
81             regsCache[addrs[i]] = data[i];
82         }
83         if (reg_val.size())
84             return connection->WriteRegisters(reg_addr.data(), reg_val.data(), reg_val.size());
85         return 0;
86     }
87     return connection->WriteRegisters(addrs, data, cnt);
88 }
89 
ReadRegisters(const uint32_t * addrs,uint32_t * data,unsigned cnt)90 int FPGA::ReadRegisters(const uint32_t *addrs, uint32_t *data, unsigned cnt)
91 {
92     if (useCache)
93     {
94         const int volatile_regs[] = {
95             0x021, 0x022, 0x060, 0x065, 0x067, 0x069, 0x06A, 0x06B, 0x06C, 0x06D,
96             0x06F, 0x070, 0x071, 0x072, 0x073, 0x074, 0x076, 0x077, 0x078, 0x07A,
97             0x07B, 0x07C, 0x0C2, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106,
98             0x107, 0x108, 0x109, 0x10A, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110,
99             0x111, 0x114};
100 
101         std::vector<uint32_t> reg_addr;
102         for (unsigned i = 0; i < cnt; i++)
103         {
104             auto endptr = volatile_regs + sizeof(volatile_regs)/sizeof(*volatile_regs);
105             if (std::find(volatile_regs, endptr, addrs[i])==endptr)
106             {
107                 auto result = regsCache.find(addrs[i]);
108                 if (result != regsCache.end())
109                     continue;
110             }
111             reg_addr.push_back(addrs[i]);
112         }
113 
114         if (reg_addr.size())
115         {
116             std::vector<uint32_t> reg_val(reg_addr.size());
117             if (connection->ReadRegisters(reg_addr.data(), reg_val.data(), reg_addr.size()) <0)
118                 return -1;
119             for (unsigned i = 0; i < reg_addr.size(); i++)
120                 regsCache[reg_addr[i]] = reg_val[i];
121         }
122         for (unsigned i = 0; i < cnt; i++)
123             data[i] = regsCache[addrs[i]];
124         return 0;
125     }
126     return connection->ReadRegisters(addrs, data, cnt);
127 }
128 
SetConnection(IConnection * conn)129 void FPGA::SetConnection(IConnection* conn)
130 {
131     connection = conn;
132 }
133 
GetConnection() const134 IConnection* FPGA::GetConnection() const
135 {
136     return connection;
137 }
138 
StartStreaming()139 int FPGA::StartStreaming()
140 {
141     int interface_ctrl_000A = ReadRegister(0x000A);
142     if (interface_ctrl_000A < 0)
143         return -1;
144     uint32_t value = RX_EN;
145     return WriteRegister(0x000A, interface_ctrl_000A | value);
146 }
147 
StopStreaming()148 int FPGA::StopStreaming()
149 {
150     int interface_ctrl_000A = ReadRegister(0x000A);
151     if (interface_ctrl_000A < 0)
152         return -1;
153     uint32_t value = ~(RX_EN | TX_EN);
154     return WriteRegister(0x000A, interface_ctrl_000A & value);
155 }
156 
ResetTimestamp()157 int FPGA::ResetTimestamp()
158 {
159 #ifndef NDEBUG
160     int interface_ctrl_000A = ReadRegister(0x000A);
161     if (interface_ctrl_000A < 0)
162         return 0;
163 
164     if ((interface_ctrl_000A & RX_EN))
165         return ReportError(EPERM, "Streaming must be stopped to reset timestamp");
166 
167 #endif // NDEBUG
168     //reset hardware timestamp to 0
169     int interface_ctrl_0009 = ReadRegister(0x0009);
170     if (interface_ctrl_0009 < 0)
171         return 0;
172     uint32_t value = (TXPCT_LOSS_CLR | SMPL_NR_CLR);
173     WriteRegister(0x0009, interface_ctrl_0009 & ~(value));
174     WriteRegister(0x0009, interface_ctrl_0009 | value);
175     return WriteRegister(0x0009, interface_ctrl_0009 & ~value);
176 }
177 
SetPllClock(int clockIndex,int nSteps,bool waitLock,uint16_t & reg23val)178 int FPGA::SetPllClock(int clockIndex, int nSteps, bool waitLock, uint16_t &reg23val)
179 {
180     const auto timeout = chrono::seconds(3);
181     auto t1 = chrono::high_resolution_clock::now();
182     auto t2 = t1;
183     vector<uint32_t> addrs;
184     vector<uint32_t> values;
185     addrs.push_back(0x0023); values.push_back(reg23val & ~PLLCFG_START);
186     addrs.push_back(0x0024); values.push_back(abs(nSteps)); //CNT_PHASE
187     int cnt_ind = (clockIndex + 2) & 0x1F; //C0 index 2, C1 index 3...
188     reg23val &= ~(0xF<<8);
189     reg23val &= ~(PHCFG_MODE);
190     reg23val = reg23val | (cnt_ind << 8);
191     if(nSteps >= 0)
192         reg23val |= PHCFG_UPDN;
193     else
194         reg23val &= ~PHCFG_UPDN;
195     addrs.push_back(0x0023); values.push_back(reg23val); //PHCFG_UpDn, CNT_IND
196     addrs.push_back(0x0023); values.push_back(reg23val | PHCFG_START);
197 
198     if(WriteRegisters(addrs.data(), values.data(), values.size()) != 0)
199         ReportError(EIO, "SetPllFrequency: PHCFG, failed to write registers");
200     addrs.clear(); values.clear();
201 
202     bool done = false;
203     uint8_t errorCode = 0;
204     t1 = chrono::high_resolution_clock::now();
205     if(waitLock) do
206     {
207         uint16_t statusReg = ReadRegister(busyAddr);
208         done = statusReg & 0x1;
209         errorCode = (statusReg >> 7) & 0xFF;
210         t2 = chrono::high_resolution_clock::now();
211         std::this_thread::sleep_for(chrono::milliseconds(10));
212     } while(!done && errorCode == 0 && (t2-t1) < timeout);
213     if(t2 - t1 > timeout)
214         return ReportError(ENODEV, "SetPllFrequency: PHCFG timeout, busy bit is still 1");
215     if(errorCode != 0)
216         return ReportError(EBUSY, "SetPllFrequency: error configuring PHCFG");
217     addrs.push_back(0x0023); values.push_back(reg23val & ~PHCFG_START);
218     if(WriteRegisters(addrs.data(), values.data(), values.size()) != 0)
219         ReportError(EIO, "SetPllFrequency: configure FPGA PLL, failed to write registers");
220     return 0;
221 }
222 
223 /** @brief Configures board FPGA clocks
224 @param serPort communications port
225 @param pllIndex index of FPGA pll
226 @param clocks list of clocks to configure
227 @param clocksCount number of clocks to configure
228 @return 0-success, other-failure
229 */
SetPllFrequency(const uint8_t pllIndex,const double inputFreq,FPGA_PLL_clock * clocks,const uint8_t clockCount)230 int FPGA::SetPllFrequency(const uint8_t pllIndex, const double inputFreq, FPGA_PLL_clock* clocks, const uint8_t clockCount)
231 {
232     auto t1 = chrono::high_resolution_clock::now();
233     auto t2 = t1;
234     const auto timeout = chrono::seconds(3);
235     if(not connection)
236         return ReportError(ENODEV, "ConfigureFPGA_PLL: connection port is NULL");
237     if(not connection->IsOpen())
238         return ReportError(ENODEV, "ConfigureFPGA_PLL: configure FPGA PLL, device not connected");
239     eLMS_DEV boardType = connection->GetDeviceInfo().deviceName == GetDeviceName(LMS_DEV_LIMESDR_QPCIE) ? LMS_DEV_LIMESDR_QPCIE : LMS_DEV_UNKNOWN;
240 
241     if(pllIndex > 15)
242         ReportError(ERANGE, "SetPllFrequency: PLL index(%i) out of range [0-15]", pllIndex);
243 
244     //check if all clocks are above 5MHz
245     const double PLLlowerLimit = 5e6;
246     if(inputFreq < PLLlowerLimit)
247         return ReportError(ERANGE, "SetPllFrequency: input frequency must be >=%g MHz", PLLlowerLimit/1e6);
248     for(int i=0; i<clockCount; ++i)
249         if(clocks[i].outFrequency < PLLlowerLimit && not clocks[i].bypass)
250             return ReportError(ERANGE, "SetPllFrequency: clock(%i) must be >=%g MHz", i, PLLlowerLimit/1e6);
251 
252     //disable direct clock source
253     uint16_t drct_clk_ctrl_0005 = ReadRegister(0x0005);
254     WriteRegister(0x0005, drct_clk_ctrl_0005 & ~(1 << pllIndex));
255 
256     uint16_t reg23val = ReadRegister(0x0003);
257 
258     reg23val &= ~(0x1F << 3); //clear PLL index
259     reg23val &= ~PLLCFG_START; //clear PLLCFG_START
260     reg23val &= ~PHCFG_START; //clear PHCFG
261     reg23val &= ~PLLRST_START; //clear PLL reset
262     reg23val &= ~PHCFG_UPDN; //clear PHCFG_UpDn
263     reg23val |= pllIndex << 3;
264 
265     uint16_t reg25 = ReadRegister(0x0025);
266 
267     uint16_t statusReg;
268     bool done = false;
269     uint8_t errorCode = 0;
270     vector<uint32_t> addrs;
271     vector<uint32_t> values;
272     addrs.push_back(0x0025); values.push_back(reg25 | 0x80);
273     addrs.push_back(0x0023); values.push_back(reg23val); //PLL_IND
274     if (clocks->findPhase == false)
275     {
276         addrs.push_back(0x0023); values.push_back(reg23val | PLLRST_START);
277     }
278     WriteRegisters(addrs.data(), values.data(), values.size());
279     addrs.clear(); values.clear();
280 
281     t1 = chrono::high_resolution_clock::now();
282     if(boardType == LMS_DEV_LIMESDR_QPCIE) do //wait for reset to activate
283     {
284         statusReg = ReadRegister(busyAddr);
285         done = statusReg & 0x1;
286         errorCode = (statusReg >> 7) & 0xFF;
287         std::this_thread::sleep_for(chrono::milliseconds(10));
288         t2 = chrono::high_resolution_clock::now();
289     } while(not done && errorCode == 0 && (t2-t1) < timeout);
290     if(t2 - t1 > timeout)
291         return ReportError(ENODEV, "SetPllFrequency: PLLRST timeout, busy bit is still 1");
292     if(errorCode != 0)
293         return ReportError(EBUSY, "SetPllFrequency: error resetting PLL");
294 
295     addrs.push_back(0x0023); values.push_back(reg23val & ~PLLRST_START);
296 
297     //configure FPGA PLLs
298     const double vcoLimits_Hz[2] = { 600e6, 1300e6 };
299 
300     map< unsigned long, int> availableVCOs; //all available frequencies for VCO
301     for(int i=0; i<clockCount; ++i)
302     {
303         unsigned long freq;
304         freq = clocks[i].outFrequency*(int(vcoLimits_Hz[0]/clocks[i].outFrequency) + 1);
305         while(freq >= vcoLimits_Hz[0] && freq <= vcoLimits_Hz[1])
306         {
307             //add all output frequency multiples that are in VCO interval
308             availableVCOs.insert( pair<unsigned long, int>(freq, 0));
309             freq += clocks[i].outFrequency;
310         }
311     }
312 
313     int bestScore = 0; //score shows how many outputs have integer dividers
314     //calculate scores for all available frequencies
315     for (auto &it : availableVCOs)
316     {
317         for(int i=0; i<clockCount; ++i)
318         {
319             if(clocks[i].outFrequency == 0 || clocks[i].bypass)
320                 continue;
321 
322             if( (int(it.first) % int(clocks[i].outFrequency)) == 0)
323                 it.second = it.second+1;
324         }
325         if(it.second > bestScore)
326         {
327             bestScore = it.second;
328         }
329     }
330     int N(0), M(0);
331     double bestDeviation = 1e9;
332     for(auto it : availableVCOs)
333     {
334         if(it.second == bestScore)
335         {
336             float coef = (it.first / inputFreq);
337             int Ntemp = 1;
338             int Mtemp = int(coef + 0.5);
339             while(inputFreq / Ntemp > PLLlowerLimit)
340             {
341                 ++Ntemp;
342                 Mtemp = int(coef*Ntemp + 0.5);
343                 if(Mtemp > 255)
344                 {
345                     --Ntemp;
346                     Mtemp = int(coef*Ntemp + 0.5);
347                     break;
348                 }
349             }
350             double deviation = fabs(it.first - inputFreq*Mtemp / Ntemp);
351             if(deviation <= bestDeviation)
352             {
353                 bestDeviation = deviation;
354                 M = Mtemp;
355                 N = Ntemp;
356             }
357         }
358     }
359 
360     int mlow = M / 2;
361     int mhigh = mlow + M % 2;
362     double Fvco = inputFreq*M/N; //actual VCO freq
363     lime::debug("M=%i, N=%i, Fvco=%.3f MHz", M, N, Fvco / 1e6);
364     if(Fvco < vcoLimits_Hz[0] || Fvco > vcoLimits_Hz[1])
365         return ReportError(ERANGE, "SetPllFrequency: VCO(%g MHz) out of range [%g:%g] MHz", Fvco/1e6, vcoLimits_Hz[0]/1e6, vcoLimits_Hz[1]/1e6);
366 
367     uint16_t M_N_odd_byp = (M%2 << 3) | (N%2 << 1);
368     if(M == 1)
369         M_N_odd_byp |= 1 << 2; //bypass M
370     if(N == 1)
371         M_N_odd_byp |= 1; //bypass N
372     addrs.push_back(0x0026); values.push_back(M_N_odd_byp);
373     int nlow = N / 2;
374     int nhigh = nlow + N % 2;
375     addrs.push_back(0x002A); values.push_back(nhigh << 8 | nlow); //N_high_cnt, N_low_cnt
376     addrs.push_back(0x002B); values.push_back(mhigh << 8 | mlow);
377 
378     uint16_t c7_c0_odds_byps = 0x5555; //bypass all C
379     uint16_t c15_c8_odds_byps = 0x5555; //bypass all C
380 
381     //set outputs
382     for(int i=0; i<clockCount; ++i)
383     {
384         int C = int(Fvco / clocks[i].outFrequency + 0.5);
385         int clow = C / 2;
386         int chigh = clow + C % 2;
387         if(i < 8)
388         {
389             if(not clocks[i].bypass && C != 1)
390                 c7_c0_odds_byps &= ~(1 << (i*2)); //enable output
391             c7_c0_odds_byps |= (C % 2) << (i*2+1); //odd bit
392         }
393         else
394         {
395             if(not clocks[i].bypass && C != 1)
396                 c15_c8_odds_byps &= ~(1 << ((i-8)*2)); //enable output
397             c15_c8_odds_byps |= (C % 2) << ((i-8)*2+1); //odd bit
398         }
399         addrs.push_back(0x002E + i); values.push_back(chigh << 8 | clow);
400         clocks[i].rd_actualFrequency = (inputFreq * M / N) / (chigh + clow);
401     }
402     addrs.push_back(0x0027); values.push_back(c7_c0_odds_byps);
403     addrs.push_back(0x0028); values.push_back(c15_c8_odds_byps);
404     if (clockCount != 4 || clocks->index == 3)
405     {
406         addrs.push_back(0x0023); values.push_back(reg23val | PLLCFG_START);
407     }
408     if(WriteRegisters(addrs.data(), values.data(), values.size()) != 0)
409         lime::error("SetPllFrequency: PLL CFG, failed to write registers");
410     addrs.clear(); values.clear();
411 
412     t1 = chrono::high_resolution_clock::now();
413     if(boardType == LMS_DEV_LIMESDR_QPCIE) do //wait for config to activate
414     {
415         statusReg = ReadRegister(busyAddr);
416         done = statusReg & 0x1;
417         errorCode = (statusReg >> 7) & 0xFF;
418         t2 = chrono::high_resolution_clock::now();
419         std::this_thread::sleep_for(chrono::milliseconds(10));
420     } while(not done && errorCode == 0 && (t2-t1) < timeout);
421     if(t2 - t1 > timeout)
422         return ReportError(ENODEV, "SetPllFrequency: PLLCFG timeout, busy bit is still 1");
423     if(errorCode != 0)
424         return ReportError(EBUSY, "SetPllFrequency: error configuring PLLCFG");
425 
426     for(int i=0; i<clockCount; ++i)
427     {
428         int C = int(Fvco / clocks[i].outFrequency + 0.5);
429         float fOut_MHz = inputFreq/1e6;
430         float Fstep_us = 1 / (8 * fOut_MHz*C);
431         float Fstep_deg = (360 * Fstep_us) / (1 / fOut_MHz);
432         if (clocks[i].findPhase == false)
433         {
434            const int nSteps = 0.49 + clocks[i].phaseShift_deg  / Fstep_deg;
435            SetPllClock(clocks[i].index, nSteps, boardType, reg23val);
436         }
437         else
438         {
439             const int nSteps = (360.0 / Fstep_deg)-0.5;
440             const auto timeout = chrono::seconds(3);
441             t1 = chrono::high_resolution_clock::now();
442             t2 = t1;
443             addrs.clear(); values.clear();
444             int cnt_ind = (clocks[i].index + 2) & 0x1F; //C0 index 2, C1 index 3...
445             reg23val &= ~PLLCFG_START;
446             reg23val &= ~(0xF << 8);
447             reg23val |= (cnt_ind << 8);
448             reg23val |= PHCFG_UPDN;
449             reg23val |= PHCFG_MODE;
450 
451             addrs.push_back(0x0023); values.push_back(reg23val); //PHCFG_UpDn, CNT_IND
452             addrs.push_back(0x0024); values.push_back(abs(nSteps)); //CNT_PHASE
453             addrs.push_back(0x0023); values.push_back(reg23val | PHCFG_START);
454 
455             if (WriteRegisters(addrs.data(), values.data(), values.size()) != 0)
456                 lime::error( "SetPllFrequency: find phase, failed to write registers");
457             addrs.clear(); values.clear();
458 
459             bool done = false;
460             bool error = false;
461 
462             t1 = chrono::high_resolution_clock::now();
463             do
464             {
465                 uint16_t statusReg = ReadRegister(busyAddr);
466                 done = statusReg & 0x4;
467                 error = statusReg & 0x08;
468                 t2 = chrono::high_resolution_clock::now();
469                 std::this_thread::sleep_for(chrono::milliseconds(10));
470             } while (!done && (t2 - t1) < timeout);
471             if (!done && t2 - t1 > timeout)
472                 lime::error("SetPllFrequency: timeout, busy bit is still 1");
473             if (error)
474                 lime::warning("SetPllFrequency: error configuring phase");
475             addrs.push_back(0x0023); values.push_back(reg23val & ~PHCFG_START);
476             if (WriteRegisters(addrs.data(), values.data(), values.size()) != 0)
477                 lime::error("SetPllFrequency: configure FPGA PLL, failed to write registers");
478             return (!done) || error ? -1 : 0;
479         }
480     }
481     return 0;
482 }
483 
SetDirectClocking(int clockIndex)484 int FPGA::SetDirectClocking(int clockIndex)
485 {
486     if(not connection)
487         return ReportError(ENODEV, "SetDirectClocking: connection port is NULL");
488     if(not connection->IsOpen())
489         return ReportError(ENODEV, "SetDirectClocking: device not connected");
490 
491     uint16_t drct_clk_ctrl_0005 = ReadRegister(0x0005);
492     vector<uint32_t> addres;
493     vector<uint32_t> values;
494     //enable direct clocking
495     addres.push_back(0x0005); values.push_back(drct_clk_ctrl_0005 | (1 << clockIndex));
496     if(WriteRegisters(addres.data(), values.data(), values.size()) != 0)
497         return ReportError(EIO, "SetDirectClocking: failed to write registers");
498     return 0;
499 }
500 
501 /** @brief Parses FPGA packet payload into samples
502 */
FPGAPacketPayload2Samples(const uint8_t * buffer,int bufLen,bool mimo,bool compressed,complex16_t ** samples)503 int FPGA::FPGAPacketPayload2Samples(const uint8_t* buffer, int bufLen, bool mimo, bool compressed, complex16_t** samples)
504 {
505     if(compressed) //compressed samples
506     {
507         int16_t sample;
508         int collected = 0;
509         for(int b=0; b<bufLen;collected++)
510         {
511             //I sample
512             sample = buffer[b++];
513             sample |= (buffer[b] << 8);
514             sample <<= 4;
515             samples[0][collected].i = sample >> 4;
516             //Q sample
517             sample =  buffer[b++];
518             sample |= buffer[b++] << 8;
519             samples[0][collected].q = sample >> 4;
520             if (mimo)
521             {
522                 //I sample
523                 sample = buffer[b++];
524                 sample |= (buffer[b] << 8);
525                 sample <<= 4;
526                 samples[1][collected].i = sample >> 4;
527                 //Q sample
528                 sample =  buffer[b++];
529                 sample |= buffer[b++] << 8;
530                 samples[1][collected].q = sample >> 4;
531             }
532         }
533         return collected;
534     }
535 
536     if (mimo) //uncompressed samples
537     {
538         complex16_t* ptr = (complex16_t*)buffer;
539         const int collected = bufLen/sizeof(complex16_t)/2;
540         for(int i=0; i<collected;i++)
541         {
542             samples[0][i] = *ptr++;
543             samples[1][i] = *ptr++;
544         }
545         return collected;
546     }
547 
548     memcpy(samples[0],buffer,bufLen);
549     return bufLen/sizeof(complex16_t);
550 }
551 
Samples2FPGAPacketPayload(const complex16_t * const * samples,int samplesCount,bool mimo,bool compressed,uint8_t * buffer)552 int FPGA::Samples2FPGAPacketPayload(const complex16_t* const* samples, int samplesCount, bool mimo, bool compressed, uint8_t* buffer)
553 {
554     if(compressed)
555     {
556         int b=0;
557         for(int src=0; src<samplesCount; ++src)
558         {
559             buffer[b++] = samples[0][src].i;
560             buffer[b++] = ((samples[0][src].i >> 8) & 0x0F) | (samples[0][src].q << 4);
561             buffer[b++] = samples[0][src].q >> 4;
562             if (mimo)
563             {
564                 buffer[b++] = samples[1][src].i;
565                 buffer[b++] = ((samples[1][src].i >> 8) & 0x0F) | (samples[1][src].q << 4);
566                 buffer[b++] = samples[1][src].q >> 4;
567             }
568         }
569         return b;
570     }
571 
572     if (mimo)
573     {
574         complex16_t* ptr = (complex16_t*)buffer;
575         for(int src=0; src<samplesCount; ++src)
576         {
577             *ptr++ = samples[0][src];
578             *ptr++ = samples[1][src];
579         }
580         return samplesCount*2*sizeof(complex16_t);
581     }
582     memcpy(buffer,samples[0],samplesCount*sizeof(complex16_t));
583     return samplesCount*sizeof(complex16_t);
584 }
585 
UploadWFM(const void * const * samples,uint8_t chCount,size_t sample_count,StreamConfig::StreamDataFormat format,int epIndex)586 int FPGA::UploadWFM(const void* const* samples, uint8_t chCount, size_t sample_count, StreamConfig::StreamDataFormat format, int epIndex)
587 {
588     bool comp = (epIndex==2 && format!=StreamConfig::FMT_INT12) ? false : true;
589 
590     const int samplesInPkt = comp ? samples12InPkt : samples16InPkt;
591     WriteRegister(0xFFFF, 1 << epIndex);
592     WriteRegister(0x000C, chCount == 2 ? 0x3 : 0x1); //channels 0,1
593     WriteRegister(0x000E, comp ? 0x2 : 0x0); //16bit samples
594 
595     uint16_t regValue = ReadRegister(0x000D);
596     regValue |= 0x4;
597     WriteRegister(0x000D, regValue);
598 
599     lime::FPGA_DataPacket pkt;
600     size_t samplesUsed = 0;
601     int cnt = sample_count;
602 
603     const complex16_t* const* src = (const complex16_t* const*)samples;
604     const lime::complex16_t** batch = new const lime::complex16_t*[chCount];
605     lime::complex16_t** samplesShort = new lime::complex16_t*[chCount];
606     for(unsigned i=0; i<chCount; ++i)
607         samplesShort[i] = nullptr;
608 
609     if (format == StreamConfig::FMT_INT16 && comp == true)
610     {
611         for(unsigned i=0; i<chCount; ++i)
612             samplesShort[i] = new lime::complex16_t[sample_count];
613         for (int ch = 0; ch < chCount; ch++)
614             for(size_t i=0; i < sample_count; ++i)
615             {
616                 samplesShort[ch][i].i = src[ch][i].i >> 4;
617                 samplesShort[ch][i].q = src[ch][i].q >> 4;
618             }
619         src = samplesShort;
620     }
621     else if(format == StreamConfig::FMT_FLOAT32)
622     {
623         const float mult = comp ? 2047.0f : 32767.0f;
624         for(unsigned i=0; i<chCount; ++i)
625             samplesShort[i] = new lime::complex16_t[sample_count];
626 
627         const float* const* samplesFloat = (const float* const*)samples;
628         for (int ch = 0; ch < chCount; ch++)
629             for(size_t i=0; i < sample_count; ++i)
630             {
631                 samplesShort[ch][i].i = samplesFloat[ch][2*i]*mult;
632                 samplesShort[ch][i].q = samplesFloat[ch][2*i+1]*mult;
633             }
634         src = samplesShort;
635     }
636 
637     while(cnt > 0)
638     {
639         pkt.counter = 0;
640         pkt.reserved[0] = 0;
641         int samplesToSend = cnt > samplesInPkt/chCount ? samplesInPkt/chCount : cnt;
642 
643         for(unsigned i=0; i<chCount; ++i)
644             batch[i] = &src[i][samplesUsed];
645         samplesUsed += samplesToSend;
646 
647         int bufPos = Samples2FPGAPacketPayload(batch, samplesToSend, chCount==2, comp, pkt.data);
648         int payloadSize = (bufPos / 4) * 4;
649         if(bufPos % 4 != 0)
650             lime::warning("Packet samples count not multiple of 4");
651         pkt.reserved[2] = (payloadSize >> 8) & 0xFF; //WFM loading
652         pkt.reserved[1] = payloadSize & 0xFF; //WFM loading
653         pkt.reserved[0] = 0x1 << 5; //WFM loading
654 
655         long bToSend = 16+payloadSize;
656         if (connection->SendData((const char*)&pkt,bToSend,epIndex,500)!=bToSend)
657             break;
658         cnt -= samplesToSend;
659     }
660     delete[] batch;
661     for(unsigned i=0; i<chCount; ++i)
662         if (samplesShort[i])
663             delete [] samplesShort[i];
664     delete[] samplesShort;
665 
666     /*Give some time to load samples to FPGA*/
667     std::this_thread::sleep_for(std::chrono::milliseconds(500));
668     connection->AbortSending(epIndex);
669     if(cnt == 0)
670         return 0;
671     else
672         return ReportError(-1, "Failed to upload waveform");
673 }
674 
675 
676 /** @brief Configures FPGA PLLs to LimeLight interface frequency
677 */
SetInterfaceFreq(double txRate_Hz,double rxRate_Hz,double txPhase,double rxPhase,int channel)678 int FPGA::SetInterfaceFreq(double txRate_Hz, double rxRate_Hz, double txPhase, double rxPhase, int channel)
679 {
680     lime::FPGA::FPGA_PLL_clock clocks[2];
681     int status = 0;
682 
683     const uint32_t addr = (0x02A<<16);
684     uint32_t val;
685     val = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFD; //msbit 1=SPI write
686     connection->WriteLMS7002MSPI(&val, 1, channel);
687     connection->ReadLMS7002MSPI(&addr, &val, 1, channel);
688     bool bypassTx = (val&0xF0) == 0x00;
689     bool bypassRx = (val&0x0F) == 0x0D;
690 
691     if  (rxRate_Hz >= 5e6)
692     {
693         clocks[0].index = 0;
694         clocks[0].outFrequency = bypassRx ? 2*rxRate_Hz:rxRate_Hz;
695         clocks[1].index = 1;
696         clocks[1].outFrequency = bypassRx ? 2*rxRate_Hz:rxRate_Hz;
697         clocks[1].phaseShift_deg = rxPhase;
698         status = SetPllFrequency(1, rxRate_Hz, clocks, 2);
699     }
700     else
701         status = SetDirectClocking(1);
702 
703     if (txRate_Hz >= 5e6)
704     {
705         clocks[0].index = 0;
706         clocks[0].outFrequency = bypassTx ? 2*txRate_Hz:txRate_Hz;
707         clocks[1].index = 1;
708         clocks[1].outFrequency = bypassTx ? 2*txRate_Hz:txRate_Hz;
709         clocks[1].phaseShift_deg = txPhase;
710         status |= SetPllFrequency(0, txRate_Hz, clocks, 2);
711     }
712     else
713         status |= SetDirectClocking(0);
714     return status;
715 }
716 
717 /** @brief Configures FPGA PLLs to LimeLight interface frequency
718 */
SetInterfaceFreq(double txRate_Hz,double rxRate_Hz,int channel)719 int FPGA::SetInterfaceFreq(double txRate_Hz, double rxRate_Hz, int channel)
720 {
721     const int pll_ind = (channel == 1) ? 2 : 0;
722     int status = 0;
723     uint32_t reg20;
724     bool bypassTx = false;
725     bool bypassRx = false;
726     const double rxPhC1 =  89.46;
727     const double rxPhC2 =  1.24e-6;
728     const double txPhC1 =  89.61;
729     const double txPhC2 =  2.71e-7;
730 
731     const std::vector<uint32_t> spiAddr = { 0x021, 0x022, 0x023, 0x024, 0x027, 0x02A, 0x82,
732                                             0x400, 0x40C, 0x40B, 0x400, 0x40B, 0x400};
733     const int bakRegCnt = spiAddr.size() - 4;
734 
735     bool phaseSearch = false;
736     //if (!(mStreamers.size() > channel && (mStreamers[channel]->rxRunning || mStreamers[channel]->txRunning)))
737     if(rxRate_Hz >= 5e6 && txRate_Hz >= 5e6)
738     {
739         uint32_t addr[3] = {0, 1, 2};
740         uint32_t vals[3];
741         ReadRegisters(addr,vals,3);
742         vals[1] = (vals[1]<<8)|vals[2];
743         if ((vals[0]==0xE && vals[1]>0x20E)||(vals[0]==0xF && vals[1]>0x206)||(vals[0]==0x10 && vals[1]>0x102)||vals[0]==0x17)
744             phaseSearch = true;
745     }
746 
747     if (!phaseSearch)
748         return SetInterfaceFreq(txRate_Hz, rxRate_Hz, txPhC1 + txPhC2 * txRate_Hz, rxPhC1 + rxPhC2 * rxRate_Hz, channel);
749 
750     std::vector<uint32_t> dataRdA;
751     std::vector<uint32_t> dataRdB;
752     std::vector<uint32_t> dataWr;
753 
754     dataWr.resize(spiAddr.size());
755     dataRdA.resize(bakRegCnt);
756     dataRdB.clear();
757     //backup registers
758     dataWr[0] = (uint32_t(0x0020) << 16);
759     connection->ReadLMS7002MSPI(dataWr.data(), &reg20, 1, channel);
760 
761     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFD; //msbit 1=SPI write
762     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
763 
764     for (int i = 0; i < bakRegCnt; ++i)
765         dataWr[i] = (spiAddr[i] << 16);
766     connection->ReadLMS7002MSPI(dataWr.data(),dataRdA.data(), bakRegCnt, channel);
767 
768     {
769         const uint32_t addr = (0x02A<<16);
770         uint32_t val;
771         connection->ReadLMS7002MSPI(&addr, &val, 1, channel);
772         bypassTx = (val&0xF0) == 0x00;
773         bypassRx = (val&0x0F) == 0x0D;
774     }
775 
776     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFE; //msbit 1=SPI write
777     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
778 
779     for (int i = 0; i < bakRegCnt; ++i)
780         if (spiAddr[i] >= 0x100)
781             dataRdB.push_back(spiAddr[i] << 16);
782     connection->ReadLMS7002MSPI(dataRdB.data(), dataRdB.data(), dataRdB.size(), channel);
783 
784     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFF; //msbit 1=SPI write
785     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
786 
787     {
788         std::vector<uint32_t> spiData = { 0x0E9F, 0x0FFF, 0x5550, 0xE4E4, 0xE4E4, 0x0086, 0x8001,
789                                           0x028D, 0x00FF, 0x5555, 0x02CD, 0xAAAA, 0x02ED};
790         if (bypassRx)spiData[5] = 0xD;
791         //Load test config
792         const int setRegCnt = spiData.size();
793         for (int i = 0; i < setRegCnt; ++i)
794             dataWr[i] = (1 << 31) | (uint32_t(spiAddr[i]) << 16) | spiData[i]; //msbit 1=SPI write
795         connection->WriteLMS7002MSPI(dataWr.data(), setRegCnt, channel);
796     }
797 
798     bool phaseSearchSuccess = false;
799     lime::FPGA::FPGA_PLL_clock clocks[2];
800 
801     for (int i = 0; i < 10; i++)    //attempt phase search 10 times
802     {
803     	clocks[0].index = 1;
804     	clocks[0].outFrequency = bypassRx ? 2*rxRate_Hz : rxRate_Hz;
805     	clocks[0].phaseShift_deg = rxPhC1 + rxPhC2 * rxRate_Hz;
806     	clocks[0].findPhase = true;
807     	clocks[1] = clocks[0];
808     	if (SetPllFrequency(pll_ind+1, rxRate_Hz, clocks, 2)==0)
809 	{
810 	    phaseSearchSuccess = true;
811 	    break;
812 	}
813     }
814 
815     if (!phaseSearchSuccess)
816     {
817 	lime::error("LML RX phase search FAIL");
818 	status = -1;
819         clocks[0].index = 0;
820         clocks[0].phaseShift_deg = 0;
821         clocks[0].findPhase = false;
822         clocks[1].findPhase = false;
823         SetPllFrequency(pll_ind+1, rxRate_Hz, clocks, 2);
824     }
825 
826     {
827         std::vector<uint32_t> spiData = {0x0E9F, 0x0FFF, 0x5550, 0xE4E4, 0xE4E4, 0x0484, 0x8001};
828         if (bypassTx)spiData[5] ^= 0x80;
829         if (bypassRx)spiData[5] ^= 0x9;
830         WriteRegister(0xFFFF, 1 << channel);
831         WriteRegister(0x000A, 0x0000);
832         //Load test config
833         const int setRegCnt = spiData.size();
834         for (int i = 0; i < setRegCnt; ++i)
835             dataWr[i] = (1 << 31) | (uint32_t(spiAddr[i]) << 16) | spiData[i]; //msbit 1=SPI write
836         connection->WriteLMS7002MSPI(dataWr.data(), setRegCnt, channel);
837     }
838 
839     phaseSearchSuccess = false;
840     for (int i = 0; i < 10; i++)  //attempt phase search 10 times
841     {
842 	 clocks[0].index = 1;
843 	 clocks[0].outFrequency = bypassTx ? 2*txRate_Hz:txRate_Hz;
844 	 clocks[0].phaseShift_deg = txPhC1 + txPhC2 * txRate_Hz;
845 	 clocks[0].findPhase = true;
846 	 clocks[1] = clocks[0];
847 	 WriteRegister(0x000A, 0x0200);
848    	 if (SetPllFrequency(pll_ind, txRate_Hz, clocks, 2)==0)
849 	 {
850 	     phaseSearchSuccess = true;
851 	     break;
852 	 }
853     }
854 
855     if (!phaseSearchSuccess)
856     {
857         lime::error("LML TX phase search FAIL");
858         status = -1;
859         clocks[0].index = 0;
860         clocks[0].phaseShift_deg = 0;
861         clocks[0].findPhase = false;
862         clocks[1].findPhase = false;
863         SetPllFrequency(pll_ind, txRate_Hz, clocks, 2);
864     }
865 
866     //Restore registers
867     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFD; //msbit 1=SPI write
868     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
869     for (int i = 0; i < bakRegCnt; ++i)
870         dataWr[i] = (1 << 31) | (uint32_t(spiAddr[i]) << 16) | dataRdA[i]; //msbit 1=SPI write
871     connection->WriteLMS7002MSPI(dataWr.data(), bakRegCnt, channel);
872     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | 0xFFFE; //msbit 1=SPI write
873     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
874 
875     int k = 0;
876     for (int i = 0; i < bakRegCnt; ++i)
877         if (spiAddr[i] >= 0x100){
878             dataWr[k] = (1 << 31) | (uint32_t(spiAddr[i]) << 16) | dataRdB[k]; //msbit 1=SPI write
879             k++;
880         }
881     connection->WriteLMS7002MSPI(dataWr.data(), k, channel);
882     dataWr[0] = (1 << 31) | (uint32_t(0x0020) << 16) | reg20; //msbit 1=SPI write
883     connection->WriteLMS7002MSPI(dataWr.data(), 1, channel);
884     WriteRegister(0x000A, 0);
885 
886     return status;
887 }
888 
ReadRawStreamData(char * buffer,unsigned length,int epIndex,int timeout_ms)889 int FPGA::ReadRawStreamData(char* buffer, unsigned length, int epIndex, int timeout_ms)
890 {
891     WriteRegister(0xFFFF, 1 << epIndex);
892     StopStreaming();
893     connection->ResetStreamBuffers();
894     WriteRegister(0x0008, 0x0100 | 0x2);
895     WriteRegister(0x0007, 1);
896     StartStreaming();
897     int totalBytesReceived = connection->ReceiveData(buffer,length, epIndex, timeout_ms);
898     StopStreaming();
899     connection->AbortReading(epIndex);
900     return totalBytesReceived;
901 }
902 
DetectRefClk(double fx3Clk)903 double FPGA::DetectRefClk(double fx3Clk)
904 {
905     const double fx3Cnt = 16777210;         //fixed fx3 counter in FPGA
906     const double clkTbl[] = { 10e6, 30.72e6, 38.4e6, 40e6, 52e6 };
907     const uint32_t addr[] = { 0x61, 0x63 };
908     const uint32_t vals[] = { 0x0, 0x0 };
909     if (WriteRegisters(addr, vals, 2) != 0)
910         return -1;
911 
912     auto start = std::chrono::steady_clock::now();
913     if (WriteRegister(0x61, 0x4) != 0)
914         return -1;
915 
916     while (1) //wait for test to finish
917     {
918         int completed = ReadRegister(0x65);
919         if (completed < 0)
920             return -1;
921         if (completed & 0x4)
922             break;
923 
924         auto end = std::chrono::steady_clock::now();
925         std::chrono::duration<double> elapsed_seconds = end - start;
926         if (elapsed_seconds.count() > 0.5) //timeout
927             return -1;
928     }
929 
930     const uint32_t addr2[] = { 0x72, 0x73 };
931     uint32_t vals2[2];
932     if (ReadRegisters(addr2, vals2, 2) != 0)
933         return -1;
934 
935     double count = (vals2[0] | (vals2[1] << 16)); //cock counter
936     count *= fx3Clk / fx3Cnt;   //estimate ref clock based on FX3 Clock
937     lime::debug("Estimated reference clock %1.4f MHz", count/1e6);
938     unsigned i = 0;
939     double delta = 100e6;
940 
941     while (i < sizeof(clkTbl) / sizeof(*clkTbl))
942         if (delta < fabs(count - clkTbl[i]))
943             break;
944         else
945             delta = fabs(count - clkTbl[i++]);
946 
947     if (i == 0)
948         return -1;
949     lime::info("Reference clock %1.2f MHz", clkTbl[i - 1] / 1e6);
950     return clkTbl[i - 1];
951 }
952 
953 } //namespace lime
954