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