diff options
author | Johnathan Corgan <johnathan@corganlabs.com> | 2015-09-05 17:59:40 -0700 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2015-09-05 17:59:40 -0700 |
commit | 45c0feeaeffde561758a4d92bf4463d60b85633a (patch) | |
tree | 0bd17e7c71c6749348d8e178a07be2acb6a4b257 | |
parent | 44148413d25c9e9e6cf65292597032bb3ccf833b (diff) | |
parent | b90c574e2fbf0443e1eea2ee06779c2a85f86def (diff) |
Merge remote-tracking branch 'drmpeg/gr-dtv-dvbt-rx'
40 files changed, 3771 insertions, 13 deletions
diff --git a/gr-dtv/grc/CMakeLists.txt b/gr-dtv/grc/CMakeLists.txt index 2187e283a5..2fed81ab12 100644 --- a/gr-dtv/grc/CMakeLists.txt +++ b/gr-dtv/grc/CMakeLists.txt @@ -60,6 +60,14 @@ install(FILES dtv_dvbt_symbol_inner_interleaver.xml dtv_dvbt_map.xml dtv_dvbt_reference_signals.xml + dtv_dvbt_ofdm_sym_acquisition.xml + dtv_dvbt_demod_reference_signals.xml + dtv_dvbt_demap.xml + dtv_dvbt_bit_inner_deinterleaver.xml + dtv_dvbt_viterbi_decoder.xml + dtv_dvbt_convolutional_deinterleaver.xml + dtv_dvbt_reed_solomon_dec.xml + dtv_dvbt_energy_descramble.xml DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "dtv_python" ) diff --git a/gr-dtv/grc/dtv_block_tree.xml b/gr-dtv/grc/dtv_block_tree.xml index 1f05bc75dc..32c8974531 100644 --- a/gr-dtv/grc/dtv_block_tree.xml +++ b/gr-dtv/grc/dtv_block_tree.xml @@ -85,6 +85,14 @@ <block>dtv_dvbt_symbol_inner_interleaver</block> <block>dtv_dvbt_map</block> <block>dtv_dvbt_reference_signals</block> + <block>dtv_dvbt_ofdm_sym_acquisition</block> + <block>dtv_dvbt_demod_reference_signals</block> + <block>dtv_dvbt_demap</block> + <block>dtv_dvbt_bit_inner_deinterleaver</block> + <block>dtv_dvbt_viterbi_decoder</block> + <block>dtv_dvbt_convolutional_deinterleaver</block> + <block>dtv_dvbt_reed_solomon_dec</block> + <block>dtv_dvbt_energy_descramble</block> </cat> </cat> </cat> diff --git a/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml b/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml new file mode 100644 index 0000000000..ff338d2118 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_bit_inner_deinterleaver.xml @@ -0,0 +1,89 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Bit Inner Deinterleaver +################################################### + --> +<block> + <name>Bit Inner Deinterleaver</name> + <key>dtv_dvbt_bit_inner_deinterleaver</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_bit_inner_deinterleaver($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + <opt>num_streams:1</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + <opt>num_streams:2</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + <opt>num_streams:2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + <opt>num_streams:2</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <sink> + <name>in</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + <nports>$hierarchy.num_streams</nports> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml b/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml new file mode 100644 index 0000000000..315920bd42 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_convolutional_deinterleaver.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Convolutional Deinterleaver +################################################### + --> +<block> + <name>Convolutional Deinterleaver</name> + <key>dtv_dvbt_convolutional_deinterleaver</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_convolutional_deinterleaver($blocks, $I, $M)</make> + <param> + <name>Blocks (12 Bytes)</name> + <key>blocks</key> + <value>136</value> + <type>int</type> + </param> + <param> + <name>Number of Shift registers</name> + <key>I</key> + <value>12</value> + <type>int</type> + </param> + <param> + <name>Depth of shift registers</name> + <key>M</key> + <value>17</value> + <type>int</type> + </param> + <check>$blocks > 0</check> + <check>$I > 0</check> + <check>$M > 0</check> + <sink> + <name>in</name> + <type>byte</type> + <vlen>1</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$blocks*$I</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_demap.xml b/gr-dtv/grc/dtv_dvbt_demap.xml new file mode 100644 index 0000000000..2268ed7cf5 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_demap.xml @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Demap +################################################### + --> +<block> + <name>DVB-T Demap</name> + <key>dtv_dvbt_demap</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_demap($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val, $gain)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <param> + <name>Gain</name> + <key>gain</key> + <value>1</value> + <type>complex</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$transmission_mode.payload_length</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$transmission_mode.payload_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml b/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml new file mode 100644 index 0000000000..f92469b7e6 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_demod_reference_signals.xml @@ -0,0 +1,222 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Demod Reference Signals +################################################### + --> +<block> + <name>Demod Reference Signals</name> + <key>dtv_dvbt_demod_reference_signals</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_demod_reference_signals($type.size, $transmission_mode.fft_length, $transmission_mode.payload_length, $constellation.val, $hierarchy.val, $code_rate_hp.val, $code_rate_lp.val, $guard_interval.val, $transmission_mode.val, $include_cell_id.val, $cell_id)</make> + <param> + <name>IO Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Code rate HP</name> + <key>code_rate_hp</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Code rate LP</name> + <key>code_rate_lp</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Guard Interval</name> + <key>guard_interval</key> + <type>enum</type> + <option> + <name>1/32</name> + <key>GI_1_32</key> + <opt>val:dtv.GI_1_32</opt> + </option> + <option> + <name>1/16</name> + <key>GI_1_16</key> + <opt>val:dtv.GI_1_16</opt> + </option> + <option> + <name>1/8</name> + <key>GI_1_8</key> + <opt>val:dtv.GI_1_8</opt> + </option> + <option> + <name>1/4</name> + <key>GI_1_4</key> + <opt>val:dtv.GI_1_4</opt> + </option> + </param> + <param> + <name>Transmission Mode</name> + <key>transmission_mode</key> + <type>enum</type> + <option> + <name>2K</name> + <key>T2k</key> + <opt>val:dtv.T2k</opt> + <opt>fft_length:2048</opt> + <opt>payload_length:1512</opt> + </option> + <option> + <name>8K</name> + <key>T8k</key> + <opt>val:dtv.T8k</opt> + <opt>fft_length:8192</opt> + <opt>payload_length:6048</opt> + </option> + </param> + <param> + <name>Include Cell ID</name> + <key>include_cell_id</key> + <type>enum</type> + <option> + <name>Yes</name> + <key>call_id_yes</key> + <opt>val:1</opt> + </option> + <option> + <name>No</name> + <key>cell_id_no</key> + <opt>val:0</opt> + </option> + </param> + <param> + <name>Cell Id</name> + <key>cell_id</key> + <value>0</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$transmission_mode.fft_length</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$transmission_mode.payload_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_energy_descramble.xml b/gr-dtv/grc/dtv_dvbt_energy_descramble.xml new file mode 100644 index 0000000000..689f85424f --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_energy_descramble.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Energy Descramble +################################################### + --> +<block> + <name>Energy Descramble</name> + <key>dtv_dvbt_energy_descramble</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_energy_descramble($nsize)</make> + <param> + <name>Blocks(188 Bytes)</name> + <key>nsize</key> + <value>8</value> + <type>int</type> + </param> + <check>$nsize > 0</check> + <sink> + <name>in</name> + <type>byte</type> + <vlen>188*8</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>1</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml b/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml new file mode 100644 index 0000000000..a75dcc02c3 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_ofdm_sym_acquisition.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- +################################################### +## OFDM Symbol Acquisition +################################################### + --> +<block> + <name>OFDM Symbol Acquisition</name> + <key>dtv_dvbt_ofdm_sym_acquisition</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_ofdm_sym_acquisition(1, $fft_length, $occupied_tones, $cp_length, $snr)</make> + <param> + <name>Output Type</name> + <key>type</key> + <value>float</value> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>fcn:c</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>fcn:f</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>fcn:i</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>fcn:s</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>fcn:b</opt> + </option> + </param> + <param> + <name>FFT Length</name> + <key>fft_length</key> + <value>2048</value> + <type>int</type> + </param> + <param> + <name>Occupied Tones</name> + <key>occupied_tones</key> + <value>1705</value> + <type>int</type> + </param> + <param> + <name>Cyclic Prefix Length</name> + <key>cp_length</key> + <value>64</value> + <type>int</type> + </param> + <param> + <name>SNR</name> + <key>snr</key> + <value>10</value> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>$fft_length</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml b/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml new file mode 100644 index 0000000000..798a6d40f8 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_reed_solomon_dec.xml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Reed Solomon Decoder +################################################### + --> +<block> + <name>Reed-Solomon Decoder</name> + <key>dtv_dvbt_reed_solomon_dec</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_reed_solomon_dec($p, $m, $gfpoly, $n, $k, $t, $s, $blocks)</make> + <param> + <name>p</name> + <key>p</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>m</name> + <key>m</key> + <value>8</value> + <type>int</type> + </param> + <param> + <name>GF polynomial</name> + <key>gfpoly</key> + <value>0x11d</value> + <type>raw</type> + </param> + <param> + <name>N</name> + <key>n</key> + <value>255</value> + <type>int</type> + </param> + <param> + <name>K</name> + <key>k</key> + <value>239</value> + <type>int</type> + </param> + <param> + <name>t</name> + <key>t</key> + <value>8</value> + <type>int</type> + </param> + <param> + <name>Shortening size</name> + <key>s</key> + <value>51</value> + <type>int</type> + </param> + <param> + <name>Blocks</name> + <key>blocks</key> + <value>8</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + <vlen>$blocks*($n-$s)</vlen> + </sink> + <source> + <name>out</name> + <type>byte</type> + <vlen>$blocks*($k-$s)</vlen> + </source> +</block> diff --git a/gr-dtv/grc/dtv_dvbt_reference_signals.xml b/gr-dtv/grc/dtv_dvbt_reference_signals.xml index 9be57630e5..3a4282cc50 100644 --- a/gr-dtv/grc/dtv_dvbt_reference_signals.xml +++ b/gr-dtv/grc/dtv_dvbt_reference_signals.xml @@ -199,7 +199,7 @@ </option> <option> <name>No</name> - <key>cell_ide_no</key> + <key>cell_id_no</key> <opt>val:0</opt> </option> </param> diff --git a/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml b/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml new file mode 100644 index 0000000000..1dde80c281 --- /dev/null +++ b/gr-dtv/grc/dtv_dvbt_viterbi_decoder.xml @@ -0,0 +1,120 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DVB-T Viterbi Decoder +################################################### + --> +<block> + <name>Viterbi Decoder</name> + <key>dtv_dvbt_viterbi_decoder</key> + <import>from gnuradio import dtv</import> + <make>dtv.dvbt_viterbi_decoder($constellation.val, $hierarchy.val, $code_rate.val, $block_size)</make> + <param> + <name>Constellation Type</name> + <key>constellation</key> + <type>enum</type> + <option> + <name>QPSK</name> + <key>qpsk</key> + <opt>val:dtv.MOD_QPSK</opt> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + <opt>val:dtv.MOD_16QAM</opt> + </option> + <option> + <name>64QAM</name> + <key>64qam</key> + <opt>val:dtv.MOD_64QAM</opt> + </option> + </param> + <param> + <name>Hierarchy Type</name> + <key>hierarchy</key> + <type>enum</type> + <option> + <name>Non Hierarchical</name> + <key>nh</key> + <opt>val:dtv.NH</opt> + </option> + <option> + <name>Alpha 1</name> + <key>alpha1</key> + <opt>val:dtv.ALPHA1</opt> + </option> + <option> + <name>Alpha 2</name> + <key>alpha2</key> + <opt>val:dtv.ALPHA2</opt> + </option> + <option> + <name>Alpha 4</name> + <key>alpha4</key> + <opt>val:dtv.ALPHA4</opt> + </option> + </param> + <param> + <name>Code rate</name> + <key>code_rate</key> + <type>enum</type> + <option> + <name>1/2</name> + <key>C1_2</key> + <opt>val:dtv.C1_2</opt> + </option> + <option> + <name>2/3</name> + <key>C2_3</key> + <opt>val:dtv.C2_3</opt> + </option> + <option> + <name>3/4</name> + <key>C3_4</key> + <opt>val:dtv.C3_4</opt> + </option> + <option> + <name>5/6</name> + <key>C5_6</key> + <opt>val:dtv.C5_6</opt> + </option> + <option> + <name>7/8</name> + <key>C7_8</key> + <opt>val:dtv.C7_8</opt> + </option> + </param> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Int</name> + <key>i</key> + <opt>io:int</opt> + </option> + <option> + <name>Short</name> + <key>s</key> + <opt>io:short</opt> + </option> + <option> + <name>Byte</name> + <key>b</key> + <opt>io:byte</opt> + </option> + </param> + <param> + <name>Block Size</name> + <key>block_size</key> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>$type.io</type> + </source> +</block> diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h new file mode 100644 index 0000000000..1f9aab16e5 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_deinterleaver.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_BIT_INNER_DEINTERLEVER_H +#define INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Bit Inner deinterleaver. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.4.1 \n + * Data Input format: \n + * 000000B0B1 - QPSK. \n + * 0000B0B1B2B3 - 16QAM. \n + * 00B0B1B2B3B4B5 - 64QAM. \n + * Data Output format: \n + * 000000X0X1 - QPSK. \n + * 0000X0X1X2X3 - 16QAM. \n + * 00X0X1X2X3X4X5 - 64QAM. \n + * bit deinterleaver block size is 126. + */ + class DTV_API dvbt_bit_inner_deinterleaver : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_bit_inner_deinterleaver> sptr; + + /*! + * \brief Create a Bit Inner deinterleaver + * + * \param nsize length of input stream. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param transmission transmission mode used. + */ + static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h new file mode 100644 index 0000000000..1a52c41af8 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_deinterleaver.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H +#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Convolutional deinterleaver. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.1 \n + * Forney (Ramsey type III) convolutional deinterleaver. \n + * Data input: Stream of 1 byte elements. \n + * Data output: Blocks of I bytes size. + */ + class DTV_API dvbt_convolutional_deinterleaver : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_convolutional_deinterleaver> sptr; + + /*! + * \brief Create a DVB-T convolutional deinterleaver. + * + * \param nsize number of blocks to process. \n + * \param I size of a block. \n + * \param M depth length for each element in shift registers. + */ + static sptr make(int nsize, int I, int M); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_demap.h b/gr-dtv/include/gnuradio/dtv/dvbt_demap.h new file mode 100644 index 0000000000..1f04beea0a --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_demap.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_DVBT_DEMAP_H +#define INCLUDED_DTV_DVBT_DVBT_DEMAP_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief DVB-T demapper. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.5. \n + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * 000000Y0Y1 - QPSK. \n + * 0000Y0Y1Y2Y3 - 16QAM. \n + * 00Y0Y1Y2Y3Y4Y5 - 64QAM. + */ + class DTV_API dvbt_demap : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_demap> sptr; + + /*! + * \brief Create a DVB-T demapper. + * + * \param nsize length of input stream. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param transmission transmission mode used. \n + * \param gain gain of complex input stream. + */ + static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DVBT_DEMAP_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h b/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h new file mode 100644 index 0000000000..3f28ddeec7 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_demod_reference_signals.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H +#define INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Reference signals demodulator. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.5 \n + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * complex(real(float), imag(float)). + */ + class DTV_API dvbt_demod_reference_signals : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_demod_reference_signals> sptr; + + /*! + * \brief Create Reference signals demodulator. + * + * \param itemsize size of an in/out item. \n + * \param ninput input stream length. \n + * \param noutput output stream length. \n + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param code_rate_HP high priority stream code rate. \n + * \param code_rate_LP low priority stream code rate. \n + * \param guard_interval guard interval used. \n + * \param transmission_mode transmission mode used. \n + * \param include_cell_id include or not Cell ID. \n + * \param cell_id value of the Cell ID. + */ + static sptr make(int itemsize, int ninput, int noutput, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \ + dvb_guardinterval_t guard_interval, dvbt_transmission_mode_t transmission_mode, \ + int include_cell_id, int cell_id); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h b/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h new file mode 100644 index 0000000000..6d50da1535 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_energy_descramble.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_ENERGY_DESCRAMBLE_H +#define INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Energy descramble + * \ingroup dtv + * + * ETSI EN 300 744 - Clause 4.3.1. \n + * Input - Randomized MPEG-2 transport packets. \n + * Output - MPEG-2 transport packets (including sync - 0x47). \n + * We assume the first byte is a NSYNC. \n + * First sync in a row of 8 packets is reversed - 0xB8. \n + * Block size is 188 bytes + */ + class DTV_API dvbt_energy_descramble : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_energy_descramble> sptr; + + /*! + * \brief Create DVB-T Energy descramble. + * + * \param nblocks number of blocks. + */ + static sptr make(int nblocks); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_map.h b/gr-dtv/include/gnuradio/dtv/dvbt_map.h index d9b7976b31..5bd8f433f9 100644 --- a/gr-dtv/include/gnuradio/dtv/dvbt_map.h +++ b/gr-dtv/include/gnuradio/dtv/dvbt_map.h @@ -18,8 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_DVBT_DVBT_MAP_H -#define INCLUDED_DVBT_DVBT_MAP_H +#ifndef INCLUDED_DTV_DVBT_MAP_H +#define INCLUDED_DTV_DVBT_MAP_H #include <gnuradio/dtv/api.h> #include <gnuradio/dtv/dvb_config.h> diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h b/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h new file mode 100644 index 0000000000..ced054dc22 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_ofdm_sym_acquisition.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_OFDM_SYM_ACQUISITION_H +#define INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief OFDM symbol acquisition. + * \ingroup dtv + * + * Data input format: \n + * complex(real(float), imag(float)). \n + * Data output format: \n + * complex(real(float), imag(float)). + */ + class DTV_API dvbt_ofdm_sym_acquisition : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_ofdm_sym_acquisition> sptr; + + /*! + * \brief Create OFDM symbol acquisition. + * + * \param blocks Always equal to 1.\n + * \param fft_length FFT size, 2048 or 8192. \n + * \param occupied_tones Active OFDM carriers, 1705 or 6817. \n + * \param cp_length Length of Cyclic Prefix (FFT size / 32, 16, 8 or 4). \n + * \param snr Initial Signal to Noise Ratio. + */ + static sptr make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h new file mode 100644 index 0000000000..5ef8e04443 --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_dec.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_REED_SOLOMON_DEC_H +#define INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> + +namespace gr { + namespace dtv { + + /*! + * \brief Reed Solomon decoder. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.2 \n + * RS(N=204,K=239,T=8). + */ + class DTV_API dvbt_reed_solomon_dec : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_reed_solomon_dec> sptr; + + /*! + * \brief Create a Reed Solomon decoder. + * + * \param p characteristic of GF(p^m). + * \param m we use GF(p^m). + * \param gfpoly Generator Polynomial. + * \param n length of codeword of RS coder. + * \param k length of information sequence of RS decoder. + * \param t number of corrected errors. + * \param s shortened length. + * \param blocks number of blocks to process at once. + */ + static sptr make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_H */ + diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h b/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h new file mode 100644 index 0000000000..b44ec4f44a --- /dev/null +++ b/gr-dtv/include/gnuradio/dtv/dvbt_viterbi_decoder.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_VITERBI_DECODER_H +#define INCLUDED_DTV_DVBT_VITERBI_DECODER_H + +#include <gnuradio/dtv/api.h> +#include <gnuradio/block.h> +#include <gnuradio/dtv/dvb_config.h> +#include <gnuradio/dtv/dvbt_config.h> + +namespace gr { + namespace dtv { + + /*! + * \brief DVB-T Viterbi decoder. + * \ingroup dtv + * + * ETSI EN 300 744 Clause 4.3.3 \n + * Mother convolutional code with rate 1/2. \n + * k=1, n=2, K=6. \n + * Generator polynomial G1=171(OCT), G2=133(OCT). \n + * Punctured to obtain rates of 2/3, 3/4, 5/6, 7/8. \n + * Data Input format: \n + * 000000X0X1 - QPSK. \n + * 0000X0X1X2X3 - 16QAM. \n + * 00X0X1X2X3X4X5 - 64QAM. \n + * Data Output format: Packed bytes (each bit is data). \n + * MSB - first, LSB last. + */ + class DTV_API dvbt_viterbi_decoder : virtual public block + { + public: + typedef boost::shared_ptr<dvbt_viterbi_decoder> sptr; + + /*! + * \brief Create a DVB-T Viterbi decoder. + * + * \param constellation constellation used. \n + * \param hierarchy hierarchy used. \n + * \param coderate coderate used. \n + * \param bsize block size. + */ + static sptr make(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_VITERBI_DECODER_H */ + diff --git a/gr-dtv/lib/CMakeLists.txt b/gr-dtv/lib/CMakeLists.txt index f2128e9a83..f0444692f4 100644 --- a/gr-dtv/lib/CMakeLists.txt +++ b/gr-dtv/lib/CMakeLists.txt @@ -104,6 +104,14 @@ list(APPEND dtv_sources dvbt/dvbt_symbol_inner_interleaver_impl.cc dvbt/dvbt_map_impl.cc dvbt/dvbt_reference_signals_impl.cc + dvbt/dvbt_ofdm_sym_acquisition_impl.cc + dvbt/dvbt_demod_reference_signals_impl.cc + dvbt/dvbt_demap_impl.cc + dvbt/dvbt_bit_inner_deinterleaver_impl.cc + dvbt/dvbt_viterbi_decoder_impl.cc + dvbt/dvbt_convolutional_deinterleaver_impl.cc + dvbt/dvbt_reed_solomon_dec_impl.cc + dvbt/dvbt_energy_descramble_impl.cc ) if(ENABLE_GR_CTRLPORT) @@ -119,6 +127,8 @@ list(APPEND dtv_libs ${VOLK_LIBRARIES} ) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2") + #Add Windows DLL resource file if using MSVC if(MSVC) include(${CMAKE_SOURCE_DIR}/cmake/Modules/GrVersion.cmake) diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc new file mode 100644 index 0000000000..bf7613adae --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.cc @@ -0,0 +1,191 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_bit_inner_deinterleaver_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + const int dvbt_bit_inner_deinterleaver_impl::d_bsize = 126; + + int + dvbt_bit_inner_deinterleaver_impl::H(int e, int w) + { + int rez = 0; + + switch (e) { + case 0: + rez = w; + break; + case 1: + rez = (w + 63) % d_bsize; + break; + case 2: + rez = (w + 105) % d_bsize; + break; + case 3: + rez = (w + 42) % d_bsize; + break; + case 4: + rez = (w + 21) % d_bsize; + break; + case 5: + rez = (w + 84) % d_bsize; + break; + default: + break; + } + + return rez; + } + + dvbt_bit_inner_deinterleaver::sptr + dvbt_bit_inner_deinterleaver::make(int nsize, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission) + { + return gnuradio::get_initial_sptr + (new dvbt_bit_inner_deinterleaver_impl(nsize, constellation, hierarchy, transmission)); + } + + /* + * The private constructor + */ + dvbt_bit_inner_deinterleaver_impl::dvbt_bit_inner_deinterleaver_impl(int nsize, dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission) + : block("dvbt_bit_inner_deinterleaver", + io_signature::make(1, 1, sizeof (unsigned char) * nsize), + io_signature::make(1, 2, sizeof (unsigned char) * nsize)), + config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission), + d_nsize(nsize), + d_hierarchy(hierarchy) + { + d_v = config.d_m; + d_hierarchy = config.d_hierarchy; + + d_perm = (unsigned char *)new unsigned char[d_v * d_bsize]; + if (d_perm == NULL) { + std::cout << "Cannot allocate memory for d_perm" << std::endl; + exit(1); + } + + //Init permutation table (used for b[e][do]) + for (int i = 0; i < d_bsize * d_v; i++) { + if (d_hierarchy == NH) { + d_perm[i] = ((i % d_v) / (d_v / 2)) + 2 * (i % (d_v / 2)); + } + else { + d_perm[i] = (i % (d_v - 2)) / ((d_v - 2) / 2) + 2 * (i % ((d_v - 2) / 2)) + 2; + } + } + + if (d_nsize % d_bsize) { + std::cout << "Error: Input size must be multiple of block size: " \ + << "nsize: " << d_nsize << "bsize: " << d_bsize << std::endl; + } + } + + /* + * Our virtual destructor. + */ + dvbt_bit_inner_deinterleaver_impl::~dvbt_bit_inner_deinterleaver_impl() + { + delete [] d_perm; + } + + void + dvbt_bit_inner_deinterleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_bit_inner_deinterleaver_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 unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *outh = (unsigned char *) output_items[0]; + unsigned char *outl = (unsigned char *) output_items[1]; + + int bmax = noutput_items * d_nsize / d_bsize; + + // First index of d_b is Bit interleaver number + // Second index of d_b is the position inside Bit interleaver + unsigned char d_b[d_v][d_bsize]; + + for (int bcount = 0; bcount < bmax; bcount++) { + for (int w = 0; w < d_bsize; w++) { + int c = in[(bcount * d_bsize) + w]; + + for (int e = 0; e < d_v; e++) { + d_b[e][H(e, w)] = (c >> (d_v - e - 1)) & 1; + } + } + + for (int i = 0; i < d_bsize; i++) { + if (d_hierarchy == NH) { + // Create output from demultiplexer + int c = 0; + + for (int k = 0; k < d_v; k++) { + c = (c << 1) | d_b[d_perm[(d_v * i) + k]][i]; + } + + outh[(bcount * d_bsize) + i] = c; + } + else { + int c = 0; + + // High priority output - first 2 streams + for (int k = 0; k < 2; k++) { + c = (c << 1) | d_b[(d_v * i + k) % 2][(d_v * i + k) / 2]; + } + + outh[(bcount * d_bsize) + i] = c; + + c = 0; + // Low priority output - (v - 2) streams + for (int k = 2; k < (d_v - 2); k++) { + c = (c << 1) | d_b[d_perm[d_v * i + k]][(d_v * i + k) / (d_v - 2)]; + } + + outl[(bcount * d_bsize) + i] = c; + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h new file mode 100644 index 0000000000..9f3811301d --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_deinterleaver_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H +#define INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H + +#include <gnuradio/dtv/dvbt_bit_inner_deinterleaver.h> +#include "dvbt_configure.h" + +namespace gr { + namespace dtv { + + class dvbt_bit_inner_deinterleaver_impl : public dvbt_bit_inner_deinterleaver + { + private: + const dvbt_configure config; + + int d_nsize; + dvbt_hierarchy_t d_hierarchy; + + // constellation + int d_v; + // Bit interleaver block size + static const int d_bsize; + + // Table to keep interleaved indices + unsigned char * d_perm; + + // Permutation function + int H(int e, int w); + + public: + dvbt_bit_inner_deinterleaver_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission); + ~dvbt_bit_inner_deinterleaver_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_BIT_INNER_DEINTERLEVER_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc new file mode 100644 index 0000000000..0358ada1ff --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.cc @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_convolutional_deinterleaver_impl.h" + +namespace gr { + namespace dtv { + + const int dvbt_convolutional_deinterleaver_impl::d_SYNC = 0x47; + const int dvbt_convolutional_deinterleaver_impl::d_NSYNC = 0xB8; + const int dvbt_convolutional_deinterleaver_impl::d_MUX_PKT = 8; + + dvbt_convolutional_deinterleaver::sptr + dvbt_convolutional_deinterleaver::make(int nsize, int I, int M) + { + return gnuradio::get_initial_sptr + (new dvbt_convolutional_deinterleaver_impl(nsize, I, M)); + } + + /* + * The private constructor + */ + dvbt_convolutional_deinterleaver_impl::dvbt_convolutional_deinterleaver_impl(int blocks, int I, int M) + : block("dvbt_convolutional_deinterleaver", + io_signature::make(1, 1, sizeof (unsigned char)), + io_signature::make(1, 1, sizeof (unsigned char) * I * blocks)), + d_blocks(blocks), d_I(I), d_M(M) + { + set_relative_rate(1.0 / d_I * d_blocks); + set_output_multiple(2); + //The positions are shift registers (FIFOs) + //of length i*M + for (int i = (d_I - 1); i >= 0; i--) { + d_shift.push_back(new std::deque<unsigned char>(d_M * i, 0)); + } + + // There are 8 mux packets + assert(d_blocks / d_M == d_MUX_PKT); + } + + /* + * Our virtual destructor. + */ + dvbt_convolutional_deinterleaver_impl::~dvbt_convolutional_deinterleaver_impl() + { + for (unsigned int i = 0; i < d_shift.size(); i++) { + delete d_shift.back(); + d_shift.pop_back(); + } + } + + void + dvbt_convolutional_deinterleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size (); + + for (int i = 0; i < ninputs; i++) { + ninput_items_required[i] = noutput_items * d_I * d_blocks; + } + } + + + int + dvbt_convolutional_deinterleaver_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 unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int to_out = noutput_items; + + /* + * Look for a tag that signals superframe_start and consume all input items + * that are in input buffer so far. + * This will actually reset the convolutional deinterleaver + */ + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + (noutput_items * d_I * d_blocks), pmt::string_to_symbol("superframe_start")); + + if (tags.size()) { + if (tags[0].offset - nread) { + consume_each(tags[0].offset - nread); + return (0); + } + } + + /* + * At this moment the first item in input buffer should be NSYNC or SYNC + */ + + for (int count = 0, i = 0; i < to_out; i++) { + for (int mux_pkt = 0; mux_pkt < d_MUX_PKT; mux_pkt++) { + // This is actually the deinterleaver + for (int k = 0; k < (d_M * d_I); k++) { + d_shift[k % d_I]->push_back(in[count]); + out[count++] = d_shift[k % d_I]->front(); + d_shift[k % d_I]->pop_front(); + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each(d_I * d_blocks * to_out); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h new file mode 100644 index 0000000000..7b3fafecad --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_convolutional_deinterleaver_impl.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H +#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H + +#include <gnuradio/dtv/dvbt_convolutional_deinterleaver.h> + +namespace gr { + namespace dtv { + + class dvbt_convolutional_deinterleaver_impl : public dvbt_convolutional_deinterleaver + { + private: + static const int d_SYNC; + static const int d_NSYNC; + static const int d_MUX_PKT; + + int d_blocks; + int d_I; + int d_M; + std::vector< std::deque<unsigned char> * > d_shift; + + public: + dvbt_convolutional_deinterleaver_impl(int nsize, int I, int M); + ~dvbt_convolutional_deinterleaver_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_DEINTERLEAVER_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demap_impl.cc b/gr-dtv/lib/dvbt/dvbt_demap_impl.cc new file mode 100644 index 0000000000..4bdec1dc96 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demap_impl.cc @@ -0,0 +1,185 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_demap_impl.h" +#include <volk/volk.h> +#include <stdio.h> + +namespace gr { + namespace dtv { + + dvbt_demap::sptr + dvbt_demap::make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvbt_transmission_mode_t transmission, float gain) + { + return gnuradio::get_initial_sptr + (new dvbt_demap_impl(nsize, constellation, hierarchy, transmission, gain)); + } + + /* + * The private constructor + */ + dvbt_demap_impl::dvbt_demap_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvbt_transmission_mode_t transmission, float gain) + : block("dvbt_demap", + io_signature::make(1, 1, sizeof (gr_complex) * nsize), + io_signature::make(1, 1, sizeof (unsigned char) * nsize)), + config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission), + d_nsize(nsize), + d_constellation_size(0), + d_step(0), + d_alpha(0), + d_gain(0.0) + { + //Get parameters from config object + d_constellation_size = config.d_constellation_size; + d_transmission_mode = config.d_transmission_mode; + d_step = config.d_step; + d_alpha = config.d_alpha; + d_gain = gain * config.d_norm; + + d_constellation_points = (gr_complex*) volk_malloc(sizeof(gr_complex) * d_constellation_size, volk_get_alignment()); + if (d_constellation_points == NULL) { + std::cout << "cannot allocate memory for d_constellation_points" << std::endl; + exit(1); + } + + d_sq_dist = (float*) volk_malloc(sizeof(float) * d_constellation_size, volk_get_alignment()); + if (d_sq_dist == NULL) { + std::cout << "cannot allocate memory for d_sq_dist" << std::endl; + volk_free(d_constellation_points); + exit(1); + } + + make_constellation_points(d_constellation_size, d_step, d_alpha); + } + + /* + * Our virtual destructor. + */ + dvbt_demap_impl::~dvbt_demap_impl() + { + volk_free(d_sq_dist); + volk_free(d_constellation_points); + } + + void + dvbt_demap_impl::make_constellation_points(int size, int step, int alpha) + { + // The symmetry of the constellation is used to calculate + // 16QAM from QPSK and 64QAM from 16QAM + + int bits_per_axis = log2(size) / 2; + int steps_per_axis = sqrt(size) / 2 - 1; + + for (int i = 0; i < size; i++) { + // This is the quadrant made of the first two bits starting from MSB + int q = i >> (2 * (bits_per_axis - 1)) & 3; + // Sign for correct calculation of I and Q in each quadrant + int sign0 = (q >> 1) ? -1 : 1; int sign1 = (q & 1) ? -1 : 1; + + int x = (i >> (bits_per_axis - 1)) & ((1 << (bits_per_axis - 1)) - 1); + int y = i & ((1 << (bits_per_axis - 1)) - 1); + + int xval = alpha + (steps_per_axis - x) * step; + int yval = alpha + (steps_per_axis - y) * step; + + int val = (bin_to_gray(x) << (bits_per_axis - 1)) + bin_to_gray(y); + + // ETSI EN 300 744 Clause 4.3.5 + // Actually the constellation is gray coded + // but the bits on each axis are not taken in consecutive order + // So we need to convert from b0b2b4b1b3b5->b0b1b2b3b4b5(64QAM) + + x = 0; y = 0; + + for (int j = 0; j < (bits_per_axis - 1); j++) { + x += ((val >> (1 + 2 * j)) & 1) << j; + y += ((val >> (2 * j)) & 1) << j; + } + + val = (q << 2 * (bits_per_axis - 1)) + (x << (bits_per_axis - 1)) + y; + + // Keep corresponding symbol bits->complex symbol in one vector + // Normalize the signal using gain + d_constellation_points[val] = d_gain * gr_complex(sign0 * xval, sign1 * yval); + } + } + + int + dvbt_demap_impl::find_constellation_value(gr_complex val) + { + float min_dist = std::norm(val - d_constellation_points[0]); + int min_index = 0; + + volk_32fc_x2_square_dist_32f(&d_sq_dist[0], &val, &d_constellation_points[0], d_constellation_size); + + for (int i = 0; i < d_constellation_size; i++) { + if (d_sq_dist[i] < min_dist) { + min_dist = d_sq_dist[i]; + min_index = i; + } + } + + //return d_constellation_bits[min_index]; + return min_index; + } + + int + dvbt_demap_impl::bin_to_gray(int val) + { + return (val >> 1) ^ val; + } + + void + dvbt_demap_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_demap_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 gr_complex *in = (const gr_complex *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // TODO - use DFE (Decision Feedback Equalizer) + + for (int i = 0; i < (noutput_items * d_nsize); i++) { + out[i] = find_constellation_value(in[i]); + } + + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demap_impl.h b/gr-dtv/lib/dvbt/dvbt_demap_impl.h new file mode 100644 index 0000000000..020578b1b5 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demap_impl.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_DVBT_DEMAP_IMPL_H +#define INCLUDED_DTV_DVBT_DVBT_DEMAP_IMPL_H + +#include <gnuradio/dtv/dvbt_demap.h> +#include "dvbt_configure.h" + +namespace gr { + namespace dtv { + + class dvbt_demap_impl : public dvbt_demap + { + private: + const dvbt_configure config; + + int d_nsize; + + //Constellation size + unsigned char d_constellation_size; + //Transmission mode + dvbt_transmission_mode_t d_transmission_mode; + //Step on each axis of the constellation + unsigned char d_step; + //Keep Alpha internally + unsigned char d_alpha; + //Gain for the complex values + float d_gain; + + gr_complex * d_constellation_points; + float * d_sq_dist; + + void make_constellation_points(int size, int step, int alpha); + int find_constellation_value(gr_complex val); + int bin_to_gray(int val); + + public: + dvbt_demap_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain); + ~dvbt_demap_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DVBT_DEMAP_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc new file mode 100644 index 0000000000..e9ee86436b --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.cc @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_demod_reference_signals_impl.h" + +namespace gr { + namespace dtv { + + dvbt_demod_reference_signals::sptr + dvbt_demod_reference_signals::make(int itemsize, int ninput, int noutput, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \ + dvb_guardinterval_t guard_interval, dvbt_transmission_mode_t transmission_mode, \ + int include_cell_id, int cell_id) + { + return gnuradio::get_initial_sptr + (new dvbt_demod_reference_signals_impl(itemsize, ninput, \ + noutput, constellation, hierarchy, code_rate_HP, code_rate_LP, \ + guard_interval, transmission_mode, include_cell_id, cell_id)); + } + + /* + * The private constructor + */ + dvbt_demod_reference_signals_impl::dvbt_demod_reference_signals_impl(int itemsize, int ninput, int noutput, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvb_code_rate_t code_rate_HP,\ + dvb_code_rate_t code_rate_LP, dvb_guardinterval_t guard_interval,\ + dvbt_transmission_mode_t transmission_mode, int include_cell_id, int cell_id) + : block("dvbt_demod_reference_signals", + io_signature::make(1, 1, itemsize * ninput), + io_signature::make(1, 1, itemsize * noutput)), + config(constellation, hierarchy, code_rate_HP, code_rate_LP, \ + guard_interval, transmission_mode, include_cell_id, cell_id), + d_pg(config), + d_init(0), + d_fi_start(0) + { + d_ninput = ninput; + d_noutput = noutput; + + // TODO - investigate why this is happening + if ((config.d_constellation == MOD_64QAM) && (config.d_transmission_mode == T8k)) + d_fi_start = 2; + else + d_fi_start = 3; + } + + /* + * Our virtual destructor. + */ + dvbt_demod_reference_signals_impl::~dvbt_demod_reference_signals_impl() + { + } + + void + dvbt_demod_reference_signals_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size(); + + for (int i = 0; i < ninputs; i++) + ninput_items_required[i] = 2 * noutput_items; + } + + int + dvbt_demod_reference_signals_impl::is_sync_start(int nitems) + { + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + nitems, pmt::string_to_symbol("sync_start")); + + return tags.size() ? 1 : 0; + } + + int + dvbt_demod_reference_signals_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 gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int symbol_index, frame_index; + int to_out = 0; + + for (int i = 0; i < noutput_items; i++) { + to_out += d_pg.parse_input(&in[i * d_ninput], &out[i * d_noutput], &symbol_index, &frame_index); + } + + /* + * Wait for a sync_start tag from upstream that signals when to start. + * Allways consume until to a superframe start. + */ + if (is_sync_start(noutput_items)) { + d_init = 0; + } + + if (d_init == 0) { + // This is super-frame start + if (((symbol_index % 68) == 0) && ((frame_index % 4) == d_fi_start)) { + d_init = 1; + + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("superframe_start"); + pmt::pmt_t value = pmt::from_long(0xaa); + this->add_item_tag(0, offset, key, value); + } + else { + consume_each(1); + return (0); + } + } + + // Send a tag for each OFDM symbol informing about + // symbol index. + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("symbol_index"); + pmt::pmt_t value = pmt::from_long(symbol_index); + this->add_item_tag(0, offset, key, value); + + // Consume from input stream + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return to_out; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h new file mode 100644 index 0000000000..1c7f5fde30 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_demod_reference_signals_impl.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H +#define INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H + +#include <gnuradio/dtv/dvbt_demod_reference_signals.h> +#include "dvbt_reference_signals_impl.h" + +namespace gr { + namespace dtv { + + class dvbt_demod_reference_signals_impl : public dvbt_demod_reference_signals + { + // configuration object for this class + const dvbt_configure config; + + private: + // Pilot Generator object + dvbt_pilot_gen d_pg; + + //In and Out data length + int d_ninput; + int d_noutput; + + int d_init; + int d_fi_start; + + int is_sync_start(int nitems); + + public: + dvbt_demod_reference_signals_impl(int itemsize, int ninput, int noutput, \ + dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \ + dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \ + dvb_guardinterval_t guard_interval, \ + dvbt_transmission_mode_t transmission_mode = gr::dtv::T2k, int include_cell_id = 0, int cell_id = 0); + ~dvbt_demod_reference_signals_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_DEMOD_REFERENCE_SIGNALS_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc new file mode 100644 index 0000000000..6b47814f8c --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.cc @@ -0,0 +1,156 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_energy_descramble_impl.h" + +namespace gr { + namespace dtv { + + const int dvbt_energy_descramble_impl::d_nblocks = 8; + const int dvbt_energy_descramble_impl::d_bsize = 188; + const int dvbt_energy_descramble_impl::d_SYNC = 0x47; + const int dvbt_energy_descramble_impl::d_NSYNC = 0xB8; + const int dvbt_energy_descramble_impl::d_MUX_PKT = 8; + + void + dvbt_energy_descramble_impl::init_prbs() + { + d_reg = 0xa9; + } + + int + dvbt_energy_descramble_impl::clock_prbs(int clocks) + { + int res = 0; + int feedback = 0; + + for(int i = 0; i < clocks; i++) { + feedback = ((d_reg >> (14 - 1)) ^ (d_reg >> (15 - 1))) & 0x1; + d_reg = ((d_reg << 1) | feedback) & 0x7fff; + + res = (res << 1) | feedback; + } + + return res; + } + + dvbt_energy_descramble::sptr + dvbt_energy_descramble::make(int nblocks) + { + return gnuradio::get_initial_sptr + (new dvbt_energy_descramble_impl(nblocks)); + } + + /* + * The private constructor + */ + dvbt_energy_descramble_impl::dvbt_energy_descramble_impl(int nblocks) + : block("dvbt_energy_descramble", + io_signature::make(1, 1, sizeof (unsigned char) * d_nblocks * d_bsize), + io_signature::make(1, 1, sizeof (unsigned char))), + d_reg(0xa9), d_index(0), d_search(0) + { + set_relative_rate((double) (d_nblocks * d_bsize)); + + // Set output multiple of (2 search + 1 data = 3) at least (4 for now) + set_output_multiple(4 * d_nblocks * d_bsize); + + // Search interval for NSYNC is 2 * 8 * MUX size + d_search = 2 * (d_nblocks * d_bsize); + } + + /* + * Our virtual destructor. + */ + dvbt_energy_descramble_impl::~dvbt_energy_descramble_impl() + { + } + + void + dvbt_energy_descramble_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = 4 * (noutput_items / (d_nblocks * d_bsize)); + } + + int + dvbt_energy_descramble_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 unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + int to_consume, to_out; + + // Search for a NSYNC + while ((in[d_index] != d_NSYNC) && (d_index < d_search)) { + d_index += d_bsize; + } + + /* + * If we did not find a NSYNC then just consume + * and return 0. + */ + if (d_index >= d_search) { + d_index = 0; + to_consume = 2; + to_out = 0; + } + else { + // We found a NSYNC, descramble the data + + to_consume = (noutput_items / (d_nblocks * d_bsize)) - 2; + to_out = noutput_items - 2 * (d_nblocks * d_bsize); + + for (int count = 0, i = 0; i < to_consume; i++) { + init_prbs(); + + for (int mux_pkt = 0; mux_pkt < d_MUX_PKT; mux_pkt++) { + out[count++] = d_SYNC; + // PRBS clocking starts right after NSYNC + + for (int k = 1; k < d_bsize; k++) { + out[count] = in[d_index + count] ^ clock_prbs(d_nblocks); + count++; + } + + // For subsequent blocks PRBS is clocked also on SYNC + // but its output is not used + clock_prbs(d_nblocks); + } + } + } + + // Tell runtime how many input items we consumed + consume_each(to_consume); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h new file mode 100644 index 0000000000..8681732016 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_energy_descramble_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H +#define INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H + +#include <gnuradio/dtv/dvbt_energy_descramble.h> + +namespace gr { + namespace dtv { + + class dvbt_energy_descramble_impl : public dvbt_energy_descramble + { + private: + static const int d_nblocks; + static const int d_bsize; + static const int d_SYNC; + static const int d_NSYNC; + static const int d_MUX_PKT; + + // Register for PRBS + int d_reg; + + // Index + int d_index; + // Search interval + int d_search; + + void init_prbs(); + int clock_prbs(int clocks); + + public: + dvbt_energy_descramble_impl(int nblocks); + ~dvbt_energy_descramble_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_ENERGY_DESCRAMBLE_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc new file mode 100644 index 0000000000..2383c54fbc --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc @@ -0,0 +1,417 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_ofdm_sym_acquisition_impl.h" +#include <complex> +#include <gnuradio/math.h> +#include <gnuradio/expj.h> +#include <stdio.h> +#include <volk/volk.h> + +namespace gr { + namespace dtv { + + int + dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha) + { + d_avg_alpha = alpha; + d_threshold_factor_rise = threshold_factor_rise; + d_threshold_factor_fall = threshold_factor_fall; + d_avg = 0; + + return (0); + } + + int + dvbt_ofdm_sym_acquisition_impl::peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max) + { + int state = 0; + float peak_val = -(float)INFINITY; int peak_index = 0; int peak_pos_length = 0; + + int i = 0; + + while(i < datain_length) { + if (state == 0) { + if (datain[i] > d_avg * d_threshold_factor_rise) { + state = 1; + } + else { + d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + } + else if (state == 1) { + if (datain[i] > peak_val) { + peak_val = datain[i]; + peak_index = i; + d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + else if (datain[i] > d_avg * d_threshold_factor_fall) { + d_avg = (d_avg_alpha) * datain[i] + (1 - d_avg_alpha) * d_avg; + i++; + } + else { + peak_pos[peak_pos_length] = peak_index; + peak_pos_length++; + state = 0; + peak_val = - (float)INFINITY; + } + } + } + + // Find peak of peaks + if (peak_pos_length) { + float max = datain[peak_pos[0]]; + int maxi = 0; + + for (int i = 1; i < peak_pos_length; i++) { + if (datain[peak_pos[i]] > max) { + max = datain[peak_pos[i]]; + maxi = i; + } + } + + *peak_max = maxi; + } + + return (peak_pos_length); + } + + int + dvbt_ofdm_sym_acquisition_impl::ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out) + { + assert(lookup_start >= lookup_stop); + assert(lookup_stop >= (d_cp_length + d_fft_length - 1)); + + int low, size; + + // Array to store peak positions + int peak_pos[d_fft_length]; + float d_phi[d_fft_length]; + + // Calculate norm + low = lookup_stop - (d_cp_length + d_fft_length - 1); + size = lookup_start - (lookup_stop - (d_cp_length + d_fft_length - 1)) + 1; + + volk_32fc_magnitude_squared_32f(&d_norm[low], &in[low], size); + + // Calculate gamma on each point +#ifdef SEGFAULT_FIX + low = lookup_stop - d_cp_length + 1; + size = lookup_start - (lookup_stop - d_cp_length + 1) + 1; +#else + low = lookup_stop - d_cp_length - 1; + size = lookup_start - (lookup_stop - d_cp_length - 1) + 1; +#endif + volk_32fc_x2_multiply_conjugate_32fc(&d_corr[low - d_fft_length], &in[low], &in[low - d_fft_length], size); + + // Calculate time delay and frequency correction + // This looks like spaghetti code but it is fast + for (int i = lookup_start - 1; i >= lookup_stop; i--) { + int k = i - lookup_stop; + + d_phi[k] = 0.0; + d_gamma[k] = 0.0; + + // Moving sum for calculating gamma and phi + for (int j = 0; j < d_cp_length; j++) { + // Calculate gamma and store it + d_gamma[k] += d_corr[i - j - d_fft_length]; + // Calculate phi and store it + d_phi[k] += d_norm[i - j] + d_norm[i - j - d_fft_length]; + } + } + + // Init lambda with gamma + low = 0; + size = lookup_start - lookup_stop; + + volk_32fc_magnitude_32f(&d_lambda[low], &d_gamma[low], size); + + // Calculate lambda + low = 0; + size = lookup_start - lookup_stop; + + volk_32f_s32f_multiply_32f(&d_phi[low], &d_phi[low], d_rho / 2.0, size); + volk_32f_x2_subtract_32f(&d_lambda[low], &d_lambda[low], &d_phi[low], size); + + int peak_length, peak, peak_max; + // Find peaks of lambda + // We have found an end of symbol at peak_pos[0] + CP + FFT + if ((peak_length = peak_detect_process(&d_lambda[0], (lookup_start - lookup_stop), &peak_pos[0], &peak_max))) { + peak = peak_pos[peak_max] + lookup_stop; + *cp_pos = peak; + + // Calculate frequency correction + float peak_epsilon = fast_atan2f(d_gamma[peak_pos[peak_max]]); + double sensitivity = (double)(-1) / (double)d_fft_length; + + // Store phases for derotating the signal + // We always process CP len + FFT len + for (int i = 0; i < (d_cp_length + d_fft_length); i++) { + if (i == d_nextpos) { + d_phaseinc = d_nextphaseinc; + } + + // We are interested only in fft_length + d_phase += d_phaseinc; + + while (d_phase > (float)M_PI) { + d_phase -= (float)(2.0 * M_PI); + } + while (d_phase < (float)(-M_PI)) { + d_phase += (float)(2.0 * M_PI); + } + + derot[i] = gr_expj(d_phase); + } + + d_nextphaseinc = sensitivity * peak_epsilon; + d_nextpos = peak - (d_cp_length + d_fft_length); + + *to_consume = d_cp_length + d_fft_length; + *to_out = 1; + } + else { + for (int i = 0; i < (d_cp_length + d_fft_length); i++) { + d_phase += d_phaseinc; + + while (d_phase > (float)M_PI) { + d_phase -= (float)(2.0 * M_PI); + } + while (d_phase < (float)(-M_PI)) { + d_phase += (float)(2.0 * M_PI); + } + } + + // We consume only fft_length + *to_consume = d_cp_length + d_fft_length; + *to_out = 0; + } + + return (peak_length); + } + + void + dvbt_ofdm_sym_acquisition_impl::send_sync_start() + { + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("sync_start"); + pmt::pmt_t value = pmt::from_long(1); + this->add_item_tag(0, offset, key, value); + } + + dvbt_ofdm_sym_acquisition::sptr + dvbt_ofdm_sym_acquisition::make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr) + { + return gnuradio::get_initial_sptr + (new dvbt_ofdm_sym_acquisition_impl(blocks, fft_length, occupied_tones, cp_length, snr)); + } + + /* + * The private constructor + */ + dvbt_ofdm_sym_acquisition_impl::dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr) + : block("dvbt_ofdm_sym_acquisition", + io_signature::make(1, 1, sizeof (gr_complex) * blocks), + io_signature::make(1, 1, sizeof (gr_complex) * blocks * fft_length)), + d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr), + d_index(0), d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_count(0), d_nextphaseinc(0), d_nextpos(0), \ + d_sym_acq_count(0),d_sym_acq_timeout(100), d_initial_acquisition(0), \ + d_freq_correction_count(0), d_freq_correction_timeout(0) + { + set_relative_rate(1.0 / (double) (d_cp_length + d_fft_length)); + + d_snr = pow(10, d_snr / 10.0); + d_rho = d_snr / (d_snr + 1.0); + + d_gamma = (gr_complex*) volk_malloc(sizeof(gr_complex) * d_fft_length, volk_get_alignment()); + if (d_gamma == NULL) { + std::cout << "cannot allocate memory for d_gamma" << std::endl; + exit(1); + } + + d_lambda = (float*) volk_malloc(sizeof(float) * d_fft_length, volk_get_alignment()); + if (d_lambda == NULL) { + std::cout << "cannot allocate memory for d_lambda" << std::endl; + volk_free(d_gamma); + exit(1); + } + + d_derot = (gr_complex*) volk_malloc(sizeof(gr_complex) * (d_fft_length + d_cp_length), volk_get_alignment()); + if (d_derot == NULL) { + std::cout << "cannot allocate memory for d_derot" << std::endl; + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_conj = (gr_complex*) volk_malloc(sizeof(gr_complex) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_conj == NULL) { + std::cout << "cannot allocate memory for d_conj" << std::endl; + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_norm = (float*) volk_malloc(sizeof(float) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_norm == NULL) { + std::cout << "cannot allocate memory for d_norm" << std::endl; + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + d_corr = (gr_complex*) volk_malloc(sizeof(gr_complex) * (2 * d_fft_length + d_cp_length), volk_get_alignment()); + if (d_corr == NULL) { + std::cout << "cannot allocate memory for d_corr" << std::endl; + volk_free(d_norm); + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + exit(1); + } + + peak_detect_init(0.8, 0.9, 30, 0.9); + } + + /* + * Our virtual destructor. + */ + dvbt_ofdm_sym_acquisition_impl::~dvbt_ofdm_sym_acquisition_impl() + { + volk_free(d_corr); + volk_free(d_norm); + volk_free(d_conj); + volk_free(d_derot); + volk_free(d_lambda); + volk_free(d_gamma); + } + + void + dvbt_ofdm_sym_acquisition_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int ninputs = ninput_items_required.size(); + + // make sure we receive at least (symbol_length + fft_length) + for (int i = 0; i < ninputs; i++) { + ninput_items_required[i] = (2 * d_fft_length + d_cp_length) * noutput_items; + } + } + + /* + * ML Estimation of Time and Frequency Offset in OFDM systems + * Jan-Jaap van de Beek + */ + + int + dvbt_ofdm_sym_acquisition_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 gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int low, size; + + // This is initial acquisition of symbol start + // TODO - make a FSM + if (!d_initial_acquisition) { + d_initial_acquisition = ml_sync(in, 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); + +#ifdef SEGFAULT_FIX + d_cp_start_initial = d_cp_start; + d_cp_start_slip = 0; +#endif + // Send sync_start downstream + send_sync_start(); + } + + // This is fractional frequency correction (pre FFT) + // It is also called coarse frequency correction + if (d_initial_acquisition) { +#ifdef SEGFAULT_FIX + d_cp_found = ml_sync(in, d_cp_start + 16, d_cp_start, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); +#else + d_cp_found = ml_sync(in, d_cp_start + 8, d_cp_start - 8, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); +#endif + + if (d_cp_found) { + d_freq_correction_count = 0; + +#ifdef SEGFAULT_FIX + // detect and ignore false peaks + if (d_cp_start != d_cp_start_initial) { + d_cp_start_slip++; + if (d_cp_start_slip == 2) { + d_cp_start_slip = 0; + } + else { + d_cp_start = d_cp_start_initial; + } + } + else { + d_cp_start_slip = 0; + } +#endif + + // Derotate the signal and out + low = d_cp_start - d_fft_length + 1; + size = d_cp_start - (d_cp_start - d_fft_length + 1) + 1; + + volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[low], size); + } + else { + // If we have a number of consecutive misses then we restart acquisition + if (++d_freq_correction_count > d_freq_correction_timeout) { + d_initial_acquisition = 0; + d_freq_correction_count = 0; + + // Restart with a half number so that we'll not endup with the same situation + // This will prevent peak_detect to not detect anything + d_to_consume = d_to_consume / 2; + } + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each(d_to_consume); + + // Tell runtime system how many output items we produced. + return (d_to_out); + } + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h new file mode 100644 index 0000000000..7190ec5f56 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H +#define INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H + +#include <gnuradio/dtv/dvbt_ofdm_sym_acquisition.h> + +#undef SEGFAULT_FIX + +namespace gr { + namespace dtv { + + class dvbt_ofdm_sym_acquisition_impl : public dvbt_ofdm_sym_acquisition + { + private: + int d_blocks; + int d_fft_length; + int d_cp_length; + float d_snr; + float d_rho; + + int d_index; + + int d_search_max; + + gr_complex * d_conj; + float * d_norm; + gr_complex * d_corr; + gr_complex * d_gamma; + float * d_lambda; + float * d_arg; + + // For peak detector + float d_threshold_factor_rise; + float d_threshold_factor_fall; + float d_avg_alpha; + float d_avg; + float d_phase; + double d_phaseinc; + int d_cp_found; + int d_count; + double d_nextphaseinc; + int d_nextpos; + + int d_sym_acq_count; + int d_sym_acq_timeout; + + int d_initial_acquisition; + + int d_freq_correction_count; + int d_freq_correction_timeout; + + int d_cp_start; + +#ifdef SEGFAULT_FIX + int d_cp_start_initial; + int d_cp_start_slip; +#endif + + gr_complex * d_derot; + int d_to_consume; + int d_to_out; + + int ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out); + + int peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha); + + int peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max); + + void send_sync_start(); + public: + dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr); + ~dvbt_ofdm_sym_acquisition_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc new file mode 100644 index 0000000000..4a5530cfbe --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_reed_solomon_dec_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + dvbt_reed_solomon_dec::sptr + dvbt_reed_solomon_dec::make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks) + { + return gnuradio::get_initial_sptr + (new dvbt_reed_solomon_dec_impl(p, m, gfpoly, n, k, t, s, blocks)); + } + + /* + * The private constructor + */ + dvbt_reed_solomon_dec_impl::dvbt_reed_solomon_dec_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks) + : block("dvbt_reed_solomon_dec", + io_signature::make(1, 1, sizeof(unsigned char) * blocks * (n - s)), + io_signature::make(1, 1, sizeof(unsigned char) * blocks * (k - s))), + d_p(p), d_m(m), d_gfpoly(gfpoly), d_n(n), d_k(k), d_t(t), d_s(s), d_blocks(blocks), + d_rs(p, m, gfpoly, n, k, t, s, blocks) + { + d_in = new unsigned char[d_n]; + if (d_in == NULL) { + std::cout << "Cannot allocate memory for d_in" << std::endl; + exit(1); + } + memset(&d_in[0], 0, d_n); + } + + /* + * Our virtual destructor. + */ + dvbt_reed_solomon_dec_impl::~dvbt_reed_solomon_dec_impl() + { + delete [] d_in; + } + + void + dvbt_reed_solomon_dec_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + dvbt_reed_solomon_dec_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 unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // We receive only nonzero data + int in_bsize = d_n - d_s; + int out_bsize = d_k - d_s; + + for (int i = 0; i < (d_blocks * noutput_items); i++) { + //TODO - zero copy? + // Set first d_s symbols to zero + memset(&d_in[0], 0, d_s); + // Then copy actual data + memcpy(&d_in[d_s], &in[i * in_bsize], in_bsize); + + d_rs.rs_decode(d_in, NULL, 0); + + memcpy(&out[i * out_bsize], &d_in[d_s], out_bsize); + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h new file mode 100644 index 0000000000..951aa4b2a1 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_dec_impl.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H +#define INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H + +#include <gnuradio/dtv/dvbt_reed_solomon_dec.h> +#include "dvbt_reed_solomon.h" + +namespace gr { + namespace dtv { + + class dvbt_reed_solomon_dec_impl : public dvbt_reed_solomon_dec + { + private: + int d_p; + int d_m; + int d_gfpoly; + int d_n; + int d_k; + int d_t; + int d_s; + int d_blocks; + + unsigned char * d_in; + + dvbt_reed_solomon d_rs; + + public: + dvbt_reed_solomon_dec_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks); + ~dvbt_reed_solomon_dec_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_DEC_IMPL_H */ + diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc index 58fc76c64e..b3c7046ae2 100644 --- a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc @@ -182,7 +182,7 @@ namespace gr { // allocate buffer for scattered pilots d_spilot_carriers_val = new gr_complex[d_Kmax - d_Kmin + 1]; if (d_spilot_carriers_val == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_spilot_carriers_val" << std::endl; delete [] d_wk; exit(1); } @@ -190,7 +190,7 @@ namespace gr { // allocate buffer for channel gains (for each useful carrier) d_channel_gain = new gr_complex[d_Kmax - d_Kmin + 1]; if (d_channel_gain == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_channel_gain" << std::endl; delete [] d_spilot_carriers_val; delete [] d_wk; exit(1); @@ -199,7 +199,7 @@ namespace gr { // Allocate buffer for continual pilots phase diffs d_known_phase_diff = new float[d_cpilot_carriers_size - 1]; if (d_known_phase_diff == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_known_phase_diff" << std::endl; delete [] d_channel_gain; delete [] d_spilot_carriers_val; delete [] d_wk; @@ -214,7 +214,7 @@ namespace gr { d_cpilot_phase_diff = new float[d_cpilot_carriers_size - 1]; if (d_cpilot_phase_diff == NULL) { - std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl; + std::cout << "Cannot allocate memory for d_cpilot_phase_diff" << std::endl; delete [] d_known_phase_diff; delete [] d_channel_gain; delete [] d_spilot_carriers_val; @@ -263,7 +263,7 @@ namespace gr { d_prev_tps_symbol = new gr_complex[d_tps_carriers_size]; if (d_prev_tps_symbol == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_prev_tps_symbol" << std::endl; delete [] d_tps_data; delete [] d_tps_carriers_val; delete [] d_derot_in; @@ -278,7 +278,7 @@ namespace gr { d_tps_symbol = new gr_complex[d_tps_carriers_size]; if (d_tps_symbol == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_tps_symbol" << std::endl; delete [] d_prev_tps_symbol; delete [] d_tps_data; delete [] d_tps_carriers_val; @@ -306,7 +306,7 @@ namespace gr { // Allocate buffer for channel estimation carriers d_chanestim_carriers = new int[d_Kmax - d_Kmin + 1]; if (d_chanestim_carriers == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_chanestim_carriers" << std::endl; delete [] d_tps_symbol; delete [] d_prev_tps_symbol; delete [] d_tps_data; @@ -323,7 +323,7 @@ namespace gr { // Allocate buffer for payload carriers d_payload_carriers = new int[d_Kmax - d_Kmin + 1]; if (d_payload_carriers == NULL) { - std::cout << "Cannot allocate memory for d_tps_data" << std::endl; + std::cout << "Cannot allocate memory for d_payload_carriers" << std::endl; delete [] d_chanestim_carriers; delete [] d_tps_symbol; delete [] d_prev_tps_symbol; @@ -435,8 +435,9 @@ namespace gr { memset(&data_in[0], 0, 60); //fill in TPS data - start bit not included //memcpy(&data_in[60], &data[1], 53); - for (int i = 0; i < 53; i++) + for (int i = 0; i < 53; i++) { data_in[60 + i] = data[1 + i]; + } //X^14+X^9+X^8+X^6+X^5+X^4+X^2+X+1 for (int i = 0; i < 113; i++) { diff --git a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc index 64d242d5fb..8bdfbf9776 100644 --- a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc @@ -184,7 +184,7 @@ namespace gr { // Interleave for (int q = 0; q < d_nsize; q++) { if (d_symbol_index % 2) { - out[blocks + q] = in[blocks + H(q)]; + out[blocks + q] = in[blocks + H(q)]; } else { out[blocks + H(q)] = in[blocks + q]; diff --git a/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc new file mode 100644 index 0000000000..4f2362ccf4 --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.cc @@ -0,0 +1,495 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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 "dvbt_viterbi_decoder_impl.h" +#include <stdio.h> + +namespace gr { + namespace dtv { + + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_1_2[2] = {1, 1}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_2_3[4] = {1, 1, 0, 1}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_3_4[6] = {1, 1, 0, 1, 1, 0}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_5_6[10] = {1, 1, 0, 1, 1, 0, 0, 1, 1, 0}; + const unsigned char dvbt_viterbi_decoder_impl::d_puncture_7_8[14] = {1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}; + /* 8-bit parity lookup table, generated by partab.c */ + const unsigned char dvbt_viterbi_decoder_impl::d_Partab[] = { + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + }; + + __m128i dvbt_viterbi_decoder_impl::d_metric0[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_metric1[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_path0[4] __attribute__ ((aligned(16))); + __m128i dvbt_viterbi_decoder_impl::d_path1[4] __attribute__ ((aligned(16))); + + branchtab27 dvbt_viterbi_decoder_impl::Branchtab27_sse2[2] __attribute__ ((aligned(16))); + + unsigned char dvbt_viterbi_decoder_impl::mmresult[64] __attribute__((aligned(16))); + unsigned char dvbt_viterbi_decoder_impl::ppresult[TRACEBACK_MAX][64] __attribute__((aligned(16))); + + void + dvbt_viterbi_decoder_impl::dvbt_viterbi_chunks_init_sse2(__m128i *mm0, __m128i *pp0) + { + // Initialize starting metrics to prefer 0 state + int i, j; + + for (i = 0; i < 4; i++) { + mm0[i] = _mm_setzero_si128(); + pp0[i] = _mm_setzero_si128(); + } + + int polys[2] = { POLYA, POLYB }; + for (i = 0; i < 32; i++) { + Branchtab27_sse2[0].c[i] = (polys[0] < 0) ^ d_Partab[(2*i) & abs(polys[0])] ? 1 : 0; + Branchtab27_sse2[1].c[i] = (polys[1] < 0) ^ d_Partab[(2*i) & abs(polys[1])] ? 1 : 0; + } + + for (i = 0; i < 64; i++) { + mmresult[i] = 0; + for (j = 0; j < TRACEBACK_MAX; j++) { + ppresult[j][i] = 0; + } + } + } + + void + dvbt_viterbi_decoder_impl::dvbt_viterbi_butterfly2_sse2(unsigned char *symbols, __m128i *mm0, __m128i *mm1, __m128i *pp0, __m128i *pp1) + { + int i; + + __m128i *metric0, *metric1; + __m128i *path0, *path1; + + metric0 = mm0; + path0 = pp0; + metric1 = mm1; + path1 = pp1; + + // Operate on 4 symbols (2 bits) at a time + + __m128i m0, m1, m2, m3, decision0, decision1, survivor0, survivor1; + __m128i metsv, metsvm; + __m128i shift0, shift1; + __m128i tmp0, tmp1; + __m128i sym0v, sym1v; + + sym0v = _mm_set1_epi8(symbols[0]); + sym1v = _mm_set1_epi8(symbols[1]); + + for (i = 0; i < 2; i++) { + if (symbols[0] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else if (symbols[1] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else { + metsvm = _mm_add_epi8(_mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v)); + metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm); + } + + m0 = _mm_add_epi8(metric0[i], metsv); + m1 = _mm_add_epi8(metric0[i+2], metsvm); + m2 = _mm_add_epi8(metric0[i], metsvm); + m3 = _mm_add_epi8(metric0[i+2], metsv); + + decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128()); + decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128()); + survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1)); + survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3)); + + shift0 = _mm_slli_epi16(path0[i], 1); + shift1 = _mm_slli_epi16(path0[2+i], 1); + shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1)); + + metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1); + tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1)); + + metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1); + tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1)); + + path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1); + path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1); + } + + metric0 = mm1; + path0 = pp1; + metric1 = mm0; + path1 = pp0; + + sym0v = _mm_set1_epi8(symbols[2]); + sym1v = _mm_set1_epi8(symbols[3]); + + for (i = 0; i < 2; i++) { + if (symbols[2] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else if (symbols[3] == 2) { + metsvm = _mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v); + metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm); + } + else { + metsvm = _mm_add_epi8(_mm_xor_si128(Branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(Branchtab27_sse2[1].v[i],sym1v)); + metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm); + } + + m0 = _mm_add_epi8(metric0[i], metsv); + m1 = _mm_add_epi8(metric0[i+2], metsvm); + m2 = _mm_add_epi8(metric0[i], metsvm); + m3 = _mm_add_epi8(metric0[i+2], metsv); + + decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128()); + decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128()); + survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1)); + survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3)); + + shift0 = _mm_slli_epi16(path0[i], 1); + shift1 = _mm_slli_epi16(path0[2+i], 1); + shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1)); + + metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1); + tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1)); + + metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1); + tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1)); + + path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1); + path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1); + } + } + + unsigned char + dvbt_viterbi_decoder_impl::dvbt_viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0, int ntraceback, unsigned char *outbuf) + { + // Find current best path + int i; + int bestmetric, minmetric; + int beststate = 0; + int pos = 0; + + // Implement a circular buffer with the last ntraceback paths + store_pos = (store_pos + 1) % ntraceback; + + // TODO - find another way to extract the value + for (i = 0; i < 4; i++) { + _mm_store_si128((__m128i *) &mmresult[i*16], mm0[i]); + _mm_store_si128((__m128i *) &ppresult[store_pos][i*16], pp0[i]); + } + + // Find out the best final state + bestmetric = mmresult[beststate]; + minmetric = mmresult[beststate]; + + for (i = 1; i < 64; i++) { + if (mmresult[i] > bestmetric) { + bestmetric = mmresult[i]; + beststate = i; + } + if (mmresult[i] < minmetric) { + minmetric = mmresult[i]; + } + } + + // Trace back + for (i = 0, pos = store_pos; i < (ntraceback - 1); i++) { + // Obtain the state from the output bits + // by clocking in the output bits in reverse order. + // The state has only 6 bits + beststate = ppresult[pos][beststate] >> 2; + pos = (pos - 1 + ntraceback) % ntraceback; + } + + // Store output byte + *outbuf = ppresult[pos][beststate]; + + // Zero out the path variable + // and prevent metric overflow + for (i = 0; i < 4; i++) { + pp0[i] = _mm_setzero_si128(); + mm0[i] = _mm_sub_epi8(mm0[i], _mm_set1_epi8(minmetric)); + } + + return bestmetric; + } + + dvbt_viterbi_decoder::sptr + dvbt_viterbi_decoder::make(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize) + { + return gnuradio::get_initial_sptr + (new dvbt_viterbi_decoder_impl(constellation, hierarchy, coderate, bsize)); + } + + /* + * The private constructor + */ + dvbt_viterbi_decoder_impl::dvbt_viterbi_decoder_impl(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize) + : block("dvbt_viterbi_decoder", + io_signature::make(1, 1, sizeof (unsigned char)), + io_signature::make(1, 1, sizeof (unsigned char))), + config(constellation, hierarchy, coderate, coderate), + d_bsize(bsize), + d_init(0), + store_pos(0) + { + //Determine k - input of encoder + d_k = config.d_cr_k; + //Determine n - output of encoder + d_n = config.d_cr_n; + //Determine m - constellation symbol size + d_m = config.d_m; + // Determine puncturing vector and traceback + if (config.d_code_rate_HP == C1_2) { + d_puncture = d_puncture_1_2; + d_ntraceback = 5; + } + else if (config.d_code_rate_HP == C2_3) { + d_puncture = d_puncture_2_3; + d_ntraceback = 9; + } + else if (config.d_code_rate_HP == C3_4) { + d_puncture = d_puncture_3_4; + d_ntraceback = 10; + } + else if (config.d_code_rate_HP == C5_6) { + d_puncture = d_puncture_5_6; + d_ntraceback = 15; + } + else if (config.d_code_rate_HP == C7_8) { + d_puncture = d_puncture_7_8; + d_ntraceback = 24; + } + else { + d_puncture = d_puncture_1_2; + d_ntraceback = 5; + } + + /* + * We input n bytes, each carrying m bits => nm bits + * The result after decoding is km bits, therefore km/8 bytes. + * + * out/in rate is therefore km/8n in bytes + */ + assert((d_k * d_m) % (8 * d_n)); + set_relative_rate((d_k * d_m) / (8 * d_n)); + + assert ((d_bsize * d_n) % d_m == 0); + set_output_multiple (d_bsize * d_k / 8); + + /* + * Calculate process variables: + * Number of symbols (d_m bits) in all blocks + * It is also the number of input bytes since + * one byte always contains just one symbol. + */ + d_nsymbols = d_bsize * d_n / d_m; + // Number of bits after depuncturing a block (before decoding) + d_nbits = 2 * d_k * d_bsize; + // Number of output bytes after decoding + d_nout = d_nbits / 2 / 8; + + // Allocate the buffer for the bits + d_inbits = new unsigned char [d_nbits]; + if (d_inbits == NULL) { + std::cout << "Cannot allocate memory for d_inbits" << std::endl; + exit(1); + } + + mettab[0][0] = 1; + mettab[0][1] = 0; + mettab[1][0] = 0; + mettab[1][1] = 1; + + dvbt_viterbi_chunks_init_sse2(d_metric0, d_path0); + } + + /* + * Our virtual destructor. + */ + dvbt_viterbi_decoder_impl::~dvbt_viterbi_decoder_impl() + { + delete [] d_inbits; + } + + void + dvbt_viterbi_decoder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + int input_required = noutput_items * 8 * d_n / (d_k * d_m); + + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } + } + + int + dvbt_viterbi_decoder_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + int nblocks = 8 * noutput_items / (d_bsize * d_k); + int out_count = 0; + + for (int m = 0; m < nstreams; m++) { + const unsigned char *in = (const unsigned char *) input_items[m]; + unsigned char *out = (unsigned char *) output_items[m]; + + /* + * Look for a tag that signals superframe_start and consume all input items + * that are in input buffer so far. + * This will actually reset the viterbi decoder. + */ + std::vector<tag_t> tags; + const uint64_t nread = this->nitems_read(0); //number of items read on port 0 + this->get_tags_in_range(tags, 0, nread, nread + (nblocks * d_nsymbols), pmt::string_to_symbol("superframe_start")); + + if (tags.size()) { + d_init = 0; + dvbt_viterbi_chunks_init_sse2(d_metric0, d_path0); + + if (tags[0].offset - nread) { + consume_each(tags[0].offset - nread); + return (0); + } + } + + // This is actually the Viterbi decoder + for (int n = 0; n < nblocks; n++) { + /* + * Depuncture and unpack a block. + * We receive the symbol (d_m bits/byte) in one byte (e.g. for QAM16 00001111). + * Create a buffer of bytes containing just one bit/byte. + * Also depuncture according to the puncture vector. + * TODO - reduce the number of branches while depuncturing. + */ + for (int count = 0, i = 0; i < d_nsymbols; i++) { + for (int j = (d_m - 1); j >= 0; j--) { + // Depuncture + while (d_puncture[count % (2 * d_k)] == 0) { + d_inbits[count++] = 2; + } + + // Insert received bits + d_inbits[count++] = (in[(n * d_nsymbols) + i] >> j) & 1; + + // Depuncture + while (d_puncture[count % (2 * d_k)] == 0) { + d_inbits[count++] = 2; + } + } + } + + /* + * Decode a block. + */ + for (int in_count = 0; in_count < d_nbits; in_count++) { + if ((in_count % 4) == 0) { // 0 or 3 + dvbt_viterbi_butterfly2_sse2(&d_inbits[in_count & 0xfffffffc], d_metric0, d_metric1, d_path0, d_path1); + + if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11 + unsigned char c; + + dvbt_viterbi_get_output_sse2(d_metric0, d_path0, d_ntraceback, &c); + + if (d_init == 0) { + if (out_count >= d_ntraceback) { + out[out_count - d_ntraceback] = c; + } + } + else { + out[out_count] = c; + } + out_count++; + } + } + } + } + } + + int to_out = noutput_items; + + if (d_init == 0) { + /* + * Send superframe_start to signal this situation + * downstream + */ + const uint64_t offset = this->nitems_written(0); + pmt::pmt_t key = pmt::string_to_symbol("superframe_start"); + pmt::pmt_t value = pmt::from_long(1); + this->add_item_tag(0, offset, key, value); + + // Take in consideration the traceback length + to_out = to_out - d_ntraceback; + d_init = 1; + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (nblocks * d_nsymbols); + + // Tell runtime system how many output items we produced. + return (to_out); + } + + } /* namespace dtv */ +} /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h new file mode 100644 index 0000000000..8870a79dcf --- /dev/null +++ b/gr-dtv/lib/dvbt/dvbt_viterbi_decoder_impl.h @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2015 Free Software Foundation, Inc. + * + * 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_DTV_DVBT_VITERBI_DECODER_IMPL_H +#define INCLUDED_DTV_DVBT_VITERBI_DECODER_IMPL_H + +#include <gnuradio/dtv/dvbt_viterbi_decoder.h> +#include "dvbt_configure.h" +#include <xmmintrin.h> + +/* The two generator polynomials for the NASA Standard K=7 code. + * Since these polynomials are known to be optimal for this constraint + * length there is not much point in changing them. + */ + +#define POLYA 0x4f +#define POLYB 0x6d +// Maximum number of traceback bytes +#define TRACEBACK_MAX 24 + +union branchtab27 { + unsigned char c[32]; + __m128i v[2]; +}; + +namespace gr { + namespace dtv { + + class dvbt_viterbi_decoder_impl : public dvbt_viterbi_decoder + { + private: + dvbt_configure config; + + // Puncturing vectors + static const unsigned char d_puncture_1_2[]; + static const unsigned char d_puncture_2_3[]; + static const unsigned char d_puncture_3_4[]; + static const unsigned char d_puncture_5_6[]; + static const unsigned char d_puncture_7_8[]; + static const unsigned char d_Partab[]; + + static __m128i d_metric0[4]; + static __m128i d_metric1[4]; + static __m128i d_path0[4]; + static __m128i d_path1[4]; + + static branchtab27 Branchtab27_sse2[2]; + + // Metrics for each state + static unsigned char mmresult[64]; + // Paths for each state + static unsigned char ppresult[TRACEBACK_MAX][64]; + + // Current puncturing vector + const unsigned char * d_puncture; + + // Code rate k/n + int d_k; + int d_n; + // Constellation with m + int d_m; + + // Block size + int d_bsize; + // Symbols to consume on decoding from one block + int d_nsymbols; + // Number of bits after depuncturing a block + int d_nbits; + // Number of full packed out bytes + int d_nout; + + // Traceback (in bytes) + int d_ntraceback; + + // Viterbi tables + int mettab[2][256]; + + // Buffer to keep the input bits + unsigned char * d_inbits; + + // This is used to get rid of traceback on the first frame + int d_init; + + // Position in circular buffer where the current decoded byte is stored + int store_pos; + + void dvbt_viterbi_chunks_init_sse2(__m128i *mm0, __m128i *pp0); + void dvbt_viterbi_butterfly2_sse2(unsigned char *symbols, __m128i m0[], __m128i m1[], __m128i p0[], __m128i p1[]); + unsigned char dvbt_viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0, int ntraceback, unsigned char *outbuf); + + public: + dvbt_viterbi_decoder_impl(dvb_constellation_t constellation, \ + dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate, int bsize); + ~dvbt_viterbi_decoder_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dtv +} // namespace gr + +#endif /* INCLUDED_DTV_DVBT_VITERBI_DECODER_IMPL_H */ + diff --git a/gr-dtv/swig/dtv_swig.i b/gr-dtv/swig/dtv_swig.i index 094e8f0faf..c2fa312e05 100644 --- a/gr-dtv/swig/dtv_swig.i +++ b/gr-dtv/swig/dtv_swig.i @@ -71,6 +71,14 @@ #include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h" #include "gnuradio/dtv/dvbt_map.h" #include "gnuradio/dtv/dvbt_reference_signals.h" +#include "gnuradio/dtv/dvbt_ofdm_sym_acquisition.h" +#include "gnuradio/dtv/dvbt_demod_reference_signals.h" +#include "gnuradio/dtv/dvbt_demap.h" +#include "gnuradio/dtv/dvbt_bit_inner_deinterleaver.h" +#include "gnuradio/dtv/dvbt_viterbi_decoder.h" +#include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h" +#include "gnuradio/dtv/dvbt_reed_solomon_dec.h" +#include "gnuradio/dtv/dvbt_energy_descramble.h" %} %include "gnuradio/dtv/atsc_deinterleaver.h" @@ -116,6 +124,14 @@ %include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h" %include "gnuradio/dtv/dvbt_map.h" %include "gnuradio/dtv/dvbt_reference_signals.h" +%include "gnuradio/dtv/dvbt_ofdm_sym_acquisition.h" +%include "gnuradio/dtv/dvbt_demod_reference_signals.h" +%include "gnuradio/dtv/dvbt_demap.h" +%include "gnuradio/dtv/dvbt_bit_inner_deinterleaver.h" +%include "gnuradio/dtv/dvbt_viterbi_decoder.h" +%include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h" +%include "gnuradio/dtv/dvbt_reed_solomon_dec.h" +%include "gnuradio/dtv/dvbt_energy_descramble.h" GR_SWIG_BLOCK_MAGIC2(dtv, atsc_deinterleaver); GR_SWIG_BLOCK_MAGIC2(dtv, atsc_depad); @@ -156,3 +172,11 @@ GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_bit_inner_interleaver); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_symbol_inner_interleaver); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_map); GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reference_signals); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_ofdm_sym_acquisition); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_demod_reference_signals); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_demap); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_bit_inner_deinterleaver); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_viterbi_decoder); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_convolutional_deinterleaver); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reed_solomon_dec); +GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_energy_descramble); |