# Bit Manipulation, Registers and volatile — Arduino & Embedded C

Source: https://www.geekswithgeeks.com/en/arduino-embedded-c/registers

> DDRx, PORTx, PINx on the ATmega328P.

## Talking to hardware directly

Peripherals are controlled through **memory-mapped registers**: special addresses where each bit controls or reports something. On the ATmega328P (Arduino Uno R3) each I/O port has three: **DDRx** sets direction (1 = output), **PORTx** sets output level or enables the pull-up on inputs, and **PINx** reads input levels. Uno digital pin 13 is bit 5 of port B (PB5), pins 0-7 are port D and pins 8-13 are PB0-PB5; check your board's pinout. Use bitwise operators: set with `|= (1 << n)`, clear with `&= ~(1 << n)`, toggle with `^=` and test with `&`. Register access is much faster than `digitalWrite` but ties code to one chip. The **`volatile`** qualifier tells the compiler that a variable can change outside normal program flow (hardware registers, or variables shared with an interrupt), so every access must really read or write memory instead of using a cached copy.

## Blink pin 13 with direct register access

Plain embedded C for the ATmega328P at 16 MHz (avr-libc).

```c
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
    DDRB |= (1 << DDB5);          /* PB5 (Uno pin 13) as output */

    for (;;) {
        PORTB ^= (1 << PORTB5);   /* toggle the LED */
        _delay_ms(500);

        if (!(PINB & (1 << PINB0))) {
            /* PB0 (Uno pin 8) reads LOW: e.g. a button to GND with pull-up */
        }
    }
}
```

## Common bit operations

Reusable C macros.

```c
#define BIT_SET(reg, n)    ((reg) |=  (1u << (n)))
#define BIT_CLEAR(reg, n)  ((reg) &= ~(1u << (n)))
#define BIT_TOGGLE(reg, n) ((reg) ^=  (1u << (n)))
#define BIT_READ(reg, n)   (((reg) >> (n)) & 1u)

/* configure PB0 as input with internal pull-up (ATmega328P) */
void button_init(void) {
    BIT_CLEAR(DDRB, DDB0);    /* input */
    BIT_SET(PORTB, PORTB0);   /* PORTx bit on an input = pull-up enabled */
}
```

## Read-modify-write is not atomic

An expression like `PORTB |= mask` reads, modifies and writes. If an interrupt changes the same register in between, an update can be lost. Disable interrupts around such sequences when ISRs touch the same port.

**Quiz:** On the ATmega328P, which register sets whether a pin is an input or an output?

- [x] DDRx
- [ ] PORTx
- [ ] PINx
- [ ] ADCSRA

*Answer:* DDRx. DDR stands for Data Direction Register.
