Variables

 [private | public] dim identifier as type [ = expression]
  • Private – An optional keyword which ensures that a variable is only available from within the module it is declared. Variables are private by default.
  • Public – An optional keyword which ensures that a variable is available to other programs or modules.
  • Identifier – A mandatory variable name, which follows the standard identifier naming conventions
  • Type – A mandatory data type. Supported types include enumerated, boolean, bit, byte, sbyte, short, ushort, integer, uinteger, single, structures, string and char.
  • Expression - An optional assignment expression.

A variable holds data on which a program operates. Unlike constants, variable values can change dynamically when the program is executing. A variable is like a box, which holds values. You have to tell the compiler in advance the type of variable that will fit into the box. You declare variables one at a time, like this

Dim index As Byte
Dim range As Byte

As mentioned previously, the type defines what values can fit into a variable.

TypeBit SizeRange
   
Boolean1True or False
Bit11 or 0
Byte80 to 255
SByte8-128 to 127
UShort160 to 65535
Short16-32768 to 32767
UInteger320 to 4294967295
Integer32-2147483648 to 2147483647
Single321.175494e-38 to 3.40282346e+38
Double642.22507385e-308 to 1.79769313e+308
Char8Single character
StringVariableMultiple (up to 255) characters
StructureVariableVariable

It's important to note that data RAM on a PIC® microcontroller is substantially less than the code memory used to store your program. In addition, program operations on large data types (for example, unsigned integers) will generate much more underlying ASM code.

Unlike many other BASIC compilers, Firewing does allow variables of different types to be used in the same expression. For example, an unsigned byte can be multiplied by an integer and assigned to a variable declared as floating point. However, this practice should be avoided if possible, as the code automatically generated by the compiler needs to convert one type into another in order to compute the correct result. This will result in a larger code footprint than would otherwise be generated if all of the variables used had been declared as the same type.

The types bit, byte, sbyte, short, ushort, integer, uinteger and single shown here clearly outline the numeric ranges for any variables declared using them.

Variable Initialiser

A variable initialiser has the ability to combine a variable declaration with an assignment. For example,

Dim value As Byte = 0

Is the same as

Dim value As Byte
value = 0

An initialiser does not need to be a constant, it can be any legal expression. For example,

Dim myStr As String = "Hello World"  ' a string
Dim myVal As Byte = Len(MyStr)       ' length of string

Boolean Types

The boolean data type enables you to represent something as true or false. It cannot hold a numeric value. The right hand side of an assignment expression must always evaluate to true or false, or set directly by using the compilers predefined boolean constants. For example,

Dim Ok As Boolean = True

Booleans are particularly useful when dealing with flow control statements, such as if…then or iteration statements, such as while…end while or do…loop until. A boolean data type can significantly contribute to the readability of a program, making code sequences appear more logical and appropriate. For example, the following code shows how you could set a bit flag, if the value of index falls within 10 and 20,

Dim index As Byte = 5
Dim dataInRange As Bit
If index >= 10 And index <= 20 Then
   dataInRange = 1
Else
   dataInRange = 0
End If

However, if we change the flag dataInRange to a boolean type, we could write the code like this,

Dim index As Byte = 5
Dim dataInRange As Boolean
dataInRange = index >= 10 And index <= 20

In the first example, testing index using if…then evaluates to true or false. In the second example, dataInRange is a boolean type, so we can dispense with the if…then statement altogether and assign the result directly to dataInRange.

In addition, because dataInRange is a boolean type, we don't have to explicitly test it when encountering any conditional expressions. Remember, a boolean can only be true or false, so we simply write something like this,

If Not dataInRange Then
   ' output an error
End If

In this example, if dataInRange is false, then the if…then statement will evaluate to true (the boolean operator not inverts the false into a true) and an error is output.

String and Char Types

A string variable can be described as a collection of character elements. For example, the string "Hello" consists of 5 individual characters, followed by a null terminator. The Firewing compiler uses a null terminator (character 0) to denote the end of a string sequence. A string variable can be declared and initialized in the following way,

Dim myString As String = "Hello World"
myString = "one"                       
myString = "one two three four"       

By default, a string declaration will hold 32 characters plus a null terminator. When you assign a value to the string, it will grow in size as required, if this number is exceeded. When passing a string by reference to a sub of function it is usually good practice to dimension it explicitly. This ensures the string is large enough to hold any data assigned to it, like this:

' 79 characters + null terminator...
Dim myBuffer As String(80)

Remember, the compiler will only allocate 32 bytes + null terminator bytes of RAM for each string declared if (a) no value is ever assigned to it or (b) it is not explicitly dimensioned.

It is extremely important that string variables are declared with enough character elements to support the runtime operation of your program. Failure to do so will certainly result in problems when your code is executing.

Firewing enables you to specify string sizes of up to 256 bytes, which equates to 255 individual character elements. Unlike strings, a char type can only hold one single character. A char variable can be declared and initialized in the following way,

Dim myChar As Char
myChar = "A"

The compiler supports the "+" or "&" operators to concatenate (join) two strings. For example,

Dim strA As String = "Hello"
Dim strB As String = "World"
Dim result As String = strA & " " & strB 

Will result in result being set to "Hello World". The two relational operators = (equal) and <> (not equal) are also supported for string comparisons. For example,

If strA = strB Then
   Console.Write("Strings are equal!")
End If
If strA <> strB Then
   Console.Write("Strings are NOT equal!")
End If

You can also mix the concatenation operator with the supported relational operators, as shown in the following example,

Dim strA As String = "Hello"
Dim strB As String = "World"
If strA & " " & strB = "Hello World" Then
   Console.Write("Strings are equal!", 13, 10)
End If 

The compiler can also read or write to a single string element by indexing it in the following way,

Dim strResult As String = "Hello World"
strResult(5) = "_"

This would result in "Hello World" being changed to "Hello_World". Note that the first character of a string variable is located at 0, the second character at 1 and so on.

An alternative way to assign a single character to a string element or char variable is by using the CChar typecast. For example, the underscore character ("_") can be represented by the ASCII number 95 decimal. We could therefore write StrResult(5) = cchar(95). This technique is particularly useful when dealing with non printable characters, such as carriage returns and line feeds.

A useful compiler constant is nothing, which can be used to set, or tested for, a string null terminator. In the following example, the length of a string is computed and output via the microcontroller’s hardware USART.

Dim str As String = "Hello World"
Dim index As Byte = 0
While str(Index) <> Nothing
   Index = Index + 1
End While
Console.Write("Length is ", CStr(Index), 13, 10)

It should be noted that the compiler constant nothing is logically equivalent to "" (an empty string).

Arrays

 [private | public] dim identifier(Size) as type [ = "{"value, {value} "}"]
  • Private – An optional keyword which ensures that an array is only available from within the module it is declared. Arrays are private by default.
  • Public – An optional keyword which ensures that an array is available to other programs or modules.
  • Identifier – A mandatory variable name, which follows the standard identifier naming conventions
  • Size – A mandatory size which describes the number of elements in the array. Arrays can only have a single dimension. Firewing does not currently support multi-dimensional arrays.
  • Type – A mandatory data type. Supported types include boolean, bit, byte, sbyte, short, ushort, integer, uinteger, single, structures, string and char.
  • Value - An optional list of array values.

Arrays are collections of values, with each element being of the same type. When you have many variables in your program, it is sometimes useful to use a more manageable array, rather than keep track of them manually. You can declare arrays like this:

Dim array1(5) As Byte
Dim array2(10) As Byte
For bit or boolean arrays, accessing a single element using a variable index is very computationally expensive. For example bitArray(index) = 1. If at all possible, use a byte array instead.

You can initialize your array when declaring it. For example,

Dim myArray(5) As Byte = {1,2,3,4,5}

This will declare a byte array of 5 elements and initialize the array with the value 1..5. To access a single array element in your program, use the array name followed by round brackets around the index of element you want. For example, if you want to access the second element of myArray, then use

myArray(1) = 10

Note that the first element of an array is located at 0, the second element at 1 and so on. Because Firewing arrays begin with zero indexes, care must be taken when iterating through an array. For example,

Dim index As Byte
For index = 0 To 4
   myArray(index) = 200
Next  

is correct, and will set all 5 array elements (0 to 4) of myArray to the value 200. A very useful compiler keyword is ubound, which will automatically insert the correct upper bound for your array when the program is compiled. The ubound keyword is particularly useful when arrays are passed to functions or procedures, allowing you to write a routine that accepts arrays with different upper bounds. Using ubound, we could rewrite the previous example like this,

Dim index As Byte
For index = 0 To UBound(myArray)
   myArray(Index) = 200
Next   

Using ubound prevents your program inadvertently indexing an array beyond its highest element, which would certainly lead to problems when you program is executing. For example,

Dim array(5) As Byte
Dim index As Byte
For index = 0 To 5
   array(Index) = 2
Next   

After compilation the variable Index would be stored in data RAM, directly after the array declaration. When index = 5, the memory location used by Index is overwritten with a 2 because we have set the incorrect upper limit in the for…next loop. Instead of terminating at 5, the for…next loop will never finish because the loop counter Index has been changed from 5 to a value of 2.

Alias and Modifiers

 [private | public] dim alias as identifier{.modifier}
  • Private – An optional keyword which ensures that an alias is only available from within the module it is declared. Variables are private by default.
  • Public – An optional keyword which ensures that an alias is available to other programs or modules.
  • Alias – A mandatory alias name, which follows the standard identifier naming conventions
  • Identifier – A mandatory and previously declared variable name, which follows the standard identifier naming conventions
  • Modifier – One or more optional modifiers which can be used to access different parts of the variable identifier

Unlike a variable, an alias is declared without a type and does not allocate any data RAM. As the name suggests, it shares its data RAM with a previously declared variable. A simple alias declaration is shown below,

Dim value As Byte
Dim myAlias As Value
myAlias = 100

In this example, value has been declared as a byte type. myAlias has been declared as an alias to value. When 100 is assigned to myAlias, the number is stored at the RAM location reserved for value. In other words, value becomes equal to 100. Whilst a simple alias like this may be useful, substantial power and flexibility can be achieved when using an alias declaration with a modifier. For example, the program

Sub Main()
   Dim Led As PORTB.7
   While True
      High(Led)
      DelayMS(500)
      Low(Led)
      DelayMS(500)
   End While
End Sub

will flash an Led connected to PORTB, pin 7. A list of additional modifiers is shown here.

Some modifiers use an array notation. For example, PORTB.7 can be written as PORTB.Bits(7). The Booleans() array modifier is very useful for changing a bit field into a boolean. For example, many PIC® microcontrollers have hardware USARTs to support serial communication. You can test to see if data is available in the receive buffer by testing PIR1.5. Using the booleans modifier, we can create a more descriptive alias which has the virtue of being easy to test when using if…then, while…end while and do…loop until statements,

Dim dataIsAvailable As U1STA.Booleans(0) ' URXDA flag
If dataIsAvailable Then
   ' process data here...
End If  

Modifiers can also be used directly from within your program code. For example,

Dim value As UShort
value.Byte1 = &HFF

will set the high byte of the variable value to 255 decimal. Alias and modifiers can also be used on arrays. This is particularly useful if you want to access a single element in a complex data structure. In the following example, value is aliased to the first array elements minutes field.

Structure Time 
   Dim hours As Byte
   Dim minutes As Byte
End Structure
Dim array(10) As Time
Dim value As array(0).minutes 

Sub Main()
   ' these assignments are logically identical...
   value = 10
   array(0).minutes = 10  
End Sub

Aliases and modifiers can also be used on previously declared aliases. For example,

Dim array(10) As UShort             ' a word array
Dim elementAlias As array(3)        ' alias to element 4
Dim byteAlias As elementAlias.Byte1 ' element 4, high byte
Dim bitAlias As byteAlias.7         ' element 4, high byte, bit 7

The modifiers discussed up until now have been used to access smaller parts of a larger variable. The Firewing compiler also supports modifier promotion. That is, aliasing a smaller variable to a larger whole. For example, given the declarations

Dim array(8) As Byte
Dim lower As array(0).AsUInteger
Dim upper As array(4).AsUInteger

we can now access the lower and upper 4 bytes of an array using single assignments, like this

Sub Main()
   lower = &HF0F0F0F0
   upper = &HF0F0F0F0
End Sub

Each element of Array will now be set to &HF0. Please note that the Firewing compiler does not currently support modifier promotion of PIC® microcontroller register names from within a code block.