iCub-main
Loading...
Searching...
No Matches
strain.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 iCub Facility - Istituto Italiano di Tecnologia
3 * Author: Marco Accame
4 * email: marco.accame@iit.it
5 * website: www.robotcub.org
6 * Permission is granted to copy, distribute, and/or modify this program
7 * under the terms of the GNU General Public License, version 2 or any
8 * later version published by the Free Software Foundation.
9 *
10 * A copy of the license can be found at
11 * http://www.robotcub.org/icub/license/gpl.txt
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details
17*/
18
19
20// --------------------------------------------------------------------------------------------------------------------
21// - public interface
22// --------------------------------------------------------------------------------------------------------------------
23
24#include "strain.h"
25
26
27
28// --------------------------------------------------------------------------------------------------------------------
29// - external dependencies
30// --------------------------------------------------------------------------------------------------------------------
31
32#include <cstring>
33#include <vector>
34#include <fstream>
35
36using namespace std;
37
38
39
40// --------------------------------------------------------------------------------------------------------------------
41// - pimpl: private implementation (see scott meyers: item 22 of effective modern c++, item 31 of effective c++
42// --------------------------------------------------------------------------------------------------------------------
43
44// so let me introduce to you the one and only .... pimpl
45
46
47#define IMPORT_CODE_FROM_EMBOT_HW_PGA308
48
50{
51
52 // marco.accame on 27jul18: i decide to use code already developed (and very well tested ....) in:
53 // namespace embot { namespace hw { namespace PGA308 {
54 // i encapluslate it under a different scope (this Impl) and I remove dependency from can protocol
55 // by changing: embot::app::canprotocol::analog::polling::PGA308cfg1
56 // with: strain::amplifier::PGA308::Registers
57 // teh two structs have the same bitmap layout. but Registers also have methods to import from and export to a can packet
58
59#if defined(IMPORT_CODE_FROM_EMBOT_HW_PGA308)
60
62 {
63 std::uint16_t value;
64 static const std::uint16_t Default = 0x8000;
65
66 // ZDAC Register: Zero DAC Register (Fine Offset Adjust)
67 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
68 // content: ZD15 ZD14 ZD13 ZD12 ZD11 ZD10 ZD9 ZD8 ZD7 ZD6 ZD5 ZD4 ZD3 ZD2 ZD1 ZD0
69 // teh value x contained in the register is mapped into: +VREF/2 – (x/65536) (VREF)
70 // the possible ranges of the offset is [+VREF*0.5, -VREF*0.4999847]
71
73
74 ZDACregister(std::uint16_t v) : value(v) {}
75
76 void reset() { value = 0; }
77
78 void set(std::uint16_t zdac) { value = zdac; }
79
81 };
82
84 {
85 std::uint16_t value;
86 static const std::uint16_t Default = 0x4000;
87
88 // GDAC Register: Gain DAC Register
89 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
90 // content: GD15 GD14 GD13 GD12 GD11 GD10 GD9 GD8 GD7 GD6 GD5 GD4 GD3 GD2 GD1 GD0
91 // the value x contained in the register is mapped into: 0.333333333 + x * (1.000000000 – 0.333333333) / 65536 = 0.333333333 + x * 1.0172526 * 10–5
92 // value of register x is: (DesiredGain – 0.333333333) / (1.0172526 x 10–5)
93 // the range of gain is [0.333333333, 0.999989824] and GDACregister::Default is 0.499999999
94
96
97 GDACregister(std::uint16_t v) : value(v) {}
98
99 void reset() { value = 0; }
100
101 void set(std::uint16_t gdac) { value = gdac; }
102
104 };
105
107 {
108 std::uint16_t value;
109
110 static const std::uint8_t DefaultGO = 0x06; // output gain = 6.0 (0x06) OR 2.0 (0x00)
111 static const std::uint8_t DefaultGO_g_32_96 = 0x06; // output gain = 6.0 (0x06)
112 static const std::uint8_t DefaultGO_g_16_80 = 0x02; // output gain = 3.0 (0x02)
113 static const std::uint8_t DefaultGO_g_11_75 = 0x00; // output gain = 3.0 (0x00)
114 static const std::uint8_t DefaultMUX = 0x00; // VIN1= VINPositive, VIN2= VINNegative
115 static const std::uint8_t DefaultGI = 0x04; // input gain = 16
116 static const std::uint8_t DefaultOS = 0x20; // coarse offset // 0x25 0x8A
117
118 // CFG0 Output Amplifier Gain Select, Front-End PGA Mux & Gain Select, Coarse Offset Adjust on Front-End PGA
119 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
120 // content: GO2 GO1 GO0 GI4 GI3 GI2 GI1 GI0 OS7 OS6 OS5 OS4 OS3 OS2 OS1 OS0
121
123
124 CFG0register(std::uint8_t GO, std::uint8_t MUX, std::uint8_t GI, std::uint8_t OS)
125 {
126 value = 0;
127 setGO(GO);
128 setMUX(MUX);
129 setGI(GI);
130 setOS(OS);
131 }
132
133 CFG0register(std::uint16_t v) : value(v) {}
134
135 void reset() { value = 0; }
136
138
139 // Output Amplifier Gain Select: [GO2-GO0] -> from 000b to 111b: 2.0, 2.4, 3, 3.6, 4.0, 4.5, 6.0 disable-internal-feedback
140 void setGO(std::uint8_t GO) { value |= (static_cast<std::uint8_t>(GO&0x07) << 13); }
141 std::uint8_t getGO() const { return ((value >> 13) & 0x07); }
142
143 // Front-End PGA Mux Select: [GI4] -> 0 is [VIN1= VINN, VIN2= VINP], 1 is [VIN1= VINP, VIN2= VINN]
144 void setMUX(std::uint8_t MUX) { value |= (static_cast<std::uint8_t>(MUX&0x01) << 12); }
145 std::uint8_t getMUX() const { return ((value >> 12) & 0x01); }
146
147 // Front-End PGA Gain Select: [GI3-GI0] -> from 0000b to 1101b: 4 6 8 12 16 32 64 100 200 400 480 600 800 960 1200 1600
148 void setGI(std::uint8_t GI) { value |= (static_cast<std::uint8_t>(GI&0x0f) << 8); }
149 std::uint8_t getGI() const { return ((value >> 8) & 0x0f); }
150
151 // Coarse Offset Adjust on Front-End PGA: [OS7-OS0] where OS7 is sign (0 is +) and [OS6-OS0] is value. valid range is only x = [-100, +100]
152 // which maps into (x/128)(Vref)(0.0256) for a global offset range of [-0.02*V_REF, +0.02*V_REF]. V_REF is in register CFG2.COSVR[1:0]
153 void setOS(std::uint8_t OS) { value |= (static_cast<std::uint8_t>(OS&0xff)); }
154 std::uint8_t getOS() const { return ((value) & 0xff); }
155
156 };
157
158
160 {
161 std::uint16_t value;
162 static const std::uint16_t Default = 0x0000;
163
164 // CFG1 Register: Configuration Register 1
165 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
166 // content: FLT-REF FLT-IPU OU-CFG FLT-SEL CMP-SEL EXT-EN INT-EN EXT-POL INT-POL OU-EN HL2 HL1 HL0 LL2 LL1 LL0
167
169
170 CFG1register(std::uint16_t v) : value(v) {}
171
172 void reset() { value = 0; }
173
174 void set(std::uint16_t cfg1) { value = cfg1; }
175
177 };
178
180 {
181 std::uint16_t value;
182 static const std::uint16_t Default = 0x0400;
183
184 // CFG2 Register: Configuration Register 2
185 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
186 // content: OWD OWD-OFF DIS-OUT NOW COSVR1 COSVR0 RESERVD DOUTSEL DOUT SD RESERVD RESERVD RESERVD RESERVD RESERVD RESERVD
187 // COSVR: 00 -> ; 01-> ; 10 -> ; 11 -> ;
188 // with COSVR = 01b, as in our Default ... we have:
189 // - Coarse Offset Range = [2.4, 3.6] V
190 // - Coarse Offset Resolution = (1/128)(VREF)(0.0427)
191 // - Coarse Offset Range = (±100mV)(VREF/3)
193
194 CFG2register(std::uint16_t v) : value(v) {}
195
196 void reset() { value = 0; }
197
198 void set(std::uint16_t cfg2) { value = cfg2; }
199
201 };
202
203
205 {
206 std::uint16_t value;
207 static const std::uint16_t Default = 0x0050; // where ... there is the SOFTWARE LOCK MODE (Runs from RAM) and the PGA308 operates from data written into the RAM registers from the user
208
209 // SFTC Register: Software Control
210 // bit: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
211 // content: RESERVD RESERVD RESERVD RESERVD RESERVD RESERVD RESERVD CHKSFLG OW-DLY SW-L2 SW-L1 SW-L0 RFB0 XP5 XP4 XP3
212 // brief description:
213 // CHKSFLG: Register Checksum Bit (Read-only) 1 = register checksum correct
214 // OW-DLY: One-Wire Delay Bit 1 = 8-bit delay from transmit to receive during One-Wire reads, 0 = 1-bit delay from transmit to receive during One-Wire reads
215 // SWL[2:0] Software Lock Mode Control 101b = SOFTWARE LOCK (Runs from RAM), etc....
216 // XP[5:3] OTP Bank Selection for Software Lock Mode If XP[5:3] = '000', then the PGA308 operates from data written into the RAM registers from the user.
218
219 SFTCregister(std::uint16_t v) : value(v) {}
220
221 void reset() { value = 0; }
222
223 void set(std::uint16_t sftc) { value = sftc; }
224
226 };
227
228
229
230
232 {
233
234 static const std::uint16_t VREF = 8192; // the allowed values are in range [0, VREF). it must be constant ...
235
236 std::uint16_t GD; // gain DAC. values are [0.333333333, 0.999989824]
237 std::uint8_t GI : 4; // front end gain. from 0000b to 1101b: {4 6 8 12 16 32 64 100 200 400 480 600 800 960 1200 1600}
238 std::uint8_t muxsign : 1; // the sign: 0 is +, 1 is -
239 std::uint8_t GO : 3; // output gain. from 000b to 111b: {2.0, 2.4, 3, 3.6, 4.0, 4.5, 6.0, disable-internal-feedback}
240 std::uint8_t Vcoarseoffset; // Vcoarseoffset is stored as sign+value and must be in range [-100, +100].
241 std::uint16_t Vzerodac;
242
243 enum class Parameter { GD = 0, GI = 1, muxsign = 2, GO = 3, Vcoarseoffset = 4, Vzerodac = 5 };
244
245 // the formulas are:
246 //
247 // from Vin to Vout
248 // Vout = ((muxsign*Vin + Vcoarseoffset)*GI + Vzerodac)*GD*GO
249 // Vout = alpha * Vin + beta
250 // alpha = muxsign*GI*GD*GO
251 // beta = (Vcoarseoffset*GI + Vzerodac)*GD*GO
252 //
253 // we use only three variables x, y, z and we keep the other fixed to default ...
254 // x -> content of register GDAC (.GD)
255 // y -> content of register CFG0.OS (.Vcoarseoffset)
256 // z -> content of register ZDAC (.Vzerodac)
257 // we thus have:
258 // alpha(x) = valueOf(GI) * valueOf(GO) * ((1/3) + ((2/3)/64k) * x)
259 // beta(x, y, z) = alpha(x) * ((1/128)*VREF*COSVR*y + (1/valueOf(GI))*VREF*(1/64k)(32k - z))
260 // for some operations we need to represent Vout as a function only of y and z, hence
261 // Vout = a * y + b * z + c
262 // a = (d/dy) Vout = (d/dy) beta = alpha(x)*(1/128)*VREF*COSVR
263 // b = (d/dz) Vout = (d/dz) beta = - alpha(x)*(1/valueOf(GI))*VREF*(1/64k)
264 // c = Vout - a*y - b*z
265
266
268
269 void load(const Registers &regs)
270 {
271 GD = regs.GD;
272 GI = regs.GI;
273 muxsign = regs.S;
274 GO = regs.GO;
276 Vzerodac = regs.Vzerodac;
277 }
278
279 void get(Registers &regs)
280 {
281 regs.GD = GD;
282 regs.GI = GI;
283 regs.S = muxsign;
284 regs.GO = GO;
286 regs.Vzerodac = Vzerodac;
287 }
288
298
299 // from internal memory to the values of the registers to be written into the amplifier
300 void obtain(CFG0register &cfg0, ZDACregister &zdac, GDACregister &gdac) const
301 {
302 cfg0.reset(); cfg0.setGO(GO); cfg0.setMUX(muxsign); cfg0.setGI(GI); cfg0.setOS(Vcoarseoffset);
303 zdac.reset(); zdac.value = Vzerodac;
304 gdac.reset(); gdac.value = GD;
305 }
306
307 // from the registers read from the amplifier to internal memory.
308 void assign(const CFG0register &cfg0, const ZDACregister &zdac, const GDACregister &gdac)
309 {
310 GO = cfg0.getGO();
311 muxsign = cfg0.getMUX();
312 GI = cfg0.getGI();
313 Vcoarseoffset = cfg0.getOS();
314 Vzerodac = zdac.value;
315 GD = gdac.value;
316 }
317
318 void load(const CFG0register &cfg0)
319 {
320 GO = cfg0.getGO();
321 muxsign = cfg0.getMUX();
322 GI = cfg0.getGI();
323 Vcoarseoffset = cfg0.getOS();
324 }
325
326 void load(const ZDACregister &zdac)
327 {
328 Vzerodac = zdac.value;
329 }
330
331 void load(const GDACregister &gdac)
332 {
333 GD = gdac.value;
334 }
335
336 float valueOfGI()
337 {
338 static const std::uint16_t mapGI2val[16] = {4, 6, 8, 12, 16, 32, 64, 100, 200, 400, 480, 600, 800, 960, 1200, 1600};
339 return static_cast<float>(mapGI2val[GI]);
340 }
341
342 float valueOfGO()
343 {
344 static const float mapGO2val[8] = {2.0f, 2.4f, 3.0f, 3.6f, 4.0f, 4.5f, 6.0f, 1.0f};
345 return mapGO2val[GO];
346 }
347
348 float valueOfGD()
349 {
350 //return 0.33333f + (static_cast<float>(GD) * 0.66666f) / 65536.0f;
351 //return (1.0f + static_cast<float>(GD)/32768.0f)/3.0f;
352 return valueOfGD(GD);
353 }
354
355 float valueOfGD(std::uint16_t x)
356 {
357 //return 0.33333f + (static_cast<float>(GD) * 0.66666f) / 65536.0f;
358 return (1.0f + static_cast<float>(x)/32768.0f)/3.0f;
359 }
360
362 {
363 //static const float mapCOSVR2val[4] = {0.064f, 0.0427f, 0.0320f, 0.0256f};
364 //std::uint8_t cosvr2 = 1;
365 //return static_cast<float>(VREF)*(1.0f/128.0f)*mapCOSVR2val[cosvr2];
366 return 2.7328f;
367 }
368
369 float regvco2value(std::uint8_t co)
370 { // regvco is inside [-100, +100] in sign-value format
371 std::uint8_t v = co & 0x7f;
372 if(v > 100) { v = 100; }
373 std::uint8_t negative = co >> 7;
374 return (1 == negative) ? -v : +v;
375 }
376
377 std::uint8_t value2regvco(float v)
378 { // regvco is inside [-100, +100] in sign-value format
379 std:: uint8_t r = 0;
380 if(v > 0)
381 {
382 v = std::floor(v + 0.5f);
383 if(v > +100.0f) { v = +100.0f; }
384 r = static_cast<std::uint8_t>(v);
385 }
386 else
387 {
388 v = -v;
389 v = std::floor(v + 0.5f);
390 if(v > +100.0f) { v = +100.0f; }
391 r = static_cast<std::uint8_t>(v) | 0x80;
392 }
393
394 return r;
395 }
396
398 {
400 }
401
403 {
404 return static_cast<float>(VREF)*(1.0f/65536.0f)*(32768.0f - static_cast<float>(Vzerodac));
405 //return static_cast<float>(VREF)*(0.0000152587890625f)*(32768.0f - static_cast<float>(Vzerodac));
406 }
407
408 float alpha()
409 {
410 //float v = valueOfGD()*valueOfGO()*valueOfGI();
411 //return (0 == muxsign) ? v : -v;
412 return alpha(GD);
413 }
414
415 float alpha(std::uint16_t x)
416 {
417 float v = valueOfGD(x)*valueOfGO()*valueOfGI();
418 return (0 == muxsign) ? v : -v;
419 }
420
421 float beta()
422 {
423 float gi = valueOfGI();
424 return alpha()*(valueOfCoarseOffset() + valueOfFineOffset()/gi);
425 }
426
427 void computeOffsetParams(const std::uint16_t vout, float &a, float &b, float &c)
428 {
429 // a = (d/dy) Vout = (d/dy) beta = alpha(x)*(1/128)*VREF*COSVR = alpha(x) * COR
430 // b = (d/dz) Vout = (d/dz) beta = - alpha(x)*(1/valueOf(GI))*VREF*(1/64k)
431 // c = Vout - a*y - b*z
432 a = alpha() * valueOfCOR();
433 b = - (alpha()*static_cast<float>(VREF)/valueOfGI())/65536.0f; // valueOfGI() is always != 0
434 c = static_cast<float>(vout) - a*regvco2value(Vcoarseoffset) - b*static_cast<float>(Vzerodac);
435 }
436
437 bool alignVOUT(const std::uint16_t vout, const std::uint16_t target, std::uint8_t &Y, std::uint16_t &Z)
438 {
439 float a, b, c;
440 computeOffsetParams(vout, a, b, c);
441 float y = (target - c - b*static_cast<float>(Vzerodac))/a; // a is always != 0
442
443 // round and limit y ... which must be integer and inside [-100, +100] and
444 std::uint8_t tmp = value2regvco(y);
445 y = regvco2value(tmp);
446
447 // must apply new y to ...
448 float z = (target - c - a*y)/b;
449 if((z > 65535.0f) || (z < 0.0f))
450 {
451 return false;
452 }
453 Y = value2regvco(y);
454 Z = static_cast<std::uint16_t>(std::floor(z + 0.5f));
455 Vcoarseoffset = Y;
456 Vzerodac = Z;
457
458 return true;
459 }
460
461 bool setalpha(float a)
462 {
463 float xgd = 98304.0f * (a/(valueOfGI()*valueOfGO()) - (1.0f/3.0f));
464 std::int32_t x = static_cast<std::int32_t>(std::floor(xgd + 0.5f));
465 if((x >= 65536) || (x < 0))
466 {
467 return false;
468 }
469 GD = static_cast<std::uint16_t>(x);
470 return true;
471 }
472
473 bool setbeta(float b)
474 {
475 float yco = b / (alpha() * valueOfCOR());
476 std::uint8_t y = value2regvco(yco);
477 // now we compute the fine adjustment
478 float zco = ( regvco2value(y) * valueOfCOR() + 0.5f*static_cast<float>(VREF)/valueOfGI() - b/alpha() ) / ( (static_cast<float>(VREF)/65536.0f)/valueOfGI() );
479 std::int32_t z = static_cast<std::int32_t>(std::floor(zco + 0.5f));
480 if((z >= 65536) || (z < 0))
481 {
482 return false;
483 }
485 Vzerodac = static_cast<std::uint16_t>(z);
486
487 return true;
488 }
489
490 };
491
493
494#endif // #if defined(IMPORT_CODE_FROM_EMBOT_HW_PGA308)
495
496
497 // data in here;
499 {
500
501 }
503 {
504
505 }
506
507
508 bool load(const DiscreteGain g)
509 {
510 //LUCA
511 // offset all equal to 32k-1
512 static const uint8_t _cfgmap[static_cast<uint8_t>(DiscreteGain::maxnumberof)][6] =
513 {
514 {0x00, 0x80, 0x66, 0x06, 0xcb, 0x80}, // gain = 256
515 {0x00, 0x80, 0x56, 0x0c, 0xcb, 0x80}, // gain = 128
516 {0x00, 0x40, 0x56, 0x10, 0x0f, 0x81}, // gain = 96
517 {0x00, 0x80, 0x46, 0x17, 0x6d, 0x7f}, // gain = 64
518 {0x00, 0x40, 0x46, 0x1f, 0xb1, 0x7f}, // gain = 48
519 {0x00, 0x10, 0x46, 0x2a, 0x80, 0x80}, // gain = 36
520 {0x00, 0x40, 0x42, 0x3e, 0x62, 0x7f}, // gain = 24 [or 0x26 instead of 0x42]
521 {0x00, 0x20, 0x42, 0x4b, 0x15, 0x80}, // gain = 20 [or 0x26 instead of 0x42]
522 {0x00, 0x00, 0x42, 0x5e, 0x72, 0x80}, // gain = 16 [or 0x26 instead of 0x42]
523 {0x00, 0xC0, 0x02, 0x64, 0xf6, 0x6e}, // gain = 10 [or 0x10 instead of 0x02]
524 {0x00, 0x80, 0x02, 0x64, 0x29, 0x62}, // gain = 08 [or 0x10 instead of 0x02]
525 {0x00, 0x40, 0x02, 0x64, 0xd4, 0x4c}, // gain = 06 [or 0x10 instead of 0x02]
526 {0x00, 0x40, 0x00, 0x64, 0x29, 0x22} // gain = 04
527 };
528
529 bool ret = true;
530 switch(g)
531 {
534 {
535 ret = false;
536 } break;
537
538 default:
539 {
540 uint8_t index = static_cast<uint8_t>(g);
541 Registers cfg;
542 cfg.load(_cfgmap[index], 6);
543 tsf.load(cfg);
544 } break;
545
546 }
547
548 return ret;
549 }
550
552 {
553 //LUCA
554 // offset are not meaningful yet. we just need zdac to be 0x8000 and cfg0.os = ... boh: 0x20
555 static const uint8_t _cfgmap[static_cast<uint8_t>(DiscreteGain::maxnumberof)][6] =
556 {
557 {0x00, 0x80, 0x66, 0x20, 0x00, 0x80}, // gain = 256
558 {0x00, 0x80, 0x56, 0x20, 0x00, 0x80}, // gain = 128
559 {0x00, 0x40, 0x56, 0x20, 0x00, 0x80}, // gain = 96
560 {0x00, 0x80, 0x46, 0x20, 0x00, 0x80}, // gain = 64
561 {0x00, 0x40, 0x46, 0x20, 0x00, 0x80}, // gain = 48
562 {0x00, 0x10, 0x46, 0x20, 0x00, 0x80}, // gain = 36
563 {0x00, 0x40, 0x42, 0x20, 0x00, 0x80}, // gain = 24 [or 0x26 instead of 0x42]
564 {0x00, 0x20, 0x42, 0x20, 0x00, 0x80}, // gain = 20 [or 0x26 instead of 0x42]
565 {0x00, 0x00, 0x42, 0x20, 0x00, 0x80}, // gain = 16 [or 0x26 instead of 0x42]
566 {0x00, 0xC0, 0x02, 0x20, 0x00, 0x80}, // gain = 10 [or 0x10 instead of 0x02]
567 {0x00, 0x80, 0x02, 0x20, 0x00, 0x80}, // gain = 08 [or 0x10 instead of 0x02]
568 {0x00, 0x40, 0x02, 0x20, 0x00, 0x80}, // gain = 06 [or 0x10 instead of 0x02]
569 {0x00, 0x40, 0x00, 0x20, 0x00, 0x80} // gain = 04
570 };
571
572 bool ret = true;
573 switch(g)
574 {
577 {
578 ret = false;
579 } break;
580
581 default:
582 {
583 uint8_t index = static_cast<uint8_t>(g);
584 Registers cfg;
585 cfg.load(_cfgmap[index], 6);
586 tsf.load(cfg);
587 } break;
588
589 }
590
591 return ret;
592 }
593
594 bool load(const DiscreteGain g, const Offset offset)
595 {
596 // there are some compinations of g+offset which cannot reached.
597 // if g is 6 and o8k > 7780 (ofsfet =
598 // if g is 4 and o8k > 5100 (offset =
599 if(((g == DiscreteGain::val06) && (offset > (62240))) || ((g == DiscreteGain::val04) && (offset > (40800))))
600 {
601 return false;
602 }
603
604 // step1: we load the gain, so that we surely have some registers which are already ok.
605 // also we wnat zdac to be 0x8000
606 if(false == load_step1(g))
607 {
608 return false;
609 }
610
611 bool ret = true;
612
613 float o8k = offset / 8;
614
615 // step2: we keep the values of the gain(s), and if ZDAC = 0x8000 we can compute cfg0.os in a simple mode:
616 // cfg0.os = o8k/(alpha()*valueOfCOR())
617 float cfg0os = o8k/(tsf.alpha()*tsf.valueOfCOR());
618
619 // however, we must be sure that what we load is in range [-100, =100] and is in format sign-value.
620 int8_t Y = tsf.value2regvco(cfg0os);
621 // ok, we assign it.
622 tsf.Vcoarseoffset = Y;
623
624 // but now we must compute the zdac with formula:
625
626 // zdac = (64*1024)/(VREF) * ( (VREF/2) - (o8k - alpha() * valueOfCoarseOffset())/(g0*gd) )
627
628 float z = ((64.0f*1024.0f)/tsf.VREF) * ( (tsf.VREF/2) - (o8k - tsf.alpha()*tsf.valueOfCoarseOffset())/(tsf.valueOfGO()*tsf.valueOfGD()) );
629
630 if((z > 65535.0f) || (z < 0.0f))
631 {
632 return false;
633 }
634
635 uint16_t Z = static_cast<std::uint16_t>(std::floor(z + 0.5f));
636 tsf.Vzerodac = Z;
637
638 return true;
639 }
640
641 bool get(Gain &gain, Offset &offset)
642 {
643 // this funtion extends / uses the struct TransferFunctionConfig
644 gain = tsf.alpha();
645 int32_t tmp = static_cast<int32_t>(round(8.0f*tsf.beta()));
646 if((tmp >= 0) && (tmp < 65536))
647 {
648 offset = static_cast<uint16_t>(tmp);
649 return true;
650 }
651 return false;
652 }
653
654
655};
656
657
658// --------------------------------------------------------------------------------------------------------------------
659// - all the rest
660// --------------------------------------------------------------------------------------------------------------------
661
662
663
664
665namespace strain { namespace amplifier {
666
667 //LUCA
668 static const float mapofgains[static_cast<uint8_t>(DiscreteGain::maxnumberof)] =
669 {
670 256,128,96,64,48, 36, 24, 20, 16, 10, 8, 6, 4
671 };
672
674 {
675 uint8_t index = static_cast<uint8_t>(dg);
676 if(index >= static_cast<uint8_t>(DiscreteGain::maxnumberof))
677 {
678 return 0;
679 }
680 return mapofgains[index];
681 }
682
683 bool convert(const Gain g, DiscreteGain &dg)
684 {
685 bool ret = false;
687
688 // if g one of the allowed? i check by iteration
689 for(int i=0; i<static_cast<uint8_t>(DiscreteGain::maxnumberof); i++)
690 {
691 if(g == mapofgains[i])
692 {
693 dg = static_cast<DiscreteGain>(i);
694 ret = true;
695 break;
696 }
697 }
698
699 return ret;
700 }
701
702 bool convert(const WideParams &wp, DiscreteParams &dp)
703 {
705 if(false == convert(wp.g, dg))
706 {
707 return false;
708 }
709 dp.dg = dg;
710 dp.o = wp.o;
711
712 return true;
713 }
714
715
716 const std::uint8_t PGA308::Registers::defval[PGA308::Registers::sizeofregisters] = {0x00, 0x40, 0x46, 0x1f, 0xb1, 0x7f}; // gain = 48, offset = midrangeOffset
717
718 bool PGA308::Registers::load(const void *data, const size_t size)
719 {
720 if((nullptr == data) || (size != sizeofregisters))
721 {
722 GD = GI = S = GO = Voffsetcoarse = Vzerodac = 0;
723 return false;
724 }
725 const uint16_t *u16 = reinterpret_cast<const uint16_t*>(data);
726 const uint8_t *u08 = reinterpret_cast<const uint8_t*>(data);
727 GD = u16[0]; Vzerodac = u16[2];
728 GI = (u08[2] >> 4) & 0x0f;
729 S = (u08[2] >> 3) & 0x01;
730 GO = (u08[2]) & 0x07;
731 Voffsetcoarse = u08[3];
732 return true;
733 }
734
735 bool PGA308::Registers::fill(void *data, size_t &size)
736 {
737 if(nullptr == data)
738 {
739 return false;
740 }
741 uint16_t *u16 = reinterpret_cast<uint16_t*>(data);
742 uint8_t *u08 = reinterpret_cast<uint8_t*>(data);
743 u16[0] = GD; u16[2] = Vzerodac;
744 u08[2] = 0;
745 u08[2] = ((static_cast<uint8_t>(GI) & 0x0f) << 4) | ((static_cast<uint8_t>(S) & 0x01) << 3) | ((static_cast<uint8_t>(GO) & 0x07));
746 u08[3] = Voffsetcoarse;
747 size = sizeofregisters;
748 return true;
749 }
750
751
752 // struct basicRegs
753 // {
754 // std::uint16_t GD; // it is a gain register
755 // std::uint8_t GI : 4; // it is a gain register
756 // std::uint8_t S : 1; // it is a sign of gain register (keep it always 0)
757 // std::uint8_t GO : 3; // it is a gain register
758 // std::uint8_t Voffsetcoarse; // it is an offset register
759 // std::uint16_t Vzerodac; // it is an offset register
760
761 // basicRegs() : GD(0), GI(0), S(0), GO(0), Voffsetcoarse(0), Vzerodac(0) {}
762 // basicRegs(void *data, size_t s) { load(data, s); }
763 // void load(const void *data, const size_t s); // import from a can frame
764 // bool fill(void *data, size_t &s); // export to a can frame
765 // };
766
767// void PGA308::basicRegs::load(const void *data, const size_t s)
768// {
769// if(nullptr == data) { GD = GI = S = GO = Voffsetcoarse = Vzerodac = 0; return; }
770// const uint16_t *u16 = reinterpret_cast<const uint16_t*>(data);
771// const uint8_t *u08 = reinterpret_cast<const uint8_t*>(data);
772// GD = u16[0]; Vzerodac = u16[2];
773// GI = (u08[2] >> 4) & 0x0f;
774// S = (u08[2] >> 3) & 0x01;
775// GO = (u08[2]) & 0x07;
776// Voffsetcoarse = u08[3];
777// }
778
779// bool PGA308::basicRegs::fill(void *data, size_t &s)
780// {
781// if(nullptr == data)
782// {
783// return false;
784// }
785// uint16_t *u16 = reinterpret_cast<uint16_t*>(data);
786// uint8_t *u08 = reinterpret_cast<uint8_t*>(data);
787// u16[0] = GD; u16[2] = Vzerodac;
788// u08[2] = 0;
789// u08[2] = ((static_cast<uint8_t>(GI) & 0x0f) << 4) | ((static_cast<uint8_t>(S) & 0x01) << 3) | ((static_cast<uint8_t>(GO) & 0x07));
790// u08[3] = Voffsetcoarse;
791// s = 6;
792// return true;
793// }
794
795
796
798 : pImpl(new Impl)
799 {
800
801 }
802
804 {
805 delete pImpl;
806 }
807
808 bool PGA308::import(const Registers &regs, WideParams *wideparams)
809 {
810 load(regs);
811
812 if(nullptr != wideparams)
813 {
814 get(wideparams->g, wideparams->o);
815 }
816
817 return true;
818 }
819
820 bool PGA308::import(const DiscreteParams &params, Registers *regs)
821 {
822 load(params);
823
824 if(nullptr != regs)
825 {
826 get(*regs);
827 }
828
829 return true;
830 }
831
832
833
834 bool PGA308::load(const Registers &regs)
835 {
836 pImpl->tsf.load(regs);
837 return true;
838 }
839
840 // attempts to load into the PGA308 a pair discretegain-offset, which produce a given Registers.
842 {
844 {
845 return pImpl->load(g);
846 }
847
848 return pImpl->load(g, offset);
849 }
850
851 bool PGA308::load(const DiscreteParams &discreteparams)
852 {
853 return load(discreteparams.dg, discreteparams.o);
854 }
855
856 // retrieve the pair gain-offset which is effectively in use after a load operation
858 {
859 return pImpl->get(gain, offset);
860 }
861
862 bool PGA308::get(WideParams &wideparams)
863 {
864 return get(wideparams.g, wideparams.o);
865 }
866
867// bool PGA308::get(Params &params)
868// {
869// return get(params.g, params.o);
870// }
871
872 // retrieve the registers effectively in use.
874 {
875 pImpl->tsf.get(regs);
876 return true;
877 }
878
879
880
881}} // namespace strain { namespace amplifier {
882
883
884
885// --------------------------------------------------------------------------------------------------------------------
886// - test code
887// --------------------------------------------------------------------------------------------------------------------
888
889namespace strain { namespace amplifier {
890
891 // example of use.
892 // we must have an array of 6 PGA308 objects
893 // in the widget of the firmwareupdater:strainwindow we retrieve for each channel of the strain2 two values: a gain and an offset.
894 // we must have a
895
897 {
898 uint8_t data[6];
899 Example_strain2_ampl_regs_t() { data[0] = data[1] = data[2] = data[3] = data[4] = data[5] = 0; }
900 void load(void *mem) { memmove(data, mem, sizeof(data)); }
901 void * memory() { return data; }
902 size_t size() { return 6; }
903 };
904
905
906 void testIT(std::string &output)
907 {
908
909 const bool step1 = true;
910
911 const bool step2 = true;
912
913 // we use service object pga just to convert from and to.
914 PGA308 pga;
915
917
918 if(true == step1)
919 {
920 // in here we get two values of gain+offset (e.g., from the gui), we load int the pga and we retrieve the registers to send to the board
921 WideParams wp;
924
925
926 wp.load(4.0, 32*1024);
927 if(true == convert(wp, dp))
928 {
929 // load dp and ...
930 //PGA308::Registers regs;
931 pga.import(dp, &regs);
932 // use the regs for instance by sending to a strain2_ampl_regs_t which can be initted from a void *
933 //Example_strain2_ampl_regs_t regstoTX;
934 size_t s;
935 regs.fill(regstoTX.memory(), s);
936 // now call
937 //cDownloader::strain_set_amplifier_regs(bus, id, regstoTX, strain_regset_inuse);
938 }
939
940 //wp.load(48.0, 32*1024);
941 wp.load(48.0, 32531);
942 if(true == convert(wp, dp))
943 {
944 // load dp and ...
945 //PGA308::Registers regs;
946 pga.import(dp, &regs);
947 // use the regs for instance by sending to a strain2_ampl_regs_t which can be initted from a void *
948 //Example_strain2_ampl_regs_t regstoTX;
949 size_t s;
950 regs.fill(regstoTX.memory(), s);
951 // now call
952 //cDownloader::strain_set_amplifier_regs(bus, id, regstoTX, strain_regset_inuse);
953 }
954 output += "step1: ";
955 output += "done!";
956
957 }
958
960
961 if(true == step2)
962 {
963 // in here we retrieve a register. and we compute the associated gain-offset
964
965 RXregs = regstoTX;
966
967 //cDownloader::strain_get_amplifier_regs(bus, id, RXregs, strain_regset_inuse);
968
970 regs.load(RXregs.memory(), RXregs.size());
971
972 // now regs has the content of what we have received from can bus
973 WideParams wparams;
974 pga.import(regs, &wparams);
975 // now we see if the wparams.g is one of the allowed
976 DiscreteParams dparams;
977 if(true == convert(wparams, dparams))
978 {
979 // use dparams
980 Gain gg = convert(dparams.dg);
981 Offset oo = dparams.o;
982 }
983 }
984
985 }
986
987 void exampleofuse(void)
988 {
989
990#if 1
991
992 // we use service object pga just to convert from and to.
993 PGA308 pga;
994
995 // in here we get two values of gain+offset (e.g., from the gui), we load int the pga and we retrieve the registers to send to the board
996 WideParams wp;
997 wp.load(48.0, 32*1024);
999 if(true == convert(wp, dp))
1000 {
1001 // load dp and ...
1002 PGA308::Registers regs;
1003 pga.import(dp, &regs);
1004 // use the regs for instance by sending to a strain2_ampl_regs_t which can be initted from a void *
1006 size_t s;
1007 regs.fill(regstoTX.memory(), s);
1008 // now call
1009 //cDownloader::strain_set_amplifier_regs(bus, id, regstoTX, strain_regset_inuse);
1010 }
1011
1012 // in here we retrieve a register. and we compute the associated gain-offset
1013
1015
1016 //cDownloader::strain_get_amplifier_regs(bus, id, RXregs, strain_regset_inuse);
1017
1018 PGA308::Registers regs;
1019 regs.load(RXregs.memory(), RXregs.size());
1020
1021 // now regs has the content of what we have received from can bus
1022 WideParams wparams;
1023 pga.import(regs, &wparams);
1024 // now we see if the wparams.g is one of the allowed
1025 DiscreteParams dparams;
1026 if(true == convert(wparams, dparams))
1027 {
1028 // use dparams
1029 Gain gg = convert(dp.dg);
1030 Offset oo = dp.o;
1031 }
1032
1033
1034
1035#else
1036 // we have one for each channel
1037 PGA308 thePGAs[6];
1038
1039 // channel 0:
1040 DiscreteParams discreteparams;
1041 // get the value from teh widget
1042 discreteparams.load(DiscreteGain::val10, 32000);
1043 // load them into the object
1044 thePGAs[0].load(discreteparams);
1045 // now i want to send the packet to the board. i retrieve teh registers .
1046 PGA308::Registers regs;
1047 thePGAs[0].get(regs);
1048 // and now i transform them into a payload for can tx
1049 uint8_t payload[8] = {0};
1050 regs.fill(payload);
1051 // and now i use payload to tx.
1052
1053 // now i ask the registers to the board. i receive a payload
1054 uint8_t rxpayload[8] = {0}; // ok, not zero but ...
1055 regs.load(rxpayload);
1056 // and i want to fill the widget with the real values
1057 PGA308::Registers rxregs;
1058 rxregs.load(rxpayload);
1059 float gg =0;
1060 uint16_t oo =0;
1061 thePGAs[0].load(rxregs);
1062 thePGAs[0].get(gg, oo);
1063 // print gg, oo
1064#endif
1065
1066 }
1067
1068
1069}} // namespace strain { namespace amplifier
1070
1071
1072
1073namespace strain { namespace dsp { namespace fsc {
1074
1075 FSC convert(const double v, bool &saturated)
1076 {
1077 saturated = false;
1078 FSC ret = static_cast<FSC>(v);
1079
1080 if(v>fsc::max)
1081 {
1082 saturated = true;
1083 ret = fsc::max;
1084 }
1085
1086 if(v<fsc::min)
1087 {
1088 saturated = true;
1089 ret = fsc::min;
1090 }
1091
1092 return ret;
1093 }
1094
1095 double convert(const FSC v)
1096 {
1097 return static_cast<double>(v);
1098 }
1099
1100
1101 bool convert(const std::vector<double> &in, std::vector<FSC> &out)
1102 {
1103 bool sat = false;
1104 bool ret = true;
1105 out.resize(0);
1106 for(int i=0; i<in.size(); i++)
1107 {
1108 out.push_back(strain::dsp::fsc::convert(in[i], sat));
1109 if(sat)
1110 {
1111 ret = false;
1112 }
1113 }
1114 return ret;
1115 }
1116
1117 bool convert(const std::vector<FSC> &in, std::vector<double> &out)
1118 {
1119 bool ret = true;
1120 out.resize(0);
1121 for(int i=0; i<in.size(); i++)
1122 {
1123 out.push_back(strain::dsp::fsc::convert(in[i]));
1124 }
1125 return ret;
1126 }
1127
1128
1129} } } // namespace strain { namespace dsp { namespace fsc {
1130
1131
1132
1133namespace strain { namespace dsp { namespace q15 {
1134
1135 Q15 convert(const double v, bool &saturated)
1136 {
1137 Q15result rr = static_cast<Q15result>(v * 32768.0); // note: 32768.0 = 2^15
1138 return saturate(rr, saturated);
1139 }
1140
1141 Q15 U16toQ15(const std::uint16_t valU16)
1142 {
1143 return valU16-0x8000;
1144 }
1145
1146 bool convert(const std::vector<double> &in, std::vector<Q15> &out)
1147 {
1148 bool sat = false;
1149 bool ret = true;
1150 out.resize(0);
1151 for(int i=0; i<in.size(); i++)
1152 {
1153 out.push_back(convert(in[i], sat));
1154 if(sat)
1155 {
1156 ret = false;
1157 }
1158 }
1159 return ret;
1160 }
1161
1162 bool convert(const std::vector<Q15> &in, std::vector<double> &out)
1163 {
1164 bool ret = true;
1165 out.resize(0);
1166 for(int i=0; i<in.size(); i++)
1167 {
1168 out.push_back(convert(in[i]));
1169 }
1170 return ret;
1171 }
1172
1173 std::uint16_t Q15toU16(const Q15 valQ15)
1174 {
1175 return valQ15+0x8000;
1176 }
1177
1178 double convert(const Q15 v)
1179 {
1180 return static_cast<double>(v) / 32768.0; // note: 32768.0 = 2^15
1181 }
1182
1184 {
1185 if(negOne == v)
1186 {
1187 return posOneNearly;
1188 }
1189 return -v;
1190 }
1191
1192 Q15 saturate(const Q15result x, bool &saturated)
1193 {
1194 if (x > 0x7FFF)
1195 {
1196 saturated = true;
1197 return 0x7FFF;
1198 }
1199 else if (x < -0x8000)
1200 {
1201 saturated = true;
1202 return -0x8000;
1203 }
1204
1205 saturated = false;
1206 return static_cast<Q15>(x);
1207 }
1208
1209 Q15 add(const Q15 a, const Q15 b)
1210 {
1211 bool saturated = false;
1212 return add(a, b, saturated);
1213 }
1214
1215 Q15 add(const Q15 a, const Q15 b, bool &saturated)
1216 {
1217 Q15result tmp = static_cast<Q15result>(a) + static_cast<Q15result>(b);
1218
1219 return saturate(tmp, saturated);
1220 }
1221
1222 Q15 sub(Q15 &a, Q15 &b)
1223 {
1224 return a-b;
1225 }
1226
1227 Q15 mul(const Q15 a, const Q15 b, bool &saturated)
1228 {
1229 Q15result tmp = static_cast<Q15result>(a) * static_cast<Q15result>(b);
1230
1231 // Rounding; mid values are rounded up
1232 tmp += (1 << (15 - 1));
1233 // Correct by dividing by base
1234 tmp >>= 15;
1235 // and saturate result
1236 return saturate(tmp, saturated);
1237 }
1238
1239 Q15 mul(const Q15 a, const Q15 b)
1240 {
1241 bool saturated = false;
1242 return mul(a, b, saturated);
1243 }
1244
1245 Q15 div(const Q15 a, const Q15 b, bool &saturated)
1246 {
1247 Q15result n1 = static_cast<Q15result>(a);
1248 Q15result n2 = static_cast<Q15result>(b);
1249 Q15result rr = 0;
1250 std::uint8_t neg = 0;
1251
1252 if(0 == n2)
1253 {
1254 saturated = true;
1255 return 0;
1256 }
1257
1258 if(n1 < 0)
1259 {
1260 neg = !neg;
1261 n1 = -n1;
1262 }
1263
1264 if(n2 < 0)
1265 {
1266 neg = !neg;
1267 n2 = -n2;
1268 }
1269
1270 rr = (n1 << 15) / n2;
1271
1272 if(0 != neg)
1273 {
1274 rr = - rr;
1275 }
1276
1277 return saturate(rr, saturated);
1278 }
1279
1280 bool add(const matrix &m1, const matrix &m2, matrix &res, bool &saturated)
1281 {
1282 if((m1.ncols != m2.ncols) || (m1.ncols != res.ncols))
1283 {
1284 return false;
1285 }
1286 if((m1.nrows != m2.nrows) || (m1.nrows != res.nrows))
1287 {
1288 return false;
1289 }
1290
1291 saturated = false;
1292
1293 // ok, we do action
1294 for(int r=0; r<res.nrows; r++)
1295 {
1296 for(int c=0; c<res.ncols; c++)
1297 {
1298 bool sat1 = false;
1299 res.data[r*res.ncols+c] = add(m1.data[r*m1.ncols+c], m2.data[r*m2.ncols+c], sat1);
1300
1301 if(sat1)
1302 {
1303 saturated = true;
1304 }
1305 }
1306 }
1307
1308 return true;
1309 }
1310
1311 bool multiply(const matrix &m1, const matrix &m2, matrix &res, bool &saturated)
1312 {
1313 if(m1.ncols != m2.nrows)
1314 {
1315 return false;
1316 }
1317
1318 if(m1.nrows != res.nrows)
1319 {
1320 return false;
1321 }
1322
1323 if(m2.ncols != res.ncols)
1324 {
1325 return false;
1326 }
1327
1328 saturated = false;
1329 std::uint32_t nsat = 0;
1330
1331 // ok, we do action
1332 for(int r=0; r<res.nrows; r++)
1333 {
1334 for(int c=0; c<res.ncols; c++)
1335 {
1336 Q15 v = 0;
1337
1338 const Q15 *row_wise = &m1.data[r*m1.ncols]; // navigo con +1
1339 const Q15 *col_wise = &m2.data[c]; // navigo con +(m2.ncols)
1340 for(int i=0; i<m1.ncols; i++)
1341 {
1342 bool sat1 = false;
1343 bool sat2 = false;
1344 Q15 x = mul(*row_wise, *col_wise, sat1);
1345 v = add(v, x, sat2);
1346 if(sat1 || sat2)
1347 {
1348 nsat ++;
1349 saturated = true;
1350 }
1351 row_wise += 1;
1352 col_wise += m2.ncols;
1353 }
1354
1355 res.data[c + r*res.ncols] = v;
1356 }
1357 }
1358
1359 return true;
1360 }
1361
1362} } } // namespace strain { namespace dsp { namespace q15 {
1363
1364namespace strain { namespace regulation {
1365
1366 bool read(const std::string fname, FullRegulation &reg)
1367 {
1368 bool ret = false;
1369#if 0
1370 // to be done later on
1371
1372 reg.clear();
1373
1374 if(fname.empty())
1375 {
1376// yError("File not found!\n");
1377// appendLogMsg("File not found!");
1378 return false;
1379 }
1380
1381// if (selected_id <1 || selected_id >= 15){
1382// yError("Invalid board address!\n");
1383// appendLogMsg("Invalid board address!");
1384// return false;
1385// }
1386
1387 const char * filename = fname.c_str();
1388 int file_version=0;
1389 std::fstream filestr;
1390 filestr.open (filename, fstream::in);
1391 if (!filestr.is_open()){
1392// yError("Error opening calibration file!\n");
1393// appendLogMsg("Error opening calibration file!");
1394 return false;
1395 }
1396
1397 int i=0;
1398 char buffer[256];
1399
1400 //file version
1401 filestr.getline (buffer,256);
1402 filestr.getline (buffer,256);
1403 sscanf (buffer,"%d",&file_version);
1404
1405
1406 if((4 != file_version) && (3 != file_version))
1407 {
1408// yError("Wrong file. Calibration version not supported for strain2: %d\n", file_version);
1409// appendLogMsg("Wrong file. Calibration version not supported for strain2");
1410 return false;
1411 }
1412
1413 reg.version = static_cast<Version>(file_version);
1414
1415 if(Version::three == reg.version)
1416 {
1417 // Board type:
1418 filestr.getline (buffer,256);
1419 filestr.getline (buffer,256);
1420 if(0 != strcmp(buffer, "strain2"))
1421 {
1422// yError("Wrong file. Board type not supported: %s\n", buffer);
1423// appendLogMsg("Wrong file. Board type not supported");
1424 return false;
1425 }
1426
1427 reg.board = Board::strain2;
1428
1429 // Serial number:
1430 char serial_no[256] = {0};
1431 filestr.getline (buffer,256);
1432 filestr.getline (buffer,256);
1433 snprintf(serial_no, sizeof(serial_no), "%s", buffer);
1434 //core->getDownloader()->strain_set_serial_number(bus,id, serial_no);
1435
1436 reg.serial = std::string(serial_no);
1437
1438 // there is only one regulation set
1439
1440 Set set;
1441 set.clear();
1442
1443 // Amplifier registers:
1444 filestr.getline (buffer,256);
1445 for (i=0;i<6; i++)
1446 {
1447 filestr.getline (buffer,256);
1448// yDebug() << buffer;
1449 unsigned int t08[6] = {0};
1450 sscanf (buffer,"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", &t08[0], &t08[1], &t08[2], &t08[3], &t08[4], &t08[5]);
1451 for(int j=0; j<6; j++)
1452 {
1453 set.analog.amplregs[i][j] = t08[j];
1454 }
1455
1456// core->getDownloader()->strain_set_amplifier_regs(core->getDownloader()->board_list[selected].bus, core->getDownloader()->board_list[selected].pid, i, amp_registers[i], regset);
1457
1458 // downloader.strain_set_offset (downloader.board_list[selected].bus, downloader.board_list[selected].pid, i, offset[i]);
1459 //core->getDownloader()->strain_set_offset (bus,id, i, offset[i]);
1460 //printf("0X%02x, 0X%02x, 0X%02x, 0X%02x, 0X%02x,0X%02x", amp_registers[i].data[0], amp_registers[i].data[1], amp_registers[i].data[2], amp_registers[i].data[3], amp_registers[i].data[4], amp_registers[i].data[5]);
1461 //fflush(stdout);
1462// drv_sleep(10);
1463 }
1464
1465
1466
1467 //calibration matrix
1468 filestr.getline (buffer,256);
1469 for (i=0;i<36; i++){
1470 unsigned int tmp = 0;
1471 filestr.getline (buffer,256);
1472 sscanf (buffer,"%x", &tmp);
1473 set.digital.matrix[i] = static_cast<strain::dsp::Q15>(tmp);
1474// core->getDownloader()->strain_set_matrix_rc(bus,id, ri, ci, calib_matrix[index][ri][ci], regset);
1475 }
1476
1477
1478
1479 //matrix gain
1480 filestr.getline (buffer,256);
1481 filestr.getline (buffer,256);
1482 int cc=0;
1483 sscanf (buffer,"%d",&cc);
1484// core->getDownloader()->strain_set_matrix_gain(bus,id, cc, regset);
1485
1486 //tare
1487 filestr.getline (buffer,256);
1488 for (i=0;i<6; i++){
1489 filestr.getline (buffer,256);
1490 int tt = 0;
1491 sscanf (buffer,"%d", &tt);
1492 set.digital.tare[i] = static_cast<std::uint16_t>(tt);
1493// core->getDownloader()->strain_set_calib_bias(bus,id, i, calib_bias[i], regset);
1494 }
1495
1496 //full scale values
1497 filestr.getline (buffer,256);
1498 for (i=0;i<6; i++){
1499 filestr.getline (buffer,256);
1500 int fs = 0;
1501 sscanf (buffer,"%d", &fs);
1502 set.digital.fullscale[i] = static_cast<strain::dsp::FSC>(fs);
1503// core->getDownloader()->strain_set_full_scale(bus,id, i, full_scale_const[index][i], regset);
1504 }
1505
1506 reg.sets.push_back(set);
1507
1508 }
1509
1510 reg.set2useatbootstrap = 1;
1511
1512
1513 filestr.close();
1514 filestr.clear();
1515
1516#endif
1517
1518 return ret;
1519 }
1520
1521} } // namespace strain { namespace regulation
1522
1523
1524// - end-of-file (leave a blank line after)----------------------------------------------------------------------------
1525
@ data
static const std::uint8_t defval[sizeofregisters]
Definition strain.h:195
virtual bool load(const void *data, const size_t size)
Definition strain.cpp:718
static const std::uint8_t sizeofregisters
Definition strain.h:193
virtual std::uint8_t size()
Definition strain.h:201
virtual bool fill(void *data, size_t &size)
Definition strain.cpp:735
bool import(const Registers &regs, WideParams *wideparams=nullptr)
Definition strain.cpp:808
bool load(const Registers &regs)
Definition strain.cpp:834
bool get(WideParams &wideparams)
Definition strain.cpp:862
double sat(const double val, const double min, const double max)
Definition utils.h:183
void exampleofuse(void)
Definition strain.cpp:987
Gain convert(const DiscreteGain dg)
Definition strain.cpp:673
static const float mapofgains[static_cast< uint8_t >(DiscreteGain::maxnumberof)]
Definition strain.cpp:668
void testIT(std::string &output)
Definition strain.cpp:906
std::uint16_t Offset
Definition strain.h:121
const Offset midrangeOffset
Definition strain.h:140
FSC convert(const double v, bool &saturated)
Definition strain.cpp:1075
const FSC max
Definition strain.h:48
const FSC min
Definition strain.h:49
const Q15 negOne
Definition strain.h:61
std::uint16_t Q15toU16(const Q15 valQ15)
Definition strain.cpp:1173
Q15 saturate(const Q15result x, bool &saturated)
Definition strain.cpp:1192
Q15 convert(const double v, bool &saturated)
Definition strain.cpp:1135
Q15 sub(Q15 &a, Q15 &b)
Definition strain.cpp:1222
bool multiply(const matrix &m1, const matrix &m2, matrix &res, bool &saturated)
Definition strain.cpp:1311
Q15 div(const Q15 a, const Q15 b, bool &saturated)
Definition strain.cpp:1245
const Q15 posOneNearly
Definition strain.h:72
Q15 mul(const Q15 a, const Q15 b, bool &saturated)
Definition strain.cpp:1227
Q15 U16toQ15(const std::uint16_t valU16)
Definition strain.cpp:1141
Q15 opposite(const Q15 v)
Definition strain.cpp:1183
Q15 add(const Q15 a, const Q15 b)
Definition strain.cpp:1209
std::uint16_t FSC
Definition strain.h:40
std::int16_t Q15
Definition strain.h:41
std::int32_t Q15result
Definition strain.h:42
bool read(const std::string fname, FullRegulation &reg)
Definition strain.cpp:1366
out
Definition sine.m:8
degrees offset
Definition sine.m:4
void load(DiscreteGain _dg, Offset _o)
Definition strain.h:149
static const std::uint8_t DefaultGO_g_32_96
Definition strain.cpp:111
static const std::uint8_t DefaultGO_g_11_75
Definition strain.cpp:113
static const std::uint8_t DefaultGO_g_16_80
Definition strain.cpp:112
CFG0register(std::uint8_t GO, std::uint8_t MUX, std::uint8_t GI, std::uint8_t OS)
Definition strain.cpp:124
static const std::uint16_t Default
Definition strain.cpp:86
bool alignVOUT(const std::uint16_t vout, const std::uint16_t target, std::uint8_t &Y, std::uint16_t &Z)
Definition strain.cpp:437
void assign(const CFG0register &cfg0, const ZDACregister &zdac, const GDACregister &gdac)
Definition strain.cpp:308
void obtain(CFG0register &cfg0, ZDACregister &zdac, GDACregister &gdac) const
Definition strain.cpp:300
void computeOffsetParams(const std::uint16_t vout, float &a, float &b, float &c)
Definition strain.cpp:427
static const std::uint16_t Default
Definition strain.cpp:64
TransferFunctionConfig tsf
Definition strain.cpp:492
bool load(const DiscreteGain g, const Offset offset)
Definition strain.cpp:594
bool load_step1(const DiscreteGain g)
Definition strain.cpp:551
bool get(Gain &gain, Offset &offset)
Definition strain.cpp:641
bool load(const DiscreteGain g)
Definition strain.cpp:508
void load(Gain _g, Offset _o)
Definition strain.h:158
std::uint8_t ncols
Definition strain.h:96
std::uint8_t nrows
Definition strain.h:95
std::uint8_t amplregs[strain::numberofchannels][strain::amplifier::PGA308::Registers::sizeofregisters]
Definition strain.h:272
strain::dsp::Q15 matrix[strain::numberofchannels *strain::numberofchannels]
Definition strain.h:287
strain::dsp::FSC fullscale[strain::numberofchannels]
Definition strain.h:288
std::uint16_t tare[strain::numberofchannels]
Definition strain.h:286