File cvt_core.h¶
FileList > cvt > cvt_core.h
Go to the source code of this file
Cvt module — public C API.
#include "clib_common.h"
Public Types¶
| Type | Name |
|---|---|
| enum | dp_bitorder_t Bit order within a byte, for the bit/value conversions below. |
Public Functions¶
| Type | Name |
|---|---|
| size_t | bin_to_hex (const uint8_t * bits, size_t bits_len, uint8_t * out, size_t out_len, int bitorder) Render unpacked bits to hex digits inverse of hex_to_bin. |
| uint64_t | bin_to_int (const uint8_t * bits, size_t bits_len, int bitorder) Read unpacked bits back into an integer inverse of int_to_bin. |
| size_t | bin_to_nrz (const uint8_t * bits, size_t bits_len, float * out, size_t out_len) Map unpacked bits to bipolar NRZ symbols: 0 -> +1, 1 -> -1. |
| size_t | hex_to_bin (const char * hex, uint8_t * out, size_t out_len, int bitorder) Expand a hex string to unpacked bits, one per byte. |
| size_t | int_to_bin (uint64_t v, uint32_t n_bits, uint8_t * out, size_t out_len, int bitorder) Expand the low n_bits of an integer to unpacked bits. |
| size_t | nrz_to_bin (const float * nrz, size_t nrz_len, uint8_t * out, size_t out_len) Hard-decide NRZ symbols back to bits inverse of bin_to_nrz. |
Public Static Functions¶
| Type | Name |
|---|---|
| size_t | cvt_bit_slot (size_t i, size_t width, int bitorder) Where the i-th bit of a unit lands under bitorder . |
| size_t | cvt_unit_width (size_t done, size_t total) The unit both directions walk in: 8 bits, then whatever is left. |
Public Types Documentation¶
enum dp_bitorder_t¶
Bit order within a byte, for the bit/value conversions below.
The name and the values follow numpy's packbits/unpackbits bitorder= argument, because that is the convention anyone writing this conversion has already met. It is a DIFFERENT axis from the endian (le/be) the BLUE writer takes, which selects a file's BYTE order the "EEEI" / "IEEE" field of a type-1000 header. A literal's digit order already fixes which byte comes first; what is left to choose is the order of bits inside one. Overloading one word for both would let a sync word and a sample stream disagree silently.
Public Functions Documentation¶
function bin_to_hex¶
Render unpacked bits to hex digits inverse of hex_to_bin.
size_t bin_to_hex (
const uint8_t * bits,
size_t bits_len,
uint8_t * out,
size_t out_len,
int bitorder
)
The digits come back as ASCII BYTES rather than a string: jm has no string out-parameter for a module function (just-buildit/just-makeit#1180), and uint8_t is the same type as the unsigned char a C caller would use anyway. A NUL is written after the digits. The C face is honest; only the Python face pays, with a bytes(out).decode().
Parameters:
bitsunpacked bits; any non-zero byte reads as 1.bits_lennumber of bits; must be a multiple of 4.outreceives the digits plus a NUL.out_lencapacity ofoutin bytes, NUL included.bitorderDP_BITORDER_BIG or DP_BITORDER_LITTLE.
Returns:
digits written, NOT counting the NUL, or 0 on refusal.
>>> import numpy as np
>>> from doppler.cvt import hex_to_bin, bin_to_hex
>>> b = np.zeros(32, np.uint8)
>>> hex_to_bin("1acffc1d", b, 0)
32
>>> h = np.zeros(16, np.uint8)
>>> n = bin_to_hex(b, h, 0)
>>> bytes(h[:n]).decode()
'1acffc1d'
function bin_to_int¶
Read unpacked bits back into an integer inverse of int_to_bin.
Returns the value rather than a status, because that is the shape a binding can carry. 0 is therefore both "the value zero" and "refused", which is acceptable only because every refusal here is a programming error in the WIDTH the caller chose (0, or over 64) or the bit order it named never a property of the data.
Parameters:
bits1..64 unpacked bits; any non-zero byte reads as 1.bits_lennumber of bits.bitorderDP_BITORDER_BIG or DP_BITORDER_LITTLE.
Returns:
the value, or 0 on refusal.
>>> import numpy as np
>>> from doppler.cvt import bin_to_int
>>> bits = np.array([0, 0, 0, 1, 1, 0, 1, 0], np.uint8)
>>> hex(bin_to_int(bits, 0))
'0x1a'
function bin_to_nrz¶
Map unpacked bits to bipolar NRZ symbols: 0 -> +1, 1 -> -1.
That is 1 - 2*b, and the convention's HOME is mpsk_core.h: BPSK is M-PSK at m = 2, where phi0 is 0, so label 0 lands at +1 and label 1 at -1. This states the same thing in the form a per-bit loop can afford, and test_cvt_core asserts the two agree rather than trusting them to. A mapper that disagreed with the receiver's would decode every bit INVERTED while looking perfectly locked which a round-trip test cannot see.
Parameters:
bitsunpacked bits; any non-zero byte reads as 1.bits_lennumber of bits.outreceivesbits_lensymbols, each +1.0f or -1.0f.out_lencapacity ofoutin symbols.
Returns:
symbols written, or 0 on refusal.
>>> import numpy as np
>>> from doppler.cvt import bin_to_nrz
>>> bits = np.array([0, 1, 1, 0], np.uint8)
>>> sym = np.zeros(4, np.float32)
>>> bin_to_nrz(bits, sym)
4
>>> sym.tolist()
[1.0, -1.0, -1.0, 1.0]
function hex_to_bin¶
Expand a hex string to unpacked bits, one per byte.
For what int_to_bin cannot serve: a literal wider than 64 bits, or one arriving as TEXT from a CLI flag or a JSON record. Each digit contributes 4 bits and digits read left to right, so an ODD number of digits is accepted and yields a 4-bit tail.
A bad digit is a REFUSAL, never a skipped one: a typo'd marker that silently shortens is the failure this exists to prevent, and it syncs to nothing rather than failing loudly.
Parameters:
hexNUL-terminated0-9a-fA-F. No0x, no separators.outreceives4 * strlen(hex)bytes, each 0 or 1.out_lencapacity ofoutin bits.bitorderDP_BITORDER_BIG or DP_BITORDER_LITTLE.
Returns:
bits written, or 0 on refusal out untouched.
>>> import numpy as np
>>> from doppler.cvt import hex_to_bin
>>> b = np.zeros(32, np.uint8)
>>> hex_to_bin("1ACFFC1D", b, 0) # the CCSDS attached sync marker
32
>>> b[:8].tolist()
[0, 0, 0, 1, 1, 0, 1, 0]
function int_to_bin¶
Expand the low n_bits of an integer to unpacked bits.
The form a frame field literal usually wants, and the one to reach for first: exact, compiler-checked, with no failure mode a typo can reach. hex_to_bin is for the two cases this cannot serve a literal wider than 64 bits, and text arriving from outside.
Bit 0 out is the MOST significant of the n_bits requested under DP_BITORDER_BIG, which is what makes int_to_bin(0x1A, 8, ...) read 0,0,0,1,1,0,1,0. Only the low n_bits are read, so a caller need not mask first.
Parameters:
vthe value.n_bits1..64.outreceivesn_bitsbytes, each 0 or 1.out_lencapacity ofoutin bits.bitorderDP_BITORDER_BIG or DP_BITORDER_LITTLE.
Returns:
n_bits, or 0 on refusal out untouched.
>>> import numpy as np
>>> from doppler.cvt import int_to_bin
>>> b = np.zeros(8, np.uint8)
>>> int_to_bin(0x1A, 8, b, 0) # 0 = big, MSB of each byte first
8
>>> b.tolist()
[0, 0, 0, 1, 1, 0, 1, 0]
function nrz_to_bin¶
Hard-decide NRZ symbols back to bits inverse of bin_to_nrz.
Negative is a 1; zero and positive are a 0, matching 1 - 2*b. Exactly zero decides to 0 rather than a coin toss, so the mapping is TOTAL and a round trip is exact. A caller that wants an erasure handled as an erasure wants a soft demapper, not this.
Parameters:
nrzsymbols.nrz_lennumber of symbols.outreceivesnrz_lenbytes, each 0 or 1.out_lencapacity ofoutin bits.
Returns:
bits written, or 0 on refusal.
>>> import numpy as np
>>> from doppler.cvt import nrz_to_bin
>>> sym = np.array([1.0, -1.0, -1.0, 1.0], np.float32)
>>> bits = np.zeros(4, np.uint8)
>>> nrz_to_bin(sym, bits)
4
>>> bits.tolist()
[0, 1, 1, 0]
Public Static Functions Documentation¶
function cvt_bit_slot¶
Where the i-th bit of a unit lands under bitorder .
function cvt_unit_width¶
The unit both directions walk in: 8 bits, then whatever is left.
Written once so the value and the string forms cannot disagree about where a short final unit begins the only place they could drift, and the place a marker would then be expanded two ways.
The documentation for this class was generated from the following file native/inc/cvt/cvt_core.h