summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschodet2005-04-10 20:13:20 +0000
committerschodet2005-04-10 20:13:20 +0000
commit7339bed6bcf4de3a79b6b361559b1f74d3f933a8 (patch)
tree8a612a6897279736548e4e020b068be6549cdf85
parent976b5047eef9b56956ef5bcc392c0c2730f4f331 (diff)
Tests ok. Reste les renvois sur erreur.
-rw-r--r--2005/i/robert/src/proto/Makefile.defs2
-rw-r--r--2005/i/robert/src/proto/proto.cc329
-rw-r--r--2005/i/robert/src/proto/proto.hh23
-rw-r--r--2005/i/robert/src/proto/test_proto.cc10
4 files changed, 195 insertions, 169 deletions
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 <iostream>
+#include <algorithm>
+#include <iterator>
+
/// 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<int>(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<uint8_t>(
- hex2digit( receivedChar )) << 4);
- revState_ = 3;
- break;
- case 3:
- currentFrame_.args.back() |= static_cast<uint8_t>(
- 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<uint8_t>(d) << 4);
+ revState_ = 3;
+ break;
+ case 3:
+ d = hex2digit (receivedChar);
+ if (d == hexInvalid)
+ {
+ Erreur.
+ }
+ currentFrame_.args.back() |= static_cast<uint8_t>(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<int>(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<uint8_t>(arg));
- break;
- case 'w':
- case 'W':
- frame.args.push_back(static_cast<uint8_t>(arg >> 8));
- frame.args.push_back(static_cast<uint8_t>(arg));
- break;
- case 'd':
- case 'D':
- frame.args.push_back(static_cast<uint8_t>(arg >> 24));
- frame.args.push_back(static_cast<uint8_t>(arg >> 16));
- frame.args.push_back(static_cast<uint8_t>(arg >> 8));
- frame.args.push_back(static_cast<uint8_t>(arg));
- break;
- }
+ {
+ case 'b':
+ case 'B':
+ frame.args.push_back(static_cast<uint8_t>(arg));
+ break;
+ case 'w':
+ case 'W':
+ frame.args.push_back(static_cast<uint8_t>(arg >> 8));
+ frame.args.push_back(static_cast<uint8_t>(arg));
+ break;
+ case 'd':
+ case 'D':
+ frame.args.push_back(static_cast<uint8_t>(arg >> 24));
+ frame.args.push_back(static_cast<uint8_t>(arg >> 16));
+ frame.args.push_back(static_cast<uint8_t>(arg >> 8));
+ frame.args.push_back(static_cast<uint8_t>(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<int>(frame.args[pos]);
+ {
+ case 'b':
+ temp[i] = static_cast<int>(frame.args[pos]);
+ pos++;
+ break;
+ case 'B':
+ {
+ int8_t t = static_cast<int8_t>(frame.args[pos]);
+ temp[i] = static_cast<int>(t);
pos++;
break;
- case 'B':
- {
- int8_t t = static_cast<int8_t>(frame.args[pos]);
- temp[i] = static_cast<int>(t);
- pos++;
- break;
- }
- case 'w':
- temp[i] = static_cast<int>(frame.args[pos]) << 8
+ }
+ case 'w':
+ temp[i] = static_cast<int>(frame.args[pos]) << 8
+ |static_cast<int>(frame.args[pos + 1]);
+ pos += 2;
+ break;
+ case 'W':
+ {
+ int8_t t = static_cast<int8_t>(frame.args[pos]);
+ temp[i] = static_cast<int>(t) << 8
|static_cast<int>(frame.args[pos + 1]);
pos += 2;
break;
- case 'W':
- {
- int8_t t = static_cast<int8_t>(frame.args[pos]);
- temp[i] = static_cast<int>(t) << 8
- |static_cast<int>(frame.args[pos + 1]);
- pos += 2;
- break;
- }
- case 'd':
- temp[i] = static_cast<int>(frame.args[pos]) << 24
- |static_cast<int>(frame.args[pos + 1]) << 16
- |static_cast<int>(frame.args[pos + 2]) << 8
- |static_cast<int>(frame.args[pos + 3]);
- pos += 4;
- break;
+ }
+ case 'd':
+ temp[i] = static_cast<int>(frame.args[pos]) << 24
+ |static_cast<int>(frame.args[pos + 1]) << 16
+ |static_cast<int>(frame.args[pos + 2]) << 8
+ |static_cast<int>(frame.args[pos + 3]);
+ pos += 4;
+ break;
- case 'D':
- int8_t t = static_cast<int8_t>(frame.args[pos]);
- temp[i] = static_cast<int>(t) << 24
- |static_cast<int>(frame.args[pos + 1]) << 16
- |static_cast<int>(frame.args[pos + 2]) << 8
- |static_cast<int>(frame.args[pos + 3]);
- break;
- }
- }
+ case 'D':
+ int8_t t = static_cast<int8_t>(frame.args[pos]);
+ temp[i] = static_cast<int>(t) << 24
+ |static_cast<int>(frame.args[pos + 1]) << 16
+ |static_cast<int>(frame.args[pos + 2]) << 8
+ |static_cast<int>(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<int> (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<queue>
-#include<stdint.h>
#include "utils/non_copyable.hh"
#include "serial/serial.hh"
+#include "log/log.hh"
+
+#include <queue>
+#include <stdint.h>
/// 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<uint8_t> 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 <iostream>
#include <stdexcept>
-#include <algorithm>
-#include <iterator>
/// 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<int> (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 ();
}