Siddhant Pradhan
Portfolio

1Tiny PCHardware · PCB · 3D Printing
2Multithreaded PWM Timestamping SystemFirmware · Embedded C · BeagleBone
3Network Topology Analysis & RoutingAlgorithms · Networking · Python
4Microgrid Energy Consumption PredictionMachine Learning · Scikit-Learn
5Timing Side-Channel Attack & DefenseCybersecurity · Python · Raspberry Pi 5
6Video Capture & Image Processing — DE1-SoCFPGA · ARM Cortex-A9 · Embedded Vision
Project 1
Tiny PC
Tiny PC — miniature retro-style desktop with monitor displaying Windows XP Bliss wallpaper

A fully functional miniature PC inspired by the classic computers of the 1990s and early 2000s. Combines 3D printing, custom PCB soldering, and software configuration into a palm-sized retro machine powered by a Raspberry Pi 4.

3D PrintingPCB SolderingCAD / Fusion 360ElectronicsRaspberry PiRetro Design

Design & Build Process


1. Design

Downloaded STL files and studied the layout to plan how all enclosure parts interconnect.

2. 3D Print

Printed all parts at 50-micron resolution using ABS filament for strength and fine detail.

3. Electronics

Soldered SMD components on a custom add-on PCB using a hot plate, including a USB-C port.

4. Display & Audio

Wired a 4-inch Waveshare screen via HDMI and connected speakers with JST-PH connectors.

5. Software

Installed Twister OS and configured screen overlays, GPIO LEDs, and PWM fan control.

6. Assembly

Mounted screen to bezel, secured Pi with heatsink, routed cables, and added rubber feet.

Key Components

Raspberry Pi 4

4" Waveshare Screen

Custom Add-on PCB

PWM Heatsink + Fan

15W USB-C Power Supply

ABS 3D-Printed Enclosure

Twister OS

3D-Printed Parts
CAD render: Tiny PC bottom case
Bottom Case
CAD render: Tiny PC back shell
Back Shell
CAD render: Tiny PC screen base
Screen Base
CAD render: Tiny PC screen core
Screen Core
CAD render: Tiny PC top cover with fan vent
Top Cover
CAD render: Tiny PC front bezel
Front Bezel
Custom PCBs
RPi4 add-on PCB top and bottom views
RPi4 Add-on
MicroSD adapter PCB top and bottom views
MicroSD Adapter
System Architecture
System architecture diagram: Raspberry Pi 4, peripherals, and add-on PCB
Project 2
Multithreaded PWM
Timestamping System
Firmware — BeagleBone Black · Embedded C · pthreads · epoll · GPIO

An event-driven embedded system built on the BeagleBone Black that captures 50 GPIO interrupt timestamps generated by an external PWM signal — without continuous polling. A producer thread waits on epoll for rising-edge interrupts and logs nanosecond timestamps into a mutex-protected shared buffer; a consumer thread writes all 50 records to disk and the terminal on completion.

Embedded CBeagleBone BlackpthreadsepollGPIO interruptsMutexPWMPOSIX
BeagleBone Black with jumper wire on P8/P9 headers and USB power
Terminal: PWM interrupt timestamps and data collection complete
BeagleBone Black — P8/P9 jumper wire connects PWM out to GPIO in
Terminal: 50 timestamped interrupt events captured
System Design

Two POSIX threads share a fixed-size buffer (SIZE=50) protected by a single pthread_mutex_t. The input thread configures P8_09 as a rising-edge GPIO interrupt via the sysfs interface and Linux epoll, then blocks on epoll_wait(). On each interrupt it acquires the mutex, writes clock_gettime(CLOCK_MONOTONIC) and pthread_self() into the buffer, and releases. The output thread sleeps 100ms per iteration until all 50 samples are collected, then writes every record to both stdout and a named text file.

Code Highlight — Interrupt Capture Loop

while (bufferindex < SIZE) {
    epoll_wait(epfd, &ev_wait, 1, -1);        // block — no CPU polling
    clock_gettime(CLOCK_MONOTONIC, &tm);      // nanosecond timestamp
    pthread_mutex_lock(&lock);
    buffer[bufferindex].timestamp = tm;
    buffer[bufferindex].thread_id = pthread_self();
    bufferindex++;
    pthread_mutex_unlock(&lock);
}
Software Stack

LanguageBare-metal C (gcc)
ThreadingPOSIX pthreads — producer / consumer pattern
InterruptLinux epoll + sysfs GPIO edge trigger
Timingclock_gettime(CLOCK_MONOTONIC) — nanosecond resolution
Syncpthread_mutex_t protecting shared buffer writes
Outputfprintf to named file + printf to terminal
Project 3
Network Topology
Analysis & Routing
Algorithms — Python · Dijkstra · BFS/DFS · Prim MST · OSPF Simulation

Graph-based analysis of six real-world Internet Service Provider networks using the RocketFuel dataset. Models router connections and weighted links, implements multiple routing algorithms to simulate OSPF forwarding behaviour, constructs minimum spanning trees, finds minimum-cost forwarding paths, optimises for minimum maximum-weight links, and detects routing loops.

PythonGraph AlgorithmsDijkstraBFS / DFSPrim MSTBellman-FordOSPFRocketFuel Dataset
ISP network topology from RocketFuel dataset: Dijkstra shortest path R1→R2→R3→R4 (cost 16) highlighted in gold
ISP router network — gold path shows Dijkstra shortest-path result (R1→R2→R3→R4, cost 16)
Algorithms Implemented

AlgorithmTaskData Structure
BFSpathExist() — reachability within N hopsQueue + visited set
Prim's MSTbuildMST() — min spanning tree from sourcePriority queue (min-heap)
DijkstrafindPath() — shortest path on MSTPriority queue + relaxation
Bellman-FordfindForwardingPath() — min-cost with cost outDistance + predecessor arrays
Modified DijkstrafindPathMaxWeight() — minimise max edge weightMax-weight tracking per vertex
BFS loop detectcheckLoop() — detect routing loopsVisited set per BFS root
Code Highlight — Dijkstra on MST

def findPath(self, router1, router2):
    start = self.MST.getVertex(router1)
    start.setDistance(0)
    pq.buildHeap([(v.getDistance(), v) for v in self.MST])
    while not pq.isEmpty():
        current = pq.delMin()
        if current == end: break
        for nxt in current.getConnections():
            newDist = current.getDistance() + current.getWeight(nxt)
            if newDist < nxt.getDistance():
                nxt.setDistance(newDist)
                pq.decreaseKey(nxt, newDist)   # O(log n)
Project 4
Microgrid Energy
Consumption Prediction
Machine Learning — Scikit-Learn · Python · Real-World Energy Dataset

A regression-based ML pipeline predicting smart microgrid energy consumption from a 3,449-sample real-world dataset combining weather variables with power generation and consumption readings (Liège smart grid). Engineered time-of-day and cloud-coverage features, trained and compared Linear Regression, Random Forest, and SVM regressors, and applied GridSearchCV with 5-fold cross-validation for hyperparameter tuning.

PythonScikit-LearnRandom ForestSVMGridSearchCVPandasMatplotlib
Bar chart: test RMSE comparison for microgrid energy prediction models (Lin Reg, Random Forest, SVM, GridSearchCV)
Test RMSE comparison — Random Forest achieves best generalisation at 0.0238
Feature Engineering

Converted time column to minutes-since-midnight (continuous numeric feature)

Engineered 'clouds' = max(CD, CM, CU) across three cloud-coverage columns

Dropped correlated/redundant columns (date, time, CD, CM, CU, SNOW) post-analysis

StandardScaler normalisation applied via Scikit-Learn Pipeline before model training

Model Results

ModelTrain RMSETest RMSENotes
Linear Regression0.03680.0343Consistent — no overfitting
Random Forest0.00890.0238Best test generalisation
SVM (linear)0.06620.0660Weakest overall
GridSearchCV (RF tuned)~0.00.0254Near-zero train — overfitting signal
Key Observations

SWD (solar irradiance) and generation show near-linear correlation — strongest predictive feature

Consumption peaks at midday, validating the minutes-since-midnight engineered feature

Random Forest achieves best test RMSE (0.0238) without explicit hyperparameter tuning

GridSearchCV near-zero training RMSE (2.7e-12) confirms overfitting without bootstrap sampling

Project 5
Timing Side-Channel
Attack & Defense
Cybersecurity — Python · Raspberry Pi 5 · Statistical Timing Analysis

Full offensive and defensive timing side-channel study on a Raspberry Pi 5. A vulnerable password-check server leaks timing through early-exit byte comparison. A custom attacker recovers the secret password byte-by-byte using statistical timing measurements. Three mitigation strategies were designed, implemented, and evaluated in a hardened server version.

PythonTiming AttackSide-ChannelUnix SocketsStatistical AnalysisRaspberry Pi 5Trimmed MeanConstant-Time
Terminal output: attacker.py recovering password byte-by-byte; final recovered password b'S3cret!'
Password b'S3cret!' recovered byte-by-byte in 5 trials on Raspberry Pi 5
Plot: timing attack success rate versus trial count
Success rate reaches 100% at trial 5 — Pi's light OS load yields far less timing noise than a laptop
Attack Design

measure(candidate): opens Unix socket, sends candidate, records 120 round-trip times using time.perf_counter_ns(), applies trimmed mean (drop top/bottom 10%) to filter OS scheduling jitter

recover(): builds password byte-by-byte — character with longest average RTT indicates most correct prefix bytes matched so far

100% success at just 5 trials on Raspberry Pi 5 vs. 50+ needed on a standard laptop due to lighter background process load and more predictable scheduling

Mitigation Strategies

DefenseMechanismEffectiveness
Constant-Time ComparisonXOR/OR all bytes regardless of match — no early exitComplete
Fixed Timing PaddingWait until 10ms has elapsed before respondingComplete
Random Delay InjectionAdd random 0–5ms noise after constant-time compareStrong
Project 6
Video Capture &
Image Processing — DE1-SoC
Embedded Systems — ARM Cortex-A9 · Cyclone V FPGA · C · Memory-Mapped I/O

A real-time software image processing system on the Altera DE1-SoC, integrating an ARM Cortex-A9 video pipeline with the FPGA video subsystem to stream, freeze, and process 320×240 RGB565 frames from a D5M camera module displayed on a VGA monitor. All image processing routines were implemented in bare-metal C using memory-mapped I/O from Linux user space.

ARM Cortex-A9Cyclone V FPGABare-Metal Cmmap()MMIOVGAD5M CameraRGB565
Setup
DE1-SoC video pipeline setup: PC connected over USB, DE1-SoC board, D5M camera, VGA monitor
Setup
System Architecture — Design Flow

StageComponentDetails
1D5M Camera ModuleStreams raw 5MP frames via TRDB-D5M interface
2Video-In Clipper (FPGA)Down-samples to 320×240 — QSYS IP core
3Video-In DMA (FPGA)Writes RGB565 frames to on-chip memory
4ARM HPS (C code)Reads frames via mmap() / /dev/mem from user space
5Image Processing (C)Applies selected filter: flip, BW threshold, invert
6Pixel Buffer DMA (FPGA)Sends processed frame to VGA controller
7VGA Controller (FPGA)Displays 320×240 output on external monitor
Image Processing Routines

Vertical Flip

Swap row i with row (H-1-i) across all columns; iterate over half the frame height.

Horizontal Flip

Swap pixel (r,c) with pixel (r, W-1-c) in-place within each row.

B&W Threshold

Convert RGB565 to luminance. Set pixel white if above threshold, black otherwise.

Pixel Inversion

XOR each RGB565 pixel with 0xFFFF to invert all colour channels simultaneously.

Code Highlight — Memory-Mapped Frame Access

// Map FPGA pixel buffer into ARM user-space virtual memory
int fd = open("/dev/mem", O_RDWR | O_SYNC);
volatile uint16_t *pixel_buf = mmap(NULL, BUF_SIZE,
    PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIXEL_BUF_BASE);

// Capture frame — 512-word hardware stride (not 320)
for (int row = 0; row < 240; row++)
    for (int col = 0; col < 320; col++)
        frame[row][col] = pixel_buf[row * 512 + col];
ARM+FPGA
Co-Design