How to merge two bytes and how buf works in part of the code ?

Thread Starter

Xenon02

Joined Feb 24, 2021
504
Hello !

I've another question about merging 2 bytes. I was watching tutorials on youtube about STM32 and saw this part of the code :

1696901124418.png

The buffer was initially with uint8_t (uint8_t but[12]) that's how it was on the video. Although I don't understand how to read this part of the code ?

I can see that int16_t is only next to buf[0] and there is nothing next to buf[1]. And I know that there is arithmetic shift by 4 to left for buf[0] and by 4 to right for buf[1].
I know that's how arithmetic shift looks like this for 8 bit data :
1696901371339.png
So shifting by 4 to the right or left changes the data that was in 8 bits or does it magically change the size of buf ? I don't know how it looks like here exactly.

Also does the buffer at the end resets to uint8_t ? Or what ?
 

Ian0

Joined Aug 7, 2020
13,097
It has a 12-bit output that is left-justified over two bytes.
To get a 12-bit value in a int16_t you need the most-significant byte in bits 4 to 11 and the top four bits of the least significant bytes in bits 0 to 3.
So you need a left shift by 4 bits on the MSB and a right shift by 4 bits on the LSB.
val=(int16_t) etc means that it is doing the arithmetic at 16 bits.
It will be a LOGICAL shift not an ARITHMETIC shift, so bit 7 will be a zero.

Your software may give the wrong results for temperatures below freezing, as it might not fill bits 12-15 with ones, it bit 11 is set.
 

WBahn

Joined Mar 31, 2012
32,703
There's no such thing as an arithmetic left shift, Also, if buf is declared as unsigned, right shifts will be logical. Right shifts on a signed integer may be either logical or arithmetic at the compiler writer's whim.
 

Ian0

Joined Aug 7, 2020
13,097
There's no such thing as an arithmetic left shift, Also, if buf is declared as unsigned, right shifts will be logical. Right shifts on a signed integer may be either logical or arithmetic at the compiler writer's whim.
I know what you mean, but the 68000 does have an ASL instruction (which does exactly the same as its LSL instruction) and the 6502 has an ASL but no LSL.
Isn't an "arithmetic shift" a multiply or divide by two, whereas a "logical shift" is a bit manipulation instruction, and it just happens that the two left shift instructions do exactly the same thing.
 

Thread Starter

Xenon02

Joined Feb 24, 2021
504
So you need a left shift by 4 bits on the MSB and a right shift by 4 bits on the LSB.
val=(int16_t) etc means that it is doing the arithmetic at 16 bits.
I'm looking at the code and I still don't get it.
Because the buf[0] is 8 bit and is shifted 4 bits. For example I have buf[0] = 10100000 and I shift << 4 then ten result is buf[0] <<4 = 00000000. So it doesn't make sense how the programs interprets that buf[0] and buf[1] are somewhere in the middle of 16 bit address and is shifted by 4 left and right. For example let's say buf[0] = 10100000 and buf[1] = 10110001

So does it look like that ? :

1696933304563.png

Or like that ? :

1696933344389.png

Probably the second one is correct but I don't understand how the program know where the two buffs are places in this 16 bit adress.

What I understand is that the buf[0] is shifted by 4 bits to the left in his 8 bit adress becasue buf[0] is 8 bit not 16 bit same goes with buf[1] so why now I can do it ? I don't understand that and what does (int16_t) mean when it is in brackets, usually it is something like int or float in C language but putting it in brackets ?

Comming back to normal when I see this code I have this interpretation which is okey I see buf[0] shifted by 4 bits to the left so the result is 00000000 and buf[1] is shifte by 4 bit to the right so 00001011 like in the example for C coding :

1696934015393.png

1696934053916.png

I see I made an error shifting the buf[0] but I used the logic from this example :

1696934117571.png

I don't know this puzzles my ...
 

Attachments

Ian0

Joined Aug 7, 2020
13,097
You have shifted buf[0] the wrong way. It goes to the right.

[edit] correction:
You have shifted buf[1] the wrong way. It goes to the right.
 
Last edited:

Thread Starter

Xenon02

Joined Feb 24, 2021
504
You have shifted buf[0] the wrong way. It goes to the right.
Please answer to the whole post ;]

The code says buf[0] << 4.
Because now you've puzzled me more than before. I've written why this code puzzles my using the knowledge of how logic shift works and how C language is doing it and It doesn't make any sense to me.
 

Ian0

Joined Aug 7, 2020
13,097
Please answer to the whole post ;]

The code says buf[0] << 4.
Because now you've puzzled me more than before. I've written why this code puzzles my using the knowledge of how logic shift works and how C language is doing it and It doesn't make any sense to me.
Sorry. buf[1] goes to the right, and you have shifted the same way as buf[0]
 

MrChips

Joined Oct 2, 2009
34,628
Stop trying to learn from someone else’s code and go and read the TMP102 datasheet. Everything you need to know is there.
 
It looks like this:
1696938518147.png
Buf[0] is shifted to left, that's why it is casted with (uint16_t). Buf[1] is shifted to right, so its size is not changing: lower 4 bits are just discarded and higher 4 bits take their place. I hope this helps
 

BobTPH

Joined Jun 5, 2013
11,463
There's no such thing as an arithmetic left shift, Also, if buf is declared as unsigned, right shifts will be logical. Right shifts on a signed integer may be either logical or arithmetic at the compiler writer's whim.
Actually there is. The difference would be when an overflow is detected. Some processor I have long forgotten about had the two varieties.

For example, a left shift of a negative number would overflow if a zero bit is shifted into or past the sign position, making the result positive. Same with a 1 bit on a positive number.

Don’t remember what the logical shift did, maybe overflow set if any 1 bit sifted out.
 

WBahn

Joined Mar 31, 2012
32,703
Actually there is. The difference would be when an overflow is detected. Some processor I have long forgotten about had the two varieties.

For example, a left shift of a negative number would overflow if a zero bit is shifted into or past the sign position, making the result positive. Same with a 1 bit on a positive number.

Don’t remember what the logical shift did, maybe overflow set if any 1 bit sifted out.
Yeah, I can see the rational for having two in which they difference in behavior is how they interact with the flag bits.
 

WBahn

Joined Mar 31, 2012
32,703
I know what you mean, but the 68000 does have an ASL instruction (which does exactly the same as its LSL instruction) and the 6502 has an ASL but no LSL.
Isn't an "arithmetic shift" a multiply or divide by two, whereas a "logical shift" is a bit manipulation instruction, and it just happens that the two left shift instructions do exactly the same thing.
It probably comes down to a naming decision on the part of who does the ISA -- do they see shifting as primarily a way to perform arithmetic and, oh, by the way we need a special kind of right shift to do logical stuff. Or do they see shifting as primarily a way to perform logic stuff and, oh by the way we need a special kind of right shift to do arithmetic stuff. I can see someone say that, "for completeness", we need to have both flavors of both types of shifts, even if one of the right shifts ends up being nothing but an alias for the other, on the basis that it aid readability and writability.

Then, too, there's the question of how the instructions interact with the flags, particularly the Carry/Borrow flag and the Overflow flag. I could see wanting different behavior from an arithmetic shift than from a logical shift.
 
Top