Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor js interpreter to be compatible with flipper zero js #750

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
53b9f8c
Add require function to js interpreter
Tawank Jan 29, 2025
ef0ced8
Add to_string, to_hex_string, to_lower_case, to_upper_case in js
Tawank Jan 29, 2025
35443d6
Add audio, display, device, ir and wifi modules to js interpreter
Tawank Jan 29, 2025
add7535
Add badusb, dialog, gpio, keyboard, math and notification modules to js
Tawank Jan 29, 2025
7899d1f
Fix undefined reference to dacWrite
Tawank Jan 29, 2025
8b72f28
Fix undefined reference to dacWrite v2
Tawank Jan 30, 2025
6d9d50c
Fix undefined reference to dacWrite v3
Tawank Jan 30, 2025
25fe050
Add require function to js, fix native_serialPrintln
Tawank Jan 30, 2025
0bf3e3c
Add drawCircle, drawRoundRect, acosh, asinh, atanh and is_equal funct…
Tawank Jan 30, 2025
ef8392b
Refactor native_serialPrintln, native_println and random js functions
Tawank Jan 31, 2025
b5cd5de
Add posibility to require scripts from SD/LittleFS in js interpreter
Tawank Jan 31, 2025
813440e
Add error handling in js interpreter
Tawank Jan 31, 2025
01968bc
Fix an error that caused the ESP32 to panic restart without any backt…
Tawank Jan 31, 2025
f3b68e9
Fix to native_to_hex_string and internal_print in js
Tawank Jan 31, 2025
89f46d3
Fix performance issues in internal_print js interpreter
Tawank Feb 2, 2025
83a738e
Fix in display.cpp
Tawank Feb 2, 2025
7ac91d2
Add prefix to console: debug, warn, error in JS interpreter
Tawank Feb 5, 2025
1a2d328
Add native_return_this to require to be compatible with es6 imports
Tawank Feb 5, 2025
43cf0d7
Add better error handling in js interpreter
Tawank Feb 5, 2025
ac9dcc2
Remove http module, move fetch to wifi module
Tawank Feb 5, 2025
80d48ad
Add readTouch to gpio module
Tawank Feb 5, 2025
36a4a38
Merge branch 'main' into js_refractor_require
Tawank Feb 5, 2025
46b7e86
Remove dacWrite from gpio module
Tawank Feb 5, 2025
1f19942
Remove default export in modules, Changes in gpio module
Tawank Feb 5, 2025
08a3784
Add sprites to display module in js interpreter
Tawank Feb 5, 2025
8594e5a
Add connected method to wifi module in js:
Tawank Feb 6, 2025
53f2afa
Add native_drawXBitmap to display module in js
Tawank Feb 6, 2025
7ccf433
Fix TFT_eSprite error when device has no screen
Tawank Feb 8, 2025
4e501f1
Fix taskInputHandler remove blocking delay, optimisations
Tawank Feb 8, 2025
d949975
Fix native_getButton in js
Tawank Feb 8, 2025
3490a97
Add ledc funtions to js
Tawank Feb 8, 2025
d6f2385
Change native_fetch to native_httpFetch to avoid confusion in future
Tawank Feb 9, 2025
03f3871
Fix esp32 no screen, add setTextAlign to js
Tawank Feb 11, 2025
7d06753
Fix for esp32-s3
Tawank Feb 12, 2025
5a497fb
Changes in interpreter.cpp
Tawank Feb 12, 2025
b15582a
Add warnings, optimize flag and monitor_speed in platformio.ini
Tawank Feb 12, 2025
7662153
Fix some bugs in code thanks to warnings flag in compiler
Tawank Feb 12, 2025
d2074e2
Add new sd_function readBigFile
Tawank Feb 13, 2025
cc19899
Merge branch 'main' into js_refractor_require
Tawank Feb 13, 2025
248597b
Refactor interpreter.cpp divide it into the modules
Tawank Feb 16, 2025
3f9e34e
Add storage functions to js
Tawank Feb 17, 2025
73838be
Fix httpFetch, Add dialogViewText in js
Tawank Feb 19, 2025
3b3d908
Increase InputHandler stack size
Tawank Feb 19, 2025
dacec6f
Move interpreter function to new task to increase stack size of js in…
Tawank Feb 20, 2025
c8b849a
Add new functions to dialogCreateTextViewer and refactor dialogChoice
Tawank Feb 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ build_flags =
-Wno-unused-label
-Wno-comment
-Wno-unused-variable
-Wno-pointer-arith
; warnings end
-Wl,--print-memory-usage
-Wl,--gc-sections
-DGIT_COMMIT_HASH='"Homebrew"'
-DSAFE_STACK_BUFFER_SIZE=4096
; -DARDUINO_LOOP_STACK_SIZE=8192 ; loop stack size default: 4096
-DFASTLED_RMT_BUILTIN_DRIVER=1 ; https://github.com/FastLED/FastLED/blob/67436be11fc3b7be611cdf9011f31c4f76817741/src/platforms/esp/32/rmt_4/idf4_clockless_rmt_esp32.h#L25-L33
; This setting let RF Spectrum to work with LED interface with FastLED on ESP32-S3
; rtl_433_ESP flags https://github.com/NorthernMan54/rtl_433_ESP/blob/main/example/OOK_Receiver/platformio.ini
Expand All @@ -71,6 +73,7 @@ build_flags =
;-DRF_MODULE_GDO2=14 ; CC1101 pin GDO2
;-DRF_MODULE_GDO2=RADIOLIB_NC ; CC1101 pin GDO2
;-DRF_MODULE_INIT_STATUS=true
; build_unflags = -Os

extra_scripts =
pre:patch.py
Expand Down
19 changes: 5 additions & 14 deletions src/core/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,6 @@ void drawMainBorder(bool clear) {
#endif
if(clear){
tft.fillScreen(bruceConfig.bgColor);
tft.fillScreen(bruceConfig.bgColor);
}
setTftDisplay(12, 12, bruceConfig.priColor, 1, bruceConfig.bgColor);
tft.setTextDatum(0);
Expand Down Expand Up @@ -1082,18 +1081,10 @@ bool Gif::openGIF(FS *fs, const char *filename) {
GIFDraw
)
) {
Serial.printf("Successfully opened GIF; Canvas size = %d x %d\n", gif->getCanvasWidth(), gif->getCanvasHeight());
GIFINFO gi;
if (gif->getInfo(&gi)) {
Serial.printf("frame count: %d\n", gi.iFrameCount);
Serial.printf("duration: %d ms\n", gi.iDuration);
Serial.printf("max delay: %d ms\n", gi.iMaxDelay);
Serial.printf("min delay: %d ms\n", gi.iMinDelay);
return true;
}
return true;
}

Serial.printf("GIF opening error: %d\n", gif->getLastError());
log_d("GIF opening error: %d\n", gif->getLastError());
return false;
}

Expand All @@ -1103,8 +1094,8 @@ bool Gif::openGIF(FS *fs, const char *filename) {
// 1 = good result and more frames exist
// 0 = no more frames exist, a frame may or may not have been played: use getLastError() and look for GIF_SUCCESS to know if a frame was played
// -1 = error
int Gif::playFrame(int x, int y) {
if ((millis() - lTime) >= *delayMilliseconds) {
int Gif::playFrame(int x, int y, bool bSync) {
if (bSync && ((millis() - lTime) >= *delayMilliseconds)) {
lTime = millis();
gifPosition.x = x;
gifPosition.y = y;
Expand Down Expand Up @@ -1144,7 +1135,7 @@ bool showGif(FS *fs, const char *filename, int x, int y, bool center, int playDu
long timeStart = millis();
do {
result = gif.playFrame(x, y);
if (result == -1) Serial.printf("GIF playFrame error: %d\n", gif.getLastError());
if (result == -1) log_d("GIF playFrame error: %d\n", gif.getLastError());

if(check(AnyKeyPress)) break;

Expand Down
2 changes: 1 addition & 1 deletion src/core/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Gif {

bool openGIF(FS *fs, const char *filename);

int playFrame(int x, int y);
int playFrame(int x = 0, int y = 0, bool bSync = true);

int getInfo(GIFINFO *pInfo) {
return gif->getInfo(pInfo);
Expand Down
96 changes: 69 additions & 27 deletions src/core/scrollableTextArea.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "scrollableTextArea.h"

ScrollableTextArea::ScrollableTextArea(const String& title) :
_startLine{0},
firstVisibleLine{0},
_redraw{true},
_title(title),
_fontSize(FP),
Expand All @@ -25,8 +25,8 @@ ScrollableTextArea::ScrollableTextArea(const String& title) :
}

ScrollableTextArea::ScrollableTextArea(
uint8_t fontSize, int16_t startX, int16_t startY, int32_t width, int32_t height
) : _startLine{0},
uint8_t fontSize, int16_t startX, int16_t startY, int32_t width, int32_t height, bool drawBorders
) : firstVisibleLine{0},
_redraw{true},
_title(""),
_fontSize(fontSize),
Expand All @@ -38,7 +38,9 @@ ScrollableTextArea::ScrollableTextArea(
,_scrollBuffer(&tft)
#endif
{
drawMainBorder();
if (drawBorders) {
drawMainBorder();
}
setup();
}

Expand All @@ -55,27 +57,59 @@ void ScrollableTextArea::setup() {
_scrollBuffer.setTextSize(_fontSize);
_scrollBuffer.fillSprite(bruceConfig.bgColor);

_maxCharsInLine = floor(_width / _scrollBuffer.textWidth("w", _fontSize));
_pxlsPerLine = _scrollBuffer.fontHeight() + 2;
_maxLinesInArea = floor(_height / _pxlsPerLine);
_maxCharactersPerLine = floor(_width / _scrollBuffer.textWidth("w", _fontSize));
_pixelsPerLine = _scrollBuffer.fontHeight() + 2;
_maxVisibleLines = floor(_height / _pixelsPerLine);
#endif
}

void ScrollableTextArea::scrollUp() {
if (_startLine) {
_startLine--;
if (firstVisibleLine) {
firstVisibleLine--;
_redraw = true;
}
}

void ScrollableTextArea::scrollDown() {
if (_startLine + _maxLinesInArea <= _lines.size()) {
if (_startLine == 0) _startLine++;
_startLine++;
if (firstVisibleLine + _maxVisibleLines <= linesBuffer.size()) {
if (firstVisibleLine == 0) firstVisibleLine++;
firstVisibleLine++;
_redraw = true;
}
}

void ScrollableTextArea::scrollToLine(size_t lineNumber) {
if (linesBuffer.empty()) return; // Ensure there's content to scroll

if (lineNumber > linesBuffer.size() - _maxVisibleLines) {
firstVisibleLine = (linesBuffer.size() > _maxVisibleLines)
? linesBuffer.size() - _maxVisibleLines
: 0;
} else {
firstVisibleLine = lineNumber;
}
}

void ScrollableTextArea::scrollToLine(size_t lineNumber) {
if (linesBuffer.empty()) return; // Ensure there's content to scroll

if (lineNumber > linesBuffer.size() - _maxVisibleLines) {
firstVisibleLine = (linesBuffer.size() > _maxVisibleLines)
? linesBuffer.size() - _maxVisibleLines
: 0;
} else {
firstVisibleLine = lineNumber;
}
}

String ScrollableTextArea::getLine(size_t lineNumber) {
return linesBuffer[((lineNumber >= linesBuffer.size()) || (lineNumber < 0)) ? linesBuffer.size() : lineNumber];
}

size_t ScrollableTextArea::getMaxLines(size_t lineNumber) {
return linesBuffer.size();
}

void ScrollableTextArea::show(bool force) {
draw(force);

Expand All @@ -85,6 +119,10 @@ void ScrollableTextArea::show(bool force) {
while(!check(SelPress)) { update(force); yield(); }
}

uint32_t ScrollableTextArea::getMaxVisibleTextLength() {
return _maxVisibleLines * _maxCharactersPerLine;
}

void ScrollableTextArea::update(bool force) {
if (check(PrevPress)) scrollUp();
else if (check(NextPress)) scrollDown();
Expand All @@ -94,6 +132,7 @@ void ScrollableTextArea::update(bool force) {
}

void ScrollableTextArea::fromFile(File file) {
linesBuffer.clear();
while (file.available()) addLine(file.readStringUntil('\n'));

draw(true);
Expand All @@ -102,6 +141,7 @@ void ScrollableTextArea::fromFile(File file) {
}

void ScrollableTextArea::fromString(const String& text) {
linesBuffer.clear();
int startIdx = 0;
int endIdx = 0;

Expand All @@ -119,16 +159,16 @@ void ScrollableTextArea::fromString(const String& text) {
#ifdef HAS_SCREEN
void ScrollableTextArea::addLine(const String& text) {
if (text.isEmpty()) {
_lines.emplace_back("");
linesBuffer.emplace_back("");
return;
}

String buff;
size_t start{0};

// automatically split into multiple lines
while( !(buff = text.substring(start, start + _maxCharsInLine)).isEmpty() ){
_lines.emplace_back(buff);
while( !(buff = text.substring(start, start + _maxCharactersPerLine)).isEmpty() ){
linesBuffer.emplace_back(buff);
start += buff.length();
}

Expand All @@ -141,44 +181,46 @@ void ScrollableTextArea::draw(bool force) {
_scrollBuffer.fillSprite(bruceConfig.bgColor);

uint16_t yOffset = 0;
uint16_t lines = 0;
size_t lines = 0;

// if there is text above
if (_startLine) {
if (firstVisibleLine) {
_scrollBuffer.drawString("...", 0, yOffset);
yOffset += _pxlsPerLine;
yOffset += _pixelsPerLine;
lines++;
}

int32_t tmpHeight = _height;
// if there is text below
if (_lines.size() - _startLine >= _maxLinesInArea) {
_scrollBuffer.drawString("...", 0, _height - _pxlsPerLine);
tmpHeight -= _pxlsPerLine;
if (linesBuffer.size() - firstVisibleLine >= _maxVisibleLines) {
_scrollBuffer.drawString("...", 0, _height - _pixelsPerLine);
tmpHeight -= _pixelsPerLine;
lines++;
}

size_t idx{_startLine};
while( yOffset < tmpHeight && lines < _maxLinesInArea && idx < _lines.size() ){
_scrollBuffer.drawString(_lines[idx], 0, yOffset);
yOffset += _pxlsPerLine;
size_t idx{firstVisibleLine};
while( yOffset < tmpHeight && lines < _maxVisibleLines && idx < linesBuffer.size() ){
_scrollBuffer.drawString(linesBuffer[idx], 0, yOffset);
yOffset += _pixelsPerLine;
lines++;
idx++;
}

lastVisibleLine = firstVisibleLine + lines;

_scrollBuffer.pushSprite(_startX, _startY);
_redraw = false;
}

// for webui as a regular text area
#else
void ScrollableTextArea::addLine(const String& text){
if( !text.isEmpty() ) _lines.emplace_back(text);
if( !text.isEmpty() ) linesBuffer.emplace_back(text);
}

void ScrollableTextArea::draw(bool force){
uint16_t yOffset = 0;
for( const auto& str : _lines ){
for( const auto& str : linesBuffer ){
_scrollBuffer.drawString(str, 0, yOffset);
yOffset += 12;
}
Expand Down
23 changes: 17 additions & 6 deletions src/core/scrollableTextArea.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class ScrollableTextArea {
int16_t startX,
int16_t startY,
int32_t width,
int32_t height
int32_t height,
bool drawBorders = true
);

~ScrollableTextArea();
Expand All @@ -18,6 +19,11 @@ class ScrollableTextArea {

void scrollDown();

void scrollToLine(size_t lineNumber);

String getLine(size_t lineNumber);
size_t getMaxLines(size_t lineNumber);

void addLine(const String& text);

void fromString(const String& text);
Expand All @@ -28,17 +34,22 @@ class ScrollableTextArea {

void show(bool force = false);

uint32_t getMaxVisibleTextLength();

size_t firstVisibleLine;
size_t lastVisibleLine;
/// TODO: Change to std::vector<char *> and alloc to PSRAM if possible
std::vector<String> linesBuffer;

private:
uint16_t _startLine;
bool _redraw;
String _title;
uint8_t _fontSize;
int16_t _startX, _startY;
int32_t _width, _height;
int32_t _pxlsPerLine;
int32_t _maxLinesInArea;
uint16_t _maxCharsInLine;
std::vector<String> _lines;
int32_t _pixelsPerLine;
size_t _maxVisibleLines;
uint16_t _maxCharactersPerLine;

#if defined(HAS_SCREEN)
TFT_eSprite _scrollBuffer;
Expand Down
38 changes: 38 additions & 0 deletions src/core/sd_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,44 @@ String readSmallFile(FS &fs, String filepath) {
return fileContent;
}

/***************************************************************************************
** Function name: readFile
** Description: read file and return its contents as a char*
** caller needs to call free()
***************************************************************************************/
char *readBigFile(FS &fs, String filepath, bool binary, size_t *fileSize) {
File file = fs.open(filepath);
if (!file) {
Serial.printf("Could not open file: %s\n", filepath.c_str());
return NULL;
}

size_t fileLen = file.size();
char *buf = (char *)(psramFound() ? ps_malloc(fileLen + 1) : malloc(fileLen + 1));
if (fileSize != NULL) {
*fileSize = file.size();
}

if (!buf) {
Serial.printf("Could not allocate memory for file: %s\n", filepath.c_str());
return NULL;
}

size_t bytesRead = 0;
while (bytesRead < fileLen && file.available()) {
size_t toRead = fileLen - bytesRead;
if (toRead > 512) {
toRead = 512;
}
file.read((uint8_t *)(buf + bytesRead), toRead);
bytesRead += toRead;
}
buf[bytesRead] = '\0';
file.close();

return buf;
}

/***************************************************************************************
** Function name: getFileSize
** Description: get a file size without opening
Expand Down
2 changes: 2 additions & 0 deletions src/core/sd_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ String readLineFromFile(File myFile);

String readSmallFile(FS &fs, String filepath);

char *readBigFile(FS &fs, String filepath, bool binary = false, size_t *fileSize = NULL);

String md5File(FS &fs, String filepath);

String crc32File(FS &fs, String filepath);
Expand Down
2 changes: 1 addition & 1 deletion src/core/serialcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ char *readFileFromSerial(size_t fileSizeChar = SAFE_STACK_BUFFER_SIZE) {
buf[bufSize++] = '\n';
}
buf[bufSize] = '\0';
Serial.println(buf);
Serial.println("JS file received");
return buf;
}
/*
Expand Down
Loading
Loading