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