Project information
- Course: ECE 5730
- Date: September 2026
- Team: Amber Li, Ivan Huang, Zarif Karim
- Platform: Raspberry Pi Pico 2 (RP2350)
- Peripherals: MCP4822 12-bit SPI DAC, slide potentiometer, 3×4 keypad, SPDT switch
- Report: Lab Report (PDF)
Summary
As part of Cornell's ECE 5730 microcontroller course, my team built a birdsong synthesizer on the Raspberry Pi Pico 2 (RP2350). The goal was to reproduce bird whistles accurately enough for the Merlin Bird ID app to recognize them. Audio is generated with Direct Digital Synthesis (DDS), sent over SPI to an external 12-bit DAC, and played through a 3.5 mm audio jack. A slide potentiometer sets pitch or volume, and a keypad lets you record, play back, and compose sequences of sound bites like a bird song.
Direct Digital Synthesis
A 32-bit phase accumulator is incremented at a fixed 50 kHz sample rate. The top 8 bits index a 256-entry sine lookup table, and the output frequency is set by the phase increment N = (Fout / Fs) · 232.
- The sine table is scaled to ±2047 and offset by 2048 so it fills the DAC's full unsigned 0–4095 range without clipping
- Silence is produced by setting the phase increment to 0 rather than zeroing the DAC, so the output holds its last value and avoids start-up clicks
- Sample generation runs in a timer ISR so audio is never disturbed by the protothread scheduler
Audio Output: SPI and DAC
The Pico talks to the MCP4822 over SPI1 at 20 MHz with 16-bit frames: four configuration bits (channel, 1× gain, active mode) followed by 12 data bits. LDAC is tied low so outputs update immediately. The waveform was first verified on an oscilloscope at 800 Hz, then wired to the audio socket and speakers.
The ISR was timed by toggling a spare GPIO on entry and exit, confirming that each sample completes well inside the 20 µs interrupt period.
Controls
- Slide potentiometer: read by the on-board ADC and mapped to 0–10 kHz
- SPDT switch: selects whether the slider controls frequency or volume, where volume scales the sine table output in the ISR
- Keypad: scanned row by row with pull-ups on the columns and 330 Ω series resistors on the rows to protect the GPIOs from multi-key shorts
- Debouncing: a four-state FSM (Not Pressed, Maybe Pressed, Pressed, Maybe Not Pressed) confirms a key across consecutive scans before acting
Record, Playback, and Compose
Mode flags set by the debounce FSM move the device between live tone, record, playback, and compose modes. While recording, a dedicated protothread samples the slider frequency into a per-key buffer, so you can sweep the pitch to sketch a chirp and assign it to a digit. Pressing that digit replays the sound, and compose mode queues several recorded keys to play back as a sequence.
Results
The system produced clean, stable tones up to several kHz, including a 4.7 kHz output captured on the oscilloscope and heard by Merlin as a bird. Merlin did not identify a Northern Cardinal, but it picked up the synthesized sound as a bird and displayed a spectrogram of the chirps. Along the way we learned to structure multi-task embedded firmware with protothreads and interrupts and to combine mixed-signal peripherals (ADC, DAC, SPI) into one system.