Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Augment CmdMessenger with Forward Error Correction #70

Open
jptech opened this issue Apr 6, 2018 · 6 comments
Open

Augment CmdMessenger with Forward Error Correction #70

jptech opened this issue Apr 6, 2018 · 6 comments

Comments

@jptech
Copy link
Member

jptech commented Apr 6, 2018

CmdMessenger should be resilient to communication faults. We should try adding some low overhead error correction or detection scheme (like crc)

@xxAtrain223
Copy link
Contributor

xxAtrain223 commented Apr 14, 2018

Would you want to have this in time for the competition? I found this implementation, I could probably implement this tonight, and have it ready to test tomorrow.

@jptech
Copy link
Member Author

jptech commented Apr 14, 2018

I am not sure if it worth changing a critical component right now. Obviously feel free to play around with it on a branch if you aren't doing anything else, but it really wasn't planned for competition.

@xxAtrain223
Copy link
Contributor

Since we have plans for making a new communication protocol after the competition, it would probably be a wasted effort, except for the research value.

@jptech
Copy link
Member Author

jptech commented Apr 14, 2018

Yes, that has been discussed, but that new communication protocol (or cmd messenger) should have FEC of some sort.

it would probably be a wasted effort, except for the research value.

I think it is fairly obvious that we wouldn't update cmd messenger AND then just replace it. It is an either/or scenario of either we update cmd messenger with some changes OR make a totally new system.

@amessing
Copy link
Member

And the correct answer is make a totally new system. One that we can easily test.

@xxAtrain223
Copy link
Contributor

xxAtrain223 commented Apr 15, 2018

This is what i've made so far. I'm looking into generating the lookup table at compile time.
This is based off of the tutorial here

#include <cstdint>
#include <type_traits>
#include <iterator>

#include <vector>
#include <cassert>

template<typename T, T generator, typename std::enable_if< std::is_unsigned<T>::value>::type* = nullptr>
class Crc
{
private:
	T table[256];

public:
	typedef T type;
	static const size_t typeSize = sizeof(T);

	Crc()
	{
		// Generate Look up table

		/* iterate over all byte values 0 - 255 */
		for (uint16_t divident = 0; divident < 256; divident++)
		{
			T currByte = (T)(divident << ((sizeof(T) - 1) * 8));
			/* calculate the CRC-8 value for current byte */
			for (uint8_t bit = 0; bit < 8; bit++)
			{
				if ((currByte & (0x80 << ((sizeof(T) - 1) * 8))) != 0)
				{
					currByte <<= 1;
					currByte ^= generator;
				}
				else
				{
					currByte <<= 1;
				}
			}
			/* store CRC value in lookup table */
			table[divident] = currByte;
		}
	}

	T Calculate(uint8_t data[], size_t length)
	{
		T crc = 0;

		for (size_t i = 0; i < length; i++)
		{
			/* XOR-in next input byte */
			uint8_t pos = (uint8_t)((crc ^ (data[i] << ((sizeof(T) - 1) * 8))) >> ((sizeof(T) - 1) * 8));

			/* get current CRC value = remainder */
			crc = ((sizeof(T) > 1) ? (crc << 8) : 0) ^ (T)table[pos];
		}

		return crc;
	}

#pragma warning(push)
#pragma warning(error : 4244)
	template<typename Container>
	T Calculate(const Container& cont)
	{
		T crc = 0;

		for (const unsigned char& byte : cont)
		{
			/* XOR-in next input byte */
			uint8_t pos = (uint8_t)((crc ^ (byte << ((sizeof(T) - 1) * 8))) >> ((sizeof(T) - 1) * 8));

			/* get current CRC value = remainder */
			crc = ((sizeof(T) > 1) ? (crc << 8) : 0) ^ (T)table[pos];
		}

		return crc;
	}
#pragma warning(pop)
};

typedef Crc<uint8_t, 0x1D> Crc8;
typedef Crc<uint16_t, 0x1021> Crc16;
typedef Crc<uint32_t, 0x04C11DB7> Crc32;

int main()
{
	unsigned char data[] = { 0x01, 0x02 };
	assert(Crc8().Calculate(data, 2) == 0x76);
	assert(Crc16().Calculate(data, 2) == 0x1373);
	assert(Crc32().Calculate(data, 2) == 0xDB9BFAB2);

	std::vector<uint8_t> data2 = { 0x01, 0x02 };
	assert(Crc8().Calculate(data2) == 0x76);
	assert(Crc16().Calculate(data2) == 0x1373);
	assert(Crc32().Calculate(data2) == 0xDB9BFAB2);

    return 0;
}

The template version of Calculate can be used with any container whose value type can be converted to unsigned char without loss of data, e.g. std::list<uint8_t> and std::string, but not std::vector<uint16_t>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants