/*
Copyright (c) 2016-2020 Peter Antypas
This file is part of the MAIANAâ„¢ transponder firmware.
The firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
*/
#include "NMEAEncoder.hpp"
#include "Utils.hpp"
#include
#include
#include
#include "AISChannels.h"
using namespace std;
NMEAEncoder::NMEAEncoder()
: mSequence(0)
{
}
NMEAEncoder::~NMEAEncoder()
{
}
void NMEAEncoder::encode(RXPacket &packet, vector &sentences)
{
static uint16_t MAX_SENTENCE_BYTES = 56;
static uint16_t MAX_SENTENCE_BITS = MAX_SENTENCE_BYTES * 6;
packet.discardCRC();
uint16_t numBits = packet.size();
uint16_t fillBits = 0;
if ( numBits % 6 )
{
fillBits = 6 - (numBits%6);
packet.addFillBits(fillBits);
numBits = packet.size();
}
uint16_t numSentences = 1;
while ( numBits > MAX_SENTENCE_BITS )
{
++numSentences;
numBits -= MAX_SENTENCE_BITS;
}
numBits = packet.size();
if ( numSentences > 1 )
{
++mSequence;
if ( mSequence > 9 )
mSequence = 0;
}
// Now we know how many sentences we need
char sentence[85];
uint16_t pos = 0;
for ( uint16_t i = 1; i <= numSentences; ++i )
{
uint8_t k = 0;
if ( numSentences > 1 )
sprintf(sentence, "!AIVDM,%d,%d,%d,%c,", numSentences, i, mSequence, AIS_CHANNELS[packet.channel()].designation);
else
sprintf(sentence, "!AIVDM,%d,%d,,%c,", numSentences, i, AIS_CHANNELS[packet.channel()].designation);
k = strlen(sentence);
uint16_t sentenceBits = 0;
for ( ; pos < numBits && sentenceBits < MAX_SENTENCE_BITS; pos += 6, sentenceBits += 6 )
{
uint8_t nmeaByte = (uint8_t)packet.bits(pos, 6);
nmeaByte += (nmeaByte < 40) ? 48 : 56;
sentence[k++] = nmeaByte;
}
sentence[k++] = ',';
if ( numSentences > 1 )
{
if ( i == numSentences )
sentence[k++] = '0' + fillBits;
else
sentence[k++] = '0';
}
else
{
sentence[k++] = '0' + fillBits;
}
sentence[k++] = '*';
sprintf(sentence+k, "%.2X", nmeaCRC(sentence));
sentences.push_back(string(sentence));
}
}
uint8_t NMEAEncoder::nmeaCRC(const char* buff)
{
uint8_t p = 1;
uint8_t crc = buff[p++];
while ( buff[p] != '*' )
crc ^= buff[p++];
return crc;
}