B4J Question ResumableSub - Wait For (resub) Complete(ret as Boolean) Not waiting - Runs through

rgarnett1955

Active Member
Licensed User
Longtime User
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:

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.
 

Attachments

  • RFChannelMonitor.zip
    162.3 KB · Views: 95
Top