Commit 0c354da1 authored by Manolis Surligas's avatar Manolis Surligas

Finish the FSK frame encoder for the CC1120

parent e80486cc
......@@ -4,7 +4,7 @@
<key>satnogs_upsat_fsk_frame_acquisition</key>
<category>satnogs</category>
<import>import satnogs</import>
<make>satnogs.upsat_fsk_frame_acquisition($preamble, $sync_word, $whitening, $manchester)</make>
<make>satnogs.upsat_fsk_frame_acquisition($preamble, $sync_word, $whitening, $manchester, $check_crc)</make>
<param>
<name>Frame Preamble</name>
......@@ -45,6 +45,20 @@
<key>True</key>
</option>
</param>
<param>
<name>Check CRC</name>
<key>check_crc</key>
<type>enum</type>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
......
......@@ -4,7 +4,7 @@
<key>satnogs_upsat_fsk_frame_encoder</key>
<category>satnogs</category>
<import>import satnogs</import>
<make>satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester)</make>
<make>satnogs.upsat_fsk_frame_encoder($preamble, $sync_word, $append_crc, $whitening, $manchester, $msb_first)</make>
<param>
<name>Frame Preamble</name>
......@@ -59,6 +59,20 @@
<key>True</key>
</option>
</param>
<param>
<name>Send MS bit first</name>
<key>msb_first</key>
<type>enum</type>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<sink>
<name>pdu</name>
......
......@@ -52,11 +52,13 @@ namespace gr
* the whitening algorithm of the CC1120 chip. False otherwise.
* @param manchester true if the transmitted data have been processed by
* the Manchester algorithm of the CC1120 chip. False otherwise.
* @param check_crc if set to true the decoder will push frames only if
* their CRC field in correct.
*/
static sptr
make (const std::vector<uint8_t> &preamble,
const std::vector<uint8_t> &sync_word, bool whitening = false,
bool manchester = false);
bool manchester = false, bool check_crc = true);
};
} // namespace satnogs
......
......@@ -61,11 +61,15 @@ namespace gr
*
* @param manchester true if the transmitted data have been processed by
* the Manchester algorithm of the CC1120 chip. False otherwise.
*
* @param msb_first if set to true, the the treansmission starts from the
* MSB of each byte.
*/
static sptr
make (const std::vector<uint8_t>& preamble,
const std::vector<uint8_t>& sync_word, bool append_crc = true,
bool whitening = false, bool manchester = false);
bool whitening = false, bool manchester = false,
bool msb_first = true);
};
} // namespace satnogs
......
......@@ -76,6 +76,22 @@ namespace gr
0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 0x7BC7,
0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 };
static inline uint16_t
update_crc16_ccitt(uint16_t crc, const uint8_t *data, size_t len)
{
register size_t i;
for (i = 0; i < len; i++) {
crc = (crc >> 8) ^ crc16_ccitt_table_reverse[(crc ^ data[i]) & 0xff];
}
return crc;
}
static inline uint16_t
crc16_ccitt(const uint8_t *data, size_t len)
{
return update_crc16_ccitt(0xFFFF, data, len) ^ 0xFFFF;
}
/**
* Counts the number of active bits in x
*/
......
......@@ -25,6 +25,7 @@
#include <gnuradio/io_signature.h>
#include "upsat_fsk_frame_acquisition_impl.h"
#include <satnogs/log.h>
#include <satnogs/utils.h>
namespace gr
{
......@@ -34,11 +35,12 @@ namespace gr
upsat_fsk_frame_acquisition::sptr
upsat_fsk_frame_acquisition::make (const std::vector<uint8_t> &preamble,
const std::vector<uint8_t> &sync_word,
bool whitening, bool manchester)
bool whitening, bool manchester,
bool check_crc)
{
return gnuradio::get_initial_sptr (
new upsat_fsk_frame_acquisition_impl (preamble, sync_word, whitening,
manchester));
manchester, check_crc));
}
/*
......@@ -46,7 +48,8 @@ namespace gr
*/
upsat_fsk_frame_acquisition_impl::upsat_fsk_frame_acquisition_impl (
const std::vector<uint8_t> &preamble,
const std::vector<uint8_t> &sync_word, bool whitening, bool manchester) :
const std::vector<uint8_t> &sync_word, bool whitening, bool manchester,
bool check_crc) :
gr::sync_block ("upsat_fsk_frame_acquisition",
gr::io_signature::make (1, 1, sizeof(float)),
gr::io_signature::make (0, 0, 0)),
......@@ -61,6 +64,9 @@ namespace gr
* searching for the SYNC word.
*/
d_search_for_sync_thrhld(d_preamble_len / 3),
d_whitening(whitening),
d_manchester(manchester),
d_check_crc(check_crc),
d_state (SEARCHING),
d_shifting_byte (0x0),
d_decoded_bytes (0),
......@@ -157,7 +163,7 @@ namespace gr
{
LOG_DEBUG("Enter have payload");
d_state = HAVE_PAYLOAD;
d_decoded_bytes = 0;
d_decoded_bytes = 1;
d_decoded_bits = 0;
}
......@@ -167,6 +173,8 @@ namespace gr
gr_vector_void_star &output_items)
{
int i;
uint16_t crc_received;
uint16_t crc_calc;
const float *in = (const float *) input_items[0];
for (i = 0; i < noutput_items; i++) {
slice_and_shift (in[i]);
......@@ -234,7 +242,10 @@ namespace gr
case HAVE_FRAME_LEN:
d_decoded_bits++;
if(d_decoded_bits == 8) {
d_frame_len = d_shifting_byte;
/* Frame length field is needed for the CRC calculation */
d_pdu[0] = d_shifting_byte;
/* CRC is not included in the frame length field, but we want it */
d_frame_len = 1 + d_shifting_byte + sizeof(uint16_t);
have_payload();
}
break;
......@@ -246,8 +257,28 @@ namespace gr
d_decoded_bytes++;
if (d_decoded_bytes == d_frame_len) {
message_port_pub (pmt::mp ("pdu"),
pmt::make_blob (d_pdu, d_frame_len));
if(!d_check_crc){
message_port_pub (
pmt::mp ("pdu"),
pmt::make_blob (d_pdu + 1,
d_frame_len - 1 - sizeof(uint16_t)));
reset_state ();
break;
}
/* Retrieve and check the CRC */
memcpy(&crc_received, d_pdu + d_frame_len - sizeof(uint16_t),
sizeof(uint16_t));
crc_calc = crc16_ccitt(d_pdu, d_frame_len - sizeof(uint16_t));
if(crc_calc == crc_received) {
message_port_pub (
pmt::mp ("pdu"),
pmt::make_blob (d_pdu + 1,
d_frame_len - 1 - sizeof(uint16_t)));
}
else{
LOG_WARN("Frame with wrong CRC");
}
reset_state ();
}
}
......
......@@ -51,6 +51,9 @@ namespace gr
const std::vector<uint8_t> d_sync_word;
const size_t d_sync_word_len;
const size_t d_search_for_sync_thrhld;
const bool d_whitening;
const bool d_manchester;
const bool d_check_crc;
decoding_state_t d_state;
uint8_t d_shifting_byte;
size_t d_decoded_bytes;
......@@ -77,7 +80,8 @@ namespace gr
public:
upsat_fsk_frame_acquisition_impl (const std::vector<uint8_t> &preamble,
const std::vector<uint8_t> &sync_word,
bool whitening, bool manchester);
bool whitening, bool manchester,
bool check_crc);
~upsat_fsk_frame_acquisition_impl ();
// Where all the action really happens
......
......@@ -25,6 +25,7 @@
#include <gnuradio/io_signature.h>
#include "upsat_fsk_frame_encoder_impl.h"
#include <satnogs/log.h>
#include <satnogs/utils.h>
namespace gr
{
......@@ -35,11 +36,12 @@ namespace gr
upsat_fsk_frame_encoder::make (const std::vector<uint8_t>& preamble,
const std::vector<uint8_t>& sync_word,
bool append_crc, bool whitening,
bool manchester)
bool manchester,
bool msb_first)
{
return gnuradio::get_initial_sptr (
new upsat_fsk_frame_encoder_impl (preamble, sync_word, append_crc,
whitening, manchester));
whitening, manchester, msb_first));
}
/*
......@@ -48,7 +50,7 @@ namespace gr
upsat_fsk_frame_encoder_impl::upsat_fsk_frame_encoder_impl (
const std::vector<uint8_t>& preamble,
const std::vector<uint8_t>& sync_word, bool append_crc, bool whitening,
bool manchester) :
bool manchester, bool msb_first) :
gr::sync_block ("upsat_fsk_frame_encoder",
gr::io_signature::make (0, 0, 0),
gr::io_signature::make (1, 1, sizeof(float))),
......@@ -59,9 +61,14 @@ namespace gr
d_append_crc(append_crc),
d_whitening(whitening),
d_manchester(manchester),
d_msb_first(msb_first),
d_max_pdu_len(d_preamble_len + d_sync_word_len + sizeof(uint8_t)
+ UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)),
d_encoded(0),
d_pdu_len(0)
{
/* Simplify the logic of the output samples handling */
set_output_multiple(8);
message_port_register_in (pmt::mp ("pdu"));
/*
* Allocate memory for the maximum possible frame WITH all headers and
......@@ -71,8 +78,11 @@ namespace gr
* +-------------+----------+--------+--------------------------+------+
* User def. User def. 1B 1-255 B 2 B
*/
d_pdu = new uint8_t[d_preamble_len + d_sync_word_len + sizeof(uint8_t)
+ UPSAT_MAX_FRAME_LEN + sizeof(uint16_t)];
d_pdu = new uint8_t[d_max_pdu_len];
if(!d_pdu) {
throw std::runtime_error("Could not allocate memory");
}
/* Copy the preamble at the start of the pdu */
memcpy(d_pdu, d_preamble.data(), d_preamble_len);
......@@ -87,11 +97,51 @@ namespace gr
delete [] d_pdu;
}
inline void
upsat_fsk_frame_encoder_impl::map_msb_first(float *out, size_t nsamples_out)
{
size_t i;
register uint8_t b;
for(i = 0; i < nsamples_out; i+=8)
{
b = d_pdu[d_encoded + i/8];
out[i] = ((b >> 7 ) * 2.0f) - 1.0f;
out[i + 1] = (( (b >> 6 ) & 0x1) * 2.0f) - 1.0f;
out[i + 2] = (( (b >> 5 ) & 0x1) * 2.0f) - 1.0f;
out[i + 3] = (( (b >> 4 ) & 0x1) * 2.0f) - 1.0f;
out[i + 4] = (( (b >> 3 ) & 0x1) * 2.0f) - 1.0f;
out[i + 5] = (( (b >> 2 ) & 0x1) * 2.0f) - 1.0f;
out[i + 6] = (( (b >> 1 ) & 0x1) * 2.0f) - 1.0f;
out[i + 7] = ((b & 0x1) * 2.0f) - 1.0f;
}
}
inline void
upsat_fsk_frame_encoder_impl::map_lsb_first(float *out, size_t nsamples_out)
{
size_t i;
register uint8_t b;
for(i = 0; i < nsamples_out; i+=8)
{
b = d_pdu[d_encoded + i/8];
out[i + 7] = ((b >> 7 ) * 2.0f) - 1.0f;
out[i + 6] = (( (b >> 6 ) & 0x1) * 2.0f) - 1.0f;
out[i + 5] = (( (b >> 5 ) & 0x1) * 2.0f) - 1.0f;
out[i + 4] = (( (b >> 4 ) & 0x1) * 2.0f) - 1.0f;
out[i + 3] = (( (b >> 3 ) & 0x1) * 2.0f) - 1.0f;
out[i + 2] = (( (b >> 2 ) & 0x1) * 2.0f) - 1.0f;
out[i + 1] = (( (b >> 1 ) & 0x1) * 2.0f) - 1.0f;
out[i] = ((b & 0x1) * 2.0f) - 1.0f;
}
}
int
upsat_fsk_frame_encoder_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
uint16_t crc;
size_t min_available;
pmt::pmt_t pdu;
float *out = (float *) output_items[0];
......@@ -107,21 +157,48 @@ namespace gr
LOG_ERROR("PDU is greater than the supported. Dropping the PDU");
return 0;
}
/* Set the frame length at the corresponding field */
/*
* Set the frame length at the corresponding field.
* NOTE: The frame length is calculated taking consideration only
* the address field (if exists) and the payload. Length and CRC fields
* are NOT included.
*/
d_pdu[d_preamble_len + d_sync_word_len] = (uint8_t) d_pdu_len;
/* Append the variable length PDU */
memcpy (d_pdu + d_preamble_len + d_sync_word_len + sizeof(uint8_t),
pmt::blob_data (pdu),
d_pdu_len * sizeof(uint8_t));
d_pdu_len += d_preamble_len + d_sync_word_len + sizeof(uint8_t);
memcpy (d_pdu + d_preamble_len + d_sync_word_len + 1,
pmt::blob_data (pdu), d_pdu_len);
/* If it is necessary calculate and append the CRC */
if(d_append_crc) {
/* TODO: Calc CRC */
crc = crc16_ccitt(d_pdu + d_preamble_len + d_sync_word_len,
d_pdu_len + 1);
memcpy(d_pdu + d_preamble_len + d_sync_word_len + 1 + d_pdu_len,
&crc, sizeof(uint16_t));
d_pdu_len += sizeof(uint16_t);
}
d_pdu_len += d_preamble_len + d_sync_word_len + 1;
}
noutput_items = std::max (0, noutput_items);
min_available = std::min ((size_t) noutput_items,
(d_pdu_len - d_encoded) * 8);
if(d_msb_first){
map_msb_first(out, min_available*8);
}
else{
map_lsb_first(out, min_available*8);
}
d_encoded += min_available/8;
/* End of the frame reached */
if(d_encoded == d_pdu_len){
d_encoded = 0;
}
return noutput_items;
return min_available;
}
} /* namespace satnogs */
......
......@@ -38,15 +38,24 @@ namespace gr
const bool d_append_crc;
const bool d_whitening;
const bool d_manchester;
const bool d_msb_first;
const size_t d_max_pdu_len;
size_t d_encoded;
size_t d_pdu_len;
uint8_t *d_pdu;
inline void
map_msb_first (float *out, size_t nsamples_out);
inline void
map_lsb_first (float *out, size_t nsamples_out);
public:
upsat_fsk_frame_encoder_impl (const std::vector<uint8_t>& preamble,
const std::vector<uint8_t>& sync_word,
bool append_crc, bool whitening,
bool manchester);
bool manchester,
bool msb_first);
~upsat_fsk_frame_encoder_impl ();
// Where all the action really happens
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment