#include #include #include #include #include #include #include #include #include "usart.h" UsartClass::UsartClass (const char * name, const int baudrate) : BaseLayer() { id = name; running = false; fd = ::open (id, O_RDWR); if (fd < 0) return; timeout = 20'000'000 / baudrate; // cca 2 násobek pro 1 byte struct termios LineFlags; int attr = tcgetattr (fd, &LineFlags); if (attr) { printf ("Nelze zjistit parametry portu %s\r\n", name); ::close (fd); return; } // nastaveni komunikacnich parametru do struct termios LineFlags.c_iflag = IGNPAR /* | IXON | IXOFF*/; // ignoruj chyby parity LineFlags.c_oflag = 0; // normalni nastaveni LineFlags.c_cflag = CS8 | CREAD | CLOCAL; // 8-bit, povol prijem LineFlags.c_lflag = 0; // Raw input bez echa LineFlags.c_cc [VMIN] = 1; // minimalni pocet znaku pro cteni LineFlags.c_cc [VTIME] = 1; // read timeout 0.1 s tcsetattr (fd, TCSANOW, &LineFlags); fcntl (fd, F_SETFL, 0); int flag = TIOCM_DTR; ioctl(fd, TIOCMBIS, & flag); setBaud(baudrate); printf ("Port %s opened (%d) at %d Bd\r\n", id, fd, baudrate); usleep (10000); running = true; pthread_create (&rc, NULL, UsartClass::UsartHandler, this); } UsartClass::~UsartClass() { running = false; pthread_cancel (rc); int flag = TIOCM_DTR; ioctl(fd, TIOCMBIC, & flag); ::close (fd); printf ("Port %s closed\r\n", id); } uint32_t UsartClass::Up (const char * data, uint32_t len) { return BaseLayer::Up (data, len); } uint32_t UsartClass::Down (const char * data, uint32_t len) { if (!running) return 0; const unsigned maxchunk = 32; // USB bulk len (64) je moc unsigned offset = 0, remain = len; while (remain) { const unsigned chunk = remain > maxchunk ? maxchunk : remain; const unsigned writn = ::write (fd, data + offset, chunk); // Počkat je nejjednodušší prevence zahlcení USB (USART má omezenou rychlost) usleep (timeout * writn); // závisí na baud rate offset += writn; remain -= writn; } return offset; } void UsartClass::ReadLoop (void) { int n; while (running) { // Nutno číst po jednom nebo použít timer, jinak to po prvním čtení zdechne. n = ::read (fd, rxbuf, 1); if (!n) continue; Up (rxbuf, n); } }