summaryrefslogtreecommitdiff
path: root/i/chuck/src/serial/serial_dev.cc
diff options
context:
space:
mode:
authorbecquet2007-05-10 18:49:20 +0000
committerbecquet2007-05-10 18:49:20 +0000
commit8f486613be58ced269db1d437e560c16558604e8 (patch)
tree41e94b2122a118cb06abf6fc2a0038cd1dfbec4a /i/chuck/src/serial/serial_dev.cc
parent4daa2c76c2a028e4b2c8ab379e7d1e0f535a0a31 (diff)
Création de chuck, le programme du robot 2007.
Diffstat (limited to 'i/chuck/src/serial/serial_dev.cc')
-rw-r--r--i/chuck/src/serial/serial_dev.cc168
1 files changed, 168 insertions, 0 deletions
diff --git a/i/chuck/src/serial/serial_dev.cc b/i/chuck/src/serial/serial_dev.cc
new file mode 100644
index 0000000..a1824a2
--- /dev/null
+++ b/i/chuck/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 <stdexcept>
+#include <fcntl.h>
+#include <cstdlib>
+
+/// 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 | BRKINT | IGNCR | ICRNL |
+ INLCR | IXON | IXOFF | IXANY | IMAXBEL);
+ tios.c_iflag |= INPCK | IGNBRK;
+ // 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 | CRTSCTS);
+ 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);
+ }
+}
+