Finish the FSK frame encoder for the CC1120
This commit is contained in:
parent
e80486cc07
commit
0c354da145
|
@ -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;
|
||||
}
|
||||
|
||||
return noutput_items;
|
||||
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 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
|
||||
|
|
Loading…
Reference in New Issue