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  usart.transmit(&rq[0], 0, sizeof(rq));
233 
234  uint16_t adc = usart.readInt();
235 
236  if(adc > 1023)
237  abort("Bad ADC data detected (1)");
238  return adc;
239 }
240 
241 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)
242 {
243  // check pointers
244  buffer_a += offset_a;
245  buffer_b += offset_b;
246 
247 
248  usart.clearInputBuffer();
249  usart.writeByte(RQ_ADC_DAC_STROKE);
250  usart.writeByte(channel_a);
251  usart.writeByte(channel_b);
252  usart.writeInt(start);
253  usart.writeInt(static_cast<uint16_t>(delta));
254  usart.writeInt(count);
255 
256  for(uint16_t i = 0; i < count; i++)
257  {
258  if(buffer_a)
259  {
260  buffer_a[i] = usart.readInt();
261 
262  if(buffer_a[i] > 1023) // check for broken usart connection
263  abort("Bad ADC data detected (2)");
264  }
265  else
266  {
267  usart.readInt();
268  }
269 
270  if(buffer_b)
271  {
272  buffer_b[i] = usart.readInt();
273 
274  if(buffer_b[i] > 1023) // check for broken usart connection
275  abort("Bad ADC data detected (3)");
276  }
277  else
278  {
279  usart.readInt();
280  }
281  }
282 
283  uint8_t aw = usart.readByte();
284  if(aw != MSG_OK)
285  abort("Sequenz unterbrochen");
286 
287  delay_us(10);
288 }
289 
290 uint8_t B15F::pwmSetFrequency(uint32_t freq)
291 {
292  usart.clearInputBuffer();
293 
294  uint8_t rq[] =
295  {
296  RQ_PWM_SET_FREQ,
297  static_cast<uint8_t>((freq >> 0) & 0xFF),
298  static_cast<uint8_t>((freq >> 8) & 0xFF),
299  static_cast<uint8_t>((freq >> 16) & 0xFF),
300  static_cast<uint8_t>((freq >> 24) & 0xFF)
301  };
302 
303  usart.transmit(&rq[0], 0, sizeof(rq));
304 
305  uint8_t byte = usart.readByte();
306  delay_us(10);
307  return byte;
308 }
309 
310 bool B15F::pwmSetValue(uint8_t value)
311 {
312  usart.clearInputBuffer();
313 
314  uint8_t rq[] =
315  {
316  RQ_PWM_SET_VALUE,
317  value
318  };
319 
320  usart.transmit(&rq[0], 0, sizeof(rq));
321 
322  uint8_t aw = usart.readByte();
323  delay_us(10);
324  return aw == MSG_OK;
325 }
326 
327 bool B15F::setRegister(uint8_t adr, uint8_t val)
328 {
329  usart.clearInputBuffer();
330 
331  uint8_t rq[] =
332  {
333  RQ_SET_REG,
334  adr,
335  val
336  };
337 
338  usart.transmit(&rq[0], 0, sizeof(rq));
339 
340  uint8_t byte = usart.readByte();
341  delay_us(10);
342  return byte == val;
343 }
344 
345 uint8_t B15F::getRegister(uint8_t adr)
346 {
347  usart.clearInputBuffer();
348 
349  uint8_t rq[] =
350  {
351  RQ_GET_REG,
352  adr
353  };
354 
355  usart.transmit(&rq[0], 0, sizeof(rq));
356 
357  uint8_t aw = usart.readByte();
358  delay_us(10);
359  return aw;
360 }
361 
362 
363 void B15F::delay_ms(uint16_t ms)
364 {
365  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
366 }
367 
368 void B15F::delay_us(uint16_t us)
369 {
370  std::this_thread::sleep_for(std::chrono::microseconds(us));
371 }
372 
374 {
375  if(!instance)
376  instance = new B15F();
377 
378  return *instance;
379 }
380 
381 // https://stackoverflow.com/a/478960
382 std::string B15F::exec(std::string cmd)
383 {
384  std::array<char, 128> buffer;
385  std::string result;
386  std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
387  if (!pipe)
388  {
389  throw std::runtime_error("popen() failed!");
390  }
391  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
392  {
393  result += buffer.data();
394  }
395  return result;
396 }
397 
398 void B15F::abort(std::string msg)
399 {
400  DriverException ex(msg);
401  abort(ex);
402 }
403 void B15F::abort(std::exception& ex)
404 {
405  if(errorhandler)
406  errorhandler(ex);
407  else
408  {
409  std::cerr << "NOTICE: B15F::errorhandler not set" << std::endl;
410  std::cout << ex.what() << std::endl;
411  throw DriverException(ex.what());
412  }
413 }
414 
415 void B15F::setAbortHandler(errorhandler_t func)
416 {
417  errorhandler = func;
418 }
B15F::exec
static std::string exec(std::string cmd)
Definition: b15f.cpp:382
B15F::getRegister
uint8_t getRegister(uint8_t adr)
Definition: b15f.cpp:345
B15F::delay_us
void delay_us(uint16_t us)
Definition: b15f.cpp:368
B15F::digitalRead0
uint8_t digitalRead0(void)
Definition: b15f.cpp:173
B15F::pwmSetFrequency
uint8_t pwmSetFrequency(uint32_t freq)
Definition: b15f.cpp:290
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:241
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:363
B15F::setRegister
bool setRegister(uint8_t adr, uint8_t val)
Definition: b15f.cpp:327
B15F::getInstance
static B15F & getInstance(void)
Definition: b15f.cpp:373
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:398
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: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:96
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
B15F::digitalWrite1
bool digitalWrite1(uint8_t)
Definition: b15f.cpp:163
B15F::pwmSetValue
bool pwmSetValue(uint8_t value)
Definition: b15f.cpp:310
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: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:415
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
B15F::testIntConv
bool testIntConv(void)
Definition: b15f.cpp:105
DriverException
Definition: driverexception.h:10