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 USART::read_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
94 auto start = std::chrono::steady_clock::now();
96 while(elapsed < timeout)
98 n_read = read(file_desc, buffer + offset, len);
102 end = std::chrono::steady_clock::now();
103 elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
109 int USART::write_timeout(uint8_t* buffer, uint16_t offset, uint8_t len, uint32_t timeout)
111 uint32_t elapsed = 0;
113 auto start = std::chrono::steady_clock::now();
115 while(elapsed < timeout)
117 n_sent = write(file_desc, buffer + offset, len);
122 end = std::chrono::steady_clock::now();
123 elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
129 void USART::writeBlock(uint8_t* buffer, uint16_t offset, uint8_t len)
133 const uint16_t us_per_bit = (1000000 / baudrate) * 16;
134 const uint16_t n_total = len + 3;
143 for(uint8_t i = 0; i < len; i++)
146 for (uint8_t k = 0; k < 8; k++)
155 block_buffer[0] = len;
156 std::memcpy(&block_buffer[1], buffer + offset, len);
157 block_buffer[len + 1] = crc;
158 block_buffer[len + 2] = BLOCK_END;
163 int n_sent = write_timeout(&block_buffer[0], 0, len + 3, us_per_bit * n_total);
164 if(n_sent != n_total)
165 throw std::runtime_error(
"fatal (send): " + std::to_string(n_sent));
180 int n_read = read_timeout(&aw, 0, 1, us_per_bit * n_blocks_total * 10);
181 for(uint16_t i = 0; i < 255 && n_read != 1; i++)
184 if(tcdrain(file_desc))
186 std::cout <<
"drain failed" << std::endl;
188 std::cout <<
"WARNING: read error (" << n_read <<
"), retry #" << (int) i << std::endl;
189 usleep(us_per_bit*100);
190 n_read = read_timeout(&aw, 0, 1, us_per_bit);
194 throw std::runtime_error(
"fatal: " + std::to_string(n_read));
203 std::cout <<
"block failed, retry" << std::endl;
214 auto start = std::chrono::steady_clock::now();
216 uint16_t elapsed = 0;
217 while(elapsed < timeout * 100)
219 int code = read(file_desc, &b, 1);
221 return static_cast<uint8_t>(b);
223 end = std::chrono::steady_clock::now();
224 elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
235 bool USART::readBlock(uint8_t* buffer, uint16_t offset)
241 uint32_t block_timeout = timeout / 10;
245 uint16_t elapsed = 0;
246 auto start = std::chrono::steady_clock::now();
248 while(elapsed < block_timeout)
250 int code = ioctl(file_desc, FIONREAD, &n_ready);
253 std::cout <<
"n_ready code: " << code << std::endl;
257 if(n_ready >= len + 1)
260 end = std::chrono::steady_clock::now();
261 elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
263 if(elapsed >= timeout)
265 std::cout <<
"block timeout: " << std::endl;
274 for (uint8_t i = 0; i < 8; i++)
283 for (uint8_t i = 0; i < 8; i++)
319 this->baudrate = baudrate;
324 this->timeout = timeout;