Embed program PREPIC

10 July 2017

prepic [options]

Preprocess a Microchip PIC assembler source file to produce a file that can be passed directly to the assembler. The input file name suffix determines the default output file name suffix and can enable or disable particular features. The valid input file name formats are:

<name>.aspic

MPASM source file (for PIC 10, 12, 16, 17, and 18). Default output file name is <name>.asm.

<name>.ins.aspic

MPASM include file. Default output filename is <name>.inc.

<name>.dspic

ASM30 source file (for the 16 bit PICs like the 24, 30, and 33). Default output file name is <name>.S.

<name>.ins.dspic

ASM30 include file. Default output file name is <name>.inc.

The input file is just copied to the output file except when a preprocessor command or inline function is encountered.

The command line options are:

<input file name>

The first command line option that does not start with a dash (-) will be taken as the input file name if no input file name was previously set. A input file name is mandatory.

The file name suffixes may be omitted on the command line. In that case file names with each of the valid suffixes ".ins.aspic", ".aspic", ".ins.dspic", and ".dspic" will be tried in that order. The first file found will be used.

-IN <input file name>

Explicitly set the input file name. This is the only way to indicate an input file name that starts with a dash (-).

<output file name>

The first command line argument that does not start with a dash after the input file name is specified, but no output file name has yet been specified, will be taken as the output file name. The default output file name for each input file type is listed above.

-OUT <output file name>

Explicitly set the output file name. This is the only way to indicate an output file name that starts with a dash (-).

-SET name

Create a BOOL variable of name NAME and set it to TRUE before the input file is processed.

-NOT name

Create a BOOL variable of name NAME and set it to FALSE before the input file is processed.

-I name val

Create a INTEGER variable of name NAME and set it to VAL before the input file is processed.

-F name val

Create a REAL (floating point) variable of name NAME and set it to VAL before the input file is processed.

-S name val

Create a STRING variable of name NAME and set it to VAL before the input file is processed. VAL must be enclosed in quotes ("") or apostrophies ('') if it contains any spaces.


Based on ESCR

The PREPIC program is based on the Embed Scripting System used in pre-processor mode. All of the functions of the ESCR system are available, plus a few custom features added by PREPIC.

Specifically, the customizations to the ESCR system are:

  1. The system is run in pre-processor mode, not script mode.

  2. Script comments start with "//" and extend to the end of the line. These type of comments are not copied to the output file.

  3. Data file comments start with ";" and extend to the end of the line. These type of comments are copied from the input file to the output file.

  4. Script commands are identified by a slash (/) immediately preceeding the command name. The slash must be the first printable character on the line.

  5. Several additional commands are added to the base ESCR commands. The additional commands are described in a separate section below.

  6. In-line function are identified by a starting "[" and ending "]".

  7. Several additional functions are added to the base ESCR functions. The additional functions are describe in a separate section below.

  8. Pre-processor include file names when the language is MPASM are assumed to end with ".ins.aspic". For ASM30, they are assumed to end with ".ins.dspic".


Data Types

The PREPIC data types are the same as the ESCR data types.


Commands

All the ESCR commands are available, plus the following:

INBIT name port bit [PUP]

Declares an I/O pin as a digital input.

Name is the private name being defined for the I/O pin, and will be used to generate unique assembler symbols associated with this pin, shown below.

Port is the name of the I/O port containing the input bit. It must be of the form PORT followed by a single letter indicating the particular port. The port argument is case-insensitive. Examples are PORTA, PortB, and portc. Some processors have a single I/O port called GPIO. The GPIO port must be referred to as PORTA.

Bit is the bit number within the port register. It must be 0-7 on 8 bit PICs (PIC 12, 16, 17, 18) and 0-15 on 16 bit PICs (PIC 24, 30, 33).

Pup is an optional keyword indicating that the internal passive pullup should be initially enabled for this I/O pin. An error will be generated when the standard PORT module is assembled if the requested combination of passive pullups requested by all INBIT commands is not attainable on this specific processor.

This command only creates or modifies preprocessor and assembler state. It generates no executable code. It is assumed that the assembler state has been properly initialized prior to this INBIT command, as is done if the standard include files STD_DEF.INS.ASPIC and STD.INS.ASPIC (or STD_DEF.INS.DSPIC and STD.INS.DSPIC) are used as directed. The actual runtime initialization code that uses the assembler state is in the PORT_INIT subroutine in the standard PORT module.

The following assembler symbols will be defined or modified by INBIT, INANA, and OUTBIT commands:

name_reg

Assembler constant equal to the address of the PORTx register containing the direct I/O pin value.

name_tris

Assembler constant equal to the address of TRISx register controlling the I/O pin in/out direction.

name_lat

Assembler constant equal to the address of LATx register containing the output latch bit for this I/O pin. This constant is only defined if the machine has a port latch register. For example, the original 16 family PICs do not have these, although 18 and 30 family PICs do.

name_bit

Assembler constant equal to the bit number for this I/O pin within the PORTx, TRISx, and other possible port-specific registers.

name_pin

String substitution macro that expands to the port register followed by the bit number within that register for this I/O pin. The string substitution macro is defined:

#define name_pin PortRegister, bit

This string substitution macro can be used to supply both arguments to bit manipulation instructions as shown in the example below.

NOTE: This string substitution macro is not implemented for dsPIC processors.

name_pinlat

String substitution macro that expands to the latch register followed by the bit number within that register for this I/O pin. This is like the name_pin macro (above), except that it refers to the bit in the latch instead of the port register. This macro is only defined when the latch register exists.

NOTE: This string substitution macro is not implemented for dsPIC processors.

VAL_TRISx

Assembler variable containing the initial value for the TRISx register (where X is the port name, like A) controlling the direction of this I/O bit. The bit for this I/O pin will be set, which will cause the pin to be initialized as an input by the standard PORT_INIT subroutine.

VAL_PULLUPx

Assembler variable indicating the desired initial state of the passive pullups for the port containing the I/O bit. The X in the variable name is the port name, like B or C, for example. A bit in this variable is set to indicate the associated passive pullup is to be initially enabled. Illegal requests for passive pullups will generate an error message when the standard PORT module is assembled.

VAL_ANALOGx

Assembler variable indicating which pins of port X are analog. 1 bits indicates analog, 0 digital.

ANALOGUSED0
ANALOGUSED1

Each of these assembler variables contains 32 bits indicating used analog channels. ANALOGUSED0 contains the bits for AN0 to AN31, and ANALOGUSED1 for AN32 to AN63. Within each variable, the analog channel numbers correspond to bits in least to most significant order.

For example, ANALOGUSED1 of 5 indicates that analog channels AN32 and AN34 are used, and that AN33 and AN35-AN63 are unused.

For example,

/inbit button portb 3 pup ;low when user button is pressed

declares bit 3 of port B (RB3 pin) to be a digital input with its passive pullup enabled. The following assembler statements will be generated:

button_reg equ portb
button_tris equ trisb
button_lat equ latb    
(only on machines that have LATB)
button_bit equ 3
#define button_pin portb,3
#define button_pinlat latb,3    
(only on machines that have LATB)
val_trisb set val_trisb | b'00001000'
val_pullupb set val_pullupb | b'00001000'
val_analogb set val_analogb & ~b'00001000'

Example MPASM code using the directive above is:

     btfsc   button_pin  ;is the button pressed ?
     goto    done_button ;no, done handling user button
     ;
     ;   The user button is pressed.
     ;
     ...
done_button unbank       ;done handling the user button
      

Example ASM30 code using the directive above is:

     btsc    button_reg, #button_bit ;is the button pressed ?
     bra     done_button ;no, done handling user button
     ;
     ;   The user button is pressed.
     ;
     ...
done_button:             ;done handling the user button
      

Undefined I/O pins default to outputs driven low.

Some preprocessor state is created for each INBIT, INANA, and OUTBIT command. The following constants are created:

Portdata_PortBit

Port is the single lower case letter of the I/O port, and bit is the 0-N number of the bit within the port. For example, if RB5 is defined as a named pin with INBIT, the preprocessor constant Portdata_b5 will be created.

This constant is of type STRING, and contains individual tokens separated by spaces. The tokens are:

  name IN|OUT POS|NEG DIG|ANA [ANx]

Name is the name assigned to this pin, which is the first parameter to the INBIT, INANA, or OUTBIT command.

IN or OUT indicate the direction the pin is configured in, from the processor's point of view.

POS or NEG indicate positive or negative logic. In positive logic, the on state is high and the off state is low. This is reversed for negative logic.

DIG or ANA indicate whether the pin is configured as digital or analog.

ANx is only present for analog pins. X is the analog channel number.

For example:

  /INBIT level porta 3   -->   Portdata_a3 = "level IN POS DIG"
  /INANA temp portc 1 an7   -->   Portdata_c1 = "temp IN POS ANA AN7"
  /OUTBIT pump portb 5   -->   Portdata_b5 = "pump OUT POS DIG"

Inbit_name_port     (for INBIT and INANA)
Outbit_name_port     (for OUTBIT)

String constant for the upper case letter of the port containing the pin. Name is the symbolic name given to that input or output bit. For example:

  /INBIT level porta 3   -->   Inbit_level_port = "A"
  /OUTBIT pump portb 5   -->   Outbit_pump_port = "B"

Inbit_name_bit     (for INBIT and INANA)
Outbit_name_bit     (for OUTBIT)

Integer constant for the number of the bit within the port. Name is the symbolic name given to that input or output bit. For example:

  /INBIT level porta 3   -->   Inbit_level_bit = 3
  /OUTBIT pump portb 5   -->   Outbit_pump_bit = 5

INANA name port bit ANx

Like INBIT except that it declares a analog input instead of a digital input.

X is the analog channel number. The analog channel numbers are mapped in unpredictable ways to the I/O ports. These are often referred to as "ANx" in the documentation. For example, "AN3" refers to analog input channel 3.

OUTBIT name port bit [polarity] [init]

Like INBIT except that it declares the I/O bit to be an output instead of an input. This means the VAL_TRISx assembler variable will be updated to indicate this bit is an output.

In addition to the symbols and string substitution macros created by INBIT, OUTBIT also creates the macros set_name_on and set_name_off. These set the bank for access to the appropriate register, then use a bit set or bit clear instruction to turn the output pin on or off. On PICs with LATx registers, the bit instruction operates on them. Otherwise the bit instruction operates on the PORTx register.

Polarity defines the polarity of the "on" and "off" states of the pin. The polarity parameter must be either P for positive or N for negative. The default is P. Positive polarity means that high is on and low is off, and negative polarity the opposite. For example, this may be useful if a LED is connected in series with a resistor between the I/O pin and the positive supply. Setting the pin low turns the LED on and setting it high turns the LED off. In this case the polarity should be indicated as N instead of P:

  /OUTBIT led portb 5 n

The polarity is taken into account by the set_name_on and set_name_off macros. For the example above, set_led_on would cause the RB5 pin to be driven low, and set_led_off would cause RB5 to be driven high.

Init indicates how the I/O pin should be set when the I/O ports are initialized. Init may be either 0 or 1 to explicitly set the pin low or high, respectively. Or, it may be ON or OFF, which will set it high or low depending on how the pin polarity is defined. The default is OFF.

Undefined I/O pins default to outputs driven low.

FLAG name

Create a new global flag with the indicated name. The assembler variable NFLAGB is updated if a new word is required to hold the new flag. The flags will be in words named GFLn, where n starts at 0 and increases by one as each new flag word is required.

The GFLn variables are native words in size. That means they are 8-bit on 8 bit PICs (PIC 16, PIC 18, etc), and 16-bit on 16 bit PICs (PIC 24, dsPIC 33, etc).

The following assembler constants will be defined:

flag_name_regn

Number of the GFLn variable containing the flag bit. In other words, this constant will be 0 if the flag is in GFL0, 1 if it is in GFL1, etc.

flag_name_reg

Address of the GFLn variable containing the flag bit.

flag_name_bit

Number of the flag bit within the GFLn variable. The least significant bit is numbered 0, and the most significant is 7 on 8 bit PICs and 15 on 16 bit PICs.

On 8 bit PICs, a string substitution macro is created called flag_name. This expands into the byte containing the flag and the bit number within the byte. The string substitution macro is written:

#define flag_name n, bit

All flag bits defined with FLAG are initialized to 0 in the standard STRT module before code in any other module is executed.

Example MPASM code:

/flag    t100                ;set every 100 ms
         .
         .
         .
         dbankif gbankadr
         btfss   flag_t100   ;time to do 100 ms processing ?
         goto    done_100ms  ;no, skip this section
         bcf     flag_t100   ;reset to 100 ms proc not pending

         ;perform 100 ms processing here

done_100ms unbank            ;done with the 100 ms processing

      

Example ASM30 code:
/flag    t100                ;set every 100mS
         .
         .
         .
         btss    flag_t100_reg, #flag_t100_bit ;100 ms tick ?
         bra     done_100ms  ;no, skip this section
         bclr    flag_t100_reg, #flag_t100_bit ;reset the flag

         ;perform 100 ms processing here

done_100ms:                  ;done with the 100 ms processing
      

Some preprocessor state is created or updated after each flag is defined. This allows access to the list of flags and information about each flag to preprocessor code following the flag definitions. This state is in the form of preprocessor constants. The constants are:

Flagdata_nflags

Integer, the total number of flags created.

Flagdata_nwords

Integer, the total number of GFLn words required for all the flags.

Flagdata_flagn

String. One of these constants exists for each flag. N is the 1 thru Flagdata_nflags sequential number of the flag. The value is a string with three tokens:

  Name WordNumber BitNumber

Name is the name as given in the FLAG command.

WordNumber is a integer string of the 0-N number of the GFLn word this flag is contained in.

BitNumber is the 0-N number of the bit within the word. Flags are allocated within GFLn words in low to high bit order. The first flag in a word therefore has a bit number of 0.


Inline Functions

All the ESCR functions are available, plus the following:

FP24I val

Converts the numeric value val to Embed Inc PIC 24-bit floating point and returns the result as a 6 character hex integer in native MPASM format. For example:

  [FP24I 3.14159]   -->   h'419220'

This function does not return a string data byte, but the raw characters of a hexadecimal value in native assembler format.

FP24_INT val

Returns the integer value of the 24 bits resulting from val expressed in Embed Inc PIC 24-bit floating point. For example:

  [FP24_INT 3.14159]   -->   4297248

FP32F val

Converts the numeric value val to Embed Inc dsPIC 32-bit fast floating point, and returns the result as a 8 character hex integer in native ASM30 format. For example:

  [FP32F -7.5]   -->   0xC002E000

This function does not return a string data byte, but the raw characters of a hexadecimal value in native assembler format.

FP32F_INT val

Returns the integer value of the 32 bits resulting from val expressed in Embed Inc dsPIC 32-bit fast floating point. For example:

  [FP32F_INT -7.5]   -->   -1073553408