GNSS-SDR 0.0.21
An Open Source GNSS Software Defined Receiver
Loading...
Searching...
No Matches
ion_gsms_chunk_unpacking_ctx.h
Go to the documentation of this file.
1/*!
2 * \file ion_gsms_chunk_unpacking_ctx.h
3 * \brief Holds state and provides utilities for unpacking samples from a chunk
4 * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
5 *
6 * This is a template class, and thus, its member functions must be defined in the header file.
7 *
8 * -----------------------------------------------------------------------------
9 *
10 * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
11 * This file is part of GNSS-SDR.
12 *
13 * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
14 * SPDX-License-Identifier: GPL-3.0-or-later
15 *
16 * -----------------------------------------------------------------------------
17 */
18
19#ifndef GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H
20#define GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H
21
22#include <gnuradio/block.h>
23#include <GnssMetadata.h>
24#include <cstdint>
25
26/** \addtogroup Signal_Source
27 * \{ */
28/** \addtogroup Signal_Source_libs
29 * \{ */
30
31template <typename WT>
32struct IONGSMSChunkUnpackingCtx
33{
34 static constexpr uint8_t word_bitsize_ = sizeof(WT) * 8;
35
36 const GnssMetadata::Chunk::WordShift word_shift_direction_;
37 WT* iterator_ = nullptr; // Not owned by this class, MUST NOT destroy
38 WT current_word_{};
39 uint8_t bitshift_ = 0;
40
41 IONGSMSChunkUnpackingCtx(
42 const GnssMetadata::Chunk::WordShift word_shift,
43 WT* data_buffer,
44 uint8_t data_buffer_word_count) : word_shift_direction_(word_shift)
45 {
46 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
47 {
48 iterator_ = data_buffer;
49 }
50 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
51 {
52 iterator_ = &data_buffer[data_buffer_word_count];
53 }
54 if (iterator_)
55 {
56 advance_word(); // Initializes current_word_
57 }
58 }
59
60 void advance_word()
61 {
62 WT word = *iterator_;
63 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
64 {
65 ++iterator_;
66 }
67 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
68 {
69 --iterator_;
70 }
71
72 current_word_ = word;
73 }
74
75 void shift_current_word(uint8_t n)
76 {
77 if ((n % word_bitsize_) == 0)
78 {
79 for (uint8_t i = 0; i < (n / word_bitsize_); ++i)
80 {
81 advance_word();
82 }
83 return;
84 }
85
86 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
87 {
88 current_word_ <<= n;
89 }
90 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
91 {
92 current_word_ >>= n;
93 }
94
95 bitshift_ += n;
96 if (bitshift_ >= word_bitsize_)
97 {
98 advance_word();
99 bitshift_ -= word_bitsize_;
100 }
101 }
102
103 void shift_padding(uint8_t n_bits)
104 {
105 if (n_bits == 0)
106 {
107 return;
108 }
109
110 if ((n_bits + (bitshift_ % word_bitsize_)) >= word_bitsize_)
111 {
112 const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
113
114 shift_current_word(bits_shifted);
115 shift_padding(n_bits - bits_shifted);
116 }
117 else
118 {
119 shift_current_word(n_bits);
120 }
121 }
122
123 template <typename OT>
124 void shift_sample(uint8_t sample_bitsize, OT* output, uint8_t output_bit_offset = 0)
125 {
126 if (sample_bitsize % word_bitsize_ == 0)
127 {
128 const uint8_t words_per_sample = sample_bitsize / word_bitsize_;
129 for (uint8_t i = 0; i < words_per_sample; ++i)
130 {
131 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
132 {
133 *output |= (current_word_ << ((words_per_sample - 1 - i) * word_bitsize_));
134 }
135 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
136 {
137 *output |= (current_word_ << (i * word_bitsize_));
138 // TODO - reverse bit order of sample? maybe?
139 }
140 advance_word();
141 }
142 }
143 else if ((sample_bitsize + (bitshift_ % word_bitsize_)) > word_bitsize_)
144 {
145 const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
146
147 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
148 {
149 WT mask = ~((1 << (word_bitsize_ - bits_shifted)) - 1);
150 *output |= ((current_word_ & mask) >> output_bit_offset);
151 }
152 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
153 {
154 WT mask = ((1 << (bits_shifted)) - 1);
155 *output |= (current_word_ & mask) << output_bit_offset;
156 // TODO - reverse bit order of sample? maybe?
157 }
158
159 shift_current_word(bits_shifted);
160 shift_sample(sample_bitsize - bits_shifted, output, bits_shifted);
161 }
162 else
163 {
164 if (word_shift_direction_ == GnssMetadata::Chunk::Left)
165 {
166 WT mask = ~((1 << (word_bitsize_ - sample_bitsize)) - 1);
167 OT sample = (current_word_ & mask) >> (word_bitsize_ - sample_bitsize);
168 *output |= (sample) >> output_bit_offset;
169 }
170 else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
171 {
172 WT mask = ((1 << (sample_bitsize)) - 1);
173 *output |= (current_word_ & mask) << output_bit_offset;
174 // TODO - reverse bit order of sample? maybe?
175 }
176
177 shift_current_word(sample_bitsize);
178 }
179 }
180};
181
182/** \} */
183/** \} */
184#endif // GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H