Signed in as:
filler@godaddy.com
Here you will find some exemplary projects of my time as a computer engineering student at U of M. They range from semi-autonomous robots to machine learning classification, CPU architectures and beyond.
My team and I wanted to create a pedal that would allow guitarists to create and loop a drum pattern with their guitar and then use it to help build a song or just to practice along with it. Rotary encoder knobs select the drum preset they would like to use, such as: rock, jazz, pop, hip-hop, techno, etc.. To select/change the preset, we included a few buttons: select, back, and reset. The select button, when hovering over the desired preset, selects that preset for use when the guitarist is ready and puts the device in the Idle state where the guitar signal is passed through to the amp. To activate the pedal, the user must stomp on the main pedal button located at the bottom of the device to set it into Live mode. In Live mode, the notes on a guitar correspond to a drum beat, and any time the guitarist plays a single note, it translates and plays the drum beat mapped to that particular note. For example, E2 could map to a kick drum, A2 could map to a snare, C2 could map to a hi-hat, G3 could map to a cymbal, and so on.
This note analysis task has hard-real time constraints, insofar as they need to execute fast enough so the delay between the musician playing the guitar and hearing the beat is imperceptible. In this vein, we set a goal of detection and translation for 20ms of latency, since this is the limit for humans distinguishing notes, and we ended up with a latency of around 40ms. In designing our system, we quickly discovered that the processors which are powerful enough to perform this task are much too difficult to solder by hand since they tend to have a BGA footprint. This is partially why we ended up choosing the Teensy 4.1 board to work with. The Teensy’s CPU, an ARM-M7 core clocked at 600MHz with dedicated hardware for floating-point math and FFTs, really gave us room to work with and allowed us to come close to our timing constraints. We were not concerned with power consumption because the pedal is always plugged into wall power during use. At a low level, we take input from the guitar at the right port, from a standard instrument cable, and process it with the onboard ADC from a WM8731 audio codec. This data is then sent to the Teensy 4.1 using the I2S protocol and out through the left port.
During the note-to-drum translation process, the Teensy performs an FFT to help perform onset detection and runs the YIN algorithm to perform note detection. Once the Teensy has determined a note has occurred and finds the frequency, the frequency is converted to a note identifier and then the note is used to select a sample from the SD card. The sample is then triggered to stream to the I2S output. The codec converts this I2S stream into an analog signal, which is also wired to a standard instrument cable. The user can connect this to an external guitar amplifier or speaker cabinet. During live translation, this is the only code running so that detection latency is minimized. During the recording stage, each detected note is stored to memory as a timestamp and sample index. After recording, during the playback state, the codec is reconfigured to mix the guitar input with the digital data received on the I2S bus. At this point, the Teensy uses the recorded timestamp information to repeatedly recreate the drumbeat and stream it to the codec until the pedal goes back into the Idle state. When in an Idle state, the onset and note detection functions are halted, and the user interface updates the VFD based on user input. The Teensy is set up with interrupts for each button, encoder, and volume potentiometer, and periodically performs partial updates to synchronize the VFD with the UI state. Below, our finished product in the stainless steel case I manufactured by hand.
A few major themes of my OS course at the University of Michigan were abstraction, concurrency, and indirection. In this vein, my team and I implemented a multi-threaded, secure network file server where I gained experience in building hierarchical file systems, socket programming, client-server systems, and security protocols. The project gave me experience building a large (1000+ LOC) multi-threaded program.
An example of how our system locks shared data on a volume being used by two different clients is depicted to the left, or above if on mobile.
One of the many bugs we faced while implementing this file server was in the use of shared locks. We spent a good amount of time debugging problems that came from ensuring all the shared instances of volumes used a shared lock while being read from and used an exclusive lock while being written to.
To gain an appreciation for the power of abstraction, indirection, and redundancy -more main themes - my team and I were tasked with designing and implementing a memory pager. This program manages application processes' virtual address spaces. The infrastructure we implemented (summarized by the image on the right, or above if on mobile) enables applications to create, copy, and destroy address spaces, allocate space in an existing address space, and switch between addresses. It further implements the interrupt handler for memory faults.
Some important ideas to improve performance were to defer as much work as possible for as long as possible in order to increase performance. This came in the form of copy-on-write page allocation and a (less than optimal) FIFO clock algorithm to schedule evictions. In writing a comprehensive test suite, like we did for each project, we found that our eviction algorithm was buggy and noticed we had to add intermediary states before certain pages were evicted.
As the first project in my OS course, to drive home the importance and power of concepts like concurrency and consistency, my team and I were tasked with building a thread library for a multi-core system. This included building definitions of threads, locks, and contexts. We needed to handle timer and inter-processor interrupts and have the library perform context swaps as necessary. We implemented the std::boost thread, mutex, and cv libraries without sephamores.
One of the main challenges we faced was figuring out the correct lifetime of a thread and when its context should be deleted. Another challenge was trying to optimize for inter-thread performance while keeping the shared data resources thread-safe. From this project I gained a deep understanding of how an OS handles multi-threaded programs.
Here I present a semi-autonomous robot with the goal of navigating to the light source while avoiding the obstacles. I used HAL-Drivers along with bare metal programming to interface with the peripherals and a simple localization and avoidance algorithm to control the robot's movements.
Object detection is done using a continuous forward sweep of an ultrasonic sensor at the front of the bot. Light detection is done by reading values from a photodiode and processing via an analog circuit.
In the first project for Machine learning, I used Support Vector Machines (SVMs) and trained models to deduce the sentiment of Amazon book reviews. I was given a large set of review data from Amazon’s catalogue of book reviews, and extracted important features (words & phrases), then trained multiple different classifiers using linear and quadratic kernels of SVMs. For both linear-kernel and quadratic-kernel SVMs, I selected the hyperparameters using 5-fold cross-validation (CV) on the training data. I selected the hyperparameters that led to the ‘best’ mean performance across all five folds. I considered the following performance measures: Accuracy, F1-Score, AUROC, Precision, Sensitivity, and Specificity. The report and source Python is presented in the PDF below.
As a final project in this graduate level class, a partner and I synthesized everything we had learned about quantum information science and authored this report which summarizes and explains the problem of quantum decoherence. We talk about the measurement and preferred basis problem, environment induced decoherence, present an example of a coin flip, and offer a brief interpretation of how quantum decoherence is responsible for our macro-scale observations.
Copyright © 2021 Dino Mastropietro - All Rights Reserved.
Powered by The Goose S.C.