mirror of
https://github.com/nodemcu/nodemcu-firmware.git
synced 2025-01-16 20:52:57 +08:00
commit
b41667b837
34
.gdbinit
Normal file
34
.gdbinit
Normal 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
182
.gdbinitlua
Normal 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
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
sdk/
|
sdk/
|
||||||
cache/
|
cache/
|
||||||
.ccache/
|
.ccache/
|
||||||
|
local/
|
||||||
|
luac.cross
|
||||||
user_config.h
|
user_config.h
|
||||||
server-ca.crt
|
server-ca.crt
|
||||||
|
|
||||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "app/u8g2lib/u8g2"]
|
||||||
|
path = app/u8g2lib/u8g2
|
||||||
|
url = https://github.com/olikraus/U8g2_Arduino.git
|
@ -5,21 +5,13 @@ addons:
|
|||||||
packages:
|
packages:
|
||||||
- python-serial
|
- python-serial
|
||||||
- srecord
|
- srecord
|
||||||
- lua5.1
|
|
||||||
cache:
|
cache:
|
||||||
- pip
|
|
||||||
- directories:
|
- directories:
|
||||||
- cache
|
- cache
|
||||||
before_install:
|
|
||||||
- pip install --user hererocks esptool
|
|
||||||
- hererocks env --lua 5.1 -rlatest
|
|
||||||
- source env/bin/activate
|
|
||||||
- luarocks install luafilesystem
|
|
||||||
install:
|
install:
|
||||||
- tar -Jxvf tools/esp-open-sdk.tar.xz
|
- tar -Jxvf tools/esp-open-sdk.tar.xz
|
||||||
- export PATH=$PATH:$PWD/esp-open-sdk/xtensa-lx106-elf/bin
|
- export PATH=$PATH:$PWD/esp-open-sdk/xtensa-lx106-elf/bin
|
||||||
script:
|
script:
|
||||||
- lua tools/cross-lua.lua || exit 1
|
|
||||||
- export BUILD_DATE=$(date +%Y%m%d)
|
- export BUILD_DATE=$(date +%Y%m%d)
|
||||||
- make EXTRA_CCFLAGS="-DBUILD_DATE='\"'$BUILD_DATE'\"'" all
|
- make EXTRA_CCFLAGS="-DBUILD_DATE='\"'$BUILD_DATE'\"'" all
|
||||||
- cd bin/
|
- cd bin/
|
||||||
|
@ -63,7 +63,9 @@ Avoid intermediate merge commits. [Rebase](https://www.atlassian.com/git/tutoria
|
|||||||
1. `git push`
|
1. `git push`
|
||||||
1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) (PR) on GitHub.
|
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
|
### 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).
|
You need to sync your fork with the NodeMCU upstream repository from time to time, latest before you rebase (see flow above).
|
||||||
|
34
Makefile
34
Makefile
@ -3,20 +3,20 @@
|
|||||||
.NOTPARALLEL:
|
.NOTPARALLEL:
|
||||||
|
|
||||||
# SDK base version, as released by Espressif
|
# 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
|
# no patch: SDK_VER equals SDK_BASE_VER and sdk dir depends on sdk_extracted
|
||||||
#SDK_VER:=$(SDK_BASE_VER)
|
SDK_VER:=$(SDK_BASE_VER)
|
||||||
#SDK_DIR_DEPENDS:=sdk_extracted
|
SDK_DIR_DEPENDS:=sdk_extracted
|
||||||
|
|
||||||
# with patch: SDK_VER differs from SDK_BASE_VER and sdk dir depends on sdk_patched
|
# with patch: SDK_VER differs from SDK_BASE_VER and sdk dir depends on sdk_patched
|
||||||
SDK_PATCH_VER:=f8f27ce
|
#SDK_PATCH_VER:=f8f27ce
|
||||||
SDK_VER:=$(SDK_BASE_VER)-$(SDK_PATCH_VER)
|
#SDK_VER:=$(SDK_BASE_VER)-$(SDK_PATCH_VER)
|
||||||
SDK_DIR_DEPENDS:=sdk_patched
|
#SDK_DIR_DEPENDS:=sdk_patched
|
||||||
|
|
||||||
SDK_FILE_VER:=$(SDK_BASE_VER)
|
SDK_FILE_VER:=$(SDK_BASE_VER)
|
||||||
SDK_FILE_SHA1:=8b63f1066d3560ff77f119e8ba30a9c39e7baaad
|
SDK_FILE_SHA1:=48f2242d5895823709f222bf0fffce9d525996c8
|
||||||
SDK_PATCH_SHA1:=0bc21ec77b08488f04d3e1c9d161b711d07201a8
|
# SDK_PATCH_SHA1:=0bc21ec77b08488f04d3e1c9d161b711d07201a8
|
||||||
# Ensure we search "our" SDK before the tool-chain's SDK (if any)
|
# Ensure we search "our" SDK before the tool-chain's SDK (if any)
|
||||||
TOP_DIR:=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
TOP_DIR:=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||||
SDK_REL_DIR=sdk/esp_iot_sdk_v$(SDK_VER)
|
SDK_REL_DIR=sdk/esp_iot_sdk_v$(SDK_VER)
|
||||||
@ -28,7 +28,7 @@ ifdef DEBUG
|
|||||||
CCFLAGS += -ggdb -O0
|
CCFLAGS += -ggdb -O0
|
||||||
LDFLAGS += -ggdb
|
LDFLAGS += -ggdb
|
||||||
else
|
else
|
||||||
CCFLAGS += -Os
|
CCFLAGS += -O2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
@ -227,8 +227,8 @@ $(TOP_DIR)/sdk/.patched-$(SDK_VER): $(TOP_DIR)/cache/$(SDK_PATCH_VER).patch
|
|||||||
|
|
||||||
$(TOP_DIR)/sdk/.pruned-$(SDK_VER):
|
$(TOP_DIR)/sdk/.pruned-$(SDK_VER):
|
||||||
rm -f $(SDK_DIR)/lib/liblwip.a $(SDK_DIR)/lib/libssl.a $(SDK_DIR)/lib/libmbedtls.a
|
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/libmain.a time.o
|
||||||
ar d $(SDK_DIR)/lib/libc.a lib_a-time.o
|
$(AR) d $(SDK_DIR)/lib/libc.a lib_a-time.o
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
$(TOP_DIR)/cache/v$(SDK_FILE_VER).zip:
|
$(TOP_DIR)/cache/v$(SDK_FILE_VER).zip:
|
||||||
@ -308,11 +308,11 @@ endif
|
|||||||
|
|
||||||
|
|
||||||
$(OBJODIR)/%.o: %.c
|
$(OBJODIR)/%.o: %.c
|
||||||
@mkdir -p $(OBJODIR);
|
@mkdir -p $(dir $@);
|
||||||
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<
|
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<
|
||||||
|
|
||||||
$(OBJODIR)/%.d: %.c
|
$(OBJODIR)/%.d: %.c
|
||||||
@mkdir -p $(OBJODIR);
|
@mkdir -p $(dir $@);
|
||||||
@echo DEPEND: $(CC) -M $(CFLAGS) $<
|
@echo DEPEND: $(CC) -M $(CFLAGS) $<
|
||||||
@set -e; rm -f $@; \
|
@set -e; rm -f $@; \
|
||||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||||
@ -331,22 +331,22 @@ $(OBJODIR)/%.d: %.cpp
|
|||||||
rm -f $@.$$$$
|
rm -f $@.$$$$
|
||||||
|
|
||||||
$(OBJODIR)/%.o: %.s
|
$(OBJODIR)/%.o: %.s
|
||||||
@mkdir -p $(OBJODIR);
|
@mkdir -p $(dir $@);
|
||||||
$(CC) $(CFLAGS) -o $@ -c $<
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(OBJODIR)/%.d: %.s
|
$(OBJODIR)/%.d: %.s
|
||||||
@mkdir -p $(OBJODIR); \
|
@mkdir -p $(dir $@); \
|
||||||
set -e; rm -f $@; \
|
set -e; rm -f $@; \
|
||||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||||
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
||||||
rm -f $@.$$$$
|
rm -f $@.$$$$
|
||||||
|
|
||||||
$(OBJODIR)/%.o: %.S
|
$(OBJODIR)/%.o: %.S
|
||||||
@mkdir -p $(OBJODIR);
|
@mkdir -p $(dir $@);
|
||||||
$(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $<
|
$(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $<
|
||||||
|
|
||||||
$(OBJODIR)/%.d: %.S
|
$(OBJODIR)/%.d: %.S
|
||||||
@mkdir -p $(OBJODIR); \
|
@mkdir -p $(dir $@); \
|
||||||
set -e; rm -f $@; \
|
set -e; rm -f $@; \
|
||||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||||
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
||||||
|
13
README.md
13
README.md
@ -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)
|
[![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)
|
[![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
|
### 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
|
# Summary
|
||||||
|
|
||||||
- Easy to program wireless node and/or access point
|
- 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
|
- 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)
|
- 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)
|
- 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
|
# 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.
|
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.
|
||||||
|
52
app/Makefile
52
app/Makefile
@ -20,89 +20,64 @@ FLAVOR = debug
|
|||||||
ifndef PDIR # {
|
ifndef PDIR # {
|
||||||
GEN_IMAGES= eagle.app.v6.out
|
GEN_IMAGES= eagle.app.v6.out
|
||||||
GEN_BINS= eagle.app.v6.bin
|
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= \
|
SUBDIRS= \
|
||||||
user \
|
user \
|
||||||
driver \
|
driver \
|
||||||
pcm \
|
|
||||||
mbedtls \
|
mbedtls \
|
||||||
platform \
|
platform \
|
||||||
libc \
|
libc \
|
||||||
lua \
|
lua \
|
||||||
lwip \
|
lwip \
|
||||||
coap \
|
|
||||||
mqtt \
|
|
||||||
task \
|
task \
|
||||||
u8glib \
|
|
||||||
ucglib \
|
|
||||||
smart \
|
smart \
|
||||||
modules \
|
modules \
|
||||||
spiffs \
|
spiffs \
|
||||||
crypto \
|
|
||||||
dhtlib \
|
|
||||||
tsl2561 \
|
|
||||||
net \
|
net \
|
||||||
http \
|
|
||||||
fatfs \
|
fatfs \
|
||||||
esp-gdbstub \
|
esp-gdbstub \
|
||||||
websocket \
|
|
||||||
pm \
|
pm \
|
||||||
sjson \
|
$(OPT_SEL_MKTARGETS)
|
||||||
sqlite3 \
|
|
||||||
|
|
||||||
|
|
||||||
endif # } PDIR
|
endif # } PDIR
|
||||||
|
|
||||||
APPDIR = .
|
APPDIR = .
|
||||||
LDDIR = ../ld
|
LDDIR = ../ld
|
||||||
|
|
||||||
CCFLAGS += -Os
|
|
||||||
|
|
||||||
TARGET_LDFLAGS = \
|
TARGET_LDFLAGS = \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-Wl,-EL \
|
-Wl,-EL \
|
||||||
--longcalls \
|
--longcalls \
|
||||||
--text-section-literals
|
--text-section-literals
|
||||||
|
|
||||||
ifeq ($(FLAVOR),debug)
|
|
||||||
TARGET_LDFLAGS += -g -Os
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(FLAVOR),release)
|
|
||||||
TARGET_LDFLAGS += -Os
|
|
||||||
endif
|
|
||||||
|
|
||||||
LD_FILE = $(LDDIR)/nodemcu.ld
|
LD_FILE = $(LDDIR)/nodemcu.ld
|
||||||
|
|
||||||
COMPONENTS_eagle.app.v6 = \
|
COMPONENTS_eagle.app.v6 = \
|
||||||
user/libuser.a \
|
user/libuser.a \
|
||||||
driver/libdriver.a \
|
driver/libdriver.a \
|
||||||
pcm/pcm.a \
|
|
||||||
platform/libplatform.a \
|
platform/libplatform.a \
|
||||||
task/libtask.a \
|
task/libtask.a \
|
||||||
libc/liblibc.a \
|
libc/liblibc.a \
|
||||||
lua/liblua.a \
|
lua/liblua.a \
|
||||||
lwip/liblwip.a \
|
lwip/liblwip.a \
|
||||||
coap/coap.a \
|
|
||||||
mqtt/mqtt.a \
|
|
||||||
u8glib/u8glib.a \
|
|
||||||
ucglib/ucglib.a \
|
|
||||||
smart/smart.a \
|
smart/smart.a \
|
||||||
spiffs/spiffs.a \
|
spiffs/spiffs.a \
|
||||||
fatfs/libfatfs.a \
|
fatfs/libfatfs.a \
|
||||||
crypto/libcrypto.a \
|
|
||||||
dhtlib/libdhtlib.a \
|
|
||||||
tsl2561/tsl2561lib.a \
|
|
||||||
http/libhttp.a \
|
|
||||||
pm/libpm.a \
|
pm/libpm.a \
|
||||||
websocket/libwebsocket.a \
|
|
||||||
esp-gdbstub/libgdbstub.a \
|
esp-gdbstub/libgdbstub.a \
|
||||||
net/libnodemcu_net.a \
|
net/libnodemcu_net.a \
|
||||||
mbedtls/libmbedtls.a \
|
mbedtls/libmbedtls.a \
|
||||||
modules/libmodules.a \
|
modules/libmodules.a \
|
||||||
sjson/libsjson.a \
|
$(OPT_SEL_COMPONENTS)
|
||||||
sqlite3/libsqlite3.a \
|
|
||||||
|
|
||||||
|
|
||||||
# Inspect the modules library and work out which modules need to be linked.
|
# 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
|
# 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 \
|
-DLWIP_OPEN_SRC \
|
||||||
-DPBUF_RSV_FOR_WLAN \
|
-DPBUF_RSV_FOR_WLAN \
|
||||||
-DEBUF_LWIP \
|
-DEBUF_LWIP \
|
||||||
-DUSE_OPTIMIZE_PRINTF \
|
-DUSE_OPTIMIZE_PRINTF \
|
||||||
-DMBEDTLS_USER_CONFIG_FILE=\"user_mbedtls.h\" \
|
-DMBEDTLS_USER_CONFIG_FILE=\"user_mbedtls.h\" \
|
||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
@ -191,6 +166,5 @@ INCLUDES += -I ./
|
|||||||
PDIR := ../$(PDIR)
|
PDIR := ../$(PDIR)
|
||||||
sinclude $(PDIR)Makefile
|
sinclude $(PDIR)Makefile
|
||||||
|
|
||||||
|
|
||||||
.PHONY: FORCE
|
.PHONY: FORCE
|
||||||
FORCE:
|
FORCE:
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = coap.a
|
GEN_LIBS = libcoap.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
|
@ -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);
|
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 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)
|
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);
|
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)
|
if (inpkt->payload.len > 0)
|
||||||
{
|
{
|
||||||
lua_Load *load = &gLoad;
|
char line[LUA_MAXINPUT];
|
||||||
if(load->line_position == 0){
|
if (!coap_buffer_to_string(line, LUA_MAXINPUT, &inpkt->payload) &&
|
||||||
coap_buffer_to_string(load->line, load->len,&inpkt->payload);
|
lua_put_line(line, c_strlen(line))) {
|
||||||
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
|
|
||||||
NODE_DBG("\nResult(if any):\n");
|
NODE_DBG("\nResult(if any):\n");
|
||||||
system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
|
system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = libdhtlib.a
|
GEN_LIBS = libdht.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
0
app/driver/uart.c
Executable file → Normal file
0
app/driver/uart.c
Executable file → Normal file
@ -23,7 +23,7 @@ endif
|
|||||||
# makefile at its root level - these are then overridden
|
# makefile at its root level - these are then overridden
|
||||||
# for a subtree within the makefile rooted therein
|
# for a subtree within the makefile rooted therein
|
||||||
#
|
#
|
||||||
#DEFINES +=
|
#DEFINES += -DGDBSTUB_REDIRECT_CONSOLE_OUTPUT
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
# Recursion Magic - Don't touch this!!
|
# Recursion Magic - Don't touch this!!
|
||||||
|
@ -414,7 +414,7 @@ static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
|
|||||||
body = body + 4;
|
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);
|
int body_size = req->buffer_size - (body - req->buffer);
|
||||||
char chunked_decode_buffer[body_size];
|
char chunked_decode_buffer[body_size];
|
||||||
|
0
app/include/arch/cc.h
Executable file → Normal file
0
app/include/arch/cc.h
Executable file → Normal file
0
app/include/driver/uart.h
Executable file → Normal file
0
app/include/driver/uart.h
Executable file → Normal file
0
app/include/driver/uart_register.h
Executable file → Normal file
0
app/include/driver/uart_register.h
Executable file → Normal file
0
app/include/lwipopts.h
Executable file → Normal file
0
app/include/lwipopts.h
Executable file → Normal file
@ -38,8 +38,11 @@
|
|||||||
#define MODULE_PASTE_(x,y) x##y
|
#define MODULE_PASTE_(x,y) x##y
|
||||||
#define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(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):
|
/* For the ROM table, we name the variable according to ( | denotes concat):
|
||||||
* cfgname | _module_selected | LUA_USE_MODULES_##cfgname
|
* cfgname | _module_selected | LUA_USE_MODULES_##cfgname
|
||||||
* where the LUA_USE_MODULES_XYZ macro is first expanded to yield either
|
* where the LUA_USE_MODULES_XYZ macro is first expanded to yield either
|
||||||
@ -51,20 +54,20 @@
|
|||||||
* to be linked in.
|
* to be linked in.
|
||||||
*/
|
*/
|
||||||
#define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \
|
#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 }; \
|
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))) \
|
luaR_table MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(LUA_USE_MODULES_,cfgname))) \
|
||||||
= { luaname, map }
|
= { luaname, map }
|
||||||
|
|
||||||
|
|
||||||
/* System module registration support, not using LUA_USE_MODULES_XYZ. */
|
/* System module registration support, not using LUA_USE_MODULES_XYZ. */
|
||||||
#define BUILTIN_LIB_INIT(name, luaname, initfunc) \
|
#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 }
|
luaL_Reg MODULE_PASTE_(lua_lib_,name) = { luaname, initfunc }
|
||||||
|
|
||||||
#define BUILTIN_LIB(name, luaname, map) \
|
#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 }
|
luaR_table MODULE_PASTE_(lua_rotable_,name) = { luaname, map }
|
||||||
|
|
||||||
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
|
#if !defined(LUA_CROSS_COMPILER) && !(MIN_OPT_LEVEL==2 && LUA_OPTIMIZE_MEMORY==2)
|
||||||
|
121
app/include/u8g2_displays.h
Normal file
121
app/include/u8g2_displays.h
Normal 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
29
app/include/u8g2_fonts.h
Normal 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 */
|
@ -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__ */
|
|
@ -1,125 +1,250 @@
|
|||||||
#ifndef __USER_CONFIG_H__
|
#ifndef __USER_CONFIG_H__
|
||||||
#define __USER_CONFIG_H__
|
#define __USER_CONFIG_H__
|
||||||
|
|
||||||
// #define FLASH_512K
|
// The firmware supports a range of Flash sizes, though 4 Mbyte seems to be
|
||||||
// #define FLASH_1M
|
// the most common currently. NodeMCU builds include a discovery function
|
||||||
// #define FLASH_2M
|
// which is enabled by FLASH_AUTOSIZE, but you can override this by commenting
|
||||||
// #define FLASH_4M
|
// this out and enabling the explicitly size, e.g. FLASH_4M. Valid sizes are
|
||||||
// #define FLASH_8M
|
// FLASH_512K, FLASH_1M, FLASH_2M, FLASH_4M, FLASH_8M, FLASH_16M.
|
||||||
// #define FLASH_16M
|
|
||||||
#define FLASH_AUTOSIZE
|
#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_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
|
#ifdef DEVELOPMENT_TOOLS
|
||||||
|
#if defined(LUA_CROSS_COMPILER) || !defined(DEVELOPMENT_USE_GDB)
|
||||||
extern void luaL_assertfail(const char *file, int line, const char *message);
|
extern void luaL_assertfail(const char *file, int line, const char *message);
|
||||||
#define lua_assert(x) ((x) ? (void) 0 : luaL_assertfail(__FILE__, __LINE__, #x))
|
#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
|
#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
|
#ifdef DEVELOP_VERSION
|
||||||
#define NODE_DEBUG
|
#define NODE_DEBUG
|
||||||
#define COAP_DEBUG
|
#define COAP_DEBUG
|
||||||
#endif /* DEVELOP_VERSION */
|
#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
|
#ifdef NODE_DEBUG
|
||||||
#define NODE_DBG dbg_printf
|
#define NODE_DBG dbg_printf
|
||||||
#else
|
#else
|
||||||
#define NODE_DBG
|
#define NODE_DBG
|
||||||
#endif /* NODE_DEBUG */
|
#endif /* NODE_DEBUG */
|
||||||
|
|
||||||
|
#define NODE_ERROR
|
||||||
#ifdef NODE_ERROR
|
#ifdef NODE_ERROR
|
||||||
#define NODE_ERR dbg_printf
|
#define NODE_ERR dbg_printf
|
||||||
#else
|
#else
|
||||||
#define NODE_ERR
|
#define NODE_ERR
|
||||||
#endif /* NODE_ERROR */
|
#endif /* NODE_ERROR */
|
||||||
|
|
||||||
#define GPIO_INTERRUPT_ENABLE
|
|
||||||
#define GPIO_INTERRUPT_HOOK_ENABLE
|
|
||||||
// #define GPIO_SAFE_NO_INTR_ENABLE
|
// #define GPIO_SAFE_NO_INTR_ENABLE
|
||||||
|
|
||||||
#define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
|
#define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
|
||||||
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
|
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
|
||||||
#define ICACHE_RAM_STRING(x) ICACHE_RAM_STRING2(x)
|
#define ICACHE_STRING(x) ICACHE_STRING2(x)
|
||||||
#define ICACHE_RAM_STRING2(x) #x
|
#define ICACHE_STRING2(x) #x
|
||||||
#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text." __FILE__ "." ICACHE_RAM_STRING(__LINE__))))
|
#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
|
#ifdef GPIO_SAFE_NO_INTR_ENABLE
|
||||||
#define NO_INTR_CODE ICACHE_RAM_ATTR __attribute__ ((noinline))
|
#define NO_INTR_CODE ICACHE_RAM_ATTR __attribute__ ((noinline))
|
||||||
#else
|
#else
|
||||||
#define NO_INTR_CODE inline
|
#define NO_INTR_CODE inline
|
||||||
#endif
|
#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__ */
|
#endif /* __USER_CONFIG_H__ */
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
#ifndef __USER_MODULES_H__
|
#ifndef __USER_MODULES_H__
|
||||||
#define __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
|
#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
|
// 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_SQLITE3
|
||||||
//#define LUA_USE_MODULES_STRUCT
|
//#define LUA_USE_MODULES_STRUCT
|
||||||
//#define LUA_USE_MODULES_SWITEC
|
//#define LUA_USE_MODULES_SWITEC
|
||||||
// #define LUA_USE_MODULES_TCS34725
|
//#define LUA_USE_MODULES_TCS34725
|
||||||
//#define LUA_USE_MODULES_TM1829
|
//#define LUA_USE_MODULES_TM1829
|
||||||
#define LUA_USE_MODULES_TLS
|
//#define LUA_USE_MODULES_TLS
|
||||||
#define LUA_USE_MODULES_TMR
|
#define LUA_USE_MODULES_TMR
|
||||||
//#define LUA_USE_MODULES_TSL2561
|
//#define LUA_USE_MODULES_TSL2561
|
||||||
//#define LUA_USE_MODULES_U8G
|
|
||||||
#define LUA_USE_MODULES_UART
|
#define LUA_USE_MODULES_UART
|
||||||
|
//#define LUA_USE_MODULES_U8G2
|
||||||
//#define LUA_USE_MODULES_UCG
|
//#define LUA_USE_MODULES_UCG
|
||||||
//#define LUA_USE_MODULES_WEBSOCKET
|
//#define LUA_USE_MODULES_WEBSOCKET
|
||||||
#define LUA_USE_MODULES_WIFI
|
#define LUA_USE_MODULES_WIFI
|
||||||
|
@ -15,55 +15,6 @@
|
|||||||
#include "c_stdlib.h"
|
#include "c_stdlib.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#include "c_string.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 <_ansi.h>
|
||||||
//#include <reent.h>
|
//#include <reent.h>
|
||||||
//#include "mprec.h"
|
//#include "mprec.h"
|
||||||
|
@ -46,8 +46,7 @@
|
|||||||
|
|
||||||
// void c_exit(int);
|
// 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_malloc(size_t __size);
|
||||||
// void *c_zalloc(size_t __size);
|
// void *c_zalloc(size_t __size);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
|
SUBDIRS = luac_cross
|
||||||
GEN_LIBS = liblua.a
|
GEN_LIBS = liblua.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -24,7 +25,8 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
|
|||||||
# makefile at its root level - these are then overridden
|
# makefile at its root level - these are then overridden
|
||||||
# for a subtree within the makefile rooted therein
|
# 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!!
|
# Recursion Magic - Don't touch this!!
|
||||||
|
@ -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__
|
|
||||||
|
|
@ -414,7 +414,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
|||||||
case LUA_TROTABLE:
|
case LUA_TROTABLE:
|
||||||
return rvalue(o);
|
return rvalue(o);
|
||||||
case LUA_TLIGHTFUNCTION:
|
case LUA_TLIGHTFUNCTION:
|
||||||
return pvalue(o);
|
return fvalue(o);
|
||||||
default: return NULL;
|
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) {
|
LUA_API void lua_pushstring (lua_State *L, const char *s) {
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
@ -45,6 +45,149 @@
|
|||||||
#define LUA_USECCLOSURES 0
|
#define LUA_USECCLOSURES 0
|
||||||
#define LUA_USELIGHTFUNCTIONS 1
|
#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
|
** 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 */
|
lf.f = c_freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||||
/* skip eventual `#!...' */
|
/* skip eventual `#!...' */
|
||||||
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
while ((c = c_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
|
||||||
lf.extraline = 0;
|
|
||||||
|
lf.extraline = 0;
|
||||||
}
|
}
|
||||||
c_ungetc(c, lf.f);
|
c_ungetc(c, lf.f);
|
||||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
|
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;
|
void *nptr;
|
||||||
|
|
||||||
if (nsize == 0) {
|
if (nsize == 0) {
|
||||||
|
#ifdef DEBUG_ALLOCATOR
|
||||||
|
return (void *)this_realloc(ptr, osize, nsize);
|
||||||
|
#else
|
||||||
c_free(ptr);
|
c_free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
|
if (L != NULL && (mode & EGC_ALWAYS)) /* always collect memory if requested */
|
||||||
luaC_fullgc(L);
|
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))
|
if(G(L)->memlimit > 0 && (mode & EGC_ON_MEM_LIMIT) && l_check_memlimit(L, nsize - osize))
|
||||||
return NULL;
|
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)) {
|
if (nptr == NULL && L != NULL && (mode & EGC_ON_ALLOC_FAILURE)) {
|
||||||
luaC_fullgc(L); /* emergency full collection. */
|
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;
|
return nptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
|
LUALIB_API void luaL_assertfail(const char *file, int line, const char *message) {
|
||||||
dbg_printf("ASSERT@%s(%d): %s\n", file, line, 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) {
|
static int panic (lua_State *L) {
|
||||||
(void)L; /* to avoid warnings */
|
(void)L; /* to avoid warnings */
|
||||||
#if defined(LUA_USE_STDIO)
|
#if defined(LUA_USE_STDIO)
|
||||||
|
@ -712,10 +712,5 @@ static void base_open (lua_State *L) {
|
|||||||
|
|
||||||
LUALIB_API int luaopen_base (lua_State *L) {
|
LUALIB_API int luaopen_base (lua_State *L) {
|
||||||
base_open(L);
|
base_open(L);
|
||||||
#if LUA_OPTIMIZE_MEMORY == 0
|
|
||||||
luaL_register(L, LUA_COLIBNAME, co_funcs);
|
|
||||||
return 2;
|
|
||||||
#else
|
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lrotable.h"
|
#include "lrotable.h"
|
||||||
|
#include "lstring.h"
|
||||||
|
#include "lflash.h"
|
||||||
#include "user_modules.h"
|
#include "user_modules.h"
|
||||||
|
|
||||||
|
|
||||||
@ -26,6 +28,39 @@ static int db_getregistry (lua_State *L) {
|
|||||||
return 1;
|
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
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
|
|
||||||
static int db_getmetatable (lua_State *L) {
|
static int db_getmetatable (lua_State *L) {
|
||||||
@ -395,6 +430,7 @@ const LUA_REG_TYPE dblib[] = {
|
|||||||
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
|
{LSTRKEY("getlocal"), LFUNCVAL(db_getlocal)},
|
||||||
#endif
|
#endif
|
||||||
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
|
{LSTRKEY("getregistry"), LFUNCVAL(db_getregistry)},
|
||||||
|
{LSTRKEY("getstrings"), LFUNCVAL(db_getstrings)},
|
||||||
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
#ifndef LUA_USE_BUILTIN_DEBUG_MINIMAL
|
||||||
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
|
{LSTRKEY("getmetatable"), LFUNCVAL(db_getmetatable)},
|
||||||
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
|
{LSTRKEY("getupvalue"), LFUNCVAL(db_getupvalue)},
|
||||||
|
274
app/lua/lflash.c
Normal file
274
app/lua/lflash.c
Normal 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
48
app/lua/lflash.h
Normal 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
|
||||||
|
|
@ -146,7 +146,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
|
|||||||
luaM_freearray(L, f->k, f->sizek, TValue);
|
luaM_freearray(L, f->k, f->sizek, TValue);
|
||||||
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||||
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
|
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);
|
luaM_freearray(L, f->code, f->sizecode, Instruction);
|
||||||
#ifdef LUA_OPTIMIZE_DEBUG
|
#ifdef LUA_OPTIMIZE_DEBUG
|
||||||
if (f->packedlineinfo) {
|
if (f->packedlineinfo) {
|
||||||
|
@ -18,9 +18,6 @@
|
|||||||
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
|
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
|
||||||
cast(int, sizeof(TValue *)*((n)-1)))
|
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 Proto *luaF_newproto (lua_State *L);
|
||||||
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
|
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
|
||||||
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
|
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#define GCSWEEPCOST 10
|
#define GCSWEEPCOST 10
|
||||||
#define GCFINALIZECOST 100
|
#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))
|
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
|
||||||
|
|
||||||
@ -37,7 +40,7 @@
|
|||||||
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
|
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
|
||||||
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
|
#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)
|
#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
|
||||||
@ -61,12 +64,18 @@
|
|||||||
|
|
||||||
static void removeentry (Node *n) {
|
static void removeentry (Node *n) {
|
||||||
lua_assert(ttisnil(gval(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 */
|
setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void reallymarkobject (global_State *g, GCObject *o) {
|
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));
|
lua_assert(iswhite(o) && !isdead(g, o));
|
||||||
white2gray(o);
|
white2gray(o);
|
||||||
switch (o->gch.tt) {
|
switch (o->gch.tt) {
|
||||||
@ -180,6 +189,8 @@ static int traversetable (global_State *g, Table *h) {
|
|||||||
while (i--)
|
while (i--)
|
||||||
markvalue(g, &h->array[i]);
|
markvalue(g, &h->array[i]);
|
||||||
}
|
}
|
||||||
|
if (luaH_isdummy (h->node))
|
||||||
|
return weakkey || weakvalue;
|
||||||
i = sizenode(h);
|
i = sizenode(h);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
Node *n = gnode(h, 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) {
|
static void traverseproto (global_State *g, Proto *f) {
|
||||||
int i;
|
int i;
|
||||||
|
if (isLFSobject(f))
|
||||||
|
return; /* don't traverse Protos in LFS */
|
||||||
if (f->source) stringmark(f->source);
|
if (f->source) stringmark(f->source);
|
||||||
for (i=0; i<f->sizek; i++) /* mark literals */
|
for (i=0; i<f->sizek; i++) /* mark literals */
|
||||||
markvalue(g, &f->k[i]);
|
markvalue(g, &f->k[i]);
|
||||||
@ -317,7 +330,7 @@ static l_mem propagatemark (global_State *g) {
|
|||||||
sizeof(TValue) * p->sizek +
|
sizeof(TValue) * p->sizek +
|
||||||
sizeof(LocVar) * p->sizelocvars +
|
sizeof(LocVar) * p->sizelocvars +
|
||||||
sizeof(TString *) * p->sizeupvalues +
|
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
|
#ifdef LUA_OPTIMIZE_DEBUG
|
||||||
(p->packedlineinfo ?
|
(p->packedlineinfo ?
|
||||||
c_strlen(cast(char *, p->packedlineinfo))+1 :
|
c_strlen(cast(char *, p->packedlineinfo))+1 :
|
||||||
@ -388,7 +401,10 @@ static void cleartable (GCObject *l) {
|
|||||||
|
|
||||||
static void freeobj (lua_State *L, GCObject *o) {
|
static void freeobj (lua_State *L, GCObject *o) {
|
||||||
switch (o->gch.tt) {
|
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_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
|
||||||
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
|
case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
|
||||||
case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
|
case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
|
||||||
@ -398,6 +414,7 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TSTRING: {
|
case LUA_TSTRING: {
|
||||||
|
lua_assert(!isLFSobject(&(o->gch)));
|
||||||
G(L)->strt.nuse--;
|
G(L)->strt.nuse--;
|
||||||
luaM_freemem(L, o, sizestring(gco2ts(o)));
|
luaM_freemem(L, o, sizestring(gco2ts(o)));
|
||||||
break;
|
break;
|
||||||
@ -420,6 +437,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
|
|||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
int deadmask = otherwhite(g);
|
int deadmask = otherwhite(g);
|
||||||
while ((curr = *p) != NULL && count-- > 0) {
|
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 */
|
if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
|
||||||
sweepwholelist(L, &gco2th(curr)->openupval);
|
sweepwholelist(L, &gco2th(curr)->openupval);
|
||||||
if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
|
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 */
|
size_t udsize; /* total size of userdata to be finalized */
|
||||||
/* remark occasional upvalues of (maybe) dead threads */
|
/* remark occasional upvalues of (maybe) dead threads */
|
||||||
remarkupvals(g);
|
remarkupvals(g);
|
||||||
/* traverse objects cautch by write barrier and by 'remarkupvals' */
|
/* traverse objects caucht by write barrier and by 'remarkupvals' */
|
||||||
propagateall(g);
|
propagateall(g);
|
||||||
/* remark weak tables */
|
/* remark weak tables */
|
||||||
g->gray = g->weak;
|
g->gray = g->weak;
|
||||||
@ -694,10 +712,10 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
|
|||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
|
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
|
||||||
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
|
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? */
|
/* must keep invariant? */
|
||||||
if (g->gcstate == GCSpropagate)
|
if (g->gcstate == GCSpropagate)
|
||||||
reallymarkobject(g, v); /* restore invariant */
|
reallymarkobject(g, v); /* Restore invariant */
|
||||||
else /* don't mind */
|
else /* don't mind */
|
||||||
makewhite(g, o); /* mark as white just to avoid other barriers */
|
makewhite(g, o); /* mark as white just to avoid other barriers */
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
#define VALUEWEAKBIT 4
|
#define VALUEWEAKBIT 4
|
||||||
#define FIXEDBIT 5
|
#define FIXEDBIT 5
|
||||||
#define SFIXEDBIT 6
|
#define SFIXEDBIT 6
|
||||||
|
#define LFSBIT 6
|
||||||
#define READONLYBIT 7
|
#define READONLYBIT 7
|
||||||
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
|
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
|
||||||
|
|
||||||
@ -100,6 +101,13 @@
|
|||||||
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
|
#define isfixedstack(x) testbit((x)->marked, FIXEDSTACKBIT)
|
||||||
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
|
#define fixedstack(x) l_setbit((x)->marked, FIXEDSTACKBIT)
|
||||||
#define unfixedstack(x) resetbit((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) { \
|
#define luaC_checkGC(L) { \
|
||||||
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
|
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
|
||||||
|
78
app/lua/linit.c
Normal file
78
app/lua/linit.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -326,7 +326,7 @@ const LUA_REG_TYPE math_map[] = {
|
|||||||
{LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
|
{LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
|
||||||
{LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
|
{LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
|
||||||
#if LUA_OPTIMIZE_MEMORY > 0
|
#if LUA_OPTIMIZE_MEMORY > 0
|
||||||
{LSTRKEY("huge"), LNUMVAL(LONG_MAX)},
|
{LSTRKEY("huge"), LNUMVAL(INT_MAX)},
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
{LSTRKEY("abs"), LFUNCVAL(math_abs)},
|
{LSTRKEY("abs"), LFUNCVAL(math_abs)},
|
||||||
@ -374,7 +374,7 @@ const LUA_REG_TYPE math_map[] = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined LUA_NUMBER_INTEGRAL
|
#if defined LUA_NUMBER_INTEGRAL
|
||||||
# include "c_limits.h" /* for LONG_MAX */
|
# include "c_limits.h" /* for INT_MAX */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LUALIB_API int luaopen_math (lua_State *L) {
|
LUALIB_API int luaopen_math (lua_State *L) {
|
||||||
@ -383,7 +383,7 @@ LUALIB_API int luaopen_math (lua_State *L) {
|
|||||||
#else
|
#else
|
||||||
luaL_register(L, LUA_MATHLIBNAME, math_map);
|
luaL_register(L, LUA_MATHLIBNAME, math_map);
|
||||||
# if defined LUA_NUMBER_INTEGRAL
|
# if defined LUA_NUMBER_INTEGRAL
|
||||||
lua_pushnumber(L, LONG_MAX);
|
lua_pushnumber(L, INT_MAX);
|
||||||
lua_setfield(L, -2, "huge");
|
lua_setfield(L, -2, "huge");
|
||||||
# else
|
# else
|
||||||
lua_pushnumber(L, PI);
|
lua_pushnumber(L, PI);
|
||||||
|
@ -613,7 +613,7 @@ static int ll_seeall (lua_State *L) {
|
|||||||
|
|
||||||
static void setpath (lua_State *L, const char *fieldname, const char *envname,
|
static void setpath (lua_State *L, const char *fieldname, const char *envname,
|
||||||
const char *def) {
|
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? */
|
if (path == NULL) /* no environment variable? */
|
||||||
lua_pushstring(L, def); /* use default */
|
lua_pushstring(L, def); /* use default */
|
||||||
else {
|
else {
|
||||||
|
@ -53,7 +53,8 @@ int luaO_fb2int (int x) {
|
|||||||
|
|
||||||
|
|
||||||
int luaO_log2 (unsigned 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,
|
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,
|
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,
|
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;
|
int l = -1;
|
||||||
while (x >= 256) { l += 8; x >>= 8; }
|
while (x >= 256) { l += 8; x >>= 8; }
|
||||||
#ifdef LUA_CROSS_COMPILER
|
|
||||||
return l + log_2[x];
|
return l + log_2[x];
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +106,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
|
|||||||
#if defined(LUA_CROSS_COMPILER)
|
#if defined(LUA_CROSS_COMPILER)
|
||||||
{
|
{
|
||||||
long lres = strtoul(s, &endptr, 16);
|
long lres = strtoul(s, &endptr, 16);
|
||||||
#if LONG_MAX != 2147483647L
|
#if INT_MAX != 2147483647L
|
||||||
if (lres & ~0xffffffffL)
|
if (lres & ~0xffffffffL)
|
||||||
*result = cast_num(-1);
|
*result = cast_num(-1);
|
||||||
else if (lres & 0x80000000L)
|
else if (lres & 0x80000000L)
|
||||||
|
@ -23,10 +23,10 @@
|
|||||||
|
|
||||||
#define NUM_TAGS (LAST_TAG+1)
|
#define NUM_TAGS (LAST_TAG+1)
|
||||||
|
|
||||||
/* mask for 'read-only' objects. must match READONLYBIT in lgc.h' */
|
#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */
|
||||||
#define READONLYMASK 128
|
#ifdef LUA_FLASH_STORE
|
||||||
|
#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
** Extra tags for non-values
|
** Extra tags for non-values
|
||||||
*/
|
*/
|
||||||
@ -55,86 +55,39 @@ typedef struct GCheader {
|
|||||||
CommonHeader;
|
CommonHeader;
|
||||||
} GCheader;
|
} 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
|
** 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 {
|
typedef union {
|
||||||
GCObject *gc;
|
GCObject *gc;
|
||||||
void *p;
|
void *p;
|
||||||
lua_Number n;
|
lua_Number n;
|
||||||
int b;
|
int b;
|
||||||
} Value;
|
} Value;
|
||||||
#endif // #if defined( LUA_PACK_VALUE ) && defined( ELUA_ENDIAN_BIG )
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Tagged Values
|
** Tagged Values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define TValuefields Value value; int tt
|
#define TValuefields Value value; int tt
|
||||||
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
|
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
|
||||||
|
|
||||||
|
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
|
||||||
|
#pragma pack(4)
|
||||||
|
#endif
|
||||||
typedef struct lua_TValue {
|
typedef struct lua_TValue {
|
||||||
TValuefields;
|
TValuefields;
|
||||||
} TValue;
|
} TValue;
|
||||||
#else // #ifndef LUA_PACK_VALUE
|
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
|
||||||
#ifdef ELUA_ENDIAN_LITTLE
|
#pragma pack()
|
||||||
#define TValuefields union { \
|
#endif
|
||||||
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
|
|
||||||
|
|
||||||
/* Macros to test type */
|
/* Macros to test type */
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define ttisnil(o) (ttype(o) == LUA_TNIL)
|
#define ttisnil(o) (ttype(o) == LUA_TNIL)
|
||||||
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
|
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
|
||||||
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
|
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
|
||||||
@ -146,27 +99,11 @@ typedef TValuefields TValue;
|
|||||||
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
||||||
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
|
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
|
||||||
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
|
#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 */
|
/* Macros to access values */
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define ttype(o) ((o)->tt)
|
#define ttype(o) ((void) (o)->value, (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 gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
|
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
|
||||||
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
|
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
|
||||||
#define rvalue(o) check_exp(ttisrotable(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
|
** for internal debug only
|
||||||
*/
|
*/
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define checkconsistency(obj) \
|
#define checkconsistency(obj) \
|
||||||
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
|
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
|
||||||
|
|
||||||
#define checkliveness(g,obj) \
|
#define checkliveness(g,obj) \
|
||||||
lua_assert(!iscollectable(obj) || \
|
lua_assert(!iscollectable(obj) || \
|
||||||
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
|
((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 */
|
/* Macros to set values */
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
|
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
|
||||||
|
|
||||||
#define setnvalue(obj,x) \
|
#define setnvalue(obj,x) \
|
||||||
@ -257,69 +185,10 @@ typedef TValuefields TValue;
|
|||||||
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
|
i_o->value.gc=i_x; i_o->tt=LUA_TPROTO; \
|
||||||
checkliveness(G(L),i_o); }
|
checkliveness(G(L),i_o); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define setobj(L,obj1,obj2) \
|
#define setobj(L,obj1,obj2) \
|
||||||
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
|
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
|
||||||
o1->value = o2->value; o1->tt=o2->tt; \
|
o1->value = o2->value; o1->tt=o2->tt; \
|
||||||
checkliveness(G(L),o1); }
|
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
|
** different types of sets, according to destination
|
||||||
@ -340,13 +209,7 @@ typedef TValuefields TValue;
|
|||||||
#define setobj2n setobj
|
#define setobj2n setobj
|
||||||
#define setsvalue2n setsvalue
|
#define setsvalue2n setsvalue
|
||||||
|
|
||||||
#ifndef LUA_PACK_VALUE
|
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
|
||||||
#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 iscollectable(o) (ttype(o) >= LUA_TSTRING)
|
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
|
||||||
|
|
||||||
@ -367,9 +230,16 @@ typedef union TString {
|
|||||||
} tsv;
|
} tsv;
|
||||||
} TString;
|
} TString;
|
||||||
|
|
||||||
|
#ifdef LUA_CROSS_COMPILER
|
||||||
#define getstr(ts) (((ts)->tsv.marked & READONLYMASK) ? cast(const char *, *(const char**)((ts) + 1)) : cast(const char *, (ts) + 1))
|
#define isreadonly(o) (0)
|
||||||
#define svalue(o) getstr(rawtsvalue(o))
|
#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 is_vararg;
|
||||||
lu_byte maxstacksize;
|
lu_byte maxstacksize;
|
||||||
} Proto;
|
} Proto;
|
||||||
|
#define proto_isreadonly(p) isreadonly(*(p))
|
||||||
|
|
||||||
|
|
||||||
/* masks for new-style vararg */
|
/* masks for new-style vararg */
|
||||||
@ -487,7 +358,6 @@ typedef union Closure {
|
|||||||
** Tables
|
** Tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
typedef union TKey {
|
typedef union TKey {
|
||||||
struct {
|
struct {
|
||||||
TValuefields;
|
TValuefields;
|
||||||
@ -497,16 +367,6 @@ typedef union TKey {
|
|||||||
} TKey;
|
} TKey;
|
||||||
|
|
||||||
#define LUA_TKEY_NIL {LUA_TVALUE_NIL, NULL}
|
#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 {
|
typedef struct Node {
|
||||||
TValue i_val;
|
TValue i_val;
|
||||||
|
@ -916,12 +916,11 @@ static int block_follow (int token) {
|
|||||||
static void block (LexState *ls) {
|
static void block (LexState *ls) {
|
||||||
/* block -> chunk */
|
/* block -> chunk */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt));
|
BlockCnt bl;
|
||||||
enterblock(fs, pbl, 0);
|
enterblock(fs, &bl, 0);
|
||||||
chunk(ls);
|
chunk(ls);
|
||||||
lua_assert(pbl->breaklist == NO_JUMP);
|
lua_assert(bl.breaklist == NO_JUMP);
|
||||||
leaveblock(fs);
|
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) {
|
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
|
||||||
/* forbody -> DO block */
|
/* forbody -> DO block */
|
||||||
BlockCnt *pbl = (BlockCnt*)luaM_malloc(ls->L,sizeof(BlockCnt));
|
BlockCnt bl;
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int prep, endfor;
|
int prep, endfor;
|
||||||
adjustlocalvars(ls, 3); /* control variables */
|
adjustlocalvars(ls, 3); /* control variables */
|
||||||
checknext(ls, TK_DO);
|
checknext(ls, TK_DO);
|
||||||
prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
|
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);
|
adjustlocalvars(ls, nvars);
|
||||||
luaK_reserveregs(fs, nvars);
|
luaK_reserveregs(fs, nvars);
|
||||||
block(ls);
|
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_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
|
||||||
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
|
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
|
||||||
luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
|
luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
|
||||||
luaM_free(ls->L,pbl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#undef LNILVAL
|
#undef LNILVAL
|
||||||
#undef LREGISTER
|
#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 LUA_REG_TYPE luaR_entry
|
||||||
#define LSTRKEY LRO_STRKEY
|
#define LSTRKEY LRO_STRKEY
|
||||||
#define LNUMKEY LRO_NUMKEY
|
#define LNUMKEY LRO_NUMKEY
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#define LUAR_FINDVALUE 1
|
#define LUAR_FINDVALUE 1
|
||||||
|
|
||||||
/* Externally defined read-only table array */
|
/* 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 */
|
/* Find a global "read only table" in the constant lua_rotable array */
|
||||||
void* luaR_findglobal(const char *name, unsigned len) {
|
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) {
|
if (pentries[pos].key.type != LUA_TNIL) {
|
||||||
/* Found an entry */
|
/* Found an entry */
|
||||||
if (pentries[pos].key.type == LUA_TSTRING)
|
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
|
else
|
||||||
setnvalue(key, (lua_Number)pentries[pos].key.id.numkey)
|
setnvalue(key, (lua_Number)pentries[pos].key.id.numkey)
|
||||||
setobj2s(L, val, &pentries[pos].value);
|
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 */
|
/* Return 1 if the given pointer is a rotable */
|
||||||
#ifdef LUA_META_ROTABLES
|
|
||||||
|
|
||||||
#include "compiler.h"
|
|
||||||
|
|
||||||
int luaR_isrotable(void *p) {
|
int luaR_isrotable(void *p) {
|
||||||
return RODATA_START_ADDRESS <= (char*)p && (char*)p <= RODATA_END_ADDRESS;
|
return IN_RO_AREA((char *)p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,32 +4,16 @@
|
|||||||
#define lrotable_h
|
#define lrotable_h
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "llimits.h"
|
|
||||||
#include "lobject.h"
|
|
||||||
#include "luaconf.h"
|
#include "luaconf.h"
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "llimits.h"
|
||||||
|
|
||||||
/* Macros one can use to define rotable entries */
|
/* Macros one can use to define rotable entries */
|
||||||
#ifndef LUA_PACK_VALUE
|
|
||||||
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
|
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
|
||||||
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
|
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
|
||||||
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
|
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
|
||||||
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
|
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
|
||||||
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
|
#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_STRKEY(k) {LUA_TSTRING, {.strkey = k}}
|
||||||
#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
|
#define LRO_NUMKEY(k) {LUA_TNUMBER, {.numkey = k}}
|
||||||
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}
|
#define LRO_NILKEY {LUA_TNIL, {.strkey=NULL}}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "ldebug.h"
|
#include "ldebug.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
#include "lflash.h"
|
||||||
#include "lfunc.h"
|
#include "lfunc.h"
|
||||||
#include "lgc.h"
|
#include "lgc.h"
|
||||||
#include "llex.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, gt(L), luaH_new(L, 0, 2)); /* table of globals */
|
||||||
sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
|
sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
|
||||||
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
|
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);
|
luaT_init(L);
|
||||||
luaX_init(L);
|
luaX_init(L);
|
||||||
luaS_fix(luaS_newliteral(L, MEMERRMSG));
|
stringfix(luaS_newliteral(L, MEMERRMSG));
|
||||||
g->GCthreshold = 4*g->totalbytes;
|
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;
|
g->memlimit = EGC_INITIAL_MEMLIMIT;
|
||||||
#else
|
#else
|
||||||
g->memlimit = 0;
|
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
|
#endif
|
||||||
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
|
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
|
||||||
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
||||||
|
@ -94,6 +94,10 @@ typedef struct global_State {
|
|||||||
UpVal uvhead; /* head of double-linked list of all open upvalues */
|
UpVal uvhead; /* head of double-linked list of all open upvalues */
|
||||||
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
|
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
|
||||||
TString *tmname[TM_N]; /* array with tag-method names */
|
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;
|
} global_State;
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
|
|||||||
tb = &G(L)->strt;
|
tb = &G(L)->strt;
|
||||||
if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
|
if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
|
||||||
luaS_resize(L, tb->size*2); /* too crowded */
|
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.len = l;
|
||||||
ts->tsv.hash = h;
|
ts->tsv.hash = h;
|
||||||
ts->tsv.marked = luaC_white(G(L));
|
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 */
|
((char *)(ts+1))[l] = '\0'; /* ending 0 */
|
||||||
} else {
|
} else {
|
||||||
*(char **)(ts+1) = (char *)str;
|
*(char **)(ts+1) = (char *)str;
|
||||||
luaS_readonly(ts);
|
l_setbit((ts)->tsv.marked, READONLYBIT);
|
||||||
}
|
}
|
||||||
h = lmod(h, tb->size);
|
h = lmod(h, tb->size);
|
||||||
ts->tsv.next = tb->hash[h]; /* chain new entry */
|
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;
|
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;
|
GCObject *o;
|
||||||
unsigned int h = cast(unsigned int, l); /* seed */
|
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 step = (l>>5)+1; /* if string is too long, don't hash all its chars */
|
||||||
size_t l1;
|
size_t l1;
|
||||||
for (l1=l; l1>=step; l1-=step) /* compute hash */
|
for (l1=l; l1>=step; l1-=step) /* compute hash */
|
||||||
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
|
h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
|
||||||
|
|
||||||
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
|
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
|
||||||
o != NULL;
|
o != NULL;
|
||||||
o = o->gch.next) {
|
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 ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newlstr(L, str, l, h, readonly); /* not found */
|
#if defined(LUA_FLASH_STORE) && !defined(LUA_CROSS_COMPILER)
|
||||||
}
|
/*
|
||||||
|
* The RAM strt is searched first since RAM access is faster tham Flash access.
|
||||||
static int lua_is_ptr_in_ro_area(const char *p) {
|
* If a miss, then search the RO string table.
|
||||||
#ifdef LUA_CROSS_COMPILER
|
*/
|
||||||
return 0;
|
if (G(L)->ROstrt.hash) {
|
||||||
#else
|
for (o = G(L)->ROstrt.hash[lmod(h, G(L)->ROstrt.size)];
|
||||||
|
o != NULL;
|
||||||
#include "compiler.h"
|
o = o->gch.next) {
|
||||||
|
TString *ts = rawgco2ts(o);
|
||||||
return p >= RODATA_START_ADDRESS && p <= RODATA_END_ADDRESS;
|
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
/* New additions to the RAM strt are tagged as readonly if the string address
|
||||||
|
* is in the CTEXT segment (target only, not luac.cross) */
|
||||||
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
|
int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) &&
|
||||||
// If the pointer is in a read-only memory and the string is at least 4 chars in length,
|
l == c_strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING);
|
||||||
// create it as a read-only string instead
|
return newlstr(L, str, l, h, readonly); /* not found */
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,22 +13,16 @@
|
|||||||
#include "lstate.h"
|
#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 sizeudata(u) (sizeof(union Udata)+(u)->len)
|
||||||
|
|
||||||
#define luaS_new(L, s) (luaS_newlstr(L, s, c_strlen(s)))
|
#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, \
|
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
||||||
(sizeof(s)/sizeof(char))-1))
|
(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 void luaS_resize (lua_State *L, int newsize);
|
||||||
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
|
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_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
|
#endif
|
||||||
|
@ -445,7 +445,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
|
|||||||
int oldasize = t->sizearray;
|
int oldasize = t->sizearray;
|
||||||
if (nasize > oldasize) /* array part must grow? */
|
if (nasize > oldasize) /* array part must grow? */
|
||||||
setarrayvector(L, t, nasize);
|
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? */
|
if (nasize < oldasize) { /* array part must shrink? */
|
||||||
t->sizearray = nasize;
|
t->sizearray = nasize;
|
||||||
/* re-insert elements from vanishing slice */
|
/* re-insert elements from vanishing slice */
|
||||||
@ -749,12 +750,12 @@ int luaH_getn_ro (void *t) {
|
|||||||
return len;
|
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) {
|
Node *luaH_mainposition (const Table *t, const TValue *key) {
|
||||||
return mainposition(t, key);
|
return mainposition(t, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int luaH_isdummy (Node *n) { return n == dummynode; }
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -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_next_ro (lua_State *L, void *t, StkId key);
|
||||||
LUAI_FUNC int luaH_getn (Table *t);
|
LUAI_FUNC int luaH_getn (Table *t);
|
||||||
LUAI_FUNC int luaH_getn_ro (void *t);
|
LUAI_FUNC int luaH_getn_ro (void *t);
|
||||||
|
LUAI_FUNC int luaH_isdummy (Node *n);
|
||||||
|
|
||||||
#if defined(LUA_DEBUG)
|
#if defined(LUA_DEBUG)
|
||||||
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
|
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
|
||||||
LUAI_FUNC int luaH_isdummy (Node *n);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,7 +137,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) {
|
|||||||
if (!lua_isstring(L, -1))
|
if (!lua_isstring(L, -1))
|
||||||
luaL_error(L, "invalid value (%s) at index %d in table for "
|
luaL_error(L, "invalid value (%s) at index %d in table for "
|
||||||
LUA_QL("concat"), luaL_typename(L, -1), i);
|
LUA_QL("concat"), luaL_typename(L, -1), i);
|
||||||
luaL_addvalue(b);
|
luaL_addvalue(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
#include "lgc.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
#include "ltable.h"
|
#include "ltable.h"
|
||||||
#include "ltm.h"
|
#include "ltm.h"
|
||||||
@ -39,7 +40,7 @@ void luaT_init (lua_State *L) {
|
|||||||
int i;
|
int i;
|
||||||
for (i=0; i<TM_N; i++) {
|
for (i=0; i<TM_N; i++) {
|
||||||
G(L)->tmname[i] = luaS_new(L, luaT_eventname[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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
209
app/lua/lua.c
209
app/lua/lua.c
@ -13,6 +13,7 @@
|
|||||||
#include "user_version.h"
|
#include "user_version.h"
|
||||||
#include "driver/readline.h"
|
#include "driver/readline.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
#define lua_c
|
#define lua_c
|
||||||
|
|
||||||
@ -21,54 +22,16 @@
|
|||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "legc.h"
|
#include "legc.h"
|
||||||
|
#ifdef LUA_FLASH_STORE
|
||||||
|
#include "lflash.h"
|
||||||
|
#endif
|
||||||
#include "os_type.h"
|
#include "os_type.h"
|
||||||
|
|
||||||
lua_State *globalL = NULL;
|
lua_State *globalL = NULL;
|
||||||
|
|
||||||
lua_Load gLoad;
|
static lua_Load gLoad;
|
||||||
|
|
||||||
static const char *progname = LUA_PROGNAME;
|
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) {
|
static void l_message (const char *pname, const char *msg) {
|
||||||
#if defined(LUA_USE_STDIO)
|
#if defined(LUA_USE_STDIO)
|
||||||
if (pname) c_fprintf(c_stderr, "%s: ", pname);
|
if (pname) c_fprintf(c_stderr, "%s: ", pname);
|
||||||
@ -154,17 +117,11 @@ static int getargs (lua_State *L, char **argv, int n) {
|
|||||||
return narg;
|
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) {
|
static int dofsfile (lua_State *L, const char *name) {
|
||||||
int status = luaL_loadfsfile(L, name) || docall(L, 0, 1);
|
int status = luaL_loadfsfile(L, name) || docall(L, 0, 1);
|
||||||
return report(L, status);
|
return report(L, status);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int dostring (lua_State *L, const char *s, const char *name) {
|
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);
|
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... */
|
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 */
|
/* check that argument has no extra characters at the end */
|
||||||
#define notail(x) {if ((x)[2] != '\0') return -1;}
|
#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) {
|
#ifndef LUA_INIT_STRING
|
||||||
const char *init = c_getenv(LUA_INIT);
|
#define LUA_INIT_STRING "@init.lua"
|
||||||
if (init == NULL) return 0; /* status OK */
|
|
||||||
else if (init[0] == '@')
|
|
||||||
#if 0
|
|
||||||
return dofile(L, init+1);
|
|
||||||
#else
|
|
||||||
return dofsfile(L, init+1);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int handle_luainit (lua_State *L) {
|
||||||
|
const char *init = LUA_INIT_STRING;
|
||||||
|
if (init[0] == '@')
|
||||||
|
return dofsfile(L, init+1);
|
||||||
else
|
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);
|
lua_gc(L, LUA_GCRESTART, 0);
|
||||||
print_version(L);
|
print_version(L);
|
||||||
s->status = handle_luainit(L);
|
s->status = handle_luainit(L);
|
||||||
#if 0
|
|
||||||
if (s->status != 0) return 0;
|
|
||||||
#endif
|
|
||||||
script = collectargs(argv, &has_i, &has_v, &has_e);
|
script = collectargs(argv, &has_i, &has_v, &has_e);
|
||||||
if (script < 0) { /* invalid args? */
|
if (script < 0) { /* invalid args? */
|
||||||
#if 0
|
|
||||||
print_usage();
|
|
||||||
#endif
|
|
||||||
s->status = 1;
|
s->status = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// if (has_v) print_version();
|
|
||||||
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
|
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
|
||||||
if (s->status != 0) return 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dojob(lua_Load *load);
|
static void dojob(lua_Load *load);
|
||||||
static bool readline(lua_Load *load);
|
static bool readline(lua_Load *load);
|
||||||
char line_buffer[LUA_MAXINPUT];
|
|
||||||
|
|
||||||
#ifdef LUA_RPC
|
#ifdef LUA_RPC
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
@ -439,6 +287,13 @@ int lua_main (int argc, char **argv) {
|
|||||||
#endif
|
#endif
|
||||||
int status;
|
int status;
|
||||||
struct Smain s;
|
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 */
|
lua_State *L = lua_open(); /* create state */
|
||||||
if (L == NULL) {
|
if (L == NULL) {
|
||||||
l_message(argv[0], "cannot create state: not enough memory");
|
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.argc = argc;
|
||||||
s.argv = argv;
|
s.argv = argv;
|
||||||
|
|
||||||
status = lua_cpcall(L, &pmain, &s);
|
status = lua_cpcall(L, &pmain, &s);
|
||||||
|
|
||||||
report(L, status);
|
report(L, status);
|
||||||
|
|
||||||
gLoad.L = L;
|
gLoad.L = L;
|
||||||
gLoad.firstline = 1;
|
gLoad.firstline = 1;
|
||||||
gLoad.done = 0;
|
gLoad.done = 0;
|
||||||
gLoad.line = line_buffer;
|
gLoad.line = c_malloc(LUA_MAXINPUT);
|
||||||
gLoad.len = LUA_MAXINPUT;
|
gLoad.len = LUA_MAXINPUT;
|
||||||
gLoad.line_position = 0;
|
gLoad.line_position = 0;
|
||||||
gLoad.prmt = get_prompt(L, 1);
|
gLoad.prmt = get_prompt(L, 1);
|
||||||
|
|
||||||
dojob(&gLoad);
|
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_ALWAYS, 4096 );
|
||||||
// legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
|
// legc_set_mode( L, EGC_ON_MEM_LIMIT, 4096 );
|
||||||
// lua_close(L);
|
// lua_close(L);
|
||||||
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
|
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)
|
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);
|
dojob (&gLoad);
|
||||||
force = false;
|
force = false;
|
||||||
}
|
}
|
||||||
|
@ -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_pushnumber) (lua_State *L, lua_Number n);
|
||||||
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer 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_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 void (lua_pushstring) (lua_State *L, const char *s);
|
||||||
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
||||||
va_list argp);
|
va_list argp);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#define c_freopen freopen
|
#define c_freopen freopen
|
||||||
#define c_getc getc
|
#define c_getc getc
|
||||||
#define c_getenv getenv
|
#define c_getenv getenv
|
||||||
|
#define c_malloc malloc
|
||||||
#define c_memcmp memcmp
|
#define c_memcmp memcmp
|
||||||
#define c_memcpy memcpy
|
#define c_memcpy memcpy
|
||||||
#define c_printf printf
|
#define c_printf printf
|
||||||
@ -56,9 +57,10 @@
|
|||||||
#define c_strrchr strrchr
|
#define c_strrchr strrchr
|
||||||
#define c_strstr strstr
|
#define c_strstr strstr
|
||||||
double c_strtod(const char *__n, char **__end_PTR);
|
double c_strtod(const char *__n, char **__end_PTR);
|
||||||
#define c_strtoul strtoul
|
|
||||||
#define c_ungetc ungetc
|
#define c_ungetc ungetc
|
||||||
|
#define c_strtol strtol
|
||||||
|
#define c_strtoul strtoul
|
||||||
|
#define dbg_printf printf
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define C_HEADER_ASSERT "c_assert.h"
|
#define C_HEADER_ASSERT "c_assert.h"
|
||||||
|
92
app/lua/luac_cross/Makefile
Normal file
92
app/lua/luac_cross/Makefile
Normal 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 $@.$$$$
|
421
app/lua/luac_cross/lflashimg.c
Normal file
421
app/lua/luac_cross/lflashimg.c
Normal 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;
|
||||||
|
}
|
@ -5,14 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// #include "c_errno.h"
|
#include <errno.h>
|
||||||
#include "c_stdio.h"
|
#include <stdio.h>
|
||||||
#include "c_stdlib.h"
|
#include <stdlib.h>
|
||||||
#include "c_string.h"
|
#include <string.h>
|
||||||
#include "vfs.h"
|
|
||||||
|
|
||||||
#define liolib_c
|
#define liolib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
#define LUA_OPTIMIZE_MEMORY 2
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
@ -20,26 +20,21 @@
|
|||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "lrotable.h"
|
#include "lrotable.h"
|
||||||
|
|
||||||
|
|
||||||
#define IO_INPUT 1
|
#define IO_INPUT 1
|
||||||
#define IO_OUTPUT 2
|
#define IO_OUTPUT 2
|
||||||
#define IO_STDERR 0
|
#define IO_STDERR 0
|
||||||
|
|
||||||
#if LUA_OPTIMIZE_MEMORY != 2
|
#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[f]))
|
||||||
#define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_ENVIRONINDEX, f)
|
#define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX,(int)(liolib_keys[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])
|
|
||||||
|
|
||||||
/* "Pseudo-random" keys for the registry */
|
/* "Pseudo-random" keys for the registry */
|
||||||
static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int)&luaL_argerror};
|
static const size_t liolib_keys[] = {(size_t)&luaL_callmeta, (size_t)&luaL_typerror, (size_t)&luaL_argerror};
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char *const fnames[] = {"input", "output"};
|
static const char *const fnames[] = {"input", "output"};
|
||||||
|
|
||||||
|
|
||||||
static int pushresult (lua_State *L, int i, const char *filename) {
|
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) {
|
if (i) {
|
||||||
lua_pushboolean(L, 1);
|
lua_pushboolean(L, 1);
|
||||||
return 1;
|
return 1;
|
||||||
@ -47,9 +42,9 @@ static int pushresult (lua_State *L, int i, const char *filename) {
|
|||||||
else {
|
else {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
if (filename)
|
if (filename)
|
||||||
lua_pushfstring(L, "%s: err(%d)", filename, en);
|
lua_pushfstring(L, "%s: %s", filename, strerror(en));
|
||||||
else
|
else
|
||||||
lua_pushfstring(L, "err(%d)", en);
|
lua_pushfstring(L, "%s", strerror(en));
|
||||||
lua_pushinteger(L, en);
|
lua_pushinteger(L, en);
|
||||||
return 3;
|
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) {
|
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));
|
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) {
|
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);
|
lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
|
||||||
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
|
if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
|
||||||
lua_pushnil(L); /* not a file */
|
lua_pushnil(L); /* not a file */
|
||||||
else if (*((int *)ud) < FS_OPEN_OK)
|
else if (*((FILE **)ud) == NULL)
|
||||||
lua_pushliteral(L, "closed file");
|
lua_pushliteral(L, "closed file");
|
||||||
else
|
else
|
||||||
lua_pushliteral(L, "file");
|
lua_pushliteral(L, "file");
|
||||||
@ -80,9 +75,9 @@ static int io_type (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tofile (lua_State *L) {
|
static FILE *tofile (lua_State *L) {
|
||||||
int *f = tofilep(L);
|
FILE **f = tofilep(L);
|
||||||
if (*f < FS_OPEN_OK)
|
if (*f == NULL)
|
||||||
luaL_error(L, "attempt to use a closed file");
|
luaL_error(L, "attempt to use a closed file");
|
||||||
return *f;
|
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
|
** before opening the actual file; so, if there is a memory error, the
|
||||||
** file is not left opened.
|
** file is not left opened.
|
||||||
*/
|
*/
|
||||||
static int *newfile (lua_State *L) {
|
static FILE **newfile (lua_State *L) {
|
||||||
int *pf = (int *)lua_newuserdata(L, sizeof(int));
|
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
|
||||||
*pf = FS_OPEN_OK - 1; /* file handle is currently `closed' */
|
*pf = NULL; /* file handle is currently `closed' */
|
||||||
luaL_getmetatable(L, LUA_FILEHANDLE);
|
luaL_getmetatable(L, LUA_FILEHANDLE);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
return pf;
|
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) {
|
static int aux_close (lua_State *L) {
|
||||||
#if LUA_OPTIMIZE_MEMORY != 2
|
FILE **p = tofilep(L);
|
||||||
lua_getfenv(L, 1);
|
if(*p == stdin || *p == stdout || *p == stderr)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushliteral(L, "cannot close standard file");
|
lua_pushliteral(L, "cannot close standard file");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
int ok = (vfs_close(*p) == 0);
|
int ok = (fclose(*p) == 0);
|
||||||
*p = FS_OPEN_OK - 1;
|
*p = NULL;
|
||||||
return pushresult(L, ok, NULL);
|
return pushresult(L, ok, NULL);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int io_close (lua_State *L) {
|
static int io_close (lua_State *L) {
|
||||||
if (lua_isnone(L, 1))
|
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 */
|
tofile(L); /* make sure argument is a file */
|
||||||
return aux_close(L);
|
return aux_close(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int io_gc (lua_State *L) {
|
static int io_gc (lua_State *L) {
|
||||||
int f = *tofilep(L);
|
FILE *f = *tofilep(L);
|
||||||
/* ignore closed files */
|
/* ignore closed files */
|
||||||
if (f != FS_OPEN_OK - 1)
|
if (f != NULL)
|
||||||
aux_close(L);
|
aux_close(L);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int io_tostring (lua_State *L) {
|
static int io_tostring (lua_State *L) {
|
||||||
int f = *tofilep(L);
|
FILE *f = *tofilep(L);
|
||||||
if (f == FS_OPEN_OK - 1)
|
if (f == NULL)
|
||||||
lua_pushliteral(L, "file (closed)");
|
lua_pushliteral(L, "file (closed)");
|
||||||
else
|
else
|
||||||
lua_pushfstring(L, "file (%i)", f);
|
lua_pushfstring(L, "file (%p)", f);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,42 +142,19 @@ static int io_tostring (lua_State *L) {
|
|||||||
static int io_open (lua_State *L) {
|
static int io_open (lua_State *L) {
|
||||||
const char *filename = luaL_checkstring(L, 1);
|
const char *filename = luaL_checkstring(L, 1);
|
||||||
const char *mode = luaL_optstring(L, 2, "r");
|
const char *mode = luaL_optstring(L, 2, "r");
|
||||||
int *pf = newfile(L);
|
FILE **pf = newfile(L);
|
||||||
*pf = vfs_open(filename, mode);
|
*pf = fopen(filename, mode);
|
||||||
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
|
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static FILE *getiofile (lua_State *L, int findex) {
|
||||||
** this function has a separated environment, which defines the
|
FILE *f;
|
||||||
** correct __close for 'popen' files
|
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
|
||||||
*/
|
f = *(FILE **)lua_touserdata(L, -1);
|
||||||
#if 0
|
if (f == NULL)
|
||||||
static int io_popen (lua_State *L) {
|
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
|
||||||
const char *filename = luaL_checkstring(L, 1);
|
return f;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -229,19 +162,19 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
|
|||||||
if (!lua_isnoneornil(L, 1)) {
|
if (!lua_isnoneornil(L, 1)) {
|
||||||
const char *filename = lua_tostring(L, 1);
|
const char *filename = lua_tostring(L, 1);
|
||||||
if (filename) {
|
if (filename) {
|
||||||
int *pf = newfile(L);
|
FILE **pf = newfile(L);
|
||||||
*pf = vfs_open(filename, mode);
|
*pf = fopen(filename, mode);
|
||||||
if (*pf == FS_OPEN_OK - 1)
|
if (*pf == NULL)
|
||||||
fileerror(L, 1, filename);
|
fileerror(L, 1, filename);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tofile(L); /* check that it's a valid file handle */
|
tofile(L); /* check that it's a valid file handle */
|
||||||
lua_pushvalue(L, 1);
|
lua_pushvalue(L, 1);
|
||||||
}
|
}
|
||||||
LUA_IO_SETFIELD(f);
|
lua_rawseti(L, LUA_ENVIRONINDEX, f);
|
||||||
}
|
}
|
||||||
/* return current value */
|
/* return current value */
|
||||||
LUA_IO_GETFIELD(f);
|
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,14 +209,14 @@ static int f_lines (lua_State *L) {
|
|||||||
static int io_lines (lua_State *L) {
|
static int io_lines (lua_State *L) {
|
||||||
if (lua_isnoneornil(L, 1)) { /* no arguments? */
|
if (lua_isnoneornil(L, 1)) { /* no arguments? */
|
||||||
/* will iterate over default input */
|
/* will iterate over default input */
|
||||||
LUA_IO_GETFIELD(IO_INPUT);
|
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
|
||||||
return f_lines(L);
|
return f_lines(L);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const char *filename = luaL_checkstring(L, 1);
|
const char *filename = luaL_checkstring(L, 1);
|
||||||
int *pf = newfile(L);
|
FILE **pf = newfile(L);
|
||||||
*pf = vfs_open(filename, "r");
|
*pf = fopen(filename, "r");
|
||||||
if (*pf == FS_OPEN_OK - 1)
|
if (*pf == NULL)
|
||||||
fileerror(L, 1, filename);
|
fileerror(L, 1, filename);
|
||||||
aux_lines(L, lua_gettop(L), 1);
|
aux_lines(L, lua_gettop(L), 1);
|
||||||
return 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;
|
lua_Number d;
|
||||||
if (fs_scanf(f, LUA_NUMBER_SCAN, &d) == 1) {
|
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
|
||||||
lua_pushnumber(L, d);
|
lua_pushnumber(L, d);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -309,27 +242,27 @@ static int read_number (lua_State *L, int f) {
|
|||||||
return 0; /* read fails */
|
return 0; /* read fails */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int test_eof (lua_State *L, int f) {
|
|
||||||
int c = vfs_getc(f);
|
static int test_eof (lua_State *L, FILE *f) {
|
||||||
vfs_ungetc(c, f);
|
int c = getc(f);
|
||||||
|
ungetc(c, f);
|
||||||
lua_pushlstring(L, NULL, 0);
|
lua_pushlstring(L, NULL, 0);
|
||||||
return (c != EOF);
|
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_Buffer b;
|
||||||
luaL_buffinit(L, &b);
|
luaL_buffinit(L, &b);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t l;
|
size_t l;
|
||||||
char *p = luaL_prepbuffer(&b);
|
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 */
|
luaL_pushresult(&b); /* close buffer */
|
||||||
return (lua_objlen(L, -1) > 0); /* check whether read something */
|
return (lua_objlen(L, -1) > 0); /* check whether read something */
|
||||||
}
|
}
|
||||||
l = c_strlen(p);
|
l = strlen(p);
|
||||||
if (l == 0 || p[l-1] != '\n')
|
if (l == 0 || p[l-1] != '\n')
|
||||||
luaL_addsize(&b, l);
|
luaL_addsize(&b, l);
|
||||||
else {
|
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 rlen; /* how much to read */
|
||||||
size_t nr; /* number of chars actually read */
|
size_t nr; /* number of chars actually read */
|
||||||
luaL_Buffer b;
|
luaL_Buffer b;
|
||||||
@ -368,7 +283,7 @@ static int read_chars (lua_State *L, int f, size_t n) {
|
|||||||
do {
|
do {
|
||||||
char *p = luaL_prepbuffer(&b);
|
char *p = luaL_prepbuffer(&b);
|
||||||
if (rlen > n) rlen = n; /* cannot read more than asked */
|
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);
|
luaL_addsize(&b, nr);
|
||||||
n -= nr; /* still have to read `n' chars */
|
n -= nr; /* still have to read `n' chars */
|
||||||
} while (n > 0 && nr == rlen); /* until end of count or eof */
|
} 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 nargs = lua_gettop(L) - 1;
|
||||||
int success;
|
int success;
|
||||||
int n;
|
int n;
|
||||||
//vfs_clearerr(f);
|
clearerr(f);
|
||||||
if (nargs == 0) { /* no arguments? */
|
if (nargs == 0) { /* no arguments? */
|
||||||
success = read_line(L, f);
|
success = read_line(L, f);
|
||||||
n = first+1; /* to return 1 result */
|
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);
|
const char *p = lua_tostring(L, n);
|
||||||
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
|
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
|
||||||
switch (p[1]) {
|
switch (p[1]) {
|
||||||
#if 0
|
|
||||||
case 'n': /* number */
|
case 'n': /* number */
|
||||||
success = read_number(L, f);
|
success = read_number(L, f);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 'l': /* line */
|
case 'l': /* line */
|
||||||
success = read_line(L, f);
|
success = read_line(L, f);
|
||||||
break;
|
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);
|
return pushresult(L, 0, NULL);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
lua_pop(L, 1); /* remove last result */
|
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) {
|
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;
|
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");
|
luaL_error(L, "file is already closed");
|
||||||
return 0;
|
sucess = read_line(L, f);
|
||||||
}
|
if (ferror(f))
|
||||||
sucess = read_line(L, *pf);
|
return luaL_error(L, "%s", strerror(errno));
|
||||||
if (vfs_ferrno(*pf))
|
|
||||||
return luaL_error(L, "err(%d)", vfs_ferrno(*pf));
|
|
||||||
if (sucess) return 1;
|
if (sucess) return 1;
|
||||||
else { /* EOF */
|
else { /* EOF */
|
||||||
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
|
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 nargs = lua_gettop(L) - 1;
|
||||||
int status = 1;
|
int status = 1;
|
||||||
for (; nargs--; arg++) {
|
for (; nargs--; arg++) {
|
||||||
#if 0
|
|
||||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||||
/* optimization: could be done exactly as for strings */
|
/* optimization: could be done exactly as for strings */
|
||||||
status = status &&
|
status = status &&
|
||||||
fs_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
|
fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
#endif
|
|
||||||
{
|
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *s = luaL_checklstring(L, arg, &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);
|
return pushresult(L, status, NULL);
|
||||||
@ -493,159 +401,103 @@ static int f_write (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
static int f_seek (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};
|
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);
|
int op = luaL_checkoption(L, 2, "cur", modenames);
|
||||||
long offset = luaL_optlong(L, 3, 0);
|
long offset = luaL_optlong(L, 3, 0);
|
||||||
op = vfs_lseek(f, offset, mode[op]);
|
op = fseek(f, offset, mode[op]);
|
||||||
if (op)
|
if (op)
|
||||||
return pushresult(L, 0, NULL); /* error */
|
return pushresult(L, 0, NULL); /* error */
|
||||||
else {
|
else {
|
||||||
lua_pushinteger(L, vfs_tell(f));
|
lua_pushinteger(L, ftell(f));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static int f_setvbuf (lua_State *L) {
|
static int f_setvbuf (lua_State *L) {
|
||||||
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
|
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
|
||||||
static const char *const modenames[] = {"no", "full", "line", NULL};
|
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);
|
int op = luaL_checkoption(L, 2, NULL, modenames);
|
||||||
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
||||||
int res = setvbuf(f, NULL, mode[op], sz);
|
int res = setvbuf(f, NULL, mode[op], sz);
|
||||||
return pushresult(L, res == 0, NULL);
|
return pushresult(L, res == 0, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int io_flush (lua_State *L) {
|
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) {
|
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
|
#define MIN_OPT_LEVEL 2
|
||||||
#include "lrodefs.h"
|
#include "lrodefs.h"
|
||||||
#if LUA_OPTIMIZE_MEMORY == 2
|
|
||||||
const LUA_REG_TYPE iolib_funcs[] = {
|
const LUA_REG_TYPE iolib_funcs[] = {
|
||||||
#else
|
{LSTRKEY("close"), LFUNCVAL(io_close)},
|
||||||
const LUA_REG_TYPE iolib[] = {
|
{LSTRKEY("flush"), LFUNCVAL(io_flush)},
|
||||||
#endif
|
{LSTRKEY("input"), LFUNCVAL(io_input)},
|
||||||
{LSTRKEY("close"), LFUNCVAL(io_close)},
|
{LSTRKEY("lines"), LFUNCVAL(io_lines)},
|
||||||
{LSTRKEY("flush"), LFUNCVAL(io_flush)},
|
{LSTRKEY("open"), LFUNCVAL(io_open)},
|
||||||
{LSTRKEY("input"), LFUNCVAL(io_input)},
|
{LSTRKEY("output"), LFUNCVAL(io_output)},
|
||||||
{LSTRKEY("lines"), LFUNCVAL(io_lines)},
|
{LSTRKEY("read"), LFUNCVAL(io_read)},
|
||||||
{LSTRKEY("open"), LFUNCVAL(io_open)},
|
{LSTRKEY("type"), LFUNCVAL(io_type)},
|
||||||
{LSTRKEY("output"), LFUNCVAL(io_output)},
|
{LSTRKEY("write"), LFUNCVAL(io_write)},
|
||||||
// {LSTRKEY("popen"), LFUNCVAL(io_popen)},
|
{LSTRKEY("__index"), LROVAL(iolib_funcs)},
|
||||||
{LSTRKEY("read"), LFUNCVAL(io_read)},
|
|
||||||
// {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)},
|
|
||||||
{LSTRKEY("type"), LFUNCVAL(io_type)},
|
|
||||||
{LSTRKEY("write"), LFUNCVAL(io_write)},
|
|
||||||
{LNILKEY, LNILVAL}
|
{LNILKEY, LNILVAL}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LUA_OPTIMIZE_MEMORY == 2
|
/* Note that IO objects use a RAM metatable created to allow extensibility */
|
||||||
static int luaL_index(lua_State *L)
|
|
||||||
|
static int io_index(lua_State *L)
|
||||||
{
|
{
|
||||||
return luaR_findfunction(L, iolib_funcs);
|
return luaR_findfunction(L, iolib_funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg iolib[] = {
|
const luaL_Reg iolib[] = {
|
||||||
{"__index", luaL_index},
|
{"__index", io_index},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef MIN_OPT_LEVEL
|
#undef MIN_OPT_LEVEL
|
||||||
#define MIN_OPT_LEVEL 1
|
#define MIN_OPT_LEVEL 1
|
||||||
#include "lrodefs.h"
|
#include "lrodefs.h"
|
||||||
const LUA_REG_TYPE flib[] = {
|
const LUA_REG_TYPE flib[] = {
|
||||||
{LSTRKEY("close"), LFUNCVAL(io_close)},
|
{LSTRKEY("close"), LFUNCVAL(io_close)},
|
||||||
{LSTRKEY("flush"), LFUNCVAL(f_flush)},
|
{LSTRKEY("flush"), LFUNCVAL(f_flush)},
|
||||||
{LSTRKEY("lines"), LFUNCVAL(f_lines)},
|
{LSTRKEY("lines"), LFUNCVAL(f_lines)},
|
||||||
{LSTRKEY("read"), LFUNCVAL(f_read)},
|
{LSTRKEY("read"), LFUNCVAL(f_read)},
|
||||||
{LSTRKEY("seek"), LFUNCVAL(f_seek)},
|
{LSTRKEY("seek"), LFUNCVAL(f_seek)},
|
||||||
// {LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)},
|
{LSTRKEY("setvbuf"), LFUNCVAL(f_setvbuf)},
|
||||||
{LSTRKEY("write"), LFUNCVAL(f_write)},
|
{LSTRKEY("write"), LFUNCVAL(f_write)},
|
||||||
{LSTRKEY("__gc"), LFUNCVAL(io_gc)},
|
{LSTRKEY("__gc"), LFUNCVAL(io_gc)},
|
||||||
{LSTRKEY("__tostring"), LFUNCVAL(io_tostring)},
|
{LSTRKEY("__tostring"), LFUNCVAL(io_tostring)},
|
||||||
#if LUA_OPTIMIZE_MEMORY > 0
|
{LSTRKEY("__index"), LROVAL(flib)},
|
||||||
{LSTRKEY("__index"), LROVAL(flib)},
|
|
||||||
#endif
|
|
||||||
{LNILKEY, LNILVAL}
|
{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, FILE *f, int k, const char *fname) {
|
||||||
static void createstdfile (lua_State *L, int f, int k, const char *fname) {
|
|
||||||
*newfile(L) = f;
|
*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
|
lua_pushvalue(L, -1);
|
||||||
static void newfenv (lua_State *L, lua_CFunction cls) {
|
lua_rawseti(L, LUA_REGISTRYINDEX, (int)(liolib_keys[k]));
|
||||||
lua_createtable(L, 0, 1);
|
lua_setfield(L, -2, fname);
|
||||||
lua_pushcfunction(L, cls);
|
|
||||||
lua_setfield(L, -2, "__close");
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
LUALIB_API int luaopen_io (lua_State *L) {
|
LUALIB_API int luaopen_io (lua_State *L) {
|
||||||
createmeta(L);
|
luaL_rometatable(L, LUA_FILEHANDLE, (void*)flib); /* create metatable for file handles */
|
||||||
#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_register_light(L, LUA_IOLIBNAME, iolib);
|
luaL_register_light(L, LUA_IOLIBNAME, iolib);
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
/* create (and set) default files */
|
/* create (and set) default files */
|
||||||
createstdfile(L, c_stdin, IO_INPUT, "stdin");
|
createstdfile(L, stdin, IO_INPUT, "stdin");
|
||||||
createstdfile(L, c_stdout, IO_OUTPUT, "stdout");
|
createstdfile(L, stdout, IO_OUTPUT, "stdout");
|
||||||
createstdfile(L, c_stderr, IO_STDERR, "stderr");
|
createstdfile(L, stderr, 0, "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
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
@ -11,13 +11,14 @@
|
|||||||
#include C_HEADER_STDIO
|
#include C_HEADER_STDIO
|
||||||
#include C_HEADER_STDLIB
|
#include C_HEADER_STDLIB
|
||||||
#include C_HEADER_STRING
|
#include C_HEADER_STRING
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define luac_c
|
#define luac_c
|
||||||
#define LUA_CORE
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
#include "lfunc.h"
|
#include "lfunc.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
@ -31,17 +32,23 @@
|
|||||||
|
|
||||||
static int listing=0; /* list bytecodes? */
|
static int listing=0; /* list bytecodes? */
|
||||||
static int dumping=1; /* dump 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 char Output[]={ OUTPUT }; /* default output file name */
|
||||||
static const char* output=Output; /* actual 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 const char* progname=PROGNAME; /* actual program name */
|
||||||
static DumpTargetInfo target;
|
static DumpTargetInfo target;
|
||||||
|
|
||||||
static void fatal(const char* message)
|
void luac_fatal(const char* message)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"%s: %s\n",progname,message);
|
fprintf(stderr,"%s: %s\n",progname,message);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
#define fatal(s) luac_fatal(s)
|
||||||
|
|
||||||
|
|
||||||
static void cannot(const char* what)
|
static void cannot(const char* what)
|
||||||
{
|
{
|
||||||
@ -61,18 +68,21 @@ static void usage(const char* message)
|
|||||||
" - process stdin\n"
|
" - process stdin\n"
|
||||||
" -l list\n"
|
" -l list\n"
|
||||||
" -o name output to file " LUA_QL("name") " (default is \"%s\")\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"
|
" -p parse only\n"
|
||||||
" -s strip debug information\n"
|
" -s strip debug information\n"
|
||||||
" -v show version 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",
|
" -- stop handling options\n",
|
||||||
progname,Output);
|
progname,Output);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS(s) (strcmp(argv[i],s)==0)
|
#define IS(s) (strcmp(argv[i],s)==0)
|
||||||
|
#define IROM0_SEG 0x40210000ul
|
||||||
|
#define IROM0_SEGMAX 0x00100000ul
|
||||||
|
|
||||||
static int doargs(int argc, char* argv[])
|
static int doargs(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
@ -89,8 +99,28 @@ static int doargs(int argc, char* argv[])
|
|||||||
if (version) ++version;
|
if (version) ++version;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (IS("-")) /* end of options; use stdin */
|
else if (IS("-")) /* end of options; use stdin */
|
||||||
break;
|
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 */
|
else if (IS("-l")) /* list */
|
||||||
++listing;
|
++listing;
|
||||||
else if (IS("-o")) /* output file */
|
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 (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
|
||||||
if (IS("-")) output=NULL;
|
if (IS("-")) output=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (IS("-p")) /* parse only */
|
else if (IS("-p")) /* parse only */
|
||||||
dumping=0;
|
dumping=0;
|
||||||
else if (IS("-s")) /* strip debug information */
|
else if (IS("-s")) /* strip debug information */
|
||||||
stripping=1;
|
stripping=1;
|
||||||
else if (IS("-v")) /* show version */
|
else if (IS("-v")) /* show version */
|
||||||
++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 */
|
else /* unknown option */
|
||||||
usage(argv[i]);
|
usage(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i==argc && (listing || !dumping))
|
if (i==argc && (listing || !dumping))
|
||||||
{
|
{
|
||||||
dumping=0;
|
dumping=0;
|
||||||
@ -150,30 +155,99 @@ static int doargs(int argc, char* argv[])
|
|||||||
|
|
||||||
#define toproto(L,i) (clvalue(L->top+(i))->l.p)
|
#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);
|
return toproto(L,-1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i,pc;
|
int i;
|
||||||
|
Instruction *pc;
|
||||||
Proto* f=luaF_newproto(L);
|
Proto* f=luaF_newproto(L);
|
||||||
setptvalue2s(L,L->top,f); incr_top(L);
|
setptvalue2s(L,L->top,f); incr_top(L);
|
||||||
f->source=luaS_newliteral(L,"=(" PROGNAME ")");
|
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->p=luaM_newvector(L,n,Proto*);
|
||||||
f->sizep=n;
|
f->sizep=n;
|
||||||
|
for (i=0; i<n; i++)
|
||||||
|
f->p[i]=toproto(L,i-n-1);
|
||||||
pc=0;
|
pc=0;
|
||||||
for (i=0; i<n; i++)
|
|
||||||
{
|
if (type == 0) {
|
||||||
f->p[i]=toproto(L,i-n-1);
|
/*
|
||||||
f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
|
* Type 0 is as per the standard luac, which is just a main routine which
|
||||||
f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
|
* 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;
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,6 +263,9 @@ struct Smain {
|
|||||||
char** argv;
|
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)
|
static int pmain(lua_State* L)
|
||||||
{
|
{
|
||||||
struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
|
struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
|
||||||
@ -197,19 +274,39 @@ static int pmain(lua_State* L)
|
|||||||
const Proto* f;
|
const Proto* f;
|
||||||
int i;
|
int i;
|
||||||
if (!lua_checkstack(L,argc)) fatal("too many input files");
|
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++)
|
for (i=0; i<argc; i++)
|
||||||
{
|
{
|
||||||
const char* filename=IS("-") ? NULL : argv[i];
|
const char* filename=IS("-") ? NULL : argv[i];
|
||||||
if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
|
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 (listing) luaU_print(f,listing>1);
|
||||||
if (dumping)
|
if (dumping)
|
||||||
{
|
{
|
||||||
|
int result;
|
||||||
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
|
FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
|
||||||
if (D==NULL) cannot("open");
|
if (D==NULL) cannot("open");
|
||||||
lua_lock(L);
|
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);
|
lua_unlock(L);
|
||||||
if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type");
|
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");
|
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);
|
int i=doargs(argc,argv);
|
||||||
argc-=i; argv+=i;
|
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();
|
L=lua_open();
|
||||||
if (L==NULL) fatal("not enough memory for state");
|
if (L==NULL) fatal("not enough memory for state");
|
||||||
s.argc=argc;
|
s.argc=argc;
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
#define LUA_WIN
|
#define LUA_WIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LUA_CROSS_COMPILER)
|
||||||
|
#define LUA_USE_LINUX
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(LUA_USE_LINUX)
|
#if defined(LUA_USE_LINUX)
|
||||||
#define LUA_USE_POSIX
|
#define LUA_USE_POSIX
|
||||||
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
|
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
|
||||||
@ -59,7 +64,7 @@
|
|||||||
#if defined(LUA_USE_POSIX)
|
#if defined(LUA_USE_POSIX)
|
||||||
#define LUA_USE_MKSTEMP
|
#define LUA_USE_MKSTEMP
|
||||||
#define LUA_USE_ISATTY
|
#define LUA_USE_ISATTY
|
||||||
#define LUA_USE_POPEN
|
//#define LUA_USE_POPEN
|
||||||
#define LUA_USE_ULONGJMP
|
#define LUA_USE_ULONGJMP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -167,7 +172,7 @@
|
|||||||
#define LUA_INTEGER ptrdiff_t
|
#define LUA_INTEGER ptrdiff_t
|
||||||
#else
|
#else
|
||||||
#if !defined LUA_INTEGRAL_LONGLONG
|
#if !defined LUA_INTEGRAL_LONGLONG
|
||||||
#define LUA_INTEGER long
|
#define LUA_INTEGER int
|
||||||
#else
|
#else
|
||||||
#define LUA_INTEGER long long
|
#define LUA_INTEGER long long
|
||||||
#endif // #if !defined LUA_INTEGRAL_LONGLONG
|
#endif // #if !defined LUA_INTEGRAL_LONGLONG
|
||||||
@ -487,7 +492,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
|
|||||||
/* 16-bit ints */
|
/* 16-bit ints */
|
||||||
#define LUAI_UINT32 unsigned long
|
#define LUAI_UINT32 unsigned long
|
||||||
#define LUAI_INT32 long
|
#define LUAI_INT32 long
|
||||||
#define LUAI_MAXINT32 LONG_MAX
|
#define LUAI_MAXINT32 INT_MAX
|
||||||
#define LUAI_UMEM unsigned long
|
#define LUAI_UMEM unsigned long
|
||||||
#define LUAI_MEM long
|
#define LUAI_MEM long
|
||||||
#endif
|
#endif
|
||||||
@ -607,8 +612,8 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
|
|||||||
*/
|
*/
|
||||||
#if defined LUA_NUMBER_INTEGRAL
|
#if defined LUA_NUMBER_INTEGRAL
|
||||||
#if !defined LUA_INTEGRAL_LONGLONG
|
#if !defined LUA_INTEGRAL_LONGLONG
|
||||||
#define LUA_NUMBER_SCAN "%ld"
|
#define LUA_NUMBER_SCAN "%d"
|
||||||
#define LUA_NUMBER_FMT "%ld"
|
#define LUA_NUMBER_FMT "%d"
|
||||||
#else
|
#else
|
||||||
#define LUA_NUMBER_SCAN "%lld"
|
#define LUA_NUMBER_SCAN "%lld"
|
||||||
#define LUA_NUMBER_FMT "%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
|
/* 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)
|
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
|
#define LUA_META_ROTABLES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ static TString* LoadString(LoadState* S)
|
|||||||
} else {
|
} else {
|
||||||
s = (char*)luaZ_get_crt_address(S->Z);
|
s = (char*)luaZ_get_crt_address(S->Z);
|
||||||
LoadBlock(S,NULL,size);
|
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;
|
Proto* f;
|
||||||
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
|
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
|
||||||
f=luaF_newproto(S->L);
|
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);
|
setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
|
||||||
f->source=LoadString(S); if (f->source==NULL) f->source=p;
|
f->source=LoadString(S); if (f->source==NULL) f->source=p;
|
||||||
f->linedefined=LoadInt(S);
|
f->linedefined=LoadInt(S);
|
||||||
|
@ -41,7 +41,7 @@ LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) {
|
|||||||
LUA_NUMBER c = 1;
|
LUA_NUMBER c = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (b & 1)
|
if (b & 1)
|
||||||
c *= a;
|
c *= a;
|
||||||
b = b >> 1;
|
b = b >> 1;
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return c;
|
return c;
|
||||||
|
2
app/lwip/app/dhcpserver.c
Executable file → Normal file
2
app/lwip/app/dhcpserver.c
Executable file → Normal file
@ -689,6 +689,7 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
|
|||||||
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
|
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
|
||||||
#endif
|
#endif
|
||||||
send_ack(pmsg_dhcps, malloc_len);
|
send_ack(pmsg_dhcps, malloc_len);
|
||||||
|
wifi_softap_set_station_info(pmsg_dhcps->chaddr, &client_address.addr);
|
||||||
break;
|
break;
|
||||||
case DHCPS_STATE_NAK://4
|
case DHCPS_STATE_NAK://4
|
||||||
#if DHCPS_DEBUG
|
#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);
|
node_insert_to_list(&plist,pback_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wifi_softap_set_station_info(bssid, &pdhcps_pool->ip);
|
|
||||||
|
|
||||||
return pdhcps_pool->ip.addr;
|
return pdhcps_pool->ip.addr;
|
||||||
}
|
}
|
||||||
|
@ -1105,6 +1105,8 @@ espconn_set_opt(struct espconn *espconn, uint8 opt)
|
|||||||
if (value) {
|
if (value) {
|
||||||
pnode->pcommon.espconn_opt |= opt;
|
pnode->pcommon.espconn_opt |= opt;
|
||||||
tpcb = pnode->pcommon.pcb;
|
tpcb = pnode->pcommon.pcb;
|
||||||
|
if (NULL == tpcb)
|
||||||
|
return ESPCONN_OK;
|
||||||
if (espconn_delay_disabled(pnode))
|
if (espconn_delay_disabled(pnode))
|
||||||
tcp_nagle_disable(tpcb);
|
tcp_nagle_disable(tpcb);
|
||||||
|
|
||||||
@ -1143,7 +1145,8 @@ espconn_clear_opt(struct espconn *espconn, uint8 opt)
|
|||||||
tpcb = pnode->pcommon.pcb;
|
tpcb = pnode->pcommon.pcb;
|
||||||
if (espconn_keepalive_enabled(pnode))
|
if (espconn_keepalive_enabled(pnode))
|
||||||
espconn_keepalive_disable(tpcb);
|
espconn_keepalive_disable(tpcb);
|
||||||
|
if (NULL == tpcb)
|
||||||
|
return ESPCONN_OK;
|
||||||
if (espconn_delay_enabled(pnode))
|
if (espconn_delay_enabled(pnode))
|
||||||
tcp_nagle_enable(tpcb);
|
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);
|
value = espconn_find_connection(espconn, &pnode);
|
||||||
if (value && espconn_keepalive_disabled(pnode)) {
|
if (value && espconn_keepalive_disabled(pnode)) {
|
||||||
struct tcp_pcb *pcb = pnode->pcommon.pcb;
|
struct tcp_pcb *pcb = pnode->pcommon.pcb;
|
||||||
|
if (NULL == pcb)
|
||||||
|
return ESPCONN_OK;
|
||||||
switch (level){
|
switch (level){
|
||||||
case ESPCONN_KEEPIDLE:
|
case ESPCONN_KEEPIDLE:
|
||||||
pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg);
|
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);
|
value = espconn_find_connection(espconn, &pnode);
|
||||||
if (value && espconn_keepalive_disabled(pnode)) {
|
if (value && espconn_keepalive_disabled(pnode)) {
|
||||||
struct tcp_pcb *pcb = pnode->pcommon.pcb;
|
struct tcp_pcb *pcb = pnode->pcommon.pcb;
|
||||||
|
if (NULL == pcb)
|
||||||
|
return ESPCONN_OK;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case ESPCONN_KEEPIDLE:
|
case ESPCONN_KEEPIDLE:
|
||||||
*(int*)optarg = (int)(pcb->keep_idle/1000);
|
*(int*)optarg = (int)(pcb->keep_idle/1000);
|
||||||
|
@ -43,14 +43,14 @@ INCLUDES += -I ./
|
|||||||
INCLUDES += -I ../libc
|
INCLUDES += -I ../libc
|
||||||
INCLUDES += -I ../coap
|
INCLUDES += -I ../coap
|
||||||
INCLUDES += -I ../mqtt
|
INCLUDES += -I ../mqtt
|
||||||
INCLUDES += -I ../u8glib
|
INCLUDES += -I ../u8g2lib/u8g2/src/clib
|
||||||
INCLUDES += -I ../ucglib
|
INCLUDES += -I ../ucglib
|
||||||
INCLUDES += -I ../lua
|
INCLUDES += -I ../lua
|
||||||
INCLUDES += -I ../pcm
|
INCLUDES += -I ../pcm
|
||||||
INCLUDES += -I ../platform
|
INCLUDES += -I ../platform
|
||||||
INCLUDES += -I ../spiffs
|
INCLUDES += -I ../spiffs
|
||||||
INCLUDES += -I ../smart
|
INCLUDES += -I ../smart
|
||||||
INCLUDES += -I ../dhtlib
|
INCLUDES += -I ../dht
|
||||||
INCLUDES += -I ../fatfs
|
INCLUDES += -I ../fatfs
|
||||||
INCLUDES += -I ../http
|
INCLUDES += -I ../http
|
||||||
INCLUDES += -I ../sjson
|
INCLUDES += -I ../sjson
|
||||||
|
@ -214,18 +214,53 @@ static int file_open( lua_State* L )
|
|||||||
static int file_list( lua_State* L )
|
static int file_list( lua_State* L )
|
||||||
{
|
{
|
||||||
vfs_dir *dir;
|
vfs_dir *dir;
|
||||||
|
const char *pattern;
|
||||||
|
struct vfs_stat stat;
|
||||||
|
int pcres;
|
||||||
|
|
||||||
if (dir = vfs_opendir("")) {
|
lua_settop(L, 1);
|
||||||
lua_newtable( L );
|
pattern = luaL_optstring(L, 1, NULL); /* Pattern (arg) or nil (not) at 1 */
|
||||||
struct vfs_stat stat;
|
|
||||||
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
|
dir = vfs_opendir("");
|
||||||
lua_pushinteger(L, stat.size);
|
if (dir == NULL) {
|
||||||
lua_setfield(L, -2, stat.name);
|
return 0;
|
||||||
}
|
|
||||||
vfs_closedir(dir);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
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 )
|
static int get_file_obj( lua_State *L, int *argpos )
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
* This module, when enabled with the LUA_USE_MODULES_GDBSTUB define causes
|
* 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.
|
* 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
|
* 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
|
* 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
|
* 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[] = {
|
static const LUA_REG_TYPE gdbstub_map[] = {
|
||||||
{ LSTRKEY( "brk" ), LFUNCVAL( lgdbstub_break ) },
|
{ LSTRKEY( "brk" ), LFUNCVAL( lgdbstub_break ) },
|
||||||
{ LSTRKEY( "gdboutput" ), LFUNCVAL( lgdbstub_gdboutput) },
|
{ LSTRKEY( "gdboutput" ), LFUNCVAL( lgdbstub_gdboutput) },
|
||||||
|
{ LSTRKEY( "open" ), LFUNCVAL( lgdbstub_open) },
|
||||||
{ LNILKEY, LNILVAL }
|
{ LNILKEY, LNILVAL }
|
||||||
};
|
};
|
||||||
|
|
||||||
NODEMCU_MODULE(GDBSTUB, "gdbstub", gdbstub_map, lgdbstub_open);
|
NODEMCU_MODULE(GDBSTUB, "gdbstub", gdbstub_map, NULL);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "lrodefs.h"
|
#include "lrodefs.h"
|
||||||
|
#ifdef LUA_FLASH_STORE
|
||||||
|
#include "lflash.h"
|
||||||
|
#endif
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#include "c_string.h"
|
#include "c_string.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
@ -149,7 +151,6 @@ static int node_chipid( lua_State* L )
|
|||||||
// lua_pushinteger(L, vdd33);
|
// lua_pushinteger(L, vdd33);
|
||||||
// return 1;
|
// return 1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Lua: flashid()
|
// Lua: flashid()
|
||||||
static int node_flashid( lua_State* L )
|
static int node_flashid( lua_State* L )
|
||||||
{
|
{
|
||||||
@ -178,26 +179,16 @@ static int node_heap( lua_State* L )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern lua_Load gLoad;
|
extern int lua_put_line(const char *s, size_t l);
|
||||||
extern bool user_process_input(bool force);
|
extern bool user_process_input(bool force);
|
||||||
|
|
||||||
// Lua: input("string")
|
// Lua: input("string")
|
||||||
static int node_input( lua_State* L )
|
static int node_input( lua_State* L ) {
|
||||||
{
|
|
||||||
size_t l = 0;
|
size_t l = 0;
|
||||||
const char *s = luaL_checklstring(L, 1, &l);
|
const char *s = luaL_checklstring(L, 1, &l);
|
||||||
if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1)
|
if (lua_put_line(s, l)) {
|
||||||
{
|
NODE_DBG("Result (if any):\n");
|
||||||
lua_Load *load = &gLoad;
|
user_process_input(true);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -609,6 +600,13 @@ static const LUA_REG_TYPE node_task_map[] = {
|
|||||||
|
|
||||||
static const LUA_REG_TYPE node_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( "restart" ), LFUNCVAL( node_restart ) },
|
||||||
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
|
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
|
||||||
{ LSTRKEY( "dsleepMax" ), LFUNCVAL( dsleepMax ) },
|
{ LSTRKEY( "dsleepMax" ), LFUNCVAL( dsleepMax ) },
|
||||||
@ -616,11 +614,9 @@ static const LUA_REG_TYPE node_map[] =
|
|||||||
#ifdef PMSLEEP_ENABLE
|
#ifdef PMSLEEP_ENABLE
|
||||||
PMSLEEP_INT_MAP,
|
PMSLEEP_INT_MAP,
|
||||||
#endif
|
#endif
|
||||||
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) },
|
|
||||||
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) },
|
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) },
|
||||||
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
|
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
|
||||||
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
|
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
|
||||||
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
|
|
||||||
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
|
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
|
||||||
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
|
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
|
||||||
// Moved to adc module, use adc.readvdd33()
|
// Moved to adc module, use adc.readvdd33()
|
||||||
@ -637,7 +633,6 @@ static const LUA_REG_TYPE node_map[] =
|
|||||||
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
|
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
|
||||||
#endif
|
#endif
|
||||||
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
|
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
|
||||||
{ LSTRKEY( "task" ), LROVAL( node_task_map ) },
|
|
||||||
#ifdef DEVELOPMENT_TOOLS
|
#ifdef DEVELOPMENT_TOOLS
|
||||||
{ LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) },
|
{ LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) },
|
||||||
#endif
|
#endif
|
||||||
|
0
app/modules/tmr.c
Executable file → Normal file
0
app/modules/tmr.c
Executable file → Normal file
1003
app/modules/u8g.c
1003
app/modules/u8g.c
File diff suppressed because it is too large
Load Diff
816
app/modules/u8g2.c
Normal file
816
app/modules/u8g2.c
Normal 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) */
|
@ -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;
|
|
||||||
}
|
|
@ -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
0
app/modules/uart.c
Executable file → Normal file
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = mqtt.a
|
GEN_LIBS = libmqtt.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STD_CFLAGS=-std=gnu11 -Wimplicit
|
STD_CFLAGS=-std=gnu11 -Wimplicit
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = pcm.a
|
GEN_LIBS = libpcm.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STD_CFLAGS=-std=gnu11 -Wimplicit
|
STD_CFLAGS=-std=gnu11 -Wimplicit
|
||||||
|
@ -43,6 +43,7 @@ INCLUDES += -I ./
|
|||||||
INCLUDES += -I ../spiffs
|
INCLUDES += -I ../spiffs
|
||||||
INCLUDES += -I ../libc
|
INCLUDES += -I ../libc
|
||||||
INCLUDES += -I ../lua
|
INCLUDES += -I ../lua
|
||||||
|
INCLUDES += -I ../u8g2lib/u8g2/src/clib
|
||||||
PDIR := ../$(PDIR)
|
PDIR := ../$(PDIR)
|
||||||
sinclude $(PDIR)Makefile
|
sinclude $(PDIR)Makefile
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ extern char _flash_used_end[];
|
|||||||
|
|
||||||
// Helper function: find the flash sector in which an address resides
|
// 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
|
// 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
|
#ifdef INTERNAL_FLASH_SECTOR_SIZE
|
||||||
// All the sectors in the flash have the same size, so just align the address
|
// 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 )
|
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)
|
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;
|
uint32_t start, end, sect;
|
||||||
NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
|
NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
|
||||||
if(_flash_used_end>0){ // find the used sector
|
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 )
|
if( psect )
|
||||||
*psect = sect + 1;
|
*psect = sect + 1;
|
||||||
return end + 1;
|
return end + 1;
|
||||||
}else{
|
} else {
|
||||||
sect = flashh_find_sector( 0, &start, NULL ); // find the first free sector
|
sect = flash_find_sector( 0, &start, NULL ); // find the first free sector
|
||||||
if( psect )
|
if( psect )
|
||||||
*psect = sect;
|
*psect = sect;
|
||||||
return start;
|
return start;
|
||||||
|
@ -116,10 +116,11 @@ bool flash_rom_set_size_type(uint8_t size)
|
|||||||
uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
|
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))
|
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))
|
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))
|
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))
|
if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
|
||||||
{
|
{
|
||||||
((SPIFlashInfo *)(&data[0]))->speed = speed_type;
|
((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))
|
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
|
||||||
{
|
{
|
||||||
NODE_DBG("\nERASE SUCCESS\n");
|
NODE_DBG("\nERASE SUCCESS\n");
|
||||||
|
25
app/platform/platform.c
Executable file → Normal file
25
app/platform/platform.c
Executable file → Normal 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)
|
if(SPI_FLASH_RESULT_OK == r)
|
||||||
return size;
|
return size;
|
||||||
else{
|
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;
|
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)
|
if(SPI_FLASH_RESULT_OK == r)
|
||||||
return size;
|
return size;
|
||||||
else{
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int platform_flash_erase_sector( uint32_t sector_id )
|
int platform_flash_erase_sector( uint32_t sector_id )
|
||||||
{
|
{
|
||||||
|
NODE_DBG( "flash_erase_sector(%u)\n", sector_id);
|
||||||
system_soft_wdt_feed ();
|
system_soft_wdt_feed ();
|
||||||
return flash_erase( sector_id ) == SPI_FLASH_RESULT_OK ? PLATFORM_OK : PLATFORM_ERR;
|
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);
|
uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG);
|
||||||
if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
|
if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
|
||||||
return -1;
|
return -1;
|
||||||
bool b0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 1 : 0;
|
uint32_t m0 = (cache_ctrl & CACHE_FLASH_MAPPED0) ? 0x100000 : 0;
|
||||||
bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0;
|
uint32_t m1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 0x200000 : 0;
|
||||||
uint32_t meg = (b1 << 1) | b0;
|
return m0 + m1;
|
||||||
return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000;
|
}
|
||||||
|
|
||||||
|
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)
|
void* platform_print_deprecation_note( const char *msg, const char *time_frame)
|
||||||
|
@ -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
|
* 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)
|
* @param mapped_addr Address to translate (>= INTERNAL_FLASH_MAPPED_ADDRESS)
|
||||||
* @return the corresponding physical flash address, or -1 if flash cache is
|
* @return the corresponding physical flash address, or -1 if flash cache is
|
||||||
* not currently active.
|
* not currently active.
|
||||||
* @see Cache_Read_Enable.
|
* @see Cache_Read_Enable.
|
||||||
*/
|
*/
|
||||||
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr);
|
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr);
|
||||||
|
uint32_t platform_flash_phys2mapped (uint32_t phys_addr);
|
||||||
|
|
||||||
// *****************************************************************************
|
// *****************************************************************************
|
||||||
// Allocator support
|
// Allocator support
|
||||||
|
291
app/platform/u8x8_nodemcu_hal.c
Normal file
291
app/platform/u8x8_nodemcu_hal.c
Normal 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 */
|
26
app/platform/u8x8_nodemcu_hal.h
Normal file
26
app/platform/u8x8_nodemcu_hal.h
Normal 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 */
|
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = tsl2561lib.a
|
GEN_LIBS = libtsl2561.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STD_CFLAGS=-std=gnu11 -Wimplicit
|
STD_CFLAGS=-std=gnu11 -Wimplicit
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# a generated lib/image xxx.a ()
|
# a generated lib/image xxx.a ()
|
||||||
#
|
#
|
||||||
ifndef PDIR
|
ifndef PDIR
|
||||||
GEN_LIBS = u8glib.a
|
GEN_LIBS = libu8g2lib.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STD_CFLAGS=-std=gnu11 -Wimplicit
|
STD_CFLAGS=-std=gnu11 -Wimplicit
|
||||||
@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
|
|||||||
# makefile at its root level - these are then overridden
|
# makefile at its root level - these are then overridden
|
||||||
# for a subtree within the makefile rooted therein
|
# for a subtree within the makefile rooted therein
|
||||||
#
|
#
|
||||||
#DEFINES +=
|
DEFINES += -DU8X8_USE_PINS
|
||||||
|
|
||||||
#############################################################
|
#############################################################
|
||||||
# Recursion Magic - Don't touch this!!
|
# Recursion Magic - Don't touch this!!
|
||||||
@ -38,9 +38,13 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
|
|||||||
# Required for each makefile to inherit from the parent
|
# Required for each makefile to inherit from the parent
|
||||||
#
|
#
|
||||||
|
|
||||||
|
CSRCS := $(wildcard u8g2/src/clib/*.c *.c)
|
||||||
|
|
||||||
INCLUDES := $(INCLUDES) -I $(PDIR)include
|
INCLUDES := $(INCLUDES) -I $(PDIR)include
|
||||||
INCLUDES += -I ./
|
INCLUDES += -I u8g2/src/clib
|
||||||
INCLUDES += -I ../libc
|
INCLUDES += -I ../libc
|
||||||
|
INCLUDES += -I ../lua
|
||||||
|
INCLUDES += -I ../platform
|
||||||
PDIR := ../$(PDIR)
|
PDIR := ../$(PDIR)
|
||||||
sinclude $(PDIR)Makefile
|
sinclude $(PDIR)Makefile
|
||||||
|
|
1
app/u8g2lib/u8g2
Submodule
1
app/u8g2lib/u8g2
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 7f2fc42af3d01fdfe2cc19320bdcfe693dd2b20d
|
184
app/u8g2lib/u8x8_d_fbrle.c
Normal file
184
app/u8g2lib/u8x8_d_fbrle.c
Normal 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;
|
||||||
|
}
|
@ -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.
|
|
2072
app/u8glib/u8g.h
2072
app/u8glib/u8g.h
File diff suppressed because it is too large
Load Diff
@ -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--;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
Loading…
x
Reference in New Issue
Block a user