Development Guide

There are lots of ways to contribute to the GCBASIC project: coding, testing, improving the build process and tools, or contributing to the documentation. This guide provides information that will not only help you get started as a GCBASIC contributor, but that you wiil find useful to refer to EVEN if you are already an experienced contributor.

Need Help?

The GCBASIC community prides itself on being an open, accessible, and friendly community for new participants. If you have any difficulties getting involved or finding answers to your questions, please bring those questions to the forum via the discussion boards, where we can help you get started.

We know EVEN before you start contributing that getting set up to work on GCBASIC and finding a bug that is a good fit for your skills can be a challenge. We are always looking for ways to improve this process: making GCBASIC more open, accessible, and easier to participate with. If you are having any trouble following this documentation, or hit a barrier you cannot get around, please contact use via the discussion forum. We will solve hurdles for new contributors and make GCBASIC better.

This section addresses developing libraries but this guide is appropriate to any GCBASIC development.

The section covers the recommended programming style, Constants, Variables, Script syntax (gotchas) and tab usage.

PROGRAMMING STYLES

Indenting is standardized.

All scripts within a specific library should be the first major section the library. Scripts within methods should not be used.

Some #defines may need to be placed before the script to provide clarity to the structure of the library.

        #startup  startupsub

        #Define I2C_ADDRESS_1  0x4E    'The default address if user does not specify in the user program

        #SCRIPT
                ... code script
                ... code script
                ... code script
       #ENDSCRIPT

Scripts support structures like IF <CONDITION> THEN <ACTION> END iF. Scripts supports the <condition> argument that must generate a TRUE result, meaning that at a literal level, your conditional formatting rule is an If - THEN statement along the lines of “If this condition is TRUE, THEN process the <ACTION>. the condition must use logical "AND" and "OR" to test two conditions. Using "AND" or "OR" reduces the script size, however, it is essential the the conditional test(s) are valid. If a test fails then you may not get the results you expect.

        IF .. THEN

        END IF

CONSTANTS

A constant is a value that cannot be altered by the program during normal execution.   Within GCBASIC there are two ways to create constants.    1. with the #DEFINE instruction, or, 2. via `#SCRIPT .. #ENDSCRIPT'. ;   Within a script constants can be created and changed. A script is process that is executed prior to the GCBASIC source program is processing the main user program.

An example of using #DEFINE is

        #DEFINE TIME_DELAY_VALUE    10

The script construct is

        #SCRIPT
              'Create a constant
              TIME_REPEAT_VALUE  =  10
        #ENDSCRIPT

Guide for constants

The following rules are recommended.

1 - All CONSTANTS are capitalized

2 - Do not define a constant in a library unless required

3 - Create all library constants within a script ( see example below Constrain a Constant Example on how to constrain a constant)

2 - Underscores are permitted in constant names within Scripts **

3 - No prefix is required when a CONSTANT is PUBLIC. A PUBLIC constant is one that the user sets or the user can use.

4 - Prefix CONSTANTS with SCRIPT_ when the CONSTANT is used outside of the library specific script section AND ARE NOT EXPOSED AS PUBLIC Constants.

5 - Prefix CONSTANTS with __ (two underscores) when the CONSTANT is ONLY used inside the library specific script section

6 - For PUBLIC prefix CONSTANTS with the capability name, _ (one underscore) and then a meaningful title, as follows GLCD_HEIGHT SPISRAM_TYPE

7 - All scripts within a specific library should be the first major section the library. Scripts within methods ( Sub, Functions) should not be used.

8 - All scripts within a specific library should be the first major section the library. Scripts within methods ( Sub, Functions) should not be used.

9 - Other naming recommendations. Do not use underscores in subroutine, function or variable names

Example script within a library

          #startup  startupsub
          #DEFINE I2C_ADDRESS_1  0x4E    'Default address if user omits
          #SCRIPT
                'script code
                'script code
                'script code
          #ENDSCRIPT

Simple Example

     #SCRIPT  'Calculate Delay Time
             __LCD_DELAY  = ( __LCD_TIMEPERIOD - __LCD_DELAYS) - (INT((4/ChipMHZ) * __LCD_INSTRUCTIONS))
            SCRIPT_LCD_POSTWRITEDELAY = __LCD_DELAY
            SCRIPT_LCD_CHECKBUSYFLAG = TRUE
     #ENDSCRIPT

     'usage within user code or code outside of script
     #IF SCRIPT_LCD_CHECKBUSYFLAG = TRUE
           WaitForReady    'Call subroutine to poll busy flag
           set LCD_RW OFF  'Write mode
     #ENDIF
     WAIT SCRIPT_LCDPOSTWRITEDELAY us

Create Constant Example

Background:  All constants are always processed, regardless of where they are placed in the user code or library.   This includes any constant defined anywhere in user code or any library - the constant will be processed and the constant will be defined.   The only method to constrain a constant is via a script.  

The following code segment will not constrain the constant.   The constant MYCONSTANT will be created.  The #IFDEF PIC will not constrain even if an AVR or LGT chip.

    #IFDEF PIC
          #DEFINE MYCONSTANT 255
    #ENDIF

The recommended method follows. The constant will only be created when a PIC.

    #SCRIPT
      IF PIC then
          MYCONSTANT  = 255
       End IF
    #ENDSCRIPT

Constrain a Constant Example

An example to constrain a constant is to test if a user constant is define in the user source program.   In this example the constant SENDALOW is defined in user source program.  

  • If yes, then define the library specific constants.  
  • If no, then do not define the library specific constants.  

Using the method below defines constants only when the user requires the constants assuming they have defined SENDALOW in the user source program.

    #SCRIPT
         IF SENDALOW then
                NONE = 0 : ODD = 1 : EVEN = 2 : NORMAL = 0 : INVERT = 1
                WAITFORSTART = 128 : SERIALINITDELAY = 5
         END IF

         IF SENDALOW then
                NONE = 0 : ODD = 1 : EVEN = 2 : NORMAL = 0 : INVERT = 1
                WAITFORSTART = 128 : SERIALINITDELAY = 5
         END IF

         IF SENDALOW then
                NONE = 0 : ODD = 1 : EVEN = 2 : NORMAL = 0 : INVERT = 1
                WAITFORSTART = 128 : SERIALINITDELAY = 5
         END IF
    #ENDSCRIPT

SCRIPTS VARIABLES

Scripting has the concept of variable that can be used within the script.   The variables are NOT available as variables to a user program or a library beyond the scope of the script.   The variables are available to a user program as constants.   The variables will be integer values, if accessed in a user program.  

SCRIPT SYNTAX

Scripting support the preprocessing of the program to create specific constants.   Scripting has a basic syntax and this is detailed in the HELP.   However, this guide is intended to provide insights into the gotchas and best practices.

Script Insights

Scripting handles the creation of specific constants that can be used within the library.   Many libraries have script to create constants to support PWM, Serial, HEFSAF etc.  

You can use the limited script language to complete calculations using real numbers but you MUST ensure the resulting constant is an integer value.   Use the IN() method to ensure an integer is assigned.

You can use IF-THEN-ENDIF but if your IF condtional test uses a chip regiseter or a user define constant then you must ensure the register or constant exists.   If you do not check the registrer or constant exists the script will fail to operate as expected.  

There is limted syntax checking. You must ensure the quality of the script by extensive testing.

    int( register +1s))  'Will not create an error, but, simple give an unexpected result.



TAB USAGE AND INDENTING

Four spaces are to be used. A tab is not permitted

Example follows where the indents are all four spaces.

sub  ExampleSub (In VariableName)
    select case VariableName
        case 1
            Do This
        case 2
            Do That
    end select
end sub

Not like this:

    SUB  ExampleSub (In VariableName)
            Select Case VariableName
                  Case 1
                                   Do This
                  Case 2
                                    Do That
             End Select
End SUB

and, not like this

    Sub  ExampleSub (In VariableName)
    Select Case VariableName
    Case 1
    Do This
    Case 2
    Do That
    End Select
    End Sub

OPTION REQUIRED

#Option Required supports ensuring the microcontroller has the mandated capabilities, such as EEPROM, HEF, SAF, USART.

Syntax:

    #option REQUIRED PIC|AVR CONSTANT %message.dat entry%
    #option REQUIRED PIC|AVR CONSTANT "Message string"

This option ensure that the specific CONSTANT exists within a library to ensure a specific capability is available with the microcontroller.

This will cause the compiler check the CONSTANT is a non zero value. If the CONSTANT does not exist it will be treated as a zero value.

Example:

This example tests the CONSTANT CHIPUSART for both the PIC and AVR microcontrollers. If the CONSTANT is zero or does not exist then the string will be displayed as an error message.

    #option REQUIRED PIC CHIPUSART "Hardware Serial operations. Remove USART commands to resolve errors."
    #option REQUIRED AVR CHIPUSART "Hardware Serial operations. Remove USART commands to resolve errors."

RAISING COMPILER ERROR CONDITIONS

From build 1131 the compiler now supports raising a compiler error message.

The method uses the `RaiseCompilerError ""<string>""|%string%" ` method to pass an error message to the compilation process.

An example from USART.H/INITUSART subroutine is shown below.  This example tests for the existence of one of the three supported baud rate constants.  If none of the constants exist and the constant (in this example) STOPCOMPILERERRORHANDLER does not exist the RaiseCompilerError with the string will be passed to the assembler for error processing.   This permits the inspect of the user program with appropriate messages to inform the user.

  ....
  #IFNDEF ONEOF(USART_BAUD_RATE,USART1_BAUD_RATE,USART2_BAUD_RATE) THEN
    'Look for one of the baud rates CONSTANTS
    #IFNDEF STOPCOMPILERERRORHANDLER
      'Use one of the following - the string MUST be start and end with a double quote

        ' Use the message.dat file
        ' RaiseCompilerError "%USART_NO_BAUD_RATE%"

        ' Use hard code text
        ' RaiseCompilerError "USART not setup correctly. No baud rate specified - please correct USART setup"

        RaiseCompilerError "%USART_NO_BAUD_RATE%"

    #ENDIF
  #ENDIF
  ....

The RaiseCompilerError handler can be stopped using the constant STOPCOMPILERERRORHANDLER as shown above.

LCD ERROR HANDLING

The setup of an LCD is inspected and an appropriate error message is displayed.   The Compiler now controls error messages when LCD is not setup up correctly.   This the text displayed is held in the messages.dat file - LCD_Not_Setup entry.