Dev -> Master Release 10
This commit is contained in:
Marcel Stör 2018-09-15 21:46:13 +02:00 committed by GitHub
commit b41667b837
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
235 changed files with 6211 additions and 115990 deletions

34
.gdbinit Normal file
View File

@ -0,0 +1,34 @@
#
# This is very much a work in progress to show how we can use macros to make the
# GDB interface a lot more useable. For example the next / step commands only
# work if the stepper doesn't leave the current scope. Beyond that you have a
# single hardware breakpoint which can be used as an hb or a wa. You have to
# remember to delete the previous one, so the br macro does this for you.
#
file app/.output/eagle/debug/image/eagle.app.v6.out
#set remotedebug 1
set remotelogfile gdb_rsp_logfile.txt
set serial baud 115200
set remote hardware-breakpoint-limit 1
set remote hardware-watchpoint-limit 1
#set debug xtensa 4
target remote /dev/ttyUSB0
set confirm off
set print null-stop
define br
d
hb $arg0
end
define upto
d
hb $arg0
c
end
set pagination off
set history filename ~/.gdb_history
set history save on
set history size 1000

182
.gdbinitlua Normal file
View File

@ -0,0 +1,182 @@
set pagination off
set print null-stop
define prTS
set $o = &(((TString *)($arg0))->tsv)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "String: hash = 0x%08x, len = %u : %s\n", $o->hash, $o->len, (char *)(&$o[1])
end
define prTnodes
set $o = (Table *)($arg0)
set $n = 1<<($o->lsizenode)
set $i = 0
while $i < $n
set $nd = ($o->node) + $i
if $nd->i_key.nk.tt && $nd->i_val.tt
if $nd->i_key.nk.tt == 6
printf "%4u: %s %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt
else
printf "%4u: %2i %2i\n", $i, $nd->i_key.nk.tt , $nd->i_val.tt
end
end
set $i = $i +1
end
end
define prTV
if $arg0
set $type = ($arg0).tt
set $val = ($arg0).value
if $type == 0
# NIL
printf "Nil\n"
end
if $type == 1
# Boolean
printf "Boolean: %u\n", $val.n
end
if $type == 2
# ROTable
printf "ROTable: %p\n", $val.p
end
if $type == 3
# Light Function
printf "Light Func: %p\n", $val.p
end
if $type == 4
# Light User Data
printf "Light Udata: %p\n", $val.p
end
if $type == 5
# Number
printf "Number: %u\n", $val.n
end
if $type == 6
prTS $arg0
end
if $type == 7
# Table
set $o = &($val->gc.h)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
printf "Nodes: %4i %p\n", 2<<($o->lsizenode), $o->node
printf "Arry: %4i %p\n", $o->sizearray, $o->array
end
if $type == 8
# Function
set $o = &($val->gc.cl.c)
printf "Common header: next = %p, marked = 0x%01x\n", $o->next, $o->marked
if $o->isC == 0
set $o = &($val->gc.cl.l)
printf "LClosure: nupvalues = %u, gclist = %p, env = %p, p = %p\n", \
$o->nupvalues, $o->gclist, $o->env, $o->p
else
printf "CClosure: nupvalues = %u, gclist = %p, env = %p, f = %p\np", \
$o->nupvalues, $o->gclist, $o->env, $o->f
end
end
if $type == 9
# UserData
end
if $type == 10
# Thread
end
end
end
define prT
print *(Table*)($arg0)
end
define prL
if L > 0
printf " stack: %u\n", L->top-L->base
printf " hooking: %u, %u, %u, %u, %p\n", L->hookmask, L->allowhook, L->basehookcount, L->hookcount, L->hook
end
end
define dumpstrt
set $st = $arg0
set $i = 0
while $i< $st->size
set $o = &(((TString *)($st->hash[$i]))->tsv)
while $o
if $o->next
printf "Slot: %5i %p %p %08x %02x %4u", \
$i, $o, $o->next, $o->hash, $o->marked, $o->len
else
printf "Slot: %5i %p %08x %02x %4u", \
$i, $o, $o->hash, $o->marked, $o->len
end
if $o->marked & 0x80
printf "* %s\n", *(char **)($o+1)
else
printf " %s\n", (char *)($o+1)
end
set $o = &(((TString *)($o->next))->tsv)
end
set $i = $i + 1
end
end
define dumpRAMstrt
dumpstrt &(L->l_G->strt)
end
define dumpROstrt
dumpstrt &(L->l_G->ROstrt)
end
define graylist
set $n = $arg0
while $n
printf "%p %2u %02X\n",$n, $n->gch.tt, $n->gch.marked
set $n=$n->gch.next
end
end
define prPC
printf "Excuting instruction %i: %08x\n", (pc - cl->p->code)+1-1, i
end
define where
set $f=cl->p
printf "<%s:%u,%u>, opcode %u\n",\
(char *)$f->source+17, $f->linedefined, $f->lastlinedefined, pc - $f->code
end
define callinfo
printf "%p: ", L->ci
print *L->ci
end
define luastack
set $i = 0
set $ci = L->base_ci
set $s = L->stack
set $last = L->stack_last - L->stack
printf "stack = %p, last: %i, size: %i, " , $s, $last, L->stacksize
if $last+6==L->stacksize
printf "(OK)\n"
else
printf "(MISMATCH)\n"
end
printf " Ndx top base func\n"
while $ci <= L->ci
printf "%3u %6i %6i %6i\n", $i++, $ci->top-$s, $ci->base-$s, ($ci++)->func-$s
end
end
define stacklen
printf "%i top: %p, base: %p\n", \
L->ci->top - L->base, L->ci->top, L->base
end
define stackcheck
set $ci = L->ci
printf "Used: %i, Headroom: %i, Total: %i\n", \
L->top-$ci->base-1, $ci->top-L->top+1, $ci->top-$ci->base
end

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
sdk/
cache/
.ccache/
local/
luac.cross
user_config.h
server-ca.crt

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "app/u8g2lib/u8g2"]
path = app/u8g2lib/u8g2
url = https://github.com/olikraus/U8g2_Arduino.git

View File

@ -5,21 +5,13 @@ addons:
packages:
- python-serial
- srecord
- lua5.1
cache:
- pip
- directories:
- cache
before_install:
- pip install --user hererocks esptool
- hererocks env --lua 5.1 -rlatest
- source env/bin/activate
- luarocks install luafilesystem
install:
- tar -Jxvf tools/esp-open-sdk.tar.xz
- export PATH=$PATH:$PWD/esp-open-sdk/xtensa-lx106-elf/bin
script:
- lua tools/cross-lua.lua || exit 1
- export BUILD_DATE=$(date +%Y%m%d)
- make EXTRA_CCFLAGS="-DBUILD_DATE='\"'$BUILD_DATE'\"'" all
- cd bin/

View File

@ -63,7 +63,9 @@ Avoid intermediate merge commits. [Rebase](https://www.atlassian.com/git/tutoria
1. `git push`
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) (PR) on GitHub.
This is just one way of doing things. If you're proficient in Git matters you're free to choose your own. If you want to read more then the [GitHub chapter in the Git book](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project#The-GitHub-Flow) is a way to start. [GitHub's own documentation](https://help.github.com/categories/collaborating/) contains a wealth of information as well.
This is just one way of doing things. If you're proficient in Git matters you're free to choose your own. If you want to read more then the [GitHub chapter in the Git book](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project#The-GitHub-Flow) is a way to start. [GitHub's own documentation](https://help.github.com/categories/collaborating-with-issues-and-pull-requests/) contains a wealth of information as well.
As a Windows or Mac user you could also resort to [GitHub Desktop](https://desktop.github.com/). It's a mature GUI application that supports most of the tasks outlined above.
### Keeping your fork in sync
You need to sync your fork with the NodeMCU upstream repository from time to time, latest before you rebase (see flow above).

View File

@ -3,20 +3,20 @@
.NOTPARALLEL:
# SDK base version, as released by Espressif
SDK_BASE_VER:=2.2.0
SDK_BASE_VER:=2.2.1
# no patch: SDK_VER equals SDK_BASE_VER and sdk dir depends on sdk_extracted
#SDK_VER:=$(SDK_BASE_VER)
#SDK_DIR_DEPENDS:=sdk_extracted
SDK_VER:=$(SDK_BASE_VER)
SDK_DIR_DEPENDS:=sdk_extracted
# with patch: SDK_VER differs from SDK_BASE_VER and sdk dir depends on sdk_patched
SDK_PATCH_VER:=f8f27ce
SDK_VER:=$(SDK_BASE_VER)-$(SDK_PATCH_VER)
SDK_DIR_DEPENDS:=sdk_patched
#SDK_PATCH_VER:=f8f27ce
#SDK_VER:=$(SDK_BASE_VER)-$(SDK_PATCH_VER)
#SDK_DIR_DEPENDS:=sdk_patched
SDK_FILE_VER:=$(SDK_BASE_VER)
SDK_FILE_SHA1:=8b63f1066d3560ff77f119e8ba30a9c39e7baaad
SDK_PATCH_SHA1:=0bc21ec77b08488f04d3e1c9d161b711d07201a8
SDK_FILE_SHA1:=48f2242d5895823709f222bf0fffce9d525996c8
# SDK_PATCH_SHA1:=0bc21ec77b08488f04d3e1c9d161b711d07201a8
# Ensure we search "our" SDK before the tool-chain's SDK (if any)
TOP_DIR:=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
SDK_REL_DIR=sdk/esp_iot_sdk_v$(SDK_VER)
@ -28,7 +28,7 @@ ifdef DEBUG
CCFLAGS += -ggdb -O0
LDFLAGS += -ggdb
else
CCFLAGS += -Os
CCFLAGS += -O2
endif
#############################################################
@ -227,8 +227,8 @@ $(TOP_DIR)/sdk/.patched-$(SDK_VER): $(TOP_DIR)/cache/$(SDK_PATCH_VER).patch
$(TOP_DIR)/sdk/.pruned-$(SDK_VER):
rm -f $(SDK_DIR)/lib/liblwip.a $(SDK_DIR)/lib/libssl.a $(SDK_DIR)/lib/libmbedtls.a
ar d $(SDK_DIR)/lib/libmain.a time.o
ar d $(SDK_DIR)/lib/libc.a lib_a-time.o
$(AR) d $(SDK_DIR)/lib/libmain.a time.o
$(AR) d $(SDK_DIR)/lib/libc.a lib_a-time.o
touch $@
$(TOP_DIR)/cache/v$(SDK_FILE_VER).zip:
@ -308,11 +308,11 @@ endif
$(OBJODIR)/%.o: %.c
@mkdir -p $(OBJODIR);
@mkdir -p $(dir $@);
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<
$(OBJODIR)/%.d: %.c
@mkdir -p $(OBJODIR);
@mkdir -p $(dir $@);
@echo DEPEND: $(CC) -M $(CFLAGS) $<
@set -e; rm -f $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
@ -331,22 +331,22 @@ $(OBJODIR)/%.d: %.cpp
rm -f $@.$$$$
$(OBJODIR)/%.o: %.s
@mkdir -p $(OBJODIR);
@mkdir -p $(dir $@);
$(CC) $(CFLAGS) -o $@ -c $<
$(OBJODIR)/%.d: %.s
@mkdir -p $(OBJODIR); \
@mkdir -p $(dir $@); \
set -e; rm -f $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
$(OBJODIR)/%.o: %.S
@mkdir -p $(OBJODIR);
@mkdir -p $(dir $@);
$(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $<
$(OBJODIR)/%.d: %.S
@mkdir -p $(OBJODIR); \
@mkdir -p $(dir $@); \
set -e; rm -f $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \

View File

@ -1,4 +1,4 @@
# **NodeMCU 2.2.0** #
# **NodeMCU 2.2.1** #
[![Join the chat at https://gitter.im/nodemcu/nodemcu-firmware](https://img.shields.io/gitter/room/badges/shields.svg)](https://gitter.im/nodemcu/nodemcu-firmware?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/nodemcu/nodemcu-firmware.svg)](https://travis-ci.org/nodemcu/nodemcu-firmware)
@ -7,19 +7,22 @@
### A Lua based firmware for ESP8266 WiFi SOC
NodeMCU is an [eLua](http://www.eluaproject.net/) based firmware for the [ESP8266 WiFi SOC from Espressif](http://espressif.com/en/products/esp8266/). The firmware is based on the [Espressif NON-OS SDK 2.2.0](https://github.com/espressif/ESP8266_NONOS_SDK/releases/tag/v2.2.0) and uses a file system based on [spiffs](https://github.com/pellepl/spiffs). The code repository consists of 98.1% C-code that glues the thin Lua veneer to the SDK.
NodeMCU is an open source [Lua](https://www.lua.org/) based firmware for the [ESP8266 WiFi SOC from Espressif](http://espressif.com/en/products/esp8266/) and uses an on-module flash-based [SPIFFS](https://github.com/pellepl/spiffs) file system. NodeMCU is implemented in C and is layered on the [Espressif NON-OS SDK](https://github.com/espressif/ESP8266_NONOS_SDK).
The NodeMCU *firmware* is a companion project to the popular [NodeMCU dev kits](https://github.com/nodemcu/nodemcu-devkit-v1.0), ready-made open source development boards with ESP8266-12E chips.
The firmware was initially developed as is a companion project to the popular ESP8266-based [NodeMCU development modules]((https://github.com/nodemcu/nodemcu-devkit-v1.0)), but the project is now community-supported, and the firmware can now be run on _any_ ESP module.
# Summary
- Easy to program wireless node and/or access point
- Based on Lua 5.1.4 (without *debug, os* modules)
- Based on Lua 5.1.4 (without `debug` & `os` modules)
- Asynchronous event-driven programming model
- more than 65 built-in modules
- more than **65 built-in modules**
- Firmware available with or without floating point support (integer-only uses less memory)
- Up-to-date documentation at [https://nodemcu.readthedocs.io](https://nodemcu.readthedocs.io)
### LFS support
In July 2018 support for a Lua Flash Store (LFS) was introduced. LFS allows Lua code and its associated constant data to be executed directly out of flash-memory; just as the firmware itself is executed. This now enables NodeMCU developers to create **Lua applications with up to 256Kb** Lua code and read-only constants executing out of flash. All of the RAM is available for read-write data!
# Programming Model
The NodeMCU programming model is similar to that of [Node.js](https://en.wikipedia.org/wiki/Node.js), only in Lua. It is asynchronous and event-driven. Many functions, therefore, have parameters for callback functions. To give you an idea what a NodeMCU program looks like study the short snippets below. For more extensive examples have a look at the [`/lua_examples`](lua_examples) folder in the repository on GitHub.

View File

@ -20,89 +20,64 @@ FLAVOR = debug
ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)
OPT_MKTARGETS := coap crypto dht http mqtt pcm sjson sqlite3 tsl2561 websocket
OPT_MKLIBTARGETS := u8g2 ucg
SEL_MKTARGETS := $(shell $(CC) -E -dM include/user_modules.h | sed -n '/^\#define LUA_USE_MODULES_/{s/.\{24\}\(.*\)/\L\1/; p}')
OPT_SEL_MKLIBTARGETS := $(foreach tgt,$(OPT_MKLIBTARGETS),$(findstring $(tgt), $(SEL_MKTARGETS)))
OPT_SEL_MKTARGETS := $(foreach tgt,$(OPT_MKTARGETS),$(findstring $(tgt), $(SEL_MKTARGETS))) \
$(foreach tgt,$(OPT_SEL_MKLIBTARGETS),$(tgt)lib)
OPT_SEL_COMPONENTS := $(foreach tgt,$(OPT_SEL_MKTARGETS),$(tgt)/lib$(tgt).a)
SPECIAL_MKTARGETS :=$(APP_MKTARGETS)
SUBDIRS= \
user \
driver \
pcm \
mbedtls \
platform \
libc \
lua \
lwip \
coap \
mqtt \
task \
u8glib \
ucglib \
smart \
modules \
spiffs \
crypto \
dhtlib \
tsl2561 \
net \
http \
fatfs \
esp-gdbstub \
websocket \
pm \
sjson \
sqlite3 \
$(OPT_SEL_MKTARGETS)
endif # } PDIR
APPDIR = .
LDDIR = ../ld
CCFLAGS += -Os
TARGET_LDFLAGS = \
-nostdlib \
-Wl,-EL \
--longcalls \
--text-section-literals
ifeq ($(FLAVOR),debug)
TARGET_LDFLAGS += -g -Os
endif
ifeq ($(FLAVOR),release)
TARGET_LDFLAGS += -Os
endif
LD_FILE = $(LDDIR)/nodemcu.ld
COMPONENTS_eagle.app.v6 = \
user/libuser.a \
driver/libdriver.a \
pcm/pcm.a \
platform/libplatform.a \
task/libtask.a \
libc/liblibc.a \
lua/liblua.a \
lwip/liblwip.a \
coap/coap.a \
mqtt/mqtt.a \
u8glib/u8glib.a \
ucglib/ucglib.a \
smart/smart.a \
spiffs/spiffs.a \
fatfs/libfatfs.a \
crypto/libcrypto.a \
dhtlib/libdhtlib.a \
tsl2561/tsl2561lib.a \
http/libhttp.a \
pm/libpm.a \
websocket/libwebsocket.a \
esp-gdbstub/libgdbstub.a \
net/libnodemcu_net.a \
mbedtls/libmbedtls.a \
modules/libmodules.a \
sjson/libsjson.a \
sqlite3/libsqlite3.a \
$(OPT_SEL_COMPONENTS)
# Inspect the modules library and work out which modules need to be linked.
# For each enabled module, a symbol name of the form XYZ_module_selected is
@ -162,7 +137,7 @@ CONFIGURATION_DEFINES = -D__ets__ \
-DLWIP_OPEN_SRC \
-DPBUF_RSV_FOR_WLAN \
-DEBUF_LWIP \
-DUSE_OPTIMIZE_PRINTF \
-DUSE_OPTIMIZE_PRINTF \
-DMBEDTLS_USER_CONFIG_FILE=\"user_mbedtls.h\" \
DEFINES += \
@ -191,6 +166,5 @@ INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
.PHONY: FORCE
FORCE:

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = coap.a
GEN_LIBS = libcoap.a
endif
#############################################################

View File

@ -162,7 +162,8 @@ end:
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
}
extern lua_Load gLoad;
extern int lua_put_line(const char *s, size_t l);
static const coap_endpoint_path_t path_command = {2, {"v1", "c"}};
static int handle_post_command(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
{
@ -170,16 +171,9 @@ static int handle_post_command(const coap_endpoint_t *ep, coap_rw_buffer_t *scra
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN);
if (inpkt->payload.len > 0)
{
lua_Load *load = &gLoad;
if(load->line_position == 0){
coap_buffer_to_string(load->line, load->len,&inpkt->payload);
load->line_position = c_strlen(load->line)+1;
// load->line[load->line_position-1] = '\n';
// load->line[load->line_position] = 0;
// load->line_position++;
load->done = 1;
NODE_DBG("Get command:\n");
NODE_DBG(load->line); // buggy here
char line[LUA_MAXINPUT];
if (!coap_buffer_to_string(line, LUA_MAXINPUT, &inpkt->payload) &&
lua_put_line(line, c_strlen(line))) {
NODE_DBG("\nResult(if any):\n");
system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
}

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libdhtlib.a
GEN_LIBS = libdht.a
endif

0
app/driver/uart.c Executable file → Normal file
View File

View File

@ -23,7 +23,7 @@ endif
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#DEFINES += -DGDBSTUB_REDIRECT_CONSOLE_OUTPUT
#############################################################
# Recursion Magic - Don't touch this!!

View File

@ -414,7 +414,7 @@ static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
body = body + 4;
}
if ( os_strstr( req->buffer, "Transfer-Encoding: chunked" ) )
if ( os_strstr( req->buffer, "Transfer-Encoding: chunked" ) || os_strstr( req->buffer, "transfer-encoding: chunked" ) )
{
int body_size = req->buffer_size - (body - req->buffer);
char chunked_decode_buffer[body_size];

0
app/include/arch/cc.h Executable file → Normal file
View File

0
app/include/driver/uart.h Executable file → Normal file
View File

0
app/include/driver/uart_register.h Executable file → Normal file
View File

0
app/include/lwipopts.h Executable file → Normal file
View File

View File

@ -38,8 +38,11 @@
#define MODULE_PASTE_(x,y) x##y
#define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(x,y)
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(s)))
#ifdef LUA_CROSS_COMPILER
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".rodata1." #s)))
#else
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
#endif
/* For the ROM table, we name the variable according to ( | denotes concat):
* cfgname | _module_selected | LUA_USE_MODULES_##cfgname
* where the LUA_USE_MODULES_XYZ macro is first expanded to yield either
@ -51,20 +54,20 @@
* to be linked in.
*/
#define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \
const LOCK_IN_SECTION(".lua_libs") \
const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,cfgname) = { luaname, initfunc }; \
const LOCK_IN_SECTION(".lua_rotable") \
const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
= { luaname, map }
/* System module registration support, not using LUA_USE_MODULES_XYZ. */
#define BUILTIN_LIB_INIT(name, luaname, initfunc) \
const LOCK_IN_SECTION(".lua_libs") \
const LOCK_IN_SECTION(libs) \
luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc }
#define BUILTIN_LIB(name, luaname, map) \
const LOCK_IN_SECTION(".lua_rotable") \
const LOCK_IN_SECTION(rotable) \
luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map }
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)

121
app/include/u8g2_displays.h Normal file
View File

@ -0,0 +1,121 @@
#ifndef _U8G2_DISPLAYS_H
#define _U8G2_DISPLAYS_H
#define U8G2_DISPLAY_TABLE_ENTRY(function, binding)
// ***************************************************************************
// Enable display drivers
//
// Uncomment the U8G2_DISPLAY_TABLE_ENTRY for the device(s) you want to
// compile into the firmware.
// Stick to the assignments to *_I2C and *_SPI tables.
#ifndef U8G2_DISPLAY_TABLE_I2C_EXTRA
// I2C based displays go into here:
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1610_i2c_ea_dogxl160_f, uc1610_i2c_ea_dogxl160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1325_i2c_nhd_128x64_f, ssd1325_i2c_nhd_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_64x48_er_f, ssd1306_i2c_64x48_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_i2c_erc24064_f, uc1608_i2c_erc24064) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7588_i2c_jlx12864_f, st7588_i2c_jlx12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_i2c_128x64_noname0_f, ssd1309_i2c_128x64_noname0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ea_dogxl240_f, uc1611_i2c_ea_dogxl240) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1305_i2c_128x32_noname_f, ssd1305_i2c_128x32_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x32_univision_f, ssd1306_i2c_128x32_univision) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_i2c_240x128_f, uc1608_i2c_240x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ld7032_i2c_60x32_f, ld7032_i2c_60x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ew50850_f, uc1611_i2c_ew50850) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1604_i2c_jlx19264_f, uc1604_i2c_jlx19264) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1601_i2c_128x32_f, uc1601_i2c_128x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_vcomh0_f, sh1106_i2c_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_96x16_er_f, ssd1306_i2c_96x16_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_noname_f, sh1106_i2c_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f, ssd1306_i2c_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_i2c_128x64_noname2_f, ssd1309_i2c_128x64_noname2) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ea_dogm240_f, uc1611_i2c_ea_dogm240) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_seeed_96x96_f, ssd1327_i2c_seeed_96x96) \
#define U8G2_DISPLAY_TABLE_I2C \
U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
#else
// I2C displays can be defined in an external file.
#define U8G2_DISPLAY_TABLE_I2C \
U8G2_DISPLAY_TABLE_I2C_EXTRA
#endif
#ifndef U8G2_DISPLAY_TABLE_SPI_EXTRA
// SPI based displays go into here:
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1606_172x72_f, ssd1606_172x72) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_240x128_f, uc1608_240x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_erc12864_f, st7565_erc12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_128x64_noname0_f, ssd1309_128x64_noname0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1601_128x32_f, uc1601_128x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_erc24064_f, uc1608_erc24064) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_lm6059_f, st7565_lm6059) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_ea_dogxl240_f, uc1611_ea_dogxl240) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_nhd_c12864_f, st7565_nhd_c12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_vcomh0_f, ssd1306_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1305_128x32_noname_f, ssd1305_128x32_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_max7219_32x8_f, max7219_32x8) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ls013b7dh03_128x128_f, ls013b7dh03_128x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_il3820_v2_296x128_f, il3820_v2_296x128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1610_ea_dogxl160_f, uc1610_ea_dogxl160) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_ea_dogm240_f, uc1611_ea_dogm240) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1604_jlx19264_f, uc1604_jlx19264) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7920_s_192x32_f, st7920_s_192x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1325_nhd_128x64_f, ssd1325_nhd_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_noname_f, ssd1306_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sed1520_122x32_f, sed1520_122x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_ea_dogm128_f, st7565_ea_dogm128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ld7032_60x32_f, ld7032_60x32) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1607_200x200_f, ssd1607_200x200) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_128x64_noname2_f, ssd1309_128x64_noname2) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_128x64_noname_f, sh1106_128x64_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x32_univision_f, ssd1306_128x32_univision) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7920_s_128x64_f, st7920_s_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_64128n_f, st7565_64128n) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1701_ea_dogs102_f, uc1701_ea_dogs102) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_ew50850_f, uc1611_ew50850) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1322_nhd_256x64_f, ssd1322_nhd_256x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_ea_dogm132_f, st7565_ea_dogm132) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1329_128x96_noname_f, ssd1329_128x96_noname) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_zolen_128x64_f, st7565_zolen_128x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx256128_f, st75256_jlx256128) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_96x16_er_f, ssd1306_96x16_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ist3020_erc19264_f, ist3020_erc19264) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7588_jlx12864_f, st7588_jlx12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_seeed_96x96_f, ssd1327_seeed_96x96) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_jlx172104_f, st75256_jlx172104) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7565_nhd_c12832_f, st7565_nhd_c12832) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_64x48_er_f, ssd1306_64x48_er) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_pcf8812_96x65_f, pcf8812_96x65) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_pi_132x64_f, st7567_pi_132x64) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_jlx12864_f, st7567_jlx12864) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_pcd8544_84x48_f, pcd8544_84x48) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_128x64_vcomh0_f, sh1106_128x64_vcomh0) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_nt7534_tg12864r_f, nt7534_tg12864r) \
// U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1701_mini12864_f, uc1701_mini12864) \
#define U8G2_DISPLAY_TABLE_SPI \
U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_noname_f, ssd1306_128x64_noname) \
#else
// SPI displays can be defined in an external file.
#define U8G2_DISPLAY_TABLE_SPI \
U8G2_DISPLAY_TABLE_SPI_EXTRA
#endif
//
// ***************************************************************************
#endif /* _U8G2_DISPLAYS_H */

29
app/include/u8g2_fonts.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _U8G2_FONTS_H
#define _U8G2_FONTS_H
#define U8G2_FONT_TABLE_ENTRY(font)
// ***************************************************************************
// Configure U8glib fonts
//
#ifndef U8G2_FONT_TABLE_EXTRA
//
// Add a U8G2_FONT_TABLE_ENTRY for each font you want to compile into the image
// See https://github.com/olikraus/u8g2/wiki/fntlistall for a complete list of
// available fonts. Drop the 'u8g2_' prefix when you add them here.
#define U8G2_FONT_TABLE \
U8G2_FONT_TABLE_ENTRY(font_6x10_tf) \
U8G2_FONT_TABLE_ENTRY(font_unifont_t_symbols) \
#else
//
// The font table can be defined in an external file.
#define U8G2_FONT_TABLE \
U8G2_FONT_TABLE_EXTRA
#endif
// ***************************************************************************
#endif /* _U8G2_FONTS_H */

View File

@ -1,88 +0,0 @@
#ifndef __U8G_CONFIG_H__
#define __U8G_CONFIG_H__
// ***************************************************************************
// Configure U8glib fonts
//
// Add a U8G_FONT_TABLE_ENTRY for each font you want to compile into the image
#define U8G_FONT_TABLE_ENTRY(font)
#define U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10) \
U8G_FONT_TABLE_ENTRY(font_chikita)
#undef U8G_FONT_TABLE_ENTRY
//
// ***************************************************************************
// ***************************************************************************
// Enable display drivers
//
// Uncomment the U8G_DISPLAY_TABLE_ENTRY for the device(s) you want to
// compile into the firmware.
// Stick to the assignments to *_I2C and *_SPI tables.
//
// I2C based displays go into here:
// U8G_DISPLAY_TABLE_ENTRY(sh1106_128x64_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x32_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_64x48_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1309_128x64_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1327_96x96_gr_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(uc1611_dogm240_i2c) \
// U8G_DISPLAY_TABLE_ENTRY(uc1611_dogxl240_i2c) \
#define U8G_DISPLAY_TABLE_ENTRY(device)
#define U8G_DISPLAY_TABLE_I2C \
U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_i2c) \
// SPI based displays go into here:
// U8G_DISPLAY_TABLE_ENTRY(ld7032_60x32_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(pcd8544_84x48_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(pcf8812_96x65_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(sh1106_128x64_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x32_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1306_64x48_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1309_128x64_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1322_nhd31oled_bw_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1322_nhd31oled_gr_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1325_nhd27oled_bw_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1325_nhd27oled_gr_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1327_96x96_gr_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1351_128x128_332_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1351_128x128gh_332_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1351_128x128_hicolor_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1351_128x128gh_hicolor_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1353_160x128_332_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(ssd1353_160x128_hicolor_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_64128n_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_dogm128_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_dogm132_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_lm6059_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_lm6063_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_nhd_c12832_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(st7565_nhd_c12864_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1601_c128032_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1608_240x128_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1608_240x64_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1610_dogxl160_bw_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1610_dogxl160_gr_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1611_dogm240_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1611_dogxl240_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1701_dogs102_hw_spi) \
// U8G_DISPLAY_TABLE_ENTRY(uc1701_mini12864_hw_spi) \
#define U8G_DISPLAY_TABLE_SPI \
U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_hw_spi) \
#undef U8G_DISPLAY_TABLE_ENTRY
// Special display device to provide run-length encoded framebuffer contents
// to a Lua callback:
//#define U8G_DISPLAY_FB_RLE
//
// ***************************************************************************
#endif /* __U8G_CONFIG_H__ */

View File

@ -1,125 +1,250 @@
#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__
// #define FLASH_512K
// #define FLASH_1M
// #define FLASH_2M
// #define FLASH_4M
// #define FLASH_8M
// #define FLASH_16M
#define FLASH_AUTOSIZE
// The firmware supports a range of Flash sizes, though 4 Mbyte seems to be
// the most common currently. NodeMCU builds include a discovery function
// which is enabled by FLASH_AUTOSIZE, but you can override this by commenting
// this out and enabling the explicitly size, e.g. FLASH_4M. Valid sizes are
// FLASH_512K, FLASH_1M, FLASH_2M, FLASH_4M, FLASH_8M, FLASH_16M.
#define FLASH_AUTOSIZE
//#define FLASH_4M
// The firmware now selects a baudrate of 115,200 by default, but the driver
// also includes automatic baud rate detection at start-up. If you want to change
// the default rate then vaild rates are 300, 600, 1200, 2400, 4800, 9600, 19200,
// 31250, 38400, 57600, 74880, 115200, 230400, 256000, 460800 [, 921600, 1843200,
// 368640]. Note that the last 3 rates are not recommended as these might be
// unreliable, but 460800 seems to work well for most USB-serial devices.
#define BIT_RATE_DEFAULT BIT_RATE_115200
//#define BIT_RATE_AUTOBAUD
// Three separate build variants are now supported. The main difference is in the
// processing of numeric data types. If LUA_NUMBER_INTEGRAL is defined, then
// all numeric calculations are done in integer, with divide being an integer
// operations, and decimal fraction constants are illegal. Otherwise all
// numeric operations use floating point, though they are exact for integer
// expressions < 2^53.
// The main advantage of INTEGRAL builds is that the basic internal storage unit,
// the TValue, is 8 bytes long. We have now reduced the size of FP TValues to
// 12 bytes rather than the previous 16 as this gives a material RAM saving with
// no performance loss. However, you can define LUA_DWORD_ALIGNED_TVALUES and
// this will force 16 byte TValues on FP builds.
//#define LUA_NUMBER_INTEGRAL
//#define LUA_DWORD_ALIGNED_TVALUES
// The Lua Flash Store (LFS) allows you to store Lua code in Flash memory and
// the Lua VMS will execute this code directly from flash without needing any
// RAM overhead. If you want to enable LFS then set the following define to
// the size of the store that you need. This can be any multiple of 4kB up to
// a maximum 256Kb.
//#define LUA_FLASH_STORE 0x10000
// By default Lua executes the file init.lua at start up. The following
// define allows you to replace this with an alternative startup. Warning:
// you must protect this execution otherwise you will enter a panic loop;
// the simplest way is to wrap the action in a function invoked by a pcall.
// The example provided executes the LFS module "_init" at startup or fails
// through to the interactive prompt.
//#define LUA_INIT_STRING "pcall(function() node.flashindex'_init'() end)"
// NodeMCU supports two file systems: SPIFFS and FATFS, the first is available
// on all ESP8266 modules. The latter requires extra H/W so is less common.
// If you use SPIFFS then there are a number of options which impact the
// RAM overhead and performance of the file system.
// If you use the spiffsimg tool to create your own FS images on your dev PC
// then we recommend that you fix the location and size of the FS, allowing
// some headroom for rebuilding flash images and LFS. As an alternative to
// fixing the size of the FS, you can force the SPIFFS file system to end on
// the next 1Mb boundary. This is useful for certain OTA scenarios. In
// general, limiting the size of the FS only to what your application needs
// gives the fastest start-up and imaging times.
#define BUILD_SPIFFS
//#define SPIFFS_FIXED_LOCATION 0x100000
//#define SPIFFS_MAX_FILESYSTEM_SIZE 0x20000
//#define SPIFFS_SIZE_1M_BOUNDARY
#define SPIFFS_CACHE 1 // Enable if you use you SPIFFS in R/W mode
#define SPIFFS_MAX_OPEN_FILES 4 // maximum number of open files for SPIFFS
#define FS_OBJ_NAME_LEN 31 // maximum length of a filename
//#define BUILD_FATFS
// The HTTPS stack requires client SSL to be enabled. The SSL buffer size is
// used only for espconn-layer secure connections, and is ignored otherwise.
// Some HTTPS applications require a larger buffer size to work. See
// https://github.com/nodemcu/nodemcu-firmware/issues/1457 for details.
// The SHA2 and MD2 libraries are also optionally used by the crypto functions.
// The SHA1 and MD5 function are implemented in the ROM BIOS. The MD2 and SHA2
// are by firmware code, and can be enabled if you need this functionality.
//#define CLIENT_SSL_ENABLE
//#define MD2_ENABLE
#define SHA2_ENABLE
#define SSL_BUFFER_SIZE 5120
// GPIO_INTERRUPT_ENABLE needs to be defined if your application uses the
// gpio.trig() or related GPIO interrupt service routine code. Likewise the
// GPIO interrupt hook is requited for a few modules such as rotary. If you
// don't require this functionality, then commenting out these options out
// will remove any associated runtime overhead.
#define GPIO_INTERRUPT_ENABLE
#define GPIO_INTERRUPT_HOOK_ENABLE
// If your application uses the light sleep functions and you wish the
// firmware to manage timer rescheduling over sleeps (the CPU clock is
// suspended so timers get out of sync) then enable the following options
//#define ENABLE_TIMER_SUSPEND
//#define PMSLEEP_ENABLE
// The WiFi module optionally offers an enhanced level of WiFi connection
// management, using internal timer callbacks. Whilst many Lua developers
// prefer to implement equivalent features in Lua, others will prefer the
// Wifi module to do this for them. Uncomment the following to enable
// this functionality. See the relevant WiFi module documentation for
// further details, as the scope of these changes is not obvious.
// Enable the wifi.startsmart() and wifi.stopsmart()
//#define WIFI_SMART_ENABLE
// Enable wifi.sta.config() event callbacks
#define WIFI_SDK_EVENT_MONITOR_ENABLE
// Enable creation on the wifi.eventmon.reason table
#define WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
// Enable use of the WiFi.monitor sub-module
//#define LUA_USE_MODULES_WIFI_MONITOR
// Whilst the DNS client details can be configured through the WiFi API,
// the defaults can be exposed temporarily during start-up. The following
// WIFI_STA options allow you to configure this in the firmware. If the
// WIFI_STA_HOSTNAME is not defined then the hostname will default to
// to the last 3 octets (6 hexadecimal digits) of MAC address with the
// prefix "NODE-". If it is defined then the hostname must only contain
// alphanumeric characters. If you are imaging multiple modules with this
// firmware then you must also define WIFI_STA_HOSTNAME_APPEND_MAC to
// append the last 3 octets of the MAC address. Note that the total
// Hostname MUST be 32 chars or less.
//#define WIFI_STA_HOSTNAME "NodeMCU"
//#define WIFI_STA_HOSTNAME_APPEND_MAC
// If you use the enduser_setup module, then you can also set the default
// SSID when this module is running in AP mode.
#define ENDUSER_SETUP_AP_SSID "SetupGadget"
// The following sections are only relevent for those developers who are
// developing modules or core Lua changes and configure how extra diagnostics
// are enabled in the firmware. These should only be configured if you are
// building your own custom firmware and have full access to the firmware
// source code.
// Enabling DEVELOPMENT_TOOLS adds the asserts in LUA and also some useful
// extras to the node module. These are silent in normal operation and so can
// be enabled without any harm (except for the code size increase and slight
// slowdown). If you want to use the remote GDB to handle breaks and failed
// assertions then enable the DEVELOPMENT_USE GDB option. A supplimentary
// define DEVELOPMENT_BREAK_ON_STARTUP_PIN allows you to define a GPIO pin,
// which if pulled low at start-up will immediately initiate a GDB session.
// The DEVELOP_VERSION option enables lots of debug output, and is normally
// only used by hardcore developers.
// These options can be enabled globally here or you can alternatively use
// the DEFINES variable in the relevant Makefile to set these on a per
// directory basis. If you do this then you can also set the corresponding
// compile options (-O0 -ggdb) on a per directory as well.
// This adds the asserts in LUA. It also adds some useful extras to the
// node module. This is all silent in normal operation and so can be enabled
// without any harm (except for the code size increase and slight slowdown)
//#define DEVELOPMENT_TOOLS
//#define DEVELOPMENT_USE_GDB
//#define DEVELOPMENT_BREAK_ON_STARTUP_PIN 1
//#define DEVELOP_VERSION
// *** Heareafter, there be demons ***
// The remaining options are advanced configuration options and you should only
// change this if you have tracked the implications through the Firmware sources
// and understand the these.
#define LUA_TASK_PRIO USER_TASK_PRIO_0
#define LUA_PROCESS_LINE_SIG 2
#define LUA_OPTIMIZE_DEBUG 2
#define READLINE_INTERVAL 80
#define STRBUF_DEFAULT_INCREMENT 3
#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback()
#ifdef DEVELOPMENT_TOOLS
#if defined(LUA_CROSS_COMPILER) || !defined(DEVELOPMENT_USE_GDB)
extern void luaL_assertfail(const char *file, int line, const char *message);
#define lua_assert(x) ((x) ? (void) 0 : luaL_assertfail(__FILE__, __LINE__, #x))
#else
extern void luaL_dbgbreak(void);
#define lua_assert(x) ((x) ? (void) 0 : luaL_dbgbreak())
#endif
#endif
#if !defined(LUA_NUMBER_INTEGRAL) && defined (LUA_DWORD_ALIGNED_TVALUES)
#define LUA_PACK_TVALUES
#else
#undef LUA_PACK_TVALUES
#endif
// This enables lots of debug output and changes the serial bit rate. This
// is normally only used by hardcore developers
// #define DEVELOP_VERSION
#ifdef DEVELOP_VERSION
#define NODE_DEBUG
#define COAP_DEBUG
#endif /* DEVELOP_VERSION */
#define BIT_RATE_DEFAULT BIT_RATE_115200
// This enables automatic baud rate detection at startup
#define BIT_RATE_AUTOBAUD
#define NODE_ERROR
#ifdef NODE_DEBUG
#define NODE_DBG dbg_printf
#else
#define NODE_DBG
#endif /* NODE_DEBUG */
#define NODE_ERROR
#ifdef NODE_ERROR
#define NODE_ERR dbg_printf
#else
#define NODE_ERR
#endif /* NODE_ERROR */
#define GPIO_INTERRUPT_ENABLE
#define GPIO_INTERRUPT_HOOK_ENABLE
// #define GPIO_SAFE_NO_INTR_ENABLE
#define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
#define ICACHE_RAM_STRING(x) ICACHE_RAM_STRING2(x)
#define ICACHE_RAM_STRING2(x) #x
#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text." __FILE__ "." ICACHE_RAM_STRING(__LINE__))))
#define ICACHE_STRING(x) ICACHE_STRING2(x)
#define ICACHE_STRING2(x) #x
#define ICACHE_RAM_ATTR \
__attribute__((section(".iram0.text." __FILE__ "." ICACHE_STRING(__LINE__))))
#define ICACHE_FLASH_RESERVED_ATTR \
__attribute__((section(".irom.reserved." __FILE__ "." ICACHE_STRING(__LINE__)),\
used,unused,aligned(INTERNAL_FLASH_SECTOR_SIZE)))
#ifdef GPIO_SAFE_NO_INTR_ENABLE
#define NO_INTR_CODE ICACHE_RAM_ATTR __attribute__ ((noinline))
#else
#define NO_INTR_CODE inline
#endif
// SSL buffer size used only for espconn-layer secure connections.
// See https://github.com/nodemcu/nodemcu-firmware/issues/1457 for conversation details.
#define SSL_BUFFER_SIZE 5120
//#define CLIENT_SSL_ENABLE
//#define MD2_ENABLE
#define SHA2_ENABLE
#define BUILD_SPIFFS
#define SPIFFS_CACHE 1
//#define BUILD_FATFS
// maximum length of a filename
#define FS_OBJ_NAME_LEN 31
// maximum number of open files for SPIFFS
#define SPIFFS_MAX_OPEN_FILES 4
// Uncomment this next line for fastest startup
// It reduces the format time dramatically
// #define SPIFFS_MAX_FILESYSTEM_SIZE 32768
//
// You can force the spiffs file system to be at a fixed location
// #define SPIFFS_FIXED_LOCATION 0x100000
//
// You can force the SPIFFS file system to end on the next !M boundary
// (minus the 16k parameter space). THis is useful for certain OTA scenarios
// #define SPIFFS_SIZE_1M_BOUNDARY
// #define LUA_NUMBER_INTEGRAL
#define READLINE_INTERVAL 80
#define LUA_TASK_PRIO USER_TASK_PRIO_0
#define LUA_PROCESS_LINE_SIG 2
#define LUA_OPTIMIZE_DEBUG 2
#define ENDUSER_SETUP_AP_SSID "SetupGadget"
/*
* A valid hostname only contains alphanumeric and hyphen(-) characters, with no hyphens at first or last char
* if WIFI_STA_HOSTNAME not defined: hostname will default to NODE-xxxxxx (xxxxxx being last 3 octets of MAC address)
* if WIFI_STA_HOSTNAME defined: hostname must only contain alphanumeric characters
* if WIFI_STA_HOSTNAME_APPEND_MAC not defined: Hostname MUST be 32 chars or less
* if WIFI_STA_HOSTNAME_APPEND_MAC defined: Hostname MUST be 26 chars or less, since last 3 octets of MAC address will be appended
* if defined hostname is invalid: hostname will default to NODE-xxxxxx (xxxxxx being last 3 octets of MAC address)
*/
//#define WIFI_STA_HOSTNAME "NodeMCU"
//#define WIFI_STA_HOSTNAME_APPEND_MAC
//#define WIFI_SMART_ENABLE
#define WIFI_SDK_EVENT_MONITOR_ENABLE
#define WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
//#define PMSLEEP_ENABLE // Enable wifi.suspend() and node.sleep() (NOTE: node.sleep() is dependent on TIMER_SUSPEND_ENABLE)
//#define TIMER_SUSPEND_ENABLE //Required by node.sleep()
#define STRBUF_DEFAULT_INCREMENT 32
#endif /* __USER_CONFIG_H__ */

View File

@ -1,16 +1,6 @@
#ifndef __USER_MODULES_H__
#define __USER_MODULES_H__
#define LUA_USE_BUILTIN_STRING // for string.xxx()
#define LUA_USE_BUILTIN_TABLE // for table.xxx()
#define LUA_USE_BUILTIN_COROUTINE // for coroutine.xxx()
#define LUA_USE_BUILTIN_MATH // for math.xxx(), partially work
// #define LUA_USE_BUILTIN_IO // for io.xxx(), partially work
// #define LUA_USE_BUILTIN_OS // for os.xxx(), not work
// #define LUA_USE_BUILTIN_DEBUG
#define LUA_USE_BUILTIN_DEBUG_MINIMAL // for debug.getregistry() and debug.traceback()
#ifndef LUA_CROSS_COMPILER
// The default configuration is designed to run on all ESP modules including the 512 KB modules like ESP-01 and only
@ -69,13 +59,13 @@
//#define LUA_USE_MODULES_SQLITE3
//#define LUA_USE_MODULES_STRUCT
//#define LUA_USE_MODULES_SWITEC
// #define LUA_USE_MODULES_TCS34725
//#define LUA_USE_MODULES_TCS34725
//#define LUA_USE_MODULES_TM1829
#define LUA_USE_MODULES_TLS
//#define LUA_USE_MODULES_TLS
#define LUA_USE_MODULES_TMR
//#define LUA_USE_MODULES_TSL2561
//#define LUA_USE_MODULES_U8G
#define LUA_USE_MODULES_UART
//#define LUA_USE_MODULES_U8G2
//#define LUA_USE_MODULES_UCG
//#define LUA_USE_MODULES_WEBSOCKET
#define LUA_USE_MODULES_WIFI

View File

@ -15,55 +15,6 @@
#include "c_stdlib.h"
#include "c_types.h"
#include "c_string.h"
// const char *lua_init_value = "print(\"Hello world\")";
const char *lua_init_value = "@init.lua";
// int c_abs(int x){
// return x>0?x:0-x;
// }
// void c_exit(int e){
// }
const char *c_getenv(const char *__string)
{
if (c_strcmp(__string, "LUA_INIT") == 0)
{
return lua_init_value;
}
return NULL;
}
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
// void *c_malloc(size_t __size){
// if(__size>system_get_free_heap_size()){
// NODE_ERR("malloc: not enough memory\n");
// return NULL;
// }
// return (void *)os_malloc(__size);
// }
// void *c_zalloc(size_t __size){
// if(__size>system_get_free_heap_size()){
// NODE_ERR("zalloc: not enough memory\n");
// return NULL;
// }
// return (void *)os_zalloc(__size);
// }
// void c_free(void *p){
// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
// os_free(p);
// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
// }c_stdlib.s
// int c_rand(void){
// }
// void c_srand(unsigned int __seed){
// }
// int c_atoi(const char *__nptr){
// }
#include <_ansi.h>
//#include <reent.h>
//#include "mprec.h"

View File

@ -46,8 +46,7 @@
// void c_exit(int);
// c_getenv() get env "LUA_INIT" string for lua initialization.
const char *c_getenv(const char *__string);
//const char *c_getenv(const char *__string);
// void *c_malloc(size_t __size);
// void *c_zalloc(size_t __size);

View File

@ -12,6 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
SUBDIRS = luac_cross
GEN_LIBS = liblua.a
endif
@ -24,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DDEVELOPMENT_BREAK_ON_STARTUP_PIN=1
#EXTRA_CCFLAGS += -ggdb -O0
#############################################################
# Recursion Magic - Don't touch this!!

View File

@ -1,47 +0,0 @@
/**
* define start/end address of ro data.
* different compiler with different implementation.
*/
#ifndef __COMPILER_H__
#define __COMPILER_H__
#if defined(__CC_ARM) // armcc
//#warning "Please check scatter file to ensure rodata is in ER_IROM1 region."
/* symbols reference to the scatter file */
extern char Image$$ER_IROM1$$Base;
extern char Image$$ER_IROM1$$Limit;
#define RODATA_START_ADDRESS (&Image$$ER_IROM1$$Base)
#define RODATA_END_ADDRESS (&Image$$ER_IROM1$$Limit)
#elif defined(__GNUC__) // gcc
//#warning "Please check linker script to ensure rodata is between _stext and _etext."
/* symbols defined in linker script */
// extern char _rodata_start;
// extern char _rodata_end;
extern char _irom0_text_start;
extern char _irom0_text_end;
// modify linker script to ensure rodata and rodata1 is between _rodata_start and _rodata_end.
// #define RODATA_START_ADDRESS (&_rodata_start)
// #define RODATA_END_ADDRESS (&_rodata_end)
#define RODATA_START_ADDRESS (&_irom0_text_start)
#define RODATA_END_ADDRESS (&_irom0_text_end)
#else // other compilers
/* Firstly, modify rodata's start/end address. Then, comment the line below */
#error "Please modify RODATA_START_ADDRESS and RODATA_END_ADDRESS below."
/* Perhaps you can use start/end address of flash */
#define RODATA_START_ADDRESS ((char*)0x40200000)
#define RODATA_END_ADDRESS ((char*)0x40280000)
#endif
#endif // __COMPILER_H__

View File

@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TROTABLE:
return rvalue(o);
case LUA_TLIGHTFUNCTION:
return pvalue(o);
return fvalue(o);
default: return NULL;
}
}
@ -459,15 +459,6 @@ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
}
LUA_API void lua_pushrolstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
luaC_checkGC(L);
setsvalue2s(L, L->top, luaS_newrolstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushstring (lua_State *L, const char *s) {
if (s == NULL)
lua_pushnil(L);

View File

@ -45,6 +45,149 @@
#define LUA_USECCLOSURES 0
#define LUA_USELIGHTFUNCTIONS 1
//#define DEBUG_ALLOCATOR
#ifdef DEBUG_ALLOCATOR
#ifdef LUA_CROSS_COMPILER
static void break_hook(void) {}
#define ASSERT(s) if (!(s)) {break_hook();}
#else
#define ASSERT(s) if (!(s)) {asm ("break 0,0" ::);}
#endif
/*
** {======================================================================
** Diagnosticd version for realloc. This is enabled only if the
** DEBUG_ALLOCATOR is defined. It is a cutdown version of the allocator
** used in the Lua Test Suite -- a compromise between the ability catch
** most alloc/free errors and overruns and working within the RAM limits
** of the ESP8266 architecture. ONLY FOR HEAVY HACKERS
** =======================================================================
*/
#define this_realloc debug_realloc
#define MARK 0x55 /* 01010101 (a nice pattern) */
#define MARKSIZE 2*sizeof(size_t) /* size of marks after each block */
#define fillmem(mem,size) memset(mem, ~MARK, size)
typedef union MemHeader MemHeader;
union MemHeader {
L_Umaxalign a; /* ensures maximum alignment for Header */
struct {
size_t size;
MemHeader *next;
size_t mark[2];
};
};
typedef struct Memcontrol { /* memory-allocator control variables */
MemHeader *start;
lu_int32 numblocks;
lu_int32 total;
lu_int32 maxmem;
lu_int32 memlimit;
} Memcontrol;
static Memcontrol mc = {NULL,0,0,0,32768*64};
static size_t marker[2] = {0,0};
static void scanBlocks (void) {
MemHeader *p = mc.start;
int i;
char s,e;
for (i=0; p ;i++) {
s = memcmp(p->mark, marker, MARKSIZE) ? '<' : ' ';
e = memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE) ? '>' : ' ';
c_printf("%4u %p %8lu %c %c\n", i, p, p->size, s, e);
ASSERT(p->next);
p = p->next;
}
}
static int checkBlocks (void) {
MemHeader *p = mc.start;
while(p) {
if (memcmp(p->mark, marker, MARKSIZE) ||
memcmp(cast(char *, p+1) + p->size, marker, MARKSIZE)) {
scanBlocks();
return 0;
}
p = p->next;
}
return 1;
}
static void freeblock (MemHeader *block) {
if (block) {
MemHeader *p = mc.start;
MemHeader *next = block->next;
size_t size = block->size;
ASSERT(checkBlocks());
if (p == block) {
mc.start = next;
} else {
while (p->next != block) {
ASSERT(p);
p = p->next;
}
p->next = next;
}
fillmem(block, sizeof(MemHeader) + size + MARKSIZE); /* erase block */
c_free(block); /* actually free block */
mc.numblocks--; /* update counts */
mc.total -= size;
}
}
void *debug_realloc (void *b, size_t oldsize, size_t size) {
MemHeader *block = cast(MemHeader *, b);
ASSERT(checkBlocks());
if (!marker[0]) memset(marker, MARK, MARKSIZE);
if (block == NULL) {
oldsize = 0;
} else {
block--; /* go to real header */
ASSERT(!memcmp(block->mark, marker, MARKSIZE))
ASSERT(oldsize == block->size);
ASSERT(!memcmp(cast(char *, b)+oldsize, marker, MARKSIZE));
}
if (size == 0) {
freeblock(block);
return NULL;
} else if (size > oldsize && mc.total+size-oldsize > mc.memlimit)
return NULL; /* fake a memory allocation error */
else {
MemHeader *newblock;
size_t commonsize = (oldsize < size) ? oldsize : size;
size_t realsize = sizeof(MemHeader) + size + MARKSIZE;
newblock = cast(MemHeader *, c_malloc(realsize)); /* alloc a new block */
if (newblock == NULL)
return NULL; /* really out of memory? */
if (block) {
memcpy(newblock + 1, block + 1, commonsize); /* copy old contents */
freeblock(block); /* erase (and check) old copy */
}
/* initialize new part of the block with something weird */
if (size > commonsize)
fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize);
/* initialize marks after block */
memset(newblock->mark, MARK, MARKSIZE);
newblock->size = size;
newblock->next = mc.start;
mc.start = newblock;
memset(cast(char *, newblock + 1)+ size, MARK, MARKSIZE);
mc.total += size;
if (mc.total > mc.maxmem)
mc.maxmem = mc.total;
mc.numblocks++;
return (newblock + 1);
}
}
/* }====================================================================== */
#else
#define this_realloc(p,os,s) c_realloc(p,s)
#endif /* DEBUG_ALLOCATOR */
/*
** {======================================================
** Error-report functions
@ -633,8 +776,9 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
lf.f = c_freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
lf.extraline = 0;
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
lf.extraline = 0;
}
c_ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
@ -787,8 +931,12 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
void *nptr;
if (nsize == 0) {
#ifdef DEBUG_ALLOCATOR
return (void *)this_realloc(ptr, osize, nsize);
#else
c_free(ptr);
return NULL;
#endif
}
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
luaC_fullgc(L);
@ -804,18 +952,45 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize))
return NULL;
}
nptr = (void *)c_realloc(ptr, nsize);
nptr = (void *)this_realloc(ptr, osize, nsize);
if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) {
luaC_fullgc(L); /* emergency full collection. */
nptr = (void *)c_realloc(ptr, nsize); /* try allocation again */
nptr = (void *)this_realloc(ptr, osize, nsize); /* try allocation again */
}
return nptr;
}
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
dbg_printf("ASSERT@%s(%d): %s\n", file, line, message);
#if defined(LUA_CROSS_COMPILER)
exit(1);
#endif
}
#ifdef DEVELOPMENT_USE_GDB
/*
* This is a simple stub used by lua_assert() if DEVELOPMENT_USE_GDB is defined.
* Instead of crashing out with an assert error, this hook starts the GDB remote
* stub if not already running and then issues a break. The rationale here is
* that when testing the developer migght be using screen/PuTTY to work ineractively
* with the Lua Interpreter via UART0. However if an assert triggers, then there
* is the option to exit the interactive session and start the Xtensa remote GDB
* which will then sync up with the remote GDB client to allow forensics of the error.
*/
extern void gdbstub_init(void);
LUALIB_API void luaL_dbgbreak(void) {
static int repeat_entry = 0;
if (repeat_entry == 0) {
dbg_printf("Start up the gdb stub if not already started\n");
gdbstub_init();
repeat_entry = 1;
}
asm("break 0,0" ::);
}
#endif
static int panic (lua_State *L) {
(void)L; /* to avoid warnings */
#if defined(LUA_USE_STDIO)

View File

@ -712,10 +712,5 @@ static void base_open (lua_State *L) {
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
#if LUA_OPTIMIZE_MEMORY == 0
luaL_register(L, LUA_COLIBNAME, co_funcs);
return 2;
#else
return 1;
#endif
}

View File

@ -17,6 +17,8 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lrotable.h"
#include "lstring.h"
#include "lflash.h"
#include "user_modules.h"
@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) {
return 1;
}
static int db_getstrings (lua_State *L) {
size_t i,n;
stringtable *tb;
GCObject *o;
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
const char *opt = lua_tolstring (L, 1, &n);
if (n==3 && memcmp(opt, "ROM", 4) == 0) {
if (G(L)->ROstrt.hash == NULL)
return 0;
tb = &G(L)->ROstrt;
}
else
#endif
tb = &G(L)->strt;
lua_settop(L, 0);
lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */
for (i=0, n=1; i<tb->size; i++) {
for(o = tb->hash[i]; o; o=o->gch.next) {
TString *ts =cast(TString *, o);
lua_pushnil(L);
setsvalue2s(L, L->top-1, ts);
lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */
}
}
lua_getfield(L, LUA_GLOBALSINDEX, "table");
lua_getfield(L, -1, "sort"); /* look up table.sort function */
lua_replace(L, -2); /* dump the table table */
lua_pushvalue(L, -2); /* duplicate the strt_copy ref */
lua_call(L, 1, 0); /* table.sort(strt_copy) */
return 1;
}
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
static int db_getmetatable (lua_State *L) {
@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = {
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
#endif
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
{LSTRKEY("getstrings"), LFUNCVAL(db_getstrings)},
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},

274
app/lua/lflash.c Normal file
View File

@ -0,0 +1,274 @@
/*
** $Id: lflash.c
** See Copyright Notice in lua.h
*/
#define lflash_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#ifdef LUA_FLASH_STORE
#include "lobject.h"
#include "lauxlib.h"
#include "lstate.h"
#include "lfunc.h"
#include "lflash.h"
#include "platform.h"
#include "vfs.h"
#include "c_fcntl.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
/*
* Flash memory is a fixed memory addressable block that is serially allocated by the
* luac build process and the out image can be downloaded into SPIFSS and loaded into
* flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build
* process.
*/
static char *flashAddr;
static uint32_t flashAddrPhys;
static uint32_t flashSector;
static uint32_t curOffset;
#define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t))))
#define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1))
#define ALL_SET cast(uint32_t, -1)
#define FLASH_SIZE LUA_FLASH_STORE
#define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
#define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
char flash_region_base[FLASH_SIZE] ICACHE_FLASH_RESERVED_ATTR;
#ifdef NODE_DEBUG
extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void dumpStrt(stringtable *tb, const char *type) {
int i,j;
GCObject *o;
NODE_DBG("\nDumping %s String table\n\n========================\n", type);
NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size);
for (i=0; i<tb->size; i++)
for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
TString *ts =cast(TString *, o);
NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n",
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len,
ts_isreadonly(ts) ? "R" : " ", getstr(ts));
}
}
LUA_API void dumpStrings(lua_State *L) {
dumpStrt(&G(L)->strt, "RAM");
if (G(L)->ROstrt.hash)
dumpStrt(&G(L)->ROstrt, "ROM");
}
#endif
/* =====================================================================================
* The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase
* wrap writing to flash. The last two are platform dependent. Also note that any
* writes are suppressed if the global writeToFlash is false. This is used in
* phase I where the pass is used to size the structures in flash.
*/
static char *flashPosition(void){
return flashAddr + curOffset;
}
static char *flashSetPosition(uint32_t offset){
NODE_DBG("flashSetPosition(%04x)\n", offset);
curOffset = offset;
return flashPosition();
}
static char *flashBlock(const void* b, size_t size) {
void *cur = flashPosition();
NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,b,size);
lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0);
platform_flash_write(b, flashAddrPhys+curOffset, size);
curOffset += size;
return cur;
}
static void flashErase(uint32_t start, uint32_t end){
int i;
if (start == -1) start = FLASH_PAGES - 1;
if (end == -1) end = FLASH_PAGES - 1;
NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end);
for (i = start; i<=end; i++)
platform_flash_erase_sector( flashSector + i );
}
/*
* Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
*/
LUAI_FUNC void luaN_init (lua_State *L) {
// luaL_dbgbreak();
curOffset = 0;
flashAddr = flash_region_base;
flashAddrPhys = platform_flash_mapped2phys((uint32_t)flashAddr);
flashSector = platform_flash_get_sector_of_address(flashAddrPhys);
FlashHeader *fh = cast(FlashHeader *, flashAddr);
/*
* For the LFS to be valid, its signature has to be correct for this build variant,
* thr ROhash and main proto fields must be defined and the main proto address
* be within the LFS address bounds. (This last check is primarily to detect the
* direct imaging of an absolute LFS with the wrong base address.
*/
if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
NODE_ERR("Flash sig not correct: %p vs %p\n",
fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
return;
}
if (fh->pROhash == ALL_SET ||
((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
NODE_ERR("Flash size check failed: %p vs 0xFFFFFFFF; %p >= %p\n",
fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
return;
}
G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash);
G(L)->ROstrt.nuse = fh->nROuse ;
G(L)->ROstrt.size = fh->nROsize;
G(L)->ROpvmain = cast(Proto *,fh->mainProto);
}
#define BYTE_OFFSET(t,f) cast(size_t, &(cast(t *, NULL)->f))
/*
* Rehook address chain to correct Flash byte addressed within the mapped adress space
* Note that on input each 32-bit address field is split into 2×16-bit subfields
* - the lu_int16 offset of the target address being referenced
* - the lu_int16 offset of the next address pointer.
*/
static int rebuild_core (int fd, uint32_t size, lu_int32 *buf, int is_absolute) {
int bi; /* byte offset into memory mapped LFS of current buffer */
int wNextOffset = BYTE_OFFSET(FlashHeader,mainProto)/sizeof(lu_int32);
int wj; /* word offset into current input buffer */
for (bi = 0; bi < size; bi += FLASH_PAGE_SIZE) {
int wi = bi / sizeof(lu_int32);
int blen = ((bi + FLASH_PAGE_SIZE) < size) ? FLASH_PAGE_SIZE : size - bi;
int wlen = blen / sizeof(lu_int32);
if (vfs_read(fd, buf , blen) != blen)
return 0;
if (!is_absolute) {
for (wj = 0; wj < wlen; wj++) {
if ((wi + wj) == wNextOffset) { /* this word is the next linked address */
int wTargetOffset = buf[wj]&0xFFFF;
wNextOffset = buf[wj]>>16;
lua_assert(!wNextOffset || (wNextOffset>(wi+wj) && wNextOffset<size/sizeof(lu_int32)));
buf[wj] = cast(lu_int32, flashAddr + wTargetOffset*sizeof(lu_int32));
}
}
}
flashBlock(buf, blen);
}
return size;
}
/*
* Library function called by node.flash.load(filename).
*/
LUALIB_API int luaN_reload_reboot (lua_State *L) {
int fd, status, is_absolute;
FlashHeader fh;
const char *fn = lua_tostring(L, 1);
if (!fn || !(fd = vfs_open(fn, "r")))
return 0;
if (vfs_read(fd, &fh, sizeof(fh)) != sizeof(fh) ||
(fh.flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG)
return 0;
if (vfs_lseek(fd, -1, VFS_SEEK_END) != fh.flash_size-1 ||
vfs_lseek(fd, 0, VFS_SEEK_SET) != 0)
return 0;
is_absolute = fh.flash_sig & FLASH_SIG_ABSOLUTE;
lu_int32 *buffer = luaM_newvector(L, FLASH_PAGE_SIZE / sizeof(lu_int32), lu_int32);
/*
* This is the point of no return. We attempt to rebuild the flash. If there
* are any problems them the Flash is going to be corrupt, so the only fallback
* is to erase it and reboot with a clean but blank flash. Otherwise the reboot
* will load the new LFS.
*
* Note that the Lua state is not passed into the lua core because from this
* point on, we make no calls on the Lua RTS.
*/
flashErase(0,-1);
if (rebuild_core(fd, fh.flash_size, buffer, is_absolute) != fh.flash_size)
flashErase(0,-1);
/*
* Issue a break 0,0. This will either enter the debugger or force a restart if
* not installed. Follow this by a H/W timeout is a robust way to insure that
* other interrupts / callbacks don't fire and reference THE old LFS context.
*/
asm("break 0,0" ::);
while (1) {}
return 0;
}
/*
* In the arg is a valid LFS module name then return the LClosure pointing to it.
* Otherwise return:
* - The Unix time that the LFS was built
* - The base address and length of the LFS
* - An array of the module names in the the LFS
*/
LUAI_FUNC int luaN_index (lua_State *L) {
int i;
int n = lua_gettop(L);
/* Return nil + the LFS base address if the LFS isn't loaded */
if(!(G(L)->ROpvmain)) {
lua_settop(L, 0);
lua_pushnil(L);
lua_pushinteger(L, (lua_Integer) flashAddr);
lua_pushinteger(L, flashAddrPhys);
return 3;
}
/* Push the LClosure of the LFS index function */
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
cl->l.p = G(L)->ROpvmain;
lua_settop(L, n+1);
setclvalue(L, L->top-1, cl);
/* Move it infront of the arguments and call the index function */
lua_insert(L, 1);
lua_call(L, n, LUA_MULTRET);
/* Return it if the response if a single value (the function) */
if (lua_gettop(L) == 1)
return 1;
lua_assert(lua_gettop(L) == 2);
/* Otherwise add the base address of the LFS, and its size bewteen the */
/* Unix time and the module list, then return all 4 params. */
lua_pushinteger(L, (lua_Integer) flashAddr);
lua_insert(L, 2);
lua_pushinteger(L, flashAddrPhys);
lua_insert(L, 3);
lua_pushinteger(L, cast(FlashHeader *, flashAddr)->flash_size);
lua_insert(L, 4);
return 5;
}
#endif

48
app/lua/lflash.h Normal file
View File

@ -0,0 +1,48 @@
/*
** lflashe.h
** See Copyright Notice in lua.h
*/
#if defined(LUA_FLASH_STORE) && !defined(lflash_h)
#define lflash_h
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
#ifdef LUA_NUMBER_INTEGRAL
# define FLASH_SIG_B1 0x02
#else
# define FLASH_SIG_B1 0x00
#endif
#ifdef LUA_PACK_TVALUES
#ifdef LUA_NUMBER_INTEGRAL
#error "LUA_PACK_TVALUES is only valid for Floating point builds"
#endif
# define FLASH_SIG_B2 0x04
#else
# define FLASH_SIG_B2 0x00
#endif
#define FLASH_SIG_ABSOLUTE 0x01
#define FLASH_SIG_IN_PROGRESS 0x08
#define FLASH_SIG (0xfafaaf50 | FLASH_SIG_B2 | FLASH_SIG_B1)
typedef lu_int32 FlashAddr;
typedef struct {
lu_int32 flash_sig; /* a stabdard fingerprint identifying an LFS image */
lu_int32 flash_size; /* Size of LFS image */
FlashAddr mainProto; /* address of main Proto in Proto hierarchy */
FlashAddr pROhash; /* address of ROstrt hash */
lu_int32 nROuse; /* number of elements in ROstrt */
int nROsize; /* size of ROstrt */
lu_int32 fill1; /* reserved */
lu_int32 fill2; /* reserved */
} FlashHeader;
LUAI_FUNC void luaN_init (lua_State *L);
LUAI_FUNC int luaN_flashSetup (lua_State *L);
LUAI_FUNC int luaN_reload_reboot (lua_State *L);
LUAI_FUNC int luaN_index (lua_State *L);
#endif

View File

@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
if (!proto_is_readonly(f)) {
if (!proto_isreadonly(f)) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo) {

View File

@ -18,9 +18,6 @@
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TValue *)*((n)-1)))
#define proto_readonly(p) l_setbit((p)->marked, READONLYBIT)
#define proto_is_readonly(p) testbit((p)->marked, READONLYBIT)
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);

View File

@ -28,6 +28,9 @@
#define GCSWEEPCOST 10
#define GCFINALIZECOST 100
#if READONLYMASK != (1<<READONLYBIT) || (defined(LUA_FLASH_STORE) && LFSMASK != (1<<LFSBIT))
#error "lgc.h and object.h out of sync on READONLYMASK / LFSMASK"
#endif
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
@ -37,7 +40,7 @@
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
#define stringmark(s) if (!isLFSobject(&(s)->tsv)) {reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT);}
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
@ -61,12 +64,18 @@
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
if (iscollectable(gkey(n)))
if (ttype(gkey(n)) != LUA_TDEADKEY && iscollectable(gkey(n)))
// The gkey is always in RAM so it can be marked as DEAD even though it
// refers to an LFS object.
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
}
static void reallymarkobject (global_State *g, GCObject *o) {
/* don't mark LFS Protos (or strings) */
if (o->gch.tt == LUA_TPROTO && isLFSobject(&(o->gch)))
return;
lua_assert(iswhite(o) && !isdead(g, o));
white2gray(o);
switch (o->gch.tt) {
@ -180,6 +189,8 @@ static int traversetable (global_State *g, Table *h) {
while (i--)
markvalue(g, &h->array[i]);
}
if (luaH_isdummy (h->node))
return weakkey || weakvalue;
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
@ -202,6 +213,8 @@ static int traversetable (global_State *g, Table *h) {
*/
static void traverseproto (global_State *g, Proto *f) {
int i;
if (isLFSobject(f))
return; /* don't traverse Protos in LFS */
if (f->source) stringmark(f->source);
for (i=0; i<f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
@ -317,7 +330,7 @@ static l_mem propagatemark (global_State *g) {
sizeof(TValue) * p->sizek +
sizeof(LocVar) * p->sizelocvars +
sizeof(TString *) * p->sizeupvalues +
(proto_is_readonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
(proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
#ifdef LUA_OPTIMIZE_DEBUG
(p->packedlineinfo ?
c_strlen(cast(char *, p->packedlineinfo))+1 :
@ -388,7 +401,10 @@ static void cleartable (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
case LUA_TPROTO:
lua_assert(!isLFSobject(&(o->gch)));
luaF_freeproto(L, gco2p(o));
break;
case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
@ -398,6 +414,7 @@ static void freeobj (lua_State *L, GCObject *o) {
break;
}
case LUA_TSTRING: {
lua_assert(!isLFSobject(&(o->gch)));
G(L)->strt.nuse--;
luaM_freemem(L, o, sizestring(gco2ts(o)));
break;
@ -420,6 +437,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
global_State *g = G(L);
int deadmask = otherwhite(g);
while ((curr = *p) != NULL && count-- > 0) {
lua_assert(!isLFSobject(&(curr->gch)) || curr->gch.tt == LUA_TTHREAD);
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
sweepwholelist(L, &gco2th(curr)->openupval);
if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
@ -538,7 +556,7 @@ static void atomic (lua_State *L) {
size_t udsize; /* total size of userdata to be finalized */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
/* traverse objects cautch by write barrier and by 'remarkupvals' */
/* traverse objects caucht by write barrier and by 'remarkupvals' */
propagateall(g);
/* remark weak tables */
g->gray = g->weak;
@ -694,10 +712,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
lua_assert(ttype(&o->gch) != LUA_TTABLE);
lua_assert(o->gch.tt != LUA_TTABLE);
/* must keep invariant? */
if (g->gcstate == GCSpropagate)
reallymarkobject(g, v); /* restore invariant */
reallymarkobject(g, v); /* Restore invariant */
else /* don't mind */
makewhite(g, o); /* mark as white just to avoid other barriers */
}

View File

@ -79,6 +79,7 @@
#define VALUEWEAKBIT 4
#define FIXEDBIT 5
#define SFIXEDBIT 6
#define LFSBIT 6
#define READONLYBIT 7
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
@ -100,6 +101,13 @@
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
#define unfixedstack(x) resetbit((x)->marked, FIXEDSTACKBIT)
#ifdef LUA_FLASH_STORE
#define isLFSobject(x) testbit((x)->marked, LFSBIT)
#define stringfix(s) if (!test2bits((s)->tsv.marked, FIXEDBIT, LFSBIT)) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#else
#define isLFSobject(x) (0)
#define stringfix(s) {l_setbit((s)->tsv.marked, FIXEDBIT);}
#endif
#define luaC_checkGC(L) { \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \

78
app/lua/linit.c Normal file
View File

@ -0,0 +1,78 @@
/*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/
#define linit_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
#if defined(LUA_CROSS_COMPILER)
BUILTIN_LIB( start_list, NULL, NULL);
BUILTIN_LIB_INIT( start_list, NULL, NULL);
#endif
extern const luaR_entry strlib[], tab_funcs[], dblib[],
co_funcs[], math_map[], syslib[];
BUILTIN_LIB_INIT( BASE, "", luaopen_base);
BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package);
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib);
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string);
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs);
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table);
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib);
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug);
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#if defined(LUA_CROSS_COMPILER)
extern const luaR_entry syslib[], iolib[];
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib);
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io);
BUILTIN_LIB( end_list, NULL, NULL);
BUILTIN_LIB_INIT( end_list, NULL, NULL);
/*
* These base addresses are internal to this module for cross compile builds
* This also exploits feature of the GCC code generator that the variables are
* emitted in either normal OR reverse order within PSECT.
*/
#define isascending(n) ((&(n ## _end_list)-&(n ## _start_list))>0)
static const luaL_Reg *lua_libs;
const luaR_table *lua_rotable;
#else
/* These base addresses are Xtensa toolchain linker constants for Firmware builds */
extern const luaL_Reg lua_libs_base[];
extern const luaR_table lua_rotable_base[];
static const luaL_Reg *lua_libs = lua_libs_base;
const luaR_table *lua_rotable = lua_rotable_base;
#endif
void luaL_openlibs (lua_State *L) {
#if defined(LUA_CROSS_COMPILER)
lua_libs = (isascending(lua_lib) ? &lua_lib_start_list : &lua_lib_end_list) + 1;
lua_rotable = (isascending(lua_rotable) ? &lua_rotable_start_list : &lua_rotable_end_list) + 1;
#endif
const luaL_Reg *lib = lua_libs;
for (; lib->name; lib++) {
if (lib->func)
{
lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
}
}
}

View File

@ -326,7 +326,7 @@ const LUA_REG_TYPE math_map[] = {
{LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
{LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
#if LUA_OPTIMIZE_MEMORY > 0
{LSTRKEY("huge"), LNUMVAL(LONG_MAX)},
{LSTRKEY("huge"), LNUMVAL(INT_MAX)},
#endif
#else
{LSTRKEY("abs"), LFUNCVAL(math_abs)},
@ -374,7 +374,7 @@ const LUA_REG_TYPE math_map[] = {
*/
#if defined LUA_NUMBER_INTEGRAL
# include "c_limits.h" /* for LONG_MAX */
# include "c_limits.h" /* for INT_MAX */
#endif
LUALIB_API int luaopen_math (lua_State *L) {
@ -383,7 +383,7 @@ LUALIB_API int luaopen_math (lua_State *L) {
#else
luaL_register(L, LUA_MATHLIBNAME, math_map);
# if defined LUA_NUMBER_INTEGRAL
lua_pushnumber(L, LONG_MAX);
lua_pushnumber(L, INT_MAX);
lua_setfield(L, -2, "huge");
# else
lua_pushnumber(L, PI);

View File

@ -613,7 +613,7 @@ static int ll_seeall (lua_State *L) {
static void setpath (lua_State *L, const char *fieldname, const char *envname,
const char *def) {
const char *path = c_getenv(envname);
const char *path = NULL; /* getenv(envname) not used in NodeMCU */;
if (path == NULL) /* no environment variable? */
lua_pushstring(L, def); /* use default */
else {

View File

@ -53,7 +53,8 @@ int luaO_fb2int (int x) {
int luaO_log2 (unsigned int x) {
static const lu_byte log_2[256] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = {
#ifdef LUA_CROSS_COMPILER
static const lu_byte log_2[256] = {
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
@ -65,10 +66,12 @@ int luaO_log2 (unsigned int x) {
};
int l = -1;
while (x >= 256) { l += 8; x >>= 8; }
#ifdef LUA_CROSS_COMPILER
return l + log_2[x];
#else
return l + byte_of_aligned_array(log_2,x);
/* Use Normalization Shift Amount Unsigned: 0x1=>31 up to 0xffffffff =>0
* See Xtensa Instruction Set Architecture (ISA) Refman P 462 */
asm volatile ("nsau %0, %1;" :"=r"(x) : "r"(x));
return 31 - x;
#endif
}
@ -103,7 +106,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
#if defined(LUA_CROSS_COMPILER)
{
long lres = strtoul(s, &endptr, 16);
#if LONG_MAX != 2147483647L
#if INT_MAX != 2147483647L
if (lres & ~0xffffffffL)
*result = cast_num(-1);
else if (lres & 0x80000000L)

View File

@ -23,10 +23,10 @@
#define NUM_TAGS (LAST_TAG+1)
/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */
#define READONLYMASK 128
#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */
#ifdef LUA_FLASH_STORE
#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */
#endif
/*
** Extra tags for non-values
*/
@ -55,86 +55,39 @@ typedef struct GCheader {
CommonHeader;
} GCheader;
#if defined(LUA_PACK_VALUE) || defined(ELUA_ENDIAN_BIG) || defined(ELUA_ENDIAN_SMALL)
# error "NodeMCU does not support the eLua LUA_PACK_VALUE and ELUA_ENDIAN defines"
#endif
/*
** Union of all Lua values
*/
#if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef union {
struct {
int _pad0;
GCObject *gc;
};
struct {
int _pad1;
void *p;
};
lua_Number n;
struct {
int _pad2;
int b;
};
} Value;
#else // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
typedef union {
GCObject *gc;
void *p;
lua_Number n;
int b;
} Value;
#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
/*
** Tagged Values
*/
#ifndef LUA_PACK_VALUE
#define TValuefields Value value; int tt
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack(4)
#endif
typedef struct lua_TValue {
TValuefields;
} TValue;
#else // #ifndef LUA_PACK_VALUE
#ifdef ELUA_ENDIAN_LITTLE
#define TValuefields union { \
struct { \
int _pad0; \
int tt_sig; \
} _ts; \
struct { \
int _pad; \
short tt; \
short sig; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {0, add_sig(LUA_TNIL)}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define TValuefields union { \
struct { \
int tt_sig; \
int _pad0; \
} _ts; \
struct { \
short sig; \
short tt; \
int _pad; \
} _t; \
Value value; \
}
#define LUA_TVALUE_NIL {add_sig(LUA_TNIL), 0}
#endif // #ifdef ELUA_ENDIAN_LITTLE
#define LUA_NOTNUMBER_SIG (-1)
#define add_sig(tt) ( 0xffff0000 | (tt) )
typedef TValuefields TValue;
#endif // #ifndef LUA_PACK_VALUE
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
#pragma pack()
#endif
/* Macros to test type */
#ifndef LUA_PACK_VALUE
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
@ -146,27 +99,11 @@ typedef TValuefields TValue;
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#else // #ifndef LUA_PACK_VALUE
#define ttisnil(o) (ttype_sig(o) == add_sig(LUA_TNIL))
#define ttisnumber(o) ((o)->_t.sig != LUA_NOTNUMBER_SIG)
#define ttisstring(o) (ttype_sig(o) == add_sig(LUA_TSTRING))
#define ttistable(o) (ttype_sig(o) == add_sig(LUA_TTABLE))
#define ttisfunction(o) (ttype_sig(o) == add_sig(LUA_TFUNCTION))
#define ttisboolean(o) (ttype_sig(o) == add_sig(LUA_TBOOLEAN))
#define ttisuserdata(o) (ttype_sig(o) == add_sig(LUA_TUSERDATA))
#define ttisthread(o) (ttype_sig(o) == add_sig(LUA_TTHREAD))
#define ttislightuserdata(o) (ttype_sig(o) == add_sig(LUA_TLIGHTUSERDATA))
#define ttisrotable(o) (ttype_sig(o) == add_sig(LUA_TROTABLE))
#define ttislightfunction(o) (ttype_sig(o) == add_sig(LUA_TLIGHTFUNCTION))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to access values */
#ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->tt)
#else // #ifndef LUA_PACK_VALUE
#define ttype(o) ((o)->_t.sig == LUA_NOTNUMBER_SIG ? (o)->_t.tt : LUA_TNUMBER)
#define ttype_sig(o) ((o)->_ts.tt_sig)
#endif // #ifndef LUA_PACK_VALUE
#define ttype(o) ((void) (o)->value, (o)->tt)
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
@ -186,24 +123,15 @@ typedef TValuefields TValue;
/*
** for internal debug only
*/
#ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
#define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
#else // #ifndef LUA_PACK_VALUE
#define checkconsistency(obj) \
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch._t.tt))
#define checkliveness(g,obj) \
lua_assert(!iscollectable(obj) || \
((ttype(obj) == (obj)->value.gc->gch._t.tt) && !isdead(g, (obj)->value.gc)))
#endif // #ifndef LUA_PACK_VALUE
/* Macros to set values */
#ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setnvalue(obj,x) \
@ -257,69 +185,10 @@ typedef TValuefields TValue;
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; o1->tt=o2->tt; \
checkliveness(G(L),o1); }
#else // #ifndef LUA_PACK_VALUE
#define setnilvalue(obj) ( ttype_sig(obj) = add_sig(LUA_TNIL) )
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); }
#define setpvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTUSERDATA);}
#define setrvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TROTABLE);}
#define setfvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->_ts.tt_sig=add_sig(LUA_TLIGHTFUNCTION);}
#define setbvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.b=(x); i_o->_ts.tt_sig=add_sig(LUA_TBOOLEAN);}
#define setsvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TSTRING); \
checkliveness(G(L),i_o); }
#define setuvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TUSERDATA); \
checkliveness(G(L),i_o); }
#define setthvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTHREAD); \
checkliveness(G(L),i_o); }
#define setclvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TFUNCTION); \
checkliveness(G(L),i_o); }
#define sethvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TTABLE); \
checkliveness(G(L),i_o); }
#define setptvalue(L,obj,x) \
{ TValue *i_o=(obj); \
i_o->value.gc=cast(GCObject *, (x)); i_o->_ts.tt_sig=add_sig(LUA_TPROTO); \
checkliveness(G(L),i_o); }
#define setobj(L,obj1,obj2) \
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
o1->value = o2->value; \
checkliveness(G(L),o1); }
#endif // #ifndef LUA_PACK_VALUE
/*
** different types of sets, according to destination
@ -340,13 +209,7 @@ typedef TValuefields TValue;
#define setobj2n setobj
#define setsvalue2n setsvalue
#ifndef LUA_PACK_VALUE
#define setttype(obj, tt) (ttype(obj) = (tt))
#else // #ifndef LUA_PACK_VALUE
/* considering it used only in lgc to set LUA_TDEADKEY */
/* we could define it this way */
#define setttype(obj, _tt) ( ttype_sig(obj) = add_sig(_tt) )
#endif // #ifndef LUA_PACK_VALUE
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
@ -367,9 +230,16 @@ typedef union TString {
} tsv;
} TString;
#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : cast(const char *, (ts) + 1))
#define svalue(o) getstr(rawtsvalue(o))
#ifdef LUA_CROSS_COMPILER
#define isreadonly(o) (0)
#else
#define isreadonly(o) ((o).marked & READONLYMASK)
#endif
#define ts_isreadonly(ts) isreadonly((ts)->tsv)
#define getstr(ts) (ts_isreadonly(ts) ? \
cast(const char *, *(const char**)((ts) + 1)) : \
cast(const char *, (ts) + 1))
#define svalue(o) getstr(rawtsvalue(o))
@ -418,6 +288,7 @@ typedef struct Proto {
lu_byte is_vararg;
lu_byte maxstacksize;
} Proto;
#define proto_isreadonly(p) isreadonly(*(p))
/* masks for new-style vararg */
@ -487,7 +358,6 @@ typedef union Closure {
** Tables
*/
#ifndef LUA_PACK_VALUE
typedef union TKey {
struct {
TValuefields;
@ -497,16 +367,6 @@ typedef union TKey {
} TKey;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL}
#else // #ifndef LUA_PACK_VALUE
typedef struct TKey {
TValue tvk;
struct {
struct Node *next; /* for chaining */
} nk;
} TKey;
#define LUA_TKEY_NIL {LUA_TVALUE_NIL}, {NULL}
#endif // #ifndef LUA_PACK_VALUE
typedef struct Node {
TValue i_val;

View File

@ -916,12 +916,11 @@ static int block_follow (int token) {
static void block (LexState *ls) {
/* block -> chunk */
FuncState *fs = ls->fs;
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt));
enterblock(fs, pbl, 0);
BlockCnt bl;
enterblock(fs, &bl, 0);
chunk(ls);
lua_assert(pbl->breaklist == NO_JUMP);
lua_assert(bl.breaklist == NO_JUMP);
leaveblock(fs);
luaM_free(ls->L,pbl);
}
@ -1081,13 +1080,13 @@ static int exp1 (LexState *ls) {
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
/* forbody -> DO block */
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt));
BlockCnt bl;
FuncState *fs = ls->fs;
int prep, endfor;
adjustlocalvars(ls, 3); /* control variables */
checknext(ls, TK_DO);
prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
enterblock(fs, pbl, 0); /* scope for declared variables */
enterblock(fs, &bl, 0); /* scope for declared variables */
adjustlocalvars(ls, nvars);
luaK_reserveregs(fs, nvars);
block(ls);
@ -1097,7 +1096,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
luaM_free(ls->L,pbl);
}

View File

@ -15,7 +15,7 @@
#undef LNILVAL
#undef LREGISTER
#if (MIN_OPT_LEVEL > 0) && (LUA_OPTIMIZE_MEMORY >= MIN_OPT_LEVEL)
#if LUA_OPTIMIZE_MEMORY >=1
#define LUA_REG_TYPE luaR_entry
#define LSTRKEY LRO_STRKEY
#define LNUMKEY LRO_NUMKEY

View File

@ -14,7 +14,7 @@
#define LUAR_FINDVALUE 1
/* Externally defined read-only table array */
extern const luaR_table lua_rotable[];
extern const luaR_table *lua_rotable;
/* Find a global "read only table" in the constant lua_rotable array */
void* luaR_findglobal(const char *name, unsigned len) {
@ -85,7 +85,7 @@ static void luaR_next_helper(lua_State *L, const luaR_entry *pentries, int pos,
if (pentries[pos].key.type != LUA_TNIL) {
/* Found an entry */
if (pentries[pos].key.type == LUA_TSTRING)
setsvalue(L, key, luaS_newro(L, pentries[pos].key.id.strkey))
setsvalue(L, key, luaS_new(L, pentries[pos].key.id.strkey))
else
setnvalue(key, (lua_Number)pentries[pos].key.id.numkey)
setobj2s(L, val, &pentries[pos].value);
@ -125,12 +125,22 @@ void luaR_getcstr(char *dest, const TString *src, size_t maxsize) {
}
}
#ifdef LUA_META_ROTABLES
/* Set in RO check depending on platform */
#if defined(LUA_CROSS_COMPILER) && defined(__CYGWIN__)
extern char __end__[];
#define IN_RO_AREA(p) ((p) < __end__)
#elif defined(LUA_CROSS_COMPILER)
extern char _edata[];
#define IN_RO_AREA(p) ((p) < _edata)
#else /* xtensa tool chain for ESP target */
extern char _irom0_text_start[];
extern char _irom0_text_end[];
#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
#endif
/* Return 1 if the given pointer is a rotable */
#ifdef LUA_META_ROTABLES
#include "compiler.h"
int luaR_isrotable(void *p) {
return RODATA_START_ADDRESS <= (char*)p && (char*)p <= RODATA_END_ADDRESS;
return IN_RO_AREA((char *)p);
}
#endif

View File

@ -4,32 +4,16 @@
#define lrotable_h
#include "lua.h"
#include "llimits.h"
#include "lobject.h"
#include "luaconf.h"
#include "lobject.h"
#include "llimits.h"
/* Macros one can use to define rotable entries */
#ifndef LUA_PACK_VALUE
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
#else // #ifndef LUA_PACK_VALUE
#define LRO_NUMVAL(v) {.value.n = v}
#ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}}
#define LRO_LUDATA(v) {{(int)v, add_sig(LUA_TLIGHTUSERDATA)}}
#define LRO_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}}
#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}}
#define LRO_LUDATA(v) {{add_sig(LUA_TLIGHTUSERDATA), (int)v}}
#define LRO_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}}
#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}}
#endif // #ifdef ELUA_ENDIAN_LITTLE
#endif // #ifndef LUA_PACK_VALUE
#define LRO_STRKEY(k) {LUA_TSTRING, {.strkey = k}}
#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}

View File

@ -13,6 +13,7 @@
#include "ldebug.h"
#include "ldo.h"
#include "lflash.h"
#include "lfunc.h"
#include "lgc.h"
#include "llex.h"
@ -72,9 +73,12 @@ static void f_luaopen (lua_State *L, void *ud) {
sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
luaN_init(L); /* optionally map RO string table */
#endif
luaT_init(L);
luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG));
stringfix(luaS_newliteral(L, MEMERRMSG));
g->GCthreshold = 4*g->totalbytes;
}
@ -191,6 +195,12 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->memlimit = EGC_INITIAL_MEMLIMIT;
#else
g->memlimit = 0;
#endif
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
g->ROstrt.size = 0;
g->ROstrt.nuse = 0;
g->ROstrt.hash = NULL;
g->ROpvmain = NULL;
#endif
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {

View File

@ -94,6 +94,10 @@ typedef struct global_State {
UpVal uvhead; /* head of double-linked list of all open upvalues */
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
TString *tmname[TM_N]; /* array with tag-method names */
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
stringtable ROstrt; /* Flash-based hash table for RO strings */
Proto *ROpvmain; /* Flash-based Proto main */
#endif
} global_State;

View File

@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
tb = &G(L)->strt;
if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
ts = cast(TString *, luaM_malloc(L, readonly ? sizeof(char**)+sizeof(TString) : (l+1)*sizeof(char)+sizeof(TString)));
ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (readonly ? sizeof(char**) : (l+1)*sizeof(char))));
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.marked = luaC_white(G(L));
@ -71,7 +71,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
((char *)(ts+1))[l] = '\0'; /* ending 0 */
} else {
*(char **)(ts+1) = (char *)str;
luaS_readonly(ts);
l_setbit((ts)->tsv.marked, READONLYBIT);
}
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
@ -80,14 +80,32 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
return ts;
}
#ifdef LUA_CROSS_COMPILER
#define IN_RO_AREA(p) (0)
#else /* xtensa tool chain for ESP */
extern char _irom0_text_start[];
extern char _irom0_text_end[];
#define IN_RO_AREA(p) ((p) >= _irom0_text_start && (p) <= _irom0_text_end)
#endif
static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, int readonly) {
int lua_is_ptr_in_ro_area(const char *p) {
return IN_RO_AREA(p);
}
/*
* The string algorithm has been modified to be LFS-friendly. The previous eLua
* algo used the address of the string was in flash and the string was >4 bytes
* This creates miminal savings and prevents the use of LFS based strings
*/
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
GCObject *o;
unsigned int h = cast(unsigned int, l); /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
@ -98,35 +116,27 @@ static TString *luaS_newlstr_helper (lua_State *L, const char *str, size_t l, in
return ts;
}
}
return newlstr(L, str, l, h, readonly); /* not found */
}
static int lua_is_ptr_in_ro_area(const char *p) {
#ifdef LUA_CROSS_COMPILER
return 0;
#else
#include "compiler.h"
return p >= RODATA_START_ADDRESS && p <= RODATA_END_ADDRESS;
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
/*
* The RAM strt is searched first since RAM access is faster tham Flash access.
* If a miss, then search the RO string table.
*/
if (G(L)->ROstrt.hash) {
for (o = G(L)->ROstrt.hash[lmod(h, G(L)->ROstrt.size)];
o != NULL;
o = o->gch.next) {
TString *ts = rawgco2ts(o);
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
return ts;
}
}
}
#endif
}
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
// If the pointer is in a read-only memory and the string is at least 4 chars in length,
// create it as a read-only string instead
if(lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) && l == c_strlen(str))
return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING);
else
return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING);
}
LUAI_FUNC TString *luaS_newrolstr (lua_State *L, const char *str, size_t l) {
if(l+1 > sizeof(char**) && l == c_strlen(str))
return luaS_newlstr_helper(L, str, l, LUAS_READONLY_STRING);
else // no point in creating a RO string, as it would actually be larger
return luaS_newlstr_helper(L, str, l, LUAS_REGULAR_STRING);
/* New additions to the RAM strt are tagged as readonly if the string address
* is in the CTEXT segment (target only, not luac.cross) */
int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) &&
l == c_strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING);
return newlstr(L, str, l, h, readonly); /* not found */
}

View File

@ -13,22 +13,16 @@
#include "lstate.h"
#define sizestring(s) (sizeof(union TString)+(luaS_isreadonly(s) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizestring(s) (sizeof(union TString)+(testbit((s)->marked, READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
#define sizeudata(u) (sizeof(union Udata)+(u)->len)
#define luaS_new(L, s) (luaS_newlstr(L, s, c_strlen(s)))
#define luaS_newro(L, s) (luaS_newrolstr(L, s, c_strlen(s)))
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
#define luaS_readonly(s) l_setbit((s)->tsv.marked, READONLYBIT)
#define luaS_isreadonly(s) testbit((s)->marked, READONLYBIT)
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_newrolstr (lua_State *L, const char *str, size_t l);
#endif

View File

@ -445,7 +445,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
int oldasize = t->sizearray;
if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize);
resize_hashpart(L, t, nhsize);
if (t->node != dummynode || nhsize>0)
resize_hashpart(L, t, nhsize);
if (nasize < oldasize) { /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing slice */
@ -749,12 +750,12 @@ int luaH_getn_ro (void *t) {
return len;
}
#if defined(LUA_DEBUG)
int luaH_isdummy (Node *n) { return n == dummynode; }
#if defined(LUA_DEBUG)
Node *luaH_mainposition (const Table *t, const TValue *key) {
return mainposition(t, key);
}
int luaH_isdummy (Node *n) { return n == dummynode; }
#endif

View File

@ -34,11 +34,9 @@ LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
LUAI_FUNC int luaH_next_ro (lua_State *L, void *t, StkId key);
LUAI_FUNC int luaH_getn (Table *t);
LUAI_FUNC int luaH_getn_ro (void *t);
LUAI_FUNC int luaH_isdummy (Node *n);
#if defined(LUA_DEBUG)
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
LUAI_FUNC int luaH_isdummy (Node *n);
#endif
#endif

View File

@ -137,7 +137,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) {
if (!lua_isstring(L, -1))
luaL_error(L, "invalid value (%s) at index %d in table for "
LUA_QL("concat"), luaL_typename(L, -1), i);
luaL_addvalue(b);
luaL_addvalue(b);
}

View File

@ -14,6 +14,7 @@
#include "lobject.h"
#include "lstate.h"
#include "lgc.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
@ -39,7 +40,7 @@ void luaT_init (lua_State *L) {
int i;
for (i=0; i<TM_N; i++) {
G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
luaS_fix(G(L)->tmname[i]); /* never collect these names */
stringfix(G(L)->tmname[i]); /* never collect these names */
}
}

View File

@ -13,6 +13,7 @@
#include "user_version.h"
#include "driver/readline.h"
#include "driver/uart.h"
#include "platform.h"
#define lua_c
@ -21,54 +22,16 @@
#include "lauxlib.h"
#include "lualib.h"
#include "legc.h"
#ifdef LUA_FLASH_STORE
#include "lflash.h"
#endif
#include "os_type.h"
lua_State *globalL = NULL;
lua_Load gLoad;
static lua_Load gLoad;
static const char *progname = LUA_PROGNAME;
#if 0
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
lua_sethook(L, NULL, 0, 0);
luaL_error(L, "interrupted!");
}
static void laction (int i) {
// signal(i, SIG_DFL);
/* if another SIGINT happens before lstop,
terminate process (default action) */
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
static void print_usage (void) {
#if defined(LUA_USE_STDIO)
c_fprintf(c_stderr,
#else
luai_writestringerror(
#endif
"usage: %s [options] [script [args]].\n"
"Available options are:\n"
" -e stat execute string " LUA_QL("stat") "\n"
" -l name require library " LUA_QL("name") "\n"
" -m limit set memory limit. (units are in Kbytes)\n"
" -i enter interactive mode after executing " LUA_QL("script") "\n"
" -v show version information\n"
" -- stop handling options\n"
" - execute stdin and stop handling options\n"
,
progname);
#if defined(LUA_USE_STDIO)
c_fflush(c_stderr);
#endif
}
#endif
static void l_message (const char *pname, const char *msg) {
#if defined(LUA_USE_STDIO)
if (pname) c_fprintf(c_stderr, "%s: ", pname);
@ -154,17 +117,11 @@ static int getargs (lua_State *L, char **argv, int n) {
return narg;
}
#if 0
static int dofile (lua_State *L, const char *name) {
int status = luaL_loadfile(L, name) || docall(L, 0, 1);
return report(L, status);
}
#else
static int dofsfile (lua_State *L, const char *name) {
int status = luaL_loadfsfile(L, name) || docall(L, 0, 1);
return report(L, status);
}
#endif
static int dostring (lua_State *L, const char *s, const char *name) {
int status = luaL_loadbuffer(L, s, c_strlen(s), name) || docall(L, 0, 1);
@ -201,92 +158,6 @@ static int incomplete (lua_State *L, int status) {
return 0; /* else... */
}
#if 0
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
if (lua_readline(L, b, prmt) == 0)
return 0; /* no input */
l = c_strlen(b);
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
b[l-1] = '\0'; /* remove it */
if (firstline && b[0] == '=') /* first line starts with `=' ? */
lua_pushfstring(L, "return %s", b+1); /* change it to `return' */
else
lua_pushstring(L, b);
lua_freeline(L, b);
return 1;
}
static int loadline (lua_State *L) {
int status;
lua_settop(L, 0);
if (!pushline(L, 1))
return -1; /* no input */
for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
if (!incomplete(L, status)) break; /* cannot try to add lines? */
if (!pushline(L, 0)) /* no more input? */
return -1;
lua_pushliteral(L, "\n"); /* add a new line... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
}
lua_saveline(L, 1);
lua_remove(L, 1); /* remove line */
return status;
}
static void dotty (lua_State *L) {
int status;
const char *oldprogname = progname;
progname = NULL;
while ((status = loadline(L)) != -1) {
if (status == 0) status = docall(L, 0, 0);
report(L, status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname, lua_pushfstring(L,
"error calling " LUA_QL("print") " (%s)",
lua_tostring(L, -1)));
}
}
lua_settop(L, 0); /* clear stack */
#if defined(LUA_USE_STDIO)
c_fputs("\n", c_stdout);
c_fflush(c_stdout);
#else
luai_writeline();
#endif
progname = oldprogname;
}
static int handle_script (lua_State *L, char **argv, int n) {
int status;
const char *fname;
int narg = getargs(L, argv, n); /* collect arguments */
lua_setglobal(L, "arg");
fname = argv[n];
if (c_strcmp(fname, "-") == 0 && c_strcmp(argv[n-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
lua_insert(L, -(narg+1));
if (status == 0)
status = docall(L, narg, 0);
else
lua_pop(L, narg);
return report(L, status);
}
#endif
/* check that argument has no extra characters at the end */
#define notail(x) {if ((x)[2] != '\0') return -1;}
@ -364,17 +235,16 @@ static int runargs (lua_State *L, char **argv, int n) {
}
static int handle_luainit (lua_State *L) {
const char *init = c_getenv(LUA_INIT);
if (init == NULL) return 0; /* status OK */
else if (init[0] == '@')
#if 0
return dofile(L, init+1);
#else
return dofsfile(L, init+1);
#ifndef LUA_INIT_STRING
#define LUA_INIT_STRING "@init.lua"
#endif
static int handle_luainit (lua_State *L) {
const char *init = LUA_INIT_STRING;
if (init[0] == '@')
return dofsfile(L, init+1);
else
return dostring(L, init, "=" LUA_INIT);
return dostring(L, init, LUA_INIT);
}
@ -397,40 +267,18 @@ static int pmain (lua_State *L) {
lua_gc(L, LUA_GCRESTART, 0);
print_version(L);
s->status = handle_luainit(L);
#if 0
if (s->status != 0) return 0;
#endif
script = collectargs(argv, &has_i, &has_v, &has_e);
if (script < 0) { /* invalid args? */
#if 0
print_usage();
#endif
s->status = 1;
return 0;
}
// if (has_v) print_version();
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
if (s->status != 0) return 0;
#if 0
if (script)
s->status = handle_script(L, argv, script);
if (s->status != 0) return 0;
if (has_i)
dotty(L);
else if (script == 0 && !has_e && !has_v) {
if (lua_stdin_is_tty()) {
print_version();
dotty(L);
}
else dofile(L, NULL); /* executes stdin as a file */
}
#endif
return 0;
}
static void dojob(lua_Load *load);
static bool readline(lua_Load *load);
char line_buffer[LUA_MAXINPUT];
#ifdef LUA_RPC
int main (int argc, char **argv) {
@ -439,6 +287,13 @@ int lua_main (int argc, char **argv) {
#endif
int status;
struct Smain s;
#if defined(NODE_DEBUG) && defined(DEVELOPMENT_USE_GDB) && \
defined(DEVELOPMENT_BREAK_ON_STARTUP_PIN) && DEVELOPMENT_BREAK_ON_STARTUP_PIN > 0
platform_gpio_mode( DEVELOPMENT_BREAK_ON_STARTUP_PIN, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP );
lua_assert(platform_gpio_read(DEVELOPMENT_BREAK_ON_STARTUP_PIN)); // Break if pin pulled low
#endif
lua_State *L = lua_open(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
@ -446,30 +301,44 @@ int lua_main (int argc, char **argv) {
}
s.argc = argc;
s.argv = argv;
status = lua_cpcall(L, &pmain, &s);
report(L, status);
gLoad.L = L;
gLoad.firstline = 1;
gLoad.done = 0;
gLoad.line = line_buffer;
gLoad.line = c_malloc(LUA_MAXINPUT);
gLoad.len = LUA_MAXINPUT;
gLoad.line_position = 0;
gLoad.prmt = get_prompt(L, 1);
dojob(&gLoad);
NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
NODE_DBG("Heap size:%d.\n",system_get_free_heap_size());
legc_set_mode( L, EGC_ALWAYS, 4096 );
// legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
// lua_close(L);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
int lua_put_line(const char *s, size_t l) {
if (s == NULL || ++l > LUA_MAXINPUT || gLoad.line_position > 0)
return 0;
c_memcpy(gLoad.line, s, l);
gLoad.line[l] = '\0';
gLoad.line_position = l;
gLoad.done = 1;
NODE_DBG("Get command: %s\n", gLoad.line);
return 1;
}
void lua_handle_input (bool force)
{
while (gLoad.L && (force || readline (&gLoad)))
{
while (gLoad.L && (force || readline (&gLoad))) {
NODE_DBG("Handle Input: first=%u, pos=%u, len=%u, actual=%u, line=%s\n", gLoad.firstline,
gLoad.line_position, gLoad.len, c_strlen(gLoad.line), gLoad.line);
dojob (&gLoad);
force = false;
}

View File

@ -173,7 +173,6 @@ LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushrolstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);

View File

@ -31,6 +31,7 @@
#define c_freopen freopen
#define c_getc getc
#define c_getenv getenv
#define c_malloc malloc
#define c_memcmp memcmp
#define c_memcpy memcpy
#define c_printf printf
@ -56,9 +57,10 @@
#define c_strrchr strrchr
#define c_strstr strstr
double c_strtod(const char *__n, char **__end_PTR);
#define c_strtoul strtoul
#define c_ungetc ungetc
#define c_strtol strtol
#define c_strtoul strtoul
#define dbg_printf printf
#else
#define C_HEADER_ASSERT "c_assert.h"

View File

@ -0,0 +1,92 @@
#
# This Make file is called from the core Makefile hierarchy which is a hierarchical
# make which uses parent callbacks to implement inheritance. However if luac_cross
# build stands outside this it uses the host toolchain to implement a separate
# host build of the luac.cross image.
#
.NOTPARALLEL:
CCFLAGS:= -I.. -I../../include -I../../../include -I ../../libc
LDFLAGS:= -L$(SDK_DIR)/lib -L$(SDK_DIR)/ld -lm -ldl -Wl,-Map=mapfile
CCFLAGS += -Wall
DEFINES += -DLUA_CROSS_COMPILER -DLUA_OPTIMIZE_MEMORY=2
TARGET = host
ifeq ($(FLAVOR),debug)
CCFLAGS += -O0 -g
TARGET_LDFLAGS += -O0 -g
else
FLAVOR = release
CCFLAGS += -O2
TARGET_LDFLAGS += -O2
endif
LUACSRC := luac.c lflashimg.c liolib.c loslib.c print.c
LUASRC := lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c \
ldo.c ldump.c lfunc.c lgc.c linit.c llex.c \
lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c lparser.c \
lrotable.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \
ltm.c lundump.c lvm.c lzio.c
LIBCSRC := c_stdlib.c
#
# This relies on the files being unique on the vpath
#
SRC := $(LUACSRC) $(LUASRC) $(LIBCSRC)
vpath %.c .:..:../../libc
ODIR := .output/$(TARGET)/$(FLAVOR)/obj
OBJS := $(SRC:%.c=$(ODIR)/%.o)
DEPS := $(SRC:%.c=$(ODIR)/%.d)
CFLAGS = $(CCFLAGS) $(DEFINES) $(EXTRA_CCFLAGS) $(STD_CFLAGS) $(INCLUDES)
DFLAGS = $(CCFLAGS) $(DDEFINES) $(EXTRA_CCFLAGS) $(STD_CFLAGS) $(INCLUDES)
CC := $(WRAPCC) gcc
ECHO := echo
BUILD_TYPE := $(shell $(CC) $(EXTRA_CCFLAGS) -E -dM - <../../../app/include/user_config.h | grep LUA_NUMBER_INTEGRAL | wc -l)
ifeq ($(BUILD_TYPE),0)
IMAGE := ../../../luac.cross
else
IMAGE := ../../../luac.cross.int
endif
.PHONY: test clean all
all: $(DEPS) $(IMAGE)
$(IMAGE) : $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
test :
@echo CC: $(CC)
@echo SRC: $(SRC)
@echo OBJS: $(OBJS)
@echo DEPS: $(DEPS)
@echo IMAGE: $(IMAGE)
clean :
$(RM) -r $(ODIR)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
$(ODIR)/%.o: %.c
@mkdir -p $(ODIR);
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<
$(ODIR)/%.d: %.c
@mkdir -p $(ODIR);
@echo DEPEND: $(CC) -M $(CFLAGS) $<
@set -e; rm -f $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\.o\)[ :]*,$(ODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$

View File

@ -0,0 +1,421 @@
/*
** lflashimg.c
** Dump a compiled Proto hiearchy to a RO (FLash) image file
** See Copyright Notice in lua.h
*/
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_CTYPE
#include C_HEADER_STDIO
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#define lflashimg_c
#define LUA_CORE
#include "lobject.h"
#include "lstring.h"
#undef LUA_FLASH_STORE
#define LUA_FLASH_STORE
#include "lflash.h"
//#define LOCAL_DEBUG
#if INT_MAX != 2147483647
# error "luac.cross requires C toolchain with 4 byte word size"
#endif
#define WORDSIZE ((int) sizeof(int))
#define ALIGN(s) (((s)+(WORDSIZE-1)) & (-(signed) WORDSIZE))
#define WORDSHIFT 2
typedef unsigned int uint;
#define FLASH_WORDS(t) (sizeof(t)/sizeof(FlashAddr))
/*
*
* This dumper is a variant of the standard ldump, in that instead of producing a
* binary loader format that lundump can load, it produces an image file that can be
* directly mapped or copied into addressable memory. The typical application is on
* small memory IoT devices which support programmable flash storage such as the
* ESP8266. A 64 Kb LFS image has 16Kb words and will enable all program-related
* storage to be accessed directly from flash, leaving the RAM for true R/W
* application data.
*
* The start address of the Lua Flash Store (LFS) is build-dependent, and the cross
* compiler '-a' option allows the developer to fix the LFS at a defined flash memory
* address. Alternatively and by default the cross compilation adopts a position
* independent image format, which permits the on-device image loader to load the LFS
* image at an appropriate base within the flash address space. As all objects in the
* LFS can be treated as multiples of 4-byte words, also all address fields are both
* word aligned, and any address references within the LFS are also word-aligned,
* such addresses are stored in a special format, where each PI address is two
* 16-bit unsigned offsets:
*
* Bits 0-15 is the offset into the LFS that this address refers to
* Bits 16-31 is the offset linking to the PIC next address.
*
* Hence the LFS can be up to 256Kb in length and the flash loader can use the forward
* links to chain down PI address from the mainProto address at offet 3 to all image
* addresses during load and convert them to the corresponding correct absolute memory
* addresses. This reloation process is skipped for absolute addressed images (which
* are identified by the FLASH_SIG_ABSOLUTE bit setting in the flash signature.
*
* The flash image has a standard header detailed in lflash.h
*
* Note that luac.cross may be compiled on any little-endian machine with 32 or 64 bit
* word length so Flash addresses can't be handled as standard C pointers as size_t
* and int may not have the same size. Hence addresses with the must be declared as
* the FlashAddr type rather than typed C pointers and must be accessed through macros.
*
* ALso note that image built with a given LUA_PACK_TVALUES / LUA_NUNBER_INTEGRAL
* combination must be loaded into a corresponding firmware build. Hence these
* configuration options are also included in the FLash Signature.
*
* The Flash image is assembled up by first building the RO stringtable containing
* all strings used in the compiled proto hierarchy. This is followed by the Protos.
*
* The storage is allocated bottom up using a serial allocator and the algortihm for
* building the image essentially does a bottom-uo serial enumeration so that any
* referenced storage has already been allocated in the image, and therefore (with the
* exception of the Flash Header) all pointer references are backwards.
*
* As addresses are 4 byte on the target and either 4 or (typically) 8 bytes on the
* host so any structures containing address fields (TStrings, TValues, Protos, other
* address vectors) need repacking.
*/
typedef struct flashts { /* This is the fixed 32-bit equivalent of TString */
FlashAddr next;
lu_byte tt;
lu_byte marked;
int hash;
int len;
} FlashTS;
#ifndef LUA_MAX_FLASH_SIZE
#define LUA_MAX_FLASH_SIZE 0x10000 //in words
#endif
static uint curOffset = 0;
static uint flashImage[LUA_MAX_FLASH_SIZE];
static unsigned char flashAddrTag[LUA_MAX_FLASH_SIZE/WORDSIZE];
#define fatal luac_fatal
extern void __attribute__((noreturn)) luac_fatal(const char* message);
#ifdef LOCAL_DEBUG
#define DBG_PRINT(...) printf(__VA_ARGS__)
#else
#define DBG_PRINT(...) ((void)0)
#endif
/*
* Serial allocator. Throw a luac-style out of memory error is allocaiton fails.
*/
static void *flashAlloc(lua_State* L, size_t n) {
void *p = (void *)(flashImage + curOffset);
curOffset += ALIGN(n)>>WORDSHIFT;
if (curOffset > LUA_MAX_FLASH_SIZE) {
fatal("Out of Flash memmory");
}
return p;
}
/*
* Convert an absolute address pointing inside the flash image to offset form.
* This macro form also takes the lvalue destination so that this can be tagged
* as a relocatable address.
*/
#define toFlashAddr(l, pd, s) _toFlashAddr(l, &(pd), s)
static void _toFlashAddr(lua_State* L, FlashAddr *a, void *p) {
uint doffset = cast(char *, a) - cast(char *,flashImage);
lua_assert(!(doffset & (WORDSIZE-1)));
doffset >>= WORDSHIFT;
lua_assert(doffset <= curOffset);
if (p) {
uint poffset = cast(char *, p) - cast(char *,flashImage);
lua_assert(!(poffset & (WORDSIZE-1)));
poffset >>= WORDSHIFT;
lua_assert(poffset <= curOffset);
flashImage[doffset] = poffset; // Set the pointer to the offset
flashAddrTag[doffset] = 1; // And tag as an address
} else { // Special case for NULL pointer
flashImage[doffset] = 0;
}
}
/*
* Convert an image address in offset form back to (host) absolute form
*/
static void *fromFashAddr(FlashAddr a) {
return a ? cast(void *, flashImage + a) : NULL;
}
/*
* Add a TS found in the Proto Load to the table at the ToS
*/
static void addTS(lua_State *L, TString *ts) {
lua_assert(ts->tsv.tt==LUA_TSTRING);
lua_pushnil(L);
setsvalue(L, L->top-1, ts);
lua_pushinteger(L, 1);
lua_rawset(L, -3);
DBG_PRINT("Adding string: %s\n",getstr(ts));
}
/*
* Enumerate all of the Protos in the Proto hiearchy and scan contents to collect
* all referenced strings in a Lua Array at ToS.
*/
static void scanProtoStrings(lua_State *L, const Proto* f) {
/* Table at L->Top[-1] is used to collect the strings */
int i;
if (f->source)
addTS(L, f->source);
#ifdef LUA_OPTIMIZE_DEBUG
if (f->packedlineinfo)
addTS(L, luaS_new(L, cast(const char *, f->packedlineinfo)));
#endif
for (i = 0; i < f->sizek; i++) {
if (ttisstring(f->k + i))
addTS(L, rawtsvalue(f->k + i));
}
for (i = 0; i < f->sizeupvalues; i++) addTS(L, f->upvalues[i]);
for (i = 0; i < f->sizelocvars; i++) addTS(L, f->locvars[i].varname);
for (i = 0; i < f->sizep; i++) scanProtoStrings(L, f->p[i]);
}
/*
* Use the collected strings table to build the new ROstrt in the Flash Image
*
* The input is an array of {"SomeString" = 1, ...} on the ToS.
* The output is an array of {"SomeString" = FlashOffset("SomeString"), ...} on ToS
*/
static void createROstrt(lua_State *L, FlashHeader *fh) {
/* Table at L->Top[-1] on input is hash used to collect the strings */
/* Count the number of strings. Can't use objlen as this is a hash */
fh->nROuse = 0;
lua_pushnil(L); /* first key */
while (lua_next(L, -2) != 0) {
fh->nROuse++;
DBG_PRINT("Found: %s\n",getstr(rawtsvalue(L->top-2)));
lua_pop(L, 1); // dump the value
}
fh->nROsize = 2<<luaO_log2(fh->nROuse);
FlashAddr *hashTab = flashAlloc(L, fh->nROsize * WORDSIZE);
toFlashAddr(L, fh->pROhash, hashTab);
/* Now iterate over the strings to be added to the RO string table and build it */
lua_newtable(L); // add output table
lua_pushnil(L); // First key
while (lua_next(L, -3) != 0) { // replaces key, pushes value
TString *ts = rawtsvalue(L->top - 2); // key.ts
const char *p = getstr(ts); // C string of key
uint hash = ts->tsv.hash; // hash of key
size_t len = ts->tsv.len; // and length
DBG_PRINT("2nd pass: %s\n",p);
FlashAddr *e = hashTab + lmod(hash, fh->nROsize);
FlashTS *last = cast(FlashTS *, fromFashAddr(*e));
FlashTS *fts = cast(FlashTS *, flashAlloc(L, sizeof(FlashTS)));
toFlashAddr(L, *e, fts); // add reference to TS to lookup vector
toFlashAddr(L, fts->next, last); // and chain to previous entry if any
fts->tt = LUA_TSTRING; // Set as String
fts->marked = bitmask(LFSBIT); // LFS string with no Whitebits set
fts->hash = hash; // add hash
fts->len = len; // and length
memcpy(flashAlloc(L, ALIGN(len+1)), p, ALIGN(len+1)); // copy string
// include the trailing null char
lua_pop(L, 1); // Junk the value
lua_pushvalue(L, -1); // Dup the key as rawset dumps its copy
lua_pushinteger(L, cast(FlashAddr*,fts)-flashImage); // Value is new TS offset.
lua_rawset(L, -4); // Add to new table
}
/* At this point the old hash is done to derefence for GC */
lua_remove(L, -2);
}
/*
* Convert a TString reference in the host G(L)->strt entry into the corresponding
* TString address in the flashImage using the lookup table at ToS
*/
static void *resolveTString(lua_State* L, TString *s) {
if (!s)
return NULL;
lua_pushnil(L);
setsvalue(L, L->top-1, s);
lua_rawget(L, -2);
lua_assert(!lua_isnil(L, -1));
void *ts = fromFashAddr(lua_tointeger(L, -1));
lua_pop(L, 1);
return ts;
}
/*
* In order to simplify repacking of structures from the host format to that target
* format, this simple copy routine is data-driven by a simple format specifier.
* n Number of consecutive records to be processed
* fmt A string of A, I, S, V specifiers spanning the record.
* src Source of record
* returns Address of destination record
*/
#if defined(LUA_PACK_TVALUES)
#define TARGET_TV_SIZE (sizeof(lua_Number)+sizeof(lu_int32))
#else
#define TARGET_TV_SIZE (2*sizeof(lua_Number))
#endif
static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
/* ToS is the string address mapping table */
if (n == 0)
return NULL;
int i, recsize;
void *newts;
/* A bit of a botch because fmt is either "V" or a string of WORDSIZE specifiers */
/* The size 8 / 12 / 16 bytes for integer builds, packed TV and default TVs resp */
if (fmt[0]=='V') {
lua_assert(fmt[1] == 0); /* V formats must be singetons */
recsize = TARGET_TV_SIZE;
} else {
recsize = WORDSIZE * strlen(fmt);
}
uint *d = cast(uint *, flashAlloc(L, n * recsize));
uint *dest = d;
uint *s = cast(uint *, src);
for (i = 0; i < n; i++) {
const char *p = fmt;
while (*p) {
/* All input address types (A,S,V) are aligned to size_t boundaries */
if (*p != 'I' && ((size_t)s)&(sizeof(size_t)-1))
s++;
switch (*p++) {
case 'A':
toFlashAddr(L, *d, *cast(void**, s));
s += FLASH_WORDS(size_t);
d++;
break;
case 'I':
*d++ = *s++;
break;
case 'S':
newts = resolveTString(L, *cast(TString **, s));
toFlashAddr(L, *d, newts);
s += FLASH_WORDS(size_t);
d++;
break;
case 'V':
/* This code has to work for both Integer and Float build variants */
memset(d, 0, TARGET_TV_SIZE);
TValue *sv = cast(TValue *, s);
if (ttisstring(sv)) {
toFlashAddr(L, *d, resolveTString(L, rawtsvalue(sv)));
} else { /* non-collectable types all of size lua_Number */
lua_assert(!iscollectable(sv));
*cast(lua_Number*,d) = *cast(lua_Number*,s);
}
*cast(int *,cast(lua_Number*,d)+1) = ttype(sv);
s += FLASH_WORDS(TValue);
d += TARGET_TV_SIZE/WORDSIZE;
break;
default:
lua_assert (0);
}
}
}
return dest;
}
/* The debug optimised version has a different Proto layout */
#ifdef LUA_OPTIMIZE_DEBUG
#define PROTO_COPY_MASK "AIAAAAAASIIIIIIIAI"
#else
#define PROTO_COPY_MASK "AIAAAAAASIIIIIIIIAI"
#endif
/*
* Do the actual prototype copy.
*/
static void *functionToFlash(lua_State* L, const Proto* orig) {
Proto f;
int i;
memcpy (&f, orig, sizeof(Proto));
f.gclist = NULL;
f.next = NULL;
l_setbit(f.marked, LFSBIT); /* OK to set the LFSBIT on a stack-cloned copy */
if (f.sizep) { /* clone included Protos */
Proto **p = luaM_newvector(L, f.sizep, Proto *);
for (i=0; i<f.sizep; i++)
p[i] = cast(Proto *, functionToFlash(L, f.p[i]));
f.p = cast(Proto **, flashCopy(L, f.sizep, "A", p));
luaM_freearray(L, p, f.sizep, Proto *);
}
f.k = cast(TValue *, flashCopy(L, f.sizek, "V", f.k));
f.code = cast(Instruction *, flashCopy(L, f.sizecode, "I", f.code));
#ifdef LUA_OPTIMIZE_DEBUG
if (f.packedlineinfo) {
TString *ts=luaS_new(L, cast(const char *,f.packedlineinfo));
f.packedlineinfo = cast(unsigned char *, resolveTString(L, ts)) + sizeof (FlashTS);
}
#else
f.lineinfo = cast(int *, flashCopy(L, f.sizelineinfo, "I", f.lineinfo));
#endif
f.locvars = cast(struct LocVar *, flashCopy(L, f.sizelocvars, "SII", f.locvars));
f.upvalues = cast(TString **, flashCopy(L, f.sizeupvalues, "S", f.upvalues));
return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f));
}
/*
* Scan through the tagged addresses. This operates in one of two modes.
* - If address is non-zero then the offset is converted back into an absolute
* mapped flash address using the specified address base.
*
* - If the address is zero then form a form linked chain with the upper 16 bits
* the link to the last offset. As the scan is backwards, this 'last' address
* becomes forward reference for the on-chip LFS loader.
*/
void linkAddresses(lu_int32 address){
int i, last = 0;
for (i = curOffset-1 ; i >= 0; i--) {
if (flashAddrTag[i]) {
lua_assert(flashImage[i]<curOffset);
if (address) {
flashImage[i] = 4*flashImage[i] + address;
} else {
flashImage[i] |= last<<16;
last = i;
}
}
}
}
uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
void* data, int strip, lu_int32 address) {
// parameter strip is ignored for now
lua_newtable(L);
FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader)));
scanProtoStrings(L, main);
createROstrt(L, fh);
toFlashAddr(L, fh->mainProto, functionToFlash(L, main));
fh->flash_sig = FLASH_SIG + (address ? FLASH_SIG_ABSOLUTE : 0);
fh->flash_size = curOffset*WORDSIZE;
linkAddresses(address);
lua_unlock(L);
int status = w(L, flashImage, curOffset * sizeof(uint), data);
lua_lock(L);
return status;
}

View File

@ -5,14 +5,14 @@
*/
// #include "c_errno.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
#include "vfs.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define liolib_c
#define LUA_LIB
#define LUA_OPTIMIZE_MEMORY 2
#include "lua.h"
@ -20,26 +20,21 @@
#include "lualib.h"
#include "lrotable.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
#define IO_STDERR 0
#if LUA_OPTIMIZE_MEMORY != 2
#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_ENVIRONINDEX, f)
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_ENVIRONINDEX, f)
#else
#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX, liolib_keys[f])
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[f])
#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
/* "Pseudo-random" keys for the registry */
static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int)&luaL_argerror};
#endif
static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror};
static const char *const fnames[] = {"input", "output"};
static int pushresult (lua_State *L, int i, const char *filename) {
int en = vfs_ferrno(0); /* calls to Lua API may change this value */
int en = errno; /* calls to Lua API may change this value */
if (i) {
lua_pushboolean(L, 1);
return 1;
@ -47,9 +42,9 @@ static int pushresult (lua_State *L, int i, const char *filename) {
else {
lua_pushnil(L);
if (filename)
lua_pushfstring(L, "%s: err(%d)", filename, en);
lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
lua_pushfstring(L, "err(%d)", en);
lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, en);
return 3;
}
@ -57,12 +52,12 @@ static int pushresult (lua_State *L, int i, const char *filename) {
static void fileerror (lua_State *L, int arg, const char *filename) {
lua_pushfstring(L, "%s: err(%d)", filename, vfs_ferrno(0));
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
luaL_argerror(L, arg, lua_tostring(L, -1));
}
#define tofilep(L) ((int *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
static int io_type (lua_State *L) {
@ -72,7 +67,7 @@ static int io_type (lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
lua_pushnil(L); /* not a file */
else if (*((int *)ud) < FS_OPEN_OK)
else if (*((FILE **)ud) == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
@ -80,9 +75,9 @@ static int io_type (lua_State *L) {
}
static int tofile (lua_State *L) {
int *f = tofilep(L);
if (*f < FS_OPEN_OK)
static FILE *tofile (lua_State *L) {
FILE **f = tofilep(L);
if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
return *f;
}
@ -94,91 +89,52 @@ static int tofile (lua_State *L) {
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
static int *newfile (lua_State *L) {
int *pf = (int *)lua_newuserdata(L, sizeof(int));
*pf = FS_OPEN_OK - 1; /* file handle is currently `closed' */
static FILE **newfile (lua_State *L) {
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
*pf = NULL; /* file handle is currently `closed' */
luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
return pf;
}
#if LUA_OPTIMIZE_MEMORY != 2
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static int io_noclose (lua_State *L) {
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
#if 0
/*
** function to close 'popen' files
*/
static int io_pclose (lua_State *L) {
int *p = tofilep(L);
int ok = lua_pclose(L, *p);
*p = FS_OPEN_OK - 1;
return pushresult(L, ok, NULL);
}
#endif
/*
** function to close regular files
*/
static int io_fclose (lua_State *L) {
int *p = tofilep(L);
int ok = (vfs_close(*p) == 0);
*p = FS_OPEN_OK - 1;
return pushresult(L, ok, NULL);
}
#endif
static int aux_close (lua_State *L) {
#if LUA_OPTIMIZE_MEMORY != 2
lua_getfenv(L, 1);
lua_getfield(L, -1, "__close");
return (lua_tocfunction(L, -1))(L);
#else
int *p = tofilep(L);
if(*p == c_stdin || *p == c_stdout || *p == c_stderr)
FILE **p = tofilep(L);
if(*p == stdin || *p == stdout || *p == stderr)
{
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
return 2;
}
int ok = (vfs_close(*p) == 0);
*p = FS_OPEN_OK - 1;
int ok = (fclose(*p) == 0);
*p = NULL;
return pushresult(L, ok, NULL);
#endif
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1))
LUA_IO_GETFIELD(IO_OUTPUT);
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
tofile(L); /* make sure argument is a file */
return aux_close(L);
}
static int io_gc (lua_State *L) {
int f = *tofilep(L);
FILE *f = *tofilep(L);
/* ignore closed files */
if (f != FS_OPEN_OK - 1)
if (f != NULL)
aux_close(L);
return 0;
}
static int io_tostring (lua_State *L) {
int f = *tofilep(L);
if (f == FS_OPEN_OK - 1)
FILE *f = *tofilep(L);
if (f == NULL)
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%i)", f);
lua_pushfstring(L, "file (%p)", f);
return 1;
}
@ -186,42 +142,19 @@ static int io_tostring (lua_State *L) {
static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
int *pf = newfile(L);
*pf = vfs_open(filename, mode);
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
/*
** this function has a separated environment, which defines the
** correct __close for 'popen' files
*/
#if 0
static int io_popen (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
int *pf = newfile(L);
*pf = lua_popen(L, filename, fs_mode2flags(mode));
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
}
static int io_tmpfile (lua_State *L) {
int *pf = newfile(L);
*pf = tmpfile();
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, NULL) : 1;
}
#endif
static int getiofile (lua_State *L, int findex) {
int *pf;
LUA_IO_GETFIELD(findex);
pf = (int *)lua_touserdata(L, -1);
if (pf == NULL || *pf == FS_OPEN_OK - 1){
luaL_error(L, "default %s file is closed", fnames[findex - 1]);
return FS_OPEN_OK - 1;
}
return *pf;
static FILE *getiofile (lua_State *L, int findex) {
FILE *f;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
f = *(FILE **)lua_touserdata(L, -1);
if (f == NULL)
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
return f;
}
@ -229,19 +162,19 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
if (filename) {
int *pf = newfile(L);
*pf = vfs_open(filename, mode);
if (*pf == FS_OPEN_OK - 1)
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
if (*pf == NULL)
fileerror(L, 1, filename);
}
else {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
LUA_IO_SETFIELD(f);
lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
LUA_IO_GETFIELD(f);
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
return 1;
}
@ -276,14 +209,14 @@ static int f_lines (lua_State *L) {
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
/* will iterate over default input */
LUA_IO_GETFIELD(IO_INPUT);
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
return f_lines(L);
}
else {
const char *filename = luaL_checkstring(L, 1);
int *pf = newfile(L);
*pf = vfs_open(filename, "r");
if (*pf == FS_OPEN_OK - 1)
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
if (*pf == NULL)
fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
@ -297,10 +230,10 @@ static int io_lines (lua_State *L) {
** =======================================================
*/
#if 0
static int read_number (lua_State *L, int f) {
static int read_number (lua_State *L, FILE *f) {
lua_Number d;
if (fs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) {
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
lua_pushnumber(L, d);
return 1;
}
@ -309,27 +242,27 @@ static int read_number (lua_State *L, int f) {
return 0; /* read fails */
}
}
#endif
static int test_eof (lua_State *L, int f) {
int c = vfs_getc(f);
vfs_ungetc(c, f);
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f);
lua_pushlstring(L, NULL, 0);
return (c != EOF);
}
#if 0
static int read_line (lua_State *L, int f) {
static int read_line (lua_State *L, FILE *f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
for (;;) {
size_t l;
char *p = luaL_prepbuffer(&b);
if (fs_gets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
l = c_strlen(p);
l = strlen(p);
if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l);
else {
@ -339,27 +272,9 @@ static int read_line (lua_State *L, int f) {
}
}
}
#else
static int read_line (lua_State *L, int f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
signed char c;
do {
c = (signed char)vfs_getc(f);
if (c==EOF) {
break;
}
if (c != '\n') {
luaL_addchar(&b, c);
}
} while (c != '\n');
luaL_pushresult(&b); /* close buffer */
return (lua_objlen(L, -1) > 0); /* check whether read something */
}
#endif
static int read_chars (lua_State *L, int f, size_t n) {
static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t rlen; /* how much to read */
size_t nr; /* number of chars actually read */
luaL_Buffer b;
@ -368,7 +283,7 @@ static int read_chars (lua_State *L, int f, size_t n) {
do {
char *p = luaL_prepbuffer(&b);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = vfs_read(f, p, rlen);
nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
@ -377,11 +292,11 @@ static int read_chars (lua_State *L, int f, size_t n) {
}
static int g_read (lua_State *L, int f, int first) {
static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
//vfs_clearerr(f);
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
@ -398,11 +313,9 @@ static int g_read (lua_State *L, int f, int first) {
const char *p = lua_tostring(L, n);
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
switch (p[1]) {
#if 0
case 'n': /* number */
success = read_number(L, f);
break;
#endif
case 'l': /* line */
success = read_line(L, f);
break;
@ -416,7 +329,7 @@ static int g_read (lua_State *L, int f, int first) {
}
}
}
if (vfs_ferrno(f))
if (ferror(f))
return pushresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
@ -437,15 +350,13 @@ static int f_read (lua_State *L) {
static int io_readline (lua_State *L) {
int *pf = (int *)lua_touserdata(L, lua_upvalueindex(1));
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
int sucess;
if (pf == NULL || *pf == FS_OPEN_OK - 1){ /* file is already closed? */
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
return 0;
}
sucess = read_line(L, *pf);
if (vfs_ferrno(*pf))
return luaL_error(L, "err(%d)", vfs_ferrno(*pf));
sucess = read_line(L, f);
if (ferror(f))
return luaL_error(L, "%s", strerror(errno));
if (sucess) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
@ -460,22 +371,19 @@ static int io_readline (lua_State *L) {
/* }====================================================== */
static int g_write (lua_State *L, int f, int arg) {
static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - 1;
int status = 1;
for (; nargs--; arg++) {
#if 0
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
status = status &&
fs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
}
else
#endif
{
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
status = status && (vfs_write(f, s, l) == l);
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
return pushresult(L, status, NULL);
@ -493,159 +401,103 @@ static int f_write (lua_State *L) {
static int f_seek (lua_State *L) {
static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END};
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
int f = tofile(L);
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0);
op = vfs_lseek(f, offset, mode[op]);
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
else {
lua_pushinteger(L, vfs_tell(f));
lua_pushinteger(L, ftell(f));
return 1;
}
}
#if 0
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
int f = tofile(L);
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL);
}
#endif
static int io_flush (lua_State *L) {
return pushresult(L, vfs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL);
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return pushresult(L, vfs_flush(tofile(L)) == 0, NULL);
return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
#if LUA_OPTIMIZE_MEMORY == 2
const LUA_REG_TYPE iolib_funcs[] = {
#else
const LUA_REG_TYPE iolib[] = {
#endif
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(io_flush)},
{LSTRKEY("input"), LFUNCVAL(io_input)},
{LSTRKEY("lines"), LFUNCVAL(io_lines)},
{LSTRKEY("open"), LFUNCVAL(io_open)},
{LSTRKEY("output"), LFUNCVAL(io_output)},
// {LSTRKEY("popen"), LFUNCVAL(io_popen)},
{LSTRKEY("read"), LFUNCVAL(io_read)},
// {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)},
{LSTRKEY("type"), LFUNCVAL(io_type)},
{LSTRKEY("write"), LFUNCVAL(io_write)},
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(io_flush)},
{LSTRKEY("input"), LFUNCVAL(io_input)},
{LSTRKEY("lines"), LFUNCVAL(io_lines)},
{LSTRKEY("open"), LFUNCVAL(io_open)},
{LSTRKEY("output"), LFUNCVAL(io_output)},
{LSTRKEY("read"), LFUNCVAL(io_read)},
{LSTRKEY("type"), LFUNCVAL(io_type)},
{LSTRKEY("write"), LFUNCVAL(io_write)},
{LSTRKEY("__index"), LROVAL(iolib_funcs)},
{LNILKEY, LNILVAL}
};
#if LUA_OPTIMIZE_MEMORY == 2
static int luaL_index(lua_State *L)
/* Note that IO objects use a RAM metatable created to allow extensibility */
static int io_index(lua_State *L)
{
return luaR_findfunction(L, iolib_funcs);
}
const luaL_Reg iolib[] = {
{"__index", luaL_index},
{"__index", io_index},
{NULL, NULL}
};
#endif
#undef MIN_OPT_LEVEL
#define MIN_OPT_LEVEL 1
#include "lrodefs.h"
const LUA_REG_TYPE flib[] = {
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(f_flush)},
{LSTRKEY("lines"), LFUNCVAL(f_lines)},
{LSTRKEY("read"), LFUNCVAL(f_read)},
{LSTRKEY("seek"), LFUNCVAL(f_seek)},
// {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)},
{LSTRKEY("write"), LFUNCVAL(f_write)},
{LSTRKEY("__gc"), LFUNCVAL(io_gc)},
{LSTRKEY("close"), LFUNCVAL(io_close)},
{LSTRKEY("flush"), LFUNCVAL(f_flush)},
{LSTRKEY("lines"), LFUNCVAL(f_lines)},
{LSTRKEY("read"), LFUNCVAL(f_read)},
{LSTRKEY("seek"), LFUNCVAL(f_seek)},
{LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)},
{LSTRKEY("write"), LFUNCVAL(f_write)},
{LSTRKEY("__gc"), LFUNCVAL(io_gc)},
{LSTRKEY("__tostring"), LFUNCVAL(io_tostring)},
#if LUA_OPTIMIZE_MEMORY > 0
{LSTRKEY("__index"), LROVAL(flib)},
#endif
{LSTRKEY("__index"), LROVAL(flib)},
{LNILKEY, LNILVAL}
};
static void createmeta (lua_State *L) {
#if LUA_OPTIMIZE_MEMORY == 0
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_register(L, NULL, flib); /* file methods */
#else
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */
#endif
}
static void createstdfile (lua_State *L, int f, int k, const char *fname) {
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
*newfile(L) = f;
#if LUA_OPTIMIZE_MEMORY != 2
if (k > 0) {
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_ENVIRONINDEX, k);
}
lua_pushvalue(L, -2); /* copy environment */
lua_setfenv(L, -2); /* set it */
lua_setfield(L, -3, fname);
#else
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[k]);
lua_setfield(L, -2, fname);
#endif
}
#if LUA_OPTIMIZE_MEMORY != 2
static void newfenv (lua_State *L, lua_CFunction cls) {
lua_createtable(L, 0, 1);
lua_pushcfunction(L, cls);
lua_setfield(L, -2, "__close");
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_REGISTRYINDEX, (int)(liolib_keys[k]));
lua_setfield(L, -2, fname);
}
#endif
LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L);
#if LUA_OPTIMIZE_MEMORY != 2
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
newfenv(L, io_fclose);
lua_replace(L, LUA_ENVIRONINDEX);
/* open library */
luaL_register(L, LUA_IOLIBNAME, iolib);
newfenv(L, io_noclose); /* close function for default files */
#else
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */
luaL_register_light(L, LUA_IOLIBNAME, iolib);
lua_pushvalue(L, -1);
lua_setmetatable(L, -2);
#endif
#if 0
/* create (and set) default files */
createstdfile(L, c_stdin, IO_INPUT, "stdin");
createstdfile(L, c_stdout, IO_OUTPUT, "stdout");
createstdfile(L, c_stderr, IO_STDERR, "stderr");
#if LUA_OPTIMIZE_MEMORY != 2
lua_pop(L, 1); /* pop environment for default files */
lua_getfield(L, -1, "popen");
newfenv(L, io_pclose); /* create environment for 'popen' */
lua_setfenv(L, -2); /* set fenv for 'popen' */
lua_pop(L, 1); /* pop 'popen' */
#endif
#endif
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, 0, "stderr");
return 1;
}

View File

@ -11,13 +11,14 @@
#include C_HEADER_STDIO
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#include <time.h>
#define luac_c
#define LUA_CORE
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
@ -31,17 +32,23 @@
static int listing=0; /* list bytecodes? */
static int dumping=1; /* dump bytecodes? */
static int stripping=0; /* strip debug information? */
static int stripping=0; /* strip debug information? */
static int flash=0; /* output flash image */
static lu_int32 address=0; /* output flash image at absolute location */
static int lookup=0; /* output lookup-style master combination header */
static char Output[]={ OUTPUT }; /* default output file name */
static const char* output=Output; /* actual output file name */
static const char* execute; /* executed a Lua file */
static const char* progname=PROGNAME; /* actual program name */
static DumpTargetInfo target;
static void fatal(const char* message)
void luac_fatal(const char* message)
{
fprintf(stderr,"%s: %s\n",progname,message);
exit(EXIT_FAILURE);
}
#define fatal(s) luac_fatal(s)
static void cannot(const char* what)
{
@ -61,18 +68,21 @@ static void usage(const char* message)
" - process stdin\n"
" -l list\n"
" -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
" -e name execute a lua source file\n"
" -f output a flash image file\n"
" -a addr generate an absolute, rather than position independent flash image file\n"
" -i generate lookup combination master (default with option -f)\n"
" -p parse only\n"
" -s strip debug information\n"
" -v show version information\n"
" -cci bits cross-compile with given integer size\n"
" -ccn type bits cross-compile with given lua_Number type and size\n"
" -cce endian cross-compile with given endianness ('big' or 'little')\n"
" -- stop handling options\n",
progname,Output);
exit(EXIT_FAILURE);
}
#define IS(s) (strcmp(argv[i],s)==0)
#define IROM0_SEG 0x40210000ul
#define IROM0_SEGMAX 0x00100000ul
static int doargs(int argc, char* argv[])
{
@ -89,8 +99,28 @@ static int doargs(int argc, char* argv[])
if (version) ++version;
break;
}
else if (IS("-")) /* end of options; use stdin */
else if (IS("-")) /* end of options; use stdin */
break;
else if (IS("-e")) /* execute a lua source file file */
{
execute=argv[++i];
if (execute ==NULL || *execute==0 || *execute=='-' )
usage(LUA_QL("-e") " needs argument");
}
else if (IS("-f")) /* Flash image file */
{
flash=lookup=1;
}
else if (IS("-a")) /* Absolue flash image file */
{
flash=lookup=1;
address=strtol(argv[++i],NULL,0);
size_t offset = (unsigned) (address -IROM0_SEG);
if (offset > IROM0_SEGMAX)
usage(LUA_QL("-e") " absolute address must be valid flash address");
}
else if (IS("-i")) /* lookup */
lookup = 1;
else if (IS("-l")) /* list */
++listing;
else if (IS("-o")) /* output file */
@ -99,42 +129,17 @@ static int doargs(int argc, char* argv[])
if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
if (IS("-")) output=NULL;
}
else if (IS("-p")) /* parse only */
dumping=0;
dumping=0;
else if (IS("-s")) /* strip debug information */
stripping=1;
else if (IS("-v")) /* show version */
++version;
else if (IS("-cci")) /* target integer size */
{
int s = target.sizeof_int = atoi(argv[++i])/8;
if (!(s==1 || s==2 || s==4)) fatal(LUA_QL("-cci") " must be 8, 16 or 32");
}
else if (IS("-ccn")) /* target lua_Number type and size */
{
const char *type=argv[++i];
if (strcmp(type,"int")==0) target.lua_Number_integral=1;
else if (strcmp(type,"float")==0) target.lua_Number_integral=0;
else if (strcmp(type,"float_arm")==0)
{
target.lua_Number_integral=0;
target.is_arm_fpa=1;
}
else fatal(LUA_QL("-ccn") " type must be " LUA_QL("int") " or " LUA_QL("float") " or " LUA_QL("float_arm"));
int s = target.sizeof_lua_Number = atoi(argv[++i])/8;
if (target.lua_Number_integral && !(s==1 || s==2 || s==4)) fatal(LUA_QL("-ccn") " size must be 8, 16, or 32 for int");
if (!target.lua_Number_integral && !(s==4 || s==8)) fatal(LUA_QL("-ccn") " size must be 32 or 64 for float");
}
else if (IS("-cce")) /* target endianness */
{
const char *val=argv[++i];
if (strcmp(val,"big")==0) target.little_endian=0;
else if (strcmp(val,"little")==0) target.little_endian=1;
else fatal(LUA_QL("-cce") " must be " LUA_QL("big") " or " LUA_QL("little"));
}
else /* unknown option */
usage(argv[i]);
usage(argv[i]);
}
if (i==argc && (listing || !dumping))
{
dumping=0;
@ -150,30 +155,99 @@ static int doargs(int argc, char* argv[])
#define toproto(L,i) (clvalue(L->top+(i))->l.p)
static const Proto* combine(lua_State* L, int n)
static TString *corename(lua_State *L, const TString *filename)
{
if (n==1)
const char *fn = getstr(filename)+1;
const char *s = strrchr(fn, '/');
s = s ? s + 1 : fn;
while (*s == '.') s++;
const char *e = strchr(s, '.');
int l = e ? e - s: strlen(s);
return l ? luaS_newlstr (L, s, l) : luaS_new(L, fn);
}
/*
* If the luac command line includes multiple files or has the -f option
* then luac generates a main function to reference all sub-main prototypes.
* This is one of two types:
* Type 0 The standard luac combination main
* Type 1 A lookup wrapper that facilitates indexing into the generated protos
*/
static const Proto* combine(lua_State* L, int n, int type)
{
if (n==1 && type == 0)
return toproto(L,-1);
else
{
int i,pc;
int i;
Instruction *pc;
Proto* f=luaF_newproto(L);
setptvalue2s(L,L->top,f); incr_top(L);
f->source=luaS_newliteral(L,"=(" PROGNAME ")");
f->maxstacksize=1;
pc=2*n+1;
f->code=luaM_newvector(L,pc,Instruction);
f->sizecode=pc;
f->p=luaM_newvector(L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++)
f->p[i]=toproto(L,i-n-1);
pc=0;
for (i=0; i<n; i++)
{
f->p[i]=toproto(L,i-n-1);
f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
if (type == 0) {
/*
* Type 0 is as per the standard luac, which is just a main routine which
* invokes all of the compiled functions sequentially. This is fine if
* they are self registering modules, but useless otherwise.
*/
f->numparams = 0;
f->maxstacksize = 1;
f->sizecode = 2*n + 1 ;
f->sizek = 0;
f->code = luaM_newvector(L, f->sizecode , Instruction);
f->k = luaM_newvector(L,f->sizek,TValue);
for (i=0, pc = f->code; i<n; i++) {
*pc++ = CREATE_ABx(OP_CLOSURE,0,i);
*pc++ = CREATE_ABC(OP_CALL,0,1,1);
}
*pc++ = CREATE_ABC(OP_RETURN,0,1,0);
} else {
/*
* The Type 1 main() is a lookup which takes a single argument, the name to
* be resolved. If this matches root name of one of the compiled files then
* a closure to this file main is returned. Otherwise the Unixtime of the
* compile and the list of root names is returned.
*/
if (n > LFIELDS_PER_FLUSH) {
#define NO_MOD_ERR_(n) ": Number of modules > " #n
#define NO_MOD_ERR(n) NO_MOD_ERR_(n)
usage(LUA_QL("-f") NO_MOD_ERR(LFIELDS_PER_FLUSH));
}
f->numparams = 1;
f->maxstacksize = n + 3;
f->sizecode = 5*n + 5 ;
f->sizek = n + 1;
f->sizelocvars = 0;
f->code = luaM_newvector(L, f->sizecode , Instruction);
f->k = luaM_newvector(L,f->sizek,TValue);
for (i=0, pc = f->code; i<n; i++)
{
/* if arg1 == FnameA then return function (...) -- funcA -- end end */
setsvalue2n(L,f->k+i,corename(L, f->p[i]->source));
*pc++ = CREATE_ABC(OP_EQ,0,0,RKASK(i));
*pc++ = CREATE_ABx(OP_JMP,0,MAXARG_sBx+2);
*pc++ = CREATE_ABx(OP_CLOSURE,1,i);
*pc++ = CREATE_ABC(OP_RETURN,1,2,0);
}
setnvalue(f->k+n, (lua_Number) time(NULL));
*pc++ = CREATE_ABx(OP_LOADK,1,n);
*pc++ = CREATE_ABC(OP_NEWTABLE,2,luaO_int2fb(i),0);
for (i=0; i<n; i++)
*pc++ = CREATE_ABx(OP_LOADK,i+3,i);
*pc++ = CREATE_ABC(OP_SETLIST,2,i,1);
*pc++ = CREATE_ABC(OP_RETURN,1,3,0);
*pc++ = CREATE_ABC(OP_RETURN,0,1,0);
}
f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
lua_assert((pc-f->code) == f->sizecode);
return f;
}
}
@ -189,6 +263,9 @@ struct Smain {
char** argv;
};
extern uint dumpToFlashImage (lua_State* L,const Proto *main, lua_Writer w,
void* data, int strip, lu_int32 address);
static int pmain(lua_State* L)
{
struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
@ -197,19 +274,39 @@ static int pmain(lua_State* L)
const Proto* f;
int i;
if (!lua_checkstack(L,argc)) fatal("too many input files");
if (execute)
{
if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1));
luaL_openlibs(L);
lua_pushstring(L, execute);
if (lua_pcall(L, 1, 1, 0)) fatal(lua_tostring(L,-1));
if (!lua_isfunction(L, -1))
{
lua_pop(L,1);
if(argc == 0) return 0;
execute = NULL;
}
}
for (i=0; i<argc; i++)
{
const char* filename=IS("-") ? NULL : argv[i];
if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
}
f=combine(L,argc);
f=combine(L,argc + (execute ? 1: 0), lookup);
if (listing) luaU_print(f,listing>1);
if (dumping)
{
int result;
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
if (D==NULL) cannot("open");
lua_lock(L);
int result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
if (flash)
{
result=dumpToFlashImage(L,f,writer, D, stripping, address);
} else
{
result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
}
lua_unlock(L);
if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type");
if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found");
@ -234,7 +331,7 @@ int main(int argc, char* argv[])
int i=doargs(argc,argv);
argc-=i; argv+=i;
if (argc<=0) usage("no input files given");
if (argc<=0 && execute==0) usage("no input files given");
L=lua_open();
if (L==NULL) fatal("not enough memory for state");
s.argc=argc;

View File

@ -38,6 +38,11 @@
#define LUA_WIN
#endif
#if defined(LUA_CROSS_COMPILER)
#define LUA_USE_LINUX
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
@ -59,7 +64,7 @@
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
//#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif
@ -167,7 +172,7 @@
#define LUA_INTEGER ptrdiff_t
#else
#if !defined LUA_INTEGRAL_LONGLONG
#define LUA_INTEGER long
#define LUA_INTEGER int
#else
#define LUA_INTEGER long long
#endif // #if !defined LUA_INTEGRAL_LONGLONG
@ -487,7 +492,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
/* 16-bit ints */
#define LUAI_UINT32 unsigned long
#define LUAI_INT32 long
#define LUAI_MAXINT32 LONG_MAX
#define LUAI_MAXINT32 INT_MAX
#define LUAI_UMEM unsigned long
#define LUAI_MEM long
#endif
@ -607,8 +612,8 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
*/
#if defined LUA_NUMBER_INTEGRAL
#if !defined LUA_INTEGRAL_LONGLONG
#define LUA_NUMBER_SCAN "%ld"
#define LUA_NUMBER_FMT "%ld"
#define LUA_NUMBER_SCAN "%d"
#define LUA_NUMBER_FMT "%d"
#else
#define LUA_NUMBER_SCAN "%lld"
#define LUA_NUMBER_FMT "%lld"
@ -894,7 +899,7 @@ union luai_Cast { double l_d; long l_l; };
/* If you define the next macro you'll get the ability to set rotables as
metatables for tables/userdata/types (but the VM might run slower)
*/
#if (LUA_OPTIMIZE_MEMORY == 2) && !defined(LUA_CROSS_COMPILER)
#if (LUA_OPTIMIZE_MEMORY == 2)
#define LUA_META_ROTABLES
#endif

View File

@ -172,7 +172,7 @@ static TString* LoadString(LoadState* S)
} else {
s = (char*)luaZ_get_crt_address(S->Z);
LoadBlock(S,NULL,size);
return luaS_newrolstr(S->L,s,size-1);
return luaS_newlstr(S->L,s,size-1);
}
}
}
@ -280,7 +280,7 @@ static Proto* LoadFunction(LoadState* S, TString* p)
Proto* f;
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
f=luaF_newproto(S->L);
if (luaZ_direct_mode(S->Z)) proto_readonly(f);
if (luaZ_direct_mode(S->Z)) l_setbit((f)->marked, READONLYBIT);
setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->linedefined=LoadInt(S);

View File

@ -41,7 +41,7 @@ LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) {
LUA_NUMBER c = 1;
for (;;) {
if (b & 1)
c *= a;
c *= a;
b = b >> 1;
if (b == 0)
return c;

2
app/lwip/app/dhcpserver.c Executable file → Normal file
View File

@ -689,6 +689,7 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
#endif
send_ack(pmsg_dhcps, malloc_len);
wifi_softap_set_station_info(pmsg_dhcps->chaddr, &client_address.addr);
break;
case DHCPS_STATE_NAK://4
#if DHCPS_DEBUG
@ -1199,7 +1200,6 @@ uint32 ICACHE_FLASH_ATTR wifi_softap_dhcps_client_update(u8 *bssid, struct ip_ad
node_insert_to_list(&plist,pback_node);
}
}
wifi_softap_set_station_info(bssid, &pdhcps_pool->ip);
return pdhcps_pool->ip.addr;
}

View File

@ -1105,6 +1105,8 @@ espconn_set_opt(struct espconn *espconn, uint8 opt)
if (value) {
pnode->pcommon.espconn_opt |= opt;
tpcb = pnode->pcommon.pcb;
if (NULL == tpcb)
return ESPCONN_OK;
if (espconn_delay_disabled(pnode))
tcp_nagle_disable(tpcb);
@ -1143,7 +1145,8 @@ espconn_clear_opt(struct espconn *espconn, uint8 opt)
tpcb = pnode->pcommon.pcb;
if (espconn_keepalive_enabled(pnode))
espconn_keepalive_disable(tpcb);
if (NULL == tpcb)
return ESPCONN_OK;
if (espconn_delay_enabled(pnode))
tcp_nagle_enable(tpcb);
@ -1176,6 +1179,8 @@ sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 lev
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (NULL == pcb)
return ESPCONN_OK;
switch (level){
case ESPCONN_KEEPIDLE:
pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg);
@ -1221,6 +1226,8 @@ sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 lev
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (NULL == pcb)
return ESPCONN_OK;
switch (level) {
case ESPCONN_KEEPIDLE:
*(int*)optarg = (int)(pcb->keep_idle/1000);

View File

@ -43,14 +43,14 @@ INCLUDES += -I ./
INCLUDES += -I ../libc
INCLUDES += -I ../coap
INCLUDES += -I ../mqtt
INCLUDES += -I ../u8glib
INCLUDES += -I ../u8g2lib/u8g2/src/clib
INCLUDES += -I ../ucglib
INCLUDES += -I ../lua
INCLUDES += -I ../pcm
INCLUDES += -I ../platform
INCLUDES += -I ../spiffs
INCLUDES += -I ../smart
INCLUDES += -I ../dhtlib
INCLUDES += -I ../dht
INCLUDES += -I ../fatfs
INCLUDES += -I ../http
INCLUDES += -I ../sjson

View File

@ -214,18 +214,53 @@ static int file_open( lua_State* L )
static int file_list( lua_State* L )
{
vfs_dir *dir;
const char *pattern;
struct vfs_stat stat;
int pcres;
if (dir = vfs_opendir("")) {
lua_newtable( L );
struct vfs_stat stat;
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
lua_pushinteger(L, stat.size);
lua_setfield(L, -2, stat.name);
}
vfs_closedir(dir);
return 1;
lua_settop(L, 1);
pattern = luaL_optstring(L, 1, NULL); /* Pattern (arg) or nil (not) at 1 */
dir = vfs_opendir("");
if (dir == NULL) {
return 0;
}
return 0;
lua_newtable( L ); /* Table at 2 */
if (pattern) {
/*
* We know that pattern is a string, and so the "match" method will always
* exist. No need to check return value here
*/
luaL_getmetafield( L, 1, "match" ); /* Function at 3 */
}
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
if (pattern) {
lua_settop( L, 3 ); /* Ensure nothing else on stack */
/* Construct and pcall(string.match,name,pattern) */
lua_pushvalue( L, 3 );
lua_pushstring( L, stat.name );
lua_pushvalue( L, 1 );
pcres = lua_pcall( L, 2, 1, 0 );
if (pcres != 0) {
vfs_closedir(dir);
lua_error( L );
}
if (lua_isnil( L, -1 )) {
continue;
}
}
lua_pushinteger( L, stat.size );
lua_setfield( L, 2, stat.name );
}
/* Shed everything back to Table */
lua_settop( L, 2 );
vfs_closedir(dir);
return 1;
}
static int get_file_obj( lua_State *L, int *argpos )

View File

@ -2,7 +2,8 @@
* This module, when enabled with the LUA_USE_MODULES_GDBSTUB define causes
* the gdbstub code to be included and enabled to handle all fatal exceptions.
* This allows you to use the lx106 gdb to catch the exception and then poke
* around. You can't continue from an exception (at least not easily).
* around. You can continue from a break, but attempting to continue from an
* exception usually fails.
*
* This should not be included in production builds as any exception will
* put the nodemcu into a state where it is waiting for serial input and it has
@ -41,8 +42,8 @@ static int lgdbstub_open(lua_State *L) {
static const LUA_REG_TYPE gdbstub_map[] = {
{ LSTRKEY( "brk" ), LFUNCVAL( lgdbstub_break ) },
{ LSTRKEY( "gdboutput" ), LFUNCVAL( lgdbstub_gdboutput) },
{ LSTRKEY( "open" ), LFUNCVAL( lgdbstub_open) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(GDBSTUB, "gdbstub", gdbstub_map, lgdbstub_open);
NODEMCU_MODULE(GDBSTUB, "gdbstub", gdbstub_map, NULL);

View File

@ -1,78 +0,0 @@
/*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/
#define linit_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
#include "module.h"
BUILTIN_LIB_INIT( BASE, "", luaopen_base);
BUILTIN_LIB_INIT( LOADLIB, LUA_LOADLIBNAME, luaopen_package);
#if defined(LUA_USE_BUILTIN_IO)
BUILTIN_LIB_INIT( IO, LUA_IOLIBNAME, luaopen_io);
#endif
#if defined (LUA_USE_BUILTIN_STRING)
extern const luaR_entry strlib[];
BUILTIN_LIB_INIT( STRING, LUA_STRLIBNAME, luaopen_string);
BUILTIN_LIB( STRING, LUA_STRLIBNAME, strlib);
#endif
#if defined(LUA_USE_BUILTIN_TABLE)
extern const luaR_entry tab_funcs[];
BUILTIN_LIB_INIT( TABLE, LUA_TABLIBNAME, luaopen_table);
BUILTIN_LIB( TABLE, LUA_TABLIBNAME, tab_funcs);
#endif
#if defined(LUA_USE_BUILTIN_DEBUG) || defined(LUA_USE_BUILTIN_DEBUG_MINIMAL)
extern const luaR_entry dblib[];
BUILTIN_LIB_INIT( DBG, LUA_DBLIBNAME, luaopen_debug);
BUILTIN_LIB( DBG, LUA_DBLIBNAME, dblib);
#endif
#if defined(LUA_USE_BUILTIN_OS)
extern const luaR_entry syslib[];
BUILTIN_LIB( OS, LUA_OSLIBNAME, syslib);
#endif
#if defined(LUA_USE_BUILTIN_COROUTINE)
extern const luaR_entry co_funcs[];
BUILTIN_LIB( CO, LUA_COLIBNAME, co_funcs);
#endif
#if defined(LUA_USE_BUILTIN_MATH)
extern const luaR_entry math_map[];
BUILTIN_LIB( MATH, LUA_MATHLIBNAME, math_map);
#endif
#ifdef LUA_CROSS_COMPILER
const luaL_Reg lua_libs[] = {{NULL, NULL}};
const luaR_table lua_rotable[] = {{NULL, NULL}};
#else
extern const luaL_Reg lua_libs[];
#endif
void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib = lua_libs;
for (; lib->name; lib++) {
if (lib->func)
{
lua_pushcfunction(L, lib->func);
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
}
}
}

View File

@ -17,7 +17,9 @@
#include "platform.h"
#include "lrodefs.h"
#ifdef LUA_FLASH_STORE
#include "lflash.h"
#endif
#include "c_types.h"
#include "c_string.h"
#include "driver/uart.h"
@ -149,7 +151,6 @@ static int node_chipid( lua_State* L )
// lua_pushinteger(L, vdd33);
// return 1;
// }
// Lua: flashid()
static int node_flashid( lua_State* L )
{
@ -178,26 +179,16 @@ static int node_heap( lua_State* L )
return 1;
}
extern lua_Load gLoad;
extern int lua_put_line(const char *s, size_t l);
extern bool user_process_input(bool force);
// Lua: input("string")
static int node_input( lua_State* L )
{
static int node_input( lua_State* L ) {
size_t l = 0;
const char *s = luaL_checklstring(L, 1, &l);
if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1)
{
lua_Load *load = &gLoad;
if (load->line_position == 0) {
c_memcpy(load->line, s, l);
load->line[l + 1] = '\0';
load->line_position = c_strlen(load->line) + 1;
load->done = 1;
NODE_DBG("Get command:\n");
NODE_DBG(load->line); // buggy here
NODE_DBG("\nResult(if any):\n");
user_process_input(true);
}
if (lua_put_line(s, l)) {
NODE_DBG("Result (if any):\n");
user_process_input(true);
}
return 0;
}
@ -609,6 +600,13 @@ static const LUA_REG_TYPE node_task_map[] = {
static const LUA_REG_TYPE node_map[] =
{
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) },
{ LSTRKEY( "task" ), LROVAL( node_task_map ) },
#ifdef LUA_FLASH_STORE
{ LSTRKEY( "flashreload" ), LFUNCVAL( luaN_reload_reboot ) },
{ LSTRKEY( "flashindex" ), LFUNCVAL( luaN_index ) },
#endif
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
{ LSTRKEY( "dsleepMax" ), LFUNCVAL( dsleepMax ) },
@ -616,11 +614,9 @@ static const LUA_REG_TYPE node_map[] =
#ifdef PMSLEEP_ENABLE
PMSLEEP_INT_MAP,
#endif
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) },
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) },
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
// Moved to adc module, use adc.readvdd33()
@ -637,7 +633,6 @@ static const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
#endif
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
{ LSTRKEY( "task" ), LROVAL( node_task_map ) },
#ifdef DEVELOPMENT_TOOLS
{ LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) },
#endif

0
app/modules/tmr.c Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

816
app/modules/u8g2.c Normal file
View File

@ -0,0 +1,816 @@
// Module for binding the u8g2 library
// Note: This file is intended to be shared between esp8266 and esp32 platform
// Do not use the code from u8g2 submodule and skip the complete source here
// if the u8g2 module is not selected.
// Reason: The whole u8g2 submodule code tree might not even exist in this case.
#include "user_modules.h"
#if defined(LUA_USE_MODULES_U8G2) || defined(ESP_PLATFORM)
#include "module.h"
#include "lauxlib.h"
#define U8X8_USE_PINS
#include "u8g2.h"
#include "u8x8_nodemcu_hal.h"
#include "u8g2_displays.h"
#include "u8g2_fonts.h"
#ifdef ESP_PLATFORM
// ESP32
#include "spi_common.h"
#include "sdkconfig.h"
#endif
#ifndef CONFIG_LUA_MODULE_U8G2
// ignore unused functions if u8g2 module will be skipped anyhow
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
typedef struct {
int font_ref;
int host_ref;
u8g2_nodemcu_t u8g2;
} u8g2_ud_t;
#define GET_U8G2() \
u8g2_ud_t *ud = (u8g2_ud_t *)luaL_checkudata( L, 1, "u8g2.display" ); \
u8g2_t *u8g2 = (u8g2_t *)(&(ud->u8g2));
static int lu8g2_clearBuffer( lua_State *L )
{
GET_U8G2();
u8g2_ClearBuffer( u8g2 );
return 0;
}
static int lu8g2_drawBox( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
u8g2_DrawBox( u8g2, x, y, w, h );
return 0;
}
static int lu8g2_drawCircle( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int rad = luaL_checkint( L, ++stack );
int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
u8g2_DrawCircle( u8g2, x0, y0, rad, opt );
return 0;
}
static int lu8g2_drawDisc( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int rad = luaL_checkint( L, ++stack );
int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
u8g2_DrawDisc( u8g2, x0, y0, rad, opt );
return 0;
}
static int lu8g2_drawEllipse( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int rx = luaL_checkint( L, ++stack );
int ry = luaL_checkint( L, ++stack );
int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
u8g2_DrawEllipse( u8g2, x0, y0, rx, ry, opt );
return 0;
}
static int lu8g2_drawFilledEllipse( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int rx = luaL_checkint( L, ++stack );
int ry = luaL_checkint( L, ++stack );
int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL );
u8g2_DrawFilledEllipse( u8g2, x0, y0, rx, ry, opt );
return 0;
}
static int lu8g2_drawFrame( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
u8g2_DrawFrame( u8g2, x, y, w, h );
return 0;
}
static int lu8g2_drawGlyph( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int enc = luaL_checkint( L, ++stack );
u8g2_DrawGlyph( u8g2, x, y, enc );
return 0;
}
static int lu8g2_drawHLine( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
u8g2_DrawHLine( u8g2, x, y, w );
return 0;
}
static int lu8g2_drawLine( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int x1 = luaL_checkint( L, ++stack );
int y1 = luaL_checkint( L, ++stack );
u8g2_DrawLine( u8g2, x0, y0, x1, y1 );
return 0;
}
static int lu8g2_drawPixel( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
u8g2_DrawPixel( u8g2, x, y );
return 0;
}
static int lu8g2_drawRBox( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
int r = luaL_checkint( L, ++stack );
u8g2_DrawRBox( u8g2, x, y, w, h, r );
return 0;
}
static int lu8g2_drawRFrame( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
int r = luaL_checkint( L, ++stack );
u8g2_DrawRFrame( u8g2, x, y, w, h, r );
return 0;
}
static int lu8g2_drawStr( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
const char *str = luaL_checkstring( L, ++stack );
u8g2_DrawStr( u8g2, x, y, str );
return 0;
}
static int lu8g2_drawTriangle( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x0 = luaL_checkint( L, ++stack );
int y0 = luaL_checkint( L, ++stack );
int x1 = luaL_checkint( L, ++stack );
int y1 = luaL_checkint( L, ++stack );
int x2 = luaL_checkint( L, ++stack );
int y2 = luaL_checkint( L, ++stack );
u8g2_DrawTriangle( u8g2, x0, y0, x1, y1, x2, y2 );
return 0;
}
static int lu8g2_drawUTF8( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
const char *str = luaL_checkstring( L, ++stack );
u8g2_DrawUTF8( u8g2, x, y, str );
return 0;
}
static int lu8g2_drawVLine( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
u8g2_DrawVLine( u8g2, x, y, h );
return 0;
}
static int lu8g2_drawXBM( lua_State *L )
{
GET_U8G2();
int stack = 1;
int x = luaL_checkint( L, ++stack );
int y = luaL_checkint( L, ++stack );
int w = luaL_checkint( L, ++stack );
int h = luaL_checkint( L, ++stack );
size_t len;
const char *bitmap = luaL_checklstring( L, ++stack, &len );
u8g2_DrawXBM( u8g2, x, y, w, h, (uint8_t *)bitmap );
return 0;
}
static int lu8g2_getAscent( lua_State *L )
{
GET_U8G2();
lua_pushinteger( L, u8g2_GetAscent( u8g2 ) );
return 1;
}
static int lu8g2_getDescent( lua_State *L )
{
GET_U8G2();
lua_pushinteger( L, u8g2_GetDescent( u8g2 ) );
return 1;
}
static int lu8g2_getStrWidth( lua_State *L )
{
GET_U8G2();
int stack = 1;
const char *s = luaL_checkstring( L, ++stack );
lua_pushinteger( L, u8g2_GetStrWidth( u8g2, s ) );
return 1;
}
static int lu8g2_getUTF8Width( lua_State *L )
{
GET_U8G2();
int stack = 1;
const char *s = luaL_checkstring( L, ++stack );
lua_pushinteger( L, u8g2_GetUTF8Width( u8g2, s ) );
return 1;
}
static int lu8g2_sendBuffer( lua_State *L )
{
GET_U8G2();
u8g2_SendBuffer( u8g2 );
return 0;
}
static int lu8g2_setBitmapMode( lua_State *L )
{
GET_U8G2();
int stack = 1;
int is_transparent = luaL_checkint( L, ++stack );
u8g2_SetBitmapMode( u8g2, is_transparent );
return 0;
}
static int lu8g2_setContrast( lua_State *L )
{
GET_U8G2();
int stack = 1;
int value = luaL_checkint( L, ++stack );
u8g2_SetContrast( u8g2, value );
return 0;
}
static int lu8g2_setDisplayRotation( lua_State *L )
{
GET_U8G2();
int stack = 1;
const u8g2_cb_t *u8g2_cb = (u8g2_cb_t *)lua_touserdata( L, ++stack );
u8g2_SetDisplayRotation( u8g2, u8g2_cb );
return 0;
}
static int lu8g2_setDrawColor( lua_State *L )
{
GET_U8G2();
int stack = 1;
int col = luaL_checkint( L, ++stack );
u8g2_SetDrawColor( u8g2, col );
return 0;
}
static int lu8g2_setFlipMode( lua_State *L )
{
GET_U8G2();
int stack = 1;
int is_enable = luaL_checkint( L, ++stack );
u8g2_SetFlipMode( u8g2, is_enable );
return 0;
}
static int lu8g2_setFont( lua_State *L )
{
GET_U8G2();
int stack = 1;
const uint8_t *font = NULL;
luaL_unref( L, LUA_REGISTRYINDEX, ud->font_ref );
ud->font_ref = LUA_NOREF;
if (lua_islightuserdata( L, ++stack )) {
font = (const uint8_t *)lua_touserdata( L, stack );
} else if (lua_isstring( L, stack )) {
// ref the font string to safe it in case the string variable gets gc'ed
lua_pushvalue( L, stack );
ud->font_ref = luaL_ref( L, LUA_REGISTRYINDEX );
size_t len;
font = (const uint8_t *)luaL_checklstring( L, stack, &len );
}
luaL_argcheck( L, font != NULL, stack, "invalid font" );
u8g2_SetFont( u8g2, font );
return 0;
}
static int lu8g2_setFontDirection( lua_State *L )
{
GET_U8G2();
int stack = 1;
int dir = luaL_checkint( L, ++stack );
u8g2_SetFontDirection( u8g2, dir );
return 0;
}
static int lu8g2_setFontMode( lua_State *L )
{
GET_U8G2();
int stack = 1;
int is_transparent = luaL_checkint( L, ++stack );
u8g2_SetFontMode( u8g2, is_transparent );
return 0;
}
static int lu8g2_setFontPosBaseline( lua_State *L )
{
GET_U8G2();
u8g2_SetFontPosBaseline( u8g2 );
return 0;
}
static int lu8g2_setFontPosBottom( lua_State *L )
{
GET_U8G2();
u8g2_SetFontPosBottom( u8g2 );
return 0;
}
static int lu8g2_setFontPosTop( lua_State *L )
{
GET_U8G2();
u8g2_SetFontPosTop( u8g2 );
return 0;
}
static int lu8g2_setFontPosCenter( lua_State *L )
{
GET_U8G2();
u8g2_SetFontPosCenter( u8g2 );
return 0;
}
static int lu8g2_setFontRefHeightAll( lua_State *L )
{
GET_U8G2();
u8g2_SetFontRefHeightAll( u8g2 );
return 0;
}
static int lu8g2_setFontRefHeightExtendedText( lua_State *L )
{
GET_U8G2();
u8g2_SetFontRefHeightExtendedText( u8g2 );
return 0;
}
static int lu8g2_setFontRefHeightText( lua_State *L )
{
GET_U8G2();
u8g2_SetFontRefHeightText( u8g2 );
return 0;
}
static int lu8g2_setPowerSave( lua_State *L )
{
GET_U8G2();
int stack = 1;
int is_enable = luaL_checkint( L, ++stack );
u8g2_SetPowerSave( u8g2, is_enable );
return 0;
}
static const LUA_REG_TYPE lu8g2_display_map[] = {
{ LSTRKEY( "clearBuffer" ), LFUNCVAL( lu8g2_clearBuffer ) },
{ LSTRKEY( "drawBox" ), LFUNCVAL( lu8g2_drawBox ) },
{ LSTRKEY( "drawCircle" ), LFUNCVAL( lu8g2_drawCircle ) },
{ LSTRKEY( "drawDisc" ), LFUNCVAL( lu8g2_drawDisc ) },
{ LSTRKEY( "drawEllipse" ), LFUNCVAL( lu8g2_drawEllipse ) },
{ LSTRKEY( "drawFilledEllipse" ), LFUNCVAL( lu8g2_drawFilledEllipse ) },
{ LSTRKEY( "drawFrame" ), LFUNCVAL( lu8g2_drawFrame ) },
{ LSTRKEY( "drawGlyph" ), LFUNCVAL( lu8g2_drawGlyph ) },
{ LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g2_drawHLine ) },
{ LSTRKEY( "drawLine" ), LFUNCVAL( lu8g2_drawLine ) },
{ LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g2_drawPixel ) },
{ LSTRKEY( "drawRBox" ), LFUNCVAL( lu8g2_drawRBox ) },
{ LSTRKEY( "drawRFrame" ), LFUNCVAL( lu8g2_drawRFrame ) },
{ LSTRKEY( "drawStr" ), LFUNCVAL( lu8g2_drawStr ) },
{ LSTRKEY( "drawTriangle" ), LFUNCVAL( lu8g2_drawTriangle ) },
{ LSTRKEY( "drawUTF8" ), LFUNCVAL( lu8g2_drawUTF8 ) },
{ LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g2_drawVLine ) },
{ LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g2_drawXBM ) },
{ LSTRKEY( "getAscent" ), LFUNCVAL( lu8g2_getAscent ) },
{ LSTRKEY( "getDescent" ), LFUNCVAL( lu8g2_getDescent ) },
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g2_getStrWidth ) },
{ LSTRKEY( "getUTF8Width" ), LFUNCVAL( lu8g2_getUTF8Width ) },
{ LSTRKEY( "sendBuffer" ), LFUNCVAL( lu8g2_sendBuffer ) },
{ LSTRKEY( "setBitmapMode" ), LFUNCVAL( lu8g2_setBitmapMode ) },
{ LSTRKEY( "setContrast" ), LFUNCVAL( lu8g2_setContrast ) },
{ LSTRKEY( "setDisplayRotation" ), LFUNCVAL( lu8g2_setDisplayRotation ) },
{ LSTRKEY( "setDrawColor" ), LFUNCVAL( lu8g2_setDrawColor ) },
{ LSTRKEY( "setFlipMode" ), LFUNCVAL( lu8g2_setFlipMode ) },
{ LSTRKEY( "setFont" ), LFUNCVAL( lu8g2_setFont ) },
{ LSTRKEY( "setFontDirection" ), LFUNCVAL( lu8g2_setFontDirection ) },
{ LSTRKEY( "setFontMode" ), LFUNCVAL( lu8g2_setFontMode ) },
{ LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lu8g2_setFontPosBaseline ) },
{ LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lu8g2_setFontPosBottom ) },
{ LSTRKEY( "setFontPosTop" ), LFUNCVAL( lu8g2_setFontPosTop ) },
{ LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lu8g2_setFontPosCenter ) },
{ LSTRKEY( "setFontRefHeightAll" ), LFUNCVAL( lu8g2_setFontRefHeightAll ) },
{ LSTRKEY( "setFontRefHeightExtendedText" ), LFUNCVAL( lu8g2_setFontRefHeightExtendedText ) },
{ LSTRKEY( "setFontRefHeightText" ), LFUNCVAL( lu8g2_setFontRefHeightText ) },
{ LSTRKEY( "setPowerSave" ), LFUNCVAL( lu8g2_setPowerSave ) },
//{ LSTRKEY( "__gc" ), LFUNCVAL( lu8g2_display_free ) },
{ LSTRKEY( "__index" ), LROVAL( lu8g2_display_map ) },
{LNILKEY, LNILVAL}
};
uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
typedef void (*display_setup_fn_t)(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
// ***************************************************************************
// Device constructors
//
// I2C based devices will use this function template to implement the Lua binding.
//
static int ldisplay_i2c( lua_State *L, display_setup_fn_t setup_fn )
{
int stack = 0;
int id = -1;
int i2c_addr = -1;
int rfb_cb_ref = LUA_NOREF;
if (lua_type( L, ++stack) == LUA_TNUMBER) {
/* hardware display connected */
id = luaL_checkint( L, stack );
i2c_addr = luaL_checkint( L, ++stack );
luaL_argcheck( L, i2c_addr >= 0 && i2c_addr <= 0x7f, stack, "invalid i2c address" );
} else
stack--;
if (lua_isfunction( L, ++stack )) {
lua_pushvalue( L, stack );
rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX );
}
if (id < 0 && rfb_cb_ref == LUA_NOREF)
return luaL_error( L, "wrong args" );
u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) );
u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2);
ud->font_ref = LUA_NOREF;
ud->host_ref = LUA_NOREF;
/* the i2c driver id is forwarded in the hal member */
ext_u8g2->hal = id >= 0 ? (void *)id : NULL;
u8g2_t *u8g2 = (u8g2_t *)ext_u8g2;
u8x8_t *u8x8 = (u8x8_t *)u8g2;
setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_i2c, u8x8_gpio_and_delay_nodemcu );
/* prepare overlay data */
if (rfb_cb_ref != LUA_NOREF) {
ext_u8g2->overlay.template_display_cb = u8x8->display_cb;
ext_u8g2->overlay.hardware_display_cb = NULL;
ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF;
u8x8->display_cb = u8x8_d_overlay;
}
if (id >= 0) {
/* hardware device specific initialization */
u8x8_SetI2CAddress( u8x8, i2c_addr );
ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb;
}
u8g2_InitDisplay( (u8g2_t *)u8g2 );
u8g2_ClearDisplay( (u8g2_t *)u8g2 );
u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );
if (rfb_cb_ref != LUA_NOREF) {
/* finally enable rfb display driver */
ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref;
}
/* set its metatable */
luaL_getmetatable(L, "u8g2.display");
lua_setmetatable(L, -2);
return 1;
}
//
// SPI based devices will use this function template to implement the Lua binding.
//
static int ldisplay_spi( lua_State *L, display_setup_fn_t setup_fn )
{
int stack = 0;
#ifndef ESP_PLATFORM
// ESP8266
typedef struct {
int host;
} lspi_host_t;
lspi_host_t host_elem;
lspi_host_t *host = &host_elem;
#else
// ESP32
lspi_host_t *host = NULL;
#endif
int host_ref = LUA_NOREF;
int cs = -1;
int dc = -1;
int res = -1;
int rfb_cb_ref = LUA_NOREF;
int get_spi_pins;
if (lua_type( L, ++stack ) == LUA_TUSERDATA) {
host = (lspi_host_t *)luaL_checkudata( L, stack, "spi.master" );
/* reference host object to avoid automatic gc */
lua_pushvalue( L, stack );
host_ref = luaL_ref( L, LUA_REGISTRYINDEX );
get_spi_pins = 1;
} else if (lua_type( L, stack ) == LUA_TNUMBER) {
host->host = luaL_checkint( L, stack );
get_spi_pins = 1;
} else {
get_spi_pins = 0;
stack--;
}
if (get_spi_pins) {
cs = luaL_checkint( L, ++stack );
dc = luaL_checkint( L, ++stack );
res = luaL_optint( L, ++stack, -1 );
}
if (lua_isfunction( L, ++stack )) {
lua_pushvalue( L, stack );
rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX );
}
if (!host && rfb_cb_ref == LUA_NOREF)
return luaL_error( L, "wrong args" );
u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) );
u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2);
ud->font_ref = LUA_NOREF;
ud->host_ref = host_ref;
/* the spi host id is forwarded in the hal member */
ext_u8g2->hal = host ? (void *)(host->host) : NULL;
u8g2_t *u8g2 = (u8g2_t *)ext_u8g2;
u8x8_t *u8x8 = (u8x8_t *)u8g2;
setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_spi, u8x8_gpio_and_delay_nodemcu );
/* prepare overlay data */
if (rfb_cb_ref != LUA_NOREF) {
ext_u8g2->overlay.template_display_cb = u8x8->display_cb;
ext_u8g2->overlay.hardware_display_cb = NULL;
ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF;
u8x8->display_cb = u8x8_d_overlay;
}
if (host) {
/* hardware specific device initialization */
u8x8_SetPin( u8x8, U8X8_PIN_CS, cs );
u8x8_SetPin( u8x8, U8X8_PIN_DC, dc );
if (res >= 0)
u8x8_SetPin( u8x8, U8X8_PIN_RESET, res );
ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb;
}
u8g2_InitDisplay( (u8g2_t *)u8g2 );
u8g2_ClearDisplay( (u8g2_t *)u8g2 );
u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );
if (rfb_cb_ref != LUA_NOREF) {
/* finally enable rfb display driver */
ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref;
}
/* set its metatable */
luaL_getmetatable(L, "u8g2.display");
lua_setmetatable(L, -2);
return 1;
}
//
//
#undef U8G2_DISPLAY_TABLE_ENTRY
#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
static int l ## binding( lua_State *L ) \
{ \
return ldisplay_i2c( L, function ); \
}
//
// Unroll the display table and insert binding functions for I2C based displays.
U8G2_DISPLAY_TABLE_I2C
//
//
#undef U8G2_DISPLAY_TABLE_ENTRY
#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
static int l ## binding( lua_State *L ) \
{ \
return ldisplay_spi( L, function ); \
}
//
// Unroll the display table and insert binding functions for SPI based displays.
U8G2_DISPLAY_TABLE_SPI
//
#undef U8G2_FONT_TABLE_ENTRY
#undef U8G2_DISPLAY_TABLE_ENTRY
#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \
{ LSTRKEY( #binding ), LFUNCVAL( l ## binding ) },
static const LUA_REG_TYPE lu8g2_map[] = {
U8G2_DISPLAY_TABLE_I2C
U8G2_DISPLAY_TABLE_SPI
//
// Register fonts
#define U8G2_FONT_TABLE_ENTRY(font) \
{ LSTRKEY( #font ), LUDATA( (void *)(u8g2_ ## font) ) },
U8G2_FONT_TABLE
//
{ LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( U8G2_DRAW_UPPER_RIGHT ) },
{ LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( U8G2_DRAW_UPPER_LEFT ) },
{ LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( U8G2_DRAW_LOWER_RIGHT ) },
{ LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( U8G2_DRAW_LOWER_LEFT ) },
{ LSTRKEY( "DRAW_ALL" ), LNUMVAL( U8G2_DRAW_ALL ) },
{ LSTRKEY( "R0" ), LUDATA( (void *)U8G2_R0 ) },
{ LSTRKEY( "R1" ), LUDATA( (void *)U8G2_R1 ) },
{ LSTRKEY( "R2" ), LUDATA( (void *)U8G2_R2 ) },
{ LSTRKEY( "R3" ), LUDATA( (void *)U8G2_R3 ) },
{ LSTRKEY( "MIRROR" ), LUDATA( (void *)U8G2_MIRROR ) },
{LNILKEY, LNILVAL}
};
int luaopen_u8g2( lua_State *L ) {
luaL_rometatable(L, "u8g2.display", (void *)lu8g2_display_map);
return 0;
}
NODEMCU_MODULE(U8G2, "u8g2", lu8g2_map, luaopen_u8g2);
#endif /* defined(LUA_USE_MODULES_U8G2) || defined(ESP_PLATFORM) */

View File

@ -1,347 +0,0 @@
/*
Functions for integrating U8glib into the nodemcu platform.
*/
#include "lauxlib.h"
#include "platform.h"
#include "c_stdlib.h"
#include "u8g.h"
#include "u8g_glue.h"
// ------------------------------------------------------------
// comm functions
//
#define I2C_CMD_MODE 0x000
#define I2C_DATA_MODE 0x040
#define ESP_I2C_ID 0
static uint8_t do_i2c_start(uint8_t id, uint8_t sla)
{
platform_i2c_send_start( id );
// ignore return value -> tolerate missing ACK
platform_i2c_send_address( id, sla, PLATFORM_I2C_DIRECTION_TRANSMITTER );
return 1;
}
static uint8_t u8g_com_esp8266_ssd_start_sequence(struct _lu8g_userdata_t *lu8g)
{
/* are we requested to set the a0 state? */
if ( lu8g->u8g.pin_list[U8G_PI_SET_A0] == 0 )
return 1;
/* setup bus, might be a repeated start */
if ( do_i2c_start( ESP_I2C_ID, lu8g->i2c_addr ) == 0 )
return 0;
if ( lu8g->u8g.pin_list[U8G_PI_A0_STATE] == 0 )
{
// ignore return value -> tolerate missing ACK
if ( platform_i2c_send_byte( ESP_I2C_ID, I2C_CMD_MODE ) == 0 )
; //return 0;
}
else
{
platform_i2c_send_byte( ESP_I2C_ID, I2C_DATA_MODE );
}
lu8g->u8g.pin_list[U8G_PI_SET_A0] = 0;
return 1;
}
static void lu8g_digital_write( struct _lu8g_userdata_t *lu8g, uint8_t pin_index, uint8_t value )
{
uint8_t pin;
pin = lu8g->u8g.pin_list[pin_index];
if ( pin != U8G_PIN_NONE )
platform_gpio_write( pin, value );
}
void u8g_Delay(u8g_t *u8g, uint16_t msec)
{
struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
const uint16_t chunk = 50;
if (lu8g->use_delay == 0)
return;
while (msec > chunk)
{
os_delay_us( chunk*1000 );
msec -= chunk;
}
if (msec > 0)
os_delay_us( msec*1000 );
}
void u8g_MicroDelay(void)
{
os_delay_us( 1 );
}
void u8g_10MicroDelay(void)
{
os_delay_us( 10 );
}
uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
switch(msg)
{
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_INIT:
// we assume that the SPI interface was already initialized
// just care for the /CS and D/C pins
lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
platform_gpio_mode( lu8g->u8g.pin_list[U8G_PI_CS], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
platform_gpio_mode( lu8g->u8g.pin_list[U8G_PI_A0], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
lu8g_digital_write( lu8g, U8G_PI_A0, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
break;
case U8G_COM_MSG_CHIP_SELECT:
if (arg_val == 0)
{
/* disable */
lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
}
else
{
/* enable */
lu8g_digital_write( lu8g, U8G_PI_CS, PLATFORM_GPIO_LOW );
}
break;
case U8G_COM_MSG_RESET:
if ( lu8g->u8g.pin_list[U8G_PI_RESET] != U8G_PIN_NONE )
lu8g_digital_write( lu8g, U8G_PI_RESET, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
break;
case U8G_COM_MSG_WRITE_BYTE:
platform_spi_send( 1, 8, arg_val );
break;
case U8G_COM_MSG_WRITE_SEQ:
case U8G_COM_MSG_WRITE_SEQ_P:
{
register uint8_t *ptr = arg_ptr;
while( arg_val > 0 )
{
platform_spi_send( 1, 8, *ptr++ );
arg_val--;
}
}
break;
}
return 1;
}
uint8_t u8g_com_esp8266_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
struct _lu8g_userdata_t *lu8g = (struct _lu8g_userdata_t *)u8g;
switch(msg)
{
case U8G_COM_MSG_INIT:
// we assume that the i2c bus was already initialized
//u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]);
break;
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_RESET:
/* Currently disabled, but it could be enable. Previous restrictions have been removed */
/* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */
break;
case U8G_COM_MSG_CHIP_SELECT:
lu8g->u8g.pin_list[U8G_PI_A0_STATE] = 0;
lu8g->u8g.pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */
if ( arg_val == 0 )
{
/* disable chip, send stop condition */
platform_i2c_send_stop( ESP_I2C_ID );
}
else
{
/* enable, do nothing: any byte writing will trigger the i2c start */
}
break;
case U8G_COM_MSG_WRITE_BYTE:
//u8g->pin_list[U8G_PI_SET_A0] = 1;
if ( u8g_com_esp8266_ssd_start_sequence(lu8g) == 0 )
return platform_i2c_send_stop( ESP_I2C_ID ), 0;
// ignore return value -> tolerate missing ACK
if ( platform_i2c_send_byte( ESP_I2C_ID, arg_val) == 0 )
; //return platform_i2c_send_stop( ESP_I2C_ID ), 0;
// platform_i2c_send_stop( ESP_I2C_ID );
break;
case U8G_COM_MSG_WRITE_SEQ:
case U8G_COM_MSG_WRITE_SEQ_P:
//u8g->pin_list[U8G_PI_SET_A0] = 1;
if ( u8g_com_esp8266_ssd_start_sequence(lu8g) == 0 )
return platform_i2c_send_stop( ESP_I2C_ID ), 0;
{
register uint8_t *ptr = arg_ptr;
while( arg_val > 0 )
{
// ignore return value -> tolerate missing ACK
if ( platform_i2c_send_byte( ESP_I2C_ID, *ptr++) == 0 )
; //return platform_i2c_send_stop( ESP_I2C_ID ), 0;
arg_val--;
}
}
// platform_i2c_send_stop( ESP_I2C_ID );
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
lu8g->u8g.pin_list[U8G_PI_A0_STATE] = arg_val;
lu8g->u8g.pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */
break;
}
return 1;
}
// ***************************************************************************
// Generic framebuffer device and RLE comm driver
//
uint8_t u8g_dev_gen_fb_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg)
{
switch(msg)
{
case U8G_DEV_MSG_PAGE_FIRST:
// tell comm driver to start new framebuffer
u8g_SetChipSelect(u8g, dev, 1);
break;
case U8G_DEV_MSG_PAGE_NEXT:
{
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
if ( u8g_pb_WriteBuffer(pb, u8g, dev) == 0 )
return 0;
}
break;
}
return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg);
}
static int bit_at( uint8_t *buf, int line, int x )
{
uint8_t byte = buf[x];
return buf[x] & (1 << line) ? 1 : 0;
}
struct _lu8g_fbrle_item
{
uint8_t start_x;
uint8_t len;
};
struct _lu8g_fbrle_line
{
uint8_t num_valid;
struct _lu8g_fbrle_item items[0];
};
uint8_t u8g_com_esp8266_fbrle_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
struct _lu8g_userdata_t *lud = (struct _lu8g_userdata_t *)u8g;
switch(msg)
{
case U8G_COM_MSG_INIT:
// allocate memory -> done
// init buffer
break;
case U8G_COM_MSG_CHIP_SELECT:
if (arg_val == 1) {
// new frame starts
if (lud->cb_ref != LUA_NOREF) {
// fire callback with nil argument
lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, lud->cb_ref );
lua_pushnil( L );
lua_call( L, 1, 0 );
}
}
break;
case U8G_COM_MSG_WRITE_SEQ:
case U8G_COM_MSG_WRITE_SEQ_P:
{
uint8_t xwidth = u8g->pin_list[U8G_PI_EN];
size_t fbrle_line_size = sizeof( struct _lu8g_fbrle_line ) + sizeof( struct _lu8g_fbrle_item ) * (xwidth/2);
int num_lines = arg_val / (xwidth/8);
uint8_t *buf = (uint8_t *)arg_ptr;
struct _lu8g_fbrle_line *fbrle_line;
if (!(fbrle_line = (struct _lu8g_fbrle_line *)c_malloc( fbrle_line_size ))) {
break;
}
for (int line = 0; line < num_lines; line++) {
int start_run = -1;
fbrle_line->num_valid = 0;
for (int x = 0; x < xwidth; x++) {
if (bit_at( buf, line, x ) == 0) {
if (start_run >= 0) {
// inside run, end it and enter result
fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
fbrle_line->items[fbrle_line->num_valid++].len = x - start_run;
//NODE_ERR( " line: %d x: %d len: %d\n", line, start_run, x - start_run );
start_run = -1;
}
} else {
if (start_run < 0) {
// outside run, start it
start_run = x;
}
}
if (fbrle_line->num_valid >= xwidth/2) break;
}
// active run?
if (start_run >= 0 && fbrle_line->num_valid < xwidth/2) {
fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
fbrle_line->items[fbrle_line->num_valid++].len = xwidth - start_run;
}
// line done, trigger callback
if (lud->cb_ref != LUA_NOREF) {
lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, lud->cb_ref );
lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size );
lua_call( L, 1, 0 );
}
}
c_free( fbrle_line );
}
break;
}
return 1;
}

View File

@ -1,22 +0,0 @@
#ifndef _U8G_GLUE_H_
#define _U8G_GLUE_H_
#include "u8g.h"
struct _lu8g_userdata_t
{
u8g_t u8g;
uint8_t i2c_addr;
uint8_t use_delay;
int cb_ref;
};
typedef struct _lu8g_userdata_t lu8g_userdata_t;
// shorthand macro for the u8g structure inside the userdata
#define LU8G (&(lud->u8g))
uint8_t u8g_com_esp8266_fbrle_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_dev_gen_fb_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg);
#endif

0
app/modules/uart.c Executable file → Normal file
View File

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = mqtt.a
GEN_LIBS = libmqtt.a
endif
STD_CFLAGS=-std=gnu11 -Wimplicit

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = pcm.a
GEN_LIBS = libpcm.a
endif
STD_CFLAGS=-std=gnu11 -Wimplicit

View File

@ -43,6 +43,7 @@ INCLUDES += -I ./
INCLUDES += -I ../spiffs
INCLUDES += -I ../libc
INCLUDES += -I ../lua
INCLUDES += -I ../u8g2lib/u8g2/src/clib
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

View File

@ -24,7 +24,7 @@ extern char _flash_used_end[];
// Helper function: find the flash sector in which an address resides
// Return the sector number, as well as the start and end address of the sector
static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
static uint32_t flash_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
{
#ifdef INTERNAL_FLASH_SECTOR_SIZE
// All the sectors in the flash have the same size, so just align the address
@ -53,7 +53,7 @@ static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t
uint32_t platform_flash_get_sector_of_address( uint32_t addr )
{
return flashh_find_sector( addr, NULL, NULL );
return flash_find_sector( addr, NULL, NULL );
}
uint32_t platform_flash_get_num_sectors(void)
@ -73,12 +73,12 @@ uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
uint32_t start, end, sect;
NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
if(_flash_used_end>0){ // find the used sector
sect = flashh_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end );
sect = flash_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end );
if( psect )
*psect = sect + 1;
return end + 1;
}else{
sect = flashh_find_sector( 0, &start, NULL ); // find the first free sector
} else {
sect = flash_find_sector( 0, &start, NULL ); // find the first free sector
if( psect )
*psect = sect;
return start;

View File

@ -116,10 +116,11 @@ bool flash_rom_set_size_type(uint8_t size)
uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
((SPIFlashInfo *)(&data[0]))->size = size;
NODE_DBG("\nflash_rom_set_size_type(%u), was %u\n", size, ((SPIFlashInfo *)data)->size );
((SPIFlashInfo *)data)->size = size;
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
{
NODE_DBG("\nERASE SUCCESS\n");
NODE_DBG("\nSECTOR 0 ERASE SUCCESS\n");
}
if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
@ -266,6 +267,7 @@ bool flash_rom_set_speed(uint32_t speed)
if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
((SPIFlashInfo *)(&data[0]))->speed = speed_type;
NODE_DBG("\nflash_rom_set_speed(%u), was %u\n", speed_type, ((SPIFlashInfo *)(&data[0]))->speed );
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
{
NODE_DBG("\nERASE SUCCESS\n");

25
app/platform/platform.c Executable file → Normal file
View File

@ -879,7 +879,7 @@ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t siz
if(SPI_FLASH_RESULT_OK == r)
return size;
else{
NODE_ERR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr);
NODE_ERR( "ERROR in flash_write: r=%d at %p\n", r, toaddr);
return 0;
}
}
@ -917,26 +917,35 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
if(SPI_FLASH_RESULT_OK == r)
return size;
else{
NODE_ERR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr);
NODE_ERR( "ERROR in flash_read: r=%d at %p\n", r, fromaddr);
return 0;
}
}
int platform_flash_erase_sector( uint32_t sector_id )
{
NODE_DBG( "flash_erase_sector(%u)\n", sector_id);
system_soft_wdt_feed ();
return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
}
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
{
static uint32_t flash_map_meg_offset (void) {
uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG);
if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
return -1;
bool b0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 1 : 0;
bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0;
uint32_t meg = (b1 << 1) | b0;
return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000;
uint32_t m0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 0x100000 : 0;
uint32_t m1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 0x200000 : 0;
return m0 + m1;
}
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr) {
uint32_t meg = flash_map_meg_offset();
return (meg&1) ? -1 : mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg ;
}
uint32_t platform_flash_phys2mapped (uint32_t phys_addr) {
uint32_t meg = flash_map_meg_offset();
return (meg&1) ? -1 : phys_addr + INTERNAL_FLASH_MAPPED_ADDRESS - meg;
}
void* platform_print_deprecation_note( const char *msg, const char *time_frame)

View File

@ -279,13 +279,14 @@ int platform_flash_erase_sector( uint32_t sector_id );
/**
* Translated a mapped address to a physical flash address, based on the
* current flash cache mapping.
* current flash cache mapping, and v.v.
* @param mapped_addr Address to translate (>= INTERNAL_FLASH_MAPPED_ADDRESS)
* @return the corresponding physical flash address, or -1 if flash cache is
* not currently active.
* @see Cache_Read_Enable.
*/
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr);
uint32_t platform_flash_phys2mapped (uint32_t phys_addr);
// *****************************************************************************
// Allocator support

View File

@ -0,0 +1,291 @@
// Do not use the code from u8g2 submodule and skip the complete source here
// if the u8g2 module is not selected.
// Reason: The whole u8g2 submodule code tree might not even exist in this case.
#include "user_modules.h"
#ifdef LUA_USE_MODULES_U8G2
#include <string.h>
#include "c_stdlib.h"
#include "platform.h"
#define U8X8_USE_PINS
#include "u8x8_nodemcu_hal.h"
uint8_t u8x8_gpio_and_delay_nodemcu(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint32_t temp;
switch(msg)
{
case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8
// can be used to setup pins
for (int idx = 0; idx < U8X8_PIN_OUTPUT_CNT; idx++) {
if (u8x8->pins[idx] != U8X8_PIN_NONE) {
// configure pin as output
if (idx == U8X8_PIN_I2C_CLOCK || idx == U8X8_PIN_I2C_DATA) {
platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OPENDRAIN, PLATFORM_GPIO_PULLUP );
} else {
platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
}
}
}
break;
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
os_delay_us( 1 );
break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
temp = arg_int * 100;
temp /= 1000;
os_delay_us( temp > 0 ? temp : 1 );
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
os_delay_us( arg_int * 10 );
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
os_delay_us( arg_int * 1000 );
break;
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
temp = 5000 / arg_int; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
temp /= 1000;
os_delay_us( temp > 0 ? temp : 1 );
break;
case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int
//case U8X8_MSG_GPIO_SPI_CLOCK:
break;
case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int
//case U8X8_MSG_GPIO_SPI_DATA:
break;
case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
break;
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
break;
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
if (u8x8_GetPinValue( u8x8, msg ) != U8X8_PIN_NONE)
platform_gpio_write( u8x8_GetPinValue(u8x8, msg), arg_int );
break;
case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int
break;
case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
// arg_int=1: Input dir with pullup high for I2C clock pin
// for SW comm routine
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
break;
case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin
// arg_int=1: Input dir with pullup high for I2C data pin
// for SW comm routine
platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int );
break;
case U8X8_MSG_GPIO_MENU_SELECT:
case U8X8_MSG_GPIO_MENU_NEXT:
case U8X8_MSG_GPIO_MENU_PREV:
case U8X8_MSG_GPIO_MENU_HOME:
u8x8_SetGPIOResult( u8x8, /* get menu select pin state */ 0 );
break;
default:
u8x8_SetGPIOResult( u8x8, 1 ); // default return value
break;
}
return 1;
}
// static variables containing info about the i2c link
// TODO: move to user space in u8x8_t once available
typedef struct {
uint8_t id;
} hal_i2c_t;
uint8_t u8x8_byte_nodemcu_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
hal_i2c_t *hal = ((u8g2_nodemcu_t *)u8x8)->hal;
switch(msg) {
case U8X8_MSG_BYTE_SEND:
if (hal->id == 0) {
data = (uint8_t *)arg_ptr;
while( arg_int > 0 ) {
platform_i2c_send_byte( 0, *data );
data++;
arg_int--;
}
} else {
// invalid id
return 0;
}
break;
case U8X8_MSG_BYTE_INIT:
{
// the hal member initially contains the i2c id
int id = (int)hal;
if (!(hal = c_malloc( sizeof ( hal_i2c_t ) )))
return 0;
hal->id = id;
((u8g2_nodemcu_t *)u8x8)->hal = hal;
}
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
if (hal->id == 0) {
platform_i2c_send_start( 0 );
platform_i2c_send_address( 0, u8x8_GetI2CAddress(u8x8), PLATFORM_I2C_DIRECTION_TRANSMITTER );
} else {
// invalid id
return 0;
}
break;
case U8X8_MSG_BYTE_END_TRANSFER:
if (hal->id == 0) {
platform_i2c_send_stop( 0 );
} else {
// invalid id
return 0;
}
break;
default:
return 0;
}
return 1;
}
// static variables containing info about the spi link
// TODO: move to user space in u8x8_t once available
typedef struct {
uint8_t host;
//spi_device_handle_t device;
uint8_t last_dc;
struct {
uint8_t *data;
size_t size, used;
} buffer;
} hal_spi_t;
static void flush_buffer_spi( hal_spi_t *hal )
{
if (hal->buffer.used > 0) {
platform_spi_blkwrite( hal->host, hal->buffer.used, hal->buffer.data );
hal->buffer.used = 0;
}
}
uint8_t u8x8_byte_nodemcu_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
hal_spi_t *hal = ((u8g2_nodemcu_t *)u8x8)->hal;
switch(msg) {
case U8X8_MSG_BYTE_INIT:
{
/* disable chipselect */
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level );
// the hal member initially contains the spi host id
int host = (int)hal;
if (!(hal = c_malloc( sizeof ( hal_spi_t ) )))
return 0;
hal->host = host;
((u8g2_nodemcu_t *)u8x8)->hal = hal;
hal->last_dc = 0;
}
break;
case U8X8_MSG_BYTE_SET_DC:
if (hal->last_dc != arg_int)
flush_buffer_spi( hal );
u8x8_gpio_SetDC( u8x8, arg_int );
hal->last_dc = arg_int;
break;
case U8X8_MSG_BYTE_START_TRANSFER:
hal->buffer.size = 256;
if (!(hal->buffer.data = (uint8_t *)c_malloc( hal->buffer.size )))
return 0;
hal->buffer.used = 0;
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_enable_level );
break;
case U8X8_MSG_BYTE_SEND:
if (!hal->buffer.data)
return 0;
while (hal->buffer.size - hal->buffer.used < arg_int) {
hal->buffer.size *= 2;
uint8_t *tmp;
if (!(tmp = (uint8_t *)c_malloc( hal->buffer.size ))) {
c_free( hal->buffer.data );
hal->buffer.data = NULL;
return 0;
}
os_memcpy( tmp, hal->buffer.data, hal->buffer.used );
c_free( hal->buffer.data );
hal->buffer.data = tmp;
}
os_memcpy( hal->buffer.data + hal->buffer.used, arg_ptr, arg_int );
hal->buffer.used += arg_int;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
if (!hal->buffer.data)
return 0;
flush_buffer_spi( hal );
u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level );
c_free( hal->buffer.data );
break;
default:
return 0;
}
return 1;
}
#endif /* LUA_USE_MODULES_U8G2 */

View File

@ -0,0 +1,26 @@
#ifndef _U8X8_NODEMCU_HAL_H
#define _U8X8_NODEMCU_HAL_H
#include "u8g2.h"
// extend standard u8g2_t struct with info that's needed in the communication callbacks
typedef struct {
u8g2_t u8g2;
void *hal;
// elements for the overlay display driver
struct {
u8x8_msg_cb hardware_display_cb, template_display_cb;
int rfb_cb_ref;
uint8_t fb_update_ongoing;
} overlay;
} u8g2_nodemcu_t;
uint8_t u8x8_gpio_and_delay_nodemcu(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_byte_nodemcu_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_byte_nodemcu_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
#endif /* _U8X8_NODEMCU_HAL_H */

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = tsl2561lib.a
GEN_LIBS = libtsl2561.a
endif
STD_CFLAGS=-std=gnu11 -Wimplicit

View File

@ -12,7 +12,7 @@
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = u8glib.a
GEN_LIBS = libu8g2lib.a
endif
STD_CFLAGS=-std=gnu11 -Wimplicit
@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
DEFINES += -DU8X8_USE_PINS
#############################################################
# Recursion Magic - Don't touch this!!
@ -38,9 +38,13 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# Required for each makefile to inherit from the parent
#
CSRCS := $(wildcard u8g2/src/clib/*.c *.c)
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
INCLUDES += -I u8g2/src/clib
INCLUDES += -I ../libc
INCLUDES += -I ../lua
INCLUDES += -I ../platform
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

1
app/u8g2lib/u8g2 Submodule

@ -0,0 +1 @@
Subproject commit 7f2fc42af3d01fdfe2cc19320bdcfe693dd2b20d

184
app/u8g2lib/u8x8_d_fbrle.c Normal file
View File

@ -0,0 +1,184 @@
// Note: This file is intended to be shared between esp8266 and esp32 platform
#include "u8x8.h"
#include "lauxlib.h"
#include "u8x8_nodemcu_hal.h"
#include "c_stdlib.h"
static const u8x8_display_info_t u8x8_fbrle_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 0,
/* pre_chip_disable_wait_ns = */ 0,
/* reset_pulse_width_ms = */ 0,
/* post_reset_wait_ms = */ 0,
/* sda_setup_time_ns = */ 0,
/* sck_pulse_width_ns = */ 0,
/* sck_clock_hz = */ 0,
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 0,
/* write_pulse_width_ns = */ 0,
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static int bit_at( uint8_t *buf, int line, int x )
{
return buf[x] & (1 << line) ? 1 : 0;
}
struct fbrle_item
{
uint8_t start_x;
uint8_t len;
};
struct fbrle_line
{
uint8_t num_valid;
struct fbrle_item items[0];
};
static uint8_t u8x8_d_fbrle(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
// forward to template display driver
return ext_u8g2->overlay.template_display_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_DISPLAY_INIT:
//u8x8_d_helper_display_init(u8x8);
ext_u8g2->overlay.fb_update_ongoing = 0;
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
break;
#endif
case U8X8_MSG_DISPLAY_REFRESH:
ext_u8g2->overlay.fb_update_ongoing = 0;
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
if (ext_u8g2->overlay.fb_update_ongoing == 0) {
// tell rfb callback that a new framebuffer starts
if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) {
// fire callback with nil argument
lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
lua_pushnil( L );
lua_call( L, 1, 0 );
}
// and note ongoing framebuffer update
ext_u8g2->overlay.fb_update_ongoing = 1;
}
{
// TODO: transport tile_y, needs structural change!
uint8_t tile_x = ((u8x8_tile_t *)arg_ptr)->x_pos;
tile_x *= 8;
tile_x += u8x8->x_offset;
uint8_t tile_w = ((u8x8_tile_t *)arg_ptr)->cnt * 8;
size_t fbrle_line_size = sizeof( struct fbrle_line ) + sizeof( struct fbrle_item ) * (tile_w/2);
int num_lines = 8; /*arg_val / (xwidth/8);*/
uint8_t *buf = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
struct fbrle_line *fbrle_line;
if (!(fbrle_line = (struct fbrle_line *)c_malloc( fbrle_line_size ))) {
break;
}
for (int line = 0; line < num_lines; line++) {
int start_run = -1;
fbrle_line->num_valid = 0;
for (int x = tile_x; x < tile_x+tile_w; x++) {
if (bit_at( buf, line, x ) == 0) {
if (start_run >= 0) {
// inside run, end it and enter result
fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
fbrle_line->items[fbrle_line->num_valid++].len = x - start_run;
//NODE_ERR( " line: %d x: %d len: %d\n", line, start_run, x - start_run );
start_run = -1;
}
} else {
if (start_run < 0) {
// outside run, start it
start_run = x;
}
}
if (fbrle_line->num_valid >= tile_w/2) break;
}
// active run?
if (start_run >= 0 && fbrle_line->num_valid < tile_w/2) {
fbrle_line->items[fbrle_line->num_valid].start_x = start_run;
fbrle_line->items[fbrle_line->num_valid++].len = tile_w - start_run;
}
// line done, trigger callback
if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) {
lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref );
lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size );
lua_call( L, 1, 0 );
}
}
c_free( fbrle_line );
}
break;
default:
return 0;
break;
}
return 1;
}
uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t res = 1;
u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
// only call for hardware display
if (ext_u8g2->overlay.hardware_display_cb)
return ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr);
break;
default:
// forward all messages first to hardware display and then to fbrle
if (ext_u8g2->overlay.hardware_display_cb)
res = ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr);
u8x8_d_fbrle(u8x8, msg, arg_int, arg_ptr);
break;
}
return res;
}

View File

@ -1,34 +0,0 @@
##U8glib package
Ported from https://github.com/olikraus/u8glib
Here is black magic with ImageMagic package for image conversion:
```bash
#!/bin/bash
mkdir out
for icon in *png; do
convert $icon -depth 1 ./out/$(basename $icon .png)_1bpp.png
if [[ "$icon" == *"black"* ]]; then
convert ./out/$(basename $icon .png)_1bpp.png -background white -alpha Background ./out/$(basename $icon .png)_1bpp.xbm
else
convert ./out/$(basename $icon .png)_1bpp.png -background black -alpha Background ./out/$(basename $icon .png)_1bpp.xbm
fi
cat ./out/$(basename $icon .png)_1bpp.xbm | tr '\n' ' ' | tr -d " " |sed -e s'#^.*{##g' | sed s'#,}##' |sed s'/;//' | xxd -r -p > ./out/$(basename $icon .png).xbm.mono
done
rm out/*png out/*xbm
```
Convert all the png in the current folder and put resulting .mono to ./out
The convert binary is a part of ImageMagic package. You need to install it.
```
sudo apt-get install imagemagick
```
for Debian/Ubuntu.

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +0,0 @@
/*
u8g_bitmap.c
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
void u8g_DrawHBitmap(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, const uint8_t *bitmap)
{
while( cnt > 0 )
{
u8g_Draw8Pixel(u8g, x, y, 0, *bitmap);
bitmap++;
cnt--;
x+=8;
}
}
void u8g_DrawBitmap(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const uint8_t *bitmap)
{
if ( u8g_IsBBXIntersection(u8g, x, y, cnt*8, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHBitmap(u8g, x, y, cnt, bitmap);
bitmap += cnt;
y++;
h--;
}
}
void u8g_DrawHBitmapP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, const u8g_pgm_uint8_t *bitmap)
{
while( cnt > 0 )
{
u8g_Draw8Pixel(u8g, x, y, 0, u8g_pgm_read(bitmap));
bitmap++;
cnt--;
x+=8;
}
}
void u8g_DrawBitmapP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
{
if ( u8g_IsBBXIntersection(u8g, x, y, cnt*8, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHBitmapP(u8g, x, y, cnt, bitmap);
bitmap += cnt;
y++;
h--;
}
}
/*=========================================================================*/
static void u8g_DrawHXBM(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, const uint8_t *bitmap)
{
uint8_t d;
x+=7;
while( w >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 2, *bitmap);
bitmap++;
w-= 8;
x+=8;
}
if ( w > 0 )
{
d = *bitmap;
x -= 7;
do
{
if ( d & 1 )
u8g_DrawPixel(u8g, x, y);
x++;
w--;
d >>= 1;
} while ( w > 0 );
}
}
void u8g_DrawXBM(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, const uint8_t *bitmap)
{
u8g_uint_t b;
b = w;
b += 7;
b >>= 3;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHXBM(u8g, x, y, w, bitmap);
bitmap += b;
y++;
h--;
}
}
static void u8g_DrawHXBMP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, const u8g_pgm_uint8_t *bitmap)
{
uint8_t d;
x+=7;
while( w >= 8 )
{
u8g_Draw8Pixel(u8g, x, y, 2, u8g_pgm_read(bitmap));
bitmap++;
w-= 8;
x+=8;
}
if ( w > 0 )
{
d = u8g_pgm_read(bitmap);
x -= 7;
do
{
if ( d & 1 )
u8g_DrawPixel(u8g, x, y);
x++;
w--;
d >>= 1;
} while ( w > 0 );
}
}
void u8g_DrawXBMP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
{
u8g_uint_t b;
b = w;
b += 7;
b >>= 3;
if ( u8g_IsBBXIntersection(u8g, x, y, w, h) == 0 )
return;
while( h > 0 )
{
u8g_DrawHXBMP(u8g, x, y, w, bitmap);
bitmap += b;
y++;
h--;
}
}

View File

@ -1,382 +0,0 @@
/*
u8g_circle.c
Utility to draw empty and filled circles.
Universal 8bit Graphics Library
Copyright (c) 2011, bjthom@gmail.com
u8g_DrawCircle & u8g_DrawDisc by olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Addition to the U8G Library 02/25/12
*/
#include "u8g.h"
#ifdef OLD_CODE
void circ_upperRight(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0) {
u8g_DrawPixel(u8g, x0 + x, y0 - y);
u8g_DrawPixel(u8g, x0 + y, y0 - x);
}
void circ_upperLeft(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0) {
u8g_DrawPixel(u8g, x0 - x, y0 - y);
u8g_DrawPixel(u8g, x0 - y, y0 - x);
}
void circ_lowerRight(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0) {
u8g_DrawPixel(u8g, x0 + x, y0 + y);
u8g_DrawPixel(u8g, x0 + y, y0 + x);
}
void circ_lowerLeft(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0) {
u8g_DrawPixel(u8g, x0 - x, y0 + y);
u8g_DrawPixel(u8g, x0 - y, y0 + x);
}
void circ_all(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0) {
circ_upperRight(u8g, x, y, x0, y0);
circ_upperLeft(u8g, x, y, x0, y0);
circ_lowerRight(u8g, x, y, x0, y0);
circ_lowerLeft(u8g, x, y, x0, y0);
}
void u8g_DrawEmpCirc(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
if ( u8g_IsBBXIntersection(u8g, x0-rad-1, y0-rad-1, 2*rad+1, 2*rad+1) == 0)
return;
int f = 1 - rad;
int ddF_x = 1;
int ddF_y = -2*rad;
uint8_t x = 0;
uint8_t y = rad;
void ( *circ_util )(u8g_t *, u8g_uint_t, u8g_uint_t, u8g_uint_t, u8g_uint_t);
switch (option)
{
case U8G_CIRC_UPPER_RIGHT:
u8g_DrawPixel(u8g, x0, y0 - rad);
u8g_DrawPixel(u8g, x0 + rad, y0);
circ_util = circ_upperRight;
break;
case U8G_CIRC_UPPER_LEFT:
u8g_DrawPixel(u8g, x0, y0 - rad);
u8g_DrawPixel(u8g, x0 - rad, y0);
circ_util = circ_upperLeft;
break;
case U8G_CIRC_LOWER_RIGHT:
u8g_DrawPixel(u8g, x0, y0 + rad);
u8g_DrawPixel(u8g, x0 + rad, y0);
circ_util = circ_lowerRight;
break;
case U8G_CIRC_LOWER_LEFT:
u8g_DrawPixel(u8g, x0, y0 + rad);
u8g_DrawPixel(u8g, x0 - rad, y0);
circ_util = circ_lowerLeft;
break;
default:
case U8G_CIRC_ALL:
u8g_DrawPixel(u8g, x0, y0 + rad);
u8g_DrawPixel(u8g, x0, y0 - rad);
u8g_DrawPixel(u8g, x0 + rad, y0);
u8g_DrawPixel(u8g, x0 - rad, y0);
circ_util = circ_all;
break;
}
while( x < y )
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
circ_util(u8g, x, y, x0, y0);
}
}
void u8g_DrawFillCirc(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
if ( u8g_IsBBXIntersection(u8g, x0-rad-1, y0-rad-1, 2*rad+1, 2*rad+1) == 0)
return;
int f = 1 - rad;
int ddF_x = 1;
int ddF_y = -2*rad;
uint8_t x = 0;
uint8_t y = rad;
// Draw vertical diameter at the horiz. center
// u8g_DrawVLine(u8g, x0, y0 - rad, 2*rad+1);
if (option == U8G_CIRC_UPPER_LEFT || option == U8G_CIRC_UPPER_RIGHT) {
u8g_DrawVLine(u8g, x0, y0 - rad, rad+1);
}
else if (option == U8G_CIRC_LOWER_LEFT || option == U8G_CIRC_LOWER_RIGHT) {
u8g_DrawVLine(u8g, x0, y0, rad+1);
}
else {
u8g_DrawVLine(u8g, x0, y0 - rad, 2*rad+1);
}
while( x < y )
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
//Draw vertical lines from one point to another
switch (option)
{
case U8G_CIRC_UPPER_RIGHT:
u8g_DrawVLine(u8g, x0+x, y0-y, y+1);
u8g_DrawVLine(u8g, x0+y, y0-x, x+1);
break;
case U8G_CIRC_UPPER_LEFT:
u8g_DrawVLine(u8g, x0-x, y0-y, y+1);
u8g_DrawVLine(u8g, x0-y, y0-x, x+1);
break;
case U8G_CIRC_LOWER_RIGHT:
u8g_DrawVLine(u8g, x0+x, y0, y+1);
u8g_DrawVLine(u8g, x0+y, y0, x+1);
break;
case U8G_CIRC_LOWER_LEFT:
u8g_DrawVLine(u8g, x0-x, y0, y+1);
u8g_DrawVLine(u8g, x0-y, y0, x+1);
break;
case U8G_CIRC_ALL:
u8g_DrawVLine(u8g, x0+x, y0-y, 2*y+1);
u8g_DrawVLine(u8g, x0-x, y0-y, 2*y+1);
u8g_DrawVLine(u8g, x0+y, y0-x, 2*x+1);
u8g_DrawVLine(u8g, x0-y, y0-x, 2*x+1);
break;
}
}
}
#endif
/*=========================================================================*/
static void u8g_draw_circle_section(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0, uint8_t option) U8G_NOINLINE;
static void u8g_draw_circle_section(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G_DRAW_UPPER_RIGHT )
{
u8g_DrawPixel(u8g, x0 + x, y0 - y);
u8g_DrawPixel(u8g, x0 + y, y0 - x);
}
/* upper left */
if ( option & U8G_DRAW_UPPER_LEFT )
{
u8g_DrawPixel(u8g, x0 - x, y0 - y);
u8g_DrawPixel(u8g, x0 - y, y0 - x);
}
/* lower right */
if ( option & U8G_DRAW_LOWER_RIGHT )
{
u8g_DrawPixel(u8g, x0 + x, y0 + y);
u8g_DrawPixel(u8g, x0 + y, y0 + x);
}
/* lower left */
if ( option & U8G_DRAW_LOWER_LEFT )
{
u8g_DrawPixel(u8g, x0 - x, y0 + y);
u8g_DrawPixel(u8g, x0 - y, y0 + x);
}
}
void u8g_draw_circle(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
u8g_int_t f;
u8g_int_t ddF_x;
u8g_int_t ddF_y;
u8g_uint_t x;
u8g_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g_draw_circle_section(u8g, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g_draw_circle_section(u8g, x, y, x0, y0, option);
}
}
void u8g_DrawCircle(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
/* check for bounding box */
{
u8g_uint_t radp, radp2;
radp = rad;
radp++;
radp2 = radp;
radp2 *= 2;
if ( u8g_IsBBXIntersection(u8g, x0-radp, y0-radp, radp2, radp2) == 0)
return;
}
/* draw circle */
u8g_draw_circle(u8g, x0, y0, rad, option);
}
static void u8g_draw_disc_section(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0, uint8_t option) U8G_NOINLINE;
static void u8g_draw_disc_section(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t x0, u8g_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G_DRAW_UPPER_RIGHT )
{
u8g_DrawVLine(u8g, x0+x, y0-y, y+1);
u8g_DrawVLine(u8g, x0+y, y0-x, x+1);
}
/* upper left */
if ( option & U8G_DRAW_UPPER_LEFT )
{
u8g_DrawVLine(u8g, x0-x, y0-y, y+1);
u8g_DrawVLine(u8g, x0-y, y0-x, x+1);
}
/* lower right */
if ( option & U8G_DRAW_LOWER_RIGHT )
{
u8g_DrawVLine(u8g, x0+x, y0, y+1);
u8g_DrawVLine(u8g, x0+y, y0, x+1);
}
/* lower left */
if ( option & U8G_DRAW_LOWER_LEFT )
{
u8g_DrawVLine(u8g, x0-x, y0, y+1);
u8g_DrawVLine(u8g, x0-y, y0, x+1);
}
}
void u8g_draw_disc(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
u8g_int_t f;
u8g_int_t ddF_x;
u8g_int_t ddF_y;
u8g_uint_t x;
u8g_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g_draw_disc_section(u8g, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g_draw_disc_section(u8g, x, y, x0, y0, option);
}
}
void u8g_DrawDisc(u8g_t *u8g, u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t option)
{
/* check for bounding box */
{
u8g_uint_t radp, radp2;
radp = rad;
radp++;
radp2 = radp;
radp2 *= 2;
if ( u8g_IsBBXIntersection(u8g, x0-radp, y0-radp, radp2, radp2) == 0)
return;
}
/* draw disc */
u8g_draw_disc(u8g, x0, y0, rad, option);
}

View File

@ -1,156 +0,0 @@
/*
u8g_clip.c
procedures for clipping
taken over from procs in u8g_pb.c
Universal 8bit Graphics Library
Copyright (c) 2012, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Notes
This is one of the most critical parts of u8glib. It must be fast, but still reliable.
Based on the intersection program (see tools folder), there is minimized version of
the condition for the intersaction test:
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
It includes the assumption, that a1 <= a2 is always true (correct, because
a1, a2 are the page dimensions.
The direct implementation of the above result is done in:
uint8_t u8g_is_intersection_boolean(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
However, this is slower than a decision tree version:
static uint8_t u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
Also suprising is, that the macro implementation is slower than the inlined version.
The decision tree is based on the expansion of the truth table.
*/
#include "u8g.h"
#ifdef __GNUC__
#define U8G_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
#define U8G_ALWAYS_INLINE
#endif
/*
intersection assumptions:
a1 <= a2 is always true
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
*/
#ifdef OLD_CODE_WHICH_IS_TOO_SLOW
static uint8_t u8g_is_intersection_boolean(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
{
uint8_t c1, c2, c3, tmp;
c1 = v0 <= a1;
c2 = v1 >= a0;
c3 = v0 > v1;
tmp = c1;
c1 &= c2;
c2 &= c3;
c3 &= tmp;
c1 |= c2;
c1 |= c3;
return c1 & 1;
}
#endif
#define U8G_IS_INTERSECTION_MACRO(a0,a1,v0,v1) ((uint8_t)( (v0) <= (a1) ) ? ( ( (v1) >= (a0) ) ? ( 1 ) : ( (v0) > (v1) ) ) : ( ( (v1) >= (a0) ) ? ( (v0) > (v1) ) : ( 0 ) ))
//static uint8_t u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1) U8G_ALWAYS_INLINE;
static uint8_t U8G_ALWAYS_INLINE u8g_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
{
/* surprisingly the macro leads to larger code */
/* return U8G_IS_INTERSECTION_MACRO(a0,a1,v0,v1); */
if ( v0 <= a1 )
{
if ( v1 >= a0 )
{
return 1;
}
else
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 >= a0 )
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
uint8_t u8g_IsBBXIntersection(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
{
register u8g_uint_t tmp;
tmp = y;
tmp += h;
tmp--;
if ( u8g_is_intersection_decision_tree(u8g->current_page.y0, u8g->current_page.y1, y, tmp) == 0 )
return 0;
tmp = x;
tmp += w;
tmp--;
return u8g_is_intersection_decision_tree(u8g->current_page.x0, u8g->current_page.x1, x, tmp);
}

View File

@ -1,173 +0,0 @@
/*
u8g_com_api.c
Universal 8bit Graphics Library
Copyright (c) 2011, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g.h"
uint8_t u8g_InitCom(u8g_t *u8g, u8g_dev_t *dev, uint8_t clk_cycle_time)
{
return dev->com_fn(u8g, U8G_COM_MSG_INIT, clk_cycle_time, NULL);
}
void u8g_StopCom(u8g_t *u8g, u8g_dev_t *dev)
{
dev->com_fn(u8g, U8G_COM_MSG_STOP, 0, NULL);
}
/* cs contains the chip number, which should be enabled */
void u8g_SetChipSelect(u8g_t *u8g, u8g_dev_t *dev, uint8_t cs)
{
dev->com_fn(u8g, U8G_COM_MSG_CHIP_SELECT, cs, NULL);
}
void u8g_SetResetLow(u8g_t *u8g, u8g_dev_t *dev)
{
dev->com_fn(u8g, U8G_COM_MSG_RESET, 0, NULL);
}
void u8g_SetResetHigh(u8g_t *u8g, u8g_dev_t *dev)
{
dev->com_fn(u8g, U8G_COM_MSG_RESET, 1, NULL);
}
void u8g_SetAddress(u8g_t *u8g, u8g_dev_t *dev, uint8_t address)
{
dev->com_fn(u8g, U8G_COM_MSG_ADDRESS, address, NULL);
}
uint8_t u8g_WriteByte(u8g_t *u8g, u8g_dev_t *dev, uint8_t val)
{
return dev->com_fn(u8g, U8G_COM_MSG_WRITE_BYTE, val, NULL);
}
uint8_t u8g_WriteSequence(u8g_t *u8g, u8g_dev_t *dev, uint8_t cnt, uint8_t *seq)
{
return dev->com_fn(u8g, U8G_COM_MSG_WRITE_SEQ, cnt, seq);
}
uint8_t u8g_WriteSequenceP(u8g_t *u8g, u8g_dev_t *dev, uint8_t cnt, const uint8_t *seq)
{
return dev->com_fn(u8g, U8G_COM_MSG_WRITE_SEQ_P, cnt, (void *)seq);
}
/*
sequence := { direct_value | escape_sequence }
direct_value := 0..254
escape_sequence := value_255 | sequence_end | delay | adr | cs | not_used
value_255 := 255 255
sequence_end = 255 254
delay := 255 0..127
adr := 255 0x0e0 .. 0x0ef
cs := 255 0x0d0 .. 0x0df
not_used := 255 101..254
#define U8G_ESC_DLY(x) 255, ((x) & 0x7f)
#define U8G_ESC_CS(x) 255, (0xd0 | ((x)&0x0f))
#define U8G_ESC_ADR(x) 255, (0xe0 | ((x)&0x0f))
#define U8G_ESC_VCC(x) 255, (0xbe | ((x)&0x01))
#define U8G_ESC_END 255, 254
#define U8G_ESC_255 255, 255
#define U8G_ESC_RST(x) 255, (0xc0 | ((x)&0x0f))
*/
uint8_t u8g_WriteEscSeqP(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq)
{
uint8_t is_escape = 0;
uint8_t value;
for(;;)
{
value = u8g_pgm_read(esc_seq);
if ( is_escape == 0 )
{
if ( value != 255 )
{
if ( u8g_WriteByte(u8g, dev, value) == 0 )
return 0;
}
else
{
is_escape = 1;
}
}
else
{
if ( value == 255 )
{
if ( u8g_WriteByte(u8g, dev, value) == 0 )
return 0;
}
else if ( value == 254 )
{
break;
}
else if ( value >= 0x0f0 )
{
/* not yet used, do nothing */
}
else if ( value >= 0xe0 )
{
u8g_SetAddress(u8g, dev, value & 0x0f);
}
else if ( value >= 0xd0 )
{
u8g_SetChipSelect(u8g, dev, value & 0x0f);
}
else if ( value >= 0xc0 )
{
u8g_SetResetLow(u8g, dev);
value &= 0x0f;
value <<= 4;
value+=2;
u8g_Delay(u8g, value);
u8g_SetResetHigh(u8g, dev);
u8g_Delay(u8g, value);
}
else if ( value >= 0xbe )
{
/* not yet implemented */
/* u8g_SetVCC(u8g, dev, value & 0x01); */
}
else if ( value <= 127 )
{
u8g_Delay(u8g, value);
}
is_escape = 0;
}
esc_seq++;
}
return 1;
}

Some files were not shown because too many files have changed in this diff Show More