PIC32Lua


PIC32Lua, Lua on a PIC32 (as the name already implied ;-)



	
    CURRENT VERSION: V0.4c (20/03/2013)(d/m/y)
		
    For changes, see chapter 9 (scroll down).
    For examples, scroll even more...



As of now (12/2012), sources are also available via Github:
https://github.com/FMMT666/PIC32Lua


...

After more than 15 years with 8 bit, later 16 bit PICs, I once ordered a PIC32 Starter Kit somewhen around 01/2008, just to see what Microchip's new PIC32 series has to offer.
For whatever reason, I never used and forgot about it.

I retrieved it this week (9/2010) and just wanted to download some docs from Microchip's site. I couldn't believe what I saw:

They now offer devices with 128kB RAM in a 64 pin packages. Nice!
This reminded me of some of my old Lua projects (dspLua, STM32Lua). RAM was always the limitating factor number one.
And even the biggest Cortex-M3 stops at 96kB (STM32F103RG, 64 pin package).

Note 9/2011:
 Well, the new STM32F2xx devices indeed have 128kB in a 64 pin package... Nice!

Note 11/2011:
 Ups, the "new" STM32F4 series comes with up to 192kB RAM. Wow...
 I guess I should update the STM32 Lua version too ;)

This will is be the framework for a lualized "Lua Pocket Computer". A multi processor device with display, keyboard and a lot of interfaces, for test, measurement and calculator replacement (Do I smell "unfinished", here? ;-)

A hardware guy is just having his fun, here...


Lua? What?

to be uploaded...



Hardware

Except for a PIC32 (PIC32MX795F512L highly recommended), there's no special hardware required.
Although I run all this stuff on my own hardware, I tried to maintain compatibility to the "Microchip Starter Kit Series" and others (e.g. SD-card: card detection signals...).

Note 11/2011:
 PIC32Lua now supports the chipKIT-Max32. No other (programming) equipment required.
 Give it a try...

Note 01/2012:
 Common chipKIT-Max32 user question:
 "Will the provided binary damage my board or bootloader?"
 No, it won't!

...

Supported (off-the-shelf) Boards

  • USB Starter Kit II
  • chipKIT-Max32
  • Audio Development Board
  • every other board containing a PIC32MX795F512L (or comparable)
  • and even more ;)



chipKIT-Max32 with SD-card test connection

Starter Kit II, backplane and SD-card module

Audio Development Board


Preliminary ASCII Documentation


+--------------------------------------------------------------------------------------------------+
|
|      Minimal, but growing PIC32Lua description V0.4c
|      ASkr 8/2010 - 03/2013; www.askrprojects.net
|
|      Note: For hardware guys only ;-)
|
+--------------------------------------------------------------------------------------------------+


0       PREFACE

          Just a quick hack...
          My personal, small, yet 3 week old, "port" (...) of Lua to a PIC32 MCU.
          A hardware guy is just having his fun, here 8-)
        
          ...
       

0.1     HARDWARE

          Although many smaller, or other PIC32, types will work, this code has been written for,
          and tested on, a PIC32MX795F512L processor (bare silicon).
          Except for an oscillator (and an ICD interface for programming), nothing else is
          required.

          By default, the console interface is routed to UART2A, with a default setting of 115200, 8N1.
          
          As of version V0.4a, PIC32Lua supports the chipKIT-Max32 from Digilent.
          The (chipkit!) HEX file can be direcly programmed by "avrdude" (comes with "MPide").
          For the chipKIT-Max32, the console interface is routed to UART1A (FTDI connection).
     
          ...
          
0.1.1   SD-CARD INTERFACE

          As of V0.2a, PIC32Lua supports SPI1 and SPI2 SD-card interface, with SPI2 as
          the default interface.
          Although not fully tested, all the access can be made via Lua's internal IOLIB.
          
          HW adaption follows the "Microchip Standard" ;-)
          Schematics for PIC32Lua are (or should be) available via:
          http://www.askrprojects.net/software/pic32lua/index.html

          For settings related to the SD-card, see "HardwareProfile.h" (a little more) below.

          
          SPI2 SD-card pins ("!" denotes inverted polarity):

              SIGNAL  PIN   FUNCTION              PIC32  CHIPKIT  SD-CARD
             -------------------------------------------------------------
                !CS   RB9   chip select             33      63       1
                 CD   RG0   card detect   (opt.)    90      79       -
                 WP   RG1   write protect (opt.)    89      78       -
                 SCK  RG6   SPI clock               10      52       5
                 SDI  RG7   SPI data in             11      51       2
                 SDO  RG8   SPI data out            12      50       7

               
          SPI1 SD-card pins ("!" denotes inverted polarity):
          
              SIGNAL  PIN   FUNCTION              PIC32  CHIPKIT  SD-CARD
             -------------------------------------------------------------
                !CS   RB1   chip select             24      55       1
                 CD   RF0   card detect   (opt.)    87      45       -
                 WP   RF1   write protect (opt.)    88      46       -
                 SCK  RD15  SPI clock               48      18       5
                 SDI  RF2   SPI data in             52       0       2
                 SDO  RF8   SPI data out            53       1       7
               
           
          SD-card (bottom view):
          
               |                           |    1   -   !CS
               |                           |    2   -   SDI
               |                           |    3   -   VSS1 (GND)
               |                        ## |    4   -   +Ub  (3.3V)
               |                        ## |    5   -   SCK
               | # ## ## ## ## ## ## ## ## |    6   -   VSS2 (GND)
               | # ## ## ## ## ## ## ##   /     7   -   SDO
               | # ## ## ## ## ## ## ##  /      8   -   n.c.
               +------------------------+       9   -   n.c.
                 8  7  6  5  4  3  2  1  9               

          ...

          
0.1.1.1   SD-CARD BOOT FILE

            As of version 0.4b, PIC32Lua supports a boot file on the SD-card.
            
            If the SD-card code is built in and the boot file option is enabled
            (see "HardwareProfile.h" section below), the file
            
              BOOT32.LUA
            
            is loaded and the function
            
              BOOT32()
              
            is called.
            
            Note #1: "BOOT32()" written in captil letters!
            Note #2: All code not "hidden" inside a function gets executed
                     immediately!
            
            Error information is available via the _global_ variable "BOOT32ERR".
            Scroll down to "SD-card boot error" for more information.
            
            NOTICE:
              It is NOT "pic.BOOT32ERR", but just "BOOT32ERR"


              
            EXAMPLE:
                -- example BOOT32.LUA file

                print("- start OF BOOT32.LUA file")

                function hidden()
                  local i

                  print("- inside hidden() function in BOOT32.LUA file")
                  
                  for i=1,3 do
                    print("  blabla "..i)
                  end

                end

                function BOOT32()
                  print("- inside BOOT32() function in BOOT32.LUA file")
                  hidden()
                end

                print("- end of BOOT32.LUA file")
                
              This example will output:
              
                Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
                Lua 5.1.4  Copyright (C) 2010-2012 ASkr, PIC32
                - start OF BOOT32.LUA file
                - end of BOOT32.LUA file
                - inside BOOT32() function in BOOT32.LUA file
                - inside hidden() function in BOOT32.LUA file
                  blabla 1
                  blabla 2
                  blabla 3
                >
              
            ...


0.2     COMPILER REQUIREMENTS

          To keep things easy, the source comes as a ready-to-use MPLab/C32 package.
          Make sure you installed the C32 compiler (the free version is fine, it just
          will not allow any optimisation beyond -O1).

          NOTE:
          If possible, load the workspace file "PIC32Lua.mcw" instead of the project file!
          Otherwise, some strange things might happen (although this might be fixed in
          MPlab versions >8.60).
          
          Except for the C32 compiler directory (and some window positions), no further changes
          should be required.
          
          NOTE (11/2011); V0.4a:
            
            As of now, PIC32Lua source code ships with two project/workspace file variants:
            
             a) PIC32Lua.mcp/w
                For custom boards without bootloader ("bare chip")
             
             b) PIC32Lua-ChipkitMAX32.mcp/w
                Load this if you are using the chipKIT-Max32.
                This sets some extra compiler, linker options and uses a special linker file
                (required for chipKIT-Max32's built-in bootloader, etc...)
                If you don't want to compile the code by your own (notice that you can NOT use
                MPide for this! You'll need MPlab, a C32 compiler suite (libs) >= 2.01), just
                stick to the binary chipKIT-Max32 distribution.
          
          
          NOTE (9/2011):
          
            - USE C32 *** v2.01 ***
            - DO NOT USE THESE VERSIONS:
              - v1.12x
              - v2.00
          
          Microchip completely "reworked" libc and all processor files (v1.12 up).
          Most of these changes are not documented, additionally some of the header files
          do not match the library any more...

          Last good, known version BEFORE "libc-rework":
          
            v1.11
            
          First good, known version AFTER "libc-rework":
          
            v2.01
            
          With v2.01, you need to add the following compiler AND linker flag:
          
            -legacy-libc

          Inside MPLab, just go to
          
            Project -> Build Options -> Project
            
            Look out for tabs
            
              - MPLAB PIC32 C Compiler
              - MPLAB PIC32 Linker
              
            Enable the "Use Alternate Settings" checkbox and add a "-legacy-libc" at
            the end of the lines.

          HINT:
            You indeed can have multiple installations of C32 (in different directories).
            
            Inside MPLab, they can be invoked via:

              Project -> Select Language Toosuite
              
            Change the paths for
             
              ASM32, C32, LINK32, LIB32
            
            to any version installed on your system.

          
          Usually, nothing else but loading PIC32Lua's project or workspace files should be required.
          
          
0.3     BASIC OPERATION/NOTES

          PIC32Lua offers the same functionality as if was started from a Linux console or from
          Windows' command line: All console input/output is routed ("quickly hacked to") to
          UART2, the main interface. You can download Lua programs with copy & paste.
          I prefer Realterm: http://realterm.sourceforge.net/
          
          There is no underlaying OS. Except for some interrupt routines (console reception,
          timer,...) there are no other interfering transactions happening in the background.
          Just simple and fast...

          The DEBUG module is omitted, the IO and SYS modules were left in, but do not contain
          any useful stuff other than 'io.write()', '...read()' and '...flush()'. Note that these
          streams can not be redirected, for now.
          
          ...

          
1       COMPILE TIME SETTINGS

1.1     CONFIGURATION BITS

          As of >V0.2a, the config bits are now set in the code (>>>"asPIC.c"<<<).
      
          Required settings for PIC32Lua:
            - 80MHz CPU
            - 40MHz peripheral clock:

          Default settings (8MHz crystal):

            #if defined(__32MX795F512L__)
              #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
              #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
              #pragma config FPLLODIV = DIV_1         // PLL Output Divider
              #pragma config FPBDIV   = DIV_2         // Peripheral Clock divisor
              #pragma config FWDTEN   = OFF           // Watchdog Timer
              #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
              #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
              #pragma config OSCIOFNC = OFF           // CLKO Enable
              #pragma config POSCMOD  = XT            // Primary Oscillator
              #pragma config IESO     = OFF           // Internal/External Switch-over
              #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable (KLO was off)
              #pragma config FNOSC    = PRIPLL        // Oscillator Selection
              #pragma config CP       = OFF           // Code Protect
              #pragma config BWP      = OFF           // Boot Flash Write Protect
              #pragma config PWP      = OFF           // Program Flash Write Protect
              #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
              #pragma config DEBUG    = OFF           // Background Debugger Enable
            #else
              #error  // as a reminder if you change the processor
              ...
            
          For an 8MHZ crystal, choose (only relevant entries shown):
        
            FPLLIDIV     2x Divider                              8MHz/2=4MHz
            FPLLMUL      20x Multiplier                          4MHz*20=80MHz
            FPLLODIV     1x Divider                              80MHz/1=80MHz
            FNOSC        Primary Osc w/PLL  (XT+,HS+...)
            FSOSCEN      Disabled
            IESO         Disabled
            POSCMD       XT osc mode
            FPBDIV       Pb_Clk is Sys_Clk/2                     80MHz/2=40MHz
            FWDTEN       WDT Disabed

          Notice that, depending on the processor selection, specific bits might be missing
          or need to be added.
          In this case, setting config bits from MPLab might be preferred over #pragma
          definitions in the code (the "old" PIC32Lua <=V0.1b behaviour).

          NOTE 11/2011; V0.4a:
          
            The chipKIT-Max32 starts with peripheral clock set to Sys_Clk/1, but is reprogrammed
            to 1/2 during the PIC32Lua start up phase.
            If you are using the chipKIT-Max32, you don't need to worry about any
            of the configuration bits...
          
          ...

          
          
1.2     COMPILER/LINKER SETTINGS

          The whole project was developed within MPLab. Therefore, no external Makefiles or
          linker scripts are available yet.

          ####
          # Do _NOT_ use a "DEBUG" build configuration! USE "RELEASE"!!!
          ####
          
          C32 debug libraries interfere with some of PIC32Luas built in functions.
          
          If you are using any other processor than a MX795F512L, choose yours, here:
            Configure -> Select Device
          and remember to set new, appropriate configuration bits!

          
          For now, the stack and heap settings need to be entered under:
            Project -> Build Options -> Projects
          
          Select TAB "MPLAB PIC32 LINKER", category "General", and set your stack and heap
          memory sizes.
          
          Default values (for MX795F512L, with 128kB RAM):
          
            stack   2048
            heap  121000
          
          Sections must not overlap.
          Heap size should be chosen as large as possible. Smaller values will make PIC32Lua
          run out of memory, while larger values might bring up linker error messages.
          For a quick overview, see "View -> Memory Usage Gauge".

          For C32 compiler v2.01, add the
          
            -legacy-libc
            
          compiler flag (for compiler AND linker!) to the "Use Alternate Settings"
          input line and enable the checkbox.

          
          For the chipKIT-Max32, add the compiler-flag
          
            -DCHIPKITMAX32
            
          and add the special linker file
          
            chipKIT-MAX32-application-32MX795F512L-PIC32Lua.ld
            
          to the project. Otherwise, the boot area will be included in the code.
          
          ...
          
      
1.3     HEADER FILE SETTINGS

          For different setups, a few header (or source) files may require some changes.
       

1.3.1   asPIC.h

          Define your system frequency (from CONFIG BITS above):
            #define SYS_FREQ 80000000L
        
          Define your peripheral frequency (from CONFIG BITS above):
            #define PER_FREQ 40000000L

          Define your console (UART2) baudrate:
            #define CONSOLE_BAUD 115200

          
          If "CONSOLE_SWAP" is defined, the console interface is routed to UART1A instead of UART2A.
          This also is the default behaviour for the chipKIT-Max32:
          
          #if defined(CHIPKITMAX32)
            // set Chipkit-Max32 behaviour
            #define CONSOLE_SWAP
          #else
            // set behaviour on other hardware
            //	#define CONSOLE_SWAP
          #endif
            
            
            
          It is safe to keep a value of '8', no matter how many ports your PIC has (see below).
            #define PIC_MAXPORTS 8
          Just make sure they are all defined:
            PIC_TRISx[PIC_MAXPORTS]={PIC_TRISA, PIC_TRISB, ..., PIC_TRISH};

          If any register (TRISx, PORTx) is, or should not be accessible, set it to 'PIC_UNUSED'.
          E.g.:
          
            #define PIC_TRISA (unsigned long)&TRISA
            #define PIC_TRISB (unsigned long)&TRISB
            #define PIC_TRISC (unsigned long)&TRISC
            #define PIC_TRISD (unsigned long)&TRISD
            #define PIC_TRISE (unsigned long)&TRISE
            #define PIC_TRISF (unsigned long)&TRISF
            #define PIC_TRISG (unsigned long)PIC_UNUSED
            #define PIC_TRISH (unsigned long)PIC_UNUSED

            #define PIC_PORTA (unsigned long)&PORTA
            #define PIC_PORTB (unsigned long)&PORTB
            #define PIC_PORTC (unsigned long)&PORTC
            #define PIC_PORTD (unsigned long)&PORTD
            #define PIC_PORTE (unsigned long)&PORTE
            #define PIC_PORTF (unsigned long)&PORTF
            #define PIC_PORTG (unsigned long)PIC_UNUSED
            #define PIC_PORTH (unsigned long)PIC_UNUSED

            #define PIC_LATA (unsigned long)&LATA
            #define PIC_LATB (unsigned long)&LATB
            #define PIC_LATC (unsigned long)&LATC
            #define PIC_LATD (unsigned long)&LATD
            #define PIC_LATE (unsigned long)&LATE
            #define PIC_LATF (unsigned long)&LATF
            #define PIC_LATG (unsigned long)PIC_UNUSED
            #define PIC_LATH (unsigned long)PIC_UNUSED
            
            ...
            

1.3.2   asCON.h

          You may wish to (but should not) modify the size of the receive buffer (UART2 console).
          1024 provide a good setting for 80MHz system clock and a baud rate of 115k:
            #define RXBUFSIZE 1024
          
          By default, a (very) dirty backspace hack is enabled:
            #define USE_DIRTY_BACKSPACE    
          
          It requires setting an ascii (or terminal) code for the backspace key:
            #ifdef USE_DIRTY_BACKSPACE
	            #define KEY_BACKSPACE 127   // ascii code: backspace
            #endif
         
          By doing nothing else, but accepting the above "backspace hack", you are able to correct
          manually typed console messages. It does nothing else but output a '\r', then remove the
          last character and reprint the remaining characters afterwards.
          This should work on almost any terminal. If you don't like it, or it does not work for
          you, just comment out 'USE_DIRTY_BACKSPACE'.
        
          ...


1.3.2   asLUA_PIC.h

          By default, a table with "port names" is available as, e.g.:
          "pic.port.A", "pic.port.B", ...
          If you want to save (a little) amount of memory and prefer handling port A as "0",
          B as "1", etc..., you may wish to uncomment:
            #define DEFINE_PORT_NAMES

          NOTICE V0.4b:
            SD-card related stuff moved to "asCARD.h"

          ...
          

1.3.3   luaconf.h

          A lot of internal Lua settings can be made here (if you know what you are doing!).
          Read the notes in 'luaconf.h'. Otherwise, keep you hands off this file!
          
          Even if a PIC32 may have up to 128kB of RAM, Lua might (no, will) run out of memory.
          By default, the garbage collector is set to conservative values:
            #define LUAI_GCPAUSE    120
            #define LUAI_GCMUL      500

          Forget about the rest...
         
          MAXCCALLS were reduced by 50%:
            #define LUAI_MAXCCALLS  100

          MAXVARS to 50 (from 200):
            #define LUAI_MAXVARS     50

          MAXUPVALUES is now 10 (not 60):
            #define LUAI_MAXUPVALUES 10


1.3.4.  linit.c

          This file determines which of the libraries should be included.
          The default setting is:
           
            //{LUA_LOADLIBNAME, luaopen_package},
              {LUA_TABLIBNAME,  luaopen_table},
              {LUA_IOLIBNAME,   luaopen_io},
            //{LUA_OSLIBNAME,   luaopen_os},
              {LUA_STRLIBNAME,  luaopen_string},
              {LUA_MATHLIBNAME, luaopen_math},
            //{LUA_DBLIBNAME,   luaopen_debug},
              {LUA_PIC_LIBNAME, luaopen_pic},
              
          Even with 128kB RAM, Lua is always short of memory.
          If you don't need math functions, turn them of during compile time, etc...
          The above settings will start up Lua with ~18kB of RAM used.
          
          In your console, type in the sequence
          
            =collectgarbage("collect")
            =collectgarbage("count")
            
          for a memory consumption overview.
          Notice that Lua will run out of memory before it hits the 128kB barrier
          (depending on your settings, this may happen at ~100kB).
          
          ...

          
1.3.5   HardwareProfile.h

          By default, PIC32Lua uses SPI2 as the SD-card interface.
          If your operates on SPI2, swap these two lines:
          
            //#define MDD_USE_SPI_1
            #define MDD_USE_SPI_2

          It might be required to change the ports/pins too.
          Scroll down a little until you see all the definitions, following:
          
           #if defined MDD_USE_SPI_1
             ...
             ...

           #elif defined MDD_USE_SPI_2
             ...
             ...
          
          ...
    
    
1.3.6   asCARD.h

          Undefine this to omit (some) SD-card code from the binary:
            #define USE_SDCARD_CODE
            
          Undefine this if you don't want the "bootfile-feature"
            #define USE_SDCARD_BOOTFILE

          ...
    


1.9     PROGRAMMING

1.9.1   CUSTOM HARDWARE

          Just use your ICD2/3, PicKitX or whatever to blow the code in.
          

1.9.2   CHIPKIT-MAX32

          The binary PIC32Lua chipKIT-Max32 distribution comes with a (Windows) batch file that
          might help you using "avrdude.exe" (supplied with "MPide") for programming the HW.
          
          Get "MPide" from: https://github.com/chipKIT32/chipKIT32-MAX/downloads
          and install it.

          From the PIC32Lua distribution, copy the provided batch file "asProgPIC32Lua.bat"
          as well as the PIC32Lua HEX file "PIC32Lua-ChipkitMAX32.hex" to your "MPide" root
          directory (the place where "mpide.exe" resides).

          Call "asProgPI32Lua" with the "chipKIT-Max32"'s COMPORT, e.g.:
          
            asProgPI32Lua COM7

          NOTE #1:
          
            This will not damage or reprogram your chipKIT-Max32's bootloader.
            You still can use it from within "MPide" without changing anything.

            
1.9.3   Audio Development Board (ADB, PIC32 version)

          upcoming attraction...

          ...
          
          
          
2       ENHANCEMENTS/CHNAGES TO THE LUA LANGUAGE/ENGINE/BEHAVIOUR

2.1     NUMBER REPRESENTATIONS

2.1.1   BINARY NUMBERS (BASE OF TWO)

          PIC32Lua supports binary number input, which comes in handy for bit manipulations.
          You no longer need to think in hex or dec:
          A preceeding '0b' or '0B' indicates a binary number (base of 2), e.g.:
          
            0b1111     represents 15 (decimal)
            0b11111110 represents 254 (decimal)

          Note #1:
            The length of a number in a binary number format can not exceed 32 bits.
            Any larger value will be truncated (<res> = <bin> & 0xffff).

          Note #2:
            A two's complement does not exist for binary number format:
              0b11111111111111111111111111111111 (32 times a '1') means:
              4294967295 dec, and not -1 dec.
            
          Note #3:
            A negative value entered (e.g.: "-0b0111") IS a negative value (-7dec, in this case).
         
            
          Examples:

            -- print 171445
            print(0b101001110110110101)

            -- set some port pins to a high state
            pic.PortPinsHigh(pic.port.A, 0b1111000011110011)
            
            
2.1.2   IOLIB

          PIC32LUA now (almost) fully supports stdio and file access via IOLIB.
          For interactive console usage, "io.read()" (from stdin) echoes all entered characters
          back to the console. Despite this little change to the behaviour, (almost) all of
          the IOLIB functions are ready to use:
          
          Examples:
          
            io.write(<str>)               ->  write string to console
            str=io.read                   ->  read string from console
            f=io.open(<fname>, <mode>)    ->  open file
            f:write(<str>)                ->  write to file
            f:read()                      ->  read from file
            for lines in f:lines() ...    ->  read iteration
            i=f:seek()                    ->  get current file position
            f:seek("set",<pos>)           ->  set file position
            io.flush()                    ->  flush console
            f:flush()                     ->  flush file
            f:close()                     ->  close file
            io.type(<file>)               ->  file status
            ...

          NOT SUPPORTED, NON-OPERATING OR NOT TESTED:
          
            f:read("*all")                ->  read complete file (out of memory)
            io.input()                    ->  todo
            io.output()                   ->  todo
            io.tmpfile()                  ->  todo
            ...


            
3       AVAILABLE PIC RELATED LUA FUNCTIONS AND VARIABLES

          All functions are available through the 'pic' module, e.g.:
          
            pic.TimerRead()
            pic.PortState()
            ...

          To browse all available functions in 'pic', use this:
          
            for i,j in pairs(pic) do
              print(i,j)
            end

            
3.1     LIST OF AVAILABLE VARIABLES

          Notice that the usage of Lua variables is slower and consumes more memory!
          Some of them can be turned off during compile time.
          One day, a "precompiler" hack will find its way into PIC32Lua, allowing
          defines inside Lua.

          Quick overview, in no particular order:

            pic.port.X       easy to read and to remember "port variables"
            pic.TIMERTICK    contains the tick-time of the internal timer (100ns, by default)
            
            
3.1.1   Port variables

          Instead of using numbers for ports ('0' == A, '1' == B, ...), the Lua table "pic.port"
          provides a predefined set of "port names" (variables) which may be used:
          
            pic.port.A
            pic.port.B
            ...
            pic.port.H
            
          Note: Although using "names" instead of numbers looks and feels good, this consumes
          some additional memory as well as comuting power.
          Can be turned off with the compile time switch "DEFINE_PORT_NAMES" in "asLUA_PIC.h".

          
3.1.2   Timer variables

          The "tick-time", the time the internal timer is incremented, is stored in the variable:

            pic.TIMERTICK

          This can be useful for timing functions, e.g.:

            -- print a number every 500ms
            tim=pic.TimerRead()
            for i=1,10 do
              tim=tim+(0.5/pic.TIMERTICK)
              pic.TimerMatch(tim)
              print(i)
            end

          Even if PIC32Lua's internal timing changes, your application will still be able to
          maintain a '500ms' delay.

          
3.1.3   SD-card boot error

          The global variable
          
            BOOT32ERR
            
          can be used to check why the SD-card boot code from file "BOOT32.LUA"
          could not be executed.
          
            CARD_BOOT_ERR_NOCODE   1  -> SD-card code not compiled in
            CARD_BOOT_ERR_NOBOOT   2  -> boot file support excluded
            CARD_BOOT_ERR_NOMOUNT  4  -> no card or file system
            CARD_BOOT_ERR_NOFILE   8  -> no "BOOT32.LUA" file present
            CARD_BOOT_ERR_NORUN   16  -> unable to run dofile() on "BOOT32.LUA"
            CARD_BOOT_ERR_NOFCT   32  -> unable to execute "BOOT32()" (not really an error)
         
            
            
3.2     LIST OF AVAILABLE FUNCTIONS
      
          Quick overview, in no particular order:
          
            UART1Enable      enable UART1
            UART1Disable     disable UART1
            UART1Baud        set UART1 baudrate
            UART1Count       count the characters available in the buffer or check RX overflow
            UART1WriteChar   write a character to UART1
            UART1ReadChar    read a character from buffer
            UART1FlushOut    flush out buffer (blocks until all characters are sent)
            UART1FlushIn     flush in buffer (clears all received characters)
          
            PortDir          set pin direction on a port (in/out)
            PortState        set pin state on a port (high/low)
            PortLatch        set port latch (high/low)
            PortPinsHigh     set pins to high state
            PortPinsLow      set pins to low state
            PortPinsInv      invert pin state (high/low)
            
            TimerRead        read the 64 bit timer value
            TimerMatch       check if timer value passes a "match" value (BLOCKING or NONBLOCKING)
            TimerDelay       delay code execution for given time in ms or us
            
            ConsoleReadChar  read a character from the console buffer (UART2)
            ConsoleCount     count the characters available in the console buffer (UART2) or RX OF
            ConsoleFlushIn   flush reception buffer (UART2)
            
            CardDetect       detect presence of an SD-card
            CardMount        mount SD-card
            CardFindFirst    find first file or directory in current path; supports wildcards
            CardFindNext     find next file or directory in current path

            ADPins           set pins to analog input state
            ADMux            select AD converter input pins
            ADRef            select AD converter reference voltage
            ADRead           start conversion and read result
            
            
          Quick reference:
         
            <nil>           = pic.UART1Enable(<baud>)
            <nil>           = pic.UART1Disable()
            <nil>           = pic.UART1Baud(<baud>)
            <count>         = pic.UART1Count()
            <nil>           = pic.UART1WriteChar(<char>)
            <nil/character> = pic.UART1ReadChar()
            <nil>           = pic.UART1FlushOut(<char>)
            <nil>           = pic.UART1FlushIn()

            <dirval>        = pic.PortDir(<port>)
            <dirval>        = pic.PortDir(<port>, <dir>, <mask>)
            <pinstate>      = pic.PortState(<port>)
            <pinstate>      = pic.PortState(<port>, <pins>, <mask>)
            <retval>        = pic.PortLatch(<port>, <state>)
            <retval>        = pic.PortPinsHigh(<port>, <pins>)
            <retval>        = pic.PortPinsLow(<port>, <pins>)
            <retval>        = pic.PortPinsInv(<port>, <pins>)

            <timerval>      = pic.TimerRead()
            <match>         = pic.TimerMatch(<matchval>)
            <match>         = pic.TimerMatch(<matchval>, <blocking>)
            <nil>           = pic.TimerDelay(<ms>)
            <nil>           = pic.TimerDelay(<ms>)
            <nil>           = pic.TimerDelay(<ms/us>, <use_usecs>)

            <nil/character> = pic.ConsoleReadChar()
            <count>         = pic.ConsoleCount()
            <nil>           = pic.ConsoleFlushIn()

            <retval>        = pic.CardDetect()
            <retval>        = pic.CardMount()
            <name>,<size>   = pic.CardFindFirst(<name>)
            <name>,<size>   = pic.CardFindFirst(<name>, <type>)
            <name>,<size>   = pic.CardFindNext()

            <state>         = pic.ADPins()
            <state>         = pic.ADPins(<pins>)
            <retval>        = pic.ADMux(<muxa_pos>, <muxb_pos>)
            <retval>        = pic.ADMux(<muxa_pos>, <muxb_pos>, <muxa_neg>, <muxb_neg>)
            <nil>           = pic.ADRef(<vrefcfg>)
            <adval>         = pic.ADRead()
            

            
3.2.1   UART1 functions
            
3.2.1.1 UART1: enable

          <nil> = UART1Enable(<baud>)
          
          Enables UART1 with baud rate <baud>.
           
            
3.2.1.2 UART1: disable

          <nil> = UART1Disable()
          
          Disables UART1.


3.2.1.3 UART1: baud rate

          <nil> = UART1Baud(<baud>)

          Sets UART1 bitrate to <baud> baud.
          <baud> must be within 110..500000 bits/s, but can
          be an arbitrary value.

          
3.2.1.4 UART1: count characters in receive buffer

          <count> = UART1Count()
          
          Returns the number of characters available in the receive buffer.
          If the RX buffer overflowed, a '-1' will be returned.
          "UART1FlushIn()" can be called to clear the buffer and reset the overflow flag.
          
          
3.2.1.5 UART1: write character

          <nil> = UART1WriteChar(<char>)

          Writes a single character <char> to the UART1

          
3.2.1.6 UART1: read a character

          <nil/character> = UART1ReadChar()
          
          Immediately returns the next available character <character>, as an integer value, from
          the receive buffer. If the receive buffer is empty, <nil> is returned.
          
          Examples:
          
          -- prints numeric value of received characters until ESC (27dec) is detected
          repeat
            ch=pic.ConsoleReadChar()
            if ch~=nil then
              print(ch)
            end
          until ch==27
          
          
3.2.1.7 UART1: flush TX buffer

          <nil> =  UART1FlushOut(<char>)

          Flushes the UART1 output (TX).
          Blocks until are bytes are sent.

3.2.1.8 UART1: flush RX buffer

          <nil> = UART1FlushIn()
          
          Clears the complete receive buffer. Additionally, it will clear the overflow flag, if set.

          

3.2.2   Port functions
          
3.2.2.1 PORT: set or read pin direction (in/out)

          <dirval> = PortDir(<port>)
          <dirval> = PortDir(<port>, <dir>, <mask>)

          Sets the pins of port <port> to direction <dir> and returns the current
          direction state <dirval> (PORT, not LAT).
          Only bits that are set in <mask> will be changed.
          If <dir> and <mask> are omitted, this function just returns the current
          direction state without changing anything (which is equal to 'PortDir(<port>,<xxx>,0)' )

            <port == 0> PORTA -> TRISA
            <port == 1> PORTB -> TRISB
            ...
            <port == 7> PORTH -> TRISC

            <dir>       16 bit pin dir;  0->IN;        1->OUT
            <mask>      16 bit pin mask; 0->NO CHANGE; 1-> CHANGE
            
            <dirval>    16 bit pin dir;  0->IN         1->OUT
                        -1 if port not defined or access not allowed
          
          Note 1: Direction bits are inverted (1=OUT), opposed to TRISx register (1=IN).
          Note 2: Read-modify-write access!

          Examples:
          
            i=PortDir(2)
              Reads state of direction register (TRISx inverted) to i.
            
            i=PortDir(2,23234,0)
              Same as above. <mask> is 0, hence no bit is modified.
              
            i=PortDir(1,7,0x0f)
              With <mask> = 0b00001111
              and <dir >  = 0b00000111
              ========================
              the new dir = 0bxxxx0111
      
      
3.2.2.2 PORT: set or read pin state (low/high)

          <pinstate> = PortState(<port>)
          <pinstate> = PortState(<port>, <pins>, <mask>)

          Operates exactly like "PortDir()" above, except it writes to PORTx,
          not to the TRISx registers, and modifies the state (high/low) of the pins.
          
3.2.2.3 PORT: unconditionally set port latch

          <retval> = PortLatch(<port>, <state>)
          
          Immediately sets the port latch <port> to the state specified by <state>
          Returns -1 if the port is not defined or access is not allowed.
          Returns 0 in all other cases.

          Example:
          
          -- set complete PORTD to 0x0007
          pic.PortLatch(3,7)
          
          
3.2.2.4 PORT: unconditionally set pins on a port to high state

          <retval> = PortPinsHigh(<port>, <pins>)
          
          Immediately sets pins, specified by a 16 bit mask in <pins>, to a high state.
          Returns -1 if the port is not defined or access is not allowed.
          Returns 0 in all other cases.

          Example:
          
          -- set PORTD.1
          pic.PortPinsHigh(3,2)

          
3.2.2.5 PORT: unconditionally clear pins on a port

          <retval> = PortPinsLow(<port>, <pins>)
          
          Immediately sets pins, specified by a 16 bit mask in <pins>, to a low state.
          Returns -1 if the port is not defined or access is not allowed.
          Returns 0 in all other cases.

          Example:
          
          -- clear PORTD.2
          pic.PortPinsLow(3,3)


3.2.2.6 PORT: unconditionally inverts pins on a port

          <retval> = PortPinsInv(<port>, <pins>)
          
          Immediately inverts pin states, specified by a 16 bit mask in <pins>.
          Returns -1 if the port is not defined or access is not allowed.
          Returns 0 in all other cases.
          
          Example:
          
          -- toggle PORTD.0
          for i=1,10 do
            pic.PortPinsInv(3,1)
          end

          
          
3.2.3   Timer functions

          PIC32Lua uses an internal 64 bit timer that increments every 100ns.
          It will overflow every 58494 years... ;)

          
3.2.3.1 TIMER: read value

          <timerval> = TimerRead()
          
          Returns the unsigned 64 bit value of the timer.
          For conversion to time, the variable "pic.TIMERTICK" can be used.
          
          Examples:
          
            -- read the 64 bit value of the timer
            stim=pic.TimerRead()

            -- perform some calulations
            while blabla do
              ...
              ...
            end
            
            -- determine the pure tick difference
            stim=pic.TimerRead()-stim
            
            -- print out the time, in seconds, the action above took
            print(stim * pic.TIMERTICK)

            
3.2.3.2 TIMER: timer match

          <match> = TimerMatch(<matchval>)
          <match> = TimerMatch(<matchval>, <blocking>)
          
          If the second argument <blocking> is omitted, this functions blocks
          execution until the timer value exceeds the value <matchval>.
          If both arguments are given, <blocking> determines the behaviour of "TimerMatch()":
          
          <blocking == 0> immediately returns '0' if <matchval> is lesser than the timer value
                          and '1' if the timer value already exceeded the value <matchval>.
          <blocking == 1> (default)
                          waits (blocks execution) until the timer value exceeds the value
                          <matchval>.

          Examples:

            -- BLOCKING:
            tim=pic.TimerRead()
            tim=tim+(5.0/pic.TIMERTICK)
            ...
            -- blocks until 5s passed
            pic.TimerMatch(tim)
            ...

            
            -- BLOCKING (explicit notation):
            tim=pic.TimerRead()
            tim=tim+(5.0/pic.TIMERTICK)
            ...
            -- blocks until 5s passed
            pic.TimerMatch(tim,1)
            ...

            
            -- NONBLOCKING:
            tim=pic.TimerRead()
            tim=tim+(5.0/100e-9)
            while(pic.TimerMatch(tim,0)==0)
              ...
            end
                          

3.2.3.3 TIMER: timer delay
                          
          <nil> = pic.TimerDelay(<ms>)
          <nil> = pic.TimerDelay(<ms/us>, <use_usecs>)
          
          Delays code execution for the time specified by <ms> or <ms/us>.
          If only one argument is present, the timebase is 1ms.
          The second argument, if any, can set set timebase to us:
          
          <use_usecs == 0>  ->  timebase is 1ms
          <use_usecs == 1>  ->  timebase is 1us
          
          Note: For accurate and precise timings, "TimerMatch()" should be used.
          
          Examples:
            
            -- these three pause for 1s:
            pic.TimerDelay(1000)
            pic.TimerDelay(1000,0)
            pic.TimerDelay(1000000,1)

                          
                          
3.2.3   Console functions


3.2.3.1 CONSOLE: read a character

          <nil/character> = ConsoleReadChar()
          
          Immediately returns the next available character <character>, as an integer value, from
          the receive buffer. If the receive buffer is empty, <nil> is returned.
          
          Examples:
          
            -- prints numeric value of received characters until ESC (27dec) is detected
            repeat
              ch=pic.ConsoleReadChar()
              if ch~=nil then
                print(ch)
              end
            until ch==27
          
          
3.2.3.2 CONSOLE: count characters in receive buffer

          <count> = ConsoleCount()
          
          Returns the number of characters (or "bytes") in the receive buffer.
          If the RX console buffer overflowed, a '-1' will be returned.
          "ConsoleFlushIn()" can be called to clear the buffer and reset the overflow flag.
          
          Example:
          
            if pic.ConsoleCount() > 0 then
              -- read buffer, perform some actions...
            end

          
3.2.3.3 CONSOLE: flush receive buffer

          <nil> = ConsoleFlushIn()
          
          Clears the complete receive buffer and resets the overflow flag, if set.

          
          
3.2.4   SD-card functions

3.2.4.1 CARD: detect card insertion

          <retval> = CardDetect()
            
          Checks if an SD-card is inserted mechanically, nothing more:
          <retval == 0>  ->  no card inserted
          <retval == 1>  ->  card inserted


3.2.4.2 CARD: mount card

          <retval> = CardMount()
          
          Mounts the SD-card for usage. Ports are initialized, and "connection" to the
          card is established.
          Note #1: Internally, this function calls DOES NOT CALL (*1*) "CardDetect()" ANYMORE.
          Note #2: You are advised to use "CardDetect()", followed by a little delay (300-500ms),
                   prior to calling "CardMount()".
                   This avoids power-up problems and gives an extra chance that the card is
                   connected electrically ("CardDetect()" only checks the mechanical insertion,
                   via a simple switch, which does not imply that the card is electrically
                   connected).

          (*1*) changed in V0.3a

                   
          Returns:       
          <retval == 0>  ->  an error occured
          <retval == 1>  ->  card mounted

          Example, including CardDetect():
          
            -- check for insertion and mount card
            while not timeout do
              if pic.CardDetect() then
                pic.TimerDelay(400)
                return pic.CardMount()
              end
              -- calculate "timeout"
              ...
            end
            return 0
          
          
3.2.4.3 CARD: find first file or directory

          <nil>/<name>,<size> = CardFindFirst(<name>)
          <nil>/<name>,<size> = CardFindFirst(<name>, <type>)

          Given a wildcard string <name>, this functions returns the file name and size of the
          first file in the current path. <name> is returned as a string, <size> is an integer.
          If no file is present or matches the given search string, "nil" is returned.
          
          An optional second argument specifies the types of entries that should be considered:
          
          <type == 0>  ->  files only (same as only one argument given)
          <type == 1>  ->  directories only
          <type == 2>  ->  files and directories


3.2.4.4 CARD: find next file or directory

          <nil>/<name>,<size>   = CardFindNext()
          
          If "CardFindFirst()" successfully returned the name of the first entry in the current
          path, further file or directory names may be retrieved with "CardFindNext()".
          This function uses the same search mask (the wildcard), as specified by "CardFindFirst()".
          If no corresponding file or directory was found, "nil" is returned, otherwise two
          return arguments contain the filename, as a string, and the size of the file in bytes.
          
          Example:

            -- print name and size of all files and directories
            nam,size=pic.CardFindFirst("*.*",2)
            if nam ~= nil then
              while 1 do
                print(nam,size)
                nam,size=pic.CardFindNext()
                if nam==nil then
                  break
                end
              end -- while
            end -- if nam not nil

            
            
3.2.5   AD-CONVERTER

3.2.5.1 AD: Set pins to analog input state

          <state> = ADPins()
          <state> = ADPins(<pins>)
          
          Set or query analog input state. If no argumant is given, this function returns
          the current state of the AD converter pins.
          If the function is called with the <pins> argument, the corresponding pins,
          specified by the 16 bit <pins> bitmask, are set to an analog (bit == '1')
          or a digital pin state (bit == '0').
          
          Note: Additionally, every pin that should be operated in analog mode, must
                have its direction set to input ("Port.Dir(pic.port.B,<anamask>,<anamask>)").

          <pins>   =>  16 bit analog pin mask (0 = digital pin; 1 = analog pin)
          
          Returns:
          <state>  =>  current state of the analog pins
          
          Examples:
          
            -- set AN1-4 to analog state
            pic.PortDir(pic.port.B,0,0b11110)
            pic.ADPins(0b11110)

            -- query pin state of AN0-31
            apins=ADPins()


3.2.5.2 AD: Set multiplexer A and B input pins

          <retval> = pic.ADMux(<muxa_pos>, <muxb_pos>)
          <retval> = pic.ADMux(<muxa_pos>, <muxb_pos>, <muxa_neg>, <muxb_neg>)
          
          Select input pins for AD converter multiplexer A and B.
          If <muxa_neg> and <muxb_neg> are omitted, their values default to "0",
          which select "VR-" as the reference for the negative inputs.
          
          NOTE: Currently, only MUX A is used (B for future upgrade)!
                
          
          MUX A positive input:
            <muxa_pos ==  0>  =>  AN0
            <muxa_pos ==  1>  =>  AN1
            ...
            <muxa_pos == 15>  =>  AN15

          MUX B positive input:
            <muxb_pos ==  0>  =>  AN0
            <muxb_pos ==  1>  =>  AN1
            ...
            <muxb_pos == 15>  =>  AN15
            
          MUX A negative input:
            <muxa_neg ==  0>  =>  VR-
            <muxa_neg ==  1>  =>  AN1
            
          MUX B negative input:
            <muxb_neg ==  0>  =>  VR-
            <muxb_neg ==  1>  =>  AN1
            
          Returns:
          <retval ==  0>  =>  no error
          <retval == -1>  =>  invalid <muxa_pos> or <muxa_neg>

            
3.2.5.3 AD: Select reference voltage

          <nil> = pic.ADRef(<vrefcfg>)
          
          Depending on <vrefcfg>, the following voltage references can be selected.
          On start up, "AVdd" and "AVss" are selected.
          
            <vrefcfg == 0b000>  =>  AVdd    AVss
            <vrefcfg == 0b001>  =>  VRef+   AVss
            <vrefcfg == 0b010>  =>  AVdd    VRef-
            <vrefcfg == 0b011>  =>  VRef+   VRef-
            <vrefcfg == 0b1xx>  =>  AVdd    AVss

            
3.2.5.4 AD: Start conversion and read result
          
          <adval> = pic.ADRead()
          
          Calling "ADRead()" immediately returns the 10 bit conversion result of
          the AD converter.


          
          
7       TODO-LIST

7.1     INTERFACES

7.1.1   UART
      
          - more than one user-UART (inside PIC32Lua)
          - freely selectable UART for console and user-UARTs

          
7.1.2   I2C

          - not implemented yet

          
7.1.3   SPI

          - not implemented yet (only as CD-card interface)
 
 
 
8       COPYRIGHT/LEFT

          See distribution...
          
          
            
9       CHANGES

9.1     V0.1a:
        VARIABLES:
          - NEW: port "names" ("pic.port.A", "pic.port.B", ...)
        PORT FUNCTIONS:
          - NEW: PortLatch(<port>, <state>)
        OTHER:
          - some cleanups in asIO.c (stdio, stderr, io.write, ...)

          
9.2     V0.1b:
        SYSTEM:
          - NEW: binary number representation with, e.g.: '0b001110'
        VARIABLES:
          - NEW: timer tick-time variable (100ns, by default) in "pic.TIMERTICK"

          
9.3     V0.2a:
        TIMER FUNCTIONS:
          - NEW: simple delay function in msec and usec; TimerDelay(<usec>, [<uflag>])
        SD-CARD FUNCTIONS:
          - NEW: check card insertion: CardDetect()
          - NEW: mount card: CardMount()
          - NEW: find first file/dir: FindFirst(<name>, <type>)
          - NEW: find next file/dir: FindNext()
          - NEW: almost complete (but yet not fully tested) IOLIB sd-card integration;
                 reading, writing, seeking, ..., can all be done through Lua's iolib
        IOLIB (stdio):
          - NEW: interface to IOLIB's console interface. E.g.: io.write, io.read, ...

          
9.4     V0.2b:
        OTHER:
          - NEW: configuration bits now in code (by popular demand ;-)
        PORT FUNCTIONS:
          - CORR: PortDir() now returns the correct values (~TRISx)
        AD CONVERTER:
          - NEW: select analog input pins; ADPins(<state>)
          - NEW: select multiplexer input pins; ADMux(<muxa_pos>,<muxb_pos>,<muxa_neg>,<muxb_neg>)
          - NEW: select Vref; ADRef(<vrefcfg>)
          - NEW: start conversion and read result; <adval>=ADRead()

          
9.5     V0.2c:
        OTHER:
          - NEW: limited support for "dofile()" and "loadfile()" (no real error checks)
          - FIX: wrong buffer index in asUART1.c (UART1_RXBUFSIZE replaces RXBUFSIZE)
          - FIX: stupid buffer overrun error in asUART1.c and asCON.c

          
9.6     V0.3a:
        OTHER:
          - FIX: support for C32 v2.01
          - CHG: CardMount() does not check for card insertion anymore
          - CHG: minor code cleanups (replaced default 'stderr' output by 'stdin', ...)

          
9.7     V0.4a:
          - NEW: support for chipKIT-Max32
          - NEW: console and serial port UARTs can now be swapped
          - FIX: minor cleanups (still a LOT to do ;-)

          
9.8     V0.4b:
          - NEW: SD-card boot file support; boots function "BOOT32()" in file "BOOT32.LUA"
          - NEW: added SPI pin documentation
          - FIX: corrected pins for SPI1
                 SD-card now works on both SPI interfaces
9.9     V0.4c:
          - FIX: 64-bit timer bug (lock-up after 430s)
								 


Examples/Tests

with V0.1a



-- simple port pin toggle
function pt()
  local i

  -- PORTB 0 out
  pic.PortDir(1,1,1)

  for i=1,1000 do
    pic.PortState(1,1,1)
    pic.PortState(1,0,1)
  end
end


-- more port pin stuff
function mp()
  local i,j

  -- PORTD 0-3 out
  pic.PortDir(3,7,7)

  for i=1,100 do
    pic.PinsHigh(3,7)
    pic.PinsLow(3,7)

    for j=1,10 do
      pic.PinsInv(3,7)
    end

  end
end


-- read timer
-- ESC quits
function rt()
  local i

  while(1) do
    print(pic.TimerRead())

    if pic.ConsoleReadChar()==27 then
      break
    end

  end

end


-- timer match (BLOCKING)
-- ESC quits
function tm()
  local stim
  local tim,timh
  local i

  tim=pic.TimerRead()
  while(1) do
    -- 500ms
    tim=tim+(0.5/100e-9)
    print(tim)
    pic.TimerMatch(tim)

    if pic.ConsoleReadChar()==27 then
      break
    end

  end
end


-- timer match 2 (NONBLOCKING)
-- ESC quits
function tm2()
  local stim
  local tim,timh
  local i

  tim=pic.TimerRead()
  while(1) do
    -- 500ms
    tim=tim+(0.5/100e-9)
    print(tim)

    while pic.TimerMatch(tim,0)==0 do
      -- do something, in here...
    end

    if pic.ConsoleReadChar()==27 then
      break
    end

  end
end


-- timer match 3 (NONBLOCKING)
-- ESC quits
function tm3()
  local stim
  local tim,timh
  local i

  tim=pic.TimerRead()
  while(1) do
    -- 500ms
    tim=tim+(0.5/100e-9)
    print(tim)

    i=0
    while(1) do
      i=i+1
      if pic.TimerMatch(tim,0)==1 then
        break
      end
    end

    print("i: "..i)

    if pic.ConsoleReadChar()==27 then
      break
    end

  end
end


-- console read
-- ESC quits
function cr()
  local ch

  repeat
    ch=pic.ConsoleReadChar()

    if ch~=nil then
      print(ch)
    end

  until ch==27

end


-- console count
-- quits after receiving 10 characters
function cc()
  local i

  repeat
    i=pic.ConsoleCount()
    print(i)
  until i>10

  pic.ConsoleFlushIn()

end


-- UART1 loopback
-- connect UART1 TX and RX together
function ul()
  local i

  pic.UART1Enable(115200)

  print("filling RX buffer:")
  for i=65,65+9 do
    print("  sending "..string.char(i))
    pic.UART1WriteChar(i)
  end

  print("check reception:")
  print("buffer contains:"..pic.UART1Count().." characters")
  while(1) do
    i=pic.UART1ReadChar()
    if i ~= nil then
      print("  received "..string.char(i))
    else
      break
    end
  end

  pic.UART1Disable()

end


-- UART1 overflow
-- connect UART1 TX and RX together
function uo()
  local i

  pic.UART1Enable(115200)

  print("filling RX buffer:")
  for i=1,260 do
    -- reports -1 on overflow
    pic.UART1WriteChar(i)
    print("buffer: "..pic.UART1Count())
  end

  print("flushing buffer...")
  pic.UART1FlushIn()
  print("buffer: "..pic.UART1Count())

  pic.UART1Disable()

end


with V0.1b



-- binary number notation, timer, console
-- toggles PORTD 0-2; leaves on ESC from console
-- Can be used with the LEDs on a PIC32 starter kit.
function bn()
  local LEDTAB={0b111, 0b000, 0b001, 0b010, 0b100, 0b010, 0b001, 0b000}
  local i
  local stim

  -- set PORTD 0-2 to low
  pic.PortPinsLow(pic.port.D,0b111)
  -- set PORTD 0-2 to output
  pic.PortDir(pic.port.D,0b111,0b111)

  -- read timer value
  stim=pic.TimerRead()

  while 1 do
    for i=1,table.getn(LEDTAB) do
      stim=stim+0.1/pic.TIMERTICK
      pic.PortState(pic.port.D,LEDTAB[i],0b111)
      pic.TimerMatch(stim)
      -- quit on ESC from console
      if pic.ConsoleReadChar()==27 then
        return
      end

      print(collectgarbage("count"))

    end -- for
  end -- while

end


-- end of memory test
-- will fill up the memory until the interpreter stops
function em()
  -- stop the garbage collector
  collectgarbage("stop")
  while(1) do
    print(collectgarbage("count"))
  end
end


-- LED control with upvalues (aka.: external local variables)
-- just a little demonstration of Lua's features
-- Do not call this directly.
-- See "golc()" below...
function lc(port,pin)
  return  function(state)
            if state==0 then
              uvState=0
              pic.PortPinsLow(port,pin)
            else
              uvState=1
              pic.PortPinsHigh(port,pin)
            end
          end
end


-- using upvalues
function golc()
  local stim

  -- clear lower 3 bits of PORTD
  pic.PortPinsLow(pic.port.D,0b111)
  -- set lower 3 bits of PORTD to output
  pic.PortDir(pic.port.D,0b111,0b111)

  -- create 3 LED closures
  led1=lc(pic.port.D,0b001)
  led2=lc(pic.port.D,0b010)
  led3=lc(pic.port.D,0b100)

  -- read timer value
  stim=pic.TimerRead()

  while 1 do
    stim=stim+0.1/pic.TIMERTICK

    -- use our new closures...
    led1(math.random(2)-1)
    led2(math.random(2)-1)
    led3(math.random(2)-1)

    pic.TimerMatch(stim)

    -- quit on ESC from console
    if pic.ConsoleReadChar()==27 then
      return
    end
  end

end


with V0.2a



-- simple delay function
-- easier to use than TimerMatch() (but not that versatile)
function dt()
  local i

  for i=20,0,-1 do
    print(i)
    pic.TimerDelay(i*50)
  end

end


-- detect and mount SD-card
-- exits on ESC from console
function dm()

  print("wating for card insertion...")
  while pic.CardDetect() == 0 do
    io.write(".")

    if pic.ConsoleReadChar() == 27 then
      print("\r\ngiving up...")
      return 0
    end
  end

  io.flush()
  io.write("\ncard found, about to mount: ")
  io.flush()

  pic.TimerDelay(500)

  if pic.CardMount() == 0 then
    print("ERROR")
    return
  end

  print("OK")
  return 1
end


-- mount card, if available
-- list all files, directories and sizes of the root dir entries
function lf()
  local nam, size

  if pic.CardMount() == 0 then
    print("ERROR MOUNTING CARD")
    return 0
  end

  print()
  nam,size=pic.CardFindFirst("*.*",2)
  if nam ~= nil then
    while 1 do
      print(nam,size)
      nam,size=pic.CardFindNext()
      if nam==nil then
        break
      end
    end
  else
    print("empty")
  end

end


-- open a file by name and display its contents
-- if no file name is specified, the first file found is used
-- make sure this is a text file ;-)
-- Note: It might look strange depending on your terminal
-- settings (newline, linefeed, ...)
function of(fname)
  local fin

  if pic.CardMount() == 0 then
    print("ERROR MOUNTING CARD")
    return 0
  end

  if fname==nil then
    fname=pic.CardFindFirst("*.*")
    if fname==nil then
      print("NO FILES FOUND")
      return 0
    end
  end

  print("OPENING "..fname)

  fin=io.open(fname,"r")
  if fin==nil then
    print("ERROR OPENING FILE")
    return 0
  end

  print("---")
  for lines in fin:lines() do
    print(lines)
  end
  print("---")

  fin:close()
  print("FILE CLOSED")

end


-- enter a file name, create that file on SD-card and
-- enter some text, empty line quits!
-- Notes (READ EM!):
--  - Do not use delete, backspace or other "special" characters.
--  - use a "8+3" filename
--  - This is just a demonstration!
function cf()
  local tmp
  local fout

  if pic.CardMount() == 0 then
    print("ERROR MOUNTING CARD")
    return 0
  end

  io.write("ENTER FILENAME: ")
  tmp=io.read()

  if string.len(tmp)==0 then
    print("QUIT...")
    return 0
  end

  fout=io.open(tmp,"w")

  if fout==nil then
    print("UNABLE TO OPEN FILE")
    return 0
  end

  print("ENTER SOME TEXT, QUIT WITH AN EMPTY LINE")

  while 1 do
    tmp=io.read()
    print()
    if string.len(tmp)==0 then
      break
    end
    fout:write("\r\n")
    fout:write(tmp)
  end

  fout:flush()
  fout:close()

  print("\r\nNOW STICK THAT CARD INTO YOUR DIRTY")
  print("PC CARD-READER AND LOOK WHAT YOU HAVE DONE...")

  return 1
end


with V0.2b



-- AD converter; read values from AN0 (B0)
-- Use precise 200ms timing via TimerMatch()
-- ESC from console quits
function ad()
  local i
  local stim

  -- pin to input
  pic.PortDir(pic.port.B,0,0b1)
  -- pin to analog
  pic.ADPins(0b1)
  -- select Vdd and Vss as reference
  pic.ADRef(0b000)
  -- select AN0 as input for MUX A+
  -- 2nd '0' (MUX B+) has no effect
  pic.ADMux(0,0)

  stim=pic.TimerRead()
  while 1 do
    stim=stim+0.2/pic.TIMERTICK
    pic.TimerMatch(stim)
    i=pic.ADRead()

    -- separate print() to eliminate jitter
    -- (not really required ;-)
    print(i)

    if pic.ConsoleReadChar() == 27 then
      break
    end
  end -- while
end


-- "Multi AD" on AN0-3
-- Write RAW values to SD-card.
-- Precise 250ms timing via TimerMatch()
-- ESC from console quits
-- All in one function; no Lua tricks; only a demonstration...
function mad()
  local ad={}
  local i
  local stim
  local fout

  if pic.CardMount() == 0 then
    print("unable to mount card")
    return -1
  end

  fout=io.open("mess.txt","w")

  if fout == nil then
    print("unable to open file")
    return -2
  end

  -- pins to input
  pic.PortDir(pic.port.B,0,0b1)
  -- pins to analog
  pic.ADPins(0b1)
  -- select Vdd and Vss as reference
  pic.ADRef(0b000)

  stim=pic.TimerRead()
  while 1 do
    local stmp

  -- wait until time matches n*250ms
    stim=stim+0.25/pic.TIMERTICK
    pic.TimerMatch(stim)

    -- read all four channels
    -- from 1 to avoid hashed tables (index 0)
    for i=1,4 do
      pic.ADMux(i-1,0)
      ad[i]=pic.ADRead()
    end

    -- create output string
    stmp=""
    for i=1,4 do
      stmp=stmp..string.format("%4d ",ad[i])
    end
    stmp=stmp.."\r\n"

    -- write to SD-card
    fout:write(stmp)

    -- write to console
    io.write(stmp)

    -- quit?
    if pic.ConsoleReadChar() == 27 then
      break
    end

  end -- while

  fout:close()

  return 0

end


with V0.4a



-- Just a stupid "SOS" LED toggle for the
-- chipKIT-Max32.
function cksos()
  local i,n
  local stim

  pic.PortDir(pic.port.A,0b1000,0b1000)
  pic.PortState(pic.port.A,0,0b1000)

  n = 0.15
  stim=pic.TimerRead()

  while(1) do

    for i=1,6 do

      stim=stim+n/pic.TIMERTICK
      pic.TimerMatch(stim)

      pic.PortPinsInv(pic.port.A,0b1000)

    end

    if n==0.15 then
      n=0.3
    else
      n=0.15
    end

    if pic.ConsoleReadChar() == 27 then
      break
    end

  end
end


	DUMMY


Download

PIC32Lua:

DOWNLOAD: PIC32Lua_V04c.zip V0.4c BINARY (20/03/2013)(d/m/y)
DOWNLOAD: PIC32Lua_V04c_chipKIT-Max32_BINARY.zip V0.4c BINARY for chipKIT (20/03/2013)(d/m/y)
DOWNLOAD: https://github.com/FMMT666/PIC32Lua source code

As usual, no docs, no warranty, no support.
If this deletes your harddisk, heats up your beer or goes out with your girlfriend.
Bad luck!




ASkr 07/2010 initial public release
ASkr 08/2010 V0.1a, V0.1b, V0.2a, V0.2b
ASkr 03/2011 V0.2c
ASkr 06/2011 working on V0.3a, an experimental release for C32 v1.12a+
ASkr 09/2011 V0.3a, for C32 V2.01
ASkr 11/2011 V0.4a, with chipKIT-Max32 support + binary
ASkr 01/2012 V0.4b, improved SD-card support incl. boot file option
ASkr 12/2012 copied source code to Github
ASkr 03/2013 v0.4c, removed a timer lock-up bug