Does fread use cast when reading non-integer byte data

3 views (last 30 days)
Dean Millard on 6 Jun 2024
Edited: Dean Millard on 11 Jun 2024
Using fread to read in binary containing 14bit ADC data streamed from an FPGA.
Wondering if fread does a cast when you use ubitn or bitn for the precision input.
Currently My fread setup similar to the code below spits out int16.
Output_data=fread(FID,Inf,'*bit14')
When I go to get this into a double will this int16 need to be bitsliced or cast.
0 CommentsShow -2 older commentsHide -2 older comments

Sign in to comment.

Accepted Answer

Steven Lord on 6 Jun 2024
MATLAB doesn't have a 14-bit integer type. The closest larger type is the signed 16-bit integer type int16. From the fread documentation, when you use the *source precision input argument: "For bitn or ubitn precisions, the output has the smallest class that can contain the input."
Can you clarify what you mean by "get this into a double"? Do you mean you want to cast the value from int16 to double? Or do you want to typecast the bit pattern? If the latter and you only want to work with 14 of the 16 bits in the int64 data returned by fread that could get a little tricky.
x = randi([intmin('int16'), intmax('int16')], 1, 8, 'int16')
x = 1x8
-31156 27584 -26584 6002 19324 12475 31998 25259
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
castValue = double(x) % or
castValue = 1x8
-31156 27584 -26584 6002 19324 12475 31998 25259
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
castValue = cast(x, 'double') % Same value as x, different type, different bit patterns
castValue = 1x8
-31156 27584 -26584 6002 19324 12475 31998 25259
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
bitPattern = typecast(x, 'double') % Different values, different type, same bit patterns
bitPattern = 1x2
1.0e+167 * 0.0000 2.0262
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
whos x castValue bitPattern
Name Size Bytes Class Attributes bitPattern 1x2 16 double castValue 1x8 64 double x 1x8 16 int16
Note that castValue has the same number of elements as x, but bitPattern has fewer. A 16-bit integer is stored in 2 bytes while a 64-bit double is stored in 8, so every 4 int16 values in x becomes 1 double in bitPattern. You can see the difference by looking at x, castValue, and bitPattern's hex representations.
format hex
x
x = 1x8
864c 6bc0 9828 1772 4b7c 30bb 7cfe 62ab
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
castValue
castValue = 1x8
c0de6d0000000000 40daf00000000000 c0d9f60000000000 40b7720000000000 40d2df0000000000 40c85d8000000000 40df3f8000000000 40d8aac000000000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
bitPattern
bitPattern = 1x2
1.0e+00 * 177298286bc0864c 62ab7cfe30bb4b7c
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
The swapbytes function may also be of interest to you.
3 CommentsShow 1 older commentHide 1 older comment
Andy Bartlett on 11 Jun 2024
Edited: Andy Bartlett on 11 Jun 2024
You can think of the internals of fread broken down into two steps.
Internal Step 1, read the VALUE from the file using the format specified.
Internal Step 2, convert the VALUE to the output type that was explicitly specified or implicitly determined.
So in your example, with '*bit14'
Internal Step 1 is to read a VALUE as type '*bit14'. Let's suppose the value is 1234.
Internal Step 2 convert the VALUE, 1234, to the implicit output type int16. Since the types are just integers (equivalently trivial fixed-point scaling), we don't have to worry about scaling changes; the real-world-values and stored-integer-values are same. Since the representable values of type int16 are a superset of the representable values in integer type signed 14 bits, the cast will be lossless. So we don't need to worry about overflows or rounding. If the input is 1234, then the output will be the identical value 1234.
If you want to think about it at the bit level, then the output would have two extra bits appended to the most significant end. These two extra bits will be a sign extension of the sign bit from the 14-bit input. So if the 14 bit input was non-negative, then the two extra bits on the most significant end will be 0's. If the the 14 bit input was negative, then the two extra bits on the most significant end of the output will be 1's.
If you wanted to get the value as a 14 bit fi object, you could just cast the output from fread.
outFread = int16(1234)
outFread = int16 1234
yFiS14 = fi(outFread,1,14,0)
yFiS14 =
1234 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 14 FractionLength: 0
% If the output should have fixed-point scaling
% just apply a reinterpretcast with the desired scaling.
fractionLength = 7;
nty = numerictype(1,14,fractionLength);
yFiScaled = reinterpretcast(yFiS14,nty)
yFiScaled =
9.6406 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 14 FractionLength: 7
ySI = yFiScaled.storedInteger
ySI = int16 1234
Dean Millard on 11 Jun 2024
Edited: Dean Millard on 11 Jun 2024
Exactly what I was looking for thank you, suprised you would sign extend the MSB end and juggle deciding wether to append 1 or 0

Sign in to comment.

Categories

Find more on Fixed Point in Help Center and File Exchange

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!