Proton BASIC Compiler - How much code space our routines have

  • PicŪ Basic

  • How much code space our routines have?

    This article is based on an idea and code by Darrel Taylor. How much code space do our routines use? We can find out with some MPASM directives.
    I have created several similar macros. These macros DO NOT use any code space in the PIC. They simply create "Symbols" in the .asm and .list files that indicates the size of the measured code.
    To measure the size of any code block, simply place a declaration at the beginning of the code:
    Next, place after the code block:

    To simplify and order these operations it is better to use an extension for each type of routine, for example for the macros:

    For the subroutines:
    ENDSIZE (Name_LIB)

    For the code in the main program:

    Example of a macro made with the preprocessor.
    $define HEXtoASCII2(pValueIn,pReturn1,pReturn2) '
        STARTSIZE(HEXtoASCII2_MACRO)                '
        EEDATA = pValueIn                           '
        _mHEXtoASCII2                               '
        pReturn1 = PRODH                            '
        pReturn2 = PRODL                            '
    In the .asm file it can be read.
        movff MyInputByte,EEDATA
    variable max_params=10,_mHEXtoASCII2_return=0,prm_count=0
        rcall HEXtoASCII2_Sub
        movff PRODH,MyASCIIH
        movff PRODL,MyASCII
    MESSG SIZE_CODE#HEXTOASCII2_MACRO = 14[BYTES]                              = 7[WORDS]
    You can see that the macro always starts with:

    And it always ends with:

    At least you can know where your code is and what size it has. By extension I have created another calculation allowing measurement of the time of execution of the code. This value would be real if there were neither subroutines called by a Gosub nor iterations in loops. Anyway, this calculation could be an idea of time.

    To obtain all this information regarding the code, you must enable the macros by this definition before the file.
    $define __MEASURE_CODE_

    If the calculations are disabled then the codes will be marked by their name in this way.
        movff MyInputByte,EEDATA
    variable max_params=10,_mHEXtoASCII2_return=0,prm_count=0
        rcall HEXtoASCII2_Sub
        movff PRODH,MyASCIIH
        movff PRODL,MyASCII
    Include file:
    In an .inc (library) file if all the routines were tagged, it would be easy to know how all the compiled code is used, for example:

    At the top of the file and before the code insert this macro.

    At the end of the file and after the code insert this macro. You can write the name of the file.

    The result compiled bytes in asm.file is:

    Library "TIPS_and_TRICKS_V10.INC":
    I gathered in a single file a few macros that could be useful for PDS users. You will see that I have compiled some old macros too.
    There are all the definitions and statements that you might need. In addition I have attached a new version of the library of local variables. You can study all the tricks used to make macros.

    20/09/2018 Update library

    I have fixed some little errors.

    Continuing with the BCD counters, I have written some codes allowing very large calculations with some unpacked integer BCD arrays. The only advantage I see in the BCD counters is that it can be easily visualized in the terminal, on the LCD display or been received/sent by a serial communication.
    On the web there is some information about calculations with the packed BCD bytes. The assembler has an instruction (Daw) for the BCD calculations. But it's not good for the arrays. Then I had to write the codes from the beginning. The most difficult codes to write have been the multiplication and especially the division.

    BCD Arrays:
    For the whole system to work correctly, I have created 8 arrays. 4 Arrays are for the use of the PDS user and 4 more for the internal calculations.


    ADD_BCD(Nb Array1,Nb Array2,Nb Array3)
    The calculation is done in this way: Array3 = Array1 + Array2
    To simplify the task, to identify an array, only the number is written, not the name.

    ADD_BCD(1,2,3) or ADD_BCD(1,2,4)
    In the ADD_BCD macro, an overflow control is provided that can be consulted.
    ErrorVar = ADD_BCD(1,2,3) If ErrorVar = 1 an overflow has occurred.
    In the end the code is very simple, considering that you can add a very large number of digits.


    SUB_BCD(Nb Array1,Nb Array2,Nb Array3)
    With overflow control: ErrorVar = SUB_BCD(1,2,3)

    The code is a bit more complex because the minuend is destroyed by the calculations. I have considered keeping it so that the user can continue making calculations with the same numbers.


    Logically, multiplication is a sum of additions. If done in this way, the calculation time would be too long. To see this principle I have written the macro MULV_BCD.
    Then a displacement of the divisor is made to the left, which corresponds to multiplying it by 10. And the number of sums of each corresponding number of the multiplicand is made. Which considerably reduces the number of repetitions.
    456 X 123 = 56088

    456 x 3 = 1368
    4560 x 2 = 9120
    45600 x 1 = 45600
    Total = 56088

    Multiplier X Multiplicand = Product
    MUL_BCD(Nb Array1,Nb Array2,Nb Array3)
    With overflow control: ErrorVar = MUL_BCD(Nb Array1,Nb Array2,Nb Array3)
    The multiplier is restored at the end because it has been destroyed.


    Logical, division is a sum of subtractions. Is done in this way, the calculation time would be too too long. (more than 60 seconds)
    The technique used is that of children who learn division in elementary school. It is easy to do with a pen and paper but difficult to pass to code when the number of digits is very important.

    458 / 12 = 38, remainder 2

    4 5 8 | 1 2
    - 3 6 _____
    = 0 9
    9 8 3 8
    - 9 6
    = 0 2

    The multiplier is restored at the end because it has been destroyed also.

    Transfers of values between variables and the BCD counters:

    STR_BCDArray(Nb Array, Variable In)
    Import a word to the BCD array number 1.
    STR_BCDArray(1, InputWord)

    Variable In could be a Byte/Word or Dword.

    Variable = VAL_BCDArray(Nb Array)
    The value of the array is extracted to a Byte/Word or Dword.
    Of course the values of the array must be the same size as the external variable.

    HRSOut_BCDarray(Nb Array,Nb of CarriageReturn)
    This command allows to send any BCD array to the terminal.
    HRSOut_BCDarray(4,2) The Array4 is sent to the terminal with 2 Carriages Return.

    Print_BCDarray(Nb Array,Line,Position)
    This command allows to send any BCD array to the display LCD.
    Print_BCDarray(2,1,5) Send the array number 2 to the LCD in line 1 and raw 5.

    I have tried some calculations of more than 64 bits without any problem.
    The execution time, which is important, depends on the number of BCD counters chosen. It is always preferable to have a little more than necessary to avoid overflow.

    In addition you can find more than 26 macros in the library that will help you in your projects.

    21/09/2018:Version 1.2 Fixed an errata with __KEYPAD_PORT.

    04/10/2018:Version 1.4 Fixed some erratas with the preprocessor.
    Add new macros: MeasurePeriod(), MeasureTime(), HRSOut_RCON(), ConvToFloat().

    By request of Teo (in forum) I have written a code to accurately measure the frequencies from 20Hz to 5000Hz by the method of measuring the period. The result could be with Integers or Float variables. You can define the minimum frequency and number of decimals.
    This complicated macro is a good example for beginners.

    I have modernized and incorporated this macro, which I had published years ago in the wiki. A code is written in your PIC to measure the execution time of a routine. It is very precise.

    This macro manages the RCON bits corresponding to the origin of different reset. It is very useful when the program suffers from false resets. This macro will be updated after the next version of the compiler.

    This macro converts 2 integer variables (whole + decimals) to a variable Float. The input variable could be positive or negative. It is not so obvious because you cannot add decimals to a negative Float variable.

    10/10/2018 Version 1.5: Added new macros:
    ReadTSensorTSH() '/ Thermistor linearisation using a Stein-Hart equasion
    VarToStrg() '/ Convert a variable to a String. Two different macros.
    Update ConvToFloat() for negative numbers.
    ConvAToFloat() '/ Convert some variables to Float with assembler macro.
    ConvBToFloat() '/ Convert some variables to Float with preprocessor macro.

    19/10/2018 Version 1.6: Added new macros:
    Added a new code for VarToStrg() Macro.
    Added new macros: CWBeacon_Init() / CWBeacon_Send() / CWWait_Buttons()
    The projector consists of 3 basic macros. Once combined, a Ham CW Beacon or a CW Memory Keyer could be developed.

    For BEACON:
    This macro allows sending to the transmitter the message number(1) forever (255).

    This macro allows sending the transmitter the message number(3) three times (3).

    This macro allows sending a message for ever at 16 WPM.

    BeaconExit = CWBeacon_Send(16)
            HRSOut "Beacon is sending:[",CW_String,"]:",CR,CR 
            BeaconExit = CWBeacon_Send(16)    '/ WPM = 16
            '/ BeaconExit = 0   => End of every message.
            '/ BeaconExit = 225 => End of messages & Shutt down the Transmitter.
            If BeaconExit = 225 Then          '/ Allows to exit Beacon loop and shutt down the transmitter.
    If CWBeacon_MESG(3,1) then at the end of message the transmitter (PTT) shutt down.
    CWTXT03: CData "CQ CQ DE EA3AGV # K",EOT1,0 (# = AR) EOT1 => BeaconExit = 225

    If CWBeacon_MESG (3,1) then at the end of message the transmitter (PTT) is still ON.
    CWTXT03: CData "CQ CQ DE EA3AGV",ETX1,0 ETX1 => BeaconExit = 0

    Five pushbuttons and another Stop can be configured to launch a specific message for each pushbutton. All the hardware must be configured before the library.
        '/ Define every message to Buttons.
        $define CWButton1Msg 2
        $define CWButton2Msg 4
        $define CWButton3Msg 5        
        $define CWButton4Msg 6 
        $define CWButton5Msg 7 
        '/ Define the Hardware Pins for Buttons.
        $define CWButton1 PORTC.4       ' "CWButton1" to port RC4. 
        $define CWButton2 PORTC.5       ' "CWButton2" to port RC5.
        $define CWButton3 PORTA.0       ' "CWButton3" to port RA0.
        $define CWButton4 PORTA.1       ' "CWButton4" to port RA1.
        $define CWButton5 PORTA.2       ' "CWButton4" to port RA2.
        $define CWButtonStop PORTA.3    ' "CWButtonStop" to port RA3.
        '/ Define the Hardware Pins for Outputs.
        $define CWRelay LATC.0    ' "CWRelay" to port RC0.
        $define CWLed   LATC.1    ' "CWLed" to port RC1.
        $define CWPTT   LATC.3    ' "CWPTT" to port RC3.
        $define _CWBeacon_
        $define __MEASURE_CODE_
        Include "D:\MyIncFiles\TIPS_AND_TRICKS_V16.Inc"
    It could be the beginning of a big project made by PDS.

    You can find more than 40 macros in this library. That will be very useful for your projects.

    For any supplementary information use the forum in the wiki section.
    Download the code from HERE.

    Alberto Freixanet October 2018.