Author Topic: Suggestion on Fx Local variables and arguments to functions  (Read 11831 times)

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Gentlemen,

Some of my favorite things that came with the addition of floating point support are the addition of local variables, custom functions that accept arguments and custom functions that return a value.

I think that it is very limiting that the only data type that is supported for the local variables, arguments and return values are floating point.  However, there are lots of cases where a 32-bit integer is much more useful.  

I understand that the the Bits2Float(n) and Float2Bits(n) functions can be used as sort of a "C-like" cast, that can allow a float variable to behave integer, but this mechanism is very awkward.

As an example, I'd like to use the local variable, %[1] as an integer:

%[1] = Bits2Float(3)
%[1] = Bits2Float(Float2Bits(%[1])/2)
[/color][/font]

Now I know that with the #DefineLocal I can make this code a little more readable, but it is still tricky:

#DefineLocal ILocal = Float2Bits(%[1])
#DefineLocal ILocalF = %[1]

ILocalF = Bits2Float(3)
ILocalF = Bits2Float(Ilocal/2)
[/color][/font]

This is what I like you guys to think about on future versions of the Fx firmware and the ITrilogi compiler, some sort of limited type definitions.  Some thing on this order:


' Declare a local variable that is to function as a signed 32-bit integer
'
#DefineLocal ILocal = (INT32)%[1]

ILocal = 3              ' Assignment of an integer variable to a local var
ILocal = Ilocal / 2   ' Integer math and an assignment to a local var
[/color][/font]

The cast "(INT32)" could clue the compiler that the type of the data stored at %[1] is an integer and should be treated as such.

Floats are nice, but there are a lot of cases where Floats can NOT do the job.  Try to represent the integer &h7ffffffffffffff with a float!  

If would be even nicer if there was a way to indicate to the compiler the behavior of a custom function so that arguments could be passed to a custom function as an integer and NOT promoted to a float. Think modern programming languages. Some sort of function declaration:


' The following function returns a 32-bit signed intger
'   and takes 2 arguments, the first one is an integer and the second is a float
'
INT32 FunctionX(INT32 A, FLOAT B)  ' function declaration

for i = 1 to 10
    DM32  = FunctionX(i, 3.14159)             ' using the function
next

[/color][/font]

The same function declartion would be needed to be repeated in actual custom function, "FunctionX".

I realize that this is probably  too big a change to a language like TBASIC to support, but I can always ask.

Gary D.


« Last Edit: May 15, 2015, 04:05:54 PM by garysdickinson »

support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3174
    • View Profile
    • Internet Programmable PLCs
Re:Suggestion on Fx Local variables and arguments to functions
« Reply #1 on: May 19, 2015, 03:06:10 PM »
Thanks for your valuable feedback, as always.

We will give it some thoughts to see if there is a clean and simple way to implement it. The main consideration is really not to make it more complicated (and therefore gives a programmer more chance of tripping himself). As of now, you can reserve some global variables that will only be used as local variables within a custom function but will not be used by any interrupt service routine. If a function is setup to be used as subroutine by another function then it can use another set of variables based on its call depth. That way these global variables will essentially serve the function of local variables.
Email: support@triplc.com
Tel: 1-877-TRI-PLCS

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Suggestion on Fx Local variables and arguments to functions
« Reply #2 on: May 19, 2015, 09:46:47 PM »
The thinking is that you have as many as 9 local variables (less the number of arugments passed to the custom function).

My concern is that the only type of local variable and the only type of data returned from a custom function is a float.

The following is code that I use for generalized table search algorithm.  The lookup table is stored in DM[] and is part of a bigger data structure that includes information on the size of the lookup table and the entry spacing.  This is handled by the #Define mechanism.

The thing to look at in this program are the 3 variables, Imin, Imid and Imax.  These variables MUST be integer as the whole binary search is dependent on this fact.  Floats cannot be used.  It is not easy to use the "local variables", %[1]..%[9] and get them to behave exactly like integers.  So my choices were to either use memory space in DM32[], A..Z or EEPROM for these variables.  I went with DM[32] as it was the fastest access.


' TableLookUp - Binary Search Algorithm to search through an ordered table of data
'   and returned a value based on the position in the table.  Most typically, this
'   table is used to covert ADC values to temperature.
'
' Function Usage:
''    Temp = TableLookUp(ADCValue, TableAddrDM32)
'
' On Entry:

#defineLocal ADCValue          = %[1]   ' ADCValue 0..4095
#defineLocal TableAddrDM32      = %[2]   ' DM32 index for the lookup table structure

' Local, temporary, variables:
'
#defineLocal TempC             = %[3]   ' computed temperature value to return

' Global variables used by this function:
'   Imin, Imid and Imax - 32 bit integer variables located in DM32[]

' Set up initial, search values to span entire lookup table

j = TableAddrDM32    ' this is a trick to provide access to a structure member
Imin = TableFE      ' index into DM for first table entry
Imax = TableLE      ' index into DM for last table entry

' Binary search through the table. This is classic CS 101.
'  
while (Imax >= Imin)
   Imid = (Imin + Imax)/2      ' Calculate new mid point for search
   if DM32[Imid] = ADCValue
      '  Exact match: Compute temperature, and return it...
      '
      TempC = (Imid-TableFE)*TableSpacing + TableFirstValue
      If TestIO(DebugTblLU)
         Print #2 "Temp: "; str$(TempC,-2)
      endif
      return = TempC
   elif DM32[Imid] < ADCValue
      Imin = Imid + 1         ' Use upper 1/2 of current range for next test
   else
      Imax = Imid -1         ' User lower 1/2 of current range for next test
   endif
endwhile

' At this point, DM[Imid] is pretty close to the ADC (ADCValue) value.
' Exact matches have already been dealt with.
'
TempC = (Imid-TableFE)*TableSpacing + TableFirstValue

' Linear Interpolation
'
'  adjacent values in the look up table provide the x_0 and x_1 values
'  each entry in the look up table is spaced EntrySpacing apart.
'
'    y = y_0 + (y_1-y_0) * (x - x_0)/(x_1-x_0)
'
TempC = TempC + (TableSpacing*(ADCValue-DM32[Imid]))/(DM32[Imid+1]-DM32[Imid])   ' Add in the interpolated part

return = TempC      ' return with interpolated value
[/font][/color]

Thanks for thinking about it.

Gary D