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  std::cout << "len: " << (int) n << std::endl << std::flush;
147  while (n--)
148  {
149  uint8_t len;
150  usart.receive(&len, 0, sizeof(len));
151 
152  char str[len + 1];
153  str[len] = '\0';
154  usart.receive(reinterpret_cast<uint8_t *>(&str[0]), 0, len);
155 
156  std::cout << &str[0] << std::endl;
157 
158  info.push_back(std::string(str));
159  }
160 
161  uint8_t aw;
162  usart.receive(&aw, 0, sizeof(aw));
163  if (aw != MSG_OK)
164  abort("Board Info fehlerhalft: code " + std::to_string((int) aw));
165 
166  return info;
167 }
168 
170 {
171  uint8_t rq[] =
172  {
173  RQ_ST
174  };
175  usart.transmit(&rq[0], 0, sizeof(rq));
176 
177  uint8_t aw;
178  usart.receive(&aw, 0, sizeof(aw));
179  return aw == MSG_OK;
180 }
181 
182 bool B15F::digitalWrite0(uint8_t port)
183 {
184  uint8_t rq[] =
185  {
186  RQ_BA0,
187  port
188  };
189  usart.transmit(&rq[0], 0, sizeof(rq));
190 
191  uint8_t aw;
192  usart.receive(&aw, 0, sizeof(aw));
193  return aw == MSG_OK;
194 }
195 
196 bool B15F::digitalWrite1(uint8_t port)
197 {
198  uint8_t rq[] =
199  {
200  RQ_BA1,
201  port
202  };
203  usart.transmit(&rq[0], 0, sizeof(rq));
204 
205  uint8_t aw;
206  usart.receive(&aw, 0, sizeof(aw));
207  return aw == MSG_OK;
208 }
209 
211 {
212  usart.clearInputBuffer();
213  uint8_t rq[] =
214  {
215  RQ_BE0
216  };
217  usart.transmit(&rq[0], 0, sizeof(rq));
218 
219  uint8_t aw;
220  usart.receive(&aw, 0, sizeof(aw));
221  return aw;
222 }
223 
225 {
226  usart.clearInputBuffer();
227  uint8_t rq[] =
228  {
229  RQ_BE1
230  };
231  usart.transmit(&rq[0], 0, sizeof(rq));
232 
233  uint8_t aw;
234  usart.receive(&aw, 0, sizeof(aw));
235  return aw;
236 }
237 
239 {
240  usart.clearInputBuffer();
241  uint8_t rq[] =
242  {
243  RQ_DSW
244  };
245  usart.transmit(&rq[0], 0, sizeof(rq));
246 
247  uint8_t aw;
248  usart.receive(&aw, 0, sizeof(aw));
249  return aw;
250 }
251 
252 bool B15F::analogWrite0(uint16_t value)
253 {
254  uint8_t rq[] =
255  {
256  RQ_AA0,
257  static_cast<uint8_t >(value & 0xFF),
258  static_cast<uint8_t >(value >> 8)
259  };
260  usart.transmit(&rq[0], 0, sizeof(rq));
261 
262  uint8_t aw;
263  usart.receive(&aw, 0, sizeof(aw));
264  return aw == MSG_OK;
265 }
266 
267 bool B15F::analogWrite1(uint16_t value)
268 {
269  uint8_t rq[] =
270  {
271  RQ_AA1,
272  static_cast<uint8_t >(value & 0xFF),
273  static_cast<uint8_t >(value >> 8)
274  };
275  usart.transmit(&rq[0], 0, sizeof(rq));
276 
277  uint8_t aw;
278  usart.receive(&aw, 0, sizeof(aw));
279  return aw == MSG_OK;
280 }
281 
282 uint16_t B15F::analogRead(uint8_t channel)
283 {
284  usart.clearInputBuffer();
285  if (channel > 7)
286  abort("Bad ADC channel: " + std::to_string(channel));
287 
288  uint8_t rq[] =
289  {
290  RQ_ADC,
291  channel
292  };
293 
294  usart.transmit(&rq[0], 0, sizeof(rq));
295 
296  uint16_t aw;
297  usart.receive(reinterpret_cast<uint8_t*>(&aw), 0, sizeof(aw));
298 
299  if (aw > 1023)
300  abort("Bad ADC data detected (1)");
301  return aw;
302 }
303 
304 void
305 B15F::analogSequence(uint8_t channel_a, uint16_t *buffer_a, uint32_t offset_a, uint8_t channel_b, uint16_t *buffer_b,
306  uint32_t offset_b, uint16_t start, int16_t delta, uint16_t count)
307 {
308  /*
309  // prepare pointers
310  buffer_a += offset_a;
311  buffer_b += offset_b;
312 
313 
314  usart.clearInputBuffer();
315  usart.writeByte(RQ_ADC_DAC_STROKE);
316  usart.writeByte(channel_a);
317  usart.writeByte(channel_b);
318  usart.writeInt(start);
319  usart.writeInt(static_cast<uint16_t>(delta));
320  usart.writeInt(count);
321 
322  for (uint16_t i = 0; i < count; i++) {
323  if (buffer_a) {
324  buffer_a[i] = usart.readInt();
325 
326  if (buffer_a[i] > 1023) // check for broken usart connection
327  abort("Bad ADC data detected (2)");
328  } else {
329  usart.readInt();
330  }
331 
332  if (buffer_b) {
333  buffer_b[i] = usart.readInt();
334 
335  if (buffer_b[i] > 1023) // check for broken usart connection
336  abort("Bad ADC data detected (3)");
337  } else {
338  usart.readInt();
339  }
340  }
341 
342  uint8_t aw = usart.readByte();
343  if (aw != MSG_OK)
344  abort("Sequenz unterbrochen");
345 
346  delay_us(10);*/
347 }
348 
349 uint8_t B15F::pwmSetFrequency(uint32_t freq)
350 {
351  usart.clearInputBuffer();
352 
353  uint8_t rq[] =
354  {
355  RQ_PWM_SET_FREQ,
356  static_cast<uint8_t>((freq >> 0) & 0xFF),
357  static_cast<uint8_t>((freq >> 8) & 0xFF),
358  static_cast<uint8_t>((freq >> 16) & 0xFF),
359  static_cast<uint8_t>((freq >> 24) & 0xFF)
360  };
361 
362  usart.transmit(&rq[0], 0, sizeof(rq));
363 
364  uint8_t aw;
365  usart.receive(&aw, 0, sizeof(aw));
366  return aw;
367 }
368 
369 bool B15F::pwmSetValue(uint8_t value)
370 {
371  usart.clearInputBuffer();
372 
373  uint8_t rq[] =
374  {
375  RQ_PWM_SET_VALUE,
376  value
377  };
378 
379  usart.transmit(&rq[0], 0, sizeof(rq));
380 
381  uint8_t aw;
382  usart.receive(&aw, 0, sizeof(aw));
383  return aw == MSG_OK;
384 }
385 
386 bool B15F::setRegister(uint8_t adr, uint8_t val)
387 {
388  usart.clearInputBuffer();
389 
390  uint8_t rq[] =
391  {
392  RQ_SET_REG,
393  adr,
394  val
395  };
396 
397  usart.transmit(&rq[0], 0, sizeof(rq));
398 
399  uint8_t aw;
400  usart.receive(&aw, 0, sizeof(aw));
401  return aw == val;
402 }
403 
404 uint8_t B15F::getRegister(uint8_t adr)
405 {
406  usart.clearInputBuffer();
407 
408  uint8_t rq[] =
409  {
410  RQ_GET_REG,
411  adr
412  };
413 
414  usart.transmit(&rq[0], 0, sizeof(rq));
415 
416  uint8_t aw;
417  usart.receive(&aw, 0, sizeof(aw));
418  return aw;
419 }
420 
421 
422 void B15F::delay_ms(uint16_t ms)
423 {
424  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
425 }
426 
427 void B15F::delay_us(uint16_t us)
428 {
429  std::this_thread::sleep_for(std::chrono::microseconds(us));
430 }
431 
433 {
434  if (!instance)
435  instance = new B15F();
436 
437  return *instance;
438 }
439 
440 // https://stackoverflow.com/a/478960
441 std::string B15F::exec(std::string cmd)
442 {
443  std::array<char, 128> buffer;
444  std::string result;
445  std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
446  if (!pipe)
447  {
448  throw std::runtime_error("popen() failed!");
449  }
450  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
451  {
452  result += buffer.data();
453  }
454  return result;
455 }
456 
457 void B15F::abort(std::string msg)
458 {
459  DriverException ex(msg);
460  abort(ex);
461 }
462 
463 void B15F::abort(std::exception &ex)
464 {
465  if (errorhandler)
466  errorhandler(ex);
467  else
468  {
469  std::cerr << "NOTICE: B15F::errorhandler not set" << std::endl;
470  std::cout << ex.what() << std::endl;
471  throw DriverException(ex.what());
472  }
473 }
474 
475 void B15F::setAbortHandler(errorhandler_t func)
476 {
477  errorhandler = func;
478 }
B15F::exec
static std::string exec(std::string cmd)
Definition: b15f.cpp:441
B15F::getRegister
uint8_t getRegister(uint8_t adr)
Definition: b15f.cpp:404
B15F::delay_us
void delay_us(uint16_t us)
Definition: b15f.cpp:427
B15F::digitalRead0
uint8_t digitalRead0(void)
Definition: b15f.cpp:210
B15F::pwmSetFrequency
uint8_t pwmSetFrequency(uint32_t freq)
Definition: b15f.cpp:349
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:305
B15F::testConnection
bool testConnection(void)
Definition: b15f.cpp:95
B15F::readDipSwitch
uint8_t readDipSwitch(void)
Definition: b15f.cpp:238
B15F::delay_ms
void delay_ms(uint16_t ms)
Definition: b15f.cpp:422
B15F::setRegister
bool setRegister(uint8_t adr, uint8_t val)
Definition: b15f.cpp:386
B15F::getInstance
static B15F & getInstance(void)
Definition: b15f.cpp:432
B15F
Definition: b15f.h:26
USART::transmit
void transmit(uint8_t *buffer, uint16_t offset, uint8_t len)
Definition: usart.cpp:95
B15F::abort
static void abort(std::string msg)
Definition: b15f.cpp:457
USART::receive
void receive(uint8_t *buffer, uint16_t offset, uint8_t len)
Definition: usart.cpp:75
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:282
B15F::digitalWrite0
bool digitalWrite0(uint8_t)
Definition: b15f.cpp:182
B15F::PRE
const std::string PRE
B15F stdout prefix.
Definition: b15f.h:231
USART::setBaudrate
void setBaudrate(uint32_t baudrate)
Definition: usart.cpp:114
B15F::activateSelfTestMode
bool activateSelfTestMode(void)
Definition: b15f.cpp:169
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:234
B15F::analogWrite1
bool analogWrite1(uint16_t port)
Definition: b15f.cpp:267
B15F::digitalWrite1
bool digitalWrite1(uint8_t)
Definition: b15f.cpp:196
B15F::pwmSetValue
bool pwmSetValue(uint8_t value)
Definition: b15f.cpp:369
B15F::discard
void discard(void)
Definition: b15f.cpp:72
B15F::MSG_OK
constexpr static uint8_t MSG_OK
Value to acknowledge a received command.
Definition: b15f.h:232
USART::openDevice
void openDevice(std::string device)
Definition: usart.cpp:9
B15F::digitalRead1
uint8_t digitalRead1(void)
Definition: b15f.cpp:224
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:237
B15F::setAbortHandler
static void setAbortHandler(errorhandler_t func)
Definition: b15f.cpp:475
B15F::analogWrite0
bool analogWrite0(uint16_t port)
Definition: b15f.cpp:252
B15F::RECONNECT_TRIES
constexpr static uint8_t RECONNECT_TRIES
Maximum count of reconnect attempts after which the driver stops.
Definition: b15f.h:236
B15F::testIntConv
bool testIntConv(void)
Definition: b15f.cpp:114
DriverException
Definition: driverexception.h:10