B4R Question looper return value and reuse

Mostez

Well-Known Member
Licensed User
Longtime User
Hello,
it is possible to use looper sub to return values ans accept parameters?, i.e. a function to calculate area. and is it possible to call same 'looper name' from different subs to do same job instead of creating looper for each sub.

what i really want to do is 'wait for user do press enter or cancel key and then get value i.e amount' and same thing also to wait for user to do the same, to enter quantity, two jobs can be done with same looper.

Thanks
 

Mostez

Well-Known Member
Licensed User
Longtime User
a timer scanning rows in 4x4 matrix keypad, when row changed event occur, I stop the timer and then compose row and col value to get keycode, then I decode it and a global variable(KeyValue) raised with pressed key value

B4X:
private Sub KBtimer_Tick()
    'NOTE: Avoid use of loops inside timer sub
    'KEYVAL BIT MAPPING
    '-------------------------------------
    'B7    B6    B5    B4    B3    B2    B1    B0
    'C3    C2    C1    C0    R3    R2    R1    R0
    '-------------------------------------

Select Case ColIndex
    Case 0
        RowIndex = 7 '0000 0111
        KBcolArray(0).DigitalWrite(False)
        KBcolArray(1).DigitalWrite(True)
        KBcolArray(2).DigitalWrite(True)
        KBcolArray(3).DigitalWrite(True)
    Case 1
        RowIndex = 11 '0000 1011
        KBcolArray(0).DigitalWrite(True)
        KBcolArray(1).DigitalWrite(False)
        KBcolArray(2).DigitalWrite(True)
        KBcolArray(3).DigitalWrite(True)
    Case 2
        RowIndex = 13 '0000 1101
        KBcolArray(0).DigitalWrite(True)
        KBcolArray(1).DigitalWrite(True)
        KBcolArray(2).DigitalWrite(False)
        KBcolArray(3).DigitalWrite(True)
    Case 3
        RowIndex = 14 '0000 1110
        KBcolArray(0).DigitalWrite(True)
        KBcolArray(1).DigitalWrite(True)
        KBcolArray(2).DigitalWrite(True)
        KBcolArray(3).DigitalWrite(False)
End Select

ColIndex = ColIndex + 1
If ColIndex = 4 Then ColIndex = 0

End Sub


B4X:
private Sub KBrow0_changed(State As Boolean)
    KeyPressed = Not (State) ' 0 means key pressed
    If State = False Then
        KBtimer.Enabled =False
        Delay(100) 'debounce key
        KeyValue = Bit.Or(RowIndex,0x70) 'compine row and column index i.e 0111 0000(0x70) with 0000 0111 = col 0 row 0
        KeypadBusy = True
        StartDisplayTimeout
        BeepClick
        KeyPressHandler(KeyValue)
        KeypadBusy = False
    Else
        KBtimer.Enabled =True
    End If
End Sub

private Sub KBrow1_changed(State As Boolean)
    KeyPressed = Not (State)
    If State = False Then
        KBtimer.Enabled =False
        Delay(100)
        KeyValue = Bit.Or(RowIndex,0xB0)
        KeypadBusy = True
        StartDisplayTimeout
        BeepClick
        KeyPressHandler(KeyValue)
        KeypadBusy = False
    Else
        KBtimer.Enabled =True
    End If
End Sub

private Sub KBrow2_changed(State As Boolean)
    KeyPressed = Not (State)
    If State = False Then
        KBtimer.Enabled =False
        Delay(100)
        KeyValue = Bit.Or(RowIndex,0xD0)
        KeypadBusy = True
        StartDisplayTimeout
        BeepClick
        KeyPressHandler(KeyValue)
        KeypadBusy = False
    Else
        KBtimer.Enabled =True
    End If
End Sub

private Sub KBrow3_changed(State As Boolean)
    KeyPressed = Not (State) ' 0 means key pressed
    If State = False Then
        KBtimer.Enabled =False
        Delay(100)
        KeyValue = Bit.Or(RowIndex,0xE0)
        KeypadBusy = True
        StartDisplayTimeout
        BeepClick
        KeyPressHandler(KeyValue)
        KeypadBusy = False
    Else
        KBtimer.Enabled =True
    End If
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I don't completely understand the code, however you I don't think that you need any looper for this.

You should maintain the state in a global variable and decide what to do based on the current state in KeyPressHandler.

You can for example do something like:
B4X:
Select CurrentState 'CurrentState is a global variable
 Case 1
  AfterKeyEvent1 (KeyValue)
 ..
End Select
 
Upvote 0

Mostez

Well-Known Member
Licensed User
Longtime User
yes Erel, sorry for not posting the handler code, but i cant get the value as (123) or ("hello"), I can decide to branch to, for example get value sub, how can I make routine wait for user to enter value 1 and if value 1 is correct get value 2 and after getting two values process them, sorry for many questions, but this matter really makes me so disappointed

B4X:
private Sub KeyPressHandler(kval As Byte)
   
    Select kval 'SCAN CODE IS THE SAME FOR ANY 4X4 KEYPAD, JUST DECODE ASCIIs ACCORDING TO WHAT IS PRINTED ON KEYPAD KEY
        Case KEY_1    '1, ROW0 COL0
            KeyASCII(0) = 0x31
        Case KEY_2    '2, ROW0 COL1
            KeyASCII(0) = 0x32
        Case KEY_3    '3, ROW0 COL2
            KeyASCII(0) = 0x33
        Case KEY_4    '4, ROW1 COL0
            KeyASCII(0) = 0x34
        Case KEY_5    '5, ROW1 COL1
            KeyASCII(0) = 0x35
        Case KEY_6    '6, ROW1 COL2
            KeyASCII(0) = 0x36
        Case KEY_7    '7, ROW2 COL0
            KeyASCII(0) = 0x37
        Case KEY_8    '8, ROW2 COL1
            KeyASCII(0) = 0x38
        Case KEY_9    '9, ROW2 COL2
            KeyASCII(0) = 0x39
        Case KEY_STAR'*, ROW3 COL0
            KeyASCII(0) = 0x2A
        Case KEY_0    '0, ROW3 COL1
            KeyASCII(0) = 0x30
        Case KEY_NUM'#, ROW3 COL2
            KeyASCII(0) = 0x23
        Case KEY_F1    'F1,ROW1 COL0
            KeyASCII(0) = 0x41
        Case KEY_F2    'F2,ROW2 COL1
            KeyASCII(0) = 0x42
        Case KEY_F3    'F3,ROW2 COL2
            KeyASCII(0) = 0x43
        Case KEY_F4    'F4,ROW2 COL3
            KeyASCII(0) = 0x44                                                           
    End Select
   
    Log("key: ",kval, " ascii ",KeyASCII)
   
   
   
Select ScreenType
        Case SCREEN_TYPE_MAIN
            If KeyValue = KEY_1 Then UpdateShift 'shift in, shift out, or count
            If KeyValue = KEY_2 Then UpdateReasonCode 'general or undefined, job related assignment i.e out to buy spare parts, stationary..etc, or permitted leave
            If KeyValue = KEY_3 Then UpdateLoadType 'vehicle loaded, unloaded or empty
            If KeyValue = KEY_F1 Then SCREEN_TYPE_ENTRY 'just test for now, changed state from normal mode to entry mode
        Case SCREEN_TYPE_ENTRY
            If KeyValue = KEY_NUM Then '# pressed, cancel and return to normal mode
                Clear
                ScreenType = SCREEN_TYPE_MAIN
            End If
           
            Dim RAF As RandomAccessFile
            RAF.Initialize(EntryBuffer,False)
            RAF.CurrentPosition = EntryBufferIndex
            RAF.WriteByte(KeyASCII(0),RAF.CurrentPosition)    'store pressed keys one after another in array
            EntryBufferIndex = EntryBufferIndex + 1
            Clear
            PutString(0,0,BC.StringFromBytes(EntryBuffer),FontArial5x8,False) 'display the array on lcd
    End Select
   
End Sub
 
Upvote 0

Mostez

Well-Known Member
Licensed User
Longtime User
OK Erel, that is my last question about this, I respect your advice about not to block the only thread, that's why I wrote the code like that, but even if I want to change the whole code to make the code 'wait', I cant do that unless I have serial input function . i.e. str = serialinput(pin,baud,timeout) would you please advice or give short example how implement this.

Thanks so much
 
Upvote 0
Top