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