Re-root site.
This commit is contained in:
19
esp32/allocation.fs
Normal file
19
esp32/allocation.fs
Normal file
@ -0,0 +1,19 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Words with OS assist )
|
||||
: allocate ( n -- a ior ) malloc dup 0= ;
|
||||
: free ( a -- ior ) sysfree 0 ;
|
||||
: resize ( a n -- a ior ) realloc dup 0= ;
|
||||
|
||||
33
esp32/autoboot.fs
Normal file
33
esp32/autoboot.fs
Normal file
@ -0,0 +1,33 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
internals definitions
|
||||
|
||||
( Change default block source on arduino )
|
||||
: arduino-default-use s" /spiffs/blocks.fb" open-blocks ;
|
||||
' arduino-default-use is default-use
|
||||
|
||||
( Setup remember file )
|
||||
: arduino-remember-filename s" /spiffs/myforth" ;
|
||||
' arduino-remember-filename is remember-filename
|
||||
|
||||
( Check for autoexec.fs and run if present.
|
||||
Failing that, try to revive save image. )
|
||||
: autoexec
|
||||
300 for key? if rdrop exit then 10 ms next
|
||||
s" /spiffs/autoexec.fs" ['] included catch 2drop drop
|
||||
['] revive catch drop ;
|
||||
' autoexec ( leave on the stack for fini.fs )
|
||||
|
||||
forth definitions
|
||||
177
esp32/bindings.fs
Normal file
177
esp32/bindings.fs
Normal file
@ -0,0 +1,177 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Migrate various words to separate vocabularies, and constants )
|
||||
|
||||
vocabulary ESP ESP definitions
|
||||
transfer ESP-builtins
|
||||
only forth definitions
|
||||
|
||||
forth definitions
|
||||
|
||||
vocabulary Wire Wire definitions
|
||||
transfer wire-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary WiFi WiFi definitions
|
||||
transfer WiFi-builtins
|
||||
( WiFi Modes )
|
||||
0 constant WIFI_MODE_NULL
|
||||
1 constant WIFI_MODE_STA
|
||||
2 constant WIFI_MODE_AP
|
||||
3 constant WIFI_MODE_APSTA
|
||||
forth definitions
|
||||
|
||||
vocabulary SD SD definitions
|
||||
transfer SD-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary SD_MMC SD_MMC definitions
|
||||
transfer SD_MMC-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary spi_flash spi_flash definitions
|
||||
transfer spi_flash-builtins
|
||||
DEFINED? spi_flash_init [IF]
|
||||
0 constant SPI_PARTITION_TYPE_APP
|
||||
1 constant SPI_PARTITION_TYPE_DATA
|
||||
$ff constant SPI_PARTITION_SUBTYPE_ANY
|
||||
|
||||
also structures
|
||||
struct esp_partition_t
|
||||
( Work around changing struct layout )
|
||||
esp_partition_t_size 40 >= [IF]
|
||||
ptr field p>gap
|
||||
[THEN]
|
||||
ptr field p>type
|
||||
ptr field p>subtype
|
||||
ptr field p>address
|
||||
ptr field p>size
|
||||
ptr field p>label
|
||||
|
||||
: p. ( part -- )
|
||||
base @ >r >r decimal
|
||||
." TYPE: " r@ p>type @ . ." SUBTYPE: " r@ p>subtype @ .
|
||||
." ADDR: " r@ hex p>address @ . ." SIZE: " r@ p>size @ .
|
||||
." LABEL: " r> p>label @ z>s type cr r> base ! ;
|
||||
: list-partition-type ( type -- )
|
||||
SPI_PARTITION_SUBTYPE_ANY 0 esp_partition_find
|
||||
begin dup esp_partition_get p. esp_partition_next dup 0= until drop ;
|
||||
: list-partitions SPI_PARTITION_TYPE_APP list-partition-type
|
||||
SPI_PARTITION_TYPE_DATA list-partition-type ;
|
||||
[THEN]
|
||||
only forth definitions
|
||||
|
||||
vocabulary SPIFFS SPIFFS definitions
|
||||
transfer SPIFFS-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary ledc ledc definitions
|
||||
transfer ledc-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary Serial Serial definitions
|
||||
transfer Serial-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary sockets sockets definitions
|
||||
transfer sockets-builtins
|
||||
1 constant SOCK_STREAM
|
||||
2 constant AF_INET
|
||||
16 constant sizeof(sockaddr_in)
|
||||
1 constant SOL_SOCKET
|
||||
2 constant SO_REUSEADDR
|
||||
: bs, ( n -- ) dup 256 / c, c, ;
|
||||
: s, ( n -- ) dup c, 256 / c, ;
|
||||
: l, ( n -- ) dup s, 65536 / s, ;
|
||||
: sockaddr create 16 c, AF_INET c, 0 bs, 0 l, 0 l, 0 l, ;
|
||||
: ->port@ ( a -- n ) 2 + >r r@ c@ 256 * r> 1+ c@ + ;
|
||||
: ->port! ( n a -- ) 2 + >r dup 256 / r@ c! r> 1+ c! ;
|
||||
forth definitions
|
||||
|
||||
vocabulary interrupts interrupts definitions
|
||||
transfer interrupts-builtins
|
||||
DEFINED? gpio_config [IF]
|
||||
0 constant ESP_INTR_FLAG_DEFAULT
|
||||
: ESP_INTR_FLAG_LEVELn ( n=1-6 -- n ) 1 swap lshift ;
|
||||
1 7 lshift constant ESP_INTR_FLAG_NMI
|
||||
1 8 lshift constant ESP_INTR_FLAG_SHARED
|
||||
1 9 lshift constant ESP_INTR_FLAG_EDGE
|
||||
1 10 lshift constant ESP_INTR_FLAG_IRAM
|
||||
1 11 lshift constant ESP_INTR_FLAG_INTRDISABLED
|
||||
( Prefix these with # because GPIO_INTR_DISABLE conflicts with a function. )
|
||||
0 constant #GPIO_INTR_DISABLE
|
||||
1 constant #GPIO_INTR_POSEDGE
|
||||
2 constant #GPIO_INTR_NEGEDGE
|
||||
3 constant #GPIO_INTR_ANYEDGE
|
||||
4 constant #GPIO_INTR_LOW_LEVEL
|
||||
5 constant #GPIO_INTR_HIGH_LEVEL
|
||||
( Easy word to trigger on any change to a pin )
|
||||
ESP_INTR_FLAG_DEFAULT gpio_install_isr_service drop
|
||||
: pinchange ( xt pin ) dup #GPIO_INTR_ANYEDGE gpio_set_intr_type throw
|
||||
swap 0 gpio_isr_handler_add throw ;
|
||||
[THEN]
|
||||
forth definitions
|
||||
|
||||
vocabulary rmt rmt definitions
|
||||
transfer rmt-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary rtos rtos definitions
|
||||
transfer rtos-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary bluetooth bluetooth definitions
|
||||
transfer bluetooth-builtins
|
||||
forth definitions
|
||||
|
||||
vocabulary oled oled definitions
|
||||
transfer oled-builtins
|
||||
DEFINED? OledNew [IF]
|
||||
128 constant WIDTH
|
||||
64 constant HEIGHT
|
||||
-1 constant OledReset
|
||||
0 constant BLACK
|
||||
1 constant WHITE
|
||||
1 constant SSD1306_EXTERNALVCC
|
||||
2 constant SSD1306_SWITCHCAPVCC
|
||||
: OledInit
|
||||
OledAddr @ 0= if
|
||||
WIDTH HEIGHT OledReset OledNew
|
||||
SSD1306_SWITCHCAPVCC $3C OledBegin drop
|
||||
then
|
||||
OledCLS
|
||||
2 OledTextsize ( Draw 2x Scale Text )
|
||||
WHITE OledTextc ( Draw white text )
|
||||
0 0 OledSetCursor ( Start at top-left corner )
|
||||
z" *Esp32forth*" OledPrintln OledDisplay
|
||||
;
|
||||
[THEN]
|
||||
forth definitions
|
||||
|
||||
internals definitions
|
||||
( Heap Capabilities )
|
||||
binary
|
||||
0001 constant MALLOC_CAP_EXEC
|
||||
0010 constant MALLOC_CAP_32BIT
|
||||
0100 constant MALLOC_CAP_8BIT
|
||||
1000 constant MALLOC_CAP_DMA
|
||||
: MALLOC_CAP_PID ( n -- ) 10000 over 11 ( 3 ) - for 2* next ;
|
||||
000010000000000 constant MALLOC_CAP_SPIRAM
|
||||
000100000000000 constant MALLOC_CAP_INTERNAL
|
||||
001000000000000 constant MALLOC_CAP_DEFAULT
|
||||
010000000000000 constant MALLOC_CAP_IRAM_8BIT
|
||||
010000000000000 constant MALLOC_CAP_RETENTION
|
||||
decimal
|
||||
forth definitions
|
||||
29
esp32/bterm.fs
Normal file
29
esp32/bterm.fs
Normal file
@ -0,0 +1,29 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Lazy loaded Bluetooth Serial Terminal )
|
||||
: bterm r|
|
||||
vocabulary bterm bterm definitions
|
||||
also bluetooth also internals
|
||||
SerialBT.new constant bt
|
||||
z" forth" 0 bt SerialBT.begin drop
|
||||
esp_bt_dev_get_address hex 6 dump cr
|
||||
: bt-type bt SerialBT.write drop ;
|
||||
: bt-key
|
||||
begin bt SerialBT.available until 0 >r rp@ 1 bt SerialBT.readBytes drop r> ;
|
||||
: bt-on ['] bt-type is type ['] bt-key is key ;
|
||||
: bt-off ['] serial-type is type ['] serial-key is key ;
|
||||
only forth definitions
|
||||
bterm 500 ms bt-on
|
||||
| evaluate ;
|
||||
97
esp32/builtins.cpp
Normal file
97
esp32/builtins.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright 2022 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
static char filename[PATH_MAX];
|
||||
|
||||
{{core}}
|
||||
{{interp}}
|
||||
{{boot}}
|
||||
|
||||
// Work around lack of ftruncate
|
||||
static cell_t ResizeFile(cell_t fd, cell_t size) {
|
||||
struct stat st;
|
||||
char buf[256];
|
||||
cell_t t = fstat(fd, &st);
|
||||
if (t < 0) { return errno; }
|
||||
if (size < st.st_size) {
|
||||
// TODO: Implement truncation
|
||||
return ENOSYS;
|
||||
}
|
||||
cell_t oldpos = lseek(fd, 0, SEEK_CUR);
|
||||
if (oldpos < 0) { return errno; }
|
||||
t = lseek(fd, 0, SEEK_END);
|
||||
if (t < 0) { return errno; }
|
||||
memset(buf, 0, sizeof(buf));
|
||||
while (st.st_size < size) {
|
||||
cell_t len = sizeof(buf);
|
||||
if (size - st.st_size < len) {
|
||||
len = size - st.st_size;
|
||||
}
|
||||
t = write(fd, buf, len);
|
||||
if (t != len) {
|
||||
return errno;
|
||||
}
|
||||
st.st_size += t;
|
||||
}
|
||||
t = lseek(fd, oldpos, SEEK_SET);
|
||||
if (t < 0) { return errno; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INTERRUPTS_SUPPORT
|
||||
struct handle_interrupt_args {
|
||||
cell_t xt;
|
||||
cell_t arg;
|
||||
};
|
||||
|
||||
static void IRAM_ATTR HandleInterrupt(void *arg) {
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) arg;
|
||||
cell_t code[2];
|
||||
code[0] = args->xt;
|
||||
code[1] = g_sys.YIELD_XT;
|
||||
cell_t fstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t rstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t stack[INTERRUPT_STACK_CELLS];
|
||||
stack[0] = args->arg;
|
||||
cell_t *rp = rstack;
|
||||
*++rp = (cell_t) (fstack + 1);
|
||||
*++rp = (cell_t) (stack + 1);
|
||||
*++rp = (cell_t) code;
|
||||
forth_run(rp);
|
||||
}
|
||||
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return esp_intr_alloc(source, flags, HandleInterrupt, args, (intr_handle_t *) ret);
|
||||
}
|
||||
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return gpio_isr_handler_add((gpio_num_t) pin, HandleInterrupt, args);
|
||||
}
|
||||
|
||||
static cell_t TimerIsrRegister(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags, void *ret) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return timer_isr_register((timer_group_t) group, (timer_idx_t) timer, HandleInterrupt, args, flags, (timer_isr_handle_t *) ret);
|
||||
}
|
||||
#endif
|
||||
555
esp32/builtins.h
Normal file
555
esp32/builtins.h
Normal file
@ -0,0 +1,555 @@
|
||||
// Copyright 2022 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SIM_PRINT_ONLY
|
||||
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/select.h>
|
||||
|
||||
// Optional hook to pull in words for userwords.h
|
||||
# if __has_include("userwords.h")
|
||||
# include "userwords.h"
|
||||
# else
|
||||
# define USER_WORDS
|
||||
# endif
|
||||
|
||||
static cell_t ResizeFile(cell_t fd, cell_t size);
|
||||
|
||||
#endif
|
||||
|
||||
#define PLATFORM_OPCODE_LIST \
|
||||
USER_WORDS \
|
||||
REQUIRED_ESP_SUPPORT \
|
||||
REQUIRED_MEMORY_SUPPORT \
|
||||
REQUIRED_SERIAL_SUPPORT \
|
||||
REQUIRED_ARDUINO_GPIO_SUPPORT \
|
||||
REQUIRED_SYSTEM_SUPPORT \
|
||||
REQUIRED_FILES_SUPPORT \
|
||||
OPTIONAL_LEDC_SUPPORT \
|
||||
OPTIONAL_DAC_SUPPORT \
|
||||
OPTIONAL_SPIFFS_SUPPORT \
|
||||
OPTIONAL_WIFI_SUPPORT \
|
||||
OPTIONAL_MDNS_SUPPORT \
|
||||
OPTIONAL_SD_SUPPORT \
|
||||
OPTIONAL_SD_MMC_SUPPORT \
|
||||
OPTIONAL_I2C_SUPPORT \
|
||||
OPTIONAL_SERIAL_BLUETOOTH_SUPPORT \
|
||||
OPTIONAL_CAMERA_SUPPORT \
|
||||
OPTIONAL_SOCKETS_SUPPORT \
|
||||
OPTIONAL_FREERTOS_SUPPORT \
|
||||
OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
OPTIONAL_RMT_SUPPORT \
|
||||
OPTIONAL_OLED_SUPPORT \
|
||||
OPTIONAL_SPI_FLASH_SUPPORT \
|
||||
FLOATING_POINT_LIST
|
||||
|
||||
#define REQUIRED_MEMORY_SUPPORT \
|
||||
YV(internals, MALLOC, SET malloc(n0)) \
|
||||
YV(internals, SYSFREE, free(a0); DROP) \
|
||||
YV(internals, REALLOC, SET realloc(a1, n0); NIP) \
|
||||
YV(internals, heap_caps_malloc, SET heap_caps_malloc(n1, n0); NIP) \
|
||||
YV(internals, heap_caps_free, heap_caps_free(a0); DROP) \
|
||||
YV(internals, heap_caps_realloc, \
|
||||
tos = (cell_t) heap_caps_realloc(a2, n1, n0); NIPn(2))
|
||||
|
||||
#define REQUIRED_ESP_SUPPORT \
|
||||
YV(ESP, getHeapSize, PUSH ESP.getHeapSize()) \
|
||||
YV(ESP, getFreeHeap, PUSH ESP.getFreeHeap()) \
|
||||
YV(ESP, getMaxAllocHeap, PUSH ESP.getMaxAllocHeap()) \
|
||||
YV(ESP, getChipModel, PUSH ESP.getChipModel()) \
|
||||
YV(ESP, getChipCores, PUSH ESP.getChipCores()) \
|
||||
YV(ESP, getFlashChipSize, PUSH ESP.getFlashChipSize()) \
|
||||
YV(ESP, getCpuFreqMHz, PUSH ESP.getCpuFreqMHz()) \
|
||||
YV(ESP, getSketchSize, PUSH ESP.getSketchSize()) \
|
||||
YV(ESP, deepSleep, ESP.deepSleep(tos); DROP)
|
||||
|
||||
#define REQUIRED_SYSTEM_SUPPORT \
|
||||
X("MS-TICKS", MS_TICKS, PUSH millis()) \
|
||||
XV(internals, "RAW-YIELD", RAW_YIELD, yield()) \
|
||||
Y(TERMINATE, exit(n0))
|
||||
|
||||
#define REQUIRED_SERIAL_SUPPORT \
|
||||
XV(serial, "Serial.begin", SERIAL_BEGIN, Serial.begin(tos); DROP) \
|
||||
XV(serial, "Serial.end", SERIAL_END, Serial.end()) \
|
||||
XV(serial, "Serial.available", SERIAL_AVAILABLE, PUSH Serial.available()) \
|
||||
XV(serial, "Serial.readBytes", SERIAL_READ_BYTES, n0 = Serial.readBytes(b1, n0); NIP) \
|
||||
XV(serial, "Serial.write", SERIAL_WRITE, n0 = Serial.write(b1, n0); NIP) \
|
||||
XV(serial, "Serial.flush", SERIAL_FLUSH, Serial.flush())
|
||||
|
||||
#define REQUIRED_ARDUINO_GPIO_SUPPORT \
|
||||
Y(pinMode, pinMode(n1, n0); DROPn(2)) \
|
||||
Y(digitalWrite, digitalWrite(n1, n0); DROPn(2)) \
|
||||
Y(digitalRead, n0 = digitalRead(n0)) \
|
||||
Y(analogRead, n0 = analogRead(n0)) \
|
||||
Y(pulseIn, n0 = pulseIn(n2, n1, n0); NIPn(2))
|
||||
|
||||
#define REQUIRED_FILES_SUPPORT \
|
||||
X("R/O", R_O, PUSH O_RDONLY) \
|
||||
X("W/O", W_O, PUSH O_WRONLY) \
|
||||
X("R/W", R_W, PUSH O_RDWR) \
|
||||
Y(BIN, ) \
|
||||
X("CLOSE-FILE", CLOSE_FILE, tos = close(tos); tos = tos ? errno : 0) \
|
||||
X("FLUSH-FILE", FLUSH_FILE, fsync(tos); /* fsync has no impl and returns ENOSYS :-( */ tos = 0) \
|
||||
X("OPEN-FILE", OPEN_FILE, cell_t mode = n0; DROP; cell_t len = n0; DROP; \
|
||||
memcpy(filename, a0, len); filename[len] = 0; \
|
||||
n0 = open(filename, mode, 0777); PUSH n0 < 0 ? errno : 0) \
|
||||
X("CREATE-FILE", CREATE_FILE, cell_t mode = n0; DROP; cell_t len = n0; DROP; \
|
||||
memcpy(filename, a0, len); filename[len] = 0; \
|
||||
n0 = open(filename, mode | O_CREAT | O_TRUNC); PUSH n0 < 0 ? errno : 0) \
|
||||
X("DELETE-FILE", DELETE_FILE, cell_t len = n0; DROP; \
|
||||
memcpy(filename, a0, len); filename[len] = 0; \
|
||||
n0 = unlink(filename); n0 = n0 ? errno : 0) \
|
||||
X("RENAME-FILE", RENAME_FILE, NIPn(3); /* unimplemented */ n0 = 1) \
|
||||
X("WRITE-FILE", WRITE_FILE, cell_t fd = n0; DROP; cell_t len = n0; DROP; \
|
||||
n0 = write(fd, a0, len); n0 = n0 != len ? errno : 0) \
|
||||
X("READ-FILE", READ_FILE, cell_t fd = n0; DROP; cell_t len = n0; DROP; \
|
||||
n0 = read(fd, a0, len); PUSH n0 < 0 ? errno : 0) \
|
||||
X("FILE-POSITION", FILE_POSITION, \
|
||||
n0 = (cell_t) lseek(n0, 0, SEEK_CUR); PUSH n0 < 0 ? errno : 0) \
|
||||
X("REPOSITION-FILE", REPOSITION_FILE, cell_t fd = n0; DROP; \
|
||||
n0 = (cell_t) lseek(fd, tos, SEEK_SET); n0 = n0 < 0 ? errno : 0) \
|
||||
X("RESIZE-FILE", RESIZE_FILE, cell_t fd = n0; DROP; n0 = ResizeFile(fd, tos)) \
|
||||
X("FILE-SIZE", FILE_SIZE, struct stat st; w = fstat(n0, &st); \
|
||||
n0 = (cell_t) st.st_size; PUSH w < 0 ? errno : 0) \
|
||||
X("NON-BLOCK", NON_BLOCK, n0 = fcntl(n0, F_SETFL, O_NONBLOCK); \
|
||||
n0 = n0 < 0 ? errno : 0)
|
||||
|
||||
#ifndef ENABLE_LEDC_SUPPORT
|
||||
# define OPTIONAL_LEDC_SUPPORT
|
||||
#else
|
||||
# define OPTIONAL_LEDC_SUPPORT \
|
||||
YV(ledc, ledcSetup, \
|
||||
n0 = (cell_t) (1000000 * ledcSetup(n2, n1 / 1000.0, n0)); NIPn(2)) \
|
||||
YV(ledc, ledcAttachPin, ledcAttachPin(n1, n0); DROPn(2)) \
|
||||
YV(ledc, ledcDetachPin, ledcDetachPin(n0); DROP) \
|
||||
YV(ledc, ledcRead, n0 = ledcRead(n0)) \
|
||||
YV(ledc, ledcReadFreq, n0 = (cell_t) (1000000 * ledcReadFreq(n0))) \
|
||||
YV(ledc, ledcWrite, ledcWrite(n1, n0); DROPn(2)) \
|
||||
YV(ledc, ledcWriteTone, \
|
||||
n0 = (cell_t) (1000000 * ledcWriteTone(n1, n0 / 1000.0)); NIP) \
|
||||
YV(ledc, ledcWriteNote, \
|
||||
tos = (cell_t) (1000000 * ledcWriteNote(n2, (note_t) n1, n0)); NIPn(2))
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_DAC_SUPPORT
|
||||
# define OPTIONAL_DAC_SUPPORT
|
||||
# else
|
||||
# define OPTIONAL_DAC_SUPPORT \
|
||||
Y(dacWrite, dacWrite(n1, n0); DROPn(2))
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SPI_FLASH_SUPPORT
|
||||
# define OPTIONAL_SPI_FLASH_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "esp_spi_flash.h"
|
||||
# include "esp_partition.h"
|
||||
# endif
|
||||
# define OPTIONAL_SPI_FLASH_SUPPORT \
|
||||
YV(spi_flash, spi_flash_init, spi_flash_init()) \
|
||||
YV(spi_flash, spi_flash_get_chip_size, PUSH spi_flash_get_chip_size()) \
|
||||
YV(spi_flash, spi_flash_erase_sector, n0 = spi_flash_erase_sector(n0)) \
|
||||
YV(spi_flash, spi_flash_erase_range, n0 = spi_flash_erase_range(n1, n0); DROP) \
|
||||
YV(spi_flash, spi_flash_write, n0 = spi_flash_write(n2, a1, n0); NIPn(2)) \
|
||||
YV(spi_flash, spi_flash_write_encrypted, n0 = spi_flash_write_encrypted(n2, a1, n0); NIPn(2)) \
|
||||
YV(spi_flash, spi_flash_read, n0 = spi_flash_read(n2, a1, n0); NIPn(2)) \
|
||||
YV(spi_flash, spi_flash_read_encrypted, n0 = spi_flash_read_encrypted(n2, a1, n0); NIPn(2)) \
|
||||
YV(spi_flash, spi_flash_mmap, \
|
||||
n0 = spi_flash_mmap(n4, n3, (spi_flash_mmap_memory_t) n2, \
|
||||
(const void **) a1, (spi_flash_mmap_handle_t *) a0); NIPn(4)) \
|
||||
YV(spi_flash, spi_flash_mmap_pages, \
|
||||
n0 = spi_flash_mmap_pages((const int *) a4, n3, (spi_flash_mmap_memory_t) n2, \
|
||||
(const void **) a1, (spi_flash_mmap_handle_t *) a0); NIPn(4)) \
|
||||
YV(spi_flash, spi_flash_munmap, spi_flash_munmap((spi_flash_mmap_handle_t) a0); DROP) \
|
||||
YV(spi_flash, spi_flash_mmap_dump, spi_flash_mmap_dump()) \
|
||||
YV(spi_flash, spi_flash_mmap_get_free_pages, \
|
||||
n0 = spi_flash_mmap_get_free_pages((spi_flash_mmap_memory_t) n0)) \
|
||||
YV(spi_flash, spi_flash_cache2phys, n0 = spi_flash_cache2phys(a0)) \
|
||||
YV(spi_flash, spi_flash_phys2cache, \
|
||||
n0 = (cell_t) spi_flash_phys2cache(n1, (spi_flash_mmap_memory_t) n0); NIP) \
|
||||
YV(spi_flash, spi_flash_cache_enabled, PUSH spi_flash_cache_enabled()) \
|
||||
YV(spi_flash, esp_partition_find, \
|
||||
n0 = (cell_t) esp_partition_find((esp_partition_type_t) n2, \
|
||||
(esp_partition_subtype_t) n1, c0); NIPn(2)) \
|
||||
YV(spi_flash, esp_partition_find_first, \
|
||||
n0 = (cell_t) esp_partition_find_first((esp_partition_type_t) n2, \
|
||||
(esp_partition_subtype_t) n1, c0); NIPn(2)) \
|
||||
YV(spi_flash, esp_partition_t_size, PUSH sizeof(esp_partition_t)) \
|
||||
YV(spi_flash, esp_partition_get, \
|
||||
n0 = (cell_t) esp_partition_get((esp_partition_iterator_t) a0)) \
|
||||
YV(spi_flash, esp_partition_next, \
|
||||
n0 = (cell_t) esp_partition_next((esp_partition_iterator_t) a0)) \
|
||||
YV(spi_flash, esp_partition_iterator_release, \
|
||||
esp_partition_iterator_release((esp_partition_iterator_t) a0); DROP) \
|
||||
YV(spi_flash, esp_partition_verify, n0 = (cell_t) esp_partition_verify((esp_partition_t *) a0)) \
|
||||
YV(spi_flash, esp_partition_read, \
|
||||
n0 = esp_partition_read((const esp_partition_t *) a3, n2, a1, n0); NIPn(3)) \
|
||||
YV(spi_flash, esp_partition_write, \
|
||||
n0 = esp_partition_write((const esp_partition_t *) a3, n2, a1, n0); NIPn(3)) \
|
||||
YV(spi_flash, esp_partition_erase_range, \
|
||||
n0 = esp_partition_erase_range((const esp_partition_t *) a2, n1, n0); NIPn(2)) \
|
||||
YV(spi_flash, esp_partition_mmap, \
|
||||
n0 = esp_partition_mmap((const esp_partition_t *) a5, n4, n3, \
|
||||
(spi_flash_mmap_memory_t) n2, \
|
||||
(const void **) a1, \
|
||||
(spi_flash_mmap_handle_t *) a0); NIPn(5)) \
|
||||
YV(spi_flash, esp_partition_get_sha256, \
|
||||
n0 = esp_partition_get_sha256((const esp_partition_t *) a1, b0); NIP) \
|
||||
YV(spi_flash, esp_partition_check_identity, \
|
||||
n0 = esp_partition_check_identity((const esp_partition_t *) a1, \
|
||||
(const esp_partition_t *) a0); NIP)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SPIFFS_SUPPORT
|
||||
// Provide a default failing SPIFFS.begin
|
||||
# define OPTIONAL_SPIFFS_SUPPORT \
|
||||
X("SPIFFS.begin", SPIFFS_BEGIN, NIPn(2); n0 = 0)
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "SPIFFS.h"
|
||||
# endif
|
||||
# define OPTIONAL_SPIFFS_SUPPORT \
|
||||
XV(SPIFFS, "SPIFFS.begin", SPIFFS_BEGIN, \
|
||||
tos = SPIFFS.begin(n2, c1, n0); NIPn(2)) \
|
||||
XV(SPIFFS, "SPIFFS.end", SPIFFS_END, SPIFFS.end()) \
|
||||
XV(SPIFFS, "SPIFFS.format", SPIFFS_FORMAT, PUSH SPIFFS.format()) \
|
||||
XV(SPIFFS, "SPIFFS.totalBytes", SPIFFS_TOTAL_BYTES, PUSH SPIFFS.totalBytes()) \
|
||||
XV(SPIFFS, "SPIFFS.usedBytes", SPIFFS_USED_BYTES, PUSH SPIFFS.usedBytes())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_FREERTOS_SUPPORT
|
||||
# define OPTIONAL_FREERTOS_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/task.h"
|
||||
# endif
|
||||
# define OPTIONAL_FREERTOS_SUPPORT \
|
||||
YV(rtos, vTaskDelete, vTaskDelete((TaskHandle_t) n0); DROP) \
|
||||
YV(rtos, xTaskCreatePinnedToCore, n0 = xTaskCreatePinnedToCore((TaskFunction_t) a6, \
|
||||
c5, n4, a3, (UBaseType_t) n2, (TaskHandle_t *) a1, (BaseType_t) n0); NIPn(6)) \
|
||||
YV(rtos, xPortGetCoreID, PUSH xPortGetCoreID())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_INTERRUPTS_SUPPORT
|
||||
# define OPTIONAL_INTERRUPTS_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "esp_intr_alloc.h"
|
||||
# include "driver/timer.h"
|
||||
# include "driver/gpio.h"
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret);
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg);
|
||||
static cell_t TimerIsrRegister(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags, void *ret);
|
||||
# endif
|
||||
# define OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
YV(interrupts, gpio_config, n0 = gpio_config((const gpio_config_t *) a0)) \
|
||||
YV(interrupts, gpio_reset_pin, n0 = gpio_reset_pin((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_intr_type, n0 = gpio_set_intr_type((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_intr_enable, n0 = gpio_intr_enable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_intr_disable, n0 = gpio_intr_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_level, n0 = gpio_set_level((gpio_num_t) n1, n0); NIP) \
|
||||
YV(interrupts, gpio_get_level, n0 = gpio_get_level((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_direction, n0 = gpio_set_direction((gpio_num_t) n1, (gpio_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_set_pull_mode, n0 = gpio_set_pull_mode((gpio_num_t) n1, (gpio_pull_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_enable, n0 = gpio_wakeup_enable((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_disable, n0 = gpio_wakeup_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_en, n0 = gpio_pullup_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_dis, n0 = gpio_pullup_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_en, n0 = gpio_pulldown_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_dis, n0 = gpio_pulldown_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_en, n0 = gpio_hold_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_dis, n0 = gpio_hold_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_en, gpio_deep_sleep_hold_en()) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_dis, gpio_deep_sleep_hold_dis()) \
|
||||
YV(interrupts, gpio_install_isr_service, n0 = gpio_install_isr_service(n0)) \
|
||||
YV(interrupts, gpio_uninstall_isr_service, gpio_uninstall_isr_service()) \
|
||||
YV(interrupts, gpio_isr_handler_add, n0 = GpioIsrHandlerAdd(n2, n1, n0); NIPn(2)) \
|
||||
YV(interrupts, gpio_isr_handler_remove, n0 = gpio_isr_handler_remove((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_drive_capability, n0 = gpio_set_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t) n0); NIP) \
|
||||
YV(interrupts, gpio_get_drive_capability, n0 = gpio_get_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t *) a0); NIP) \
|
||||
YV(interrupts, esp_intr_alloc, n0 = EspIntrAlloc(n4, n3, n2, n1, a0); NIPn(4)) \
|
||||
YV(interrupts, esp_intr_free, n0 = esp_intr_free((intr_handle_t) n0)) \
|
||||
YV(timers, timer_isr_register, n0 = TimerIsrRegister(n5, n4, n3, n2, n1, a0); NIPn(5))
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_RMT_SUPPORT
|
||||
# define OPTIONAL_RMT_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "driver/rmt.h"
|
||||
# endif
|
||||
# define OPTIONAL_RMT_SUPPORT \
|
||||
YV(rmt, rmt_set_clk_div, n0 = rmt_set_clk_div((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_clk_div, n0 = rmt_get_clk_div((rmt_channel_t) n1, b0); NIP) \
|
||||
YV(rmt, rmt_set_rx_idle_thresh, n0 = rmt_set_rx_idle_thresh((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_rx_idle_thresh, \
|
||||
n0 = rmt_get_rx_idle_thresh((rmt_channel_t) n1, (uint16_t *) a0); NIP) \
|
||||
YV(rmt, rmt_set_mem_block_num, n0 = rmt_set_mem_block_num((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_mem_block_num, n0 = rmt_get_mem_block_num((rmt_channel_t) n1, b0); NIP) \
|
||||
YV(rmt, rmt_set_tx_carrier, n0 = rmt_set_tx_carrier((rmt_channel_t) n4, n3, n2, n1, \
|
||||
(rmt_carrier_level_t) n0); NIPn(4)) \
|
||||
YV(rmt, rmt_set_mem_pd, n0 = rmt_set_mem_pd((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_mem_pd, n0 = rmt_get_mem_pd((rmt_channel_t) n1, (bool *) a0); NIP) \
|
||||
YV(rmt, rmt_tx_start, n0 = rmt_tx_start((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_tx_stop, n0 = rmt_tx_stop((rmt_channel_t) n0)) \
|
||||
YV(rmt, rmt_rx_start, n0 = rmt_rx_start((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_rx_stop, n0 = rmt_rx_stop((rmt_channel_t) n0)) \
|
||||
YV(rmt, rmt_tx_memory_reset, n0 = rmt_tx_memory_reset((rmt_channel_t) n0)) \
|
||||
YV(rmt, rmt_rx_memory_reset, n0 = rmt_rx_memory_reset((rmt_channel_t) n0)) \
|
||||
YV(rmt, rmt_set_memory_owner, n0 = rmt_set_memory_owner((rmt_channel_t) n1, (rmt_mem_owner_t) n0); NIP) \
|
||||
YV(rmt, rmt_get_memory_owner, n0 = rmt_get_memory_owner((rmt_channel_t) n1, (rmt_mem_owner_t *) a0); NIP) \
|
||||
YV(rmt, rmt_set_tx_loop_mode, n0 = rmt_set_tx_loop_mode((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_tx_loop_mode, n0 = rmt_get_tx_loop_mode((rmt_channel_t) n1, (bool *) a0); NIP) \
|
||||
YV(rmt, rmt_set_rx_filter, n0 = rmt_set_rx_filter((rmt_channel_t) n2, n1, n0); NIPn(2)) \
|
||||
YV(rmt, rmt_set_source_clk, n0 = rmt_set_source_clk((rmt_channel_t) n1, (rmt_source_clk_t) n0); NIP) \
|
||||
YV(rmt, rmt_get_source_clk, n0 = rmt_get_source_clk((rmt_channel_t) n1, (rmt_source_clk_t * ) a0); NIP) \
|
||||
YV(rmt, rmt_set_idle_level, n0 = rmt_set_idle_level((rmt_channel_t) n2, n1, \
|
||||
(rmt_idle_level_t) n0); NIPn(2)) \
|
||||
YV(rmt, rmt_get_idle_level, n0 = rmt_get_idle_level((rmt_channel_t) n2, \
|
||||
(bool *) a1, (rmt_idle_level_t *) a0); NIPn(2)) \
|
||||
YV(rmt, rmt_get_status, n0 = rmt_get_status((rmt_channel_t) n1, (uint32_t *) a0); NIP) \
|
||||
YV(rmt, rmt_set_rx_intr_en, n0 = rmt_set_rx_intr_en((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_set_err_intr_en, n0 = rmt_set_err_intr_en((rmt_channel_t) n1, (rmt_mode_t) n0); NIP) \
|
||||
YV(rmt, rmt_set_tx_intr_en, n0 = rmt_set_tx_intr_en((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_set_tx_thr_intr_en, n0 = rmt_set_tx_thr_intr_en((rmt_channel_t) n2, n1, n0); NIPn(2)) \
|
||||
YV(rmt, rmt_set_gpio, n0 = rmt_set_gpio((rmt_channel_t) n3, (rmt_mode_t) n2, (gpio_num_t) n1, n0); NIPn(3)) \
|
||||
YV(rmt, rmt_config, n0 = rmt_config((const rmt_config_t *) a0)) \
|
||||
YV(rmt, rmt_isr_register, n0 = rmt_isr_register((void (*)(void*)) a3, a2, n1, \
|
||||
(rmt_isr_handle_t *) a0); NIPn(3)) \
|
||||
YV(rmt, rmt_isr_deregister, n0 = rmt_isr_deregister((rmt_isr_handle_t) n0)) \
|
||||
YV(rmt, rmt_fill_tx_items, n0 = rmt_fill_tx_items((rmt_channel_t) n3, \
|
||||
(rmt_item32_t *) a2, n1, n0); NIPn(3)) \
|
||||
YV(rmt, rmt_driver_install, n0 = rmt_driver_install((rmt_channel_t) n2, n1, n0); NIPn(2)) \
|
||||
YV(rmt, rmt_driver_uinstall, n0 = rmt_driver_uninstall((rmt_channel_t) n0)) \
|
||||
YV(rmt, rmt_get_channel_status, n0 = rmt_get_channel_status((rmt_channel_status_result_t *) a0)) \
|
||||
YV(rmt, rmt_get_counter_clock, n0 = rmt_get_counter_clock((rmt_channel_t) n1, (uint32_t *) a0); NIP) \
|
||||
YV(rmt, rmt_write_items, n0 = rmt_write_items((rmt_channel_t) n3, (rmt_item32_t *) a2, n1, n0); NIPn(3)) \
|
||||
YV(rmt, rmt_wait_tx_done, n0 = rmt_wait_tx_done((rmt_channel_t) n1, n0); NIP) \
|
||||
YV(rmt, rmt_get_ringbuf_handle, n0 = rmt_get_ringbuf_handle((rmt_channel_t) n1, (RingbufHandle_t *) a0); NIP) \
|
||||
YV(rmt, rmt_translator_init, n0 = rmt_translator_init((rmt_channel_t) n1, (sample_to_rmt_t) n0); NIP) \
|
||||
YV(rmt, rmt_translator_set_context, n0 = rmt_translator_set_context((rmt_channel_t) n1, a0); NIP) \
|
||||
YV(rmt, rmt_translator_get_context, n0 = rmt_translator_get_context((const size_t *) a1, (void **) a0); NIP) \
|
||||
YV(rmt, rmt_write_sample, n0 = rmt_write_sample((rmt_channel_t) n3, b2, n1, n0); NIPn(3))
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_CAMERA_SUPPORT
|
||||
# define OPTIONAL_CAMERA_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "esp_camera.h"
|
||||
# endif
|
||||
# define OPTIONAL_CAMERA_SUPPORT \
|
||||
YV(camera, esp_camera_init, n0 = esp_camera_init((camera_config_t *) a0)) \
|
||||
YV(camera, esp_camera_deinit, PUSH esp_camera_deinit()) \
|
||||
YV(camera, esp_camera_fb_get, PUSH esp_camera_fb_get()) \
|
||||
YV(camera, esp_camera_fb_return, esp_camera_fb_return((camera_fb_t *) a0); DROP) \
|
||||
YV(camera, esp_camera_sensor_get, PUSH esp_camera_sensor_get())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SOCKETS_SUPPORT
|
||||
# define OPTIONAL_SOCKETS_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include <errno.h>
|
||||
# include <sys/select.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/un.h>
|
||||
# include <sys/poll.h>
|
||||
# endif
|
||||
# define OPTIONAL_SOCKETS_SUPPORT \
|
||||
YV(sockets, socket, n0 = socket(n2, n1, n0); NIPn(2)) \
|
||||
YV(sockets, setsockopt, n0 = setsockopt(n4, n3, n2, a1, n0); NIPn(4)) \
|
||||
YV(sockets, bind, n0 = bind(n2, (struct sockaddr *) a1, n0); NIPn(2)) \
|
||||
YV(sockets, listen, n0 = listen(n1, n0); NIP) \
|
||||
YV(sockets, connect, n0 = connect(n2, (struct sockaddr *) a1, n0); NIPn(2)) \
|
||||
YV(sockets, sockaccept, n0 = accept(n2, (struct sockaddr *) a1, (socklen_t *) a0); NIPn(2)) \
|
||||
YV(sockets, select, n0 = select(n4, (fd_set *) a3, (fd_set *) a2, (fd_set *) a1, (struct timeval *) a0); NIPn(4)) \
|
||||
YV(sockets, poll, n0 = poll((struct pollfd *) a2, (nfds_t) n1, n0); NIPn(2)) \
|
||||
XV(sockets, "errno", ERRNO, PUSH errno)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SD_SUPPORT
|
||||
# define OPTIONAL_SD_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "SD.h"
|
||||
# endif
|
||||
# define OPTIONAL_SD_SUPPORT \
|
||||
XV(SD, "SD.begin", SD_BEGIN, PUSH SD.begin()) \
|
||||
XV(SD, "SD.beginFull", SD_BEGIN_FULL, \
|
||||
tos = SD.begin(n5, *(SPIClass*)a4, n3, c2, n1, n0); NIPn(5)) \
|
||||
XV(SD, "SD.beginDefaults", SD_BEGIN_DEFAULTS, \
|
||||
PUSH SS; PUSH &SPI; PUSH 4000000; PUSH "/sd"; PUSH 5; PUSH false) \
|
||||
XV(SD, "SD.end", SD_END, SD.end()) \
|
||||
XV(SD, "SD.cardType", SD_CARD_TYPE, PUSH SD.cardType()) \
|
||||
XV(SD, "SD.totalBytes", SD_TOTAL_BYTES, PUSH SD.totalBytes()) \
|
||||
XV(SD, "SD.usedBytes", SD_USED_BYTES, PUSH SD.usedBytes())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SD_MMC_SUPPORT
|
||||
# define OPTIONAL_SD_MMC_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "SD_MMC.h"
|
||||
# endif
|
||||
# define OPTIONAL_SD_MMC_SUPPORT \
|
||||
XV(SD_MMC, "SD_MMC.begin", SD_MMC_BEGIN, PUSH SD_MMC.begin()) \
|
||||
XV(SD_MMC, "SD_MMC.beginFull", SD_MMC_BEGIN_FULL, tos = SD_MMC.begin(c2, n1, n0); NIPn(2)) \
|
||||
XV(SD_MMC, "SD_MMC.beginDefaults", SD_MMC_BEGIN_DEFAULTS, \
|
||||
PUSH "/sdcard"; PUSH false; PUSH false) \
|
||||
XV(SD_MMC, "SD_MMC.end", SD_MMC_END, SD_MMC.end()) \
|
||||
XV(SD_MMC, "SD_MMC.cardType", SD_MMC_CARD_TYPE, PUSH SD_MMC.cardType()) \
|
||||
XV(SD_MMC, "SD_MMC.totalBytes", SD_MMC_TOTAL_BYTES, PUSH SD_MMC.totalBytes()) \
|
||||
XV(SD_MMC, "SD_MMC.usedBytes", SD_MMC_USED_BYTES, PUSH SD_MMC.usedBytes())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_I2C_SUPPORT
|
||||
# define OPTIONAL_I2C_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include <Wire.h>
|
||||
# endif
|
||||
# define OPTIONAL_I2C_SUPPORT \
|
||||
XV(Wire, "Wire.begin", WIRE_BEGIN, n0 = Wire.begin(n1, n0); NIP) \
|
||||
XV(Wire, "Wire.setClock", WIRE_SET_CLOCK, Wire.setClock(n0); DROP) \
|
||||
XV(Wire, "Wire.getClock", WIRE_GET_CLOCK, PUSH Wire.getClock()) \
|
||||
XV(Wire, "Wire.setTimeout", WIRE_SET_TIMEOUT, Wire.setTimeout(n0); DROP) \
|
||||
XV(Wire, "Wire.getTimeout", WIRE_GET_TIMEOUT, PUSH Wire.getTimeout()) \
|
||||
XV(Wire, "Wire.beginTransmission", WIRE_BEGIN_TRANSMISSION, Wire.beginTransmission(n0); DROP) \
|
||||
XV(Wire, "Wire.endTransmission", WIRE_END_TRANSMISSION, SET Wire.endTransmission(n0)) \
|
||||
XV(Wire, "Wire.requestFrom", WIRE_REQUEST_FROM, n0 = Wire.requestFrom(n2, n1, n0); NIPn(2)) \
|
||||
XV(Wire, "Wire.write", WIRE_WRITE, n0 = Wire.write(b1, n0); NIP) \
|
||||
XV(Wire, "Wire.available", WIRE_AVAILABLE, PUSH Wire.available()) \
|
||||
XV(Wire, "Wire.read", WIRE_READ, PUSH Wire.read()) \
|
||||
XV(Wire, "Wire.peek", WIRE_PEEK, PUSH Wire.peek()) \
|
||||
XV(Wire, "Wire.flush", WIRE_FLUSH, Wire.flush())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SERIAL_BLUETOOTH_SUPPORT
|
||||
# define OPTIONAL_SERIAL_BLUETOOTH_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "esp_bt_device.h"
|
||||
# include "BluetoothSerial.h"
|
||||
# define bt0 ((BluetoothSerial *) a0)
|
||||
# endif
|
||||
# define OPTIONAL_SERIAL_BLUETOOTH_SUPPORT \
|
||||
XV(bluetooth, "SerialBT.new", SERIALBT_NEW, PUSH new BluetoothSerial()) \
|
||||
XV(bluetooth, "SerialBT.delete", SERIALBT_DELETE, delete bt0; DROP) \
|
||||
XV(bluetooth, "SerialBT.begin", SERIALBT_BEGIN, n0 = bt0->begin(c2, n1); NIPn(2)) \
|
||||
XV(bluetooth, "SerialBT.end", SERIALBT_END, bt0->end(); DROP) \
|
||||
XV(bluetooth, "SerialBT.available", SERIALBT_AVAILABLE, n0 = bt0->available()) \
|
||||
XV(bluetooth, "SerialBT.readBytes", SERIALBT_READ_BYTES, n0 = bt0->readBytes(b2, n1); NIPn(2)) \
|
||||
XV(bluetooth, "SerialBT.write", SERIALBT_WRITE, n0 = bt0->write(b2, n1); NIPn(2)) \
|
||||
XV(bluetooth, "SerialBT.flush", SERIALBT_FLUSH, bt0->flush(); DROP) \
|
||||
XV(bluetooth, "SerialBT.hasClient", SERIALBT_HAS_CLIENT, n0 = bt0->hasClient()) \
|
||||
XV(bluetooth, "SerialBT.enableSSP", SERIALBT_ENABLE_SSP, bt0->enableSSP(); DROP) \
|
||||
XV(bluetooth, "SerialBT.setPin", SERIALBT_SET_PIN, n0 = bt0->setPin(c1); NIP) \
|
||||
XV(bluetooth, "SerialBT.unpairDevice", SERIALBT_UNPAIR_DEVICE, \
|
||||
n0 = bt0->unpairDevice(b1); NIP) \
|
||||
XV(bluetooth, "SerialBT.connect", SERIALBT_CONNECT, n0 = bt0->connect(c1); NIP) \
|
||||
XV(bluetooth, "SerialBT.connectAddr", SERIALBT_CONNECT_ADDR, n0 = bt0->connect(b1); NIP) \
|
||||
XV(bluetooth, "SerialBT.disconnect", SERIALBT_DISCONNECT, n0 = bt0->disconnect()) \
|
||||
XV(bluetooth, "SerialBT.connected", SERIALBT_CONNECTED, n0 = bt0->connected(n1); NIP) \
|
||||
XV(bluetooth, "SerialBT.isReady", SERIALBT_IS_READY, n0 = bt0->isReady(n2, n1); NIPn(2)) \
|
||||
/* Bluetooth */ \
|
||||
YV(bluetooth, esp_bt_dev_get_address, PUSH esp_bt_dev_get_address())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_WIFI_SUPPORT
|
||||
# define OPTIONAL_WIFI_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include <WiFi.h>
|
||||
# include <WiFiClient.h>
|
||||
|
||||
static IPAddress ToIP(cell_t ip) {
|
||||
return IPAddress(ip & 0xff, ((ip >> 8) & 0xff), ((ip >> 16) & 0xff), ((ip >> 24) & 0xff));
|
||||
}
|
||||
|
||||
static cell_t FromIP(IPAddress ip) {
|
||||
cell_t ret = 0;
|
||||
ret = (ret << 8) | ip[3];
|
||||
ret = (ret << 8) | ip[2];
|
||||
ret = (ret << 8) | ip[1];
|
||||
ret = (ret << 8) | ip[0];
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
# define OPTIONAL_WIFI_SUPPORT \
|
||||
/* WiFi */ \
|
||||
XV(WiFi, "WiFi.config", WIFI_CONFIG, \
|
||||
WiFi.config(ToIP(n3), ToIP(n2), ToIP(n1), ToIP(n0)); DROPn(4)) \
|
||||
XV(WiFi, "WiFi.begin", WIFI_BEGIN, WiFi.begin(c1, c0); DROPn(2)) \
|
||||
XV(WiFi, "WiFi.disconnect", WIFI_DISCONNECT, WiFi.disconnect()) \
|
||||
XV(WiFi, "WiFi.status", WIFI_STATUS, PUSH WiFi.status()) \
|
||||
XV(WiFi, "WiFi.macAddress", WIFI_MAC_ADDRESS, WiFi.macAddress(b0); DROP) \
|
||||
XV(WiFi, "WiFi.localIP", WIFI_LOCAL_IPS, PUSH FromIP(WiFi.localIP())) \
|
||||
XV(WiFi, "WiFi.mode", WIFI_MODE, WiFi.mode((wifi_mode_t) n0); DROP) \
|
||||
XV(WiFi, "WiFi.setTxPower", WIFI_SET_TX_POWER, WiFi.setTxPower((wifi_power_t) n0); DROP) \
|
||||
XV(WiFi, "WiFi.getTxPower", WIFI_GET_TX_POWER, PUSH WiFi.getTxPower())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_MDNS_SUPPORT
|
||||
# define OPTIONAL_MDNS_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include <ESPmDNS.h>
|
||||
# endif
|
||||
# define OPTIONAL_MDNS_SUPPORT \
|
||||
/* mDNS */ \
|
||||
X("MDNS.begin", MDNS_BEGIN, n0 = MDNS.begin(c0))
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_OLED_SUPPORT
|
||||
# define OPTIONAL_OLED_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include <Adafruit_GFX.h>
|
||||
# include <Adafruit_SSD1306.h>
|
||||
static Adafruit_SSD1306 *oled_display = 0;
|
||||
# endif
|
||||
# define OPTIONAL_OLED_SUPPORT \
|
||||
YV(oled, OledAddr, PUSH &oled_display) \
|
||||
YV(oled, OledNew, oled_display = new Adafruit_SSD1306(n2, n1, &Wire, n0); DROPn(3)) \
|
||||
YV(oled, OledDelete, delete oled_display) \
|
||||
YV(oled, OledBegin, n0 = oled_display->begin(n1, n0); NIP) \
|
||||
YV(oled, OledHOME, oled_display->setCursor(0,0); DROP) \
|
||||
YV(oled, OledCLS, oled_display->clearDisplay()) \
|
||||
YV(oled, OledTextc, oled_display->setTextColor(n0); DROP) \
|
||||
YV(oled, OledPrintln, oled_display->println(c0); DROP) \
|
||||
YV(oled, OledNumln, oled_display->println(n0); DROP) \
|
||||
YV(oled, OledNum, oled_display->print(n0); DROP) \
|
||||
YV(oled, OledDisplay, oled_display->display()) \
|
||||
YV(oled, OledPrint, oled_display->write(c0); DROP) \
|
||||
YV(oled, OledInvert, oled_display->invertDisplay(n0); DROP) \
|
||||
YV(oled, OledTextsize, oled_display->setTextSize(n0); DROP) \
|
||||
YV(oled, OledSetCursor, oled_display->setCursor(n1,n0); DROPn(2)) \
|
||||
YV(oled, OledPixel, oled_display->drawPixel(n2, n1, n0); DROPn(2)) \
|
||||
YV(oled, OledDrawL, oled_display->drawLine(n4, n3, n2, n1, n0); DROPn(4)) \
|
||||
YV(oled, OledCirc, oled_display->drawCircle(n3,n2, n1, n0); DROPn(3)) \
|
||||
YV(oled, OledCircF, oled_display->fillCircle(n3, n2, n1, n0); DROPn(3)) \
|
||||
YV(oled, OledRect, oled_display->drawRect(n4, n3, n2, n1, n0); DROPn(4)) \
|
||||
YV(oled, OledRectF, oled_display->fillRect(n4, n3, n2, n1, n0); DROPn(3)) \
|
||||
YV(oled, OledRectR, oled_display->drawRoundRect(n5, n4, n3, n2, n1, n0); DROPn(5)) \
|
||||
YV(oled, OledRectRF, oled_display->fillRoundRect(n5, n4, n3, n2, n1, n0 ); DROPn(5))
|
||||
#endif
|
||||
59
esp32/camera.fs
Normal file
59
esp32/camera.fs
Normal file
@ -0,0 +1,59 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
internals definitions
|
||||
transfer camera-builtins
|
||||
forth definitions
|
||||
|
||||
( Lazy loaded camera handling for ESP32-CAM )
|
||||
: camera r|
|
||||
|
||||
vocabulary camera camera definitions
|
||||
also internals
|
||||
transfer camera-builtins
|
||||
|
||||
0 constant PIXFORMAT_RGB565
|
||||
1 constant PIXFORMAT_YUV422
|
||||
2 constant PIXFORMAT_GRAYSCALE
|
||||
3 constant PIXFORMAT_JPEG
|
||||
4 constant PIXFORMAT_RGB888
|
||||
5 constant PIXFORMAT_RAW
|
||||
6 constant PIXFORMAT_RGB444
|
||||
7 constant PIXFORMAT_RGB555
|
||||
|
||||
5 constant FRAMESIZE_QVGA
|
||||
8 constant FRAMESIZE_VGA
|
||||
|
||||
( See https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h )
|
||||
( Settings for AI_THINKER )
|
||||
create camera-config
|
||||
32 , ( pin_pwdn ) -1 , ( pin_reset ) 0 , ( pin_xclk )
|
||||
26 , ( pin_sscb_sda ) 27 , ( pin_sscb_scl )
|
||||
35 , 34 , 39 , 36 , 21 , 19 , 18 , 5 , ( pin_d7 - pin_d0 )
|
||||
25 , ( pin_vsync ) 23 , ( pin_href ) 22 , ( pin_pclk )
|
||||
20000000 , ( xclk_freq_hz )
|
||||
0 , ( ledc_timer ) 0 , ( ledc_channel )
|
||||
here
|
||||
PIXFORMAT_JPEG , ( pixel_format )
|
||||
FRAMESIZE_VGA , ( frame_size ) 12 , ( jpeg_quality 0-63 low good )
|
||||
here
|
||||
1 , ( fb_count )
|
||||
constant camera-fb-count
|
||||
constant camera-format
|
||||
|
||||
forth definitions
|
||||
camera
|
||||
| evaluate ;
|
||||
|
||||
[THEN]
|
||||
87
esp32/camera_server.fs
Normal file
87
esp32/camera_server.fs
Normal file
@ -0,0 +1,87 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Lazy loaded Camera Server )
|
||||
: camera-server r~
|
||||
|
||||
camera httpd
|
||||
vocabulary camera-server camera-server definitions
|
||||
also camera also httpd
|
||||
|
||||
r|
|
||||
<!DOCTYPE html>
|
||||
<body>
|
||||
<img id="pic">
|
||||
<script>
|
||||
var pic = document.getElementById('pic');
|
||||
function httpPost(url, callback) {
|
||||
var r = new XMLHttpRequest();
|
||||
r.responseType = 'blob';
|
||||
r.onreadystatechange = function() {
|
||||
if (this.readyState == XMLHttpRequest.DONE) {
|
||||
if (this.status === 200) {
|
||||
callback(this.response);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
r.open('POST', url);
|
||||
r.send();
|
||||
}
|
||||
function Frame() {
|
||||
httpPost('./image', function(r) {
|
||||
if (r !== null) {
|
||||
try {
|
||||
pic.src = URL.createObjectURL(r);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
setTimeout(Frame, 30);
|
||||
});
|
||||
}
|
||||
Frame();
|
||||
</script>
|
||||
| constant index-html# constant index-html
|
||||
|
||||
: handle-index
|
||||
s" text/html" ok-response
|
||||
index-html index-html# send
|
||||
;
|
||||
|
||||
: handle-image
|
||||
s" image/jpeg" ok-response
|
||||
esp_camera_fb_get dup dup @ swap cell+ @ send
|
||||
esp_camera_fb_return
|
||||
;
|
||||
|
||||
: handle1
|
||||
handleClient if
|
||||
s" /" path str= if handle-index exit then
|
||||
s" /image" path str= if handle-image exit then
|
||||
notfound-response
|
||||
then
|
||||
;
|
||||
|
||||
: do-serve begin ['] handle1 catch drop pause again ;
|
||||
|
||||
: server ( port -- )
|
||||
server
|
||||
camera-config esp_camera_init throw
|
||||
do-serve
|
||||
;
|
||||
|
||||
only forth definitions
|
||||
camera-server
|
||||
~ evaluate ;
|
||||
27
esp32/main.cpp
Normal file
27
esp32/main.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
void setup() {
|
||||
cell_t fh = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
cell_t hc = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
|
||||
if (fh - hc < MINIMUM_FREE_SYSTEM_HEAP) {
|
||||
hc = fh - MINIMUM_FREE_SYSTEM_HEAP;
|
||||
}
|
||||
cell_t *heap = (cell_t *) malloc(hc);
|
||||
forth_init(0, 0, heap, hc, boot, sizeof(boot));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
g_sys.rp = forth_run(g_sys.rp);
|
||||
}
|
||||
76
esp32/options.h
Normal file
76
esp32/options.h
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2022 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#define STACK_CELLS 512
|
||||
#define INTERRUPT_STACK_CELLS 64
|
||||
#define MINIMUM_FREE_SYSTEM_HEAP (64 * 1024)
|
||||
|
||||
// Default on several options.
|
||||
#define ENABLE_SPIFFS_SUPPORT
|
||||
#define ENABLE_WIFI_SUPPORT
|
||||
#define ENABLE_MDNS_SUPPORT
|
||||
#define ENABLE_I2C_SUPPORT
|
||||
#define ENABLE_SOCKETS_SUPPORT
|
||||
#define ENABLE_FREERTOS_SUPPORT
|
||||
#define ENABLE_INTERRUPTS_SUPPORT
|
||||
#define ENABLE_LEDC_SUPPORT
|
||||
#define ENABLE_SD_SUPPORT
|
||||
#define ENABLE_SPI_FLASH_SUPPORT
|
||||
|
||||
// SD_MMC does not work on ESP32-S2 / ESP32-C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
# define ENABLE_SD_MMC_SUPPORT
|
||||
#endif
|
||||
|
||||
// ESP32-C3 has no DACs.
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
# define ENABLE_DAC_SUPPORT
|
||||
#endif
|
||||
|
||||
// RMT support designed around v2.0.1 toolchain.
|
||||
// While ESP32 also has RMT, for now only include for
|
||||
// ESP32-S2 and ESP32-C3.
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || \
|
||||
defined(CONFIG_IDF_TARGET_ESP32C3) || \
|
||||
defined(SIM_PRINT_ONLY)
|
||||
# define ENABLE_RMT_SUPPORT
|
||||
#endif
|
||||
|
||||
// Uncomment this #define for OLED Support.
|
||||
// You will need to install these libraries from the Library Manager:
|
||||
// Adafruit SSD1306
|
||||
// Adafruit GFX Library
|
||||
// Adafruit BusIO
|
||||
//#define ENABLE_OLED_SUPPORT
|
||||
|
||||
// For now assume only boards with PSRAM should enable
|
||||
// camera support and BluetoothSerial.
|
||||
// ESP32-CAM always have PSRAM, but so do WROVER boards,
|
||||
// so this isn't an ideal indicator.
|
||||
// Some boards (e.g. ESP32-S2-WROVER) don't seem to have
|
||||
// built the serial library, so check if its enabled as well.
|
||||
#if defined(BOARD_HAS_PSRAM) || defined(SIM_PRINT_ONLY)
|
||||
# define ENABLE_CAMERA_SUPPORT
|
||||
# if (defined(CONFIG_BT_ENABLED) && \
|
||||
defined(CONFIG_BLUEDROID_ENABLED)) || \
|
||||
defined(SIM_PRINT_ONLY)
|
||||
# define ENABLE_SERIAL_BLUETOOTH_SUPPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define VOCABULARY_LIST \
|
||||
V(forth) V(internals) \
|
||||
V(rtos) V(SPIFFS) V(serial) V(SD) V(SD_MMC) V(ESP) \
|
||||
V(ledc) V(Wire) V(WiFi) V(bluetooth) V(sockets) V(oled) \
|
||||
V(rmt) V(interrupts) V(spi_flash) V(camera) V(timers)
|
||||
78
esp32/platform.fs
Normal file
78
esp32/platform.fs
Normal file
@ -0,0 +1,78 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Add a yielding task so pause yields )
|
||||
internals definitions
|
||||
: yield-step raw-yield yield ;
|
||||
' yield-step 100 100 task yield-task
|
||||
yield-task start-task
|
||||
forth definitions
|
||||
|
||||
( Set up Basic I/O )
|
||||
internals definitions also serial
|
||||
: esp32-bye 0 terminate ;
|
||||
: serial-type ( a n -- ) Serial.write drop ;
|
||||
: serial-key ( -- n )
|
||||
begin pause Serial.available until 0 >r rp@ 1 Serial.readBytes drop r> ;
|
||||
: serial-key? ( -- n ) Serial.available ;
|
||||
also forth definitions
|
||||
: default-type serial-type ;
|
||||
: default-key serial-key ;
|
||||
: default-key? serial-key? ;
|
||||
' default-type is type
|
||||
' default-key is key
|
||||
' default-key? is key?
|
||||
' esp32-bye is bye
|
||||
only forth definitions
|
||||
|
||||
also ledc also serial also SPIFFS
|
||||
|
||||
( Map Arduino / ESP32 things to shorter names. )
|
||||
: pin ( n pin# -- ) swap digitalWrite ;
|
||||
: adc ( n -- n ) analogRead ;
|
||||
: duty ( n n -- ) 255 min 8191 255 */ ledcWrite ;
|
||||
: freq ( n n -- ) 1000 * 13 ledcSetup drop ;
|
||||
: tone ( n n -- ) 1000 * ledcWriteTone drop ;
|
||||
|
||||
( Utilities )
|
||||
: page 30 for cr next ;
|
||||
|
||||
( Basic Ardiuno Constants )
|
||||
0 constant LOW
|
||||
1 constant HIGH
|
||||
1 constant INPUT
|
||||
2 constant OUTPUT
|
||||
2 constant LED
|
||||
|
||||
( Startup Setup )
|
||||
-1 echo !
|
||||
115200 Serial.begin
|
||||
100 ms
|
||||
-1 z" /spiffs" 10 SPIFFS.begin drop
|
||||
led OUTPUT pinMode
|
||||
high led pin
|
||||
|
||||
internals definitions also ESP
|
||||
: esp32-stats
|
||||
getChipModel z>s type ." "
|
||||
getCpuFreqMHz . ." MHz "
|
||||
getChipCores . ." cores "
|
||||
getFlashChipSize . ." bytes flash" cr
|
||||
." System Heap: " getFreeHeap getHeapSize free. cr
|
||||
." " getMaxAllocHeap . ." bytes max contiguous" cr ;
|
||||
' esp32-stats internals boot-prompt !
|
||||
only forth definitions
|
||||
|
||||
( Setup entry )
|
||||
internals : ok ." ESP32forth" raw-ok ; forth
|
||||
38
esp32/print-builtins.cpp
Normal file
38
esp32/print-builtins.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2022 Bradley D. Nelson
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define SIM_PRINT_ONLY
|
||||
#define ENABLE_OLED_SUPPORT
|
||||
#include "esp32/options.h"
|
||||
#define FLOATING_POINT_LIST
|
||||
#define USER_WORDS
|
||||
#include "builtins.h"
|
||||
|
||||
#define YV(flags, op, code) XV(flags, #op, op, code)
|
||||
#define X(name, op, code) XV(forth, name, op, code)
|
||||
#define Y(op, code) XV(forth, #op, op, code)
|
||||
|
||||
int main() {
|
||||
printf("#define PLATFORM_SIMULATED_OPCODE_LIST \\\n");
|
||||
#define XV(flags, str, name, code) \
|
||||
printf(" XV(%s, \"%s\", %s, DUP; sp = simulated(sp, STR_%s); DROP) \\\n", #flags, str, #name, #name);
|
||||
PLATFORM_OPCODE_LIST
|
||||
#undef XV
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
22
esp32/registers.fs
Normal file
22
esp32/registers.fs
Normal file
@ -0,0 +1,22 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
vocabulary registers registers definitions
|
||||
|
||||
( Tools for working with bit masks )
|
||||
: m! ( val shift mask a -- )
|
||||
dup >r @ over invert and >r >r lshift r> and r> or r> ! ;
|
||||
: m@ ( shift mask a -- val ) @ and swap rshift ;
|
||||
|
||||
only forth definitions
|
||||
160
esp32/sim_main.cpp
Normal file
160
esp32/sim_main.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright 2022 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "esp32/options.h"
|
||||
#include "common/opcodes.h"
|
||||
#include "common/extra_opcodes.h"
|
||||
#include "common/floats.h"
|
||||
#include "common/calling.h"
|
||||
|
||||
#define SIM_HEAP_SIZE (100 * 1024 + 1024 * 1024)
|
||||
|
||||
static cell_t *simulated(cell_t *sp, const char *op);
|
||||
|
||||
#define PLATFORM_OPCODE_LIST \
|
||||
PLATFORM_SIMULATED_OPCODE_LIST \
|
||||
FLOATING_POINT_LIST
|
||||
|
||||
#include "gen/esp32_sim_opcodes.h"
|
||||
|
||||
#define XV(flags, str, name, code) static const char *STR_ ## name = str;
|
||||
PLATFORM_SIMULATED_OPCODE_LIST
|
||||
#undef XV
|
||||
|
||||
#define MALLOC_CAP_INTERNAL 0
|
||||
#define heap_caps_get_largest_free_block(x) SIM_HEAP_SIZE
|
||||
#define heap_caps_get_free_size(x) SIM_HEAP_SIZE
|
||||
|
||||
#include "common/core.h"
|
||||
#include "common/interp.h"
|
||||
#include "gen/esp32_boot.h"
|
||||
#include "esp32/main.cpp"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static cell_t *simulated(cell_t *sp, const char *op) {
|
||||
if (op == STR_MALLOC) {
|
||||
*sp = (cell_t) malloc(*sp);
|
||||
return sp;
|
||||
} else if (op == STR_SYSFREE) {
|
||||
free((void*) *sp--);
|
||||
return sp;
|
||||
} else if (op == STR_SERIAL_BEGIN) {
|
||||
--sp;
|
||||
return sp;
|
||||
} else if (op == STR_SERIAL_READ_BYTES) {
|
||||
cell_t len = *sp--;
|
||||
*sp = read(0, (void *) *sp, len);
|
||||
return sp;
|
||||
} else if (op == STR_SERIAL_WRITE) {
|
||||
cell_t len = *sp--;
|
||||
*sp = write(1, (void *) *sp, len);
|
||||
return sp;
|
||||
} else if (op == STR_MS_TICKS) {
|
||||
struct timespec tm;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tm);
|
||||
*++sp = tm.tv_sec * 1000 + tm.tv_nsec / 1000000;
|
||||
return sp;
|
||||
} else if (op == STR_RAW_YIELD) {
|
||||
return sp;
|
||||
} else if (op == STR_SPIFFS_BEGIN) {
|
||||
sp -= 2;
|
||||
*sp = 0;
|
||||
return sp;
|
||||
} else if (op == STR_pinMode) {
|
||||
sp -= 2;
|
||||
return sp;
|
||||
} else if (op == STR_digitalWrite) {
|
||||
sp -= 2;
|
||||
return sp;
|
||||
} else if (op == STR_gpio_install_isr_service) {
|
||||
*sp = 0;
|
||||
return sp;
|
||||
} else if (op == STR_SERIAL_AVAILABLE) {
|
||||
*++sp = 1;
|
||||
return sp;
|
||||
} else if (op == STR_TERMINATE) {
|
||||
exit(*sp--);
|
||||
return sp;
|
||||
} else if (op == STR_R_O) {
|
||||
*++sp = O_RDONLY;
|
||||
return sp;
|
||||
} else if (op == STR_OPEN_FILE) {
|
||||
cell_t mode = *sp--;
|
||||
cell_t len = *sp--;
|
||||
char filename[1024];
|
||||
memcpy(filename, (void *) *sp, len); filename[len] = 0;
|
||||
cell_t ret = open(filename, mode, 0777);
|
||||
*sp = ret;
|
||||
*++sp = ret < 0 ? errno : 0;
|
||||
return sp;
|
||||
} else if (op == STR_FILE_SIZE) {
|
||||
struct stat st;
|
||||
cell_t w = fstat(*sp, &st);
|
||||
*sp = (cell_t) st.st_size;
|
||||
*++sp = w < 0 ? errno : 0;
|
||||
return sp;
|
||||
} else if (op == STR_READ_FILE) {
|
||||
cell_t fd = *sp--;
|
||||
cell_t len = *sp--;
|
||||
cell_t ret = read(fd, (void *) *sp, len);
|
||||
*sp = ret;
|
||||
*++sp = ret < 0 ? errno : 0;
|
||||
return sp;
|
||||
} else if (op == STR_CLOSE_FILE) {
|
||||
cell_t ret = close(*sp);
|
||||
*sp = ret ? errno : 0;
|
||||
return sp;
|
||||
} else if (op == STR_getChipModel) {
|
||||
*++sp = (cell_t) "FAKE-ESP32";
|
||||
return sp;
|
||||
} else if (op == STR_getCpuFreqMHz) {
|
||||
*++sp = 240;
|
||||
return sp;
|
||||
} else if (op == STR_getChipCores) {
|
||||
*++sp = 2;
|
||||
return sp;
|
||||
} else if (op == STR_getFlashChipSize) {
|
||||
*++sp = 4 * 1024 * 1024;
|
||||
return sp;
|
||||
} else if (op == STR_getFreeHeap) {
|
||||
*++sp = 90000;
|
||||
return sp;
|
||||
} else if (op == STR_getHeapSize) {
|
||||
*++sp = 320 * 1024;
|
||||
return sp;
|
||||
} else if (op == STR_getMaxAllocHeap) {
|
||||
*++sp = 80 * 1024;
|
||||
return sp;
|
||||
} else if (op == STR_esp_partition_t_size) {
|
||||
*++sp = 64;
|
||||
return sp;
|
||||
} else {
|
||||
fprintf(stderr, "MISSING SIM OPCODE: %s\n", op);
|
||||
exit(1);
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
}
|
||||
29
esp32/template.ino
Normal file
29
esp32/template.ino
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 Bradley D. Nelson
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ESP32forth v{{VERSION}}
|
||||
* Revision: {{REVISION}}
|
||||
*/
|
||||
|
||||
{{options}}
|
||||
{{opcodes}}
|
||||
{{extra_opcodes}}
|
||||
{{floats}}
|
||||
{{calling}}
|
||||
{{builtins.h}}
|
||||
{{builtins.cpp}}
|
||||
{{main.cpp}}
|
||||
86
esp32/timers.fs
Normal file
86
esp32/timers.fs
Normal file
@ -0,0 +1,86 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
internals definitions
|
||||
transfer timers-builtins
|
||||
forth definitions
|
||||
|
||||
( Lazy loaded timers )
|
||||
: timers r|
|
||||
|
||||
vocabulary timers timers definitions
|
||||
also registers also interrupts also internals
|
||||
transfer timers-builtins
|
||||
|
||||
$3ff5f000 constant TIMG_BASE
|
||||
( group n = 0/1, timer x = 0/1, watchdog m = 0-5 )
|
||||
: TIMGn ( n -- a ) $10000 * TIMG_BASE + ;
|
||||
: TIMGn_Tx ( n x -- a ) $24 * swap TIMGn + ;
|
||||
: TIMGn_TxCONFIG_REG ( n x -- a ) TIMGn_Tx 0 cells + ;
|
||||
: TIMGn_TxLOHI_REG ( n x -- a ) TIMGn_Tx 1 cells + ;
|
||||
: TIMGn_TxUPDATE_REG ( n x -- a ) TIMGn_Tx 3 cells + ;
|
||||
: TIMGn_TxALARMLOHI_REG ( n x -- a ) TIMGn_Tx 4 cells + ;
|
||||
: TIMGn_TxLOADLOHI_REG ( n x -- a ) TIMGn_Tx 6 cells + ;
|
||||
: TIMGn_TxLOAD_REG ( n x -- a ) TIMGn_Tx 8 cells + ;
|
||||
|
||||
: TIMGn_Tx_WDTCONFIGm_REG ( n m -- a ) swap TIMGn cells + $48 + ;
|
||||
: TIMGn_Tx_WDTFEED_REG ( n -- a ) TIMGn $60 + ;
|
||||
: TIMGn_Tx_WDTWPROTECT_REG ( n -- a ) TIMGn $6c + ;
|
||||
|
||||
: TIMGn_RTCCALICFG_REG ( n -- a ) TIMGn $68 + ;
|
||||
: TIMGn_RTCCALICFG1_REG ( n -- a ) TIMGn $6c + ;
|
||||
|
||||
: TIMGn_Tx_INT_ENA_REG ( n -- a ) TIMGn $98 + ;
|
||||
: TIMGn_Tx_INT_RAW_REG ( n -- a ) TIMGn $9c + ;
|
||||
: TIMGn_Tx_INT_ST_REG ( n -- a ) TIMGn $a0 + ;
|
||||
: TIMGn_Tx_INT_CLR_REG ( n -- a ) TIMGn $a4 + ;
|
||||
|
||||
: t>nx ( t -- n x ) dup 2/ 1 and swap 1 and ;
|
||||
|
||||
: timer@ ( t -- lo hi )
|
||||
dup t>nx TIMGn_TxUPDATE_REG 0 swap !
|
||||
t>nx TIMGn_TxLOHI_REG 2@ ;
|
||||
: timer! ( lo hi t -- )
|
||||
dup >r t>nx TIMGn_TxLOADLOHI_REG 2!
|
||||
r> t>nx TIMGn_TxLOAD_REG 0 swap ! ;
|
||||
: alarm ( t -- a ) t>nx TIMGn_TxALARMLOHI_REG ;
|
||||
|
||||
: enable! ( v t ) >r 31 $80000000 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: increase! ( v t ) >r 30 $40000000 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: autoreload! ( v t ) >r 29 $20000000 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: divider! ( v t ) >r 13 $1fffc000 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: edgeint! ( v t ) >r 12 $1000 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: levelint! ( v t ) >r 11 $800 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: alarm-enable! ( v t ) >r 10 $400 r> t>nx TIMGn_TxCONFIG_REG m! ;
|
||||
: alarm-enable@ ( v t ) >r 10 $400 r> t>nx TIMGn_TxCONFIG_REG m@ ;
|
||||
|
||||
: int-enable! ( f t -- )
|
||||
t>nx swap >r dup 1 swap lshift r> TIMGn_Tx_INT_ENA_REG m! ;
|
||||
|
||||
: onalarm ( xt t ) swap >r t>nx r> 0 ESP_INTR_FLAG_EDGE 0
|
||||
timer_isr_register throw ;
|
||||
: interval ( xt usec t ) 80 over divider!
|
||||
swap over 0 swap alarm 2!
|
||||
1 over increase!
|
||||
1 over autoreload!
|
||||
1 over alarm-enable!
|
||||
1 over edgeint!
|
||||
0 over 0 swap timer!
|
||||
dup >r onalarm r>
|
||||
1 swap enable! ;
|
||||
: rerun ( t -- ) 1 swap alarm-enable! ;
|
||||
|
||||
only forth definitions
|
||||
timers
|
||||
| evaluate ;
|
||||
36
esp32/web_interface.fs
Normal file
36
esp32/web_interface.fs
Normal file
@ -0,0 +1,36 @@
|
||||
\ Copyright 2021 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
( Lazy loaded Server Terminal )
|
||||
|
||||
:noname [ ' web-interface >body @ ] literal execute
|
||||
r|
|
||||
also streams also WiFi also web-interface definitions
|
||||
|
||||
: ip# dup 255 and n. [char] . emit 256 / ;
|
||||
: ip. ( n -- ) ip# ip# ip# 255 and . ;
|
||||
|
||||
also forth definitions
|
||||
|
||||
: login ( z z -- )
|
||||
WIFI_MODE_STA Wifi.mode
|
||||
WiFi.begin begin WiFi.localIP 0= while 100 ms repeat WiFi.localIP ip. cr
|
||||
z" forth" MDNS.begin if ." MDNS started" else ." MDNS failed" then cr ;
|
||||
: webui ( z z -- ) login 80 server ;
|
||||
|
||||
only forth definitions
|
||||
web-interface
|
||||
| evaluate ; is web-interface
|
||||
: login web-interface forth r| login | evaluate ;
|
||||
: webui web-interface forth r| webui | evaluate ;
|
||||
Reference in New Issue
Block a user