MidCourse Project — Smart Device Manager (Console
Simulation)
Module: Microcontroller-Based Systems (90 Hours) Author: Ahmed
Ellamie · [Link]@[Link] Scope: Days 01 – 03 (C fundamentals only — no AVR
hardware required) Issued: End of Day 03 — Jul 14, 2026 Due: End of Day 04 — Jul 15, 2026
(midterm slot, see Course_Content_Mapping.md §12) Submission:
09_Student_Submissions/Midterm_Project/<Your_Name>/ Team size:
Individual Environment: Any C99 compiler (GCC / MinGW / VS Code setup from Day 01)
1. Project Overview
You will build a menu-driven console application in C that simulates the control panel of a small
smart-home system. The program manages a registry of virtual devices (lights, fans, heaters,
sensors). Each device keeps its state in a packed 8-bit status register that you manipulate only
with bitwise operations — exactly the way you will drive real AVR
registers (DDRx/PORTx/PINx) starting Day 05.
There is no hardware and no simulator in this project. The goal is to prove, in one program, that
you have full command of everything from Days 01–03:
structs, unions, enums, arrays, pointers, strings
const / static and the other storage classes
sizeof, offsetof, structure padding
bit masks: set / clear / toggle / read, shifting
if/else, switch, ternary, for / while / do-while
function declaration, prototypes, parameter passing, scope, recursion
Think of it as "an embedded firmware without the chip."
2. Learning Objectives → Day Mapping
Day Topic block Where it appears in this
project
01 Primitive & non-primitive types Device_t struct,
DeviceType_t enum,
sample arrays, name strings,
pointers to devices
01 Qualifiers & storage classes const version banner,
static device list private to
the module, static local call
counter
Day Topic block Where it appears in this
project
02 Memory alignment Memory Inspector feature:
sizeof / offsetof report of
Device_t, explain the
padding you find
02 Bitwise operations Status register: SET_BIT,
CLR_BIT, TOGGLE_BIT,
READ_BIT macros — the only
allowed way to touch status
03 Conditions & loops switch-based menu, input
validation, do-while main
loop, for scans over the
registry
03 Functions Every feature is its own
function with a prototype; one
recursive function (sum of
samples)
3. System Description
The program runs an endless menu loop:
=========================================
Smart Device Manager v1.0
=========================================
1) Add device
2) List all devices
3) Power ON / OFF a device (bitwise)
4) Toggle device fault flag (bitwise)
5) Show device status register (binary view)
6) Record sensor sample
7) Sensor statistics (min/max/avg)
8) Memory inspector (sizeof/offsetof)
9) Search device by name
0) Exit
Select >
Devices live in a fixed-size array (MAX_DEVICES) — no dynamic memory — just like on a
microcontroller with 2 KB of SRAM.
The status register (1 byte per device)
Bit 7 6 5 4 3 2 1 0
Meaning reserved reserved reserved reserved LOW_B FAULT ONLINE POWER
AT
Example: a powered, online device with low battery → 0000 1011 = 0x0B.
4. Functional Requirements
ID Requirement
FR-01 The program shall show the menu above and
repeat until the user selects 0 (use a do-while
loop and a switch).
FR-02 The program shall reject invalid menu choices
with a clear message (no crash, no exit).
FR-03 Add device: the user enters a name (max 15
chars) and a type (enum choice). The device gets
an auto-incremented id, status 0x00, and zero
samples.
FR-04 The registry shall hold at most MAX_DEVICES
devices; adding beyond that prints Registry
full!.
FR-05 List devices: print a table — id, name, type (as
text, not a number), POWER and ONLINE state
(as ON/OFF, derived from the status bits).
FR-06 Power ON/OFF: set or clear bit POWER of the
selected device using the bit macros only (no
arithmetic, no hard-coded values like status
= 1).
FR-07 Toggle fault: flip bit FAULT with the toggle
macro.
FR-08 Status view: print the full status byte of a device
in binary (0b00001011 style, 8 digits) and in
hex.
FR-09 Record sample: append a uint16_t reading
(0–1023, like a 10-bit ADC) to the device's
sample array; reject values out of range and a
full buffer.
FR-10 Statistics: for a chosen device print min, max,
and average of its samples. The sum must be
computed by a recursive function.
FR-11 Memory inspector: print
sizeof(Device_t), the offsetof every
struct member, and the number of padding
bytes.
FR-12 Search: find a device by exact name (strcmp)
and print its full details; print Not found.
otherwise.
5. Non-Functional Requirements
ID Requirement
NFR-01 Standard C99 — must compile with gcc -
std=c99 -Wall -Wextra with zero
warnings.
NFR-02 Single file main.c is acceptable; a split into
devices.c/.h earns bonus (see rubric).
NFR-03 No dynamic allocation (malloc family is
forbidden) — fixed-size arrays only.
NFR-04 No magic numbers: every constant is a
#define, enum, or const.
NFR-05 The device array and its counter shall be
static (file scope) — accessed only through
functions, never directly from main.
NFR-06 Every function ≤ 40 lines, one job per function,
prototypes at the top of the file.
NFR-07 All user input must be validated; bad input never
crashes or corrupts the registry.
NFR-08 Fixed-width types from <stdint.h>
(uint8_t, uint16_t) for all device data —
embedded habit starts now.
NFR-09 Meaningful names (deviceCount, not dc),
consistent 4-space indentation, comment every
non-obvious block.
6. Simple Architecture
┌───────────────────────────────────────────────────────────┐
│ main() │
│ do-while menu loop + switch dispatcher │
└──────┬──────────┬──────────────┬───────────────┬──────────┘
│ │ │ │
┌──────▼───┐ ┌────▼─────┐ ┌──────▼───────┐ ┌─────▼────────┐
│ Registry │ │ Status │ │ Sensor │ │ Memory │
│ manager │ │ engine │ │ analytics │ │ inspector │
│ add/list │ │ bit ops │ │ min/max/avg │ │ sizeof / │
│ /search │ │ on flags │ │ (recursion) │ │ offsetof │
└──────┬───┘ └────┬─────┘ └──────┬───────┘ └─────┬────────┘
│ │ │ │
┌──────▼──────────▼──────────────▼───────────────▼──────────┐
│ static Device_t deviceList[MAX_DEVICES] │
│ static uint8_t deviceCount (data store) │
└───────────────────────────────────────────────────────────┘
Registry manager — owns the array: addDevice(), listDevices(),
findByName()
Status engine — the only code allowed to touch status, via bit macros
Sensor analytics — recordSample(), printStats(), recursive sumSamples()
Memory inspector — pure reporting, nothing writes