In CASE of mystery

Dear Forum, I have gone code-blind. What is wrong with below CASE section? - the compiler stops at 64 with "Expected and instruction or variable"
PUB Gain(gainSel) | bGain, regbyte                                                              

   CASE gainSel    
      128: bGain:= 7                                                          'gain selected - in dB
       64: bGain:= 6         
       32: bGain:= 5         
       16: bGain:= 4         
        8: bGain:= 3         
        4: bGain:= 2         
        2: bGain:= 1         
        1: bGain:= 0
        OTHER: RETURN FALSE          
    
   regByte:= i2c.ReadByteA8(ChipAddr, CTRL1_CRP) & !bGAINselCTRL1             'blank out the old Gain bits
   i2c.WriteByteA8(ChipAddr, PWR_CTRL, regByte | bGain)                       'write byte with new lower 3 bits representing Gain
   Recal                                                                      'always do re-cal after
   RETURN bGain

Erlend

Comments

  • Not sure, but what about moving 64,32 and 16 one step left. To align the first digits with 1 in 128. The other numbers also is to be moved 2 step left.
  • Ahh, I never fail to go into the indentation-trap! Thank you!
    CASE gainSel    
          128: bGain:= 7                                                          'gain selected - in dB
          64: bGain:= 6         
          32: bGain:= 5         
          16: bGain:= 4         
          8: bGain:= 3         
          4: bGain:= 2         
          2: bGain:= 1         
          1: bGain:= 0
          OTHER: RETURN FALSE          
        
       regByte:= i2c.ReadByteA8(ChipAddr, CTRL1_CRP) & !bGAINselCTRL1             'blank out the old Gain bits
       i2c.WriteByteA8(ChipAddr, PWR_CTRL, regByte | bGain)                       'write byte with new lower 3 bits representing Gain
       Recal                                                                      'always do re-cal after
       RETURN bGain
    
    Erlend
  • JonnyMacJonnyMac Posts: 6,582
    edited 2020-02-08 - 03:23:25
    The problem is assumed indenting levels. You can left-align the digits, or pad with zeroes to fix the alignment.

    Since the outcome is a single variable update, I suggest you replace case with this line: (corrected)
      bGain := lookdownz(gainSel : 1, 2, 4, 8, 16, 32, 64, 128)
    
    IF gainSel is in the list you'll get 0..7 back, otherwise you'll get 0 -- this is exactly what your case is doing.
  • Assuming that you only actually pass in powers of two or zero, you can also do this:
    bGain := ((>|gainSel)-1) #> 0
    
    (other values will get rounded down to the nearest power of two)
  • JonnyMacJonnyMac Posts: 6,582
    edited 2020-02-07 - 18:33:31
    I had originally suggested what @Wuerfel_21 did -- this is better if you have control of gainSel and it's not going to be outside the list of values that you spell out in the case. What her suggestion does, if converted to case, is this:
      case gainSel
        000..001 : bGain := 0
        002..003 : bGain := 1
        004..007 : bGain := 2
        008..015 : bGain := 3    
        016..031 : bGain := 4    
        032..063 : bGain := 5   
        064..127 : bGain := 6    
        128      : bGain := 7    
        other    : bGain := 0
    
    That said, there is no upper limit, so you may want to modify like this:
      bGain := 0 #> >|gainSel-1 <# 7
    
    Warning: If gainSel goes negative, you're always going to get 7 for bGain. You could fix that with:
      if (gainSel > 0)
        bGain := 0 #> >|gainSel-1 <# 7
      else
        bGain := 0
    
  • JonnyMac wrote: »
    The problem is assumed indenting levels. You can left-align the digits, or pad with zeroes to fix the alignment.

    Since the outcome is a single variable update, I suggest you replace case with this line:
      bGain := lookupz(gainSel : 1, 2, 4, 8, 16, 32, 64, 128)
    
    IF gainSel is in the list you'll get 0..7 back, otherwise you'll get 0 -- this is exactly what your case is doing.

    I like this solution a lot. I have several of these parameter list situations, and not all of them are regular like this one.

    Erlend
  • I did this, though - to not write to the register if not valid
       bGain := LOOKUP(gainSel : 1, 2, 4, 8, 16, 32, 64, 128)                     'convert from desired gain dB to bit numbers to set
       IF bGain == 0                                                              'if not found, do not write to register
         RETURN FALSE
       bGain -= 1                                                                 'because I used lookup instead of lookupz
       regByte:= i2c.ReadByteA8(ChipAddr, CTRL1_CRP) & !bGAINselCTRL1             'blank out the old Gain bits
       i2c.WriteByteA8(ChipAddr, PWR_CTRL, regByte | bGain)                       'write byte with new lower 3 bits representing Gain
       Recal                                                                      'always do re-cal after
       RETURN bGain
    
    Agree?
  • Actually, doesn't it have to be LOOKDOWN instead of LOOKUP?
  • Actually, doesn't it have to be LOOKDOWN instead of LOOKUP?
    You're absolutely right. Clearly, the coffee hadn't kicked in when I made that suggestion this morning. Thanks for the catch.
  • ErlendErlend Posts: 605
    edited 2020-02-08 - 09:04:46
    JonnyMac wrote: »
    Actually, doesn't it have to be LOOKDOWN instead of LOOKUP?
    You're absolutely right. Clearly, the coffee hadn't kicked in when I made that suggestion this morning. Thanks for the catch.

    Now I have read the manual (again) and gotten to know that LOOKUP(Z) takes an index and returns the corresponding number in the list, whereas LOOKDOWN(Z) takes a number and returns its index in the list. I need the latter. Thanks @JonnyMac and @Wuerfel_21
       bGain := LOOKDOWN(gainSel : 1, 2, 4, 8, 16, 32, 64, 128)                     'convert from desired gain dB to bit numbers to set
       IF bGain == 0                                                              'if not found, do not write to register
         RETURN FALSE
       bGain -= 1                                                                 'because I used lookdown instead of lookdownz
       regByte:= i2c.ReadByteA8(ChipAddr, CTRL1_CRP) & !bGAINselCTRL1             'blank out the old Gain bits
       i2c.WriteByteA8(ChipAddr, CTRL1_CRP, regByte | bGain)                       'write byte with new lower 3 bits representing Gain
       Recal                                                                      'always do re-cal after
       RETURN gainSel
    
  • For the lists that are not contiguous i settled for this code, 'padding' the list with -1, - but it is maybe not very elegant.
    bSPS := LOOKDOWN(SPSsel : 10, 20, 40, 80, -1, -1, -1, 320)
    IF bSPS == 0                                              
      RETURN FALSE                                            
    bSPS -= 1
    
    Erlend
  • If spsSel can never be -1, and the only valid values for bSPS are 0, 1, 2, 3, and 7, that makes sense to me.
Sign In or Register to comment.