AIS decoding and really bad UI.

The decoder needs a serious refactoring/decoupling.
The UI just dumps bits of the received packets into a console window, whcih scrolls too quickly in an AIS-dense area with a good antenna.
This commit is contained in:
Jared Boone 2015-11-06 13:53:04 -08:00
parent a366b3ac4f
commit 9e694ce836
5 changed files with 388 additions and 148 deletions

View file

@ -22,38 +22,14 @@
#ifndef __AIS_BASEBAND_H__
#define __AIS_BASEBAND_H__
#include "crc.hpp"
#include <cstdint>
#include <cstddef>
#include <complex>
#include <array>
#include <bitset>
#include <utility>
namespace baseband {
template<typename T, typename BitRemap>
class FieldReader {
public:
constexpr FieldReader(
const T& data
) : data { data }
{
}
uint32_t read(const size_t start_bit, const size_t length) const {
uint32_t value = 0;
for(size_t i=start_bit; i<(start_bit + length); i++) {
value = (value << 1) | data[bit_remap(i)];
}
return value;
}
private:
const T& data;
const BitRemap bit_remap { };
};
namespace ais {
// RRC length should be about 4 x the symbol length to do a good job of
@ -209,128 +185,9 @@ constexpr std::array<std::complex<float>, 128> rrc_taps_128_decim_1_p { {
{ -1.1001696231e-04f, 4.5570517881e-05f }, { -2.5877077742e-04f, 5.1472707944e-05f },
} };
struct BitRemap {
size_t operator()(const size_t bit_index) const {
return bit_index ^ 7;
}
};
using decoded_packet = std::pair<std::string, std::string>;
struct CRCBitRemap {
size_t operator()(const size_t bit_index) const {
return bit_index;
}
};
using FieldReader = baseband::FieldReader<std::bitset<1024>, BitRemap>;
using CRCFieldReader = baseband::FieldReader<std::bitset<1024>, CRCBitRemap>;
struct PacketLengthRange {
constexpr PacketLengthRange(
) : min_bytes { 0 },
max_bytes { 0 }
{
}
constexpr PacketLengthRange(
const uint16_t min_bits,
const uint16_t max_bits
) : min_bytes { static_cast<uint8_t>(min_bits / 8U) },
max_bytes { static_cast<uint8_t>(max_bits / 8U) }
{
// static_assert((min_bits & 7) == 0, "minimum bits not a multiple of 8");
// static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8");
}
bool contains(const size_t bit_count) const {
return !is_above(bit_count) && !is_below(bit_count);
}
bool is_above(const size_t bit_count) const {
return (min() > bit_count);
}
bool is_below(const size_t bit_count) const {
return (max() < bit_count);
}
size_t min() const {
return min_bytes * 8;
}
size_t max() const {
return max_bytes * 8;
}
private:
const uint8_t min_bytes;
const uint8_t max_bytes;
};
constexpr std::array<PacketLengthRange, 64> packet_length_range { {
{ 0, 0 }, // 0
{ 168, 168 }, // 1
{ 168, 168 }, // 2
{ 168, 168 }, // 3
{ 168, 168 }, // 4
{ 424, 424 }, // 5
{ 0, 0 }, // 6
{ 0, 0 }, // 7
{ 0, 1008 }, // 8
{ 0, 0 }, // 9
{ 0, 0 }, // 10
{ 0, 0 }, // 11
{ 0, 0 }, // 12
{ 0, 0 }, // 13
{ 0, 0 }, // 14
{ 0, 0 }, // 15
{ 0, 0 }, // 16
{ 0, 0 }, // 17
{ 168, 168 }, // 18
{ 0, 0 }, // 19
{ 72, 160 }, // 20
{ 272, 360 }, // 21
{ 168, 168 }, // 22
{ 160, 160 }, // 23
{ 160, 168 }, // 24
{ 0, 168 }, // 25
{ 0, 0 }, // 26
{ 0, 0 }, // 27
{ 0, 0 }, // 28
{ 0, 0 }, // 29
{ 0, 0 }, // 30
{ 0, 0 }, // 31
} };
struct PacketLengthValidator {
bool operator()(const uint_fast8_t message_id, const size_t length) {
return packet_length_range[message_id].contains(length);
}
};
struct PacketTooLong {
bool operator()(const uint_fast8_t message_id, const size_t length) {
return packet_length_range[message_id].is_below(length);
}
};
struct CRCCheck {
bool operator()(const std::bitset<1024>& payload, const size_t data_length) {
CRCFieldReader field_crc { payload };
CRC<uint16_t> ais_fcs { 0x1021 };
uint16_t crc_calculated = 0xffff;
for(size_t i=0; i<data_length + 16; i+=8) {
if( i == data_length ) {
crc_calculated ^= 0xffff;
}
const uint8_t byte = field_crc.read(i, 8);
crc_calculated = ais_fcs.calculate_byte(crc_calculated, byte);
}
return crc_calculated == 0x0000;
}
};
decoded_packet packet_decode(const std::bitset<1024>& data, const size_t data_length);
} /* namespace ais */
} /* namespace baseband */