I am developing signal generator Windows Iot universal javascript application to Raspberry Pi 2.
I connected MCP4921 DAC to it thru SPI.
What I am trying to do is to generate sine wave with given frequency, amplitude and offset. I already got device working, but when I try to produce accurate wave, application is to slow even 10 Hz accurate sin wave.
Currently wave is generated like this.
var Spi = Windows.Devices.Spi;
var Enumeration = Windows.Devices.Enumeration;
var frequency = 10;
var ts = 1 / frequency;
var updateFreq = ts / 100;
var time = 0;
var offset = 2;
var amplitude = 2;
var resolution = 4095;
var voltage = 5;
var settings = Spi.SpiConnectionSettings(0);
settings.clockFrequency = 2 * Math.pow(10, 7);
settings.mode = Spi.SpiMode.mode0;
var ags = Spi.SpiDevice.getDeviceSelector();
Enumeration.DeviceInformation.findAllAsync(ags, null).done(dis => {
Spi.SpiDevice.fromIdAsync(dis[0].id, settings).done(device => {
for (; ;) {
var value = offset + amplitude * Math.sin(2 * Math.PI * frequency * time);
var dacValue = parseInt(resolution / voltage * value);
if (dacValue > resolution) dacValue = resolution;
time += updateFreq;
if (time > 1000) time = 0;
var buffer = new Uint8Array(2);
buffer[0] = 0x30 | (dacValue >>> 8);
buffer[1] = 0xFF & dacValue;
device.write(buffer);
}
});
});
I tried to use setInterval, I know that it is not good practice, it wait's atleast 10 ms before runs again.
Is there any ways to modify raspberry timer, clock, or whatever to run custom interrupt ISR function on every 0.1 ms?
I already looked dma registers at BCM2835 Datasheet and BCM2836 Datasheet datasheet. I can't find any solutions how to manage Raspberry Pi clock interruptions, only on pin interruptions.
I also know how to do it in Arduino Uno, but it won't help me as I don't know how to manipulate raspberry registers.
Here is image of generated sine wave.
Thanks in advance.
If possible, you can try to use LUT for sine generation because these lines:
var value = offset + amplitude * Math.sin(2 * Math.PI * frequency * time); var dacValue = parseInt(resolution / voltage * value);
are very time consuming. Essentially, with LUT, you need pre-generated samples of the sine wave and store them in RAM.
If your intention is to calcualte the sine-wave value by counting the elapsed time, I don't think you should be using
`time += updateFreq;`
in the first place. This way, you're counting on software timing, you might end up with seriously skewed waveforms. I would suggest using a timer.
Windows IoT is not a real-time operating system. Even if using high-resolution timer it can't repeat operations in extremely accurate intervals(<1ms) due to software timing uncertainty.
I don't think interrupt ISR can solve your problem because it is also implemented based on OS layer.
As you mentioned you may try using DMA mode of the SPI. But, unfortunately, it seems no valid driver to manipulate SPI DMA relate registers of Raspberry both in Arduino and Windows IoT core. So, you may need write the driver by yourself. This is about development of device drivers for the Microsoft Windows platform. Pwm is a BCM2836 driver using DMA on Windows IoT core you can reference.