ESP32forth Update
       🙘
 October 8, 2022

IMPROVEMENTS SINCE AUGUST
         🙘
• CASE
• BTERM & RELINQUISH
• Shell Words
• Code Words & DUMP
• More ESP-CAM Bindings
• USER_VOCABULARIES

CASE

CASE
  1 OF ." one" ENDOF
  2 OF ." two" ENDOF
  ." other: " DUP .
ENDCASE

1 OVER = IF
    s" one" type
ELSE
    2 OVER = IF
        s" two" type
    ELSE
        s" other:" type DUP .
    THEN
THEN
DROP

CASE
  🙘
• Terser branching on a value
• Forth syntax doesn't quite allow jump tables
  - Worth exploring? Or un-Forthy?

BTERM &
RELINQUISH

BTERM
  🙘
• Bluetooth serial can be handy
• Discovered that bterm wasn't working on regular ESP32!
• The issue is that bluetooth needs about 120KB free
• RELINQUISH ( n -- ) releases n bytes from the back of the heap
• Built into bterm lazy loading

Shell
 Words

A Forth-y Shell
  🙘
• Basic BASH-like words
• But ESP32 doesn't build in directory support
• A few extra words on Linux

cp ( "src" "dst" -- ) Copy "src" file to "dst".
mv ( "src" "dst" -- ) Rename "src" file to "dst".
rm ( "path" -- ) Remove "path" file.
touch ( "path" -- ) Create "path" file if it doesn't exist.
cat ( "path" -- ) Print contents of "path" file.
ls ( "path" -- ) List files or directories in "path".

cd ( "path" -- ) Change director to "path".
mkdir ( "path" -- ) Create directory "path".
rmdir ( "path" -- ) Remove directory "path".
pwd ( -- ) Print current directory.

DEMO Shell
& Editor

Code Words
 & DUMP

Code Words
  🙘
• Added CODE words, but assembler not yet ready
• Uses a C call signature for stable ABI
• Not all memory can be used for ESP32 code
• ESP32 and Linux support only at the moment
• Assembler coming soon
• Lazy loaded by ASM word

CODE ( "name" ) -- Define a code word
END-CODE        -- End a code word
CHERE ( -- a )  -- Get code pointer
CALLOT ( n -- ) -- Allocate code memory
CODE1, ( n -- ) -- Compile 1 byte
CODE2, ( n -- ) -- Compile 2 byte
CODE3, ( n -- ) -- Compile 3 byte
CODE4, ( n -- ) -- Compile 4 byte

Forth to C Entry SIGNATURE:
cell_t *myfunc(cell_t *sp, float **fp);
-------
On x64:
  %rdi - Data stack pointer in
  %rax - Data stack pointer out
  %rsi - Pointer to floating stack pointer
-------
On Xtensa (ESP32):
  a2 - Data stack pointer in & out
  a3 - Pointer to floating stack pointer

YV(internals, CALLCODE, float *t_fp = fp; DUP; \
    sp = (cell_t *) (*(call_t*) (w + sizeof(cell_t)))(sp, &t_fp); \
    fp = t_fp; DROP) \

ASM FORTH
CODE my2*
  $48 CODE1, $89 CODE1, $f8 CODE1, ( mov %rdi, %rax )
  $48 CODE1, $d1 CODE1, $27 CODE1, ( shlq [%rdi] )
  $c3 CODE1,                       ( ret )
END-CODE

ASM FORTH
CODE my2*
  $004136 CODE3, ( entry   a1, 32 )
  $0288   CODE2, ( l32i.n  a8, a2, 0 )
  $1188f0 CODE3, ( slli    a8, a8, 1 )
  $0289   CODE2, ( s32i.n  a8, a2, 0 )
  $f01d   CODE2, ( retw.n )
END-CODE

' - 20 hex dump
 
416208                                      34 2A 40 00 00 00 00 00
416210              B2 3E 41 00 00 00 00 00 08 03 00 00 00 00 00 00
416220              16 2A 40 00 00 00 00 00

ESP-CAM
Bindings

esp_camera_init ( config -- f )
esp_camera_deinit ( -- f )
esp_camera_fb_get ( -- fb )
esp_camera_fb_return ( fb -- )
esp_camera_sensor_get ( -- sensor )
esp_camera_save_to_nvs ( key -- n )
esp_camera_load_from_nvs ( key -- n )

( formats )
PIXFORMAT_RGB565
PIXFORMAT_YUV422
PIXFORMAT_GRAYSCALE
PIXFORMAT_JPEG
PIXFORMAT_RGB888
PIXFORMAT_RAW
PIXFORMAT_RGB444
PIXFORMAT_RGB555

( frame sizes )
FRAMESIZE_96x96    ( 96x96)
FRAMESIZE_QQVGA    ( 160x120 )
FRAMESIZE_QCIF     ( 176x144 )
FRAMESIZE_HQVGA    ( 240x176 )
FRAMESIZE_240x240  ( 176x144 )
FRAMESIZE_QVGA     ( 320x240 )
FRAMESIZE_CIF      ( 400x296 )
FRAMESIZE_HVGA     ( 480x320 )
FRAMESIZE_VGA      ( 640x480 )
FRAMESIZE_SVGA     ( 800x600 )
FRAMESIZE_XGA     ( 1024x768 )
FRAMESIZE_HD      ( 1280x720 )
FRAMESIZE_SXGA    ( 1280x1024 )
FRAMESIZE_UXGA    ( 1600x1200 )

( access to config )
camera-fb-count ( -- a )
camera-jpeg-quality ( -- a )
camera-frame-size ( -- a )
camera-format ( -- a )

( Access a frame returned by esp_camera_fb_get )
fb->buf ( -- a )
fb->len ( -- n )
fb->width ( -- n )
fb->height ( -- n )
fb->format ( -- n )
fb->sec ( -- n )
fb->usec ( -- n )

( Access methods in struct returned by esp_camera_sensor_get )
s->xclk_freq_hz ( a )
s->init_status ( s )
s->reset ( s )
s->set_pixformat ( s pixformat )
s->set_framesize ( s framesize )
s->set_contrast ( s level )
s->set_brightness ( s level )
s->set_saturation ( s level )
s->set_sharpness ( s level )
s->set_denoise ( s level )
s->set_gainceiling ( s gainceil )
s->set_quality ( s quality )
s->set_colorbar ( s enable )
s->set_whitebal ( s enable )
s->set_gain_ctrl ( s enable )
s->set_exposure_ctrl ( s enable )
s->set_hmirror ( s enable )
s->set_vflip ( s enable )
( --- )
s->set_aec2 ( s enable )
s->set_awb_gain ( s enable )
s->set_agc_gain ( s gain )
s->set_aec_value ( s gain )
( --- )
s->set_special_effect ( s effect )
s->set_wb_mode ( s mode )
s->set_ae_level ( s level )
( --- )
s->set_raw_gma ( s enable )
s->set_lenc ( s enable )
( --- )
s->get_reg ( s reg mask )
s->set_reg ( s reg mask value )
s->set_res_raw ( s startX startY endX endY offsetX offsetY totalX totalY outputX outputY scale binning )
s->set_pll ( s bypass mul sys root pre seld5 pclken pclk )
s->set_xclk ( s time xclk )

USER_VOCABULARIES

Y(myword, n0 = myfunc(a1, n0); DROP) \
X("myword!", MYWORDBANG, n0 = myfunc(n0)) \

YV(myvocab, myword, n0 = myfunc(a1, n0); DROP) \
XV(myvocab, "myword!", MYWORDBANG, n0 = myfunc(n0)) \

Builtins add an extra chain of builtin words
e.g. 
internals-builtins
Wire-builtins

userwords.h
-----------
#define USER_VOCABULARIES V(myvocab) V(myvocab2)
#define USER_WORDS \
  XV(myvocab, "my+", MYPLUS, n1 = n1 + n0; DROP) \
  YV(myvocab2, myword, n0 = n0 + 10) \

VOCABULARY myvocab myvocab DEFINITIONS
  transfer myvocab-builtins
FORTH
VOCABULARY myvocab2 myvocab2 DEFINITIONS
  transfer myvocab2-builtins
FORTH

QUESTIONS?
   🏵
 Thank you!