ESP32Forth eoy 2021 🙜 Brad Nelson 🙜 Decemeber 18, 2021 Agenda 🙜 • Floating Point • More Kinds of ESP-32 • Lots of Libraries Floating Point 🙜 • Use what the hardware has • Preparing to run ML models • ESP-32 only has hardware float32 • Many libraries take floats Approach 🙜 • Additional floating point stack • fp pointer throughout register cell_t *ip, *rp, *sp, tos, w; register float *fp; rp = init_rp; ip = (cell_t *) *rp--; sp = (cell_t *) *rp--; fp = (float *) *rp--; DROP; NEXT; #define PARK DUP; \ *++rp = (cell_t) fp; \ *++rp = (cell_t) sp; \ *++rp = (cell_t) ip static cell_t fconvert(const char *pos, cell_t n, float *ret) { *ret = 0; cell_t negate = 0; cell_t has_dot = 0; cell_t exp = 0; float shift = 1.0; if (!n) { return 0; } if (*pos == '-') { negate = -1; ++pos; --n; } for (; n; --n) { if (*pos >= '0' && *pos <= '9') { if (has_dot) { shift = shift * 0.1f; *ret = *ret + (*pos - '0') * shift; } else { *ret = *ret * 10 + (*pos - '0'); } } else if (*pos == 'e' || *pos == 'E') { break; } else if (*pos == '.') { if (has_dot) { return 0; } has_dot = -1; } ++pos; } if (!n) { return 0; } // must have E ++pos; --n; if (n) { if (!convert(pos, n, 10, &exp)) { return 0; } } if (exp < -128 || exp > 128) { return 0; } for (;exp < 0; ++exp) { *ret *= 0.1f; } for (;exp > 0; --exp) { *ret *= 10.0f; } if (negate) { *ret = -*ret; } return -1; } X("F>NUMBER?", FCONVERT, tos = fconvert((const char *) *sp, tos, fp); --sp) \ } else { float f; if (fconvert((const char *) name, len, &f)) { if (g_sys.state) { *g_sys.heap++ = g_sys.DOFLIT_XT; *(float *) g_sys.heap++ = f; } else { *++(*fp) = f; } #define FLOATING_POINT_LIST \ Y(DOFLIT, *++fp = *(float *) ip++) \ X("FDUP", FDUP, fp[1] = *fp; ++fp) \ X("FNIP", FNIP, fp[-1] = *fp; --fp) \ X("FDROP", FDROP, --fp) \ X("FOVER", FOVER, fp[1] = fp[-1]; ++fp) \ X("FSWAP", FSWAP, float ft = fp[-1]; fp[-1] = *fp; *fp = ft) \ X("F0<", FZLESS, DUP; tos = *fp-- < 0.0f ? -1 : 0) \ X("F0=", FZEQUAL, DUP; tos = *fp-- == 0.0f ? -1 : 0) \ : f= ( r r -- f ) f- f0= ; : f< ( r r -- f ) f- f0< ; : f> ( r r -- f ) fswap f< ; : f<> ( r r -- f ) f= 0= ; : f<= ( r r -- f ) f> 0= ; : f>= ( r r -- f ) f< 0= ; X("FNEGATE", FNEGATE, *fp = -*fp) \ X("F+", FPLUS, fp[-1] += *fp; --fp) \ X("F-", FMINUS, fp[-1] -= *fp; --fp) \ X("F*", FSTAR, fp[-1] *= *fp; --fp) \ X("F/", FSLASH, fp[-1] /= *fp; --fp) \ X("1/F", FINVERSE, *fp = 1.0 / *fp) \ X("S>F", STOF, *++fp = (float) tos; DROP) \ X("F>S", FTOS, DUP; tos = (cell_t) *fp--) \ X("FP@", FPAT, DUP; tos = (cell_t) fp) \ X("FP!", FPSTORE, fp = (float *) tos; DROP) \ X("SF@", FAT, *++fp = *(float *) tos; DROP) \ X("SF!", FSTORE, *(float *) tos = *fp--; DROP) \ 4 constant sfloat : sfloats ( n -- n*4 ) sfloat * ; : sfloat+ ( a -- a ) sfloat + ; : sf, ( r -- ) here sf! sfloat allot ; : afliteral ( r -- ) ['] DOFLIT , sf, align ; : fliteral afliteral ; immediate : fconstant ( r "name" ) create sf, align does> sf@ ; : fvariable ( "name" ) create sfloat allot align ; 6 value precision : set-precision ( n -- ) to precision ; : #f+s ( r -- ) fdup precision 0 ?do 10e f* loop precision 0 ?do fdup f>s 10 mod [char] 0 + hold 0.1e f* loop [char] . hold fdrop f>s #s ; : #fs ( r -- ) fdup f0< if fnegate #f+s [char] - hold else #f+s then ; : f. ( r -- ) <# #fs #> type space ; : fsqrt ( r -- r ) 1e 20 0 do fover fover f/ f+ 0.5e f* loop fnip ; ESP32 Hardware Explosion 🙜 ESP8266 - Tensilica Xtensa L106 - 80MHz - Single Core ESP32 - Tensilica Xtensa LX6 - 240MHz - Dual Core ESP32-SOLO & ESP32-MINI - Tensilica Xtensa LX6 - 240MHz - Single Core ESP32-S2 - Tensilica Xtensa LX7 - 240MHz - Single Core ESP32-S3 - Tensilica Xtensa LX7 - 240MHz - Single Core ESP32-C3 - RISC-V - 160MHz - Single Core ESP32-C6 - RISC-V - 160MHz - Single Core ESP32 Hardware Explosion 🙜 ESP8266 - 80KiB RAM - 17 GPIO ESP32 - 320KiB RAM - 34 GPIO ESP32-SOLO - 520KiB RAM - 22 GPIO - NO ARDUINO! ESP32-MINI - 520KiB RAM - 28 GPIO - NO ARDUINO! ESP32-S2 - 320KiB RAM - 43 GPIO - USB OTG / No BLE ESP32-S3 - 384KiB RAM - 44 GPIO - USB OTG ESP32-C3 - 400KiB RAM - 22 GPIO (Pin compat 8266) ESP32-C6 - 400KiB RAM - 22 GPIO - NO ARDUINO! ESP32 Hardware Explosion 🙜 ESP8266 - No FPU ESP32 - Single Precision FPU ESP32-SOLO - Single Precision FPU ESP32-MINI - Single Precision FPU ESP32-S2 - No FPU ESP32-S3 - Single Precision FPU ESP32-C3 - No FPU ESP32-C6 - No FPU Easy to Expand 🙜 ---- userwords.h ---- int my_cool_function(char *foo, int bar, uint8_t *baz); ... #define USER_WORDS \ Y(MY_FUNC, n0 = my_cool_function(c2, n1, b0); NIPn(2)) \ Lots of Libraries 🙜 • Serial • Serial Bluetooth • LED Controller • SPIFFS • SD_MMC • WiFi • mDNS • I2C • WebServer (Forth and Native) • Camera • GPIO & Interrupts • Remote Control (RMT) • Tasks • Blocks eforth.appspot.com ⚘ QUESTIONS?