Jallib Device Files Users Guide

by Rob Hamerling

Table of contents

  1. Introduction
  2. The Overall Picture
  3. User Information
  4. Generating device files

    1. Introduction

    This document serves two purposes:

    The Jallib device files are generated by means of a Rexx script 'dev2jal'. Its name is an abbreviation of 'MPLAB .dev to .jal' because it uses the .dev files of the MPLAB-IDE to create the Jallib device files.
    Notes:

    The advantages of automated generation of device files are pretty obvious, such as:

    The advantages of a consistent naming convention are also obvious:


    2. The Overall Picture

    With the design of the device files I had in mind a structure as shown below.

                       +----------+   +------------------+
                       | device   |   |     general      |
                       | specific |---|     include      |
                       | include  |   |chipdef_jallib.jal|
                       +----------+   +------------------+
                            |
             +--------------+--------------+-------------+-----------
             |              |              |             |
       +----------+   +----------+   +----------+   +----------+
       | function |   | function |   | function |   | function |
       | include  |   | include  |   | include  |   | include  |   etc
       | 'delay'  |   |  'jal'   |   |'adc.....'|   |'pwm....' |
       +----------+   +----------+   +----------+   +----------+
    

    The device files are now part of the central JalV2 library repository Jallib at GoogleCode, which uses the same structure.

    Device Files

    The device files are the base for other include files and contain:

    Including a device file doesn't change anything to the PIC. For example pins which are input after power-on or reset remain input, etc. Required changes are the responsibility of the application program or function libraries.
    For user convenience every device file contains a procedure to disable all analog modules of the PIC and to change all pins which are by default analog to digital I/O: enable_digital_io(). This procedure calls on its turn procedures to disable ADC modules, Comparator modules and a procedure to set analog pins to digital, all when applicable to the specific PIC.

    The device file contains a set of 'default' configuration bits, which may be different than the 'Default/Unprogrammed default' in the datasheet! Consider 'default' as a synonym of 'undefined'! Always specify all configuration bits!

    Common Include File 'chipdef_jallib.jal'

    The file 'chipdef_jallib.jal' which comes with these device files replaces the file 'chipdef.jal' which comes with the compiler distribution. It is included by every device file and contains:

    With the statement 'pragma target chip = .....' in every device file the compiler assigns a unique value to the constant 'target_chip'. The program may reference this variable with a symbolic name. This symbolic name consists of 'pic_' followed by the type of the PIC, which makes it possible to use the same source file to generate a hex file for different types of PICs, as the following example shows:

       include 16f88
    
       if (target_chip == PIC_16F88) then          -- (not for 16f87)
    
         ....                                      -- 16F88 unique code
    
       end if
    

    By changing the include statement to 16f87 (or any other) the statements between 'if' and 'end if' will be skipped by the compiler.

    The list of targets in chipdef_jallib.jal makes sure that every possible target name and the corresponding value of target_chip is known by the compiler.

    Note: The original chipdef.jal file of the compiler package specifies a different value for 'target_chip' and not for all PIC types. Therefore it had to be replaced when using this set of device files.

    Function Include Files

    Function specific include files offer facilities to ease the use of PIC peripherals (such as USART, ADC), external devices (such as LCDs, sensors), or extensions to the Jal language such as for data formatting, mathematical functions, etc.

    Function specific include files should be included explicitly as required by the application program, this is not done by the device files.

    In most cases the function include files require some statements to couple function specific registers and pins with the device. Read the comments in the library sources and the library documentation for instructions. Most libraries contain comments with user instructions in the header of include files and just ahead of the procedures and functions in these files.


    3. User Information

    We'll start with a very elementary sample program (blink-a-led) to show how device files make programming in JAL a piece of cake, followed by a description of other features of the device files which are aimed at writing device independent libraries.

    Sample program

    The device files define static device (PICmicro) specific matter. This allows writing elementary programs, such as for a blinking led, which are almost device independent. Differences are mostly in the fuse settings.

    The device files are also the base for extensions, such as libraries for more complicated functions like displaying text on an LCD display or handling analog devices.

    Below a simple blink-a-led program (led on pin 1 of port A) for a PIC16F886 using a 20 MHz resonator. In addition to the device-specific information obtained from the include file '16f886.jal' some run-time information is needed, like the speed and type of the oscillator and some other 'environmental' variables. No extra function libraries are required.

    -- ------ blink-a-led on pin_A1 of a PIC16F886 --------
    
       include 16f886                        -- target is a PIC16F886
                                             -- Notes: - The extension .jal is
                                             --          added by the compiler!
                                             --        - No other includes needed.
    
       pragma target clock  20_000_000       -- oscillator frequency (in Hz)
                                             -- required for delays
    
       pragma target OSC    HS               -- high speed external oscillator
       pragma target WDT    Disabled         -- watchdog off
       pragma target MCLR   External         -- external chip reset
       pragma target LVP    Disabled         -- no low voltage programming
    
       enable_digital_io()                   -- set all pins to digital I/O
    
       alias  led           is pin_A1        -- declare alias for pin_A1
       alias  led_direction is pin_A1_direction   -- and for its direction
    
       led_direction = output                -- make led-pin output
       forever loop                          -- endless loop
          led = on                           -- there is light!
          _usec_delay(250000)                -- spin 1/4 seconds
          led = off                          -- flip (on->off,off->on)
          _usec_delay(250000)                -- spin 1/4 seconds
       end loop
    
    
    When loaded in a 16F886 with 20 MHz resonator or crystal a led connected (with series resistor!) to pin 3 (RA1) should blink twice a second.

    Naming conventions for Ports and Pins

    Unfortunately MPLAB of Microchip is not particularly consistent in its choice of names! The datasheets and the various informational files in MPLAB not infrequently use different names for the same entity! As a rule the device files use the names as used by the datasheets. However the device files have been generated from the MPLAB information files, not from the datasheets! So it is possible that some names may not be conform to the datasheet. When you find such a deviation not mentioned in this document, please report to the Jallib team, and most likely the next release will contain the corrected name.

    For all registers of the chip a name is declared and where appropriate also the individual bits or groups of bits are declared.
    Subfields of registers have the name of the register as prefix, like

       var volatile bit  INTCON_GIE  at INTCON : 7
    
    Some aliases are declared for easy migration or conversion of existing JalV2 libraries and programs to the Jallib environment.

    There are exceptions to the rules above.
    The aim of 'normalization' (using a consistent naming) is:

    1. to be able to use all libraries for all types of PICmicros
    2. to ease the migration of programs to other types of PICs.

    PORTx and pins, TRISx and pin directions

    For all ports and port pins a device independent alias is declared and a similar direction declaration, as the following examples show:

       var  volatile  byte  PORTA  at  <addr>
       var  volatile  byte  TRISA  at  <addr>
       var  volatile  byte  PORTA_direction at TRISA
       var  volatile  bit   pin_A0  at  PORTA : 0
       var  volatile  bit   pin_A0_direction at TRISA : 0
    
    etc. (for all other existing pins and ports).

    GPIO and TRISIO (with the smaller chips)

    Although the smaller PICs have no 'official' PORTA and TRISA registers, the device files contain aliases for these. So even with the smaller PICs you can use the names PORTA, pin_A0, etc.

       var  volatile  byte  GPIO   at  <addr>
       var  volatile  byte  PORTA  at  GPIO
       var  volatile  byte  TRISIO  at <addr>
       var  volatile  byte  TRISA  at  TRISIO
       var  volatile  byte  PORTA_direction at TRISIO
       var  volatile  bit   pin_A0  at  GPIO : 0
       var  volatile  bit   pin_A0_direction at TRISIO : 0
    
    etc. (for all other existing pins)

    Pins which can be input-only may have no corresponding _direction variable, for example pin_E3 of the 18F4550.

    Nibbles

    Because the upper and lower 4 bits ('nibble') of a port are used frequently as a unit, these are declared as pseudo variables.

       PORTx_low               - bits 0..3    (low order bits)
       PORTx_high              - bits 4..7    (high order bits)
       PORTx_low_direction
       PORTx_high_direction
    
    This allows nibbles to be used as a regular variables, and can also be used to set pin directions by 4 at a time:
       PORTA_high = "7"                  -- low nibble remains unchanged
       PORTA_low_direction = all_output  -- direction upper nibble unchanged
    
    Several function libraries in the Jallib collection use this facility.

    Note: Nibbles are always declared even if the register doesn't have the nibble fully populated, or even not populated at all!

    Alias names

    When a pin is multiplexed (has a different function depending on control registers or configuration bit settings), aliases are declared to make the pin accessible by a more functional name. For example: of the 16F88 pin_B6 is usable as analog input for the ADC module as channel 5 and therefore pin_B6 has been given an alias name pin_AN5. You can find the 'AN5' name with the pin layout pictures and tables in the datasheet.
    Of course also for the pin_B6_direction an alias is declared and called similarly pin_AN5_direction!
    Libraries (for this example the ADC library) will use the alias names in stead of the physical pin names. Another PIC may have pin_AN5 associated with a different physical pin, but by using the alias name the ADC library becomes indenpent of the physical pin configuration which makes the library to a large extent device independent.

    If you want to use another name for a port, nibble or individual pin you can also specify an alias in your program. For example when you have a red led connected to pin 0 of PortA, you could specify:

       alias led_red  is  pin_A0
    
    and use 'led_red = on' or 'led_red = off' assignments in your program.

    Pin aliases in the device files are declared in this way and therefore also make use of the port shadowing provided by the device files. This way of aliasing - using the keyword 'alias' - is only available since JalV2 compiler version 2.4n.

    You should avoid direct pin and I/O port manipulation, because it will be overruled by the automatic shadowing mechanism (see the chapter about About Port Shadowing). For example do not specify:

       var bit led_red at portA : 0
    
    With this specification a 'led-red = on' will have the desired result, but it will not update the shadow register. Any next operation which uses the shadowing mechanism will override the previous direct control operation.

    Some pin alias names are not acceptable for the JalV2 compiler, in which case a special name is used. For example PICs with USB support have a D+ and D- pin. These are declared (for the 18F4550) as:

       alias  pin_D_POS     is  pin_C5
       alias  pin_D_NEG     is  pin_C4
    

    Some function pins can be on one or another pin of a PIC, controlled by a register or a configuration bit setting. In these cases the name has to be suffixed to prevent duplicate names. For example the 16F737 can have the CCP2 bit on pin_B3 or pin_C1, controlled by a configuration bit (fuse_def CCP2MUX).

       alias  pin_CCP2_RB3  is  pin_B3
       alias  pin_CCP2_RC1  is  pin_C1
    
    The program or library has to detect the actual use of the CCP2 pin.

    Some high end 18Fs have an even more complex multiplexing mode. With the 18F8310 for example the multiplexing depends also on the processor mode. One position of CCP2 is pin_C1, the alternate pin is pin_E7 (in Microcontroller mode) or pin_B3 (in Microprocessor, Extended Microcontroller and Microcontroller with Boot Block modes). This variant is not always available in the current device files!

    Non-memory-mapped registers

    Some PICs, mainly in the baseline series are missing some addressable ('memory mapped') Special Function Registers (SFRs). For example the 12-bit core PICs (10Fs, 12F5x, etc) have no memory mapped TRISx registers, in stead these PICs have a TRISx instruction to set the direction of ports or pins. This would make it impossible for function libraries and application programs to use statements like:

       PORTA_direction = all_output
    
    To make this possible the device files contain pseudo variables which mimic the existence of memory mapped registers.

    For example even though a 16F509 has no addressable TRISA register, you can still specify:

       pin_A5_direction = output
    
    to make pin_A5 (alias of pin_GP5) an output pin.

    Some PICs of the 18F series have SFRs which are only accessible when the ADSHR bit in WDTCON is set (when not set a different SFR is accessed). For example with the 18F65J50 ADCON0 and ANCON1 share address FC2h. When the ADSHR bit of WDTCON is reset (0) ADCON0 is accessed, when the ADSHR bit is set (1) ANCON1 is accessed.
    The device files will do this automatically with the help of pseudo variables. For example when ANCON1 is used in a JALV2 statement the ADSHR bit is set automatically (and reset afterwards).

    Input-only pins

    The Jallib device files of the 18F-series and the extended midrange families have their pins declared as 'expansion' of the LATx registers, even when the pin is input-only and the corresponding bit in the LATx register would not be active. But when PORTx has just input-only pins the LATx register is not required and may not be present (in the MPLAB .dev file). And when LATx is absent the pins of PORTx cannot be declared as expansion of the LATx register! One such a situation is known and a solution is provided.

    Several PICs of the 18F-series and the extended midrange families have their MCLR pin multiplexed with pin_E3. This pin is useable as input-only pin when MCLR is set to 'internal' via a configuration bit setting. When pin_E3 is the only active pin of PORTE the LATE register is frequently not present, and therefore pin_E3 and its aliases are declared as expansion of the PORTE register in stead of the LATE register even when the LATE register is present, (which may be an error in the MPLAB .dev file).

    Note: For an input-only pin the corresponding bit in the TRISx register may be inactive, or even the TRISx register may be absent. In that case the Jallib device files will not contain a declaration of the corresponding pin_direction.

    Names of functions modules

    Names of MSSP registers

    Names of registers of MSSP modules have been normalized as follows:

    This naming convention has been chosen because of the differences between the midrange and 18F series.

    In many cases the first SSP module (SSP1) of the 18Fs and extended midrange PICS can be used in the same way as the SSP module of a midrange PIC. For this purpose the following aliases are declared for registers and their subfields of the first SSP module in the relevant device files:
    field alias remarks
    SSP1CON or SSP1CON1 SSPCON
    SSP1CON2 SSPCON2 when present
    SSP1CON3 SSPCON3 when present
    SSP1STAT SSPSTAT
    SSP1BUF SSPBUF
    SSP1MSK SSPMSK when present

    All subfields of these registers have a similar alias (the register prefix is changed, the subfield name kept asis).

    In addition some related subfields have an alias, like:
    field alias remarks
    PIE1_SSP1IE PIE1_SSPIE
    PIR1_SSP1IF PIR1_SSPIF

    Names for registers and subfields of CCP modules

    There are CCP modules and Enhanced CCP modules. The first is also called 'legacy' CPP modules in this document and elsewhere. Most legacy CCP modules have registers names starting with CCP, most registers of enhanced CCP modules start with ECCP. The same is true for subfields of these registers. However there are many deviations from these rules and contradictions between MPLAB .dev files and the datasheets!

    Enhanced CCP modules can be used as legacy CCP modules, in particular for PWM operations. For this purpose a number aliases are added to the device files which allow access of enhanced CCP registers and subfields with legacy names. An example of this is the pwm_hardware library.

    The following aliases for enhanced CCP modules are declared:
    field alias remarks
    ECCPxCON CCPxCON x in range 1..10
    ECCPxCON_EDCxB CCPxCON_DCxB bits*2
    ECCPxCON_ECCPxM CCPxCON_CCPxM bits*4
    ECCPRx CCPRx
    ECCPRxH CCPRxH
    ECCPRxL CCPRxL

    Extended midrange PICs (12/16F18/19xx) have only enhanced CCP modules which have 'legacy' names. Therefore no special naming is needed to use these as legacy CCP modules.

    For PICs with both an CCP1CON and a ECCP1CON register (18f448,4480,458,4580,4585,4680,4682,4685) to allow the enhanced CCP module to be used as second legacy CCP module the following aliases are declared:
    field alias remarks
    ECCP1CON CCP2CON
    ECCP1CON_EDC1B CCP2CON_DC2B
    ECCP1CON_ECCP1M CCP2CON_CCP2M
    ECCPR1 CCPR2
    ECCPR1H CCPR2H
    ECCPR1L CCPR2L

    Corresponding pins when called ECCP1 have an alias CCP1.

    Some PICs (16F91x,946, 18F2321,2480,2580,4321,4480,4580) have the CCPxCON 2-bits subfield DCxB defined as 2 separate bits CCPxX and CCPxY, other PICs (16F88x) have this field enumerated and defined as DCxB1 and DCxB0. For compatibility with most other PICs a 2 bits field CCPxCON_DCxB has been added in the device files for these cases.

    Names of ANSEL bits

    For the control of the ADC channel the ADC library has to set the appropriate pin(s) to analog (input). There are generally 3 methods used by the different PICs:

    The first two methods as covered by the ADC libraries, this section is about the third method with ANSEL register(s). There are a couple of issues with this method:

    The first item is no problem when always referring to the logical pin name pin_ANx (an alias of the physical pin name). A solution for the second item has been found by declaring aliases for the channel selection bits in ANSEL registers (name normalization). In stead of enumerating the bits of all ANSELx registers individually, a number of bit aliases 'JANSEL_ANSx' is declared, in which 'x' represents the ADC channel and which point to the appropriate AN-pin.
    For example the declaration of the JANSEL bits of a 16F722 looks like:

       var volatile byte   ANSELA           at  { 0x185 }
       var volatile bit    JANSEL_ANS4      at  ANSELA : 5     -- pin_AN4 = pin_A5
       var volatile bit    JANSEL_ANS3      at  ANSELA : 3     -- pin_AN3 = pin_A3
       var volatile bit    JANSEL_ANS2      at  ANSELA : 2     -- pin_AN2 = pin_A2
       var volatile bit    JANSEL_ANS1      at  ANSELA : 1     -- pin_AN1 = pin_A1
       var volatile bit    JANSEL_ANS0      at  ANSELA : 0     -- pin_AN0 = pin_A0
       -- -------------------------------------------------
       var volatile byte   ANSELB           at  { 0x186 }
       var volatile bit    JANSEL_ANS13     at  ANSELB : 5     -- pin_AN13 = pin_B5
       var volatile bit    JANSEL_ANS11     at  ANSELB : 4     -- pin_AN11 = pin_B4
       var volatile bit    JANSEL_ANS9      at  ANSELB : 3     -- pin_AN9  = pin_B3
       var volatile bit    JANSEL_ANS8      at  ANSELB : 2     -- pin_AN8  = pin_B2
       var volatile bit    JANSEL_ANS10     at  ANSELB : 1     -- pin_AN10 = pin_B1
       var volatile bit    JANSEL_ANS12     at  ANSELB : 0     -- pin_AN12 = pin_B0
    
    As you can see the JANSEL_ANSx numbering is not restricted to bits 0..7 of the first ANSEL register (whatever its name), it is also used for channel numbers higher than 7 controlled by another ANSEL register. Note further that:

    Other PICs, like for example the 18F43K22, have 28 ADC channels spread over 5 ANSEL registers, also largely irregularly numbered. For example pin_AN5..7 are controlled by ANSELE. The declaration of JANSEL_ANS0..27 hides all these irregularities from the ADC library.

    Another example, now for the 10F222:

       var volatile byte   ADCON0           at  { 0x7 }
       var volatile bit    JANSEL_ANS1      at  ADCON0 : 7
       var volatile bit    JANSEL_ANS0      at  ADCON0 : 6
    
    In this case the channel selection bits are in register ADCON0 (the 10Fs have no ANSEL register), but the ADC library doesn't need to know when it uses the JANSEL_ANSx alias.
    Note: in reality the channel selection of the 10F220/222 is somewhat more complicated, but the ADC library takes care of that!.

    Names of other ADC registers and subfields

    Names of registers and subfields of ADC modules have been normalized as follows:

    When the ADCONx_VCFG subfield is a multi-bit field it is declared both as a multi-bit field ADCONx_VCFG and as enumerated bits (ADCONx_VCFG0 and ADCONx_VCFG1). Same for ADCONx_PVCFG and ADCONx_NVCFG.

    While most PICS with more than 8 ADC channels have a 4-bits subfield ADCONx_CHS, some PICs have the channel selection bits scattered over more than 1 subfield. For example the 16F7x7s have a 3-bits CHS field plus a single CHS3 bit to be able to support channel 8 and up. In this and similar cases a pseudo variable ADCONx_CHS has been declared which takes care of the scattering of channel selection bits. So an ADC library can always address the variable ADCONx_CHS as multibit 'binary' field, regardless if the bits are scattered over the register or not.

    A similar situation exists for the ADCS bits of ADCONx of some PICs. For PICs which have their ADCS bits scattered over ADCON0 and ADCON1 a pseudo-variable ADCON0_ADCS is added which takes care of setting the proper bits. In this way an ADC library can always address the variable ADCONx_ADCS as single multibit field, regardless if the bits are scattered over registers or not and regardless if it is a bit*2 or a bit*3 variable.

    Names of registers and subfields of [E]USART modules

    PICs can have zero, one or two USART modules, of which zero, one or both can be 'extended' (EUSART) modules. Compared to a 'legacy' USART an 'extended' USART has a BAUDCON register and can use a 16 bits in stead of an 8-bits value for the baudrate divisor, allowing a more accurate baudrate setting, especially at high speeds.

    The names of USART related registers and -subfields are not particular constent in the MPLAB .dev files, so it is desired to normalize these. And it would be convenient if serial libraries supporting a single serial interface could be used one of both USARTs of PICs with two USARTs. These are the primary reasons for the following naming convention in the Jallib device files:

    Application of these rules results in the following list of names:
    single USART first of 2 USARTs second of 2 USARTs
    BAUDCON BAUDCON1
    BAUDCON (alias)
    BAUDCON2
    BAUDCTL BAUDCTL1
    BAUDCTL (alias)
    BAUDCTL2
    RCREG RCREG1
    RCREG (alias)
    RCREG2
    RCSTA RCSTA1
    RCSTA (alias)
    RCSTA2
    SPBRG SPBRG1
    SPBRG (alias)
    SPBRG2
    SPBRGH SPBRGH1
    SPBRGH (alias)
    SPBRGH2
    TXREG TXREG1
    TXREG (alias)
    TXREG2
    TXSTA TXSTA1
    TXSTA (alias)
    TXSTA2
    PIE1_RCIE PIE1_RC1IE
    PIE1_RCIE (alias)
    PIE3_RC2IE
    PIE1_TXIE PIE1_TX1IE
    PIE1_TXIE (alias)
    PIE3_TX2IE
    PIR1_RCIF PIR1_RC1IF
    PIR1_RCIF (alias)
    PIR3_RC2IF
    PIR1_TXIF PIR1_TX1IF
    PIR1_TXIF (alias)
    PIR3_TX2IF

    Notes:

    With these names serial libaries or application programs supporting only a single serial interface can use the register and field names without suffix for the only USART or the first of two USARTs. Libraries supporting two serial interfaces will preferrably use the qualified names (with suffix).

    Multiple SPI or I2C Modules

    Like multiple USARTs PICs can have other multiple peripheral modules like SPI and I2C. With multiple modules of the same type the related pins have names with a suffix ('1' or '2'), while with a single module the pin names have no suffix. Currently the libraries for SPI and I2C support only a single module and use pin names without suffix. To make it possible to use these libraries for the first of both modules the related pins with suffix '1' have been given an extra alias name without suffix.

    Note: In the device files the extra aliases refer to the original 'real' pins (are not aliases of an aliases), hence the notation <pin_xxxx> above! For example a device file might contain:
      alias      pin_SDI1       is pin_C4
      alias      pin_SDI        is pin_C4
    
    and similar definitions for the other pins.

    Names of Timer fields

    Some register subfields of timer control registers have inconsistent names in the MPLAB .dev files.

    For these subfields the following naming convention has been chosen:

    Names of RTCC registers

    For consistency with the ALRMCFG register and since the RTCPTR1 - and RTCPTR0 bits of the RTCCFG register could be used as 2-bits binary field - an additional field is declared:

      var volatile  bit*2  RTCCFG_RTCPTR     at RTCCFG : 0
    
    Same for the RTSECSEL1 and RTSECSEL0 bits of PADCFG1:
      var volatile  bit*2  PADCFG1_RTSECSEL  at PADCFG1 : 1
    
    For consistency the 2-bits ALRMCFG_ALRMPRT field has been enumerated:
      var volatile  bit    ALRMCFG_ALRMPTR1  at ALRMCFG : 1
      var volatile  bit    ALRMCFG_ALRMPTR0  at ALRMCFG : 0
    

    Subfields of STATUS_SHAD

    The shadow of the STATUS register (in the extended midrange PICs) has its bits named like in the STATUS register:

      STATUS_SHAD_Z
      STATUS_SHAD_DC
      STATUS_SHAD_C
    

    Miscellaneous remarks about names

    When you hit compilation errors related to undefined names, scan the device file of the specified target PIC to search for the Jallib name of the registers and their subfields.

    About Port Shadowing

    Port shadowing is a technique to prevent the Read-Modify-Write ('RMW') problem with I/O ports of PICmicro's. This is a problem related to its hardware design. Search the Internet for "PIC" and "read-modify-read" and you'll get many hits to more or less interesting articles! None of the explanations are repeated here. And you don't absolutely need to understand the problem, since by using the Jallib device files you won't face the problem when you follow some simple rules and avoid a few pitfalls.

    With port shadowing for the baseline and midrange PICs (10F, 12F, 16F) a RAM location is used as replacement for the port for output.

    The 18F series and the newer extended midrange (XLP) PICs have a special register for this purpose (LATx). Although the techniques are slightly different, the general rules are: reading is done from the port directly while writing is done to the shadow register of which the contents is subsequently passed to the real port.

    With the Jallib device files shadowing is automatic, as long as you use the following names:

       PORTx             -- all bits of port x
       PORTx_low         -- low order nibble of port x (bits 3..0)
       PORTx_high        -- high order nibble of port x (bits 7..4)
       pin_xy            -- single pin 'y' of port 'x'
       aliases of pin_xy
    
    (in which 'x' is a port-letter and 'y' a bit number).

    PORTx_low is read from or written to bits 3..0 of Portx, PORTx_high is read from or written to bits 7..4 of Portx.
    Note: The value for both PORTx_low and PORTx_high is passed with reading from (and must be passed with writing to) in the lower nibble (bits 3..0) of a constant or variable.

    At power on and reset all ports are in input mode. It is recommended to always initialise ports or individual pins before switching 'm from input to output mode.

    About OSCCAL

    A number of low end PICS have a reserved word in high memory, provided by the manufacturer, which contains information for calibration of the internal oscillator. When your PIC application needs the frequency of the internal oscillator to be accurate the OSCCAL register should be loaded with the provided value. This value is loaded automatically in register 'W' after a reset of the PIC. To store it in OSCCON a MOVWF OSCCAL is required at address 0x0000 of the user program.

    This is not supported by compiler or device file!

    Midrange PICs

    The midrange PICs with this feature (12F629/675, 16F630/676) have in the high memory word a RETLW instruction. This allows the following technique to be used: Insert the following statements somewhere in the beginning of your program (the exact place is not critical):

      assembler
        page call <end-of-memory>
        bank movwf OSCCAL
      end assembler
    
    in which you have to specify for <end-of-memory> the offset of the highest program memory word. For example when your PIC has 1K words of program memory you should specify:
      page call 0x3FF
    

    This technique is not without danger. When the high memory word is accidentally destroyed - for example by an erase operation of a PIC programmer whereby the contents of the high memory word is not preserved - you should not use this technique! When the high memory does not contain a return instruction the PIC will most likely enter an endless reset loop.

    Baseline PICs

    The baseline PICs with this feature (10Fs, some 12Fs) have in high memory a MOVLW instruction. Therefore the technique of 'calling' the high memory address as described above for the midrange cannot be used for the baseline!

    GenericWhen your program is for a baseline PIC, or when it is for a midrange PIC and you are not sure what is in the high memory word or you want to play it safe, you better move a 'medium' value directly into OSCCAL, for example with:
       OSCCAL = 0x80
    
    See the datasheet for acceptable values: frequently the low order bits should be zero.

    By varying the value in OSCCAL and measuring the result you may fine tune the oscillator frequency.

    Provisions for USB

    When the USB module of a PIC is activated, memory for data buffers is needed. For some PICs the address and size of data buffers is fixed, other PICs offer more freedom. The USB data buffers are specified in the Buffer Descriptor Table (BDT). This BDT is at a fixed location in RAM but not the same for all PICs. To help the USB library with finding the actual location of the BDT for a specific PIC a constant USB_BDT_ADDRESS is defined indicating the address of the Buffer Descriptor Table.

    Peripheral Pin Selection

    A number of 18F PICs have a feature called Peripheral Pin Selection. For the input and/or output of some modules a pin can be selected. There are limitations in the choice of pins, but more importantly there a many similarities and some differences between PICs.

    Input Mapping

    Pin selection for an input function is controlled by assigning a pin number to a specific register. For example the Receive pin of ESUART2 is assigned to a specific pin by putiing the pin number in RPINR16_RX2DT2 (x of pin_RPx). The control registers for the all function are the same for all PICs. Differences between PICs are only in the number of remappable pins.

    Output Mapping

    Pin selection for an output function is controlled by assigning a function number to a specific register. For example to give pin_RP10 the Transmit function of ESUART2 the function number of TX2/DT2 (number 5 for an 18F26J50) to RPOR10_RPOR. Unfortunately not all function numbers are the same for all PICs. For example the TX2/DT2 function has number 6 with the 18F27J53.

    Currently there are 2 groups of PICs:

    The differences between the groups are in numbers for output function, as shown in the following table:
    Func. Group 1 Group 2
    0 NULL NULL
    1 C1OUT C1OUT
    2 C2OUT C2OUT
    3 C3OUT
    4
    5 TX2/CK2
    6 DT2 TX2/CK2
    7 DT2
    8
    9 SDO2
    10 SCK2 SDO2
    11 SCK2
    12 SSDMA SSDMA
    13 ULPOUT ULPOUT
    14 CCP1/P1A CCP1/P1A
    15 P1B P1B
    16 P1C P1C
    17 P1D P1D
    18 CCP2/P2A CCP2/P2A
    19 P2B P2B
    20 P2C P2C
    21 P2D P2D
    22 CCP3/P3A
    23 P3B
    24 P3C
    25 P3D

    The following table shows which PICs belong in which group:
    PPS group Datasheet PICs
    1 39932 18f24j11 18f25j11 18f26j11 18f44j11 18f45j11 18f46j11
    39931 18f24j50 18f25j50 18f26j50 18f44j50 18f45j50 18f46j50
    2 39974 18f26j13 18f27j13 18f46j13 18f47j13
    39964 18f26j53 18f27j53 18f46j53 18f47j53

    The 'LF' variants these PICs are not listed, but belong to the same groups!

    To simplify the use of the PPS feature every device file has been given a constant 'PPS_GROUP' with the appropriate group number. A symbolic name of the format 'PPS_x' is used, in which x is 0,1 or 2. 'PPS_0' means: this PIC does not support Peripheral Pin Selection. The symbolic numbers are defined in constants_jallib.jal.

    With new PICS more groups may have to be introduced.

    Naming convention for configuration bit fields (fuses)

    Pragma fuse_def

    The MPLAB .dev files contain a keyword for every configuration bit or group of bits, and a description of the possible bit settings. Unfortunately not always the same keyword is used for essentially the same configuration bit or bit-field, and the keyword is sometimes different from the keyword in the datasheet, or is simply spelled wrongly! The descriptions have an even larger variation and are sometimes very long.

    For use with Jal, in particular for the 'pragma fuse_def' declarations, a consistent keyword (in JalV2 called 'opt') and single-word symbolic values (in JalV2 called 'tag') are desired. The Jallib 'standard' is described below.

    Fuse_def keywords, synonyms and replaced words

    For all pragma fuse_defs a keyword and a number of symbolic values are declared in the device files. This section deals with the keywords, the next section with symbolic values.

    Every configuration word or byte is preceeded with a comment line indicating its address in memory.
    The meaning of configuration bits can in most cases be found in the DataSheet of the specific chip, in the section 'Special Features of the CPU'. This info can also be found in the Programming Specifications of the chip. For convenience the MicroChip document numbers of the specific PIC are mentioned in the heading of its device file.

    To minimize misunderstanding and confusion the description for every keyword as found in the MPLAB .dev file is appended as comment on the 'pragma fuse_def' line. The combination of memory address and description should unambiguously identify which configuration bits are controlled by the keyword, even though the name might be different from that in the datasheet.

    Where convenient and intuitive enough the keywords found in the MPLAB .dev files are used. But synonyms are eliminated and some apparent misspellings are corrected. Sometimes an arbitrary keyword is chosen.

    The list below shows examples of most deviations of keywords from MPLAB .dev files:
    keyword replaces synonym(s) and typo(s)
    ABW ADDRBW
    BBSIZ BBSIZ0
    BROWNOUT BODEN, BOREN, DSBOREN
    BW DATABW
    CCP(x)MUX CCP(x)MX
    CPD CPDF, CPSW
    CPx CP_x
    DEBUG BACKBUG, BKBUG
    EBTRx EBTR_x, EBRTx (typo)
    ECCPMUX ECCPMX
    EXCLKMUX EXCLKMX
    FCMEN FSCM
    FLTAMUX FLTAMX
    OSC FOSC
    IOSCFS IOFSCS (typo)
    MCLR MCLRE
    MSSPMASK MSSP7B_EN, MSSPMSK
    P2BMUX P2BMX
    PMODE PM
    PMPMUX PMPMX
    PWM4MUX PWM4MX
    PWRTE PUT, PWRT, PWRTEN, NPWRTE, NPWRTEN
    RTCOSC RTCSOSC
    SOSCSEL SOSCEL
    SSPMUX SSPMX
    STVR STVREN
    T1OSCMUX T1OSCMX
    T3CMUX T3CMX
    VOLTAGE BODENV, BOR4V, BORV
    WDT WDTEN
    WRT WRT_ENABLE, WRTE
    WRTx WRT_x
    Notes:

    1. Keywords for pin multiplexing end in 'MUX', like CPPxMUX.
    2. Not all declared keywords in the MPLAB .dev files may be 'catched', there may be some inconveniently (long) keywords left.
    3. When the compiler stalls over a fuse-def line a correction should be applied. If you encounter such an occasion please report it in the Jallib discussion group at Google Groups.

    Fuse_def symbolic values

    As mentioned above the MPLAB .dev files contain frequently long and descriptions with many variations of the same story. Only for the oscillator specification alone the MPLAB .dev files contains about 200 different descriptions! But often the description is a single word like DISABLED or ACTIVE. Multi-word descriptions have been reduced to a single word or at least a single string (multiple words coupled by underscore characters).

    Like for the keywords also for the symbolic values many synonyms can be found in the MPLAB .dev files. These synonyms are eliminated to a large extent. For example 'ENABLE' is often used even when the datasheet or MPLAB .dev file specifies 'ON' or 'ACTIVE'.

    Below a set of 'normalized' pragma fuse_def:

    Fuse_def ADSEL (ADC resolution)

       B10                -- 10 bits
       B12                -- 12 bits
       B..                -- other number of bits
    

    Fuse_def ABW (Address Bus Width)

       B8                 -- 8 bits
       B16                -- 16 bits
       B..                -- other number of bits
    

    Fuse_def BBSIZ (Boot Block Size)

       W256               -- 256 words
       W512               -- 512 words
       W1K                -- 1024 words (1K words)
       W2K                -- 2048 words (2K words)
       W...               -- any other number of words
    

    Fuse_def BG (Band Gap)

       ADJUST_NEG         -- negative adjustment
       ADJUST_POS         -- positive adjustment
       ...                -- other
    

    Fuse_def BROWNOUT (Brown Out detection)

       ENABLED            -- BOD enabled, SBOREN disabled
       RUNONLY            -- BOD enabled in run, disabled in sleep
       CONTROL            -- SBOREN controls BOR function
       DISABLED           -- BOD and SBOREN disabled
    
    BROWNOUT is also used for Deep Sleep BrownOut (DSBOREN).

    Fuse_def BW (Bus Width)

       B8                 -- 8 bits
       B16                -- 16 bits
       B..                -- other number of bits
    

    Fuse_def CCPxMUX (multiplexing of pin of CCP module x)

       pin_xy             -- assigned to pin y of PORTx
       pin_..             -- any other
       Enabled            -- ) see datasheet
       Disabled           -- )
    

    When the multiplexing is also dependend of the microprocessor mode (with some high end 18Fs) the pin for 'Microcontroller mode' is specified. Of course in other modes another alternate pin will actually be configured!

    Fuse_def CP (Code Protection)

       ENABLED            -- Code memory read protection on
       DISABLED           -- Code mewmory read protection off
    

    Fuse_def CPD (Data Code Protection)

       ENABLED            -- Data (EEPROM) memory read protection on
       DISABLED           -- Data (EEPROM) memory read protection off
    

    Fuse_def CPUDIV (CPU clock divisor)

    Specifies the divisor value for the Primary Oscillator to obtain the desired CPU frequency.
       P1                 -- No divide *)
       P2                 -- CPU freq. is oscillator freq. divided by 2 *)
       P3                 -- CPU freq. is oscillator freq. divided by 3 *)
       P4                 -- CPU freq. is oscillator freq. divided by 4 *)
    

    * The symbolic values P1, P2, P3 and P4 have a one-to-one relationship with the divisor value, but only when PLL is not enabled.
    When the PIC has a PLL module and PLL is enabled the output of the PLL module (96 MHz) is used obtain the desired CPU frequency and the corresponding divisor values may be different! For example: when PLL is enabled with the 18f4550 P1 gives a divisor value 2, P2 divisor 3, P3 divisor 4, P4 divisor 6.
    See the Oscillator chapter in the datasheet for actual values.

    Fuse_def DSWDTOSC (Watchdog oscillator selections)

       INTOSC             -- internal oscillator
       OSC                -- oscillator determined by OSC fuse_def
    

    Fuse_def DSWDTPS and WDTPS (Deep Sleep) WatchDog Timer PostScaler

       P2G                -- 1 : 2G  (2 * 1073741824)
       P...
       P2M                -- 1 : 2M  (2 * 1048576)
       P...
       P2K                -- 1 : 2K  (2 * 1024)
       P..
       P2                 -- 1 : 2
    

    Fuse_def EBTRB (bootblock write protection)

       ENABLED            -- boot block table read protected
       DISABLED           -- boot block may be table read
    

    Fuse_def ECCPxMUX (ECCP pin multiplexing)

       pin_xy             -- pin y of portx is used
    

    Fuse_def EMB (External memory bus width)

       B12                -- 12 bits
       B16                -- 16 bits
       B20                -- 20 bit
       DISABLED           -- disabled
    

    Fuse_def ETHLED (Ethernet LED)

       ENABLED            -- Ethernet LED enabled
       DISABLED           -- Ethernet LED disabled
    

    Fuse_def EXCLKMUX (TMR1/T5CLKI assignement)

       pin_xy             -- Clock input assigned to pin y of portx
    

    Fuse_def FLTAMUX (FLTA multiplexing)

       pin_xy             -- pin y of portx is used
    

    Fuse_def FOSC2 (default/reset system clock select)

       INTOSC             -- Internal oscillator
       OSC                -- Clock selected by OSC setting
    

    Fuse_def HFOFST (...)

       ENABLED            -- enable
       DISABLED           -- disabled
    

    Fuse_def IOSCFS (Internal Oscillator Frequency Select)

       F4MHZ              -- 4 MHz
       F8MHZ              -- 8 MHz
    

    Fuse_def LPT1OSC (Low Power Timer1 Oscillator)

       LOW_POWER          -- low power, low noise immunity
       HIGH_POWER         -- high power high noise immunity
    

    Fuse_def LVP (Low Voltage Programming)

       ENABLED            -- LVP on
       DISABLED           -- LVP off
    

    Fuse_def MCLR (reset)

       EXTERNAL           -- /MCLR pin enabled
       INTERNAL           -- /MCLR pin is digital I/O
    

    Fuse_def OSC (oscillator)

       LP                 -- Low Power crystal on OSC1,OSC2
       XT                 -- Crystal or Resonator on OSC1,OSC2
       HS                 -- High Speed Crystal or Resonator on OSC1,OSC2
       HS_PLL             -- HS with (hardware) PLL active
       EC_CLKOUT          -- External Clock (TTL) signal on OSC1, ClockOut on OSC2
       EC_NOCLKOUT        -- External Clock (TTL) signal on OSC1, OSC2 is I/O
       EC_CLKOUT_PLL      -- EC_CLKOUT with PLL active
       EC_NOCLKOUT_PLL    -- EC_NOCLKOUT with PLL active
       ECH_NOCLKOUT       -- external clock, high power mode
       ECL_NOCLKOUT       -- external clock, low power mode
       ECM_NOCLKOUT       -- external clock, medium power mode
       RC_CLKOUT          -- (external) Resistor/Capacitor oscillator on OSC1, ClockOut on OSC2
       RC_NOCLKOUT        -- (external) Resistor/Capacitor oscillator on OSC1, OSC2 is I/O
       INTOSC_CLKOUT      -- Internal oscillator, OSC1 is I/O, ClockOut on OSC2
       INTOSC_NOCLKOUT    -- Internal oscillator, OSC1 and OSC2 are I/O
    
    The first or only part is the oscillator type, the [optional] second part indicates a related subfunction. For example it may indicate if the OSC2 pin is CLKOUT or I/O, or if PLL is active. Several other keywords are possible, for example: The datasheet will specify the possibilities, browse the device file for the applicable keywords.

    Fuse_def PLLDIV (PLL prescaler)

       P1                 -- 1 : 1
       P..                -- etc
       P12                -- 1 : 12
    

    Fuse_def PLLEN (PLL enable)

       P1                 -- 1 : 1
       P4                 -- 4 : 1
       F500KHZ            -- freq 500 KHz
       F16MHZ             -- freq 16 MHz
    

    Fuse_def PWM4MUX (PWM4 multiplexing)

       pin_xy             -- PWM4 assigned to pin_y of portx
    

    Fuse_def PMODE (Extended memory bus)

       B12                 -- extended microcontroller 12-bit
       B16                 -- extended microcontroller 16-bit
       B20                 -- extended microcontroller 20-bit
       EXT                 -- extended microcontroller
       MICROCONTROLLER     -- microcontroller
       MICROPROCESSOR      -- microprocessor
       MICROPROCESSOR_BOOT -- microprocessor with boot block
    

    Fuse_def PMPMUX (PMP multiplexing)

       PORTx              -- PMP on PORTx and other ports
    

    Fuse_def PWRTE (Power-up Timer Enable)

       ENABLED            -- Power up timer enabled
       DISABLED           -- Power Up timer disabled
    

    Fuse_def RTCOSC (RTC reference clock selection)

       INTOSC             -- Internal oscillator
       T1OSC              -- Timer 1 oscillator
    

    Fuse_def SIGN (bulk erase)

       NOT_CONDUCATED
       AREA_COMPLETE
    

    Fuse_def SSPMUX (SPI I/O multiplexing)

       pin_xy             -- SPI active on pin y of portx
       DISABLED           -- SPI not assigned
    

    Fuse_def T1OSCMUX (Timer 1 multiplexing)

       pin_A6_A7          -- pin_A6 and pin_A7 are used
       pin_B2_B3          -- pin_B2 and pin_B3 are used
    

    Fuse_def USBDIV (USB clock selection)

       P1                 -- no divide
       P2                 -- divide by 2
    

    Fuse_def USBPLL (USB PLL source)

       F48MHZ             -- from 96MHZ PLL / 2
       OSC                -- from Oscillator
    

    Fuse_def VCAPEN (Voltage regulator capacitor pin)

       DISABLED
       pin_A0
       ...  etc (other pins which could be assigned
    

    Fuse_def VOLTAGE (Brown out voltage)

       V20                -- 2.0 Volt
       V27                -- 2.7 Volt
       V42                -- 4.0 Volt
       V45                -- 4.5 Volt
       ...  etc (whatever voltages are applicable)
    

    Fuse_def WAIT (Wait ...)

       ENABLED            -- synchronous
       DISABLED           -- asynchronous
    

    Fuse_def WDT (WatchDog Timer)

       ENABLED            -- Watchdog enabled
       DISABLED           -- Watchdog disabled
       CONTROL            -- Software controlled (SWDTEN)
       RUNNING            -- Enabled while running, disabled in Sleep.
    

    Fuse_def WDTCS (WatchDog Timer Clock Select)

       STANDARD
       LOW_POWER
    

    Fuse_def WPEND (Write protect area)

       P0_WPFP            -- from page 0 to write protect page
       PWPFD_END          -- from write protect page to end of memory
    

    Fuse_def WPFP (Write Protect Flash Page)

       P0                 -- Write protect flash page 0
       P1                 -- Write protect flash page 1
       P..                -- etc
       P127               -- Write protect flash page 127
    

    Fuse_def WRT (Program Memory Self-Write Protection)

       NO_PROTECTION      -- All program memory writable
       ALL_PROTECTED      -- Writing of program memory prohibited
       Rxxxx_yyyy         -- Protected memory range
                          -- (only specific ranges can be write protected)
    

    Fuse_def WRTx (Write Protection of Table/Region)

       ENABLED            -- table/region is not write protected
       DISABLED           -- table/region is write protected
    
    Notes:
    1. The list above in not exhaustive there may be others, depending on the features of the specific PICmicro. To conform to a compiler requirement names must start with a letter or an underscore and may not contain special characters and spaces. Multi-word descriptions as found in the MPLAB .dev files (other than those listed above) have been transformed to a keyword as follows:
      • special characters and spaces are translated to underscores
      • leading and trailing underscores are removed
      • multiple consecutive underscores are reduced to a single underscore
      • when the first character is a digit a letter is added as prefix, which can be 'R' for range, 'F' for frequency, 'B' for number of bits, or 'N' otherwise.
    2. As an example of an address range specification for PICs with the possibility to protect certain code memory areas you may have to specify:
      pragma target CP R0F00_0FFF
      
    3. The device file contains a specification for the fuses array. how many words or bytes and their corresponding memory addresses. Also a default fuse setting is specified, which may or may not be suitable for your application! Never trust defaults!

    Alternate ways to specify configuration bits

    When you find the specification of fuse_def inconvenient or you want to specify the bits one-by-one by yourself, the compiler allows you to do so. For example for the PIC16F690 the following group of statements:

       pragma target OSC       HS
       pragma target WDT       Disabled
       pragma target PWRTE     Enabled
       pragma target MCLR      External
       pragma target CP        Disabled
       pragma target CPD       Disabled
       pragma target BROWNOUT  Enabled
       pragma target IESO      Disabled
       pragma target FCMEN     Disabled
    
    is equivalent with:
       pragma target fuses   0b11_0011_1110_0010
    

    PICs with 16-bits core (the 18F series) have such a large set and variety of configuration bits that explicit specification is probably the best way to make sure all configuration bits are set correctly for your program. As an example see the following list for a simple blink-a-led program with an 18F242.

       pragma  target fuses 0  0b0000_0000       -- (n/a)
       pragma  target fuses 1  0b0010_0010       -- not switchable, HS osc, no PLL
       pragma  target fuses 2  0b0000_0001       -- BOR disabled, PWTR disabled
       pragma  target fuses 3  0b0000_0000       -- watchdog disabled
       pragma  target fuses 4  0b0000_0000       -- (n/a)
       pragma  target fuses 5  0b0000_0001       -- CCP2 on RC1
       pragma  target fuses 6  0b1000_0001       -- no bg debug, no LVP, STVREN
       pragma  target fuses 7  0b0000_0000       -- (n/a)
       pragma  target fuses 8  0b0000_1111       -- no code protection
       pragma  target fuses 9  0b1100_0000       -- no data protection
       pragma  target fuses 10 0b0000_1111       -- no code write protection
       pragma  target fuses 11 0b1110_0000       -- no other write protection
       pragma  target fuses 12 0b0000_1111       -- no table read protection
       pragma  target fuses 13 0b0100_0000       -- no boot block write protect
    
    (n/a) means not applicable to this specific PIC, but may be specified (as all zeroes).

    Notes:

    1. When a PIC has multiple configuration words or bytes the index value of the word or byte must be specified between 'fuses' and the value.

    Compiler requirements

    The compiler - at the moment of this writing version 2.4n - has a number of requirements for device specifications. The most important from a user perspective are the following:

    Memory allocation

    The device files specify the amounts of available data memory (RAM) for variables in bytes.

    There is a distinction between 'shared' and 'unshared' memory. For the compiler 'shared' means:

    Memory which is accessible in more than one bank but not in all banks is in this context 'unshared'.
    The compiler allocates memory for regular ('user') variables in unshared memory. When a PIC has shared memory (most PICs have) it is specified with 'pragma shared' in the device files, while unshared memory is specified with 'pragma data'.
    The log of a compilation contains a line like:
     Data area: 250 of 368
    
    in which the last number is the total amount of unshared memory, which is in most cases lower than the total amount of data memory according to the datasheet, because it does not inlcude shared memory.

    The compiler needs some data memory for internal use. The variables are named _pic_accum and _pic_isr_w, and must be in shared memory. Each device files contains a declarations for these variables. Most PICS have both shared and unshared RAM and then there is no issue, neither is there an issue with PICs with only 1 memory bank. But some midrange PICs have only shared memory while some others have no shared memory at all. This complication is handled by the device files as follows:

    Another subject of attention is data memory for USB modules. This is 'special' data memory, sometimes dedicated to the USB module, sometimes it can be used as normal data memory by the user program, but only when the USB module is inactive, and sometimes it can be shared between USB module and user program. So the amount of available data memory as specified in the device file can be smaller than the total amount of memory specified in the datasheet due to reservation by the USB module.

    Analog modules

    (to be done)


    Compatibility and Miscellaneous Remarks

    These device files are part of the central JalV2 repository 'Jallib' (http://jallib.googlecode.com). Other libraries of Jallib have been or are being converted to use the names in these device files. You are strongly recommended to use only this combination of include files. Using these device files in combination with other libraries may cause problems, especially with libraries for the old (pre JalV2) compiler.

    Note: With Jallib version 0.7 a number of constants, formerly declared in each device file is moved to a file 'constants_jallib.jal'. This file is included by chipdef_jallib.jal (which is on its turn included by every device file). Don't worry about memory occupation: unused constants are removed by the compiler automatically and don't occupy memory!


    4. Generating device files

    The process

    The device files are generated by transforming MPLAB files with a script 'dev2jal.cmd' in the /Jallib/tools directory. The script is developed and executed with 'classic' Rexx as standardly delivered with eComStation (OS/2). To run it:

    Notes:

    1. The dev2jal script expects both MPLAB and a local copy of Jallib installed on drive K. The script contains comments with instructions for possible changes in the script to run it on a different system configuration. This concerns only a few variables in the top of the script file.
    2. The 'test' commandline argument will put the device files in a 'test' subdirectory of the current directory.

    The dev2jal script can be executed on other systems (Linux, Windows) when a compatible Rexx interpreter is installed. The free 'Regina Rexx' has proven to do fine for this script (tested under Windows XP). For more information about Regina Rexx see:

    Download and install the package (latest version 3.5) when you want to run the script on a non-eComStation system. Probably the easiest way to run the script is:

    The generated device files will be in subdirectory 'test' (./test).

    To do when new datasheets become available

    Generally MPLAB contains .dev and .lkr files of PICs of which the datasheet is not yet available. The dev2jal script does not generate device files when the datasheet number is (yet) unknown. When a datasheet becomes available the following actions are needed to generate device files (by 'manual' editing the involved tools files):

    Re-iterate these actions until you are satisfied everything is OK. Then do the following:

  5. Run the dev2jal.cmd script with the 'PROD' option, SVN-add the device files of any new device files, and commit all device files and changed files in the tools and wiki directories.
  6. Run the blink-a-led script with PROD option too, SVN-add any new blink samples and commit these.
  7. Run the Rexx script 'createdswikis.cmd' to generate up-to-date wiki files related to datasheets. Note: This script needs to be run after new device files have been generated because it considers only 'existing' Jallib device files.
  8. Optionally update CHANGELOG and TORELEASE.

    To do after a fresh install of MPLAB

    The dev2jal.cmd script contains several device specific 'adaptations' to make the device files suitable for Jallib. Most of these are mentioned in chapter 3 of this document. When generating Jallib device files after a fresh install of MPLAB in addition to the 'automatic' corrections some 'manual' editing is required. These are mainly corrections of errors or omissions in the MPLAB .dev files, which may have been corrected by Microchip from one to the next version of MPLAB!

    When there are new device files which are not in Jallib yet then before running the dev2jal script you may have to perform the actions described above in the section 'To do when new datasheets become available'.

    Now run the dev2jal script with the 'TEST' option, redirect the output to a file and check this file for errors and warnings which need attention.