FYI here is my test code:
// Test of timing for reading analog sound signal
Define PinMode Pin8 As AnalogInput
//spi test
Define PinMode Pin5 As DigitalOutput
Class SoundTest
Shared jdata As Json
Shared spi1 As ExternalSPI
Shared numberofsamples As Integer
Shared mqtt_data As ListOfByte
Shared mqtt_topic As String
Shared running As Boolean //crude mutex
Shared Event Boot()
Lplan.SetMidPowerMode(5000)
numberofsamples = 128 // a sample is 2 bytes
jdata = New Json
spi1 = New ExternalSPI
mqtt_topic = "MCThings/" + Device.mcUID().ToString("X8") + "/"
mqtt_data = New ListOfByte
mqtt_data.Add("Booted")
Lplan.Publish(mqtt_topic + "Status", mqtt_data)
//SoundTest.runallTest()
End Event
Shared Event runtests() RaiseEvent Every 1 Minutes
If running Then
Return
End If
' mqtt_data.Clear()
' mqtt_data.Add(numberofsamples.ToString)
' Lplan.Publish(mqtt_topic + "numsamples", mqtt_data)
If numberofsamples > 4096 Then
numberofsamples = 128
End If
SoundTest.runallTest()
numberofsamples *= 2
End Event
Shared Sub runallTest()
If running Then
Return
End If
running = True
SoundTest.testAnalog()
Thread.Sleep(10000000)
SoundTest.testSPISingle()
Thread.Sleep(10000000)
SoundTest.testSPIContinuous()
Thread.Sleep(10000000)
running = False
End Sub
Shared Function testAnalog() As Nothing
//test read analog pin
SoundTest.LEDFlash()
Dim Values As ListOfShort = New ListOfShort
Dim duration As Integer = Device.GetTimeSpan()
For count As Integer = 0 To numberofsamples - 1
Values.Add(Pin8)
Next
duration = Device.GetTimeSpan()
SoundTest.Publish("analog", duration, Values.Count)
End Function
Shared Sub testSPISingle()
//test read spi single
SoundTest.LEDFlash()
Dim Values As ListOfShort = New ListOfShort
Dim value As Short
Dim duration As Integer = Device.GetTimeSpan()
For count As Integer = 0 To numberofsamples - 1
Values.Add(spi1.Read)
Next
duration = Device.GetTimeSpan()
SoundTest.Publish("spi_single", duration, Values.Count)
End Sub
Shared Sub testSPIContinuous()
//test spi continuous reads
SoundTest.LEDFlash()
Dim duration As Integer = Device.GetTimeSpan()
Dim Bytes As ListOfByte = spi1.Read(numberofsamples * 2)
duration = Device.GetTimeSpan()
Dim Values As ListOfShort = New ListOfShort
Dim value As Short
' For count As Integer = 0 To Bytes.Count() - 2 Step 2 //does not work for some reason
' value = Bytes.ExtractShort(count)
' Values.Add(value)
' Next
Dim count As Integer = 0
While count < Bytes.Count()
value = Bytes.ExtractShort(count)
Values.Add(value)
count += 2
End While
SoundTest.Publish("spi_continuous", duration, Values.Count)
End Sub
Shared Sub Publish(test As String, duration As Integer, samples As Integer)
Dim uspersample As Float = duration / samples
mqtt_data.Clear()
jdata.Clear()
jdata.Add("test", test)
jdata.Add("duration_us", duration)
jdata.Add("samples", samples)
jdata.Add("us_per_sample", uspersample)
mqtt_data.Add(jdata.ToString)
Lplan.Publish(mqtt_topic + "Data", mqtt_data)
End Sub
Shared Function LEDFlash() As Nothing
LedGreen = True
Thread.Sleep(3000)
LedGreen = False
End Function
End Class
Class ExternalSPI
//class to read external spi sensor
Shared sensor As Spi
Public Sub New()
Pin5 = True
sensor = Spi.Create(125000, 0, Pin.Pin0, Pin.Pin1, Pin.Pin3, Pin.Pin5) //125KHz spi interface
End Sub
Public Function Read() As Short
//read single short value
Return Read(2).ExtractShort(0)
End Function
Public Function Read(numbytes As Integer) As ListOfByte
//read data (number of bytes)
Dim data As ListOfByte = New ListOfByte
data.AddElements(numbytes) 'size of data to read
data = sensor.Transfer(data)
Return data
End Function
End Class
and here are my results:
[I 2017-01-30 15:14:07,373] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 7721,
"samples": 128,
"us_per_sample": 60.320312
}
[I 2017-01-30 15:14:19,119] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_single",
"duration_us": 34790,
"samples": 128,
"us_per_sample": 271.796875
}
[I 2017-01-30 15:15:37,063] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 34882,
"samples": 256,
"us_per_sample": 136.257812
}
[I 2017-01-30 15:15:47,164] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_single",
"duration_us": 89203,
"samples": 256,
"us_per_sample": 348.449219
}
[I 2017-01-30 15:16:00,304] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_continuous",
"duration_us": 32989,
"samples": 256,
"us_per_sample": 128.863281
}
[I 2017-01-30 15:17:07,292] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 125183,
"samples": 512,
"us_per_sample": 244.498047
}
[I 2017-01-30 15:17:17,535] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_single",
"duration_us": 234772,
"samples": 512,
"us_per_sample": 458.539062
}
[I 2017-01-30 15:17:27,902] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_continuous",
"duration_us": 65796,
"samples": 512,
"us_per_sample": 128.507812
}
[I 2017-01-30 15:18:38,242] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 457550,
"samples": 1024,
"us_per_sample": 446.826172
}
[I 2017-01-30 15:20:11,731] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 1731659,
"samples": 2048,
"us_per_sample": 845.536621
}
[I 2017-01-30 15:20:23,723] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_single",
"duration_us": 2169586,
"samples": 2048,
"us_per_sample": 1059.368164
}
[I 2017-01-30 15:20:35,235] MCThings/00011532/Data : Decoded JSON:
{
"test": "spi_continuous",
"duration_us": 262909,
"samples": 2048,
"us_per_sample": 128.373535
}
[I 2017-01-30 15:21:53,454] MCThings/00011532/Data : Decoded JSON:
{
"test": "analog",
"duration_us": 6834015,
"samples": 4096,
"us_per_sample": 1668.460693
}
There are a few publishing's missed, but you get the idea.
As you can see the time per sample (sample is 2 bytes) goes up with the number of samples, except for the continuous spi read test. It seems that the individual reads take place at the expected rate, but after a certain number of reads (or time) there is a delay (probably while the OS does something else). The continuous spi read test does not do this, as I suspect the spi read is atomic, and can't be interrupted. So one long read always takes the same time per byte, but multiple reads gets split up into time sliced chunks by the OS, so overall it slows down by the number of chunks read at a time. The more chunks, the slower it gets.
I was hitting 3.2ms per sample (2 bytes) at 8096 reads.
Any ideas on how to work around this? I know it's an extreme case, but there are probably other circumstances where you don't want successive reads/writes delayed by random amounts. Something like Thread.preventInterrupt(True) guards you could put around time critical code.