Skip to content

Commit 09712d9

Browse files
committed
Bit ops
1 parent 6cf495e commit 09712d9

File tree

1 file changed

+16
-23
lines changed

1 file changed

+16
-23
lines changed

README.md

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -186,31 +186,24 @@ case). This is done in two steps. First, we must clear the current value of
186186
bits 6-7, because it may hold some value already. Then we must set bits 6-7
187187
to the value we want.
188188

189-
So, first, we must set bit range 6-7 to zero. How do we set
190-
a number of bits to zero? In four steps:
191-
192-
- Get a number that has N contiguous bits set:
193-
- 1 for 1 bit: `0b1`,
194-
- 3 for 2 bits: `0b11`,
195-
- 7 for 3 bits: `0b111`,
196-
- 15 for 4 bits: `0b1111`,
197-
- and so on: generally, for N bits, the number is `2^N - 1`
198-
So, for 2 bits it is number `3`, or `0b00000000000000000000000000000011`
199-
- Shift that number left. If we need to set bits X-Y, then shift on X positions
200-
left. In our case, shift on a 6 positions left: `(3 << 6)`, or
201-
`0b00000000000000000000000011000000`
202-
- Invert the number: turn zeros to ones, and ones to zeroes:
203-
`~(3 << 6)`, or `0xb11111111111111111111111100111111`
204-
- Now, perform a "logical AND" operation of the register with our number. Bits
205-
6-7, AND-ed with 0, will give zero - that's what we want! All other bits,
206-
AND-ed with 1, will retain their current value: `REG &= ~(3 << 6)`. Retaining
207-
values of all other bits is important: we don't want to change other settings
208-
in other bit ranges!
209-
210-
So, in general, if we want to clear bits X-Y (set them to zero), do:
189+
So, first, we must set bit range 6-7 (two bits at position 6) to zero. How do
190+
we set a number of bits to zero? In four steps:
191+
192+
| Action | Expression | Bits (first 12 of 32) |
193+
| - | - | - |
194+
| Get a number with N contiguous bits set: `2^N-1`, N=2 | `3` | `000000000011` |
195+
| Shift that number X positions left | `(3<<6)` | `000011000000` |
196+
| Invert the number: turn zeros to ones, and ones to zeroes | `~(3<<6)` | `111100111111` |
197+
| Logical AND with existing value | `VAL &= ~(3<<6)` | `xxxx00xxxxxx` |
198+
199+
Note that the last operation, logical AND, turns N bits at position X to zero
200+
(because they are ANDed with 0), but retains the value of all other bits
201+
(because they are ANDed with 1). Retaining existing value is important, cause
202+
we don't want to change settings in other bit ranges. So in general, if we want
203+
to clear N bits at position X:
211204

212205
```c
213-
PERIPHERAL->REGISTER &= ~(NUMBER_WITH_N_BITS << X);
206+
PERIPHERAL->REGISTER &= ~((2^N - 1) << X);
214207
```
215208

216209
And, finally, we want to set a given bit range to the value we want. We

0 commit comments

Comments
 (0)