-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MIMO Channel Estimation #29
base: master
Are you sure you want to change the base?
Conversation
…ime error if Eigen3 not found.
…d 1x1 and 2x2 MIMO scheme.
…ng the Eigen library.
…() loops for terminated input data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The uint16 symbol_length overflow issue is the only bug I could find.
Not quite sure about the break
issue, might be an oversight.
The PMT performance issues are not important.
// Iterate over tags in buffer. | ||
for (unsigned int i = 0; i < tags.size(); ++i) { | ||
// Calculate the number of items before the next tag. | ||
if (i < tags.size() - 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not simply split into a for
loop with condition i < tags.size() - 1
and a separate i = tags.size()-1
?
That'd enhance readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I would have to repeat the code after the if else statement in the for loop for both cases which would worsen the readability again, or am I overseeing something here?
if (symbol_length < d_training_length){ | ||
/* We consume the whole training sequence in the next buffer and don't consume it now | ||
* in order to do the estimation at once. */ | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the last iteration of the for
loop anyway, and this is the last statement in that iteration. Breaking at this point doesn't do anything, or am I mistaken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we perhaps missing the case where symbol length is not smaller than training sequence length and we need to consume now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The for loop is not finished after the if else statement. If the symbol length is smaller than the training length, we cannot process the received training sequence right now. So we are breaking the loop (we are on the last iteration, but there would still be the copy and tag assignment operations in this iteration to be done) to skip the rest of the code in the for loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, I'll have to talk to you personally about this, but this is the "else" belonging to the "if(not last iteration)" clause, and that means this else is only executed on the last iteration, and right after the closing bracket of the "else" clause comes the closing bracket of the "for" clause. I'm clearly missing something here!
uint16_t d_N; /*!< Number of receiving antennas. */ | ||
std::vector<std::vector<gr_complex> > d_training_sequence; | ||
/*!< Training matrix: Each subvector/row is sent through one of the M transmit antennas. */ | ||
uint16_t d_training_length; /*!< Length of the training sequence. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just out of interest (it's unlikely we find a training sequence longer than 2¹⁶ - 1): Why the uint16_t
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has no specific reason. I am changing it to uint32_t.
// Collect all tags of the input buffer in the vector 'tags'. | ||
get_tags_in_window(tags, 0, 0, noutput_items); | ||
|
||
uint16_t symbol_length; // Number of items in the current symbol. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we sure our symbols are limited to 2¹⁶ - 1 items?
if (tags[0].offset - nitems_read(0) > 0){ | ||
/* There are items in the input buffer, before the first tag arrives, | ||
* which belong to the previous symbol. */ | ||
symbol_length = (tags[0].offset - nitems_read(0))*d_num_inputs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or rather, limited to (2¹⁶-1)/num_inputs? Sounds a bit of a dangerous thing, considering let's say 8×8 DAB MIMO ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to fix these issues in the according branch 'vblast'.
symbol_length = noutput_items - (tags[i].offset - nitems_read(0))*d_num_inputs; | ||
} | ||
// Check the key of the tag. | ||
if (pmt::symbol_to_string(tags[i].key).compare("csi") == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole idea of PMTs having symbols is that a symbol representing the same string is unique. So, instead of converting the symbol to the string and comparing the string you should just have a static pmt_t csi_key
here which get initialized once; then you can compare that to the tag key with == directly.
} | ||
// Calculate the weighting vector for the next symbol with the received CSI. | ||
update_mimo_equalizer(); | ||
} else if (pmt::symbol_to_string(tags[i].key).compare("snr") == 0 && d_equalizer_type.compare("MMSE") == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with comparing the string really is that PMT is horrific. The symbol_to_string
function does a dynamic cast of the pmt_base
to a pmt_symbol
. That's an awful lot of indirection just to compare. Also, in a lot of cases (I think this might be one), this requires a copy of the std::string
contained in that PMT to be made (did I ever mention how bad an idea that design is? Like, have "polymorphic type", but it not be properly polymorphic, and it also just inefficiently wrap std types, for communication within the same process?).
std::string
copies are relatively expensive and you try to avoid them in the signal processing part, because they require allocation and deallocation of memory.
gr_complex *out = (gr_complex *) output_items[i]; | ||
// Write output data to current output port. | ||
for (int j = 0; j < noutput_items; ++j) { | ||
out[j] = in[j*d_num_outputs + i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we even need this, or would one of the standard deinterleaver blocks work, too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if we swap the i
loop with the j
loop, it becomes evident that this might be solvable more efficiently with a memcpy
''' | ||
2 tests validating the correct estimation of the channel coefficients with a random channel | ||
and 1xN MIMO scheme. ''' | ||
def test_001_t (self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine, but for your own sanity in the future: test methods need to start with test_
and can take names like test_heavier_than_duck
.
pmt.make_f32vector(num_inputs, 1e8), | ||
pmt.from_long(0)))) | ||
|
||
for i in range(0, num_tags): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's simply range(num_tags)
;)
I get merge conflicts. Can you rebase? |
Thanks for the review! As discussed, I opened a new branch with the merged master. I am going to request a new pull and this pull request gets obsolete. |
This closes #17.