B4R Question Exit from loop stops timer!

Mostez

Well-Known Member
Licensed User
Hello,
I have a function with do-while loop that reads lines from SD card file then send it to async stream object. this function returns true or false according to SD card read status. I have also main timer runs in background to display date\time and some parameters. every thing runs very well, but if this function returns false the time completely stops(timer temporarily stops when loop runs), but the software runs OK, only the timer stops! any ideas what to do.

Thanks

B4X:
private Sub CommandHandler(Buffer () As Byte, StreamSource As Byte)   
   
    If ReadRFIDbusy = True Or CommandBusy = True Then
        Return
    End If
   
    IndicateAll(False,False,False)
    CommandBusy = True
    IndicateBusy(True)
    StartDisplayTimeout
   
    Dim BufferLength As Byte = Buffer.Length
    Dim BufferHeader As Byte = Buffer(0)
    Dim Command As Byte = Buffer(1) 'read = 1 write = 0
    Dim RegisterID As Byte = Buffer(2) 'register id, i.e. register 0x01 = date time register
    Dim FrameLength As Byte = Buffer(3) 'length of frame
    Dim BufferEndofTransmission As Byte = Buffer(BufferLength - 1)
   
    End If   
Select RegisterID
        Case REG_DATE_TIME
            If Command = CMD_WRITE Then
                SetRTCDateTime(Buffer(4) + 2000,Buffer(5),Buffer(6),Buffer(7),Buffer(8),Buffer(9),Buffer(10))
                SendStreamMessage(ERR_PC_NO_ERR,StreamSource)
            Else IF Command = CMD_READ Then
                SendStreamMessage(Array As Byte (0x02,CMD_READ,REG_DATE_TIME,0x0C,Years - 2000,Months,DayOfMonth,DayOfWeek,Hours,Minutes,Seconds,0x04),StreamSource)
            End If
            NotifyCommand(True)
            Return
       
       
        Case REG_FILE '<<<<< this will call upload file
            Dim StringStart As Byte = Buffer(4)
            If StringStart <> 0x24 Then  'ASCII $
                SendStreamMessage(ERR_PC_DATA_START_CHR,StreamSource)
                NotifyCommand(False)
                Return   
            End If
            Dim fnl As Byte = BufferLength - 6 'length of file name = buffer length - 6 bytes
            Dim fnx As Byte = 5 ' file name starts from byte 5 in buffer
            Dim filename (fnl) As Byte
            BC.ArrayCopy2(Buffer,fnx,filename,0,fnl)
               
            If Command = CMD_READ Then
                Dim upl As Boolean
                upl = UploadFile(BC.StringFromBytes(filename),True,StreamSource)
                If upl Then
                    NotifyCommand(True)
                    Return
                Else
                    SendStreamMessage(ERR_PC_STREAM,StreamSource)
                    NotifyCommand(False)
                    Return
                End If
            End If


B4X:
Sub UploadFile (FileName As String,SendFileInfo As Boolean,StreamSource As Byte) As Boolean
    Dim BytesPerLine As Byte = 0x2A ' bytes per packet in log file excluding line feed chars
    Delay(1000)
    Dim success As Boolean = True
    If Sd.OpenRead(BC.StringFromBytes(FileName)) Then
        Dim size As ULong = Sd.CurrentFile.Size
        UPLOAD_FILE_SIZE = size
       
        Dim Tmp(15) As Byte 'compose file header array
        Dim RAF As RandomAccessFile
        RAF.Initialize(Tmp,False)
        RAF.WriteByte(0x02,RAF.CurrentPosition)
        RAF.WriteByte(CMD_READ,RAF.CurrentPosition)
        RAF.WriteByte(REG_FILE,RAF.CurrentPosition)
        RAF.WriteByte(0x0F,RAF.CurrentPosition)
        RAF.WriteBytes(NumberFormat(size+5,6,0).GetBytes,0,6,RAF.CurrentPosition) 'file size
        RAF.WriteBytes(NumberFormat(BytesPerLine,4,0).GetBytes,0,4,RAF.CurrentPosition) 'bytes per line
        RAF.WriteByte(Asc("$"),RAF.CurrentPosition)
        If SendFileInfo Then SendStreamMessage(Tmp,StreamSource)
       
        Dim counter As ULong = 0
        Dim Buffer(BytesPerLine) As  Byte
        Do While counter < size
            UPLOAD_PERCENTAGE = (counter / size) * 100
            Dim read As Int =  Sd.Stream.ReadBytes(Buffer, 0, Min(Buffer.Length, size - counter))
            If read = 0 Then
                success= False
                Exit
            End If
            counter = counter + read
            SendStreamMessage((BC.SubString2(Buffer,0,Buffer.Length-2)),StreamSource)
        Loop
        If SendFileInfo Then SendStreamMessage(Array As Byte (0x04),StreamSource)'Log(0x04) 'end of transmission
        Sd.Close
    Else
        success = False
    End If
   
    If success Then
        Return True
    Else
        Return False
    End If
   
End Sub


B4X:
Sub DS1320timer_Tick()

    Dim currenttime As DSTime
    currenttime = DS1302.CurrentTime

     Years = currenttime.years
     Months = currenttime.Months
     DayOfMonth = currenttime.DayOfMonth
     Hours = currenttime.Hours
     Minutes = currenttime.Minutes
     Seconds = currenttime.Seconds
     DayOfWeek = currenttime.DayOfWeek
     TimeTicks = TimeTicks + 1
     MinutesSerial = GetMinutsSerialNumber(Years,Months,DayOfMonth,Hours,Minutes)
     Blink = Not(Blink) 'toggle blink status, all blinking leds will blink at same time
    
     If TimeTicks > (TimeTicksLast + 5) Then
        For m = 0 To 13
            BufferLast(m) = 0  'reset comparison array
        Next
        EnableRFID(True)
    End If
    
     'If readRFIDbusy = False Or KeypadBusy = False Or CommandBusy = False Then ' no reading, start count
     If ReadRFIDbusy = False Or CommandBusy = False Then ' no reading, start count
         LCDdisplayTicks = LCDdisplayTicks + 1
        If LCDdisplayTicks >= SYS_LCD_TIMEOUT Then
            Sleep = True
            SetBacklightLevel(0x00,False)
            LCD.Clear
            LCD.DisplayOn = False
            LCD.CursorOn =False
            LCD.Blink = False
            IndicateAll (False,False,False)
            'ScreenType =  SCREEN_TYPE_MAIN '******************* change this in the future, but now we return to main screen if timeout occure at any place in code
            StandbyPowerLED.DigitalWrite(Blink) 'blink standby led
        End If
     End If
    
     If RFIDmode <> RFID_MODE_LOGGER Then
        OKReadyLED.DigitalWrite(Blink)
     End If
    
If ScreenType = SCREEN_TYPE_MAIN Then 'update date time on main screen only

    PutString(0,0,DayOfWeekArr(DayOfWeek - 1),False)
    'PutString(0,0,DayOfWeekArr(DayOfWeek-1),False)
    PutString (4,0,NumberFormat(Years,4,0),False)
    PutString (8,0,"-",False)
    PutString (9,0,NumberFormat(Months,2,0),False)
    PutString (11,0,"-",False)
    PutString (12,0,NumberFormat(DayOfMonth,2,0),False)
   
    PutString (5,1,NumberFormat(Hours,2,0),False)
    PutString (7,1,":",False)
    PutString (8,1,NumberFormat(Minutes,2,0),False)
    PutString (10,1,":",False)
    PutString (11,1,NumberFormat(Seconds,2,0),False)
   
    PutString (0,3,SigningArray(SigningMode-1),False)
    PutString (4,3,ReasonCodeArray(ReasonCode-1),False)
    PutString (8,3,LoadTypeArray(LoadType-1),False)
    PutString (11,3,RFIDmodeArr(RFIDmode-1),False)
End If

End Sub
 

Mostez

Well-Known Member
Licensed User
the download counter stops at count 2730, then program branches out of loop, sounds error beep, then back again(should not happen), counter incremented by 42 just for once (line length) everything stops at count 2772 (read variable always = 0)either with small or larger files!! i tried to send read buffer to stream object directly, counter reached 2436.

I checked files with notepad and hex file editor, they look OK, nothing wrong with them

is it related to stack, something i should handle (open, close, or re initialize..)

Do While counter < size
UPLOAD_PERCENTAGE = (counter / size) *
100
Dim read As Int = Sd.Stream.ReadBytes(Buffer, 0, Min(Buffer.Length, size - counter))
If read = 0 Then
success= False
Exit
End If
counter = counter + read
SendStreamMessage((BC.SubString2(Buffer,
0,Buffer.Length-2)),StreamSource)
Loop
 
Upvote 0

Mostez

Well-Known Member
Licensed User
I commented SendStreamMessage but did not upload the file to the end, i monitored the stack usage inside the loop on LCD
B4X:
PutString(0,3,NumberFormat(StackBufferUsage,5,0),False)

when it reaches 3019, read = 0 then exit loop occure. Is it possible to reset the stack?

B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 3000
#End Region
 
Upvote 0

Mostez

Well-Known Member
Licensed User
put string to print text on LCD, I'm so sorry for not posting the code, the stack is very stable, it is just gone crazy when I call that loop
B4X:
Sub PutString(x As Byte, y As Byte, PrnString As String,Center As Boolean)
        Dim Ln As Byte = PrnString.Length
        Dim Xc As Byte
        If Center Then
            Xc = (SYS_LCD_COLUMNS-Ln) / 2 'if print string centered, get center column
        Else
            Xc = x   
        End If
        LCD.SetCursor(Xc,y)
        LCD.Write(PrnString)
    End Sub
 
Upvote 0

Mostez

Well-Known Member
Licensed User
Ok, I would like to thank you so much Erel for your support, it works OK now, I replaced this line:

B4X:
SendStreamMessage((BC.SubString2(Buffer,0,Buffer.Length-2)),StreamSource)

with this one:

B4X:
SendStreamMessage(Buffer,Buffer.Length - 2,StreamSource) 'remove line feed

and modified SendStreamMessage to accept third parameter to select number of bytes to be sent to async stream object, BC.SubString2 is not used in loop anymore. so any other function inside the loop will make it unstable, i really don't know why stack is that sensitive to loops. As I know stack getting grow if called procedure does not return correctly to the address where it was called from.

B4X:
private Sub SendStreamMessage(Message() As Byte,BytestoSend As Byte,StreamSource As Byte)
    Dim ForSend(BytestoSend + 2) As Byte
    BC.ArrayCopy2(Message,0,ForSend,0,BytestoSend)
    ForSend(BytestoSend) = 0x0D
    ForSend(BytestoSend + 1) = 0x0A
   
    Select StreamSource
        Case SYS_STREAM_SOURCE_USB
             USBstream.Write(ForSend)
        Case SYS_STREAM_SOURCE_ETHERNET
            EthernetStream.Write(ForSend)
   End Select

End Sub
 
Upvote 0
Top