5 file_desc = open(device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
9 struct termios options;
10 int code = tcgetattr(file_desc, &options);
14 options.c_cflag = CS8 | CLOCAL | CREAD;
15 options.c_iflag = IGNPAR;
18 options.c_cc[VMIN] = 0;
19 options.c_cc[VTIME] = timeout;
20 code = cfsetspeed(&options, baudrate);
24 code = tcsetattr(file_desc, TCSANOW, &options);
34 int code = close(file_desc);
41 int code = tcflush(file_desc, TCIFLUSH);
48 int code = tcflush(file_desc, TCOFLUSH);
55 int code = tcdrain(file_desc);
62 double pz = 1e2 * n_blocks_failed / n_blocks_total;
63 pz = std::round(pz * 1e2) / 1e2;
64 std::cout <<
"blocks total: " << n_blocks_total <<
" ok: " << (n_blocks_total - n_blocks_failed) <<
" failed: " << n_blocks_failed <<
" (" << pz <<
"%)" << std::endl;
69 int sent = write(file_desc, &b, 1);
72 std::cout <<
"WARNUNG: Fehler beim Senden (" << sent <<
"): writeByte(), wiederhole..." << std::endl;
74 sent = write(file_desc, &b, 1);
83 int sent = write(file_desc, reinterpret_cast<char*>(&d), 2);
90 int sent = write(file_desc, reinterpret_cast<char*>(&w), 4);
95 int USART::read_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
99 auto start = std::chrono::steady_clock::now();
101 while(elapsed < timeout)
103 n_read = read(file_desc, buffer + offset, len);
107 end = std::chrono::steady_clock::now();
108 elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
114 int USART::write_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
116 uint32_t elapsed = 0;
118 auto start = std::chrono::steady_clock::now();
120 while(elapsed < timeout)
122 n_sent = write(file_desc, buffer + offset, len);
127 end = std::chrono::steady_clock::now();
128 elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
134 void USART::writeBlock(uint8_t* buffer, uint16_t offset, uint8_t len)
138 const uint16_t us_per_bit = (1000000 / baudrate) * 16;
139 const uint16_t n_total = len + 3;
148 for(uint8_t i = 0; i < len; i++)
151 for (uint8_t k = 0; k < 8; k++)
160 block_buffer[0] = len;
161 std::memcpy(&block_buffer[1], buffer + offset, len);
162 block_buffer[len + 1] = crc;
163 block_buffer[len + 2] = BLOCK_END;
168 int n_sent = write_timeout(&block_buffer[0], 0, len + 3, us_per_bit * n_total);
169 if(n_sent != n_total)
170 throw std::runtime_error(
"fatal (send): " + std::to_string(n_sent));
185 int n_read = read_timeout(&aw, 0, 1, us_per_bit * n_blocks_total * 10);
186 for(uint16_t i = 0; i < 255 && n_read != 1; i++)
189 if(tcdrain(file_desc))
191 std::cout <<
"drain failed" << std::endl;
193 std::cout <<
"WARNING: read error (" << n_read <<
"), retry #" << (int) i << std::endl;
194 usleep(us_per_bit*100);
195 n_read = read_timeout(&aw, 0, 1, us_per_bit);
199 throw std::runtime_error(
"fatal: " + std::to_string(n_read));
208 std::cout <<
"block failed, retry" << std::endl;
219 auto start = std::chrono::steady_clock::now();
221 uint16_t elapsed = 0;
222 while(elapsed < timeout * 100)
224 int code = read(file_desc, &b, 1);
226 return static_cast<uint8_t>(b);
228 end = std::chrono::steady_clock::now();
229 elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
240 bool USART::readBlock(uint8_t* buffer, uint16_t offset)
246 uint32_t block_timeout = timeout / 10;
250 uint16_t elapsed = 0;
251 auto start = std::chrono::steady_clock::now();
253 while(elapsed < block_timeout)
255 int code = ioctl(file_desc, FIONREAD, &n_ready);
258 std::cout <<
"n_ready code: " << code << std::endl;
262 if(n_ready >= len + 1)
265 end = std::chrono::steady_clock::now();
266 elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
268 if(elapsed >= timeout)
270 std::cout <<
"block timeout: " << std::endl;
279 for (uint8_t i = 0; i < 8; i++)
288 for (uint8_t i = 0; i < 8; i++)
324 this->baudrate = baudrate;
329 this->timeout = timeout;