diff options
author | Tom Tsou <tom@tsou.cc> | 2015-01-05 16:35:07 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2015-01-14 10:15:40 +0100 |
commit | 7b61f4bb1a3c02acbab083000fcd9d62f79708a2 (patch) | |
tree | 2c0c196bd51fbf409b1c440f547f2405909531a7 | |
parent | 0175da4f86e6ff47ba6960e0d1138a76e5717592 (diff) | |
download | uhd-7b61f4bb1a3c02acbab083000fcd9d62f79708a2.tar.gz uhd-7b61f4bb1a3c02acbab083000fcd9d62f79708a2.tar.bz2 uhd-7b61f4bb1a3c02acbab083000fcd9d62f79708a2.zip |
convert: Limit sc12 converter buffer overwrite
This patch addresses issue #648 "B200: TX with SC12 format and MIMO".
The observed MIMO header corruption was caused by overwriting the
end of the packed 12-bit sample output buffer. The overwrite was due to
the converter call always writing out 4 complex samples even if less
than 4 samples were available. The extra samples would corrupt data with
zero padding.
Avoid the overwrite condition by only writing the minimum number of
32-bit lines necessary rather than the entire 12 byte struct.
Samples 32-bit lines
1 1
2 2
3 3
4 3
Signed-off-by: Tom Tsou <tom@tsou.cc>
-rw-r--r-- | host/lib/convert/convert_pack_sc12.cpp | 86 |
1 files changed, 74 insertions, 12 deletions
diff --git a/host/lib/convert/convert_pack_sc12.cpp b/host/lib/convert/convert_pack_sc12.cpp index 081f60a89..4f2aa3a64 100644 --- a/host/lib/convert/convert_pack_sc12.cpp +++ b/host/lib/convert/convert_pack_sc12.cpp @@ -32,6 +32,27 @@ struct item32_sc12_3x item32_t line2; }; +enum item32_sc12_3x_enable { + CONVERT12_LINE0 = 0x01, + CONVERT12_LINE1 = 0x02, + CONVERT12_LINE2 = 0x04, +}; + +/* + * Packed 12-bit converter with selective line enable + * + * The converter operates on 4 complex inputs and selectively writes to one to + * three 32-bit lines. Line selection allows for partial writes of less than + * 4 complex samples, or a full 3 x 32-bit struct. Writes are always full 32-bit + * lines, so in the case of partial writes, the number of bytes written will + * exceed the the number of bytes filled by actual samples. + * + * _ _ _ _ _ _ _ _ + * |_ _ _1_ _ _|_ _| 0 + * |_2_ _ _|_ _ _3_| + * |_ _|_ _ _4_ _ _| 2 + * 31 0 + */ template <typename type, towire32_type towire> void convert_star_4_to_sc12_item32_3 ( @@ -39,6 +60,7 @@ void convert_star_4_to_sc12_item32_3 const std::complex<type> &in1, const std::complex<type> &in2, const std::complex<type> &in3, + const int enable, item32_sc12_3x &output, const double scalar ) @@ -59,9 +81,30 @@ void convert_star_4_to_sc12_item32_3 const item32_t line1 = (i1 << 28) | (q1 << 16) | (i2 << 4) | (q2 >> 8); const item32_t line2 = (q2 << 24) | (i3 << 12) | (q3); - output.line0 = towire(line0); - output.line1 = towire(line1); - output.line2 = towire(line2); + if (enable & CONVERT12_LINE0) + output.line0 = towire(line0); + if (enable & CONVERT12_LINE1) + output.line1 = towire(line1); + if (enable & CONVERT12_LINE2) + output.line2 = towire(line2); +} + +/* + * Packed 12-bit converter with all lines enabled + */ +template <typename type, towire32_type towire> +void convert_star_4_to_sc12_item32_3 +( + const std::complex<type> &in0, + const std::complex<type> &in1, + const std::complex<type> &in2, + const std::complex<type> &in3, + item32_sc12_3x &output, + const double scalar +) +{ + int enable = CONVERT12_LINE0 | CONVERT12_LINE1 | CONVERT12_LINE2; + convert_star_4_to_sc12_item32_3<type, towire>(in0, in1, in2, in3, enable, output, scalar); } template <typename type, towire32_type towire> @@ -85,7 +128,8 @@ struct convert_star_1_to_sc12_item32_1 : public converter * Effectively outputs will point to a managed_buffer instance. These buffers are 32 bit aligned. * For a detailed description see comments in 'convert_unpack_sc12.cpp'. */ - const size_t head_samps = size_t(inputs[0]) & 0x3; + const size_t head_samps = size_t(outputs[0]) & 0x3; + int enable; size_t rewind = 0; switch(head_samps) { @@ -102,10 +146,19 @@ struct convert_star_1_to_sc12_item32_1 : public converter //handle the head case switch (head_samps) { - case 0: break; //no head - case 1: convert_star_4_to_sc12_item32_3<type, towire>(0, 0, 0, input[0], output[o++], _scalar); break; - case 2: convert_star_4_to_sc12_item32_3<type, towire>(0, 0, input[0], input[1], output[o++], _scalar); break; - case 3: convert_star_4_to_sc12_item32_3<type, towire>(0, input[0], input[1], input[2], output[o++], _scalar); break; + case 0: + break; //no head + case 1: + enable = CONVERT12_LINE2; + convert_star_4_to_sc12_item32_3<type, towire>(0, 0, 0, input[0], enable, output[o++], _scalar); + break; + case 2: + enable = CONVERT12_LINE2 | CONVERT12_LINE1; + convert_star_4_to_sc12_item32_3<type, towire>(0, 0, input[0], input[1], enable, output[o++], _scalar); + break; + case 3: + convert_star_4_to_sc12_item32_3<type, towire>(0, input[0], input[1], input[2], output[o++], _scalar); + break; } i += head_samps; @@ -120,10 +173,19 @@ struct convert_star_1_to_sc12_item32_1 : public converter const size_t tail_samps = nsamps - i; switch (tail_samps) { - case 0: break; //no tail - case 1: convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], 0, 0, 0, output[o], _scalar); break; - case 2: convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], input[i+1], 0, 0, output[o], _scalar); break; - case 3: convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], input[i+1], input[i+2], 0, output[o], _scalar); break; + case 0: + break; //no tail + case 1: + enable = CONVERT12_LINE0; + convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], 0, 0, 0, enable, output[o], _scalar); + break; + case 2: + enable = CONVERT12_LINE0 | CONVERT12_LINE1; + convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], input[i+1], 0, 0, enable, output[o], _scalar); + break; + case 3: + convert_star_4_to_sc12_item32_3<type, towire>(input[i+0], input[i+1], input[i+2], 0, output[o], _scalar); + break; } } |