Hi
I have a project that sends scan commands sequentially over a serial port to a Spectrum Analyser (TinySA).
For each scan I have to wait for the data to be completely received, 21 lines of data viz:
527000000 -1.192500e+02 0.000000000<LF>...
The scan commands are initiated by a timer in Main:
The timer tick calls code in a code module name SaCom.scanBandsAndAverage:
This sub loops around the data acquired in each band data set and averages them, on a frequency point basis calling the sub : scanAllBandsForThisSignalSet. with each loop iteration the sub should wait for saAllScansComplete but it does not. If I comment out the CallSubDelayed(Me, "saAllScansComplete") In the saAllScansComplete sub the wait for is ignored and the sub completes.
Thje same happens with the saAllScansComplete resumable sub called by scanAllBandsForThisSignalSet. See below.
The scanAllBandsForThisSignalSet loops around the separate bands and sends write commands to the serial port using: Main.writeCmdSerial.
The data returned from the TinySA is captured by Main.AStream_NewData which calls SaCom.processCmdRx(Buffer)
The sub SaCom.processCmdRx(Buffer) selects the appropriate function for the current command that has been sent to the TinySA:
For the "scan" command CallSubDelayed(Me, "saDataReceived") is called to signal that the data has been recieved and processed. The data is processed by cleanUpScanData(Buffer) which loops around the received data until all of the scan resords are collected and processed:
This sub was copied and modified from Erel's AsyncStreamsText module. I wasn't sure if I should use subs or delayed subs, but with either, the wait for resunableSubs did not wait. If I do a single scan the data is returned OK usually in multiple "packets" which the cleanup sub converts to multiple lines with a <LF> appended for data extraction by the checkAndProcessScanLine subs
I don't know what the problem is. I've used resumable subs before to handle serial data streams, but only in prefix mode over ethernet, (WiFi). I can't use prefix mode with the TinySA as it just sends raw UTF8 back to the pc with varying size depending on the command and config of the device.
I've googled, looked through the community and watched Erel's video on resumable subs, but I can't see what I'm doing wrong. I suspect it has something to do with the recursive calls of astream_newdata, but I'm not sure.
Can anyone help?
I've posted a zip of the project.
I have a project that sends scan commands sequentially over a serial port to a Spectrum Analyser (TinySA).
For each scan I have to wait for the data to be completely received, 21 lines of data viz:
527000000 -1.192500e+02 0.000000000<LF>...
The scan commands are initiated by a timer in Main:
Scan Timer:
'--------------------------------------------------------------------------------------------
Public Sub scanTimer_Tick
If scanCompleteFlag = True Then
SaCom.scanBandsAndAverage
End If
End Sub
The timer tick calls code in a code module name SaCom.scanBandsAndAverage:
Scan Bands and Average:
'--------------------------------------------------------------------------------------------
Public Sub scanBandsAndAverage
Private scanResList As List
scanResList.Initialize
Main.AllProcessingComplete = False
Main.clearprogAverage
preAverageStartInit
'Do the averageing.
'If the average no specified is zero just do one avg otherwise do the number specified
If Main.Band_Data.SigSrcCurrentRecord.NoSpectrumAvgs = 0 Then 'Or Main.singleScannInitiated = True Then
'Scan all the frequency bands specified by the user and wai tof SA to complete
scanAllBandsForThisSignalSet
wait for (saAllScansComplete) Complete(ret As Boolean)
Else
For noAverageCount = 0 To Main.Band_Data.SigSrcCurrentRecord.NoSpectrumAvgs
scanAllBandsForThisSignalSet
wait for (saAllScansComplete) Complete(ret As Boolean)
Next
End If
create_dBm_CurveForPlotting
Main.Band_Data.plotSpectrumOnMainGraph
Main.singleScannInitiated = True
Main.AllProcessingComplete = True
End Sub
This sub loops around the data acquired in each band data set and averages them, on a frequency point basis calling the sub : scanAllBandsForThisSignalSet. with each loop iteration the sub should wait for saAllScansComplete but it does not. If I comment out the CallSubDelayed(Me, "saAllScansComplete") In the saAllScansComplete sub the wait for is ignored and the sub completes.
The two signalling resumable subs:
'======================================================================================================
Sub saDataReceived() As ResumableSub
Sleep(0)
Return True
End Sub
'======================================================================================================
Sub saAllScansComplete() As ResumableSub
Sleep(0)
Return True
End Sub
Thje same happens with the saAllScansComplete resumable sub called by scanAllBandsForThisSignalSet. See below.
Scan all bands for this signal set:
'--------------------------------------------------------------------------------------------
Public Sub scanAllBandsForThisSignalSet
Dim bList As List
bList.Initialize
Main.progBandScan.Progress = 0
Dim count As Int = 0
bandIndex = 0
Main.AllScansCompleteFlag = False
bList = Main.Band_Data.MbandList
For Each Record() As Object In bList
setBandSweepAndScan(Record(0), Record(1), Record(2), Record(11), Record(10), Main.Band_Data.SigSrcCurrentRecord.RBW_Khz)
' Wait for processing complete before sending another command
Wait For (saDataReceived) Complete(ret As Boolean)
bandIndex = bandIndex + 1
Next
Main.AllScansCompleteFlag = True
CallSubDelayed(Me, "saAllScansComplete")
End Sub
The scanAllBandsForThisSignalSet loops around the separate bands and sends write commands to the serial port using: Main.writeCmdSerial.
Write command to the TinySA over the serial port:
'--------------------------------------------------------------------------------------------
Public Sub writeCmdSerial(cmdStr As String)
Dim str As String
str = cmdStr & Chr(13)
byteBuffer = bc.StringToBytes(str, "UTF8")
astream.Write(byteBuffer)
End Sub
The data returned from the TinySA is captured by Main.AStream_NewData which calls SaCom.processCmdRx(Buffer)
AStream_NewData:
'--------------------------------------------------------------------------------------------
Private Sub AStream_NewData (Buffer() As Byte)
Dim s As String = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
SaCom.processCmdRx(Buffer)
End Sub
The sub SaCom.processCmdRx(Buffer) selects the appropriate function for the current command that has been sent to the TinySA:
Process the received data:
public Sub processCmdRx(Buffer() As Byte)
replyError = False
tempStr = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
Select cmd
Case "pause"
checkReplyForErrorsShortCmds("pause")
Main.dataReceivedFlag = True
Case "lna"
checkReplyForErrorsShortCmds("lna")
Main.dataReceivedFlag = True
Case "lna2"
checkReplyForErrorsShortCmds("lna2")
Main.dataReceivedFlag = True
Case "attenuate"
checkReplyForErrorsShortCmds("attenuate")
Main.dataReceivedFlag = True
Case "rbw"
checkReplyForErrorsShortCmds("rbw")
Main.dataReceivedFlag = True
Case "trace reflevel"
checkReplyForErrorsShortCmds("trace reflevel")
Main.dataReceivedFlag = True
Case "resume"
checkReplyForErrorsShortCmds("resume")
Main.dataReceivedFlag = True
Case "scan"
' Log(tempStr)
cleanUpScanData(Buffer)
Main.dataReceivedFlag = True
CallSubDelayed(Me, "saDataReceived")
End Select
End Sub
For the "scan" command CallSubDelayed(Me, "saDataReceived") is called to signal that the data has been recieved and processed. The data is processed by cleanUpScanData(Buffer) which loops around the received data until all of the scan resords are collected and processed:
Clean up scan data:
Private Sub cleanUpScanData(buffer() As Byte)
Dim newDataStart As Int = sb.Length
sb.Append(BytesToString(buffer, 0, buffer.Length, charset))
Dim s As String = sb.ToString
Dim start As Int = 0
For i = newDataStart To s.Length - 1
Dim c As Char = s.CharAt(i)
If i = 0 And c = Chr(10) Then '\n...
start = 1 'might be a broken end of line character
Continue
End If
If c = Chr(10) Then '\n
CallSubDelayed2(Me, "checkAndProcessScanLine", s.SubString2(start, i))
' checkAndProcessScanLine(s.SubString2(start, i))
start = i + 1
Else If c = Chr(13) Then '\r
CallSubDelayed2(Me, "checkAndProcessScanLine", s.SubString2(start, i))
' checkAndProcessScanLine(s.SubString2(start, i))
If i < s.Length - 1 And s.CharAt(i + 1) = Chr(10) Then '\r\n
i = i + 1
End If
start = i + 1
End If
Next
If start > 0 Then sb.Remove(0, start)
End Sub
This sub was copied and modified from Erel's AsyncStreamsText module. I wasn't sure if I should use subs or delayed subs, but with either, the wait for resunableSubs did not wait. If I do a single scan the data is returned OK usually in multiple "packets" which the cleanup sub converts to multiple lines with a <LF> appended for data extraction by the checkAndProcessScanLine subs
I don't know what the problem is. I've used resumable subs before to handle serial data streams, but only in prefix mode over ethernet, (WiFi). I can't use prefix mode with the TinySA as it just sends raw UTF8 back to the pc with varying size depending on the command and config of the device.
I've googled, looked through the community and watched Erel's video on resumable subs, but I can't see what I'm doing wrong. I suspect it has something to do with the recursive calls of astream_newdata, but I'm not sure.
Can anyone help?
I've posted a zip of the project.