From 7339bed6bcf4de3a79b6b361559b1f74d3f933a8 Mon Sep 17 00:00:00 2001 From: schodet Date: Sun, 10 Apr 2005 20:13:20 +0000 Subject: Tests ok. Reste les renvois sur erreur. --- 2005/i/robert/src/proto/Makefile.defs | 2 +- 2005/i/robert/src/proto/proto.cc | 329 ++++++++++++++++++---------------- 2005/i/robert/src/proto/proto.hh | 23 ++- 2005/i/robert/src/proto/test_proto.cc | 10 +- 4 files changed, 195 insertions(+), 169 deletions(-) (limited to '2005/i') diff --git a/2005/i/robert/src/proto/Makefile.defs b/2005/i/robert/src/proto/Makefile.defs index ec86342..fa984bc 100644 --- a/2005/i/robert/src/proto/Makefile.defs +++ b/2005/i/robert/src/proto/Makefile.defs @@ -3,6 +3,6 @@ PROGRAMS += test_proto proto_OBJECTS = proto.o test_proto_OBJECTS = test_proto.o $(proto_OBJECTS) $(utils_OBJECTS) \ - $(serial_OBJECTS) $(timer_OBJECTS) + $(serial_OBJECTS) $(timer_OBJECTS) $(log_OBJECTS) test_proto: $(test_proto_OBJECTS) diff --git a/2005/i/robert/src/proto/proto.cc b/2005/i/robert/src/proto/proto.cc index 20727a2..78177f7 100644 --- a/2005/i/robert/src/proto/proto.cc +++ b/2005/i/robert/src/proto/proto.cc @@ -27,9 +27,13 @@ #include "utils/hexa.hh" #include "proto.hh" +#include +#include +#include + /// Constructeur. Proto::Proto(Receiver &receiver) - :receiver_(receiver), tLastSend_(0), revState_(0) + : log_ ("proto"), receiver_(receiver), tLastSend_(0), revState_(0) { } @@ -52,46 +56,44 @@ Proto::close(void) bool Proto::sync(void) { - bool reGet = true; + bool reGet; //Récupération de la frame - while(reGet) - { - if(reGet = getFrame()) - { - //Si la frame est un aquittement - if(currentFrame_ == frameQueue_.front()) - { - //on vire la commande de la queue - frameQueue_.pop(); - //Et on envoie la suivante si elle existe - if(!frameQueue_.empty()) - sendFrame(frameQueue_.front()); - } - //Si c'est une nouvelle commande, on l'envoie avec receive - else - receiver_.receive(currentFrame_.command, currentFrame_); - } - } + while (reGet = getFrame()) + { + log_ ("recv") << "frame" << currentFrame_; + //Si la frame est un aquittement + if(currentFrame_ == frameQueue_.front()) + { + //on vire la commande de la queue + frameQueue_.pop(); + //Et on envoie la suivante si elle existe + if(!frameQueue_.empty()) + sendFrame(frameQueue_.front()); + } + //Si c'est une nouvelle commande, on l'envoie avec receive + else + receiver_.receive(currentFrame_.command, currentFrame_); + } //On regarde depuis combien de temps on a envoyé une commande if(!frameQueue_.empty()) - { + { //Si on dépasse la milliseconde, on renvoie if(Timer::getProgramTime() - tLastSend_ >= timeout_) sendFrame(frameQueue_.front()); - } + } return frameQueue_.empty(); } /// Envoie un packet void -Proto::send (const Frame & frame, bool fiable) +Proto::send (const Frame & frame, bool reliable) { - if(fiable) - { + if(reliable) + { if(frameQueue_.empty()) tLastSend_ = -timeout_; frameQueue_.push(frame); - } + } else sendFrame(frame); sync(); @@ -103,33 +105,33 @@ Proto::send (const Frame & frame, bool fiable) /// 32 bits, majuscule pour signé). void Proto::send (char command, const char *format, int a0, int a1, - int a2, int a3, bool fiable) + int a2, int a3, bool reliable) { // Constitution de la frame Proto::Frame frame; frame.command = command; - + if (format[0] != '\0') - { + { newArgFrame(frame, format[0],a0); if (format[1] != '\0') - { + { newArgFrame(frame, format[1],a1); if (format[2] != '\0') - { + { newArgFrame(frame, format[2],a2); if (format[3] != '\0') newArgFrame(frame, format[3],a3); - } - } - } - send(frame,fiable); + } + } + } + send(frame,reliable); } /// permet d'envoyer un packet pas fiable void -Proto::send_pas_fiable (char command, const char *format, int a0, int a1, - int a2, int a3) +Proto::sendUnreliable (char command, const char *format, int a0, int a1, + int a2, int a3) { send(command, format, a0, a1, a2, a3, false); } @@ -159,7 +161,7 @@ Proto::decode (const Frame &frame, const char *format, int &a0, int &a1) bool Proto::decode (const Frame &frame, const char *format, int &a0, - int &a1, int &a2) + int &a1, int &a2) { int dummy; @@ -168,14 +170,14 @@ Proto::decode (const Frame &frame, const char *format, int &a0, bool Proto::decode (const Frame &frame, const char *format, int &a0, - int &a1, int &a2, int &a3) + int &a1, int &a2, int &a3) { //Teste si il y a bien le bon nombre d'argument if (static_cast(frame.args.size()) != argsFrameSize(format)) return false; // On décode et on envoie decodeArg(frame, format, a0, a1, a2, a3); - + return true; } @@ -196,46 +198,54 @@ Proto::getFrame(void) int receivedChar; //tant que le tampon n'est pas vide, on teste while((receivedChar = serial_.getchar()) != -1) - { - //si la donnée n'est pas erronnée - if(receivedChar != 0xff) // XXX Heu, c'est vraiment ça????? - { - //Si on reçoit un bang - if(receivedChar == '!') - { - revState_ = 1; - currentFrame_.command = 0; - currentFrame_.args.clear(); - } - //Si on reçoit le retour chariot et que on reçevait les args - else if(receivedChar == '\n' && revState_ == 2) - { - revState_ = 0; - return true; - } - //Pour les autres charactères - //Si on attend la commande - else - switch(revState_) - { - case 1: - currentFrame_.command = receivedChar; - revState_ = 2; - break; - case 2: // XXX Bite de poids fort à gauche dans la frame?? - currentFrame_.args.push_back(static_cast( - hex2digit( receivedChar )) << 4); - revState_ = 3; - break; - case 3: - currentFrame_.args.back() |= static_cast( - hex2digit( receivedChar )); - revState_ = 2; - break; - } - //Si revState == 0 alors on jette - } - } + { + //Si on reçoit un bang + if(receivedChar == '!') + { + revState_ = 1; + currentFrame_.command = 0; + currentFrame_.args.clear(); + } + //Si on reçoit le retour chariot et que on reçevait les args + else if(receivedChar == '\r' && revState_ == 2) + { + revState_ = 0; + return true; + } + //Pour les autres charactères + //Si on attend la commande + else + switch(revState_) + { + case 1: + if (!isalpha (receivedChar)) + { + Erreur. + } + currentFrame_.command = receivedChar; + revState_ = 2; + break; + case 2: + d = hex2digit (receivedChar); + if (d == hexInvalid) + { + Erreur. + } + currentFrame_.args.push_back (static_cast(d) << 4); + revState_ = 3; + break; + case 3: + d = hex2digit (receivedChar); + if (d == hexInvalid) + { + Erreur. + } + currentFrame_.args.back() |= static_cast(d); + revState_ = 2; + break; + } + //Si revState == 0 alors on jette + } return false; } @@ -243,22 +253,22 @@ Proto::getFrame(void) void Proto::sendFrame(const Frame & frame) { + log_ ("send") << "frame" << frame; //envoyer le bang serial_.putchar('!'); //Envoyer la commande - serial_.putchar(digit2hex(frame.command >> 4)); - serial_.putchar(digit2hex(frame.command & 0x0f)); + serial_.putchar(frame.command); //Envoyer les arguments for(int i = 0; i < static_cast(frame.args.size()); i++) - { + { serial_.putchar(digit2hex(frame.args[i] >> 4)); serial_.putchar(digit2hex(frame.args[i] & 0x0f)); - } + } //Envoyer le retour chariot - serial_.putchar('\n'); + serial_.putchar('\r'); //actualiser le timer tLastSend_ = Timer::getProgramTime(); @@ -269,24 +279,24 @@ void Proto::newArgFrame(Proto::Frame & frame, char format, int arg) { switch(format) - { - case 'b': - case 'B': - frame.args.push_back(static_cast(arg)); - break; - case 'w': - case 'W': - frame.args.push_back(static_cast(arg >> 8)); - frame.args.push_back(static_cast(arg)); - break; - case 'd': - case 'D': - frame.args.push_back(static_cast(arg >> 24)); - frame.args.push_back(static_cast(arg >> 16)); - frame.args.push_back(static_cast(arg >> 8)); - frame.args.push_back(static_cast(arg)); - break; - } + { + case 'b': + case 'B': + frame.args.push_back(static_cast(arg)); + break; + case 'w': + case 'W': + frame.args.push_back(static_cast(arg >> 8)); + frame.args.push_back(static_cast(arg)); + break; + case 'd': + case 'D': + frame.args.push_back(static_cast(arg >> 24)); + frame.args.push_back(static_cast(arg >> 16)); + frame.args.push_back(static_cast(arg >> 8)); + frame.args.push_back(static_cast(arg)); + break; + } } /// Renvoie la taille necessaire du vecteur args pour un format donné @@ -294,21 +304,22 @@ int Proto::argsFrameSize(const char *format) { int size = 0; + Bla ! for(; *format != '\0'; format++) switch(*format) - { - case 'b': - case 'B': - size += 1; - case 'w': - case 'W': - size += 1; - case 'd': - case 'D': - size += 1; - default: - size += 1; - } + { + case 'b': + case 'B': + size += 1; + case 'w': + case 'W': + size += 1; + case 'd': + case 'D': + size += 1; + default: + size += 1; + } return size; } @@ -320,50 +331,50 @@ Proto::decodeArg(const Frame & frame, const char *format, int &a0, int &a1, int int pos = 0; for(int i = 0; *format != '\0'; format++,i++) - { + { switch(*format) - { - case 'b': - temp[i] = static_cast(frame.args[pos]); + { + case 'b': + temp[i] = static_cast(frame.args[pos]); + pos++; + break; + case 'B': + { + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t); pos++; break; - case 'B': - { - int8_t t = static_cast(frame.args[pos]); - temp[i] = static_cast(t); - pos++; - break; - } - case 'w': - temp[i] = static_cast(frame.args[pos]) << 8 + } + case 'w': + temp[i] = static_cast(frame.args[pos]) << 8 + |static_cast(frame.args[pos + 1]); + pos += 2; + break; + case 'W': + { + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t) << 8 |static_cast(frame.args[pos + 1]); pos += 2; break; - case 'W': - { - int8_t t = static_cast(frame.args[pos]); - temp[i] = static_cast(t) << 8 - |static_cast(frame.args[pos + 1]); - pos += 2; - break; - } - case 'd': - temp[i] = static_cast(frame.args[pos]) << 24 - |static_cast(frame.args[pos + 1]) << 16 - |static_cast(frame.args[pos + 2]) << 8 - |static_cast(frame.args[pos + 3]); - pos += 4; - break; + } + case 'd': + temp[i] = static_cast(frame.args[pos]) << 24 + |static_cast(frame.args[pos + 1]) << 16 + |static_cast(frame.args[pos + 2]) << 8 + |static_cast(frame.args[pos + 3]); + pos += 4; + break; - case 'D': - int8_t t = static_cast(frame.args[pos]); - temp[i] = static_cast(t) << 24 - |static_cast(frame.args[pos + 1]) << 16 - |static_cast(frame.args[pos + 2]) << 8 - |static_cast(frame.args[pos + 3]); - break; - } - } + case 'D': + int8_t t = static_cast(frame.args[pos]); + temp[i] = static_cast(t) << 24 + |static_cast(frame.args[pos + 1]) << 16 + |static_cast(frame.args[pos + 2]) << 8 + |static_cast(frame.args[pos + 3]); + break; + } + } a0 = temp[0]; a1 = temp[1]; a2 = temp[2]; @@ -375,3 +386,15 @@ Proto::Frame::operator==(const Frame& frame) { return this->command == frame.command && this->args == frame.args; } + +/// Affiche une frame. +std::ostream & +operator<< (std::ostream &os, const Proto::Frame &f) +{ + os << '<' << f.command << ' '; + std::copy (f.args.begin (), f.args.end (), + std::ostream_iterator (os, " ")); + os << '>'; + return os; +} + diff --git a/2005/i/robert/src/proto/proto.hh b/2005/i/robert/src/proto/proto.hh index 0a2099b..7b249d1 100644 --- a/2005/i/robert/src/proto/proto.hh +++ b/2005/i/robert/src/proto/proto.hh @@ -25,15 +25,17 @@ // // }}} -#include -#include #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: + public: class Receiver; /// Packet. struct Frame @@ -42,7 +44,8 @@ class Proto : public NonCopyable std::vector args; bool operator==(const Frame& frame); }; - private: + private: + Log log_; Serial serial_; Receiver &receiver_; @@ -74,15 +77,15 @@ class Proto : public NonCopyable /// le faire. bool sync (void); /// Envois un packet. - void send (const Frame &frame, bool fiable = true); + 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 = 0, int a0 = 0, int a1 = 0, - int a2 = 0, int a3 = 0, bool fiable = true); + int a2 = 0, int a3 = 0, bool reliable = true); /// permet d'envoyer un packet robert - void Proto::send_pas_fiable (char command, const char *format, int a0, - int a1, int a2, int a3); + void Proto::sendUnreliable (char command, const char *format, int a0, + int a1, int a2, int a3); //@{ /// Teste si le packet correspond au format et décode les valeurs. Utilise /// le même format que send. @@ -121,4 +124,8 @@ class Proto : public NonCopyable int &a1, int &a2, int &a3); }; +/// Affiche une frame. +std::ostream & +operator<< (std::ostream &os, const Proto::Frame &f); + #endif // proto_hh diff --git a/2005/i/robert/src/proto/test_proto.cc b/2005/i/robert/src/proto/test_proto.cc index faec030..9ec119d 100644 --- a/2005/i/robert/src/proto/test_proto.cc +++ b/2005/i/robert/src/proto/test_proto.cc @@ -27,18 +27,13 @@ #include #include -#include -#include /// Classe de test pour proto. class TestProto : public Proto::Receiver { void receive (char command, const Proto::Frame &frame) { - std::cout << command << ' '; - std::copy (frame.args.begin (), frame.args.end (), - std::ostream_iterator (std::cout, " ")); - std::cout << std::endl; + std::cout << "received " << frame << std::endl; } }; @@ -91,6 +86,8 @@ main (int argc, char **argv) arg[a] = atoi (argv[++i]); proto.send (c, format, arg[0], arg[1], arg[2], arg[3], reliable); + while (!proto.wait (-1)) + ; } break; case 'w': @@ -102,7 +99,6 @@ main (int argc, char **argv) t = Timer::getProgramTime (); while (t < stop) { - std::cout << std::endl; proto.wait (stop - t); t = Timer::getProgramTime (); } -- cgit v1.2.3