#ifndef proto_hh #define proto_hh // proto.hh // 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 "utils/non_copyable.hh" #include "serial/serial.hh" #include "log/log.hh" #include #include /// Classe de dialogue avec une carte électronique par le port série. class Proto : public NonCopyable { public: class Receiver; /// Packet. struct Frame { char command; std::vector args; bool operator==(const Frame& frame); }; private: Log log_; Serial serial_; Receiver &receiver_; /// File d'attente des messages à aquiter. typedef std::queue FrameQueue; FrameQueue frameQueue_; //Date du dernier envoie int tLastSend_; //Temps entre les ré-émission static const int timeout_ = 100; /// Frame en cours de réception Frame currentFrame_; int revState_; // Etat de la réception de la frame // 0 - Rien reçu // 1 - Bang reçu // 2 - Commande reçu & nouveau argument // 3 - char 1 argument reçu public: /// Constructeur. Proto (Receiver &receiver); /// Ouvre le port série. void open (const std::string &ttyname); /// Ferme le port série. void close (void); /// Teste si tout les packets ont été envoyés et aquités, sinon, essaye de /// le faire. bool sync (void); /// Envois un packet. void send (const Frame &frame, bool reliable = true); /// Envois un packet. COMMAND est la commande à envoyer, FORMAT, donne le /// format et le nombre de paramètres ('b' : 8 bits, 'w' : 16 bits, 'd' : /// 32 bits, majuscule pour signé). void send (char command, const char *format = "", int a0 = 0, int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, bool reliable = true); /// Send a string of size number. void sendStr (char command, const char *str, int size, bool reliable = true); /// permet d'envoyer un packet robert void Proto::sendUnreliable (char command, const char *format, int a0, int a1, int a2, int a3, int a4, int a5); //@{ /// Teste si le packet correspond au format et décode les valeurs. Utilise /// le même format que send. static bool decode (const Frame &frame); static bool decode (const Frame &frame, const char *format, int &a0); static bool decode (const Frame &frame, const char *format, int &a0, int &a1); static bool decode (const Frame &frame, const char *format, int &a0, int &a1, int &a2); static bool decode (const Frame &frame, const char *format, int &a0, int &a1, int &a2, int &a3); static bool decode (const Frame &frame, const char *format, int &a0, int &a1, int &a2, int &a3, int &a4); //@} /// Attend que des caractères soit disponible pendant un temps maximum en /// milliseconde et les traite. Renvois le résultat de sync (). Attention, /// fonction bloquante, n'utiliser que pour les tests. bool wait (int timeout = -1); /// Récupère le File Descriptor int getFd(void) const; public: /// Les clients de Proto doivent dériver de Receiver. class Receiver { public: virtual ~Receiver(void) {}; /// Recoit un packet. virtual void receive (char command, const Frame &frame) = 0; }; private: /// Récupère les infos de l'AVR pour construire une frame bool getFrame(void); /// Envoie la frame dans l'AVR void sendFrame(const Frame & frame); /// Remplie une frame avec un argument void newArgFrame(Proto::Frame & frame, char format, int arg); /// Renvoie la taille necessaire du vecteur args pour un format donné static int argsFrameSize(const char *format); /// Décode un argument static void decodeArg(const Frame & frame, const char *format, int &a0, int &a1, int &a2, int &a3, int &a4); }; /// Affiche une frame. std::ostream & operator<< (std::ostream &os, const Proto::Frame &f); #endif // proto_hh