Menu

Direct jump selected by value

Help
2026-05-06
2026-05-07
  • Roger Jönsson

    Roger Jönsson - 2026-05-06

    Say I have a value from a sensor 1-20. I would like to do a fast direct jump to one of 20 subroutines or functions (selected by the sensor value) without having to test my way trough a long list of if-then or select case.
    (At this time I am looking for a way to select one of 20 tables for converting incoming data, the table used to be selected by the sensor value. Sensor value=1 then use table1, Sensor value=2 then use table2 etc)
    In GCbasic what should I look for?

     
  • Anobium

    Anobium - 2026-05-07

    ready..... the fastest I can think of.

    ' ============================================================
    '  SensorBinaryDispatch.GCB  –  GCBASIC binary-tree dispatch
    '  Target : PIC16F877A (adjust chip/clock to suit your board)
    '
    '  Worst case: 5 comparisons to reach any of 20 actions.
    '  A straight IF-THEN chain worst case would be 20 comparisons.
    '
    '  Tree structure used:
    '
    '              [<=10]
    '           /          \
    '        [<=5]         [<=15]
    '        /   \         /    \
    '     [<=2] [<=7]  [<=12] [<=17]
    '      / \   / \    / \    / \
    '     1   2 ...      ...      ...
    '
    '  Each level halves the remaining range.
    '  Maximum depth = 5 levels for 20 items.
    ' ============================================================
    
    #CHIP PIC16F877A, 20
    
    
    #DEFINE USART_BAUD_RATE  9600
    #DEFINE USART_TX_BLOCKING
    
    Dim SensorValue As Byte
    Dim RawInput    As Byte
    Dim ConvResult  As Word
    
    ' ============================================================
    '  MAIN LOOP
    ' ============================================================
    Main:
        HSerPrint "Binary Dispatch Demo"
        HSerPrintCRLF
    
        Do
            ' Replace these two lines with your real sensor read
            RawInput = RawInput + 1
            If RawInput > 20 Then RawInput = 1
            SensorValue = RawInput
    
            ' Bounds check
            If SensorValue >= 1 And SensorValue <= 20 Then
                GoSub DispatchAction
                HSerPrint "Sensor="
                HSerPrint Str(SensorValue)
                HSerPrint "  Result="
                HSerPrint Str(ConvResult)
                HSerPrintCRLF
            Else
                HSerPrint "ERROR: out of range"
                HSerPrintCRLF
            End If
    
            Wait 250 ms
        Loop
    
    ' ============================================================
    '  BINARY DISPATCH TREE
    '  Each node splits the remaining range in half.
    '  Worst case = 5 comparisons to reach any leaf.
    '
    '  Level 1 : splits 1-20 into 1-10 / 11-20
    '  Level 2 : splits into 1-5/6-10  and  11-15/16-20
    '  Level 3 : splits into pairs of ~2-3
    '  Level 4 : final single-value checks
    ' ============================================================
    DispatchAction:
        If SensorValue <= 10 Then
            '--- LEFT branch: values 1-10 ---
            If SensorValue <= 5 Then
                '--- LEFT-LEFT branch: values 1-5 ---
                If SensorValue <= 2 Then
                    If SensorValue = 1 Then
                        GoSub Action1
                    Else
                        GoSub Action2
                    End If
                Else
                    If SensorValue = 3 Then
                        GoSub Action3
                    Else If SensorValue = 4 Then
                        GoSub Action4
                    Else
                        GoSub Action5
                    End If
                End If
            Else
                '--- LEFT-RIGHT branch: values 6-10 ---
                If SensorValue <= 7 Then
                    If SensorValue = 6 Then
                        GoSub Action6
                    Else
                        GoSub Action7
                    End If
                Else
                    If SensorValue = 8 Then
                        GoSub Action8
                    Else If SensorValue = 9 Then
                        GoSub Action9
                    Else
                        GoSub Action10
                    End If
                End If
            End If
        Else
            '--- RIGHT branch: values 11-20 ---
            If SensorValue <= 15 Then
                '--- RIGHT-LEFT branch: values 11-15 ---
                If SensorValue <= 12 Then
                    If SensorValue = 11 Then
                        GoSub Action11
                    Else
                        GoSub Action12
                    End If
                Else
                    If SensorValue = 13 Then
                        GoSub Action13
                    Else If SensorValue = 14 Then
                        GoSub Action14
                    Else
                        GoSub Action15
                    End If
                End If
            Else
                '--- RIGHT-RIGHT branch: values 16-20 ---
                If SensorValue <= 17 Then
                    If SensorValue = 16 Then
                        GoSub Action16
                    Else
                        GoSub Action17
                    End If
                Else
                    If SensorValue = 18 Then
                        GoSub Action18
                    Else If SensorValue = 19 Then
                        GoSub Action19
                    Else
                        GoSub Action20
                    End If
                End If
            End If
        End If
        Return
    
    ' ============================================================
    '  ACTION SUBROUTINES
    '  Replace the body of each with your real lookup data.
    '  Each reads RawInput, writes result to ConvResult.
    ' ============================================================
    
    Action1:
        ConvResult = RawInput * 3
        Return
    
    Action2:
        ConvResult = RawInput + 100
        Return
    
    Action3:
        ConvResult = RawInput / 2
        Return
    
    Action4:
        Select Case RawInput
            Case 1  : ConvResult = 412
            Case 2  : ConvResult = 398
            Case 3  : ConvResult = 521
            Case 4  : ConvResult = 305
            Case 5  : ConvResult = 477
            Case Else : ConvResult = 0
        End Select
        Return
    
    Action5:
        ConvResult = RawInput * RawInput
        Return
    
    Action6:
        ConvResult = 255 - RawInput
        Return
    
    Action7:
        ConvResult = RawInput + 50
        Return
    
    Action8:
        ConvResult = RawInput * 10
        Return
    
    Action9:
        ConvResult = RawInput << 1
        Return
    
    Action10:
        ConvResult = RawInput >> 1
        Return
    
    Action11:
        ConvResult = RawInput + 200
        Return
    
    Action12:
        ConvResult = 300 - RawInput
        Return
    
    Action13:
        ConvResult = RawInput * 7
        Return
    
    Action14:
        ConvResult = RawInput Mod 16
        Return
    
    Action15:
        ConvResult = 1024
        Return
    
    Action16:
        ConvResult = RawInput + 75
        Return
    
    Action17:
        ConvResult = RawInput * 4
        Return
    
    Action18:
        Select Case RawInput
            Case 1  : ConvResult = 1000
            Case 2  : ConvResult = 1025
            Case 3  : ConvResult = 1051
            Case 4  : ConvResult = 1078
            Case 5  : ConvResult = 1106
            Case 6  : ConvResult = 1135
            Case 7  : ConvResult = 1165
            Case 8  : ConvResult = 1196
            Case 9  : ConvResult = 1228
            Case 10 : ConvResult = 1261
            Case Else : ConvResult = 0
        End Select
        Return
    
    Action19:
        ConvResult = RawInput * 15
        Return
    
    Action20:
        ConvResult = RawInput + 512
        Return
    
    ' ============================================================
    '  END OF PROGRAM
    ' ============================================================
    
     
  • Roger Jönsson

    Roger Jönsson - 2026-05-07

    Thank you for your reply and example. I had a tree structure in mind, but I wondered if there was some way to direct jump based on value
    AI:s gives all kinds of suggestions, but nothing I can make into sense looking in the GCbasic docs on how to realize it into code that will work.

    -So there is no way using the sensor value to make a logic direct jump (jump table or what ever it might be called)?
    Is that simply is not possible because the hardware in the 8-bit PIC chips etc does not support/assist it? Just so I get that clear and move on.

    I can probably move the sensor data -> selection to my main loop and make copies of the program part that processes the data flowing through into my 32kHz clocked interrupt routine (using the part decided in the main loop). I can probably make this work if I re-think. This way the sensor data based decision does not need to be done 32000 times per second or more.
    I have also an idea of converting the sensor data to logarithmic via a table and then fewer out values may be required for similar performance in my secret project (until finished). I can then make the tree structure smaller or maybe even get away without it.

     
  • Anobium

    Anobium - 2026-05-07

    Yes, the hardware is the core limitation. On an 8-bit PIC:

    • The program counter (PC) is not a general-purpose register you can freely load with a calculated address in the way a 16/32-bit CPU allows
    • There is a trick using ADDWF PCL (add W to the low byte of PC) in raw assembler to do a computed jump, but it's fragile — it only works within a 256-instruction page boundary, and GCBASIC's compiler manages PC layout itself so you can't safely exploit it
    • This is exactly why GCBASIC never implemented ON x GOSUB label1, label2... — it would be unreliable across different PIC variants and memory layouts

    So yes — no safe direct jump table on 8-bit PIC in GCBASIC. You've hit a genuine hardware constraint, not a gap in your knowledge.


    The ideas you're describing are the right engineering response:

    Move the selection to the main loop — absolutely correct. Deciding which action/table to use based on sensor value is a slow, infrequent decision. Running a 5-comparison binary tree 32,000 times per second inside an ISR is wasteful when the sensor type probably changes rarely or never during a run. Set a variable like CurrentAction in the main loop, and your ISR just acts on it directly.

    Logarithmic pre-conversion — this is a classic DSP technique and a very elegant solution. If your 20 possible output values compress well onto a log scale, you may find that 6-8 log-spaced values cover the perceptually or functionally important range just as well. That could reduce your tree to 3 levels and 3 comparisons worst case — or even allow a small SELECT CASE that the compiler handles efficiently.

    Both ideas together — slow sensor-type selection in main loop, log-compressed fast lookup in the ISR — is a genuinely good architecture for a resource-constrained 8-bit system. Good luck with the project when you're ready to share it!

     
    👍
    1

Log in to post a comment.

MongoDB Logo MongoDB