B15F
Board 15 Famulus Edition
b15f.cpp
1 #include "b15f.h"
2 
3 B15F *B15F::instance = nullptr;
4 errorhandler_t B15F::errorhandler = nullptr;
5 
6 
7 /*************************************
8  * Grundfunktionen des B15F Treibers *
9  *************************************/
10 
12 {
13  if (!instance)
14  instance = new B15F();
15 
16  return *instance;
17 }
18 
19 void B15F::reconnect()
20 {
21  uint8_t tries = RECONNECT_TRIES;
22  while (tries--)
23  {
25  discard();
26 
27  if (testConnection())
28  return;
29  }
30 
31  abort("Verbindung kann nicht repariert werden");
32 }
33 
34 void B15F::discard(void)
35 {
36  try
37  {
38  uint8_t rq[] =
39  {
40  RQ_DISCARD
41  };
42 
43  usart.clearOutputBuffer();
44  for (uint8_t i = 0; i < 16; i++)
45  {
46  usart.transmit(&rq[0], 0, sizeof(rq)); // sende discard Befehl (verwerfe input)
47  delay_ms(4);
48  }
49  usart.clearInputBuffer();
50  }
51  catch (std::exception &ex)
52  {
53  abort(ex);
54  }
55 }
56 
58 {
59  // erzeuge zufälliges Byte
60  srand(time(NULL));
61  uint8_t dummy = rand() % 256;
62 
63  uint8_t rq[] =
64  {
65  RQ_TEST,
66  dummy
67  };
68  usart.transmit(&rq[0], 0, sizeof(rq));
69 
70  uint8_t aw[2];
71  usart.receive(&aw[0], 0, sizeof(aw));
72 
73  return aw[0] == MSG_OK && aw[1] == dummy;
74 }
75 
76 bool B15F::testIntConv()
77 {
78  srand(time(NULL));
79  uint16_t dummy = rand() % (0xFFFF / 3);
80 
81  uint8_t rq[] =
82  {
83  RQ_INT_TEST,
84  static_cast<uint8_t >(dummy & 0xFF),
85  static_cast<uint8_t >(dummy >> 8)
86  };
87  usart.transmit(&rq[0], 0, sizeof(rq));
88 
89  uint16_t aw;
90  usart.receive(reinterpret_cast<uint8_t *>(&aw), 0, sizeof(aw));
91 
92  return aw == dummy * 3;
93 }
94 
95 
96 std::vector<std::string> B15F::getBoardInfo(void)
97 {
98  std::vector<std::string> info;
99 
100  uint8_t rq[] =
101  {
102  RQ_INFO
103  };
104  usart.transmit(&rq[0], 0, sizeof(rq));
105 
106  uint8_t n;
107  usart.receive(&n, 0, sizeof(n));
108  while (n--)
109  {
110  uint8_t len;
111  usart.receive(&len, 0, sizeof(len));
112 
113  char str[len + 1];
114  str[len] = '\0';
115  usart.receive(reinterpret_cast<uint8_t *>(&str[0]), 0, len);
116 
117  info.push_back(std::string(str));
118  }
119 
120  uint8_t aw;
121  usart.receive(&aw, 0, sizeof(aw));
122  if (aw != MSG_OK)
123  abort("Board Info fehlerhalft: code " + std::to_string((int) aw));
124 
125  return info;
126 }
127 
128 void B15F::delay_ms(uint16_t ms)
129 {
130  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
131 }
132 
133 void B15F::delay_us(uint16_t us)
134 {
135  std::this_thread::sleep_for(std::chrono::microseconds(us));
136 }
137 
138 void B15F::reverse(uint8_t& b)
139 {
140  b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
141  b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
142  b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
143 }
144 
145 // https://stackoverflow.com/a/478960
146 std::string B15F::exec(std::string cmd)
147 {
148  std::array<char, 128> buffer;
149  std::string result;
150  std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
151  if (!pipe)
152  {
153  throw std::runtime_error("popen() failed!");
154  }
155  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
156  {
157  result += buffer.data();
158  }
159  return result;
160 }
161 
162 void B15F::abort(std::string msg)
163 {
164  DriverException ex(msg);
165  abort(ex);
166 }
167 
168 void B15F::abort(std::exception &ex)
169 {
170  if (errorhandler)
171  errorhandler(ex);
172  else
173  {
174  std::cerr << "NOTICE: B15F::errorhandler not set" << std::endl;
175  std::cout << ex.what() << std::endl;
176  throw DriverException(ex.what());
177  }
178 }
179 
180 void B15F::setAbortHandler(errorhandler_t func)
181 {
182  errorhandler = func;
183 }
184 
185 /*************************************/
186 
187 
188 
189 /*************************
190  * Steuerbefehle für B15 *
191  *************************/
192 
194 {
195  uint8_t rq[] =
196  {
197  RQ_SELF_TEST
198  };
199  usart.transmit(&rq[0], 0, sizeof(rq));
200 
201  uint8_t aw;
202  usart.receive(&aw, 0, sizeof(aw));
203  return aw == MSG_OK;
204 }
205 
206 bool B15F::digitalWrite0(uint8_t port)
207 {
208  uint8_t rq[] =
209  {
210  RQ_DIGITAL_WRITE_0,
211  port
212  };
213  usart.transmit(&rq[0], 0, sizeof(rq));
214 
215  uint8_t aw;
216  usart.receive(&aw, 0, sizeof(aw));
217  return aw == MSG_OK;
218 }
219 
220 bool B15F::digitalWrite1(uint8_t port)
221 {
222  uint8_t rq[] =
223  {
224  RQ_DIGITAL_WRITE_1,
225  port
226  };
227  usart.transmit(&rq[0], 0, sizeof(rq));
228 
229  uint8_t aw;
230  usart.receive(&aw, 0, sizeof(aw));
231  return aw == MSG_OK;
232 }
233 
234 uint8_t B15F::digitalRead0()
235 {
236  usart.clearInputBuffer();
237  uint8_t rq[] =
238  {
239  RQ_DIGITAL_READ_0
240  };
241  usart.transmit(&rq[0], 0, sizeof(rq));
242 
243  uint8_t aw;
244  usart.receive(&aw, 0, sizeof(aw));
245  return aw;
246 }
247 
248 uint8_t B15F::digitalRead1()
249 {
250  usart.clearInputBuffer();
251  uint8_t rq[] =
252  {
253  RQ_DIGITAL_READ_1
254  };
255  usart.transmit(&rq[0], 0, sizeof(rq));
256 
257  uint8_t aw;
258  usart.receive(&aw, 0, sizeof(aw));
259  return aw;
260 }
261 
262 uint8_t B15F::readDipSwitch()
263 {
264  usart.clearInputBuffer();
265  uint8_t rq[] =
266  {
267  RQ_READ_DIP_SWITCH
268  };
269  usart.transmit(&rq[0], 0, sizeof(rq));
270 
271  uint8_t aw;
272  usart.receive(&aw, 0, sizeof(aw));
273 
274  reverse(aw); // DIP Schalter muss invertiert werden!
275 
276  return aw;
277 }
278 
279 bool B15F::analogWrite0(uint16_t value)
280 {
281  uint8_t rq[] =
282  {
283  RQ_ANALOG_WRITE_0,
284  static_cast<uint8_t >(value & 0xFF),
285  static_cast<uint8_t >(value >> 8)
286  };
287  usart.transmit(&rq[0], 0, sizeof(rq));
288 
289  uint8_t aw;
290  usart.receive(&aw, 0, sizeof(aw));
291  return aw == MSG_OK;
292 }
293 
294 bool B15F::analogWrite1(uint16_t value)
295 {
296  uint8_t rq[] =
297  {
298  RQ_ANALOG_WRITE_1,
299  static_cast<uint8_t >(value & 0xFF),
300  static_cast<uint8_t >(value >> 8)
301  };
302  usart.transmit(&rq[0], 0, sizeof(rq));
303 
304  uint8_t aw;
305  usart.receive(&aw, 0, sizeof(aw));
306  return aw == MSG_OK;
307 }
308 
309 uint16_t B15F::analogRead(uint8_t channel)
310 {
311  usart.clearInputBuffer();
312  if (channel > 7)
313  abort("Bad ADC channel: " + std::to_string(channel));
314 
315  uint8_t rq[] =
316  {
317  RQ_ANALOG_READ,
318  channel
319  };
320 
321  usart.transmit(&rq[0], 0, sizeof(rq));
322 
323  uint16_t aw;
324  usart.receive(reinterpret_cast<uint8_t *>(&aw), 0, sizeof(aw));
325 
326  if (aw > 1023)
327  abort("Bad ADC data detected (1)");
328  return aw;
329 }
330 
331 void
332 B15F::analogSequence(uint8_t channel_a, uint16_t *buffer_a, uint32_t offset_a, uint8_t channel_b, uint16_t *buffer_b,
333  uint32_t offset_b, uint16_t start, int16_t delta, uint16_t count)
334 {
335  // prepare pointers
336  buffer_a += offset_a;
337  buffer_b += offset_b;
338 
339 
340  usart.clearInputBuffer();
341  uint8_t rq[] =
342  {
343  RQ_ADC_DAC_STROKE,
344  channel_a,
345  channel_b,
346  static_cast<uint8_t >(start & 0xFF),
347  static_cast<uint8_t >(start >> 8),
348  static_cast<uint8_t >(delta & 0xFF),
349  static_cast<uint8_t >(delta >> 8),
350  static_cast<uint8_t >(count & 0xFF),
351  static_cast<uint8_t >(count >> 8)
352  };
353 
354  usart.transmit(&rq[0], 0, sizeof(rq));
355 
356  for (uint16_t i = 0; i < count; i++)
357  {
358  if (buffer_a)
359  {
360  usart.receive(reinterpret_cast<uint8_t *>(&buffer_a[i]), 0, 2);
361 
362  if (buffer_a[i] > 1023) // check for broken usart connection
363  abort("Bad ADC data detected (2)");
364  }
365  else
366  {
367  usart.drop(2);
368  }
369 
370  if (buffer_b)
371  {
372  usart.receive(reinterpret_cast<uint8_t *>(&buffer_b[i]), 0, 2);
373 
374  if (buffer_b[i] > 1023) // check for broken usart connection
375  abort("Bad ADC data detected (3)");
376  }
377  else
378  {
379  usart.drop(2);
380  }
381  }
382 
383  uint8_t aw;
384  usart.receive(&aw, 0, sizeof(aw));
385  if(aw != MSG_OK)
386  abort("Sequenz unterbrochen");
387 }
388 
389 uint8_t B15F::pwmSetFrequency(uint32_t freq)
390 {
391  usart.clearInputBuffer();
392 
393  uint8_t rq[] =
394  {
395  RQ_PWM_SET_FREQ,
396  static_cast<uint8_t>((freq >> 0) & 0xFF),
397  static_cast<uint8_t>((freq >> 8) & 0xFF),
398  static_cast<uint8_t>((freq >> 16) & 0xFF),
399  static_cast<uint8_t>((freq >> 24) & 0xFF)
400  };
401 
402  usart.transmit(&rq[0], 0, sizeof(rq));
403 
404  uint8_t aw;
405  usart.receive(&aw, 0, sizeof(aw));
406  return aw;
407 }
408 
409 bool B15F::pwmSetValue(uint8_t value)
410 {
411  usart.clearInputBuffer();
412 
413  uint8_t rq[] =
414  {
415  RQ_PWM_SET_VALUE,
416  value
417  };
418 
419  usart.transmit(&rq[0], 0, sizeof(rq));
420 
421  uint8_t aw;
422  usart.receive(&aw, 0, sizeof(aw));
423  return aw == MSG_OK;
424 }
425 
426 bool B15F::setMem8(volatile uint16_t* adr, uint8_t val)
427 {
428  usart.clearInputBuffer();
429 
430  uint8_t rq[] =
431  {
432  RQ_SET_MEM_8,
433  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) & 0xFF),
434  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) >> 8),
435  val
436  };
437 
438  usart.transmit(&rq[0], 0, sizeof(rq));
439 
440  uint8_t aw;
441  usart.receive(&aw, 0, sizeof(aw));
442  return aw == val;
443 }
444 
445 uint8_t B15F::getMem8(volatile uint16_t* adr)
446 {
447  usart.clearInputBuffer();
448 
449  uint8_t rq[] =
450  {
451  RQ_GET_MEM_8,
452  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) & 0xFF),
453  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) >> 8)
454  };
455 
456  usart.transmit(&rq[0], 0, sizeof(rq));
457 
458  uint8_t aw;
459  usart.receive(&aw, 0, sizeof(aw));
460  return aw;
461 }
462 
463 bool B15F::setMem16(volatile uint16_t* adr, uint16_t val)
464 {
465  usart.clearInputBuffer();
466 
467  uint8_t rq[] =
468  {
469  RQ_SET_MEM_16,
470  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) & 0xFF),
471  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) >> 8),
472  static_cast<uint8_t >(val & 0xFF),
473  static_cast<uint8_t >(val >> 8)
474  };
475 
476  usart.transmit(&rq[0], 0, sizeof(rq));
477 
478  uint16_t aw;
479  usart.receive(reinterpret_cast<uint8_t *>(&aw), 0, sizeof(aw));
480  return aw == val;
481 }
482 
483 uint16_t B15F::getMem16(volatile uint16_t* adr)
484 {
485  usart.clearInputBuffer();
486 
487  uint8_t rq[] =
488  {
489  RQ_GET_MEM_16,
490  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) & 0xFF),
491  static_cast<uint8_t >(reinterpret_cast<size_t>(adr) >> 8)
492  };
493 
494  usart.transmit(&rq[0], 0, sizeof(rq));
495 
496  uint16_t aw;
497  usart.receive(reinterpret_cast<uint8_t *>(&aw), 0, sizeof(aw));
498  return aw;
499 }
500 
501 bool B15F::setRegister(volatile uint8_t* adr, uint8_t val)
502 {
503  return setMem8(reinterpret_cast<volatile uint16_t*>(adr), val);
504 }
505 
506 uint8_t B15F::getRegister(volatile uint8_t* adr)
507 {
508  return getMem8(reinterpret_cast<volatile uint16_t*>(adr));
509 }
510 
511 /*************************/
512 
513 
514 /**********************
515  * Private Funktionen *
516  **********************/
517 
518 B15F::B15F()
519 {
520  init();
521 }
522 
523 
524 void B15F::init()
525 {
526 
527  std::string device = exec("bash -c 'ls /dev/ttyUSB*'");
528  while (device.find(' ') != std::string::npos || device.find('\n') != std::string::npos ||
529  device.find('\t') != std::string::npos)
530  device.pop_back();
531 
532  if (device.length() == 0)
533  abort("Adapter nicht gefunden");
534 
535  std::cout << PRE << "Verwende Adapter: " << device << std::endl;
536 
537 
538  std::cout << PRE << "Stelle Verbindung mit Adapter her... " << std::flush;
539  usart.setBaudrate(BAUDRATE);
540  usart.openDevice(device);
541  std::cout << "OK" << std::endl;
542 
543 
544  std::cout << PRE << "Teste Verbindung... " << std::flush;
545  uint8_t tries = 3;
546  while (tries--)
547  {
548  // verwerfe Daten, die µC noch hat
549  //discard();
550 
551  if (!testConnection())
552  continue;
553 
554  if (!testIntConv())
555  continue;
556 
557  break;
558  }
559  if (tries == 0)
560  abort("Verbindungstest fehlgeschlagen. Neueste Version im Einsatz?");
561  std::cout << "OK" << std::endl;
562 
563 
564  // Gib board info aus
565  std::vector<std::string> info = getBoardInfo();
566  std::cout << PRE << "AVR Firmware Version: " << info[0] << " um " << info[1] << " Uhr (" << info[2] << ")"
567  << std::endl;
568 }
B15F::exec
static std::string exec(std::string cmd)
Definition: b15f.cpp:145
B15F::getMem16
uint16_t getMem16(volatile uint16_t *adr)
Definition: b15f.cpp:481
B15F::delay_us
void delay_us(uint16_t us)
Definition: b15f.cpp:132
B15F::digitalRead0
uint8_t digitalRead0(void)
Definition: b15f.cpp:232
B15F::pwmSetFrequency
uint8_t pwmSetFrequency(uint32_t freq)
Definition: b15f.cpp:387
B15F::analogSequence
void analogSequence(uint8_t channel_a, uint16_t *buffer_a, uint32_t offset_a, uint8_t channel_b, uint16_t *buffer_b, uint32_t offset_b, uint16_t start, int16_t delta, uint16_t count)
Definition: b15f.cpp:330
B15F::testConnection
bool testConnection(void)
Definition: b15f.cpp:56
B15F::readDipSwitch
uint8_t readDipSwitch(void)
Definition: b15f.cpp:260
B15F::getRegister
uint8_t getRegister(volatile uint8_t *adr)
Definition: b15f.cpp:504
B15F::delay_ms
void delay_ms(uint16_t ms)
Definition: b15f.cpp:127
B15F::getInstance
static B15F & getInstance(void)
Definition: b15f.cpp:10
B15F
Definition: b15f.h:33
USART::transmit
void transmit(uint8_t *buffer, uint16_t offset, uint8_t len)
Definition: usart.cpp:75
B15F::abort
static void abort(std::string msg)
Definition: b15f.cpp:161
USART::receive
void receive(uint8_t *buffer, uint16_t offset, uint8_t len)
Definition: usart.cpp:84
USART::clearInputBuffer
void clearInputBuffer(void)
Definition: usart.cpp:54
USART::clearOutputBuffer
void clearOutputBuffer(void)
Definition: usart.cpp:61
B15F::analogRead
uint16_t analogRead(uint8_t channel)
Definition: b15f.cpp:307
B15F::digitalWrite0
bool digitalWrite0(uint8_t)
Definition: b15f.cpp:204
B15F::PRE
const std::string PRE
B15F stdout prefix.
Definition: b15f.h:287
B15F::reverse
void reverse(uint8_t &b)
Definition: b15f.cpp:137
USART::setBaudrate
void setBaudrate(uint32_t baudrate)
Definition: usart.cpp:131
B15F::activateSelfTestMode
bool activateSelfTestMode(void)
Definition: b15f.cpp:191
B15F::getBoardInfo
std::vector< std::string > getBoardInfo(void)
Definition: b15f.cpp:95
B15F::RECONNECT_TIMEOUT
constexpr static uint16_t RECONNECT_TIMEOUT
Time in ms after which a reconnect attempt aborts.
Definition: b15f.h:290
B15F::analogWrite1
bool analogWrite1(uint16_t port)
Definition: b15f.cpp:292
B15F::setMem16
bool setMem16(volatile uint16_t *adr, uint16_t val)
Definition: b15f.cpp:461
B15F::digitalWrite1
bool digitalWrite1(uint8_t)
Definition: b15f.cpp:218
B15F::pwmSetValue
bool pwmSetValue(uint8_t value)
Definition: b15f.cpp:407
B15F::discard
void discard(void)
Definition: b15f.cpp:33
B15F::setRegister
bool setRegister(volatile uint8_t *adr, uint8_t val)
Definition: b15f.cpp:499
B15F::MSG_OK
constexpr static uint8_t MSG_OK
Value to acknowledge a received command.
Definition: b15f.h:288
USART::openDevice
void openDevice(std::string device)
Definition: usart.cpp:9
B15F::digitalRead1
uint8_t digitalRead1(void)
Definition: b15f.cpp:246
B15F::setMem8
bool setMem8(volatile uint16_t *adr, uint8_t val)
Definition: b15f.cpp:424
B15F::reconnect
void reconnect(void)
Definition: b15f.cpp:18
B15F::BAUDRATE
constexpr static uint32_t BAUDRATE
USART baudrate for communication with the MCU.
Definition: b15f.h:293
B15F::setAbortHandler
static void setAbortHandler(errorhandler_t func)
Definition: b15f.cpp:179
USART::drop
void drop(uint8_t len)
Definition: usart.cpp:114
B15F::getMem8
uint8_t getMem8(volatile uint16_t *adr)
Definition: b15f.cpp:443
B15F::analogWrite0
bool analogWrite0(uint16_t port)
Definition: b15f.cpp:277
B15F::RECONNECT_TRIES
constexpr static uint8_t RECONNECT_TRIES
Maximum count of reconnect attempts after which the driver stops.
Definition: b15f.h:292
B15F::testIntConv
bool testIntConv(void)
Definition: b15f.cpp:75
DriverException
Definition: driverexception.h:10