Software Unit Tests
Small tests of individual features of the Saucer Platform mentioned in Software Integration. Each demonstrates a single feature.
Basic Tests(Primitives)
DacWrite
This is an important test for any output chip: we need a baseline audio output signal, on any pin you can get it.
There are 3 different examples, each at a different level of the API. analogRead(), from 1, calls dac_write_value() at level 2, which calls HAL_DAC_* at 3.
For the extra setup code using HAL_DAC directly, you get a 10x speedup on the Nucleo 476 and 432! (More accurately, you get a 10x slowdown if you do it the other way).
A uint8_t wraps around to create a sawtooth waveform.
Observed period ~= 200us / 256 = .78ns Freq=1.2 MHz
L476RG Channel 1 L476RG Channel 2 ~2-4 us settling time(full range)
TimerInterrupt
This test will determine if we can stay in tune. Get a regular callback function firing, toggling the state of a pin each time. measure output frequency against expected for a range of frequency values.
AnalogRead
Read as many values from the ADC at once as possible. Output values over serial connection.
TODO: see if we get any benefit from channel setup and pin positioning.
DigitalRead
Read as many digital values as possible. Output values over serial connection.
TODO: multiplexing scan matrix logic, n-key rollover, etc.
Integration Tests
Level 1
Tone440
DacWrite + TimerInterrupt
Output an audible 440Hz tone to any available pin. Simple square wave output will suffice to demonstrate if the instrument can stay in tune. Sine wave is nicer.
PWM is a decent standin for platforms without a DAC.
TODO: What will it sound like if the chip can't keep up as programmed with the sample rate? High harmonics?
Combined Input
DigitalRead + AnalogRead
Read as many digital and analog inputs as possible, simultaneously. See which pins conflict. Rearrange pins for maximum input channels on the board.
Level 2
Simple Synth
DigitalRead + Tone440
Instrument01 https://bitbucket.org/DIY_Instruments/electric_eel_markii/src/master/arduino/stm32duino/Instrument01/
Read as many digital pins as possible, each one triggering a note of a different frequency. Makes a great wiring test!
Instrument02 https://bitbucket.org/DIY_Instruments/electric_eel_markii/src/master/arduino/stm32duino/Instrument02/
A basic monophonic instrument implementation, choose between voices, pick note and fret keys.
Instrument_BlueDog https://bitbucket.org/DIY_Instruments/electric_eel_markii/src/master/arduino/stm32duino/Instrument_BlueDog2/
The Blue Dog, still under development. Pulls off 4-voice Karplus-Strong polyphony on a 432KC.
PitchKnob
AnalogRead + Tone440
Source: https://bitbucket.org/DIY_Instruments/electric_eel_markii/src/master/arduino/stm32duino/PitchKnob/PitchKnob.ino
Read one analog pin, altering the 440Hz frequency of the output.
Discovery: the arduino function analogRead initializes and tears down the ADC channel every read! This is so inefficient that the naive implementation of this test has visible plateau artifacts in the output waveform.
Using a more efficient analog read function that initializes only once, preliminary results are captured on pin PB_0(Channel 15):
L476RG Result: Each analog read adds ~100us read/polling time.
0 reads 1 read 2 reads 3 reads
TODO Read analogs non-blocking, or overlapped
Optimizations
Short-term, high-value things :
- let's background the process. basically, we poll in software, but don't block. when conversion is complete, we configure for the next channel.
- Let's shorten the SAMPLETIME for the ADCs. we can check the ref to see the smallest possible value. (we should make sure short sample times don't create too much noise).
Longer term, heavier lifting, perfectionist stuff
- Optional: configure multiple ADCs to do conversions for us. This is a good way to go for combining fast reads with slow ones. e.g. knobs can be done at 100-3000Hz.
- We can set up the hardware to do that backgrounding for us. SQR_ register
Jan 11, 2018:
Some googling on the topic discovered these threads:
https://stackoverflow.com/questions/42790936/stm32-adc-continuous-conv-mode-does-not-automatically-start-conversion
https://visualgdb.com/tutorials/arm/stm32/adc/
https://electronics.stackexchange.com/questions/202938/stm32-adc-conversion-using-hal/202952#202952
https://community.st.com/s/question/0D50X00009XkYVXSA3/stm32-adc-and-continuous-conversion-mode
Changing the flag to EOC_SEQ_CONV did not have the desired effect, however.
We should be able to call HAL_ADC_Start just once, and poll and read repeatedly after that. When attempting to do so, no data is read(wave does not change frequency).
The hardware must be fine - as repeatedly initing, reading and destroying works.
Level 3
SensorSynth
SimpleSynth + PitchKnob
With a few responsive analog sensors, an instrument can be made. Any leftover resources the chip/platform has at this point can be devoted to software synthesis.
Power-on to audio time delay test.
9/25/2018
HW: STM32L476 Nucleo
SW: Tone440, based on analogWrite()
Result: 100ms from power-on to sinusoid.
Discussion: Far too slow for Electric Eels. Possibly limited by "analogWrite()"? But more likely in setup
SW: Instrument01, based on writeDacData() / HAL_DAC_SetValue()
Result: 100ms from power-on to sinusoid
Discussion: Possibly setupDac() which calls:
HAL_DAC_DeInit()
HAL_DAC_Init()
HAL_DAC_ConfigChannel()
HAL_DAC_SetValue()
HAL_DAC_Start()
Experiment: instrumented Instrument01/setupDac() with digitalWrite(debugTimingPin, *) calls.
All six calls within setupDac took place within 75us! That's fast enough...
First call took place approximately 5ms after turn on. That's not quite fast enough.
Questions:
1. What is happening in first 5ms?
Only call is to FireCbAtFrequency(), which does make calls to TimerPulseInit() and TimerHandleInit
2. What happens in 95 ms following setupDac()?!
Main calls are to digital_io_init(). Where is that function? What does it do?
Also Observed: startup time is much faster when USB cable is plugged into board, even though external battery power is used! ???
Control Timing Test
The latest Instrument01 has debug timing outputs on pins 2 and 3 to show timing. With audio rate at 60kHz, the board is freezing on certain instruments.
Some instruments take more control time than others.
Questions:
- Why is the board becoming unresponsive?
- Is there a way we can lay out computation for better response time?
- What's is the optimal audio rate? How high can we push that?
- Will we get better performance from fixed point math?
Comments (0)
You don't have permission to comment on this page.