← Back to track

Print Mode

Quick select
Show fields
Options
Layout
1

Save your content as an A5 PDF first. In the print dialog, choose "Save as PDF".

2

Select the saved PDF below. It will be rearranged into booklet page order and downloaded automatically.

Core Topics

5 sections · 13 topics · 54 concepts

eee-roadmap.muhammadhazimiyusri.uk/roadmaps/core/

Select items from the sidebar to preview them here.

Analog Electronics

Transistors (BJT & MOSFET)

The building blocks of amplification and switching. BJTs are current-controlled, MOSFETs are voltage-controlled. Understanding both lets you choose the right device for your application.

Prerequisites: DC Circuits, Diodes basics
You'll learn to:
  • Bias BJT and MOSFET circuits for linear operation
  • Analyze small-signal amplifier behavior
  • Design basic switching circuits
  • Read transistor datasheets effectively
BJT biasing

BJT biasing establishes the DC operating point (Q-point) for linear amplification. The goal is to set ICI_CIC​ and VCEV_{CE}VCE​ in the active region where the transistor amplifies without distortion.

The Four Operating Regions:

  • Cutoff: Both junctions reverse-biased, IC≈0I_C \approx 0IC​≈0
  • Active: B-E forward, B-C reverse — this is where amplification happens
  • Saturation: Both junctions forward-biased, transistor acts as closed switch
  • Breakdown: Excessive voltage destroys the device

Key Relationships:

IC=βIBI_C = \beta I_BIC​=βIB​

IE=IC+IB=(β+1)IBI_E = I_C + I_B = (\beta + 1)I_BIE​=IC​+IB​=(β+1)IB​

IC=ISeVBE/VTI_C = I_S e^{V_{BE}/V_T}IC​=IS​eVBE​/VT​

where VT≈26mVV_T \approx 26mVVT​≈26mV at room temperature and β\betaβ typically ranges from 50-300.

Common Biasing Configurations:

  • Fixed bias: Simple but unstable — ICI_CIC​ varies wildly with β\betaβ
  • Voltage divider bias: Most common, provides good stability
  • Emitter feedback: Resistor RER_ERE​ stabilizes against β\betaβ variations

Voltage divider bias circuit

The load line on the I-V characteristic shows all possible operating points. Where the load line intersects the base current curve determines the Q-point.

BJT I-V characteristics

Design Rule of Thumb: For voltage divider bias, make the divider current at least 10× the base current to minimize loading effects.

For more depth, see All About Circuits BJT Chapter.

MOSFET operation

MOSFETs are voltage-controlled devices — the gate voltage creates an electric field that modulates channel conductivity. No gate current flows (in DC), giving extremely high input impedance.

Structure and Physics: The gate is insulated from the channel by a thin oxide layer. Applying VGS>VthV_{GS} > V_{th}VGS​>Vth​ creates an inversion layer (channel) between source and drain.

MOSFET cross-section

Operating Regions:

Region Condition Drain Current
Cutoff VGS<VthV_{GS} < V_{th}VGS​<Vth​ ID≈0I_D \approx 0ID​≈0
Linear (Triode) VGS>VthV_{GS} > V_{th}VGS​>Vth​, VDS<VGS−VthV_{DS} < V_{GS} - V_{th}VDS​<VGS​−Vth​ ID=μnCoxWL[(VGS−Vth)VDS−VDS22]I_D = \mu_n C_{ox} \frac{W}{L}\left[(V_{GS}-V_{th})V_{DS} - \frac{V_{DS}^2}{2}\right]ID​=μn​Cox​LW​[(VGS​−Vth​)VDS​−2VDS2​​]
Saturation VGS>VthV_{GS} > V_{th}VGS​>Vth​, VDS≥VGS−VthV_{DS} \geq V_{GS} - V_{th}VDS​≥VGS​−Vth​ ID=12μnCoxWL(VGS−Vth)2I_D = \frac{1}{2}\mu_n C_{ox} \frac{W}{L}(V_{GS}-V_{th})^2ID​=21​μn​Cox​LW​(VGS​−Vth​)2

The Saturation Equation (Square Law):

ID=12μnCoxWL(VGS−Vth)2(1+λVDS)I_D = \frac{1}{2}\mu_n C_{ox} \frac{W}{L}(V_{GS}-V_{th})^2(1 + \lambda V_{DS})ID​=21​μn​Cox​LW​(VGS​−Vth​)2(1+λVDS​)

where λ\lambdaλ is the channel-length modulation parameter.

MOSFET I-V characteristics

Enhancement vs Depletion:

  • Enhancement mode (most common): Channel forms when VGS>VthV_{GS} > V_{th}VGS​>Vth​
  • Depletion mode: Channel exists at VGS=0V_{GS} = 0VGS​=0, removed by negative VGSV_{GS}VGS​

Why MOSFETs Dominate Digital:

  • Near-zero static power (no gate current)
  • Easy to fabricate complementary pairs (CMOS)
  • Scales well with smaller geometries

For switching applications, the goal is to operate fully in cutoff or deep in the linear region (as a closed switch with low $R_{DS(on)}$).

Small-signal models

Small-signal analysis linearizes transistor behavior around the Q-point. We replace the nonlinear device with a linear equivalent circuit valid for small AC variations.

The Hybrid-Pi Model (BJT):

BJT hybrid-pi model

Key parameters:

gm=ICVT≈40⋅IC (at room temp)g_m = \frac{I_C}{V_T} \approx 40 \cdot I_C \text{ (at room temp)}gm​=VT​IC​​≈40⋅IC​ (at room temp)

rπ=βgm=VTIBr_\pi = \frac{\beta}{g_m} = \frac{V_T}{I_B}rπ​=gm​β​=IB​VT​​

ro=VAICr_o = \frac{V_A}{I_C}ro​=IC​VA​​

where VAV_AVA​ is the Early voltage (typically 50-100V).

MOSFET Small-Signal Model:

MOSFET small-signal model

gm=2IDVGS−Vth=2μnCoxWLIDg_m = \frac{2I_D}{V_{GS} - V_{th}} = \sqrt{2\mu_n C_{ox} \frac{W}{L} I_D}gm​=VGS​−Vth​2ID​​=2μn​Cox​LW​ID​​

ro=1λIDr_o = \frac{1}{\lambda I_D}ro​=λID​1​

Using Small-Signal Models:

  1. Find DC operating point (bias analysis)
  2. Replace transistor with small-signal model
  3. Short all DC voltage sources, open DC current sources
  4. Analyze resulting linear circuit

Voltage Gain (Common-Emitter/Source):

Av=−gm(ro∥RL)A_v = -g_m(r_o \| R_L)Av​=−gm​(ro​∥RL​)

The negative sign indicates phase inversion.

Miller Effect: Feedback capacitance CμC_\muCμ​ (or $C_{gd}$) appears multiplied at the input: CMiller=Cμ(1+gmRL)C_{Miller} = C_\mu(1 + g_m R_L)CMiller​=Cμ​(1+gm​RL​). This often dominates high-frequency response.

Saturation vs active region

Understanding operating regions is critical for both amplifier design (stay in active) and switching circuits (transition through regions quickly).

BJT Regions Summary:

Region B-E Junction B-C Junction Use
Cutoff Reverse Reverse OFF switch
Active Forward Reverse Amplification
Saturation Forward Forward ON switch
Reverse Active Reverse Forward Rarely used

Detecting Saturation (BJT): In saturation, VCE(sat)≈0.1−0.3VV_{CE(sat)} \approx 0.1-0.3VVCE(sat)​≈0.1−0.3V regardless of base current. The transistor can't sink more collector current — it's "bottomed out."

IC<βIB (saturated)I_C < \beta I_B \text{ (saturated)}IC​<βIB​ (saturated) IC=βIB (active)I_C = \beta I_B \text{ (active)}IC​=βIB​ (active)

MOSFET Regions:

The "saturation" terminology is confusingly opposite to BJTs:

  • MOSFET saturation = constant current region (used for amplification)
  • MOSFET linear/triode = resistive region (used for switching)

Boundary Condition:

VDS=VGS−Vth (edge of saturation)V_{DS} = V_{GS} - V_{th} \text{ (edge of saturation)}VDS​=VGS​−Vth​ (edge of saturation)

Operating regions on I-V curve

Practical Implications:

  • Amplifiers: Bias in active/saturation region with margin
  • Switches: Drive hard into cutoff or ohmic region
  • Power dissipation: Highest during transitions through active region
Resources:
  • All About Circuits - BJT https://www.allaboutcircuits.com/textbook/semiconductors/chpt-4/bipolar-junction-transistors/
  • All About Circuits - MOSFET https://www.allaboutcircuits.com/textbook/semiconductors/chpt-7/insulated-gate-field-effect-transistors-mosfet/
  • MIT OCW 6.002 https://ocw.mit.edu/courses/6-002-circuits-and-electronics-spring-2007/

Operational Amplifiers

The Swiss Army knife of analog design. Two simple rules (virtual short, no input current) let you build amplifiers, filters, comparators, and more. Master the 741 and its modern successors.

Prerequisites: DC Circuits, AC Circuits
You'll learn to:
  • Design inverting and non-inverting amplifiers
  • Build active filters and integrators
  • Understand op-amp limitations (bandwidth, slew rate)
  • Select appropriate op-amps for specific applications
Virtual short

The "virtual short" is the most powerful concept for analyzing op-amp circuits. With negative feedback, the op-amp adjusts its output to keep both inputs at the same voltage.

The Two Golden Rules (Ideal Op-Amp with Negative Feedback):

  1. Virtual Short: V+=V−V_+ = V_-V+​=V−​ (inputs at same potential)
  2. No Input Current: I+=I−=0I_+ = I_- = 0I+​=I−​=0 (infinite input impedance)

These rules only apply with negative feedback. Open-loop or positive feedback circuits don't obey these rules.

Non-inverting amplifier

Non-Inverting Amplifier Analysis:

  • Virtual short: V−=VinV_- = V_{in}V−​=Vin​
  • No current into V−V_-V−​: voltage divider gives V−=Vout⋅R1R1+RfV_- = V_{out} \cdot \frac{R_1}{R_1 + R_f}V−​=Vout​⋅R1​+Rf​R1​​
  • Therefore: Vin=Vout⋅R1R1+RfV_{in} = V_{out} \cdot \frac{R_1}{R_1 + R_f}Vin​=Vout​⋅R1​+Rf​R1​​

Av=VoutVin=1+RfR1A_v = \frac{V_{out}}{V_{in}} = 1 + \frac{R_f}{R_1}Av​=Vin​Vout​​=1+R1​Rf​​

Inverting amplifier

Inverting Amplifier Analysis:

  • Virtual short: V−=V+=0V_- = V_+ = 0V−​=V+​=0 (virtual ground)
  • Current through RinR_{in}Rin​: I=VinRinI = \frac{V_{in}}{R_{in}}I=Rin​Vin​​
  • Same current through RfR_fRf​ (no current into op-amp)
  • Vout=−I⋅RfV_{out} = -I \cdot R_fVout​=−I⋅Rf​

Av=−RfRinA_v = -\frac{R_f}{R_{in}}Av​=−Rin​Rf​​

Unity gain buffer

The Buffer (Voltage Follower): Av=1A_v = 1Av​=1, but provides high input impedance and low output impedance. Essential for impedance matching between stages.

Gain-bandwidth product

Real op-amps have finite bandwidth. The gain-bandwidth product (GBW) is approximately constant — trading gain for bandwidth.

Single-Pole Model:

A(f)=A01+jffpA(f) = \frac{A_0}{1 + j\frac{f}{f_p}}A(f)=1+jfp​f​A0​​

where A0A_0A0​ is DC open-loop gain (often 100,000+) and fpf_pfp​ is the dominant pole frequency (often just a few Hz).

Gain-bandwidth product

The GBW Relationship:

GBW=Aclosed×f−3dB=constantGBW = A_{closed} \times f_{-3dB} = \text{constant}GBW=Aclosed​×f−3dB​=constant

For a 741 with GBW = 1 MHz:

  • Gain of 1 → Bandwidth = 1 MHz
  • Gain of 10 → Bandwidth = 100 kHz
  • Gain of 100 → Bandwidth = 10 kHz

Unity-Gain Frequency ($f_T$): The frequency where open-loop gain drops to 1 (0 dB). This equals GBW for single-pole systems.

Practical Implications:

  • High-gain stages have limited bandwidth
  • Cascade multiple low-gain stages for high gain with good bandwidth
  • Modern op-amps: GBW from 1 MHz (general purpose) to 1 GHz+ (high-speed)

Slew Rate Limitation: Large signals can't change faster than the slew rate (V/μs):

fmax=SR2πVpeakf_{max} = \frac{SR}{2\pi V_{peak}}fmax​=2πVpeak​SR​

A 741 with SR = 0.5 V/μs can only output a 10V peak sine up to ~8 kHz.

Feedback

Feedback is the foundation of op-amp circuits. Negative feedback trades gain for improved performance in almost every other metric.

Negative Feedback Benefits:

  • Reduced distortion
  • Increased bandwidth
  • Stabilized gain (depends on passive components, not op-amp)
  • Reduced output impedance
  • Reduced sensitivity to component variations

Feedback block diagram

Closed-Loop Gain:

Af=A1+AβA_f = \frac{A}{1 + A\beta}Af​=1+AβA​

where AAA is open-loop gain and β\betaβ is the feedback fraction.

For large loop gain ($A\beta >> 1$):

Af≈1βA_f \approx \frac{1}{\beta}Af​≈β1​

This is why op-amp gain depends only on resistor ratios!

The Four Feedback Topologies:

Topology Samples Returns Effect
Series-Shunt Voltage Voltage Voltage amplifier
Shunt-Series Current Current Current amplifier
Series-Series Voltage Current Transconductance
Shunt-Shunt Current Voltage Transimpedance

Stability Concern: Negative feedback can become positive at high frequencies due to phase shift, causing oscillation. The op-amp's internal compensation prevents this for most applications.

Loop Gain: T=AβT = A\betaT=Aβ determines stability margin and how well the virtual short approximation holds.

Comparators

Comparators are op-amps used without negative feedback (or with positive feedback for hysteresis). They output a digital-like high or low based on which input is larger.

Basic Comparator:

Vout={Vhighif V+>V−Vlowif V+<V−V_{out} = \begin{cases} V_{high} & \text{if } V_+ > V_- \\ V_{low} & \text{if } V_+ < V_- \end{cases}Vout​={Vhigh​Vlow​​if V+​>V−​if V+​<V−​​

The Problem with Simple Comparators: Noise near the threshold causes rapid oscillation (chatter) as the input crosses back and forth.

Schmitt trigger

Schmitt Trigger (Comparator with Hysteresis): Positive feedback creates two different thresholds — one for rising inputs, one for falling.

Hysteresis curve

Hysteresis Thresholds:

VTH=VrefR1R1+R2+VsatR2R1+R2V_{TH} = V_{ref}\frac{R_1}{R_1+R_2} + V_{sat}\frac{R_2}{R_1+R_2}VTH​=Vref​R1​+R2​R1​​+Vsat​R1​+R2​R2​​

VTL=VrefR1R1+R2−VsatR2R1+R2V_{TL} = V_{ref}\frac{R_1}{R_1+R_2} - V_{sat}\frac{R_2}{R_1+R_2}VTL​=Vref​R1​+R2​R1​​−Vsat​R1​+R2​R2​​

Hysteresis width: ΔV=VTH−VTL\Delta V = V_{TH} - V_{TL}ΔV=VTH​−VTL​

Dedicated Comparator ICs vs Op-Amps:

  • Comparators: Faster (ns), open-collector outputs, no compensation
  • Op-amps: Slower in open-loop, may oscillate, but work in a pinch

Applications:

  • Zero-crossing detectors
  • Window comparators (in-range detection)
  • PWM generation
  • ADC building blocks
Resources:
  • Electronics Tutorials - Op-amps https://www.electronics-tutorials.ws/opamp/opamp_1.html
  • All About Circuits - Op-amps https://www.allaboutcircuits.com/textbook/semiconductors/chpt-8/introduction-operational-amplifiers/
  • TI Op-Amp Basics https://www.ti.com/lit/eb/sloa011b/sloa011b.pdf

Analog Filters optional

Shape the frequency content of signals. Low-pass removes noise, high-pass blocks DC, band-pass selects specific frequencies. Active filters with op-amps give you gain plus filtering.

Prerequisites: AC Circuits, Op-amps basics
You'll learn to:
  • Design passive RC and RLC filters
  • Build active filters using op-amps
  • Analyze filter frequency response using Bode plots
  • Choose appropriate filter topology for application
Cutoff frequency

The cutoff frequency ($f_c$) marks where the filter begins to attenuate. Defined as the -3dB point where output power is half the passband value.

RC Low-Pass Filter:

fc=12πRCf_c = \frac{1}{2\pi RC}fc​=2πRC1​

RC low-pass filter

At fcf_cfc​: ∣H(jωc)∣=12≈0.707|H(j\omega_c)| = \frac{1}{\sqrt{2}} \approx 0.707∣H(jωc​)∣=2​1​≈0.707 (-3dB)

Transfer Function (1st Order Low-Pass):

H(s)=11+sRC=11+s/ωcH(s) = \frac{1}{1 + sRC} = \frac{1}{1 + s/\omega_c}H(s)=1+sRC1​=1+s/ωc​1​

Roll-off

Roll-off describes how quickly a filter attenuates beyond cutoff. Measured in dB per decade (10× frequency) or dB per octave (2×).

First-Order Filter: -20 dB/decade = -6 dB/octave

nth-Order Filter: −20n-20n−20n dB/decade

Higher order = sharper transition but more complexity and potential for instability.

Why It Matters: A 1st-order filter at 1 kHz only attenuates a 10 kHz signal by 20 dB. A 4th-order filter achieves 80 dB — much better noise rejection.

Butterworth vs Chebyshev

Filter design involves tradeoffs between passband flatness, transition sharpness, and phase response.

Butterworth (Maximally Flat):

∣H(jω)∣2=11+(ω/ωc)2n|H(j\omega)|^2 = \frac{1}{1+(\omega/\omega_c)^{2n}}∣H(jω)∣2=1+(ω/ωc​)2n1​

  • Flattest possible passband
  • Moderate roll-off
  • Good all-around choice

Chebyshev Type I (Equiripple Passband):

  • Ripple in passband (you choose how much)
  • Sharper roll-off than Butterworth
  • More ringing in step response

Chebyshev Type II (Equiripple Stopband):

  • Flat passband
  • Ripple in stopband
  • Sharp roll-off

Butterworth Bode plot

Selection Guide:

  • Need flat passband? → Butterworth
  • Need sharp cutoff? → Chebyshev
  • Need linear phase? → Bessel (not covered here)
Bode plots

Bode plots show magnitude and phase vs. frequency on logarithmic scales. Essential for understanding and designing filters.

Magnitude Plot:

∣H∣dB=20log⁡10∣H(jω)∣|H|_{dB} = 20\log_{10}|H(j\omega)|∣H∣dB​=20log10​∣H(jω)∣

Phase Plot:

∠H(jω)=arctan⁡(Im(H)Re(H))\angle H(j\omega) = \arctan\left(\frac{\text{Im}(H)}{\text{Re}(H)}\right)∠H(jω)=arctan(Re(H)Im(H)​)

Bode plot example

Sketching Rules (1st Order):

  • Below fcf_cfc​: flat at 0 dB
  • Above fcf_cfc​: -20 dB/decade slope
  • At fcf_cfc​: -3 dB, phase = -45°
  • Phase goes from 0° to -90° over ~2 decades centered at fcf_cfc​

Combining Stages:

  • Magnitude: add dB values
  • Phase: add angles
  • Cascaded filters multiply transfer functions
Resources:
  • Electronics Tutorials - Filters https://www.electronics-tutorials.ws/filter/filter_1.html
  • All About Circuits - Filters https://www.allaboutcircuits.com/textbook/alternating-current/chpt-8/what-is-a-filter/

Digital Logic Design

Boolean Algebra & Logic Gates

The mathematics of digital systems. AND, OR, NOT gates combine to implement any logical function. Boolean algebra lets you simplify and optimize circuits before building them.

Prerequisites: Basic algebra
You'll learn to:
  • Simplify Boolean expressions using algebra and K-maps
  • Convert between truth tables and gate circuits
  • Implement functions using NAND/NOR as universal gates
  • Understand gate propagation delay
Truth tables

Truth tables exhaustively list all input combinations and their outputs. They're the starting point for designing any combinational logic circuit.

Basic Gate Truth Tables:

A B AND OR NAND NOR XOR XNOR
0 0 0 0 1 1 0 1
0 1 0 1 1 0 1 0
1 0 0 1 1 0 1 0
1 1 1 1 0 0 0 1

Logic gate symbols

Boolean Expressions from Truth Tables:

  1. Find all rows where output = 1
  2. Write a product (AND) term for each row
  3. Sum (OR) all product terms together

This gives the Sum of Products (SOP) form.

Example: F=AˉBˉC+AˉBC+ABCˉ+ABCF = \bar{A}\bar{B}C + \bar{A}BC + AB\bar{C} + ABCF=AˉBˉC+AˉBC+ABCˉ+ABC

Minterms and Maxterms:

  • Minterm: AND of all variables (complemented or not) that produces 1
  • Maxterm: OR of all variables that produces 0
  • F=∑m(1,3,5,7)F = \sum m(1,3,5,7)F=∑m(1,3,5,7) means F=1 for minterms 1,3,5,7

For a deeper dive, see All About Circuits - Boolean Algebra.

K-maps

Karnaugh maps provide a visual method for simplifying Boolean expressions. Adjacent cells differ by exactly one variable, enabling easy grouping.

2-Variable K-map:

      B=0  B=1
A=0 |  0  |  1  |
A=1 |  2  |  3  |

3-Variable K-map:

       BC=00  BC=01  BC=11  BC=10
A=0  |   0  |   1  |   3  |   2  |
A=1  |   4  |   5  |   7  |   6  |

Note the Gray code ordering: 00, 01, 11, 10 (only one bit changes).

K-map with groupings

Simplification Rules:

  1. Group adjacent 1s in powers of 2 (1, 2, 4, 8...)
  2. Groups can wrap around edges (the map is a torus!)
  3. Make groups as large as possible
  4. Cover all 1s with minimum number of groups
  5. Each group becomes one product term

Reading Groups:

  • Variables that don't change across the group → include in term
  • Variables that do change → eliminate from term

A group of 2k2^k2k cells eliminates kkk variables.

K-map torus topology

Don't Cares (X): Can be treated as 0 or 1 — choose whichever gives larger groups. Common in BCD circuits where codes 10-15 are unused.

De Morgan's theorem

De Morgan's theorems let you convert between AND/OR operations and push inversions through expressions. Essential for NAND/NOR implementations.

The Two Theorems:

A+B‾=Aˉ⋅Bˉ\overline{A + B} = \bar{A} \cdot \bar{B}A+B​=Aˉ⋅Bˉ

A⋅B‾=Aˉ+Bˉ\overline{A \cdot B} = \bar{A} + \bar{B}A⋅B=Aˉ+Bˉ

In words:

  • NOT(OR) = AND of NOTs → "break the bar, change the sign"
  • NOT(AND) = OR of NOTs

De Morgan gate equivalents

Bubble Pushing: A visual technique using De Morgan's theorems:

  • Push bubbles through a gate, changing AND↔OR
  • Bubbles on both sides of a gate cancel

Generalized Form:

A1+A2+...+An‾=A1ˉ⋅A2ˉ⋅...⋅Anˉ\overline{A_1 + A_2 + ... + A_n} = \bar{A_1} \cdot \bar{A_2} \cdot ... \cdot \bar{A_n}A1​+A2​+...+An​​=A1​ˉ​⋅A2​ˉ​⋅...⋅An​ˉ​

A1⋅A2⋅...⋅An‾=A1ˉ+A2ˉ+...+Anˉ\overline{A_1 \cdot A_2 \cdot ... \cdot A_n} = \bar{A_1} + \bar{A_2} + ... + \bar{A_n}A1​⋅A2​⋅...⋅An​​=A1​ˉ​+A2​ˉ​+...+An​ˉ​

Practical Application: Convert SOP to use only NAND gates:

  1. Start with F=AB+CDF = AB + CDF=AB+CD
  2. Double invert: F=AB+CD‾‾F = \overline{\overline{AB + CD}}F=AB+CD​​
  3. Apply De Morgan: F=AB‾⋅CD‾‾F = \overline{\overline{AB} \cdot \overline{CD}}F=AB⋅CD
  4. Result: NAND of NANDs!
Universal gates

NAND and NOR gates are "universal" — any Boolean function can be built using only NAND gates or only NOR gates. This simplifies manufacturing.

Why Universal? If you can make NOT, AND, and OR from a single gate type, you can build anything. Both NAND and NOR can do this.

Building Blocks from NAND:

NOT from NAND

  • NOT: Connect both inputs together: Aˉ=A⋅A‾\bar{A} = \overline{A \cdot A}Aˉ=A⋅A
  • AND: NAND followed by NOT: AB=AB‾‾AB = \overline{\overline{AB}}AB=AB
  • OR: NOT inputs, then NAND: A+B=Aˉ⋅Bˉ‾A+B = \overline{\bar{A} \cdot \bar{B}}A+B=Aˉ⋅Bˉ

AND from NAND

OR from NAND

Building Blocks from NOR:

  • NOT: Aˉ=A+A‾\bar{A} = \overline{A + A}Aˉ=A+A​
  • OR: NOR followed by NOT
  • AND: NOT inputs, then NOR

AND from NOR

Why NAND Dominates: In CMOS, NAND gates are faster and smaller than NOR gates because NMOS transistors (in series for NAND) are faster than PMOS.

Gate Count Optimization: Direct NAND/NOR implementation often uses fewer transistors than converting from AND/OR/NOT. Modern synthesis tools handle this automatically.

Resources:
  • Neso Academy Digital Electronics https://www.nesoacademy.org/ee/05-digital-electronics
  • All About Circuits - Boolean https://www.allaboutcircuits.com/textbook/digital/chpt-7/introduction-boolean-algebra/

Combinational Circuits

Outputs depend only on current inputs — no memory. Multiplexers route signals, decoders select devices, adders do arithmetic. These blocks combine to build ALUs and more.

Prerequisites: Boolean Algebra & Logic Gates
You'll learn to:
  • Design multiplexers and demultiplexers
  • Build encoders, decoders, and priority encoders
  • Implement binary adders and subtractors
  • Use ROMs and PLAs for function implementation
Mux/Demux

Multiplexers (MUX) select one of many inputs to pass to the output. Demultiplexers (DEMUX) route one input to one of many outputs.

2:1 Multiplexer:

Y=Sˉ⋅I0+S⋅I1Y = \bar{S} \cdot I_0 + S \cdot I_1Y=Sˉ⋅I0​+S⋅I1​

When S=0, Y=I₀. When S=1, Y=I₁.

2-to-1 MUX

General MUX:

  • nnn select lines → 2n2^n2n data inputs
  • 4:1 MUX has 2 select lines, 4 data inputs
  • 8:1 MUX has 3 select lines, 8 data inputs

4-to-1 MUX

MUX as Universal Logic: Any n-variable function can be implemented with a 2n2^n2n:1 MUX:

  • Connect variables to select lines
  • Connect 0, 1, or variable to data inputs based on truth table

Demultiplexer (1:n DEMUX): Routes single input to one of 2n2^n2n outputs based on select lines. Often combined with decoder functionality.

Demultiplexer

Applications:

  • Data routing in buses
  • Time-division multiplexing
  • Memory address decoding
  • Function generators
Encoders/Decoders

Encoders compress information (many inputs → few outputs). Decoders expand it (few inputs → many outputs).

Binary Encoder (2ⁿ:n): Converts one-hot input to binary code.

  • 8:3 encoder: 8 inputs, 3-bit binary output
  • Only one input should be active at a time

Priority Encoder: Handles multiple active inputs by encoding the highest-priority one. Also outputs a "valid" signal indicating at least one input is active.

Binary Decoder (n:2ⁿ): Activates exactly one of 2n2^n2n outputs based on n-bit input.

A₁ A₀ Y₃ Y₂ Y₁ Y₀
0 0 0 0 0 1
0 1 0 0 1 0
1 0 0 1 0 0
1 1 1 0 0 0

Decoder circuit

7-Segment Decoder: Converts 4-bit BCD to 7 outputs for display segments.

7-segment display

Applications:

  • Memory chip select (address decoding)
  • Instruction decoding in CPUs
  • Keyboard encoding
  • Display drivers
Adders

Binary adders are the foundation of arithmetic logic units. Built from simple gates, they perform the addition we take for granted.

Half Adder: Adds two 1-bit numbers, produces Sum and Carry.

Sum=A⊕BSum = A \oplus BSum=A⊕B Carry=A⋅BCarry = A \cdot BCarry=A⋅B

Half adder circuit

Full Adder: Adds three 1-bit numbers (A, B, and Carry-in).

Sum=A⊕B⊕CinSum = A \oplus B \oplus C_{in}Sum=A⊕B⊕Cin​ Cout=AB+Cin(A⊕B)C_{out} = AB + C_{in}(A \oplus B)Cout​=AB+Cin​(A⊕B)

Full adder logic diagram

Ripple Carry Adder: Chain full adders together — carry ripples from LSB to MSB.

Ripple carry adder

The Propagation Delay Problem: For n-bit addition, worst case is n × (full adder delay). A 32-bit ripple adder is slow!

Full adder propagation delay

Faster Adders:

  • Carry Lookahead (CLA): Compute carries in parallel using Generate ($G = AB$) and Propagate ($P = A \oplus B$) signals
  • Carry Select: Compute both possibilities, select when carry arrives
  • Carry Skip: Skip over blocks that propagate

Subtraction: Use 2's complement: A−B=A+Bˉ+1A - B = A + \bar{B} + 1A−B=A+Bˉ+1 Invert B, set carry-in to 1.

Comparators

Magnitude comparators determine the relationship between two binary numbers: A > B, A = B, or A < B.

1-Bit Comparator:

A>B:ABˉA > B: A\bar{B}A>B:ABˉ A=B:A⊕B‾=A⊙BA = B: \overline{A \oplus B} = A \odot BA=B:A⊕B​=A⊙B A<B:AˉBA < B: \bar{A}BA<B:AˉB

n-Bit Comparator: Compare bit-by-bit from MSB to LSB. First unequal bit determines result.

Magnitude comparator

Cascading Comparators: For wider comparisons, chain comparator ICs (like 74HC85). Each stage has A>B, A=B, A<B inputs from the previous stage.

4-bit comparator extension

Equality Comparator (Simpler): Just check if A XOR B = 0 for each bit position, then AND all results.

A=B:∏i=0n−1(Ai⊙Bi)A = B: \prod_{i=0}^{n-1}(A_i \odot B_i)A=B:i=0∏n−1​(Ai​⊙Bi​)

Applications:

  • Address matching in networking
  • Branch conditions in CPUs
  • Window comparators (range checking)
  • Sorting networks
Resources:
  • Neso Academy - Combinational https://www.nesoacademy.org/ee/05-digital-electronics
  • GeeksforGeeks Digital Logic https://www.geeksforgeeks.org/digital-electronics-logic-design-tutorials/

Sequential Circuits

Circuits with memory — outputs depend on current inputs AND past history. Flip-flops store bits, registers hold bytes, counters sequence through states. The basis of all digital systems.

Prerequisites: Combinational Circuits
You'll learn to:
  • Design circuits using SR, D, JK, and T flip-flops
  • Build counters (synchronous and asynchronous)
  • Design finite state machines
  • Analyze timing diagrams and setup/hold violations
Flip-flops

Flip-flops are bistable circuits that store one bit. They're the fundamental building blocks of all sequential logic.

SR (Set-Reset) Flip-Flop: The simplest memory element, but has a forbidden state.

S R Q⁺ Action
0 0 Q Hold
0 1 0 Reset
1 0 1 Set
1 1 ? Forbidden

SR flip-flop using NOR gates

D (Data) Flip-Flop: The most commonly used type. Output follows input on clock edge.

Q+=DQ^+ = DQ+=D

D flip-flop symbol

JK Flip-Flop: Like SR but with no forbidden state. J=K=1 toggles the output.

Q+=JQˉ+KˉQQ^+ = J\bar{Q} + \bar{K}QQ+=JQˉ​+KˉQ

J K Q⁺ Action
0 0 Q Hold
0 1 0 Reset
1 0 1 Set
1 1 Q̄ Toggle

JK flip-flop

T (Toggle) Flip-Flop: Toggles on each clock when T=1. Perfect for counters.

Q+=T⊕QQ^+ = T \oplus QQ+=T⊕Q

T flip-flop

Edge Triggering: Modern flip-flops are edge-triggered (positive or negative edge), not level-triggered. This prevents transparency issues.

Timing Parameters:

  • Setup time ($t_{su}$): Data must be stable before clock edge
  • Hold time ($t_h$): Data must remain stable after clock edge
  • Propagation delay ($t_{pd}$): Clock edge to output change
Registers

Registers are groups of flip-flops that store multi-bit values. They can load, hold, or shift data.

Parallel Load Register: All bits loaded simultaneously on clock edge when LOAD=1.

Shift Register: Data shifts one position per clock cycle.

Shift register

Shift Register Types:

  • SISO: Serial In, Serial Out — delay line
  • SIPO: Serial In, Parallel Out — serial to parallel converter
  • PISO: Parallel In, Serial Out — parallel to serial converter
  • PIPO: Parallel In, Parallel Out — standard register

Bidirectional shift register

Universal Shift Register: Can shift left, shift right, parallel load, or hold. Mode select inputs choose the operation.

Applications:

  • Serial communication (UART)
  • LED displays (driving many LEDs with few pins)
  • Pseudo-random number generators (LFSR)
  • Digital delay lines

Ring Counter: Shift register with output fed back to input. Circulates a single 1 (or 0) through the stages.

Counters

Counters sequence through a series of states, typically counting up or down in binary.

Asynchronous (Ripple) Counter: Each flip-flop is clocked by the previous stage's output. Simple but slow — delays accumulate.

Synchronous Counter: All flip-flops share the same clock. Faster, more reliable.

Synchronous up counter

Binary Up Counter Design:

  • LSB (Q₀) toggles every clock
  • Q₁ toggles when Q₀=1
  • Q₂ toggles when Q₁Q₀=11
  • Pattern: Qₙ toggles when all lower bits are 1

Modulo-N Counter: Counts from 0 to N-1, then wraps. A mod-10 counter counts 0-9. Use additional logic to detect N and reset.

Synchronous down counter

Up/Down Counter: Direction control input selects counting direction. Changes the feedback logic.

Counter ICs:

  • 74HC161: 4-bit synchronous binary
  • 74HC190: Decade up/down
  • 74HC4520: Dual 4-bit binary

Applications:

  • Frequency division
  • Event counting
  • Timer/PWM generation
  • Address generation for memory
State machines

Finite State Machines (FSMs) are the general model for sequential circuits. They consist of states, transitions, and outputs.

Moore Machine: Outputs depend only on current state. More stable outputs (change only on clock edges).

Moore machine example

Mealy Machine: Outputs depend on current state AND inputs. Faster response but outputs can glitch.

Mealy machine example

FSM Design Process:

  1. Define states and state diagram
  2. Create state transition table
  3. Choose state encoding (binary, one-hot, Gray)
  4. Derive next-state logic (K-maps or equations)
  5. Derive output logic
  6. Implement with flip-flops and gates

FSM block diagram

State Encoding:

  • Binary: Minimum flip-flops, complex logic
  • One-Hot: One flip-flop per state, simple logic, more FFs
  • Gray Code: Only one bit changes per transition, reduces glitches

Example: Traffic Light Controller States: Green→Yellow→Red→Green... Inputs: Timer, sensor Outputs: Light signals

Avoiding Common Pitfalls:

  • Initialize to a known state (reset)
  • Handle unused states (don't let FSM get stuck)
  • Watch for asynchronous input synchronization
Resources:
  • Neso Academy - Sequential https://www.nesoacademy.org/ee/05-digital-electronics
  • Ben Eater - 8-bit Computer https://eater.net/

Signals & Systems

Signal Fundamentals

The language of information. Continuous vs discrete, periodic vs aperiodic, energy vs power signals. Understanding signal properties is essential before analyzing how systems process them.

Prerequisites: Calculus, Complex numbers
You'll learn to:
  • Classify signals by their properties
  • Perform basic signal operations (scaling, shifting)
  • Understand even/odd decomposition
  • Work with unit impulse and step functions
Continuous vs discrete

Signals come in two fundamental flavors based on their independent variable (usually time).

Continuous-Time (CT) Signals: Defined for all real values of ttt: x(t),t∈Rx(t), \quad t \in \mathbb{R}x(t),t∈R

Examples: voltage from a microphone, temperature sensor output

Discrete-Time (DT) Signals: Defined only at integer indices: x[n],n∈Zx[n], \quad n \in \mathbb{Z}x[n],n∈Z

Examples: sampled audio, digital sensor readings

Discrete signal representation

Sampling Relationship:

x[n]=x(nTs)x[n] = x(nT_s)x[n]=x(nTs​)

where TsT_sTs​ is the sampling period and fs=1/Tsf_s = 1/T_sfs​=1/Ts​ is the sampling frequency.

Sampling process

Nyquist Theorem: To perfectly reconstruct a signal, sample at least twice the highest frequency:

fs>2fmaxf_s > 2f_{max}fs​>2fmax​

Violating this causes aliasing — high frequencies masquerade as low frequencies.

Analog vs Digital:

  • Analog: continuous time AND continuous amplitude
  • Digital: discrete time AND quantized amplitude
  • Sampled: discrete time, continuous amplitude (theoretical)

Why Discrete Matters: All modern signal processing is digital. Understanding both domains and how they relate is essential.

Periodic signals

A signal is periodic if it repeats exactly after some period TTT (CT) or NNN (DT).

Continuous-Time Periodic:

x(t)=x(t+T) for all tx(t) = x(t + T) \text{ for all } tx(t)=x(t+T) for all t

The fundamental frequency is f0=1/Tf_0 = 1/Tf0​=1/T or ω0=2π/T\omega_0 = 2\pi/Tω0​=2π/T.

Discrete-Time Periodic:

x[n]=x[n+N] for all nx[n] = x[n + N] \text{ for all } nx[n]=x[n+N] for all n

NNN must be a positive integer.

Common waveforms

Common Periodic Signals:

Sinusoid: x(t)=Asin⁡(2πf0t+ϕ)=Asin⁡(ω0t+ϕ)x(t) = A\sin(2\pi f_0 t + \phi) = A\sin(\omega_0 t + \phi)x(t)=Asin(2πf0​t+ϕ)=Asin(ω0​t+ϕ)

Square Wave (Fourier Series): x(t)=4π∑n=1,3,5...∞1nsin⁡(nω0t)x(t) = \frac{4}{\pi}\sum_{n=1,3,5...}^{\infty}\frac{1}{n}\sin(n\omega_0 t)x(t)=π4​n=1,3,5...∑∞​n1​sin(nω0​t)

Triangle Wave: x(t)=8π2∑n=1,3,5...∞(−1)(n−1)/2n2sin⁡(nω0t)x(t) = \frac{8}{\pi^2}\sum_{n=1,3,5...}^{\infty}\frac{(-1)^{(n-1)/2}}{n^2}\sin(n\omega_0 t)x(t)=π28​n=1,3,5...∑∞​n2(−1)(n−1)/2​sin(nω0​t)

Sawtooth Wave: x(t)=2π∑n=1∞(−1)n+1nsin⁡(nω0t)x(t) = \frac{2}{\pi}\sum_{n=1}^{\infty}\frac{(-1)^{n+1}}{n}\sin(n\omega_0 t)x(t)=π2​n=1∑∞​n(−1)n+1​sin(nω0​t)

DT Periodicity Subtlety: Not all sinusoids are periodic in discrete time! $x[n] = \cos(\omega_0 n)$ is periodic only if ω0/(2π)\omega_0/(2\pi)ω0​/(2π) is rational.

Energy vs Power Signals:

  • Energy signal: finite total energy, zero average power (transients)
  • Power signal: infinite energy, finite average power (periodic signals)
Impulse function

The impulse (Dirac delta) is a mathematical idealization — infinite height, zero width, unit area. It's the foundation of linear systems theory.

Continuous-Time Impulse δ(t)\delta(t)δ(t):

δ(t)=0 for t≠0\delta(t) = 0 \text{ for } t \neq 0δ(t)=0 for t=0

∫−∞∞δ(t) dt=1\int_{-\infty}^{\infty} \delta(t) \, dt = 1∫−∞∞​δ(t)dt=1

Dirac delta function

Sifting Property (Most Important!):

∫−∞∞f(t)δ(t−t0) dt=f(t0)\int_{-\infty}^{\infty} f(t)\delta(t-t_0) \, dt = f(t_0)∫−∞∞​f(t)δ(t−t0​)dt=f(t0​)

The impulse "picks out" the function value at t0t_0t0​.

Discrete-Time Impulse δ[n]\delta[n]δ[n]:

δ[n]={1,n=00,n≠0\delta[n] = \begin{cases} 1, & n=0 \\ 0, & n \neq 0 \end{cases}δ[n]={1,0,​n=0n=0​

Much simpler than the CT version — just a sample of height 1 at n=0.

Unit Step Function:

u(t)={1,t≥00,t<0u(t) = \begin{cases} 1, & t \geq 0 \\ 0, & t < 0 \end{cases}u(t)={1,0,​t≥0t<0​

u[n]={1,n≥00,n<0u[n] = \begin{cases} 1, & n \geq 0 \\ 0, & n < 0 \end{cases}u[n]={1,0,​n≥0n<0​

Relationship:

ddtu(t)=δ(t)\frac{d}{dt}u(t) = \delta(t)dtd​u(t)=δ(t)

u(t)=∫−∞tδ(τ) dτu(t) = \int_{-\infty}^{t} \delta(\tau) \, d\tauu(t)=∫−∞t​δ(τ)dτ

For discrete: δ[n]=u[n]−u[n−1]\delta[n] = u[n] - u[n-1]δ[n]=u[n]−u[n−1]

Why Impulses Matter: The impulse response h(t)h(t)h(t) completely characterizes an LTI system. Any input can be decomposed into weighted, shifted impulses.

Convolution

Convolution is THE fundamental operation for linear time-invariant (LTI) systems. If you know the impulse response, you can find the output for any input.

Continuous-Time Convolution:

y(t)=x(t)∗h(t)=∫−∞∞x(τ)h(t−τ) dτy(t) = x(t) * h(t) = \int_{-\infty}^{\infty} x(\tau)h(t-\tau) \, d\tauy(t)=x(t)∗h(t)=∫−∞∞​x(τ)h(t−τ)dτ

Discrete-Time Convolution:

y[n]=x[n]∗h[n]=∑k=−∞∞x[k]h[n−k]y[n] = x[n] * h[n] = \sum_{k=-\infty}^{\infty} x[k]h[n-k]y[n]=x[n]∗h[n]=k=−∞∑∞​x[k]h[n−k]

Convolution animation

Graphical Convolution Steps:

  1. Flip h(τ)h(\tau)h(τ) to get h(−τ)h(-\tau)h(−τ)
  2. Shift by ttt to get h(t−τ)h(t-\tau)h(t−τ)
  3. Multiply x(τ)⋅h(t−τ)x(\tau) \cdot h(t-\tau)x(τ)⋅h(t−τ)
  4. Integrate (sum) the product
  5. Repeat for all values of ttt

Convolution diagram

Key Properties:

Property Expression
Commutative x∗h=h∗xx * h = h * xx∗h=h∗x
Associative (x∗h1)∗h2=x∗(h1∗h2)(x * h_1) * h_2 = x * (h_1 * h_2)(x∗h1​)∗h2​=x∗(h1​∗h2​)
Distributive x∗(h1+h2)=x∗h1+x∗h2x * (h_1 + h_2) = x*h_1 + x*h_2x∗(h1​+h2​)=x∗h1​+x∗h2​
Identity x∗δ=xx * \delta = xx∗δ=x

The Frequency Domain Shortcut:

F{x∗h}=X(ω)⋅H(ω)\mathcal{F}\{x * h\} = X(\omega) \cdot H(\omega)F{x∗h}=X(ω)⋅H(ω)

Convolution in time = multiplication in frequency! This is why we use Fourier transforms.

Practical Interpretation:

  • Convolution with impulse response = filtering
  • Convolution with rectangular pulse = moving average
  • Convolution with Gaussian = smoothing/blurring

For detailed examples, see the DSPGuide Convolution Chapter.

Resources:
  • MIT OCW 6.003 https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/
  • Neso Academy - Signals https://www.nesoacademy.org/ee/04-signals-and-systems

Fourier Analysis

Any signal can be decomposed into sinusoids. Fourier series for periodic signals, Fourier transform for aperiodic. This frequency-domain view reveals what filters do and how signals occupy bandwidth.

Prerequisites: Signal Fundamentals, Calculus
You'll learn to:
  • Compute Fourier series coefficients
  • Apply Fourier transform to common signals
  • Interpret frequency spectra
  • Understand Parseval's theorem (energy in time = energy in frequency)
Fourier series

Any periodic signal can be represented as a sum of harmonically related sinusoids. This is the Fourier series.

Trigonometric Form:

x(t)=a0+∑n=1∞[ancos⁡(nω0t)+bnsin⁡(nω0t)]x(t) = a_0 + \sum_{n=1}^{\infty}[a_n\cos(n\omega_0 t) + b_n\sin(n\omega_0 t)]x(t)=a0​+n=1∑∞​[an​cos(nω0​t)+bn​sin(nω0​t)]

Coefficients:

a0=1T∫0Tx(t) dt(DC component)a_0 = \frac{1}{T}\int_0^T x(t) \, dt \quad \text{(DC component)}a0​=T1​∫0T​x(t)dt(DC component)

an=2T∫0Tx(t)cos⁡(nω0t) dta_n = \frac{2}{T}\int_0^T x(t)\cos(n\omega_0 t) \, dtan​=T2​∫0T​x(t)cos(nω0​t)dt

bn=2T∫0Tx(t)sin⁡(nω0t) dtb_n = \frac{2}{T}\int_0^T x(t)\sin(n\omega_0 t) \, dtbn​=T2​∫0T​x(t)sin(nω0​t)dt

Complex Exponential Form (More Elegant):

x(t)=∑n=−∞∞cnejnω0tx(t) = \sum_{n=-\infty}^{\infty} c_n e^{jn\omega_0 t}x(t)=n=−∞∑∞​cn​ejnω0​t

cn=1T∫0Tx(t)e−jnω0t dtc_n = \frac{1}{T}\int_0^T x(t)e^{-jn\omega_0 t} \, dtcn​=T1​∫0T​x(t)e−jnω0​tdt

Square wave Fourier series

Example: Square Wave

x(t)=4π(sin⁡(ω0t)+13sin⁡(3ω0t)+15sin⁡(5ω0t)+...)x(t) = \frac{4}{\pi}\left(\sin(\omega_0 t) + \frac{1}{3}\sin(3\omega_0 t) + \frac{1}{5}\sin(5\omega_0 t) + ...\right)x(t)=π4​(sin(ω0​t)+31​sin(3ω0​t)+51​sin(5ω0​t)+...)

Only odd harmonics! Even functions have only cosine terms, odd functions have only sine terms.

Fourier series visualization

Gibbs Phenomenon: At discontinuities, the Fourier series overshoots by ~9%, no matter how many terms you include. This is fundamental, not a bug.

Convergence:

  • Dirichlet conditions guarantee convergence for most practical signals
  • At discontinuities, converges to midpoint of jump
Fourier transform

The Fourier transform extends Fourier series to non-periodic signals, giving a continuous spectrum instead of discrete harmonics.

Forward Transform:

X(jω)=∫−∞∞x(t)e−jωt dtX(j\omega) = \int_{-\infty}^{\infty} x(t)e^{-j\omega t} \, dtX(jω)=∫−∞∞​x(t)e−jωtdt

Inverse Transform:

x(t)=12π∫−∞∞X(jω)ejωt dωx(t) = \frac{1}{2\pi}\int_{-\infty}^{\infty} X(j\omega)e^{j\omega t} \, d\omegax(t)=2π1​∫−∞∞​X(jω)ejωtdω

Time and frequency domain relationship

Common Transform Pairs:

Time Domain Frequency Domain
δ(t)\delta(t)δ(t) 111
111 2πδ(ω)2\pi\delta(\omega)2πδ(ω)
e−atu(t)e^{-at}u(t)e−atu(t) 1a+jω\frac{1}{a+j\omega}a+jω1​
e−a∣t∣e^{-a|t|}e−a∣t∣ 2aa2+ω2\frac{2a}{a^2+\omega^2}a2+ω22a​
rect(t/T)\text{rect}(t/T)rect(t/T) Tsinc(ωT/2)T\text{sinc}(\omega T/2)Tsinc(ωT/2)
cos⁡(ω0t)\cos(\omega_0 t)cos(ω0​t) π[δ(ω−ω0)+δ(ω+ω0)]\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]π[δ(ω−ω0​)+δ(ω+ω0​)]

Key Properties:

Property Time Domain Frequency Domain
Linearity ax(t)+by(t)ax(t)+by(t)ax(t)+by(t) aX(ω)+bY(ω)aX(\omega)+bY(\omega)aX(ω)+bY(ω)
Time Shift x(t−t0)x(t-t_0)x(t−t0​) e−jωt0X(ω)e^{-j\omega t_0}X(\omega)e−jωt0​X(ω)
Freq Shift ejω0tx(t)e^{j\omega_0 t}x(t)ejω0​tx(t) X(ω−ω0)X(\omega-\omega_0)X(ω−ω0​)
Convolution x(t)∗h(t)x(t)*h(t)x(t)∗h(t) X(ω)H(ω)X(\omega)H(\omega)X(ω)H(ω)
Multiplication x(t)y(t)x(t)y(t)x(t)y(t) 12πX(ω)∗Y(ω)\frac{1}{2\pi}X(\omega)*Y(\omega)2π1​X(ω)∗Y(ω)
Differentiation dxdt\frac{dx}{dt}dtdx​ jωX(ω)j\omega X(\omega)jωX(ω)

Transform relationships

Duality: Time and frequency are interchangeable — properties in one domain have mirror properties in the other.

Spectrum

The spectrum shows how a signal's energy or power is distributed across frequencies. It's how we "see" signals in the frequency domain.

Magnitude Spectrum:

∣X(jω)∣=Re(X)2+Im(X)2|X(j\omega)| = \sqrt{\text{Re}(X)^2 + \text{Im}(X)^2}∣X(jω)∣=Re(X)2+Im(X)2​

Phase Spectrum:

∠X(jω)=arctan⁡(Im(X)Re(X))\angle X(j\omega) = \arctan\left(\frac{\text{Im}(X)}{\text{Re}(X)}\right)∠X(jω)=arctan(Re(X)Im(X)​)

Sine wave spectrum

Single Frequency (Sinusoid): A pure tone appears as two impulses at ±f0\pm f_0±f0​.

Square Wave Spectrum: Impulses at odd harmonics with decreasing amplitude ($1/n$).

Square wave spectrum

Power Spectral Density (PSD): For power signals, the PSD shows power per unit frequency:

Sxx(ω)=lim⁡T→∞∣XT(ω)∣2TS_{xx}(\omega) = \lim_{T\to\infty} \frac{|X_T(\omega)|^2}{T}Sxx​(ω)=T→∞lim​T∣XT​(ω)∣2​

Energy Spectral Density: For energy signals: ∣X(ω)∣2|X(\omega)|^2∣X(ω)∣2

One-Sided vs Two-Sided:

  • Two-sided: shows negative frequencies (mathematically complete)
  • One-sided: doubles positive side, ignores negative (practical measurements)

Real signals have conjugate-symmetric spectra: X(−ω)=X∗(ω)X(-\omega) = X^*(\omega)X(−ω)=X∗(ω)

Bandwidth

Bandwidth measures how much frequency "space" a signal occupies. Different definitions exist for different applications.

3dB Bandwidth: Range where ∣X(ω)∣≥∣X(ωmax)∣/2|X(\omega)| \geq |X(\omega_{max})|/\sqrt{2}∣X(ω)∣≥∣X(ωmax​)∣/2​

Bandwidth definition

Null-to-Null Bandwidth: Distance between first zeros of the spectrum.

Equivalent Noise Bandwidth: Width of rectangular filter with same area under the curve.

Time-Bandwidth Product: A fundamental tradeoff — you can't have both short duration AND narrow bandwidth.

Δt⋅Δf≥14π\Delta t \cdot \Delta f \geq \frac{1}{4\pi}Δt⋅Δf≥4π1​

Equality holds only for Gaussian pulses.

Practical Implications:

  • Shorter pulses need more bandwidth
  • Sharper filter cutoffs need longer impulse responses
  • Communication rate limited by available bandwidth (Shannon)

Parseval's Theorem: Total energy is the same in time and frequency domains:

∫−∞∞∣x(t)∣2dt=12π∫−∞∞∣X(jω)∣2dω\int_{-\infty}^{\infty} |x(t)|^2 dt = \frac{1}{2\pi}\int_{-\infty}^{\infty} |X(j\omega)|^2 d\omega∫−∞∞​∣x(t)∣2dt=2π1​∫−∞∞​∣X(jω)∣2dω

This lets you calculate energy from the spectrum.

Resources:
  • 3Blue1Brown - Fourier https://www.youtube.com/watch?v=spUNpyF58BY
  • MIT OCW 6.003 https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/

Laplace & Z-Transform optional

Generalized frequency domain tools. Laplace transform handles continuous systems with initial conditions, Z-transform does the same for discrete systems. Both turn differential/difference equations into algebra.

Prerequisites: Fourier Analysis, Differential equations
You'll learn to:
  • Apply Laplace transform to solve circuit problems
  • Find transfer functions from differential equations
  • Use Z-transform for discrete-time system analysis
  • Analyze system stability using pole locations
Transfer function

The transfer function H(s)H(s)H(s) or H(z)H(z)H(z) is the Laplace/Z-transform of the impulse response. It completely characterizes an LTI system.

Laplace Transform:

X(s)=∫0∞x(t)e−st dtX(s) = \int_{0}^{\infty} x(t)e^{-st} \, dtX(s)=∫0∞​x(t)e−stdt

where s=σ+jωs = \sigma + j\omegas=σ+jω is a complex frequency.

Transfer Function Definition:

H(s)=Y(s)X(s)H(s) = \frac{Y(s)}{X(s)}H(s)=X(s)Y(s)​

From Differential Equations: For d2ydt2+3dydt+2y=x(t)\frac{d^2y}{dt^2} + 3\frac{dy}{dt} + 2y = x(t)dt2d2y​+3dtdy​+2y=x(t):

s2Y(s)+3sY(s)+2Y(s)=X(s)s^2Y(s) + 3sY(s) + 2Y(s) = X(s)s2Y(s)+3sY(s)+2Y(s)=X(s)

H(s)=Y(s)X(s)=1s2+3s+2H(s) = \frac{Y(s)}{X(s)} = \frac{1}{s^2 + 3s + 2}H(s)=X(s)Y(s)​=s2+3s+21​

Standard Form:

H(s)=K(s−z1)(s−z2)...(s−zm)(s−p1)(s−p2)...(s−pn)H(s) = K\frac{(s-z_1)(s-z_2)...(s-z_m)}{(s-p_1)(s-p_2)...(s-p_n)}H(s)=K(s−p1​)(s−p2​)...(s−pn​)(s−z1​)(s−z2​)...(s−zm​)​

Feedback system

Poles and zeros

Poles and zeros determine everything about a system's behavior — stability, frequency response, and transient response.

Zeros: Values of sss where H(s)=0H(s) = 0H(s)=0 (numerator = 0) Poles: Values of sss where H(s)→∞H(s) \to \inftyH(s)→∞ (denominator = 0)

Pole-Zero Plot: Plot poles (×) and zeros (○) in the complex s-plane.

Pole-zero plot

Pole Locations and Time Response:

Pole Location Time Response
Real, negative Decaying exponential
Real, positive Growing exponential (unstable!)
Complex conjugate pair, LHP Decaying oscillation
Complex conjugate pair, RHP Growing oscillation (unstable!)
On imaginary axis Sustained oscillation

Effect on Frequency Response:

  • Poles create peaks in ∣H(jω)∣|H(j\omega)|∣H(jω)∣
  • Zeros create notches/dips
  • Distance from jω-axis determines sharpness
ROC

The Region of Convergence (ROC) specifies where the transform integral/sum converges. It's essential for uniqueness and stability.

Laplace ROC: The transform converges for Re(s)>σ0\text{Re}(s) > \sigma_0Re(s)>σ0​ where $\sigma_0$ depends on the signal.

ROC Rules (Laplace):

  • Right-sided signals: ROC is right of rightmost pole
  • Left-sided signals: ROC is left of leftmost pole
  • Two-sided signals: ROC is a strip (if it exists)
  • Causal + stable: ROC includes jω-axis and extends right

Z-Transform ROC: For discrete systems, ROC is an annular region in the z-plane.

  • Causal signals: ROC is outside the outermost pole
  • Stable systems: ROC includes the unit circle
Stability

A system is BIBO (bounded-input, bounded-output) stable if every bounded input produces a bounded output.

Continuous-Time Stability: All poles must be in the left half-plane (LHP):

Re(pi)<0 for all poles pi\text{Re}(p_i) < 0 \text{ for all poles } p_iRe(pi​)<0 for all poles pi​

Discrete-Time Stability: All poles must be inside the unit circle:

∣pi∣<1 for all poles pi|p_i| < 1 \text{ for all poles } p_i∣pi​∣<1 for all poles pi​

Stability Tests:

  • Routh-Hurwitz: Algebraic test for CT systems
  • Jury Test: Algebraic test for DT systems
  • Nyquist Criterion: Graphical, handles feedback

Marginal Stability: Poles on the boundary (jω-axis or unit circle) give sustained oscillations — theoretically stable but practically risky.

Common Stable Systems:

  • Low-pass filters (poles in LHP)
  • Most physical systems without positive feedback

For more depth, see the DSPGuide Laplace Chapter.

Resources:
  • MIT OCW 6.003 https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/
  • Brian Douglas - Control https://www.youtube.com/@BrianDouglas

Microcontrollers

Microcontroller Fundamentals

A computer on a chip — CPU, memory, and peripherals in one package. Arduino made embedded systems accessible, but understanding what happens under the hood makes you a better developer.

Prerequisites: Digital Logic basics, Basic programming
You'll learn to:
  • Understand microcontroller architecture (CPU, memory, peripherals)
  • Program GPIO pins for digital I/O
  • Use Arduino IDE effectively
  • Read microcontroller datasheets
Architecture

Microcontroller Architecture

A microcontroller (MCU) integrates a processor core, memory, and peripherals on a single chip — a complete computer system in miniature.

Von Neumann vs Harvard Architecture

Von Neumann Architecture

Von Neumann uses a single bus for both instructions and data:

  • Simpler design, fewer connections
  • Potential bottleneck (can't fetch instruction while accessing data)
  • Used in: x86 processors, some ARM cores

Harvard Architecture

Harvard separates instruction and data buses:

  • Simultaneous instruction fetch and data access
  • Higher performance for embedded applications
  • Used in: AVR (Arduino), PIC, most ARM Cortex-M

Core Components

8051 Block Diagram

Component Function
CPU Executes instructions (ALU, registers, control unit)
Flash Program memory (non-volatile, stores your code)
SRAM Data memory (volatile, variables, stack)
Peripherals I/O ports, timers, ADC, communication interfaces
Clock System timing (internal RC or external crystal)

Word Size

  • 8-bit: AVR, PIC, 8051 — simple, low power, cheap
  • 16-bit: MSP430 — ultra-low power applications
  • 32-bit: ARM Cortex-M — performance, complex applications

The word size affects register width, address space, and arithmetic efficiency. 8-bit MCUs handle 32-bit math through multiple operations.

Pipeline and Execution

Most MCUs use pipelining for efficiency:

Throughput=InstructionsClock cycles\text{Throughput} = \frac{\text{Instructions}}{\text{Clock cycles}}Throughput=Clock cyclesInstructions​

AVR achieves ~1 MIPS/MHz through single-cycle execution of most instructions.

GPIO

General Purpose Input/Output (GPIO)

GPIO pins are the fundamental interface between your MCU and the outside world. Each pin can be configured as input (reading sensors, buttons) or output (driving LEDs, motors).

Port Registers (AVR Example)

Port Register Structure

Each I/O port typically has three registers:

Register Function
DDRx Data Direction (0 = input, 1 = output)
PORTx Output data / Pull-up enable
PINx Read input state

Basic Configuration

// Set pin as output
DDRB |= (1 << PB5);    // Pin 13 on Arduino Uno

// Set output high
PORTB |= (1 << PB5);   // LED on

// Set output low
PORTB &= ~(1 << PB5);  // LED off

// Toggle output
PORTB ^= (1 << PB5);

// Set pin as input with pull-up
DDRD &= ~(1 << PD2);   // Input
PORTD |= (1 << PD2);   // Enable pull-up

// Read input
if (PIND & (1 << PD2)) {
    // Pin is HIGH
}

Input Modes

  • Floating (Hi-Z): Undefined voltage, susceptible to noise
  • Pull-up: Internal resistor to VCC (~20-50kΩ)
  • Pull-down: External resistor to GND (not always available internally)

Output Modes

  • Push-pull: Can source and sink current
  • Open-drain: Can only sink current (needs external pull-up)

Current Limits

Imax≈20−40 mA per pinI_{max} \approx 20-40\text{ mA per pin}Imax​≈20−40 mA per pin Itotal≈100−200 mA per portI_{total} \approx 100-200\text{ mA per port}Itotal​≈100−200 mA per port

Exceeding limits damages the MCU. Use transistors or drivers for high-current loads.

Clock

Clock System

The clock is the heartbeat of your MCU — every operation is synchronized to it. Understanding clock configuration is essential for timing-critical applications.

Clock Sources

Source Accuracy Startup Power
Internal RC ±1-10% Fast (~µs) Lowest
External Crystal ±20-50 ppm Slow (~ms) Medium
External Oscillator Best Fast Highest
PLL (multiplied) Varies Medium High

Clock Tree

The system clock feeds various subsystems through dividers: Clock Tree Example

Main Clock → CPU Clock
          → Peripheral Clock (may be divided)
          → Timer Clock
          → ADC Clock

Prescalers

Prescalers divide the clock for slower peripherals:

fperipheral=fsystem2nf_{peripheral} = \frac{f_{system}}{2^n}fperipheral​=2nfsystem​​

Common prescaler values: 1, 2, 4, 8, 16, 32, 64, 128, 256

Power vs Performance

Clock frequency directly affects power consumption:

P∝f⋅V2P \propto f \cdot V^2P∝f⋅V2

Lower frequency = lower power, but slower execution. Many MCUs support dynamic frequency scaling.

Arduino Default Clocks

Board MCU Clock
Uno ATmega328P 16 MHz (external)
Nano ATmega328P 16 MHz (external)
Pro Mini 3.3V ATmega328P 8 MHz (internal)
Memory map

Memory Organization

MCUs organize memory into distinct regions with different characteristics and access methods.

MCS-51 Memory Map

Memory Types

Type Volatile Use Typical Size
Flash No Program code, constants 16-256 KB
SRAM Yes Variables, stack, heap 1-32 KB
EEPROM No Configuration, calibration 512-4096 bytes
Registers Yes CPU and peripheral control Hundreds

Memory Map (AVR ATmega328P)

0x0000-0x001F  General Purpose Registers (R0-R31)
0x0020-0x005F  I/O Registers (64 locations)
0x0060-0x00FF  Extended I/O Registers
0x0100-0x08FF  SRAM (2KB)
0x0900-0x1FFF  EEPROM (1KB)
0x2000-0xFFFF  Flash Program Memory (32KB)

Special Sections

Internal RAM Organization

  • .text: Program code (in Flash)
  • .data: Initialized global variables (Flash → SRAM at startup)
  • .bss: Uninitialized globals (zeroed at startup)
  • .stack: Function call frames, local variables (grows down)
  • .heap: Dynamic allocation (grows up, avoid in embedded)

Stack Considerations

Stack usage=local vars+return addresses+saved registers\text{Stack usage} = \text{local vars} + \text{return addresses} + \text{saved registers}Stack usage=local vars+return addresses+saved registers

Interrupts add to stack depth. Deep call chains + ISRs can overflow. Always leave margin — stack overflow causes mysterious crashes.

Accessing Flash Data

In Harvard architecture, constants in Flash need special access:

#include <avr/pgmspace.h>
const char message[] PROGMEM = "Hello";
char c = pgm_read_byte(&message[0]);
Resources:
  • SparkFun Arduino Tutorials https://learn.sparkfun.com/tutorials/tags/arduino
  • Adafruit Learn Arduino https://learn.adafruit.com/series/learn-arduino

Peripherals & Communication

Microcontrollers talk to sensors and other devices through standardized protocols. I2C for multiple devices on two wires, SPI for speed, UART for simplicity. ADC/DAC bridge analog and digital worlds.

Prerequisites: Microcontroller Fundamentals
You'll learn to:
  • Configure and use UART, SPI, and I2C
  • Read analog sensors with ADC
  • Generate analog outputs with PWM
  • Use timers and interrupts effectively
UART

UART (Universal Asynchronous Receiver/Transmitter)

UART is the simplest serial protocol — no clock line, just two data wires. Both devices must agree on baud rate beforehand.

UART Frame Format

Frame Structure

Field Bits Description
Start 1 Always LOW, signals frame start
Data 5-9 LSB first, typically 8 bits
Parity 0-1 Optional error detection
Stop 1-2 Always HIGH, signals frame end

Baud Rate

Common rates: 9600, 19200, 38400, 57600, 115200 (most common today)

Bit time=1baud rate\text{Bit time} = \frac{1}{\text{baud rate}}Bit time=baud rate1​

At 115200 baud: ~8.68 µs per bit, ~86.8 µs per byte (with overhead).

Connections

Device A          Device B
TX  ───────────── RX
RX  ───────────── TX
GND ───────────── GND

Cross-connect TX/RX! Common beginner mistake.

Voltage Levels

Standard Logic High Logic Low
TTL 3.3V or 5V 0V
RS-232 -3 to -15V +3 to +15V

Never connect RS-232 directly to MCU pins — use level shifter (MAX232).

Arduino Example

Serial.begin(115200);
Serial.println("Hello, World!");
if (Serial.available()) {
    char c = Serial.read();
    Serial.print("Received: ");
    Serial.println(c);
  }

See SparkFun Serial Tutorial for comprehensive guide.

SPI

SPI (Serial Peripheral Interface)

SPI is fast, full-duplex, and synchronous. The master provides the clock, so no baud rate agreement needed. Used for displays, SD cards, sensors.

SPI Single Slave

Signal Lines

Line Direction Function
MOSI Master → Slave Master Out, Slave In
MISO Slave → Master Master In, Slave Out
SCK Master → Slave Serial Clock
CS/SS Master → Slave Chip Select (active LOW)

Multiple Slaves

SPI Three Slaves

Each slave needs its own CS line. Only one slave active at a time.

Clock Modes

SPI Timing Diagram

Mode CPOL CPHA Description
0 0 0 Idle LOW, sample on rising edge
1 0 1 Idle LOW, sample on falling edge
2 1 0 Idle HIGH, sample on falling edge
3 1 1 Idle HIGH, sample on rising edge

Check your device's datasheet for required mode!

Speed

SPI can run at 1-50 MHz typically. Limited by:

  • Slave device maximum frequency
  • Wire length and capacitance
  • EMI considerations

Arduino Example

#include <SPI.h>
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(CS_PIN, LOW);
byte response = SPI.transfer(0x42);  // Send and receive
digitalWrite(CS_PIN, HIGH);
SPI.endTransaction();

See SparkFun SPI Tutorial.

I2C

I2C (Inter-Integrated Circuit)

I2C uses only two wires for multiple devices. Each device has a unique address. Great for sensors, EEPROMs, RTCs — anything that doesn't need high speed.

I2C Bus

Signal Lines

Line Function
SDA Serial Data (bidirectional)
SCL Serial Clock (master driven)

Both lines are open-drain with pull-up resistors (typically 4.7kΩ).

Addressing

7-bit address = up to 128 devices (some reserved). First byte after START: [7-bit address][R/W bit]

  • R/W = 0: Master writes to slave
  • R/W = 1: Master reads from slave

I2C Data Transfer

Speed Modes

Mode Speed Use Case
Standard 100 kHz General purpose
Fast 400 kHz Most sensors
Fast+ 1 MHz Higher bandwidth
High Speed 3.4 MHz Rare, specialized

Protocol Sequence

  1. START: SDA goes LOW while SCL HIGH
  2. Address + R/W: 8 bits, slave responds with ACK
  3. Data: 8 bits each, ACK after each byte
  4. STOP: SDA goes HIGH while SCL HIGH

I2C Start Condition

Arduino Example

#include <Wire.h>
Wire.begin();
Wire.beginTransmission(0x48);  // Address
Wire.write(0x00);              // Register
Wire.endTransmission();
Wire.requestFrom(0x48, 2);     // Read 2 bytes
int value = Wire.read() << 8 | Wire.read();

See SparkFun I2C Tutorial.

ADC/DAC

Analog-to-Digital Conversion

MCUs work in digital, but the real world is analog. ADC bridges that gap, converting continuous voltages to discrete numbers.

SAR ADC Block Diagram

SAR ADC (Successive Approximation Register)

Most common type in MCUs. Uses binary search algorithm:

SAR ADC Process

  1. Compare input to DAC output (start at mid-scale)
  2. If input > DAC: keep MSB = 1, else MSB = 0
  3. Move to next bit, repeat
  4. After n bits, conversion complete

Conversion time: n clock cycles for n-bit resolution.

Resolution

LSB=Vref2n\text{LSB} = \frac{V_{ref}}{2^n}LSB=2nVref​​

Resolution Levels LSB (5V ref)
8-bit 256 19.5 mV
10-bit 1024 4.88 mV
12-bit 4096 1.22 mV

Key Specs

  • INL/DNL: Linearity errors (in LSBs)
  • SNR: Signal-to-noise ratio
  • Sampling rate: Conversions per second

SNRmax=6.02n+1.76 dBSNR_{max} = 6.02n + 1.76 \text{ dB}SNRmax​=6.02n+1.76 dB

Arduino ADC

int value = analogRead(A0);  // 0-1023 (10-bit)
float voltage = value * (5.0 / 1023.0);

Default: 10-bit, ~100 µs conversion, single-ended.

DAC (Digital-to-Analog)

Not all MCUs have DAC. Alternatives:

  • PWM + filter: Simple, good for audio/motor control
  • External DAC: Higher precision (MCP4725, etc.)
PWM

Pulse Width Modulation (PWM)

PWM creates "analog-like" output using digital pins. By rapidly switching between HIGH and LOW, the average voltage can be controlled.

PWM Signal

Duty Cycle

Duty Cycle=TONTperiod×100%\text{Duty Cycle} = \frac{T_{ON}}{T_{period}} \times 100\%Duty Cycle=Tperiod​TON​​×100%

Duty Cycle Examples

Duty Cycle Average Voltage (5V)
0% 0V
25% 1.25V
50% 2.5V
75% 3.75V
100% 5V

Applications

  • LED dimming: Duty cycle controls brightness
  • Motor speed: Average voltage controls speed
  • Servo control: Pulse width encodes position
  • Audio: PWM DAC with low-pass filter

Arduino PWM

analogWrite(9, 127);  // 50% duty cycle (0-255)
Board PWM Pins Frequency
Uno 3,5,6,9,10,11 490 Hz (5,6: 980 Hz)
Mega 2-13, 44-46 490 Hz

Timer-Based PWM

PWM is generated by hardware timers, not software. For custom frequencies:

// Fast PWM, prescaler 8, ~7.8 kHz on Timer1
TCCR1A = _BV(COM1A1) | _BV(WGM11);
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS11);
ICR1 = 255;
OCR1A = 127;  // Duty cycle

fPWM=fclockprescaler×(TOP+1)f_{PWM} = \frac{f_{clock}}{prescaler \times (TOP + 1)}fPWM​=prescaler×(TOP+1)fclock​​

Interrupts

Interrupts

Interrupts let hardware events preempt normal code execution. Essential for responsive, efficient embedded systems.

Why Interrupts?

Polling (checking repeatedly):

while (1) {
    if (button_pressed()) handle_button();
    if (serial_available()) handle_serial();
    // Wastes CPU time waiting
  }

Interrupts (event-driven):

ISR(INT0_vect) { handle_button(); }
ISR(USART_RX_vect) { handle_serial(); }
// Main loop does useful work

Interrupt Vector Table

Interrupt Vector Table

Each interrupt source has a fixed address (vector) containing a jump to its handler (ISR - Interrupt Service Routine).

Interrupt Types

Type Source Example
External Pin change Button press
Timer Counter overflow/match Periodic tasks
Serial TX/RX complete UART data
ADC Conversion complete Sensor reading

ISR Rules

  1. Keep it short: Get in, set flag, get out
  2. No blocking: No delays, no Serial.print
  3. volatile variables: Required for ISR-main communication
  4. Atomic access: Disable interrupts when reading multi-byte shared data
volatile uint8_t flag = 0;

ISR(INT0_vect) {
    flag = 1;  // Just set flag
}

int main() {
    while (1) {
        if (flag) {
            flag = 0;
            handle_event();  // Process outside ISR
        }
    }
}

Enable/Disable

sei();  // Enable global interrupts
cli();  // Disable global interrupts

// Critical section
cli();
uint16_t copy = shared_value;  // Atomic read
sei();
Resources:
  • SparkFun Serial Communication https://learn.sparkfun.com/tutorials/serial-communication/all
  • SparkFun I2C Tutorial https://learn.sparkfun.com/tutorials/i2c/all

Embedded C Programming optional

C is the lingua franca of embedded systems. Direct hardware access, bit manipulation, memory management — skills that matter when every byte counts and timing is critical.

Prerequisites: Microcontroller Fundamentals, C programming basics
You'll learn to:
  • Write efficient embedded C code
  • Manipulate registers using bit operations
  • Understand volatile keyword and memory-mapped I/O
  • Debug embedded systems effectively
Bit manipulation

Bit Manipulation

Embedded systems live at the bit level. Every register, every flag, every hardware configuration is controlled through bits.

Bitwise Operators

Operator Symbol Operation
AND & Mask bits
OR | Set bits
XOR ^ Toggle bits
NOT ~ Invert all bits
Left Shift << Multiply by 2^n
Right Shift >> Divide by 2^n

Common Macros

#define BIT_SET(reg, bit)     ((reg) |= (1 << (bit)))
#define BIT_CLEAR(reg, bit)   ((reg) &= ~(1 << (bit)))
#define BIT_TOGGLE(reg, bit)  ((reg) ^= (1 << (bit)))
#define BIT_CHECK(reg, bit)   ((reg) & (1 << (bit)))

Examples

// Set bit 5
PORTB |= (1 << 5);       // PORTB = PORTB | 0b00100000

// Clear bit 3
PORTB &= ~(1 << 3);      // PORTB = PORTB & 0b11110111

// Toggle bit 0
PORTB ^= (1 << 0);       // Flip state

// Check if bit 2 is set
if (PINB & (1 << 2)) { /* bit is 1 */ }

// Set multiple bits
PORTB |= (1 << 5) | (1 << 3);  // Set bits 5 and 3

// Clear multiple bits
PORTB &= ~((1 << 5) | (1 << 3));

Bit Fields (Alternative)

struct {
    uint8_t enable : 1;
    uint8_t mode   : 2;
    uint8_t speed  : 3;
    uint8_t reserved : 2;
  } config;

config.enable = 1;
config.mode = 2;

Note: Bit field ordering is compiler-dependent. Use with caution.

Registers

Hardware Registers

Registers are special memory locations that control hardware. Each bit typically has a specific function defined in the datasheet.

Register Access

// Direct register names (from header)
DDRB = 0xFF;           // All pins output
PORTB = 0x0F;          // Lower nibble HIGH
uint8_t val = PINB;    // Read port

// Using addresses
#define PORTB  (*(volatile uint8_t *)0x25)
#define DDRB   (*(volatile uint8_t *)0x24)

Register Types

Type Description Access
Control Configure peripheral Read/Write
Status Current state/flags Read (some W1C)
Data Input/output values Read/Write

W1C = Write 1 to Clear (common for interrupt flags)

Reading the Datasheet

TCCR1A – Timer/Counter1 Control Register A
┌───┬───┬───┬───┬───┬───┬───┬───┐
│COM1A1│COM1A0│COM1B1│COM1B0│ - │ - │WGM11│WGM10│
└───┴───┴───┴───┴───┴───┴───┴───┘

Each bit/field is documented with:

  • Name and position
  • Read/Write capability
  • Effect of each value

Safe Register Modification

// Read-Modify-Write pattern
uint8_t temp = TCCR1A;
temp &= ~(0x03);       // Clear bits 0-1
temp |= (0x01);        // Set new value
TCCR1A = temp;

// Or one-liner
TCCR1A = (TCCR1A & ~0x03) | 0x01;
Volatile

The volatile Keyword

volatile tells the compiler "this variable can change unexpectedly." Without it, optimizations can break your code.

Why It Matters

// WITHOUT volatile - BROKEN
uint8_t flag = 0;

ISR(INT0_vect) { flag = 1; }

void main() {
    while (!flag) { }  // May optimize to while(1)
    // Compiler thinks flag never changes in loop
  }
// WITH volatile - CORRECT
volatile uint8_t flag = 0;

ISR(INT0_vect) { flag = 1; }

void main() {
    while (!flag) { }  // Actually reads flag each time
  }

When to Use volatile

  1. Variables shared with ISR
  2. Memory-mapped hardware registers
  3. Variables modified by DMA
  4. Multi-threaded shared data (with proper synchronization)

Hardware Registers

// All hardware registers should be volatile
volatile uint8_t *port = (volatile uint8_t *)0x25;
*port = 0xFF;  // Compiler won't optimize away

MCU header files define registers with volatile:

#define PORTB (*(volatile uint8_t *)0x25)

What volatile Does NOT Do

  • Does not make access atomic
  • Does not provide memory barriers
  • Does not prevent reordering between volatile accesses

For multi-byte variables shared with ISRs:

volatile uint16_t counter;

uint16_t read_counter() {
    cli();  // Disable interrupts
    uint16_t copy = counter;
    sei();  // Re-enable
    return copy;
  }
Memory-mapped I/O

Memory-Mapped I/O

In most MCUs, hardware peripherals appear as memory addresses. Reading/writing these addresses controls the hardware.

How It Works

CPU ─────┬───── Memory Bus ─────┬───── RAM
         │                      │
         └──── I/O Decoder ─────┴───── Peripherals
                                │
                           GPIO, UART,
                           Timers, etc.

Accessing Hardware

// Define register address
#define GPIO_BASE    0x40020000
#define GPIO_MODER   (*(volatile uint32_t *)(GPIO_BASE + 0x00))
#define GPIO_ODR     (*(volatile uint32_t *)(GPIO_BASE + 0x14))

// Use like normal variables
GPIO_MODER = 0x55555555;  // All outputs
GPIO_ODR = 0x0000FFFF;    // Lower 16 bits HIGH

Struct Overlay Pattern

typedef struct {
    volatile uint32_t MODER;
    volatile uint32_t OTYPER;
    volatile uint32_t OSPEEDR;
    volatile uint32_t PUPDR;
    volatile uint32_t IDR;
    volatile uint32_t ODR;
  } GPIO_TypeDef;

#define GPIOA ((GPIO_TypeDef *)0x40020000)
#define GPIOB ((GPIO_TypeDef *)0x40020400)

// Clean access
GPIOA->ODR = 0xFF;
uint32_t input = GPIOB->IDR;

Why Memory-Mapped?

  • Unified addressing simplifies CPU design
  • Same instructions for memory and I/O
  • Pointers work with hardware
  • C can directly manipulate hardware

This is why embedded C remains dominant — direct hardware control without assembly language.

Resources:
  • Embedded Systems Programming https://www.state-machine.com/quickstart/
  • SparkFun Tutorials https://learn.sparkfun.com/tutorials

PCB Design

PCB Design Fundamentals

Move from breadboard to real product. PCBs are reliable, reproducible, and professional. Learn the workflow: schematic → layout → fabrication files. KiCad is free and industry-capable.

Prerequisites: DC Circuits, Basic component knowledge
You'll learn to:
  • Create schematics in KiCad or similar
  • Lay out simple two-layer boards
  • Generate Gerber files for fabrication
  • Understand design rules and clearances
Schematic capture

Schematic Capture

The schematic is your circuit's logical blueprint — components and their connections without physical placement concerns.

Electrical Symbols

Schematic Workflow

  1. Add components from libraries (or create custom symbols)
  2. Place and arrange logically (inputs left, outputs right)
  3. Wire connections (nets)
  4. Add power symbols (VCC, GND)
  5. Annotate (assign reference designators: R1, C1, U1)
  6. Run ERC (Electrical Rules Check)

Symbol Elements

Transistor Circuit Example

Element Purpose
Symbol Graphical representation
Reference R1, C1, U1 (unique ID)
Value 10kΩ, 100nF, ATmega328P
Footprint Physical package link
Pins Connection points with names/numbers

Best Practices

  • Signal flow: Left-to-right, top-to-bottom
  • Group by function: Power, digital, analog sections
  • Label nets: Named nets are clearer than lines everywhere
  • Use hierarchical sheets for complex designs
  • Add notes: Document non-obvious design decisions

Power Symbols

Battery Symbols

Use global power symbols (VCC, +3V3, GND) rather than wiring power to every component — cleaner schematics.

ERC (Electrical Rules Check)

Catches common errors:

  • Unconnected pins
  • Multiple outputs driving same net
  • Power pins not connected
  • Input pins floating

See SparkFun How to Read Schematics and SparkFun EAGLE Schematic.

Layout

PCB Layout

Layout transforms your schematic into physical reality — component placement, copper traces, and layer stackup.

Layout Workflow

  1. Import netlist from schematic
  2. Define board outline
  3. Place components (critical components first)
  4. Route traces (connect the nets)
  5. Pour ground planes
  6. Run DRC (Design Rules Check)
  7. Generate manufacturing files

Layer Stackup

Layers Typical Configuration
2-layer Top: Signals + Power / Bottom: GND + Signals
4-layer Signal → GND → Power → Signal
6-layer Sig → GND → Sig → Sig → Power → Sig

Two-layer is cheapest and sufficient for most hobby/simple projects. Four-layer adds solid reference planes for better signal integrity.

Placement Guidelines

  1. Connectors at board edges
  2. Decoupling caps close to IC power pins
  3. Crystal/oscillator close to MCU
  4. High-frequency components near their sources
  5. Thermal considerations (hot components away from sensitive ones)
  6. Mechanical constraints (mounting holes, keep-outs)

Routing Guidelines

  • Shortest path (but not at expense of other rules)
  • Avoid 90° corners (use 45° or curves)
  • Match trace lengths for high-speed differential pairs
  • Keep analog/digital separate
  • Don't route under noisy components

Trace Width

Width determines current capacity:

Width (1oz Cu) ~Current (10°C rise)
10 mil 300 mA
20 mil 800 mA
50 mil 1.5 A
100 mil 3 A

Use online calculators for precise values based on your stackup.

Ground Planes

Pour copper fills connected to GND:

  • Low impedance return path
  • EMI shielding
  • Heat dissipation

See SparkFun PCB Basics and SparkFun EAGLE Layout.

Gerbers

Gerber Files

Gerbers are the universal language of PCB fabrication — every manufacturer accepts them. They describe each layer as 2D artwork.

Standard File Set

Extension Layer Description
.GTL Top Copper Signal traces, pads
.GBL Bottom Copper Signal traces, pads
.GTS Top Solder Mask Green coating openings
.GBS Bottom Solder Mask Green coating openings
.GTO Top Silkscreen Component labels
.GBO Bottom Silkscreen Component labels
.GTP Top Paste Stencil for solder paste
.GBP Bottom Paste Stencil for solder paste
.GKO / .GM1 Board Outline Mechanical boundary
.DRL Drill File Hole locations (Excellon format)

Gerber Format

RS-274X (extended Gerber) is the modern standard:

  • Embedded aperture definitions
  • Self-contained files
  • ASCII format (human-readable)

Generation Workflow

  1. Run final DRC check
  2. Generate Gerbers (plot each layer)
  3. Generate drill file (Excellon format)
  4. Review in Gerber viewer (critical step!)
  5. Zip all files together
  6. Upload to manufacturer

Gerber Viewers

Always verify before ordering:

  • KiCad GerbView (built-in)
  • gerbv (free, open-source)
  • Online viewers (OSH Park, JLCPCB)

Common Mistakes

  • Missing drill file
  • Wrong board outline layer
  • Solder mask inverted (shows mask, not openings)
  • Missing paste layer for SMD assembly
  • Different units (mm vs inches) between files

Manufacturer Upload

Most fabs (JLCPCB, PCBWay, OSH Park) auto-detect layers from standard extensions. Review their preview before ordering!

Design rules

Design Rules (DRC)

Design rules ensure your PCB can actually be manufactured. Every fab has minimum capabilities — violate them and your board fails or costs extra.

Critical Parameters

Parameter Typical Minimum Description
Trace width 6-8 mil Narrowest copper
Trace spacing 6-8 mil Gap between copper
Via drill 10-12 mil Hole diameter
Via annular ring 5-8 mil Copper around hole
Solder mask dam 4 mil Mask between pads
Silkscreen width 5-6 mil Text/line minimum

1 mil = 0.001 inch = 0.0254 mm

Clearances

Clearances prevent shorts and manufacturing issues:

┌─────────────────────────────────────┐
│  Trace ══════  ║spacing║  ══════ Trace  │
│                                     │
│  Pad ●────── annular ring ──────● Via │
│                                     │
│  Board edge ├── edge clearance ──┤   │
└─────────────────────────────────────┘
  • Trace-to-trace: Prevent shorts
  • Trace-to-pad: Manufacturing tolerance
  • Pad-to-pad: Solder bridging prevention
  • Edge clearance: Routing/panelization

High Voltage Considerations

For voltages >50V, spacing must increase:

Spacing (mm)≈0.1+Vpeak500\text{Spacing (mm)} \approx 0.1 + \frac{V_{peak}}{500}Spacing (mm)≈0.1+500Vpeak​​

Consult IPC-2221 for proper clearances.

DRC Setup

Configure rules in your EDA tool before layout:

Minimum trace width:     0.2mm (8 mil)
Minimum clearance:       0.2mm (8 mil)
Minimum via drill:       0.3mm (12 mil)
Minimum annular ring:    0.15mm (6 mil)
Board edge clearance:    0.5mm (20 mil)

Manufacturer Capabilities

Check your fab's specs! Example (JLCPCB standard):

Parameter Standard Advanced
Min trace/space 5/5 mil 3.5/3.5 mil
Min via drill 0.3mm 0.2mm
Min hole size 0.3mm 0.15mm

Advanced capabilities cost more. Design to standard rules when possible.

Running DRC

  1. Set rules matching your manufacturer
  2. Run DRC before generating Gerbers
  3. Fix all errors (yellow = warning, red = error)
  4. Re-run until clean
  5. Document any intentional rule violations

See TI application notes for advanced guidelines:

  • PCB EMI Guidelines
  • High Speed Layout
Resources:
  • KiCad Getting Started https://docs.kicad.org/
  • SparkFun PCB Basics https://learn.sparkfun.com/tutorials/pcb-basics/all