From da4a77ff094a0dc74414ec1de2cac08e8b7b60f4 Mon Sep 17 00:00:00 2001 From: haller Date: Thu, 17 Nov 2005 11:10:17 +0000 Subject: Importation brut du code récupérable de robert --- i/marvin/src/serial/serial_dev.cc | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 i/marvin/src/serial/serial_dev.cc (limited to 'i/marvin/src/serial/serial_dev.cc') diff --git a/i/marvin/src/serial/serial_dev.cc b/i/marvin/src/serial/serial_dev.cc new file mode 100644 index 0000000..3e796e7 --- /dev/null +++ b/i/marvin/src/serial/serial_dev.cc @@ -0,0 +1,168 @@ +// serial_dev.cc +// robert - programme du robot 2005. {{{ +// +// Copyright (C) 2005 Nicolas Schodet +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "serial_dev.hh" +#include "utils/errno_exception.hh" + +#include +#include +#include + +/// Constructeur. +SerialDev::SerialDev (bool blocking/*false*/) + : blocking_ (blocking) +{ +} + +/// Destructeur. +SerialDev::~SerialDev (void) +{ + close (); +} + +/// Ouvre et paramètre le port série, accepte plusieurs paramètres séparés par +/// des virgules : tty, vitesse, parité (none, odd, even). Par exemple : +/// "/dev/ttyS00,115200,even" (par defaut). +void +SerialDev::open (const std::string &ttyname) +{ + struct termios tios; + std::string tty; + int speed = 115200; + char par = 'e'; + // Décode le ttyname. + decode (ttyname, tty, speed, par); + // Ouvre le port série. + fdIn_ = ::open (tty.c_str (), O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fdIn_ < 0) + throw errno_exception (ttyname, errno); + // Rendre le port série asynchrone. + //fcntl (fd_, F_SETFL, FASYNC); + // Sauver la configuration courante du port série. + tcgetattr (fdIn_, &old_); + tcgetattr (fdIn_, &tios); + // Paramètrer les options du port série. + // Vérification de la parité en entrée, remplace toute erreur de + // transmission par un caractère nul. Pas de Xon Xoff. Entrée crue. + tios.c_iflag &= ~(IGNPAR | PARMRK | ISTRIP | IGNBRK | BRKINT | IGNCR | + ICRNL | INLCR | IXON | IXOFF | IXANY | IMAXBEL); + tios.c_iflag |= INPCK; + // Sortie crue. + tios.c_oflag &= ~(OPOST); + // Pas de status line, 1 bit de stop, 8 bits de données, règle la parité. + tios.c_cflag &= ~(HUPCL | CSTOPB | PARENB | PARODD | CSIZE); + tios.c_cflag |= CS8 | CLOCAL | CREAD; + if (par != 'n') tios.c_cflag |= PARENB; + if (par == 'o') tios.c_cflag |= PARODD; + // Cru. + tios.c_lflag &= ~(ICANON | ECHO | ISIG | NOFLSH | TOSTOP); + // On n'attend jamais si on est en non-block. On attend sinon. + tios.c_cc[VTIME] = 0; + if (blocking_) + tios.c_cc[VMIN] = 1; + else + tios.c_cc[VMIN] = 0; + switch (speed) + { + case 1200: + cfsetspeed (&tios, B1200); + break; + case 9600: + cfsetspeed (&tios, B9600); + break; + case 19200: + cfsetspeed (&tios, B19200); + break; + case 38400: + cfsetspeed (&tios, B38400); + break; + case 57600: + cfsetspeed (&tios, B57600); + break; + case 115200: + cfsetspeed (&tios, B115200); + break; + case 230400: + cfsetspeed (&tios, B230400); + break; + case 460800: + cfsetspeed (&tios, B460800); + break; + default: + throw std::runtime_error ("Vitesse de port série non supportée\n"); + } + // Vider et configurer le port série. + tcflush (fdIn_, TCIFLUSH); + tcsetattr (fdIn_, TCSANOW, &tios); + fdOut_ = fdIn_; +} + +/// Ferme le port série, appellé automatiquement dans le destructeur de la +/// classe SerialBase. +void +SerialDev::close (void) +{ + if (fdIn_ != -1) + { + tcsetattr (fdIn_, TCSANOW, &old_); + ::close (fdIn_); + fdIn_ = -1; + fdOut_ = -1; + } +} + +/// Décode le ttyname, voir open. +void +SerialDev::decode (const std::string &ttyname, std::string &tty, int &speed, + char &par) const +{ + std::string::size_type a, b, d; + int i; + a = 0; + b = ttyname.find (','); + while (a != std::string::npos) + { + d = b == std::string::npos ? std::string::npos : b - a; + std::string s (ttyname, a, d); + i = atoi (s.c_str ()); + if (i) + speed = i; + else + { + if (s == "e" || s == "even") + par = 'e'; + else if (s == "o" || s == "odd") + par = 'o'; + else if (s == "n" || s == "none") + par = 'n'; + else if (tty.empty ()) + tty = s; + else + throw std::runtime_error ("error in ttyname: " + s); + } + a = b == std::string::npos ? b : b + 1; + b = ttyname.find (',', a); + } +} + -- cgit v1.2.3