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
57 void B15F::reconnect()
58 {
59 uint8_t tries = RECONNECT_TRIES;
60 while (tries--)
61 {
62 delay_ms(RECONNECT_TIMEOUT);
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
95 bool B15F::testConnection()
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
114 bool B15F::testIntConv()
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
166 bool B15F::activateSelfTestMode()
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
207 uint8_t B15F::digitalRead0()
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
221 uint8_t B15F::digitalRead1()
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
235 uint8_t B15F::readDipSwitch()
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
442 B15F &B15F::getInstance(void)
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