Skip to content

Commit

Permalink
Merge branch 'full_rate'
Browse files Browse the repository at this point in the history
This feature branch introduces preliminary decoding of the VW (full rate) mode.
This contribution would not have been possible without Sylvain Munaut, who
taught me a number of amazing tricks in the process. The feature branch entails
the following changes:

1. New block YSF FR VCH Decoder
   This block expects a stream of bits. 144 bits of those bits are treated as
   one AMBE frame and converted into something that mbelib can process. We are
   using mbelib's IMBE decoder because the rate stipulated by the Yaesu spec is
   supposed to be backwards compatible to that. This block should apply FEC
   eventually, but currently does not.

2. Changes to the deframer and planner in order to recognize and process packets
   in VW mode.

3. Changes to the ysf_rx.grc example flow graph: A new path was added to receive
   and play voice transmissions in VW mode.

4. Change to the mbelib block: The labels, text strings and code contained the
   FEC size. This was wrong and misleading because we are supposed to do all the
   FEC-work outside of that block. Once we pass a MBE frame to the block, it
   does not have any FEC anymore. We should therefore not imply otherwise.

The merge fixes issue #13.
  • Loading branch information
Mathias Weyland committed Mar 28, 2016
2 parents fe8721d + ea138b6 commit 6830db0
Show file tree
Hide file tree
Showing 17 changed files with 1,220 additions and 677 deletions.
1,549 changes: 895 additions & 654 deletions examples/ysf_rx.grc

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion grc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ install(FILES
ysf_fich_sink_b.xml
ysf_dch_sink_b.xml
ysf_vd2_vch_decoder_bb.xml
ysf_mbelib_block_bf.xml DESTINATION share/gnuradio/grc/blocks
ysf_mbelib_block_bf.xml
ysf_fr_vch_decoder_bb.xml DESTINATION share/gnuradio/grc/blocks
)
4 changes: 4 additions & 0 deletions grc/ysf_deframer_bb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@
<name>VD_VCH</name>
<type>byte</type>
</source>
<source>
<name>FR_VCH</name>
<type>byte</type>
</source>
</block>
15 changes: 15 additions & 0 deletions grc/ysf_fr_vch_decoder_bb.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<block>
<name>YSF FR VCH Decoder</name>
<key>ysf_fr_vch_decoder_bb</key>
<category>YSF</category>
<import>import ysf</import>
<make>ysf.fr_vch_decoder_bb()</make>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>out</name>
<type>byte</type>
</source>
</block>
12 changes: 6 additions & 6 deletions grc/ysf_mbelib_block_bf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
<key>codec</key>
<type>string</type>
<option>
<name>ambe3600x2400</name>
<key>ambe3600x2400</key>
<name>AMBE 2400</name>
<key>AMBE 2400</key>
</option>
<option>
<name>ambe3600x2450</name>
<key>ambe3600x2450</key>
<name>AMBE 2450</name>
<key>AMBE 2450</key>
</option>
<option>
<name>imbe7200x4400</name>
<key>imbe7200x4400</key>
<name>IMBE 4400</name>
<key>IMBE 4400</key>
</option>
</param>
<sink>
Expand Down
3 changes: 2 additions & 1 deletion include/ysf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ install(FILES
fich_sink_b.h
dch_sink_b.h
vd2_vch_decoder_bb.h
mbelib_block_bf.h DESTINATION include/ysf
mbelib_block_bf.h
fr_vch_decoder_bb.h DESTINATION include/ysf
)
56 changes: 56 additions & 0 deletions include/ysf/fr_vch_decoder_bb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* Copyright 2015 Mathias Weyland
*
* This 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, or (at your option)
* any later version.
*
* This software 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/


#ifndef INCLUDED_YSF_FR_VCH_DECODER_BB_H
#define INCLUDED_YSF_FR_VCH_DECODER_BB_H

#include <ysf/api.h>
#include <gnuradio/block.h>

namespace gr {
namespace ysf {

/*!
* \brief <+description of block+>
* \ingroup ysf
*
*/
class YSF_API fr_vch_decoder_bb : virtual public gr::block
{
public:
typedef boost::shared_ptr<fr_vch_decoder_bb> sptr;

/*!
* \brief Return a shared_ptr to a new instance of ysf::fr_vch_decoder_bb.
*
* To avoid accidental use of raw pointers, ysf::fr_vch_decoder_bb's
* constructor is in a private implementation
* class. ysf::fr_vch_decoder_bb::make is the public interface for
* creating new instances.
*/
static sptr make();
};

} // namespace ysf
} // namespace gr

#endif /* INCLUDED_YSF_FR_VCH_DECODER_BB_H */

3 changes: 2 additions & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ list(APPEND ysf_sources
dch_sink_b_impl.cc
demux_planner.cc
vd2_vch_decoder_bb_impl.cc
mbelib_block_bf_impl.cc )
mbelib_block_bf_impl.cc
fr_vch_decoder_bb_impl.cc )

set(ysf_sources "${ysf_sources}" PARENT_SCOPE)
if(NOT ysf_sources)
Expand Down
13 changes: 11 additions & 2 deletions lib/deframer_bb_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const int FICH_STREAM = 0;
const int VD1_DCH_STREAM = 1;
const int VD2_DCH_STREAM = 2;
const int VD_VCH_STREAM = 3;
const int FR_VCH_STREAM = 4;

namespace gr {
namespace ysf {
Expand All @@ -45,7 +46,7 @@ namespace gr {
deframer_bb_impl::deframer_bb_impl(int threshold)
: gr::block("deframer_bb",
gr::io_signature::make(1, 1, sizeof(char)),
gr::io_signature::make(4, 4, sizeof(char)))
gr::io_signature::make(5, 5, sizeof(char)))
{
d_state = UNSYNCED;
d_shift_register = 0;
Expand Down Expand Up @@ -86,9 +87,11 @@ namespace gr {
(char*) output_items[VD1_DCH_STREAM], // out_vd1_dch
(char*) output_items[VD2_DCH_STREAM], // out_vd2_dch
(char*) output_items[VD_VCH_STREAM], // out_vd_vch
(char*) output_items[FR_VCH_STREAM], // out_fr_vch
0, // output_counter_vd1_dch
0, // output_counter_vd2_dch
0, // output_counter_vd_vch
0, // output_counter_fr_vch
noutput_items, // noutput_item
};

Expand Down Expand Up @@ -164,6 +167,7 @@ namespace gr {
produce(VD1_DCH_STREAM, payload_streams.output_counter_vd1_dch);
produce(VD2_DCH_STREAM, payload_streams.output_counter_vd2_dch);
produce(VD_VCH_STREAM, payload_streams.output_counter_vd_vch);
produce(FR_VCH_STREAM, payload_streams.output_counter_fr_vch);

return WORK_CALLED_PRODUCE;
}
Expand All @@ -174,7 +178,8 @@ namespace gr {
while( d_planner.get_state() == demux_planner::ACTIONS_PENDING &&
payload_streams.output_counter_vd1_dch < payload_streams.noutput_items &&
payload_streams.output_counter_vd2_dch < payload_streams.noutput_items &&
payload_streams.output_counter_vd_vch < payload_streams.noutput_items )
payload_streams.output_counter_vd_vch < payload_streams.noutput_items &&
payload_streams.output_counter_fr_vch < payload_streams.noutput_items )
{
demux_planner::plan_item_t item = d_planner.get_current_item();
switch( item.output_stream )
Expand Down Expand Up @@ -205,6 +210,10 @@ namespace gr {
payload_streams.out_vd_vch[payload_streams.output_counter_vd_vch++] =
d_packet_buffer[item.position];
break;
case demux_planner::FR_VCH:
payload_streams.out_fr_vch[payload_streams.output_counter_fr_vch++] =
d_packet_buffer[item.position];
break;

}
d_planner.consume_current_item();
Expand Down
2 changes: 2 additions & 0 deletions lib/deframer_bb_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ namespace gr {
char *out_vd1_dch;
char *out_vd2_dch;
char *out_vd_vch;
char *out_fr_vch;
uint16_t output_counter_vd1_dch;
uint16_t output_counter_vd2_dch;
uint16_t output_counter_vd_vch;
uint16_t output_counter_fr_vch;
const int noutput_items;
};

Expand Down
5 changes: 5 additions & 0 deletions lib/demux_planner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ demux_planner::plan_for(long fi, long fn, long dt)
}
break;

case 0b11:
for(uint8_t i=0; i < 5; i++)
d_item_queue.push({ FR_VCH, i*(144/2), i*(144/2)+144/2, NONE } );
break;

default:
std::cerr << "Ignoring unknown packet with DT=" << dt << std::endl;
break;
Expand Down
2 changes: 1 addition & 1 deletion lib/demux_planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class demux_planner
{
public:
enum output_stream_t { VD1_DCH, VD2_DCH, VD_VCH, SKIP }; // FIXME get rid of SKIP
enum output_stream_t { VD1_DCH, VD2_DCH, VD_VCH, FR_VCH, SKIP }; // FIXME get rid of SKIP
enum state_t { STALL, ACTIONS_PENDING, DONE };
enum unit_type_t { CSD1, CSD2, CSD3, DEST, SRC, DOWN, UP, REM12, REM34, DT, NONE };
struct plan_item_t
Expand Down
151 changes: 151 additions & 0 deletions lib/fr_vch_decoder_bb_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* -*- c++ -*- */
/*
* Copyright 2015 Mathias Weyland
*
* This 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, or (at your option)
* any later version.
*
* This software 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "fr_vch_decoder_bb_impl.h"

namespace gr {
namespace ysf {

fr_vch_decoder_bb::sptr
fr_vch_decoder_bb::make()
{
return gnuradio::get_initial_sptr
(new fr_vch_decoder_bb_impl());
}

fr_vch_decoder_bb_impl::fr_vch_decoder_bb_impl()
: gr::block("fr_vch_decoder_bb",
gr::io_signature::make(1, 1, sizeof(char)),
gr::io_signature::make(1, 1, sizeof(char)))
{
d_bit_counter = 0;
}

fr_vch_decoder_bb_impl::~fr_vch_decoder_bb_impl()
{
}

void
fr_vch_decoder_bb_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
/* <+forecast+> e.g. ninput_items_required[0] = noutput_items */ //FIXME issue #14
}

int
fr_vch_decoder_bb_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const char *in = (const char*) input_items[0];
char *out = (char *) output_items[0];

int input_counter = 0;
int output_counter = 0;
while(input_counter < ninput_items[0])
{

if(d_bit_counter == 144)
{
if(noutput_items - output_counter < 88) break; // output buffer too full

d_bit_counter = 0;

uint8_t reshuffled_frame[144];
reshuffle_frame(d_frame, reshuffled_frame);

uint16_t seed = 0;
for(uint16_t i=0; i<12; i++)
{
seed = (seed << 1) | reshuffled_frame[i];
}

scramble(reshuffled_frame+23, reshuffled_frame+23, 144-23-7, seed, 4);

// FIXME: We should apply FEC here
for(uint8_t i= 0; i< 12; i++) out[output_counter++] = reshuffled_frame[i]; // u0
for(uint8_t i= 23; i< 35; i++) out[output_counter++] = reshuffled_frame[i]; // u1
for(uint8_t i= 46; i< 58; i++) out[output_counter++] = reshuffled_frame[i]; // u2
for(uint8_t i= 69; i< 81; i++) out[output_counter++] = reshuffled_frame[i]; // u3

for(uint8_t i= 92; i<103; i++) out[output_counter++] = reshuffled_frame[i]; // u4
for(uint8_t i=107; i<118; i++) out[output_counter++] = reshuffled_frame[i]; // u5
for(uint8_t i=122; i<133; i++) out[output_counter++] = reshuffled_frame[i]; // u6

for(uint8_t i=137; i<144; i++) out[output_counter++] = reshuffled_frame[i]; // u7

}

d_frame[d_bit_counter++] = in[input_counter++];
}

consume_each(input_counter);
produce(0, output_counter);

return WORK_CALLED_PRODUCE;
}

void
fr_vch_decoder_bb_impl::reshuffle_frame(uint8_t old_frame[144], uint8_t new_frame[144])
{
// I hold Sylvain Munaut in high esteem for figuring this out.
const uint8_t permutation[144] = {
0, 7, 12, 19, 24, 31, 36, 43, 48, 55, 60, 67, // [ 0 - 11] yellow message
72, 79, 84, 91, 96, 103, 108, 115, 120, 127, 132, // [ 12 - 22] yellow FEC
139, 1, 6, 13, 18, 25, 30, 37, 42, 49, 54, 61, // [ 23 - 34] orange message
66, 73, 78, 85, 90, 97, 102, 109, 114, 121, 126, // [ 35 - 45] orange FEC
133, 138, 2, 9, 14, 21, 26, 33, 38, 45, 50, 57, // [ 46 - 57] red message
62, 69, 74, 81, 86, 93, 98, 105, 110, 117, 122, // [ 58 - 68] red FEC
129, 134, 141, 3, 8, 15, 20, 27, 32, 39, 44, 51, // [ 69 - 80] pink message
56, 63, 68, 75, 80, 87, 92, 99, 104, 111, 116, // [ 81 - 91] pink FEC
123, 128, 135, 140, 4, 11, 16, 23, 28, 35, 40, // [ 92 - 102] dark blue message
47, 52, 59, 64, // [103 - 106] dark blue FEC
71, 76, 83, 88, 95, 100, 107, 112, 119, 124, 131, // [107 - 117] light blue message
136, 143, 5, 10, // [118 - 121] light blue FEC
17, 22, 29, 34, 41, 46, 53, 58, 65, 70, 77, // [122 - 132] green message
82, 89, 94, 101, // [133 - 136] green FEC
106, 113, 118, 125, 130, 137, 142, // [137 - 143] unprotected
};

for(uint8_t i=0; i<144; i++)
{
new_frame[i] = old_frame[permutation[i]];
}
}

void
fr_vch_decoder_bb_impl::scramble(uint8_t out[], uint8_t in[], uint16_t n, uint32_t seed, uint8_t shift)
{
uint32_t v = seed << shift;
for (uint16_t i=0; i<n; i++)
{
v = ((v * 173) + 13849) & 0xffff;
out[i] = in[i] ^ (v >> 15);
}
}

} /* namespace ysf */
} /* namespace gr */

Loading

0 comments on commit 6830db0

Please sign in to comment.