Lua Interpreter
As stated previously, the firmware features a Lua 5.4 interpreter.
The configuration has been hammered down more or less to be able to run under Zephyr and the Teensy4.0.
Here's the key things to make it happen:
- #define LUA_32BITS 1 in luaconf.h is an obvious one
- Zephyr doesn't ship with whole POSIX compatibility, so a few functions were copied from civetweb
- The "KB" macro in lvm.c had to be redefined to "_KB" so that it doesn't clash with the existing Zephyr one
There are some things that I forgot to document, but if you happen to want to embed Lua into the Teensy4.0 in PIO's Zephyr than just drop me a message and I'll send over the code.
But Lua is only as exciting as the functions it comes with, here's a list of them:
- bload: Load Lua bytecode
- run: Run loaded Lua bytecode
- poke: Poke around at any address, supports 8, 16 and 32 bit words
- peek: Peek around at any address, complimentary to poke
- rshift/lshift: Do a right/left bitshift on a value
- band/bor/bneg: Bitwise and/or and negation
- memused: Print current amount of memory used for Lua
- memfree: Print remaining memory available to Lua
- printlog: Prints the Zephyr log
- pp: It's the pretty print function
- hex: Convert a numeric to a hexadecimal string
- xio_set/xio_get: Set and get an IO on the cartridge
- xio_peek/xio_poke: Set and get all 32 available IOs at once
- Currently, only I2C peripheral function exist, but this will be extended to SPI, UART, CAN and eventually ADCs
Bytecode currently is compiled using an emulator on a developer machine, which can later be incorporated into a cartridges I2C EEPROM to be loaded on plugging in.
SPI Protocol
Meanwhile, the SPI communication between the DevTerm and the DTC Module is coming along well. Slave configuration was really easy by using the MCUXpresso library. As with all peripherals that are used during runtime in Zephyr on the Teensy4.0, the pinmux has to be adjusted before usage. On the topic of pinmux, I found out that on my version, the configuration for LPSPI3 seems incorrect. It is easily fixable tough.
The SPI protocol utilized is simple, featuring a start byte and end CRC8 for both validation of the frame and detection of the frame end. There are two types of frames utilized: Basic and Data.
Basic Frames are fixed width and is the go-to for exchanging. Basic frames contain a command and argument from the master, and a status code and return value from the slave. Then, there's Data Frames which are utilized currently by one command: the buffer exchange. By issuing a buffer exchange command, a local all-purpose buffer can be read and written to. This all purpose data buffer is where the the data for peripheral commands such as for SPI and I2C is. A basic frame beforehand will contain the neccesary length information for a following data frame.
An example exchage is illustrated in the following diagram, outlining the neccesary transactions for one I2C read of up to 128 bytes.
Big thanks to @yatli for all the valuable input on the ClockworkPi forums regarding the protocol among other things.
Linux Driver
Currently, a cheap python script is used to test the protocol during development, but a fully fledged Linux driver is in the works that exposes the IO as GPIO, as well as the I2C buses. I currently have no idea to implement an SPI or CAN driver on Linux, but it is definitely on the todo-list.
A wiring-pi like Python library would be nice to have on top, but I'm unsure if it will be necessary at all.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.