InterviewDB Experience

LED Toggle: Implement a Bitfield LED Driver with Toggle, Set, and Clear Operations

Interview Experience

Problem

You are implementing a bare-metal LED driver in C. LEDs are controlled via an 8-bit hardware register where each bit corresponds to one LED (bit 0 = LED0, bit 7 = LED7). Implement functions to set, clear, toggle, and query individual LEDs without affecting others.

c
#include <stdint.h>
#include <stdbool.h>

typedef struct {
    volatile uint8_t reg;  // memory-mapped hardware register
} LedController;

void led_set(LedController* ctrl, uint8_t led_index);
void led_clear(LedController* ctrl, uint8_t led_index);
void led_toggle(LedController* ctrl, uint8_t led_index);
bool led_is_on(const LedController* ctrl, uint8_t led_index);

Example:

// reg initially = 0x00
led_set(ctrl, 3);     // reg = 0x08
led_set(ctrl, 0);     // reg = 0x09
led_toggle(ctrl, 3);  // reg = 0x01
led_is_on(ctrl, 3)    -> false
led_is_on(ctrl, 0)    -> true

Follow-ups

  1. Why is the register declared volatile, and what happens if you omit it with compiler optimizations enabled?
  2. How do you atomically read-modify-write the register on a microcontroller that does not have hardware atomic instructions?
  3. How would you implement a led_set_all(pattern) function that sets all 8 LEDs to a bitmask pattern in a single write?
  4. How would you extend this driver to support a 16-bit register (e.g., two chained shift registers)?

Full Details

Problem

You are implementing a bare-metal LED driver in C. LEDs are controlled via an 8-bit hardware register where each bit corresponds to one LED (bit 0 = LED0, bit 7 = LED7). Implement functions to set, clear, toggle, and query individual LEDs without affecting others.

c
#include <stdint.h>
#include <stdbool.h>

typedef struct {
    volatile uint8_t reg;  // memory-mapped hardware register
} LedController;

void led_set(LedController* ctrl, uint8_t led_index);
void led_clear(LedController* ctrl, uint8_t led_index);
void led_toggle(LedController* ctrl, uint8_t led_index);
bool led_is_on(const LedController* ctrl, uint8_t led_index);

Example:

// reg initially = 0x00
led_set(ctrl, 3);     // reg = 0x08
led_set(ctrl, 0);     // reg = 0x09
led_toggle(ctrl, 3);  // reg = 0x01
led_is_on(ctrl, 3)    -> false
led_is_on(ctrl, 0)    -> true

Follow-ups

  1. Why is the register declared volatile, and what happens if you omit it with compiler optimizations enabled?
  2. How do you atomically read-modify-write the register on a microcontroller that does not have hardware atomic instructions?
  3. How would you implement a led_set_all(pattern) function that sets all 8 LEDs to a bitmask pattern in a single write?
  4. How would you extend this driver to support a 16-bit register (e.g., two chained shift registers)?

About This Question

This is a candidate experience report from a anduril interview during the phone round.

It covers the following topics: Embedded, Coding, Phone, Bit Manipulation .