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
...
Lua? What?
Hardware
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
Download
PIC32Lua:
As usual, no docs, no warranty, no support.
|