Built a Dual-Channel Oscilloscope with a PSoC-5 and a Raspberry Pi 3 B+
The PSoC handles converting the analog voltage signal into a digital with the ADC and a DMA controller sends those bytes to ping pong buffers. The buffers are each 64 bytes and take turns being filled up by the DMA. Once one of the two buffers are filled the DMA signals an interrupt that signals the USBFS to send over the 64 bytes to the Raspberry Pi side. When one buffer is filled the DMA switches to the other buffer and will swap between the two filling and sending thus ping ponging to ensure no data is lost. There are two SAR ADC's which both boast incredibly fast sampling rates of roughly 1M samples per second and as such the DMA clock is what controls the sampling rate. There is another ADC conversion for the two potentiometer values that will handle moving the waveforms up and down. On the right is the entire top design of the PSoC which has the USBFS component, I2C configured as a slave, ping pong buffers with respective DMA controllers, and the multiple of ADC's
The key decisions made were to have the PSoC only handle transferring the ADC values from the analog signal with USBFS protocols and send over potentiometer values over through the I2C link. So as such the Pi and PSoC are connected with a micro USB cable and wiring with both the SDA and SCL pinouts. The Raspberry Pi powers the PSoC with a 3.3V pin. This means that the PSoC can only handle amplitudes of the analog signal less than 3.3V. Both the I2C link and the USB transfer are configured for the PSoC as the slave and the Pi as the master.
Because the oscilloscope needs to be able to change the sample rate, an I2C link is required to send commands from the Raspberry Pi side to clock divide the DMA controller and have the PSoC send over potentiometer values every 100ms. The I2C can handle a two way connection simulatensouly and helps enable the USB link to focus only on transfering the data bytes of the signal. When a user wants a certain frequency such as 10kHz the program will send the respective integer 10 that will clock divide from 100KHz clock driving the DMA controller to the desired 10KHz. And potentiometer values are sent over the link every 100ms to change the height of the waveforms on the Pi side.
The entire program starts when the user runs the program with their desired parameters (the specfic parameters will be discussed in the next section). The Pi starts by filling up the calculated sample size buffer from the USB, each time grabbing 64 bytes and continues to do so until the sample size is reached. Once that sample size is reached the program checks if a trigger mode is set, if so the program processes the trigger to see if the waveform satisfies the condition. The program then shifts to displaying the waveform where it takes the sample size buffer and converts each point into coordinates ready to be displayed through OpenVG. While displaying the program repeats itself taking another set sample size buffer and once the buffer is filled the waveform will refresh itself on the display. Once the waveforms are displayed the user can move the potentiometers to adjust the waveforms' heights
The oscilloscope system can take a user’s input of trigger mode, trigger level, trigger slope, sample rate, trigger channel, x scale, and y scale (using characters m, t, s, r, c, x, y respectively). For trigger mode choose between free mode or trigger mode where free mode will simply output the plot waveform without any conditions and trigger mode will take the set trigger level, slope, and channel and compare the level to the signal to see if it satisfies the conditions based on the set slope. The slopes you can choose from are either positive or negative. Sample rate changes how many samples the program will get per second. Trigger channel sets which signal channel to use to check the trigger conditions. X and y scale set how many microseconds and mV per division when displaying the oscilloscope. There are set values predefined and if the user does not know if an input is valid the program will print out all the valid inputs for that specific character.
When the user sets the mode to trigger the program takes user's user’s trigger level, channel, and slope to determine when to start the plot of the waveform. The conditions to satisfy the trigger for positive slope is shown below:
The conditions to satisfy the trigger for negative slope is shown below:
The program will iterate through the sample size array until it reaches the trigger conditions and returns the index at which the exact conditions were met to start plotting. If the trigger conditions are never met the program grabs another set of the sample size to try again and see if the conditions will be met.