TransferID class

This commit is contained in:
Pavel Kirienko 2014-02-02 01:57:54 +04:00
parent 5252972d3e
commit 4bf2b2e81a
3 changed files with 113 additions and 24 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 <pavel.kirienko@gmail.com>
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#pragma once
@ -19,21 +19,60 @@ enum TransferType
MESSAGE_UNICAST = 3
};
class TransferID
{
uint_fast8_t value_;
public:
enum { BITLEN = 4 };
enum { MAX = (1 << BITLEN) - 1 };
TransferID()
: value_(0)
{ }
TransferID(uint_fast8_t value) // implicit
: value_(value)
{
value_ &= MAX;
assert(value == value_);
}
bool operator!=(TransferID rhs) const { return !operator==(rhs); }
bool operator==(TransferID rhs) const { return get() == rhs.get(); }
void increment()
{
value_ = (value_ + 1) & MAX;
}
uint_fast8_t get() const
{
assert(value_ <= MAX);
return value_;
}
/**
* Amount of increment() calls to reach rhs value.
*/
int forwardDistance(TransferID rhs) const;
};
struct Frame
{
enum { MAX_TRANSFER_ID = 15 };
uint8_t payload[8];
TransferType transfer_type;
uint_fast16_t data_type_id;
uint_fast8_t payload_len;
uint_fast8_t source_node_id;
uint_fast8_t frame_index;
uint_fast8_t transfer_id;
TransferID transfer_id;
bool last_frame;
Frame(const uint8_t* payload, uint_fast8_t payload_len, uint_fast16_t data_type_id, TransferType transfer_type,
uint_fast8_t source_node_id, uint_fast8_t frame_index, uint_fast8_t transfer_id, bool last_frame)
uint_fast8_t source_node_id, uint_fast8_t frame_index, TransferID transfer_id, bool last_frame)
: transfer_type(transfer_type)
, data_type_id(data_type_id)
, payload_len(payload_len)
@ -48,11 +87,7 @@ struct Frame
static Frame parse(const CanFrame& can_frame);
/**
* Difference computed from (this.transfer_id - rhs.transfer_id) with proper overflow handling.
*/
int subtractTransferID(const Frame& rhs) const { return subtractTransferID(rhs.transfer_id); }
int subtractTransferID(int rhs) const;
CanFrame compile() const;
bool operator!=(const Frame& rhs) const { return !operator==(rhs); }
bool operator==(const Frame& rhs) const
@ -69,6 +104,7 @@ struct Frame
}
};
struct RxFrame
{
uint_fast64_t timestamp;

View File

@ -1,27 +1,20 @@
/*
* Copyright (C) 2014 <pavel.kirienko@gmail.com>
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#include <cassert>
#include <uavcan/internal/transport/transfer.hpp>
namespace uavcan
{
//static Frame Frame::parse(const CanFrame& can_frame)
//{
//}
int Frame::subtractTransferID(int rhs) const
int TransferID::forwardDistance(TransferID rhs) const
{
static const int RANGE = MAX_TRANSFER_ID + 1; // 16 256
static const int NEGATIVE = -RANGE / 2; // -8 -128 (two's complement)
static const int POSITIVE = (-NEGATIVE) - 1; // 7 127
int d = int(rhs.get()) - int(get());
if (d < 0)
d += 1 << BITLEN;
const int d = int(this->transfer_id) - rhs;
if (d <= NEGATIVE)
return RANGE + d;
else if (d >= POSITIVE)
return d - RANGE;
assert(((get() + d) & MAX) == rhs.get());
return d;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#include <string>
#include <gtest/gtest.h>
#include <uavcan/internal/transport/transfer.hpp>
TEST(Transfer, TransferID)
{
using uavcan::TransferID;
// Tests below are based on this assumption
ASSERT_EQ(16, 1 << TransferID::BITLEN);
/*
* forwardDistance()
*/
EXPECT_EQ(0, TransferID(0).forwardDistance(0));
EXPECT_EQ(1, TransferID(0).forwardDistance(1));
EXPECT_EQ(15, TransferID(0).forwardDistance(15));
EXPECT_EQ(0, TransferID(7).forwardDistance(7));
EXPECT_EQ(15, TransferID(7).forwardDistance(6));
EXPECT_EQ(1, TransferID(7).forwardDistance(8));
EXPECT_EQ(9, TransferID(10).forwardDistance(3));
EXPECT_EQ(7, TransferID(3).forwardDistance(10));
EXPECT_EQ(8, TransferID(6).forwardDistance(14));
EXPECT_EQ(8, TransferID(14).forwardDistance(6));
EXPECT_EQ(1, TransferID(14).forwardDistance(15));
EXPECT_EQ(2, TransferID(14).forwardDistance(0));
EXPECT_EQ(4, TransferID(14).forwardDistance(2));
EXPECT_EQ(15, TransferID(15).forwardDistance(14));
EXPECT_EQ(14, TransferID(0).forwardDistance(14));
EXPECT_EQ(12, TransferID(2).forwardDistance(14));
/*
* Misc
*/
EXPECT_TRUE(TransferID(2) == TransferID(2));
EXPECT_FALSE(TransferID(2) != TransferID(2));
EXPECT_FALSE(TransferID(2) == TransferID(8));
EXPECT_TRUE(TransferID(2) != TransferID(8));
TransferID tid;
for (int i = 0; i < 999; i++)
{
ASSERT_EQ(i & ((1 << TransferID::BITLEN) - 1), tid.get());
const TransferID copy = tid;
tid.increment();
ASSERT_EQ(1, copy.forwardDistance(tid));
ASSERT_EQ(15, tid.forwardDistance(copy));
ASSERT_EQ(0, tid.forwardDistance(tid));
}
}