continue implementing config file parsing
Stefan Schuermans

Stefan Schuermans commited on 2017-06-10 20:17:07
Showing 7 changed files, with 842 additions and 7 deletions.

... ...
@@ -19,13 +19,18 @@
19 19
 
20 20
 #include <algorithm>
21 21
 #include <cctype>
22
+#include <cmath>
23
+#include <cstdlib>
22 24
 #include <functional>
23 25
 #include <fstream>
26
+#include <map>
24 27
 #include <stdexcept>
25 28
 #include <sstream>
26 29
 #include <string>
27 30
 
28 31
 #include "config.h"
32
+#include "distri.h"
33
+#include "mapping.h"
29 34
 
30 35
 /**
31 36
  * @brief constructor
... ...
@@ -71,6 +76,195 @@ void Config::split(std::string const &str, std::vector<std::string> &fields)
71 76
   }
72 77
 }
73 78
 
79
+/**
80
+ * @brief split string at specific character
81
+ * @param[in] str string to split
82
+ * @param[in] delim delimiter character
83
+ * @param[out] fields fields of string
84
+ */
85
+void Config::split_chr(std::string const &str, char delim,
86
+                       std::vector<std::string> &fields)
87
+{
88
+  std::string::size_type pos = 0, end;
89
+  fields.clear();
90
+  while ((end = str.find(delim, pos)) != std::string::npos) {
91
+    fields.push_back(str.substr(pos, end - pos));
92
+    pos = end + 1;
93
+  }
94
+  fields.push_back(str.substr(pos));
95
+}
96
+
97
+/**
98
+ * @brief convert string to unsigned long
99
+ * @param[in] str string to convert
100
+ * @return unsigned long parsed from string
101
+ * @throws std::exception in case of error
102
+ */
103
+unsigned long Config::str2ul(std::string const &str)
104
+{
105
+  char const *sz = str.c_str();
106
+  char *end;
107
+  unsigned long ul = strtoul(sz, &end, 0);
108
+  if (end == sz || *end != 0) {
109
+    std::stringstream msg;
110
+    msg << "invalid unsigned integer \"" << str << "\"";
111
+    throw std::runtime_error(msg.str());
112
+  }
113
+  return ul;
114
+}
115
+
116
+/**
117
+ * @brief convert string to two unsigned longs
118
+ * @param[in] str string containing two comma-separated unsigned integers
119
+ * @param[out] ul1 first unsigned long parsed from string
120
+ * @param[out] ul2 second unsigned long parsed from string
121
+ * @throws std::exception in case of error
122
+ */
123
+void Config::str2ul2(std::string const &str,
124
+                     unsigned long &ul1, unsigned long &ul2)
125
+{
126
+  std::vector<std::string> fields;
127
+  split_chr(str, ',', fields);
128
+  if (fields.size() != 2) {
129
+    std::stringstream msg;
130
+    msg << "expected two comma-separated unsigned integers, found \""
131
+        << str << "\"";
132
+    throw std::runtime_error(msg.str());
133
+  }
134
+  try {
135
+    ul1 = str2ul(fields[0]);
136
+    ul2 = str2ul(fields[1]);
137
+  } catch (std::exception &ex) {
138
+    std::stringstream msg;
139
+    msg << "invalid unsigned integer pair \"" << str << "\": " << ex.what();
140
+    throw std::runtime_error(msg.str());
141
+  }
142
+}
143
+
144
+/**
145
+ * @brief convert string to double (using the decimal dot for any locale)
146
+ * @param[in] str string to convert
147
+ * @return double parsed from string
148
+ * @throws std::exception in case of error
149
+ */
150
+double Config::str2d(std::string const &str)
151
+{
152
+  char const *sz = str.c_str();
153
+
154
+  // skip leading whitespace
155
+  while (isspace(*sz)) {
156
+    ++sz;
157
+  }
158
+
159
+  // start processing after leading whitespace
160
+  char const *ptr = sz;
161
+
162
+  // read optional sign
163
+  double sign = 1.0;
164
+  if (*ptr == '+') {
165
+    sign = 1.0;
166
+    ++ptr;
167
+  } else if (*ptr == '-') {
168
+    sign = -1.0;
169
+    ++ptr;
170
+  }
171
+
172
+  // read digits before dot
173
+  double value = 0.0;
174
+  while (*ptr >= '0' && *ptr <= '9') {
175
+    value = value * 10.0 + (double)(*ptr - '0');
176
+    ++ptr;
177
+  }
178
+
179
+  // read dot and digits after it
180
+  double weight = 0.1;
181
+  if (*ptr == '.') {
182
+    ++ptr;
183
+
184
+    /* read digits after dot */
185
+    while (*ptr >= '0' && *ptr <= '9') {
186
+      value += weight * (double)(*ptr - '0');
187
+      weight *= 0.1;
188
+      ++ptr;
189
+    }
190
+
191
+  } // if (*ptr == '.')
192
+
193
+  // merge sign into value
194
+  value *= sign;
195
+
196
+  // read exponent
197
+  if (*ptr == 'E' || *ptr == 'e') {
198
+    ++ptr;
199
+
200
+    /* read optional sign */
201
+    int exp_sign = 1;
202
+    if (*ptr == '+') {
203
+      exp_sign = 1;
204
+      ++ptr;
205
+    } else if (*ptr == '-') {
206
+      exp_sign = -1;
207
+      ++ptr;
208
+    }
209
+
210
+    /* read digits */
211
+    int exp_value = 0;
212
+    while (*ptr >= '0' && *ptr <= '9') {
213
+      exp_value = exp_value * 10 + (int)(*ptr - '0');
214
+      ++ptr;
215
+    }
216
+
217
+    /* merge exponent into value */
218
+    value *= pow(10.0, exp_sign * exp_value);
219
+
220
+  } // if (*nptr == 'E' || *nptr == 'e')
221
+
222
+  // skip trailing whitespace
223
+  while (isspace(*ptr)) {
224
+    ++ptr;
225
+  }
226
+
227
+  // leftover characters -> error */
228
+  if (ptr == sz || *ptr != 0) {
229
+    std::stringstream msg;
230
+    msg << "invalid floating point value \"" << str << "\"";
231
+    throw std::runtime_error(msg.str());
232
+  }
233
+
234
+  // return value
235
+  return value;
236
+}
237
+
238
+/**
239
+ * @brief convert string to three doubles (decimal dot for any locale)
240
+ * @param[in] str string containing three comma-separated doubles
241
+ * @param[out] d1 first double parsed from string
242
+ * @param[out] d2 second double parsed from string
243
+ * @param[out] d3 third double parsed from string
244
+ * @throws std::exception in case of error
245
+ */
246
+void Config::str2d3(std::string const &str,
247
+                    double &d1, double &d2, double &d3)
248
+{
249
+  std::vector<std::string> fields;
250
+  split_chr(str, ',', fields);
251
+  if (fields.size() != 3) {
252
+    std::stringstream msg;
253
+    msg << "expected three comma-separated floating point values, found \""
254
+        << str << "\"";
255
+    throw std::runtime_error(msg.str());
256
+  }
257
+  try {
258
+    d1 = str2d(fields[0]);
259
+    d2 = str2d(fields[1]);
260
+    d3 = str2d(fields[2]);
261
+  } catch (std::exception &ex) {
262
+    std::stringstream msg;
263
+    msg << "invalid floating point triplet \"" << str << "\": " << ex.what();
264
+    throw std::runtime_error(msg.str());
265
+  }
266
+}
267
+
74 268
 /**
75 269
  * @brief read config file
76 270
  * @param[in] configFile name of config file
... ...
@@ -159,19 +353,19 @@ void Config::procSetting(std::string const &setting, std::string const &value)
159 353
 
160 354
   // distributor
161 355
   if (setFields[0] == "distributor") {
162
-    // TODO
356
+    proc_distributor(setFields, valFields);
163 357
   }
164 358
   // distributor address
165 359
   else if (setFields[0] == "distributorAddr") {
166
-    // TODO
360
+    proc_distributorAddr(setFields, valFields);
167 361
   }
168 362
   // mapping
169 363
   else if (setFields[0] == "mapping") {
170
-    // TODO
364
+    proc_mapping(setFields, valFields);
171 365
   }
172 366
   // output
173 367
   else if (setFields[0] == "output") {
174
-    // TODO
368
+    proc_output(setFields, valFields);
175 369
   }
176 370
   // unknown setting
177 371
   else {
... ...
@@ -181,3 +375,292 @@ void Config::procSetting(std::string const &setting, std::string const &value)
181 375
   }
182 376
 }
183 377
 
378
+/**
379
+ * @brief process distributor line from config file
380
+ * @param[in] setFields fields of the setting parts
381
+ * @param[in] valFields fields of the value part
382
+ * @throws std::exception in case of error
383
+ */
384
+void Config::proc_distributor(std::vector<std::string> const &setFields,
385
+                              std::vector<std::string> const &valFields)
386
+{
387
+  // check number of setting fields
388
+  if (setFields.size() != 2) {
389
+    std::stringstream msg;
390
+    msg << "invalid \"distributor\" setting with " << setFields.size()
391
+        << " fields, expected \"distributor <distno>\"";
392
+    throw std::runtime_error(msg.str());
393
+  }
394
+
395
+  // get and check distributor number
396
+  unsigned long distno;
397
+  try {
398
+    distno = str2ul(setFields[1]);
399
+  } catch (std::exception &ex) {
400
+    std::stringstream msg;
401
+    msg << "invalid distributor number \"" << setFields[1] << "\": "
402
+        << ex.what();
403
+    throw std::runtime_error(msg.str());
404
+  }
405
+  if (m_distriMap.find(distno) != m_distriMap.end()) {
406
+    std::stringstream msg;
407
+    msg << "duplicate \"distributor " << distno << "\" setting";
408
+    throw std::runtime_error(msg.str());
409
+  }
410
+
411
+  // check number of value fields
412
+  if (valFields.size() != 1) {
413
+    std::stringstream msg;
414
+    msg << "invalid value for \"distributor " << distno << "\": "
415
+        << setFields.size() << " fields, expected \"<outputs>,<pixels>\"";
416
+    throw std::runtime_error(msg.str());
417
+  }
418
+
419
+  // get and check outputs and pixels per output
420
+  unsigned long outputs, pixels;
421
+  try {
422
+    str2ul2(valFields[0], outputs, pixels);
423
+    if (outputs < 1) {
424
+      std::stringstream msg;
425
+      msg << "invalid number of outputs \"" << outputs << "\"";
426
+      throw std::runtime_error(msg.str());
427
+    }
428
+    if (pixels < 1) {
429
+      std::stringstream msg;
430
+      msg << "invalid number of pixels per output \"" << pixels << "\"";
431
+      throw std::runtime_error(msg.str());
432
+    }
433
+  } catch (std::exception &ex) {
434
+    std::stringstream msg;
435
+    msg << "invalid value for \"distributor " << distno << "\": "
436
+        << ex.what();
437
+    throw std::runtime_error(msg.str());
438
+  }
439
+
440
+  // create distributor
441
+  m_distriMap[distno].init(distno, outputs, pixels);
442
+}
443
+
444
+/**
445
+ * @brief process distributorAddr line from config file
446
+ * @param[in] setFields fields of the setting parts
447
+ * @param[in] valFields fields of the value part
448
+ * @throws std::exception in case of error
449
+ */
450
+void Config::proc_distributorAddr(std::vector<std::string> const &setFields,
451
+                                  std::vector<std::string> const &valFields)
452
+{
453
+  // check number of setting fields
454
+  if (setFields.size() != 2) {
455
+    std::stringstream msg;
456
+    msg << "invalid \"distributorAddr\" setting with " << setFields.size()
457
+        << " fields, expected \"distributorAddr <distno>\"";
458
+    throw std::runtime_error(msg.str());
459
+  }
460
+
461
+  // get distributor
462
+  Distri &distri = getDistri(setFields[1]);
463
+
464
+  // check number of value fields
465
+  if (valFields.size() != 1) {
466
+    std::stringstream msg;
467
+    msg << "invalid value for \"distributorAddr " << distri.getNo() << "\": "
468
+        << setFields.size() << " fields, expected \"<IPv4>:<port>\"";
469
+    throw std::runtime_error(msg.str());
470
+  }
471
+
472
+  // parse address
473
+  // TODO
474
+}
475
+
476
+/**
477
+ * @brief process mapping line from config file
478
+ * @param[in] setFields fields of the setting parts
479
+ * @param[in] valFields fields of the value part
480
+ * @throws std::exception in case of error
481
+ */
482
+void Config::proc_mapping(std::vector<std::string> const &setFields,
483
+                          std::vector<std::string> const &valFields)
484
+{
485
+  // check number of setting fields
486
+  if (setFields.size() != 3) {
487
+    std::stringstream msg;
488
+    msg << "invalid \"mapping\" setting with " << setFields.size()
489
+        << " fields, expected \"mapping <distno> [red|green|blue]\"";
490
+    throw std::runtime_error(msg.str());
491
+  }
492
+
493
+  // get distributor
494
+  Distri &distri = getDistri(setFields[1]);
495
+
496
+  // get channel
497
+  std::string strColor = setFields[2];
498
+  Mapping::Channel channel;
499
+  if (strColor == "red" ) {
500
+    channel = Mapping::Red;
501
+  } else if (strColor == "green" ) {
502
+    channel = Mapping::Green;
503
+  } else if (strColor == "blue" ) {
504
+    channel = Mapping::Blue;
505
+  } else {
506
+    std::stringstream msg;
507
+    msg << "invalid \"mapping\" setting: unknown color \"" << strColor
508
+        << "\" fields, expected \"red\", \"green\" or \"blue\"";
509
+    throw std::runtime_error(msg.str());
510
+  }
511
+
512
+  // check number of value fields
513
+  if (valFields.size() != 3) {
514
+    std::stringstream msg;
515
+    msg << "invalid value for \"mapping " << distri.getNo() << " "
516
+        << strColor << "\": " << setFields.size()
517
+        << " fields, expected \"<base> <factor> <gamma>\"";
518
+    throw std::runtime_error(msg.str());
519
+  }
520
+
521
+  // parse value fields
522
+  double base, factor, gamma;
523
+  try {
524
+    base = str2d(valFields[0]);
525
+  } catch (std::exception &ex) {
526
+    std::stringstream msg;
527
+    msg << "invalid value for \"mapping " << distri.getNo() << " "
528
+            << strColor << "\": invalid value \"" << valFields[0]
529
+            << "\"for \"base\": " << ex.what();
530
+    throw std::runtime_error(msg.str());
531
+  }
532
+  try {
533
+    factor = str2d(valFields[1]);
534
+  } catch (std::exception &ex) {
535
+    std::stringstream msg;
536
+    msg << "invalid value for \"mapping " << distri.getNo() << " "
537
+            << strColor << "\": invalid value \"" << valFields[1]
538
+            << "\"for \"factor\": " << ex.what();
539
+    throw std::runtime_error(msg.str());
540
+  }
541
+  try {
542
+    gamma = str2d(valFields[2]);
543
+    if (gamma <= 0.0) {
544
+      throw std::runtime_error("gamma value must be positive");
545
+    }
546
+  } catch (std::exception &ex) {
547
+    std::stringstream msg;
548
+    msg << "invalid value for \"mapping " << distri.getNo() << " "
549
+            << strColor << "\": invalid value \"" << valFields[2]
550
+            << "\"for \"base\": " << ex.what();
551
+    throw std::runtime_error(msg.str());
552
+  }
553
+
554
+  // set mapping of distributor
555
+  distri.setMapping(channel, Mapping(base, factor, gamma));
556
+}
557
+
558
+/**
559
+ * @brief process output line from config file
560
+ * @param[in] setFields fields of the setting parts
561
+ * @param[in] valFields fields of the value part
562
+ * @throws std::exception in case of error
563
+ */
564
+void Config::proc_output(std::vector<std::string> const &setFields,
565
+                         std::vector<std::string> const &valFields)
566
+{
567
+  // check number of setting fields
568
+  if (setFields.size() != 2) {
569
+    std::stringstream msg;
570
+    msg << "invalid \"output\" setting with " << setFields.size()
571
+        << " fields, expected \"output <distno>,<outno>\"";
572
+    throw std::runtime_error(msg.str());
573
+  }
574
+
575
+  // parse distributor and output numbers
576
+  unsigned long distno, outno;
577
+  try {
578
+    str2ul2(setFields[1], distno, outno);
579
+  } catch (std::exception &ex) {
580
+    std::stringstream msg;
581
+    msg << "invalid output specifier \"" << setFields[1]
582
+        << "\": expected \"<distno>,<outno>\": " << ex.what();
583
+    throw std::runtime_error(msg.str());
584
+  }
585
+
586
+  // get distributor
587
+  Distri &distri = getDistri(distno);
588
+
589
+  // check output number
590
+  unsigned long outputs = distri.getOutputs();
591
+  if (outno > outputs) {
592
+    std::stringstream msg;
593
+    msg << "invalid output number " << outno << " for distributor " << distno
594
+        << ": only " << outputs << " outputs available";
595
+    throw std::runtime_error(msg.str());
596
+  }
597
+
598
+  // parse all pixels
599
+  unsigned long pixels = distri.getPixels();
600
+  std::vector<std::string>::const_iterator pix;
601
+  unsigned long p;
602
+  for (pix = valFields.begin(), p = 0; pix != valFields.end(); ++pix, ++p) {
603
+    // check maximum number of pixels
604
+    if (p >= pixels) {
605
+      std::stringstream msg;
606
+      msg << "too many pixels (" << (p + 1) << ")"
607
+          << p << " for output " << outno << " of distributor " << distno
608
+          << ": only " << pixels << " pixels supported";
609
+      throw std::runtime_error(msg.str());
610
+    }
611
+    // parse pixel description
612
+    double x, y, r;
613
+    try {
614
+      str2d3(*pix, x, y, r);
615
+    } catch (std::exception &ex) {
616
+      std::stringstream msg;
617
+      msg << "invalid pixel description \"" << *pix << "\" for pixel "
618
+          << p << " at output " << outno << " of distributor " << distno
619
+          << ": expected \"<x>,<y>,<r>\": " << ex.what();
620
+      throw std::runtime_error(msg.str());
621
+    }
622
+    // add pixel
623
+    // TODO
624
+    (void)x;
625
+    (void)y;
626
+    (void)r;
627
+  } // for pixel
628
+}
629
+
630
+/**
631
+ * @brief get distributor
632
+ * @param[in] strDistno distributor number as string
633
+ * @return reference to distributor object in map
634
+ * @throws std::exception in case of error
635
+ */
636
+Distri & Config::getDistri(std::string const &strDistno)
637
+{
638
+  unsigned long distno;
639
+  try {
640
+    distno = str2ul(strDistno);
641
+  } catch (std::exception &ex) {
642
+    std::stringstream msg;
643
+    msg << "invalid distributor number \"" << strDistno << "\": "
644
+        << ex.what();
645
+    throw std::runtime_error(msg.str());
646
+  }
647
+  return getDistri(distno);
648
+}
649
+
650
+/**
651
+ * @brief get distributor
652
+ * @param[in] distno distributor number
653
+ * @return reference to distributor object in map
654
+ * @throws std::exception in case of error
655
+ */
656
+Distri & Config::getDistri(unsigned long distno)
657
+{
658
+  DistriMap::iterator distri = m_distriMap.find(distno);
659
+  if (distri == m_distriMap.end()) {
660
+    std::stringstream msg;
661
+    msg << "no distributor with number \"" << distno << "\" found";
662
+    throw std::runtime_error(msg.str());
663
+  }
664
+  return distri->second;
665
+}
666
+
... ...
@@ -20,9 +20,12 @@
20 20
 #ifndef CONFIG_H
21 21
 #define CONFIG_H
22 22
 
23
+#include <map>
23 24
 #include <string>
24 25
 #include <vector>
25 26
 
27
+#include "distri.h"
28
+
26 29
 /// config file
27 30
 class Config
28 31
 {
... ...
@@ -33,6 +36,10 @@ public:
33 36
    */
34 37
   Config(std::string const &configFile);
35 38
 
39
+protected:
40
+  /// distributor map: distributor number -> distributor object
41
+  typedef std::map<unsigned long, Distri> DistriMap;
42
+
36 43
 protected:
37 44
   /**
38 45
    * @brief remove whitespace at beging and end of string
... ...
@@ -47,6 +54,52 @@ protected:
47 54
    */
48 55
   static void split(std::string const &str, std::vector<std::string> &fields);
49 56
 
57
+  /**
58
+   * @brief split string at specific character
59
+   * @param[in] str string to split
60
+   * @param[in] delim delimiter character
61
+   * @param[out] fields fields of string
62
+   */
63
+  static void split_chr(std::string const &str, char delim,
64
+                        std::vector<std::string> &fields);
65
+
66
+  /**
67
+   * @brief convert string to unsigned long
68
+   * @param[in] str string to convert
69
+   * @return unsigned long parsed from string
70
+   * @throws std::exception in case of error
71
+   */
72
+  static unsigned long str2ul(std::string const &str);
73
+
74
+  /**
75
+   * @brief convert string to two unsigned longs
76
+   * @param[in] str string containing two comma-separated unsigned integers
77
+   * @param[out] ul1 first unsigned long parsed from string
78
+   * @param[out] ul2 second unsigned long parsed from string
79
+   * @throws std::exception in case of error
80
+   */
81
+  static void str2ul2(std::string const &str,
82
+                      unsigned long &ul1, unsigned long &ul2);
83
+
84
+  /**
85
+   * @brief convert string to double (using the decimal dot for any locale)
86
+   * @param[in] str string to convert
87
+   * @return double parsed from string
88
+   * @throws std::exception in case of error
89
+   */
90
+  static double str2d(std::string const &str);
91
+
92
+  /**
93
+   * @brief convert string to three doubles (decimal dot for any locale)
94
+   * @param[in] str string containing three comma-separated doubles
95
+   * @param[out] d1 first double parsed from string
96
+   * @param[out] d2 second double parsed from string
97
+   * @param[out] d3 third double parsed from string
98
+   * @throws std::exception in case of error
99
+   */
100
+  static void str2d3(std::string const &str,
101
+                     double &d1, double &d2, double &d3);
102
+
50 103
   /**
51 104
    * @brief read config file
52 105
    * @param[in] configFile name of config file
... ...
@@ -69,6 +122,61 @@ protected:
69 122
    */
70 123
   void procSetting(std::string const &setting, std::string const &value);
71 124
 
125
+  /**
126
+   * @brief process distributor line from config file
127
+   * @param[in] setFields fields of the setting parts
128
+   * @param[in] valFields fields of the value part
129
+   * @throws std::exception in case of error
130
+   */
131
+  void proc_distributor(std::vector<std::string> const &setFields,
132
+                        std::vector<std::string> const &valFields);
133
+
134
+  /**
135
+   * @brief process distributorAddr line from config file
136
+   * @param[in] setFields fields of the setting parts
137
+   * @param[in] valFields fields of the value part
138
+   * @throws std::exception in case of error
139
+   */
140
+  void proc_distributorAddr(std::vector<std::string> const &setFields,
141
+                            std::vector<std::string> const &valFields);
142
+
143
+  /**
144
+   * @brief process mapping line from config file
145
+   * @param[in] setFields fields of the setting parts
146
+   * @param[in] valFields fields of the value part
147
+   * @throws std::exception in case of error
148
+   */
149
+  void proc_mapping(std::vector<std::string> const &setFields,
150
+                    std::vector<std::string> const &valFields);
151
+
152
+  /**
153
+   * @brief process output line from config file
154
+   * @param[in] setFields fields of the setting parts
155
+   * @param[in] valFields fields of the value part
156
+   * @throws std::exception in case of error
157
+   */
158
+  void proc_output(std::vector<std::string> const &setFields,
159
+                   std::vector<std::string> const &valFields);
160
+
161
+  /**
162
+   * @brief get distributor
163
+   * @param[in] strDistno distributor number as string
164
+   * @return reference to distributor object in map
165
+   * @throws std::exception in case of error
166
+   */
167
+  Distri & getDistri(std::string const &strDistno);
168
+
169
+  /**
170
+   * @brief get distributor
171
+   * @param[in] distno distributor number
172
+   * @return reference to distributor object in map
173
+   * @throws std::exception in case of error
174
+   */
175
+  Distri & getDistri(unsigned long distno);
176
+
177
+protected:
178
+  /// distributors
179
+  DistriMap m_distriMap;
72 180
 };
73 181
 
74 182
 #endif // #ifndef CONFIG_H
... ...
@@ -41,14 +41,14 @@ mapping 0 blue = 0.0 1.0 1.0
41 41
 # for each pixel, the position and size if specified relative to the
42 42
 # simulator window dimensions
43 43
 # syntax:
44
-#   output <distno>,<outno> = <px 1 x>,<px 1 y>,<px 1 size>
45
-#   <px 2 x>,<px 2 y>,<px 2 size> ... <pixel N>
44
+#   output <distno>,<outno> = <px 1 x>,<px 1 y>,<px 1 r>
45
+#   <px 2 x>,<px 2 y>,<px 2 r> ... <pixel N>
46 46
 # description:
47 47
 #   distno: number of distributor
48 48
 #   outno: number of output of distributor
49 49
 #   px i x/y: the x/y coordinates of the simulated pixel of the video pixel
50 50
 #             in the simulator window
51
-#   px i size: the size of the simulated pixel of the video pixel in the
51
+#   px i r: the radius of the simulated pixel of the video pixel in the
52 52
   #         simulator window
53 53
 output 0,0 = 0.0125,0.5125,0.0110485 0.0125,0.5375,0.0110485 0.0125,0.5625,0.0110485 0.0125,0.5875,0.0110485 0.0125,0.6125,0.0110485 0.0125,0.6375,0.0110485 0.0125,0.6625,0.0110485 0.0125,0.6875,0.0110485 0.0125,0.7125,0.0110485 0.0125,0.7375,0.0110485 0.0125,0.7625,0.0110485 0.0125,0.7875,0.0110485 0.0375,0.7875,0.0110485 0.0375,0.7625,0.0110485 0.0375,0.7375,0.0110485 0.0375,0.7125,0.0110485 0.0375,0.6875,0.0110485 0.0375,0.6625,0.0110485 0.0375,0.6375,0.0110485 0.0375,0.6125,0.0110485 0.0375,0.5875,0.0110485 0.0375,0.5625,0.0110485 0.0375,0.5375,0.0110485 0.0375,0.5125,0.0110485 0.0625,0.5125,0.0110485 0.0625,0.5375,0.0110485 0.0625,0.5625,0.0110485 0.0625,0.5875,0.0110485 0.0625,0.6125,0.0110485 0.0625,0.6375,0.0110485 0.0625,0.6625,0.0110485 0.0625,0.6875,0.0110485 0.0625,0.7125,0.0110485 0.0625,0.7375,0.0110485 0.0625,0.7625,0.0110485 0.0625,0.7875,0.0110485 0.0875,0.7875,0.0110485 0.0875,0.7625,0.0110485 0.0875,0.7375,0.0110485 0.0875,0.7125,0.0110485 0.0875,0.6875,0.0110485 0.0875,0.6625,0.0110485 0.0875,0.6375,0.0110485 0.0875,0.6125,0.0110485 0.0875,0.5875,0.0110485 0.0875,0.5625,0.0110485 0.0875,0.5375,0.0110485 0.0875,0.5125,0.0110485 0.1125,0.5125,0.0110485 0.1125,0.5375,0.0110485 0.1125,0.5625,0.0110485 0.1125,0.5875,0.0110485 0.1125,0.6125,0.0110485 0.1125,0.6375,0.0110485 0.1125,0.6625,0.0110485 0.1125,0.6875,0.0110485 0.1125,0.7125,0.0110485 0.1125,0.7375,0.0110485 0.1125,0.7625,0.0110485 0.1125,0.7875,0.0110485 0.1375,0.7875,0.0110485 0.1375,0.7625,0.0110485 0.1375,0.7375,0.0110485 0.1375,0.7125,0.0110485 0.1375,0.6875,0.0110485 0.1375,0.6625,0.0110485 0.1375,0.6375,0.0110485 0.1375,0.6125,0.0110485 0.1375,0.5875,0.0110485 0.1375,0.5625,0.0110485 0.1375,0.5375,0.0110485 0.1375,0.5125,0.0110485 0.1625,0.5125,0.0110485 0.1625,0.5375,0.0110485 0.1625,0.5625,0.0110485 0.1625,0.5875,0.0110485 0.1625,0.6125,0.0110485 0.1625,0.6375,0.0110485 0.1625,0.6625,0.0110485 0.1625,0.6875,0.0110485 0.1625,0.7125,0.0110485 0.1625,0.7375,0.0110485 0.1625,0.7625,0.0110485 0.1625,0.7875,0.0110485 0.1875,0.7875,0.0110485 0.1875,0.7625,0.0110485 0.1875,0.7375,0.0110485 0.1875,0.7125,0.0110485 0.1875,0.6875,0.0110485 0.1875,0.6625,0.0110485 0.1875,0.6375,0.0110485 0.1875,0.6125,0.0110485 0.1875,0.5875,0.0110485 0.1875,0.5625,0.0110485 0.1875,0.5375,0.0110485 0.1875,0.5125,0.0110485
54 54
 output 0,1 = 0.0125,0.2125,0.0110485 0.0125,0.2375,0.0110485 0.0125,0.2625,0.0110485 0.0125,0.2875,0.0110485 0.0125,0.3125,0.0110485 0.0125,0.3375,0.0110485 0.0125,0.3625,0.0110485 0.0125,0.3875,0.0110485 0.0125,0.4125,0.0110485 0.0125,0.4375,0.0110485 0.0125,0.4625,0.0110485 0.0125,0.4875,0.0110485 0.0375,0.4875,0.0110485 0.0375,0.4625,0.0110485 0.0375,0.4375,0.0110485 0.0375,0.4125,0.0110485 0.0375,0.3875,0.0110485 0.0375,0.3625,0.0110485 0.0375,0.3375,0.0110485 0.0375,0.3125,0.0110485 0.0375,0.2875,0.0110485 0.0375,0.2625,0.0110485 0.0375,0.2375,0.0110485 0.0375,0.2125,0.0110485 0.0625,0.2125,0.0110485 0.0625,0.2375,0.0110485 0.0625,0.2625,0.0110485 0.0625,0.2875,0.0110485 0.0625,0.3125,0.0110485 0.0625,0.3375,0.0110485 0.0625,0.3625,0.0110485 0.0625,0.3875,0.0110485 0.0625,0.4125,0.0110485 0.0625,0.4375,0.0110485 0.0625,0.4625,0.0110485 0.0625,0.4875,0.0110485 0.0875,0.4875,0.0110485 0.0875,0.4625,0.0110485 0.0875,0.4375,0.0110485 0.0875,0.4125,0.0110485 0.0875,0.3875,0.0110485 0.0875,0.3625,0.0110485 0.0875,0.3375,0.0110485 0.0875,0.3125,0.0110485 0.0875,0.2875,0.0110485 0.0875,0.2625,0.0110485 0.0875,0.2375,0.0110485 0.0875,0.2125,0.0110485 0.1125,0.2125,0.0110485 0.1125,0.2375,0.0110485 0.1125,0.2625,0.0110485 0.1125,0.2875,0.0110485 0.1125,0.3125,0.0110485 0.1125,0.3375,0.0110485 0.1125,0.3625,0.0110485 0.1125,0.3875,0.0110485 0.1125,0.4125,0.0110485 0.1125,0.4375,0.0110485 0.1125,0.4625,0.0110485 0.1125,0.4875,0.0110485 0.1375,0.4875,0.0110485 0.1375,0.4625,0.0110485 0.1375,0.4375,0.0110485 0.1375,0.4125,0.0110485 0.1375,0.3875,0.0110485 0.1375,0.3625,0.0110485 0.1375,0.3375,0.0110485 0.1375,0.3125,0.0110485 0.1375,0.2875,0.0110485 0.1375,0.2625,0.0110485 0.1375,0.2375,0.0110485 0.1375,0.2125,0.0110485 0.1625,0.2125,0.0110485 0.1625,0.2375,0.0110485 0.1625,0.2625,0.0110485 0.1625,0.2875,0.0110485 0.1625,0.3125,0.0110485 0.1625,0.3375,0.0110485 0.1625,0.3625,0.0110485 0.1625,0.3875,0.0110485 0.1625,0.4125,0.0110485 0.1625,0.4375,0.0110485 0.1625,0.4625,0.0110485 0.1625,0.4875,0.0110485 0.1875,0.4875,0.0110485 0.1875,0.4625,0.0110485 0.1875,0.4375,0.0110485 0.1875,0.4125,0.0110485 0.1875,0.3875,0.0110485 0.1875,0.3625,0.0110485 0.1875,0.3375,0.0110485 0.1875,0.3125,0.0110485 0.1875,0.2875,0.0110485 0.1875,0.2625,0.0110485 0.1875,0.2375,0.0110485 0.1875,0.2125,0.0110485
... ...
@@ -0,0 +1,78 @@
1
+/*
2
+ * EtherPix simulator
3
+ *
4
+ * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, version 3 of the License.
9
+ *
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include <sstream>
21
+#include <stdexcept>
22
+
23
+#include "distri.h"
24
+
25
+/// constructor
26
+Distri::Distri():
27
+  m_distno(0),
28
+  m_outputs(0),
29
+  m_pixels(0)
30
+{
31
+}
32
+
33
+/**
34
+ * @brief initialize
35
+ * @param[in] distno distributor number
36
+ * @param[in] outputs number of outputs
37
+ * @param[in] pixels number of pixels per output
38
+ */
39
+void Distri::init(unsigned long distno, unsigned long outputs,
40
+                  unsigned long pixels)
41
+{
42
+  m_distno = distno;
43
+  m_outputs = outputs;
44
+  m_pixels = pixels;
45
+}
46
+
47
+/**
48
+ * @brief get mapping
49
+ * @param[in] chan color channel
50
+ * @return mapping mapping object of color channel
51
+ * @throws std::exception in case of error
52
+ */
53
+Mapping const& Distri::getMapping(Mapping::Channel chan) const
54
+{
55
+  if (chan >= Mapping::ChannelCount) {
56
+    std::stringstream msg;
57
+    msg << "invalid channel: " << chan;
58
+    throw std::runtime_error(msg.str());
59
+  }
60
+  return m_mappings[chan];
61
+}
62
+
63
+/**
64
+ * @brief set mapping
65
+ * @param[in] chan color channel
66
+ * @param[in] mapping new mapping object for color channel
67
+ * @throws std::exception in case of error
68
+ */
69
+void Distri::setMapping(Mapping::Channel chan, Mapping const &mapping)
70
+{
71
+  if (chan >= Mapping::ChannelCount) {
72
+    std::stringstream msg;
73
+    msg << "invalid channel: " << chan;
74
+    throw std::runtime_error(msg.str());
75
+  }
76
+  m_mappings[chan] = mapping;
77
+}
78
+
... ...
@@ -0,0 +1,77 @@
1
+/*
2
+ * EtherPix simulator
3
+ *
4
+ * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, version 3 of the License.
9
+ *
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef DISTRI_H
21
+#define DISTRI_H
22
+
23
+#include "mapping.h"
24
+
25
+/// distributor
26
+class Distri
27
+{
28
+public:
29
+  /// constructor
30
+  Distri();
31
+
32
+  /**
33
+   * @brief initialize
34
+   * @param[in] distno distributor number
35
+   * @param[in] outputs number of outputs
36
+   * @param[in] pixels number of pixels per output
37
+   */
38
+  void init(unsigned long distno, unsigned long outputs, unsigned long pixels);
39
+
40
+  /// get distributor number
41
+  unsigned long getNo() const { return m_distno; }
42
+
43
+  /// get number of outputs
44
+  unsigned long getOutputs() const { return m_outputs; }
45
+
46
+  /// get number of pixels at each output
47
+  unsigned long getPixels() const { return m_pixels; }
48
+
49
+  /**
50
+   * @brief get mapping
51
+   * @param[in] chan color channel
52
+   * @return mapping mapping object of color channel
53
+   * @throws std::exception in case of error
54
+   */
55
+  Mapping const& getMapping(Mapping::Channel chan) const;
56
+
57
+  /**
58
+   * @brief set mapping
59
+   * @param[in] chan color channel
60
+   * @param[in] mapping new mapping object for color channel
61
+   * @throws std::exception in case of error
62
+   */
63
+  void setMapping(Mapping::Channel chan, Mapping const &mapping);
64
+
65
+protected:
66
+   /// distributor number
67
+   unsigned long m_distno;
68
+   /// number of outputs
69
+   unsigned long m_outputs;
70
+   /// number of pixels per output
71
+   unsigned long m_pixels;
72
+   /// mappings of color channels
73
+   Mapping m_mappings[Mapping::ChannelCount];
74
+};
75
+
76
+#endif // #ifndef DISTRI_H
77
+
... ...
@@ -0,0 +1,37 @@
1
+/*
2
+ * EtherPix simulator
3
+ *
4
+ * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, version 3 of the License.
9
+ *
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include "mapping.h"
21
+
22
+/// default constructor
23
+Mapping::Mapping():
24
+  m_base(1.0),
25
+  m_factor(0.0),
26
+  m_gamma(1.0)
27
+{
28
+}
29
+
30
+/// constructor based on parameters
31
+Mapping::Mapping(double base, double factor, double gamma):
32
+  m_base(base),
33
+  m_factor(factor),
34
+  m_gamma(gamma)
35
+{
36
+}
37
+
... ...
@@ -0,0 +1,52 @@
1
+/*
2
+ * EtherPix simulator
3
+ *
4
+ * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, version 3 of the License.
9
+ *
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#ifndef MAPPING_H
21
+#define MAPPING_H
22
+
23
+/// mapping of input values to LED output values for a color channel
24
+class Mapping
25
+{
26
+public:
27
+  /// color channel number
28
+  enum Channel {
29
+    Red,
30
+    Green,
31
+    Blue,
32
+    ChannelCount
33
+  };
34
+
35
+public:
36
+  /// default constructor
37
+  Mapping();
38
+
39
+  /// constructor based on parameters
40
+  Mapping(double base, double factor, double gamma);
41
+
42
+protected:
43
+   /// parameters of mapping: display := base + factor * video ** (1.0 / gamma)
44
+   //@{
45
+   double m_base;
46
+   double m_factor;
47
+   double m_gamma;
48
+   //@}
49
+};
50
+
51
+#endif // #ifndef MAPPING_H
52
+
0 53