Does fread use cast when reading non-integer byte data
2 views (last 30 days)
Show older comments
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 Comments
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')
castValue = double(x) % or
castValue = cast(x, 'double') % Same value as x, different type, different bit patterns
bitPattern = typecast(x, 'double') % Different values, different type, same bit patterns
whos x castValue bitPattern
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
castValue
bitPattern
3 Comments
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)
yFiS14 = fi(outFread,1,14,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)
ySI = yFiScaled.storedInteger
More Answers (0)
See Also
Categories
Find more on Fixed Point in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!