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 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
169 bool B15F::activateSelfTestMode()
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
210 uint8_t B15F::digitalRead0()
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
224 uint8_t B15F::digitalRead1()
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
238 uint8_t B15F::readDipSwitch()
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
432 B15F &B15F::getInstance(void)
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