iCub-main
Loading...
Searching...
No Matches
strain.h
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// - include guard ----------------------------------------------------------------------------------------------------
20
21#ifndef _STRAIN_H_
22#define _STRAIN_H_
23
24#include <cmath>
25#include <cstdint>
26#include <cstring>
27#include <string>
28#include <vector>
29
30namespace strain {
31
32 enum class Board { strain1 = 1, strain2 = 2 };
33
34 const std::uint8_t numberofchannels = 6;
35
36} // namespace strain {
37
38namespace strain { namespace dsp {
39
40 using FSC = std::uint16_t;
41 using Q15 = std::int16_t;
42 using Q15result = std::int32_t;
43
44} } // namespace strain { namespace dsp {
45
46namespace strain { namespace dsp { namespace fsc {
47
48 const FSC max = 64*1024-1;
49 const FSC min = 0;
50
51 FSC convert(const double v, bool &saturated);
52 double convert(const FSC v);
53
54 bool convert(const std::vector<double> &in, std::vector<FSC> &out);
55 bool convert(const std::vector<FSC> &in, std::vector<double> &out);
56
57} } } // namespace strain { namespace dsp { namespace fsc {
58
59namespace strain { namespace dsp { namespace q15 {
60
61 const Q15 negOne = 0x8000;
62 const Q15 negOneNearly = 0x8001; // -1+2^(-15) = -0.999969482421875
63 const Q15 negOneHalf = 0xC000; // -1+2^(-1) = -1.00+0.50 = -0.50
64 const Q15 negOneFourth = 0xE000; // -1+2^(-1)+2^(-2) = -1.00+0.50+0.25 = -0.25
65 const Q15 negOneEigth = 0xF000; // -1+2^(-1)+2^(-2)+2^(-3) = -1.00+0.50+0.25+0.125 = -0.125
66 const Q15 negEPSILON = 0xFFFF; // -1+sum_(i=-1,..,-15)(2^i) = -0.000030517578125
67 const Q15 zero = 0;
68 const Q15 posEPSILON = 0x0001; // 2^(-15) = 0.000030517578125
69 const Q15 posOneHalf = 0x4000; // 2^(-1) = 0.5
70 const Q15 posOneFourth = 0x2000; // 2^(-2) = 0.25
71 const Q15 posOneEigth = 0x4000; // 2^(-3) = 0.125
72 const Q15 posOneNearly = 0x7FFF; // sum_(i=-1,..,-15)(2^i) = 1-2^(-15) = 0.999969482421875
73
74 Q15 convert(const double v, bool &saturated);
75 double convert(const Q15 v);
76
77 bool convert(const std::vector<double> &in, std::vector<Q15> &out);
78 bool convert(const std::vector<Q15> &in, std::vector<double> &out);
79
80 Q15 U16toQ15(const std::uint16_t valU16); // transforms a value in range [0, 64k-1] into a Q15
81 std::uint16_t Q15toU16(const Q15 valQ15); // transforms a Q15 into range [0, 64k-1]
82
83 Q15 opposite(const Q15 v); // opposite of negOne is posOneNearly
84 Q15 saturate(const Q15result x, bool &saturated);
85 Q15 add(const Q15 a, const Q15 b);
86 Q15 add(const Q15 a, const Q15 b, bool &saturated);
87 Q15 sub(const Q15 a, const Q15 b);
88 Q15 mul(const Q15 a, const Q15 b);
89 Q15 mul(const Q15 a, const Q15 b, bool &saturated);
90 Q15 div(const Q15 a, const Q15 b, bool &saturated);
91
92
93 struct matrix
94 {
95 std::uint8_t nrows;
96 std::uint8_t ncols;
97 Q15* data; // organised by row
98
99 void load(std::uint8_t r, std::uint8_t c, Q15* d) { nrows = r; ncols = c; data = d; }
100 matrix() { load(0, 0, nullptr); }
101 matrix(std::uint8_t r, std::uint8_t c, Q15* d) { load(r, c, d); }
102 Q15 get(std::uint8_t r, std::uint8_t c) { if((r<nrows) && (c<ncols) && (nullptr != data)) { return data[c + r*ncols]; } else { return 0; } }
103 void set(std::uint8_t r, std::uint8_t c, Q15 v) { if((r<nrows) && (c<ncols) && (nullptr != data)) { data[c + r*ncols] = v; } }
104 void clear() { if(nullptr != data) { std::memset(data, 0, sizeof(Q15)*ncols*nrows); } }
105 void diagonal(Q15 v) { clear(); if(nullptr != data) { std::uint8_t min = (ncols<nrows) ? (ncols) : (nrows); for(int i=0; i<min; i++) data[i+i*ncols] = v; } }
106 void fill(Q15 v) { clear(); if(nullptr != data) { for(int r=0; r<nrows; r++) for(int c=0; c<nrows; c++) data[c+r*ncols] = v; } }
107 };
108
109 bool multiply(const matrix &m1, const matrix &m2, matrix &res, bool &saturated);
110 bool add(const matrix &m1, const matrix &m2, matrix &res, bool &saturated);
111
112} } } // namespace strain { namespace dsp { namespace q15 {
113
114
115
116namespace strain { namespace amplifier {
117
118 // according to formula: Vout = gain * Vin + offset
119 // gain is a float, and offset is a positive integer in range [0, 64k)
120 using Gain = float;
121 using Offset = std::uint16_t;
122
123 // but gain cannot be any real number because it is given by a limited combination of registers.
124 // the exact definition of the possible values is possible but very complicated, hence we decide
125 // to simplify and allow only a limited number of possible values whcih have shown to be useful.
126 // they are the DiscreteGain
127 //LUCA
128 enum class DiscreteGain { val256 = 0, val128 = 1, val96 = 2, val64 = 3, val48 = 4, val36 = 5, val24 = 6, val20 = 7, val16 = 8, val10 = 9, val08 = 10, val06 = 11, val04 = 12, none = 32, maxnumberof = 13 };
129
130 // with this we convert from the enum to the real value (should you use it in some debug message)
132
133 // with this we convert a float gain into a discrete one. but only if the float gain is exactly equal.
134 // as an example g = 48.0f will be succesfully converted to dg = DiscreteGain::val48 and teh funtion will return true,
135 // but g = 47.0f will cause funtion to return false and dg = DiscreteGain::none
136 bool convert(const Gain g, DiscreteGain &dg);
137
138 // we have some special offsets: the minimum, the midrange, the maximum
140 const Offset midrangeOffset = 32*1024-1;
141 const Offset maximumOffset = 64*1024-1;
142
143 // we group in here the discrete gain + offset
151
152 // we group in here the float gain + offset
154 {
158 void load(Gain _g, Offset _o) { g = _g; o = _o; }
159 void load(DiscreteGain _dg, Offset _o) { g = convert(_dg); o = _o; }
160 void load(const DiscreteParams &_dp) { g = convert(_dp.dg); o = _dp.o; }
161 };
162
163 // and in here we can convert from wide to discrete. it returns true only if conversion of Gain to DiscreteGain is possible
164 bool convert(const WideParams &wp, DiscreteParams &dp);
165
166 // in here we define a virtual interface for the registers
167 class IFregs
168 {
169 public:
170 virtual ~IFregs() {}
171 virtual bool load(const void *data, const size_t size) = 0; // import from a stream (e.g., a can frame)
172 virtual bool fill(void *data, size_t &size) = 0; // export to a stream (e.g., a can frame)
173 virtual std::uint8_t size() = 0;
174 };
175
176 // and now we have a class which manages a particular amplifier: the PGA308.
177 // transformations between discrete params of the amplifier in the form of DiscreteParams
178 // towards the registers of the PGA308. And also the transformation from the registers towards full range Gain+Offset
179 class PGA308
180 {
181 public:
182
183 class Registers: public IFregs
184 {
185 public:
186 std::uint16_t GD; // it is a gain register
187 std::uint8_t GI : 4; // it is a gain register
188 std::uint8_t S : 1; // it is a sign of gain register (keep it always 0)
189 std::uint8_t GO : 3; // it is a gain register
190 std::uint8_t Voffsetcoarse; // it is an offset register
191 std::uint16_t Vzerodac; // it is an offset register
192
193 static const std:: uint8_t sizeofregisters = 6;
194
195 static const std::uint8_t defval[sizeofregisters];// = {0x00, 0x40, 0x46, 0x1f, 0xb1, 0x7f}; // gain = 48, offset = midrangeOffset
196
197 Registers() : GD(0), GI(0), S(0), GO(0), Voffsetcoarse(0), Vzerodac(0) {}
198 Registers(void *data, size_t size) { load(data, size); }
199 virtual bool load(const void *data, const size_t size);
200 virtual bool fill(void *data, size_t &size);
201 virtual std::uint8_t size() { return sizeofregisters; }
202 };
203
204
205 PGA308();
206 ~PGA308();
207
208 // usage: there are two possible modes:
209 // 1. import registers and retrieve gain+offset into WideParams
210 // 2. load discrete-gain+ofsfet and retrieve regs into Registers.
211
212 bool import(const Registers &regs, WideParams *wideparams = nullptr);
213 bool get(WideParams &wideparams);
214
215 bool import(const DiscreteParams &discreteparams, Registers *regs = nullptr);
216 bool get(Registers &regs);
217
218
219
220 protected:
221
222 // in here we put a ... protected interface
223
224 // loads into the PGA308 the basic registers which define its behaviour in terms of gain-offset
225 // that will cause the PGA to have values of gain and offset
226 bool load(const Registers &regs);
227
228 // attempts to load into the PGA308 a pair discretegain-offset, which produce a given Registers.
229 // the attempt can cause sligthly different values
230 bool load(const DiscreteGain g, const Offset offset = midrangeOffset);
231 bool load(const DiscreteParams &discreteparams);
232
233 // retrieve the pair gain-offset which is effectively in use after a load operation
234 bool get(Gain &gain, Offset &offset);
235
236
237 bool get(DiscreteParams &discreteparams);
238
239
240
241 private:
242 struct Impl;
243 Impl *pImpl;
244 };
245
246
247 void testIT(std::string &output);
248
249
250}} // namespace strain { namespace amplifier
251
252
253
254class cDownloader;
255
256namespace strain { namespace regulation {
257
258
259 const std::uint8_t maxSets = 3;
260
261 enum class Version { two = 2, three = 3, four = 4 };
262
263 struct Analog1
264 { // for strain1
266 Analog1() { clear(); }
267 void clear() { std::memset(offset, 0, sizeof(offset)); }
268 };
269
281
282
283
297
298 struct Set1
299 { // for strain1
302 };
303
304 struct Set
305 { // for strain2
308 Set() { clear(); }
309 void clear() { analog.clear(); digital.clear(); }
310 };
311
312
313
321
323 {
326 std::string serial;
327 std::uint8_t set2useatbootstrap; // 1, 2 or 3
328 std::vector<Set> sets;
330 void clear() { version = Version::four; board = Board::strain2; serial = "SN666"; set2useatbootstrap = 1; sets.resize(0); }
331 };
332
333 // it just reads from file and fills FullRegulation for use outside of this module
334 bool read(const std::string filename, FullRegulation &reg);
335
336 // it just reads from file and fills FullRegulation for use outside of this module
337 bool write(const std::string filename, const FullRegulation &reg);
338 bool apply(cDownloader *down, const FullRegulation &reg);
339
340} } // namespace strain { namespace regulation {
341
342
343
344
345
346#endif // include-guard
347
348
349// - end-of-file (leave a blank line after)----------------------------------------------------------------------------
350
351
352
353
@ data
virtual std::uint8_t size()=0
virtual bool load(const void *data, const size_t size)=0
virtual bool fill(void *data, size_t &size)=0
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
Registers(void *data, size_t size)
Definition strain.h:198
virtual bool fill(void *data, size_t &size)
Definition strain.cpp:735
bool get(DiscreteParams &discreteparams)
bool load(const Registers &regs)
Definition strain.cpp:834
bool get(WideParams &wideparams)
Definition strain.cpp:862
const Offset minimumOffset
Definition strain.h:139
const Offset maximumOffset
Definition strain.h:141
Gain convert(const DiscreteGain dg)
Definition strain.cpp:673
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 posOneEigth
Definition strain.h:71
const Q15 negOne
Definition strain.h:61
const Q15 negOneEigth
Definition strain.h:65
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
const Q15 negOneFourth
Definition strain.h:64
Q15 sub(Q15 &a, Q15 &b)
Definition strain.cpp:1222
const Q15 negEPSILON
Definition strain.h:66
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
const Q15 posOneFourth
Definition strain.h:70
const Q15 posEPSILON
Definition strain.h:68
const Q15 zero
Definition strain.h:67
const Q15 negOneHalf
Definition strain.h:63
const Q15 negOneNearly
Definition strain.h:62
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
const Q15 posOneHalf
Definition strain.h:69
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
const std::uint8_t maxSets
Definition strain.h:259
bool write(const std::string filename, const FullRegulation &reg)
bool apply(cDownloader *down, const FullRegulation &reg)
bool read(const std::string fname, FullRegulation &reg)
Definition strain.cpp:1366
const std::uint8_t numberofchannels
Definition strain.h:34
Board
Definition strain.h:32
out
Definition sine.m:8
degrees offset
Definition sine.m:4
void load(DiscreteGain _dg, Offset _o)
Definition strain.h:149
void load(DiscreteGain _dg, Offset _o)
Definition strain.h:159
void load(const DiscreteParams &_dp)
Definition strain.h:160
void load(Gain _g, Offset _o)
Definition strain.h:158
void set(std::uint8_t r, std::uint8_t c, Q15 v)
Definition strain.h:103
Q15 get(std::uint8_t r, std::uint8_t c)
Definition strain.h:102
std::uint8_t ncols
Definition strain.h:96
matrix(std::uint8_t r, std::uint8_t c, Q15 *d)
Definition strain.h:101
void load(std::uint8_t r, std::uint8_t c, Q15 *d)
Definition strain.h:99
void diagonal(Q15 v)
Definition strain.h:105
std::uint8_t nrows
Definition strain.h:95
std::uint8_t offset[strain::numberofchannels]
Definition strain.h:265
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