From c157c2d05e7a5286507a77a69007fcfd6c9cbdf8 Mon Sep 17 00:00:00 2001 From: Pirata Date: Sun, 25 Aug 2024 16:19:01 -0300 Subject: [PATCH 1/2] JavaScript Interpreter Added JavaScript Interpreter with some examples. Changed the SPIClass to StickCs to work with SD Card.. need testing --- README.md | 21 +- interpreter.md | 247 ++++++++++++ platformio.ini | 243 ++++++------ sd_files/interpreter/Example1.js | 67 ++++ sd_files/interpreter/Snake_Cardputer.js | 154 ++++++++ sd_files/interpreter/Snake_Stick_CoreS3.js | 143 +++++++ src/core/globals.h | 5 + src/core/main_menu.cpp | 4 + src/main.cpp | 19 +- src/modules/bjs_interpreter/interpreter.cpp | 409 ++++++++++++++++++++ src/modules/bjs_interpreter/interpreter.h | 16 + src/modules/ble/ble_jammer.cpp | 16 +- src/modules/rf/rf.cpp | 7 +- 13 files changed, 1227 insertions(+), 124 deletions(-) create mode 100644 interpreter.md create mode 100644 sd_files/interpreter/Example1.js create mode 100644 sd_files/interpreter/Snake_Cardputer.js create mode 100644 sd_files/interpreter/Snake_Stick_CoreS3.js create mode 100644 src/modules/bjs_interpreter/interpreter.cpp create mode 100644 src/modules/bjs_interpreter/interpreter.h diff --git a/README.md b/README.md index 610097a06..4124c432a 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) ### BLE - [X] BLE Beacon - [X] BLE Scan +- [X] NRF24 Jammer - [X] AppleJuice - [X] SwiftPair - [X] Android Spam @@ -62,15 +63,15 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) ### RF - [x] Scan/Copy - [x] Custom SubGhz -- [x] Spectrum - @incursiohack -- [x] Jammer Full - @incursiohack -- [x] Jammer Intermittent - @incursiohack +- [x] Spectrum +- [x] Jammer Full (sends a full squared wave into output) +- [x] Jammer Intermittent (sends PWM signal into output) - [x] Config - [X] RF TX Pin - [X] RF RX Pin - [X] RF Module - [X] RF Frequency -- [ ] Replay +- [x] Replay ### RFID - [x] Read tag @@ -104,6 +105,7 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) - [x] Megalodon - [x] BADUsb (New features, SPIFFS and SDCard) - [X] Openhaystack +- [X] JavaScript Interpreter (Credits to justinknight93)[https://github.com/justinknight93/Doolittle] ### Clock - [X] Clock @@ -117,6 +119,17 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) - [x] Sleep - [x] Restart +## Specific functions per Device, the ones not mentioned here are available to all. +| Device | CC1101 | NRF24 | Interpreter | FMRadio | Mic_SPM1423 | BadUSB | RGB Led | Speaker | LITE_MODE | +| Cardputer | :ok: | :ok: | :ok: | :x: | :ok: | :ok: | :ok: | NS4168 | :x: | +| StickCPlus2 | :ok: | :ok: | :ok: | :ok: | :ok: | :x: | :x: | Tone | :x: | +| StickCPlus 1.1 | :ok: | :ok: | :ok: | :x: | :ok: | :x: | :x: | Tone | :ok: | +| Core | :x: | :x: | :x: | :x: | :ok: | :x: | :x: | Tone | :x: | +| Core2 | :x: | :x: | :x: | :x: | :ok: | :x: | :x: | :x: | :x: | +| CoreSe/SE | :x: | :x: | :ok: | :x: | :x: | :ok: | :x: | :x: | :x: | + +*LITE_MODE*: TelNet, SSH, DPWO, WireGuard, BLEBacon, BLEScan, FMRadio and OpenHaystack are NOT available for M5Launcher Compatibility + ## :sparkles: Why and how does it look? Bruce stems from a keen observation within the community focused on devices like Flipper Zero. While these devices offered a glimpse into the world of offensive security, there was a palpable sense that something more could be achieved without being that overpriced, particularly with the robust and modular hardware ecosystem provided by m5stack products. diff --git a/interpreter.md b/interpreter.md new file mode 100644 index 000000000..45859bb68 --- /dev/null +++ b/interpreter.md @@ -0,0 +1,247 @@ +## Manual for Coding in JavaScript to Bruce + +This secction was ported from (justinknight93/Doolittle)[https://github.com/justinknight93/Doolittle], who made a very nice job with its JavaScript interpreter + +Some changes were made and some new functions were added, and more are to be add. + +Bellow you can find some of the + + +## API Reference for Native Functions Accessible from JS + +### `load(script: string)` + +**Description**: Sets the script to be executed next when the current script ends. + +**Parameters**: +- `script` (string): The JavaScript code as a string to be loaded. + +**Returns**: `void` + +--- + +### `print(message: string)` + +**Description**: Prints the given message to the Serial monitor. + +**Parameters**: +- `message` (string): The message to print. + +**Returns**: `void` + +--- + +### `now()` + +**Description**: Returns the current time in milliseconds since the epoch. + +**Returns**: `number`: The current timestamp in milliseconds. + +--- + +### `delay(ms: number)` + +**Description**: Pauses execution for the specified number of milliseconds. + +**Parameters**: +- `ms` (number): The number of milliseconds to delay. + +**Returns**: `void` + +--- + +### `digitalWrite(pin: number, value: boolean)` + +**Description**: Sets the digital value (HIGH or LOW) for a specified pin. + +**Parameters**: +- `pin` (number): The pin number. +- `value` (boolean): The value to write (true for HIGH, false for LOW). + +**Returns**: `void` + +--- + +### `pinMode(pin: number, mode: number)` + +**Description**: Configures the specified pin to behave as an input or an output. + +**Parameters**: +- `pin` (number): The pin number. +- `mode` (number): The mode to set (INPUT, OUTPUT, etc.). + +**Returns**: `void` + +--- +## Get some board information +### `getBattery` +**Description**: Get and integer from 0 to 100 relative to the battery level. + +**Returns**: `number`: 0-100 battery level. + +--- +### `getBoard` +**Description**: Get and integer from 0 to 100 relative to the battery level. + +**Returns**: `string[]`: "StickCPlus", "StickCPlus2", "Cardputer", "Core2", "Core", "CoreS3/SE". + +--- +## WiFi functions +### `wifiConnect` +**Description**: Open Bruce WiFi connection menu. + +--- +### `wifiDisconnect` +**Description**: Disconnect Wifi. + +--- +### `httpGet(url: string, headers: string[])` + +**Description**: Performs an HTTP GET request to the specified URL. Optionally includes headers. + +**Parameters**: +- `url` (string): The URL to send the GET request to. +- `headers` (string[]): An array of headers to include in the request. Headers should be provided as key-value pairs in the array. Example: `[ + "Content-Type", "application/json", + "Authorization", "Bearer your_token_here", + "Accept", "application/json" +]` + +**Returns**: `object`: An object with two properties: + - `response` (number): The HTTP response code. + - `body` (string): The response body. + +--- + +## TFT Display Functions + +### `color(r: number, g: number, b: number)` + +**Description**: Creates a color from the given RGB values. + +**Parameters**: +- `r` (number): The red component (0-255). +- `g` (number): The green component (0-255). +- `b` (number): The blue component (0-255). + +**Returns**: `number`: The color value in 16-bit RGB format. + +--- + +### `setTextColor(color: number)` + +**Description**: Sets the text color for drawing operations. + +**Parameters**: +- `color` (number): The color value in 16-bit RGB format. + +**Returns**: `void` + +--- + +### `setTextSize(size: number)` + +**Description**: Sets the text size for drawing operations. + +**Parameters**: +- `size` (number): The text size multiplier. + +**Returns**: `void` + +--- + +### `drawRect(x: number, y: number, width: number, height: number, color: number)` + +**Description**: Draws a rectangle with the specified parameters. + +**Parameters**: +- `x` (number): The x-coordinate of the top-left corner. +- `y` (number): The y-coordinate of the top-left corner. +- `width` (number): The width of the rectangle. +- `height` (number): The height of the rectangle. +- `color` (number): The color value in 16-bit RGB format. + +**Returns**: `void` + +--- + +### `drawFillRect(x: number, y: number, width: number, height: number, color: number)` + +**Description**: Draws a filled rectangle with the specified parameters. + +**Parameters**: +- `x` (number): The x-coordinate of the top-left corner. +- `y` (number): The y-coordinate of the top-left corner. +- `width` (number): The width of the rectangle. +- `height` (number): The height of the rectangle. +- `color` (number): The color value in 16-bit RGB format. + +**Returns**: `void` + +--- + +### `drawString(text: string, x: number, y: number)` + +**Description**: Draws the specified text at the given coordinates. + +**Parameters**: +- `text` (string): The text to draw. +- `x` (number): The x-coordinate where the text starts. +- `y` (number): The y-coordinate where the text starts. + +**Returns**: `void` + +--- + +### `width()` + +**Description**: Returns the width of the display. + +**Returns**: `number`: The width of the display in pixels. + +--- + +### `height()` + +**Description**: Returns the height of the display. + +**Returns**: `number`: The height of the display in pixels. + +--- + +## Keyboard Inputs + +### `getPrevPress()` +**Description**: Return the current state of 'Previous' button; + +**Returns**: `boolean`: Returns `true` if pressed and `false` if not pressed + +--- +### `getSelPress()` +**Description**: Return the current state of 'Select' button; + +**Returns**: `boolean`: Returns `true` if pressed and `false` if not pressed + +--- +### `getNextPress()` +**Description**: Return the current state of 'Next' button; + +**Returns**: `boolean`: Returns `true` if pressed and `false` if not pressed + +--- +### `getKeysPressed()` +**Restriction**: Works only in Cardputer + +**Description**: Returns the current state of the keys pressed on the M5Cardputer. + +**Returns**: `string[]`: An array of strings representing the pressed keys. Possible values include "Delete", "Enter", "Alt", "Tab", "Function", "Option", or the actual key character. + +--- +## ToDo +### Send IR command + +### Send RF command + +### Send BadUSB payload + +### \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 710b97a36..f117f73a1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -63,6 +63,7 @@ lib_deps = SmartRC-CC1101-Driver-Lib=https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib/archive/refs/heads/Bruce.zip h2zero/NimBLE-Arduino@^1.4.0 nrf24/RF24 @ ^1.4.9 + ducktape=https://github.com/bmorcelli/duktape/releases/download/2.7.0-lite/duktape-2.7.0.zip ;https://github.com/eadmaster/rtl_433_ESP [env:m5stack-cplus2] @@ -871,6 +872,130 @@ build_flags = lib_deps = ${common.lib_deps} +[env:m5stack-cores3] +platform = espressif32 +board = m5stack-cores3 +framework = arduino +monitor_speed = 115200 +board_build.partitions = custom_16Mb.csv +board_upload.flash_size = 16MB +board_upload.maximum_size = 16777216 +build_flags = + ${common.build_flags} + -DCORE_DEBUG_LEVEL=5 + -DARDUINO_USB_CDC_ON_BOOT=1 + + -DM5STACK=1 ;key for new device, + -DCORES3=1 ;mykeyboard.cpp: need map buttons an/or touchscreen, + ;display.cpp: need map battery status value, + ;settings.cpp: need map brighness control + ;main.cpp: need set startup + ;serialcmds.cpp: need set power off command + + ;Features Enabled + ;FM Radio + ;-DFM_SI4713=1 ;Uncomment to activate FM Radio using Adafruit Si4713 + ;-DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility + + ;Microphone + ;-DMIC_SPM1423=1 ;uncomment to enable Applicable for SPM1423 device + -DPIN_CLK=-1 + -DI2S_SCLK_PIN=-1 + -DI2S_DATA_PIN=-1 + -DPIN_DATA=-1 + + ;RGB LED runned by xylopyrographer/LiteLED@^1.2.0 library + ;-DHAS_RGB_LED=1 ;uncomment to enable + -DRGB_LED=-1 + + ;Have RTC Chip + -DHAS_RTC=1 + + ;Speaker to run music, compatible with NS4168 + ;-DHAS_NS4168_SPKR=1 ;uncomment to enable + -DBCLK=-1 + -DWCLK=-1 + -DDOUT=-1 + + ;Can run USB as HID + -DUSB_as_HID=1 ;uncomment to enable + + ;Battery ADC read pin + ;-DBAT_PIN=10 + + ;Buttons configuration + ;-DHAS_BTN=1 + -DBTN_ALIAS='"Ok"' + -DBTN_PIN=-1 + -DBTN_ACT=LOw + + ;Touchscreen Config + -DHAS_TOUCH=1 + + -DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins + + ;Infrared Led default pin and state + -DIR_TX_PINS='{{"M5 IR Mod", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + -DIR_RX_PINS='{{"M5 IR Mod", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + -DLED=GROVE_SDA + -DLED_ON=HIGH + -DLED_OFF=LOW + + ;Radio Frequency (one pin modules) pin setting + -DRF_TX_PINS='{{"M5 RF433T", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + -DRF_RX_PINS='{{"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' + + ;Font sizes, depending on device + -DFP=1 + -DFM=2 + -DFG=3 + + ;Screen Setup + -DHAS_SCREEN=1 + -DROTATION=1 + -DWIDTH=320 + -DHEIGHT=220 ;240 - 50 for bottom margin + ;-DBACKLIGHT=38 + ;-DMINBRIGHT=160 + + ;TFT_eSPI Setup + -DUSER_SETUP_LOADED=1 + -DILI9341_DRIVER=1 + -DTFT_INVERSION_ON=1 + -DM5STACK=1 + -DTFT_MOSI=23 + -DTFT_SCLK=18 + -DTFT_CS=5 + -DTFT_DC=15 + -DTFT_RST=-1 + -DTFT_BL=-1 + -DTOUCH_CS=-1 + -DSMOOTH_FONT=1 + -DSPI_FREQUENCY=20000000 + -DSPI_READ_FREQUENCY=20000000 + -DSPI_TOUCH_FREQUENCY=2500000 + + ;SD Card Setup pins + -DSDCARD_CS=4 + -DSDCARD_SCK=18 + -DSDCARD_MISO=38 + -DSDCARD_MOSI=23 + + ;Default I2C port + -DGROVE_SDA=32 + -DGROVE_SCL=33 + +lib_deps = + ${common.lib_deps} + + + + + + + + + #New device model [env:NewDeviceModel] platform = espressif32 @@ -1001,120 +1126,4 @@ build_flags = lib_deps = ${common.lib_deps} - xylopyrographer/LiteLED@^1.2.0 - -[env:m5stack-cores3] -platform = espressif32 -board = m5stack-cores3 -framework = arduino -monitor_speed = 115200 -board_build.partitions = custom_16Mb.csv -board_upload.flash_size = 16MB -board_upload.maximum_size = 16777216 -build_flags = - ${common.build_flags} - -DCORE_DEBUG_LEVEL=5 - -DARDUINO_USB_CDC_ON_BOOT=1 - - -DM5STACK=1 ;key for new device, - ;mykeyboard.cpp: need map buttons an/or touchscreen, - ;display.cpp: need map battery status value, - ;settings.cpp: need map brighness control - ;main.cpp: need set startup - ;serialcmds.cpp: need set power off command - - ;Features Enabled - ;FM Radio - ;-DFM_SI4713=1 ;Uncomment to activate FM Radio using Adafruit Si4713 - ;-DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility - - ;Microphone - ;-DMIC_SPM1423=1 ;uncomment to enable Applicable for SPM1423 device - -DPIN_CLK=-1 - -DI2S_SCLK_PIN=-1 - -DI2S_DATA_PIN=-1 - -DPIN_DATA=-1 - - ;RGB LED runned by xylopyrographer/LiteLED@^1.2.0 library - ;-DHAS_RGB_LED=1 ;uncomment to enable - -DRGB_LED=-1 - - ;Have RTC Chip - -DHAS_RTC=1 - - ;Speaker to run music, compatible with NS4168 - ;-DHAS_NS4168_SPKR=1 ;uncomment to enable - -DBCLK=-1 - -DWCLK=-1 - -DDOUT=-1 - - ;Can run USB as HID - -DUSB_as_HID=1 ;uncomment to enable - - ;Battery ADC read pin - ;-DBAT_PIN=10 - - ;Buttons configuration - ;-DHAS_BTN=1 - -DBTN_ALIAS='"Ok"' - -DBTN_PIN=-1 - -DBTN_ACT=LOw - - ;Touchscreen Config - -DHAS_TOUCH=1 - - -DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins - - ;Infrared Led default pin and state - -DIR_TX_PINS='{{"M5 IR Mod", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - -DIR_RX_PINS='{{"M5 IR Mod", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - -DLED=GROVE_SDA - -DLED_ON=HIGH - -DLED_OFF=LOW - - ;Radio Frequency (one pin modules) pin setting - -DRF_TX_PINS='{{"M5 RF433T", GROVE_SDA}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - -DRF_RX_PINS='{{"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' - - ;Font sizes, depending on device - -DFP=1 - -DFM=2 - -DFG=3 - - ;Screen Setup - -DHAS_SCREEN=1 - -DROTATION=1 - -DWIDTH=320 - -DHEIGHT=220 ;240 - 50 for bottom margin - ;-DBACKLIGHT=38 - ;-DMINBRIGHT=160 - - ;TFT_eSPI Setup - -DUSER_SETUP_LOADED=1 - -DILI9341_DRIVER=1 - -DTFT_INVERSION_ON=1 - -DM5STACK=1 - -DTFT_MOSI=23 - -DTFT_SCLK=18 - -DTFT_CS=5 - -DTFT_DC=15 - -DTFT_RST=-1 - -DTFT_BL=-1 - -DTOUCH_CS=-1 - -DSMOOTH_FONT=1 - -DSPI_FREQUENCY=20000000 - -DSPI_READ_FREQUENCY=20000000 - -DSPI_TOUCH_FREQUENCY=2500000 - - ;SD Card Setup pins - -DSDCARD_CS=4 - -DSDCARD_SCK=18 - -DSDCARD_MISO=38 - -DSDCARD_MOSI=23 - - ;Default I2C port - -DGROVE_SDA=32 - -DGROVE_SCL=33 - -lib_deps = - ${common.lib_deps} + xylopyrographer/LiteLED@^1.2.0 \ No newline at end of file diff --git a/sd_files/interpreter/Example1.js b/sd_files/interpreter/Example1.js new file mode 100644 index 000000000..8c75f6566 --- /dev/null +++ b/sd_files/interpreter/Example1.js @@ -0,0 +1,67 @@ +var screenWidth = width(); +var screenHeight = height(); +var totalDelay = 400; +var delayTime = totalDelay; +var time = now(); +var prevTime = now(); +var battery = 0; +var board=""; +var redraw=false; +setTextSize(2); +battery = getBattery(); +board = getBoard(); + +function updateDelayTime() { + var timePassed = time - prevTime; + if (timePassed == 0) { + time = now(); + return; + } + prevTime = time; + time = now(); + delayTime -= timePassed; +}; + +function updateBtn() { + if(getSelPress() && getNextPress()) { + drawFillRect(0, 0, screenWidth, screenHeight, color(255, 0, 0)); + setTextColor(color(0,0,0)); + drawString("Exiting", screenWidth / 2 - 60, screenHeight / 2 - 10); + delay(3000); + throw new Error("Exit"); + } + if(getPrevPress()) { + setTextColor(color(255,0,0)); + drawFillRect(0, 0, screenWidth, screenHeight, color(0, 0, 0)); + drawString("Prev Btn Pressed ", 10, screenHeight/2-8); + redraw=true; + } + if(getSelPress()) { + setTextColor(color(0,255,0)); + drawFillRect(0, 0, screenWidth, screenHeight, color(0, 0, 0)); + drawString("Selec Btn Pressed", 10, screenHeight/2-8); + redraw=true; + } + if(getNextPress()) { + setTextColor(color(0,0,255)); + drawFillRect(0, 0, screenWidth, screenHeight, color(0, 0, 0)); + drawString("Next Btn Pressed ", 10, screenHeight/2-8); + redraw=true; + } + if(redraw==true) { + battery = getBattery(); + drawString("Battery level: " + battery, 10, 10); + drawString("Board: " + board, 10, 27); + drawString("Sel + Next to Exit", 10, screenHeight-22); + drawRect(5,5,screenWidth-10, screenHeight-10, color(150,20,210)); + delay(200); + redraw=false; + } + +} + + +while (true) { + updateDelayTime(); + updateBtn(); +} \ No newline at end of file diff --git a/sd_files/interpreter/Snake_Cardputer.js b/sd_files/interpreter/Snake_Cardputer.js new file mode 100644 index 000000000..a3c12350d --- /dev/null +++ b/sd_files/interpreter/Snake_Cardputer.js @@ -0,0 +1,154 @@ +// Snake Example + +var screenWidth = width(); +var screenHeight = height(); +var cBG = color(0, 0, 0); +var cSnake = color(150, 150, 255); +var cApple = color(120, 255, 120); +var gridSize = 8; +var headX = 4; +var headY = 4; +var appleX = 8; +var appleY = 4; +var headDir = 3; // 0 = up, 1 = down, 2 = left, 3 = right +var totalDelay = 400; +var delayTime = totalDelay; +var tails = []; +var canMove = true; +var time = now(); +var prevTime = now(); +tails.push([headX, headY]); + +setTextSize(2); +drawFillRect(headX * gridSize, headY * gridSize, gridSize, gridSize, cSnake); +drawFillRect(appleX * gridSize, appleY * gridSize, gridSize, gridSize, cApple); + +function gameOver() { + drawFillRect(0, 0, screenWidth, screenHeight, color(255, 0, 0)); + setTextColor(cBG); + drawString("Game Over", screenWidth / 2 - 60, screenHeight / 2 - 10); + delay(3000); + throw new Error("Game Over"); +}; + +function updateTails() { + if (tails.length > 0) { + var lastTail = tails.pop(); + drawFillRect(lastTail[0] * gridSize, lastTail[1] * gridSize, gridSize, gridSize, cBG); + tails.unshift([headX, headY]); + + for (var i = 0; i < tails.length; i++) { + drawRect(tails[i][0] * gridSize + 1, tails[i][1] * gridSize + 1, gridSize - 2, gridSize - 2, cSnake); + } + } +}; + +function updateDelayTime() { + var timePassed = time - prevTime; + if (timePassed == 0) { + time = now(); + return; + } + prevTime = time; + time = now(); + delayTime -= timePassed; +}; + +function isOnSnake(x, y) { + if (headX === x && headY === y) { + return true; + } + for (var i = 0; i < tails.length; i++) { + if (tails[i][0] === x && tails[i][1] === y) { + return true; + } + } + return false; +} + +function updateSnake() { + if (canMove) { + switch (getKeysPressed()[0]) { + case ";": + if (headDir !== 1) { + headDir = 0; + canMove = false; + } + break; + case ".": + if (headDir !== 0) { + headDir = 1; + canMove = false; + } + break; + case ",": + if (headDir !== 3) { + headDir = 2; + canMove = false; + } + break; + case "/": + if (headDir !== 2) { + headDir = 3; + canMove = false; + } + break; + } + } + + if (delayTime < 0) { + canMove = true; + var prevX = headX; + var prevY = headY; + + switch (headDir) { + case 0: + headY -= 1; + break; + case 1: + headY += 1; + break; + case 2: + headX -= 1; + break; + case 3: + headX += 1; + break + } + + if (headX !== prevX || headY !== prevY) { + drawFillRect(prevX * gridSize, prevY * gridSize, gridSize, gridSize, cBG); + drawFillRect(headX * gridSize, headY * gridSize, gridSize, gridSize, cSnake); + } + + if (headX === appleX && headY === appleY) { + do { + appleX = Math.floor(Math.random() * (screenWidth / gridSize)); + appleY = Math.floor(Math.random() * (screenHeight / gridSize)); + } while (isOnSnake(appleX, appleY)); + drawFillRect(appleX * gridSize, appleY * gridSize, gridSize, gridSize, cApple); + tails.push([prevX, prevY]); + totalDelay -= 10; + } + + updateTails(); + + if (headX < 0 || headX >= screenWidth / gridSize || headY < 0 || headY >= screenHeight / gridSize) { + gameOver(); + } + + for (var i = 1; i < tails.length; i++) { + if (headX === tails[i][0] && headY === tails[i][1]) { + gameOver(); + } + } + + delayTime = totalDelay; + } +} + + +while (true) { + updateDelayTime(); + updateSnake(); +} \ No newline at end of file diff --git a/sd_files/interpreter/Snake_Stick_CoreS3.js b/sd_files/interpreter/Snake_Stick_CoreS3.js new file mode 100644 index 000000000..26c0c20d0 --- /dev/null +++ b/sd_files/interpreter/Snake_Stick_CoreS3.js @@ -0,0 +1,143 @@ +// Snake Example + +var screenWidth = width(); +var screenHeight = height(); +var cBG = color(0, 0, 0); +var cSnake = color(150, 150, 255); +var cApple = color(120, 255, 120); +var gridSize = 8; +var headX = 4; +var headY = 4; +var appleX = 8; +var appleY = 4; +var headDir = 3; // 0 = up, 1 = down, 2 = left, 3 = right +var totalDelay = 400; +var delayTime = totalDelay; +var tails = []; +var canMove = true; +var time = now(); +var prevTime = now(); +tails.push([headX, headY]); + +setTextSize(2); +drawFillRect(headX * gridSize, headY * gridSize, gridSize, gridSize, cSnake); +drawFillRect(appleX * gridSize, appleY * gridSize, gridSize, gridSize, cApple); + +function gameOver() { + drawFillRect(0, 0, screenWidth, screenHeight, color(255, 0, 0)); + setTextColor(cBG); + drawString("Game Over", screenWidth / 2 - 60, screenHeight / 2 - 10); + delay(3000); + throw new Error("Game Over"); +}; + +function updateTails() { + if (tails.length > 0) { + var lastTail = tails.pop(); + drawFillRect(lastTail[0] * gridSize, lastTail[1] * gridSize, gridSize, gridSize, cBG); + tails.unshift([headX, headY]); + + for (var i = 0; i < tails.length; i++) { + drawRect(tails[i][0] * gridSize + 1, tails[i][1] * gridSize + 1, gridSize - 2, gridSize - 2, cSnake); + } + } +}; + +function updateDelayTime() { + var timePassed = time - prevTime; + if (timePassed == 0) { + time = now(); + return; + } + prevTime = time; + time = now(); + delayTime -= timePassed; +}; + +function isOnSnake(x, y) { + if (headX === x && headY === y) { + return true; + } + for (var i = 0; i < tails.length; i++) { + if (tails[i][0] === x && tails[i][1] === y) { + return true; + } + } + return false; +} + +function updateSnake() { + if (canMove) { + // 0 = up, 1 = down, 2 = left, 3 = right + if(getSelPress()) { // clockwise + if(headDir==0) headDir=3; + else if(headDir==3) headDir=1; + else if(headDir==1) headDir=2; + else if(headDir==2) headDir=0; + canMove = false; + } + if(getNextPress()) { // Anti-Clockwise + if(headDir==0) headDir=2; + else if(headDir==2) headDir=1; + else if(headDir==1) headDir=3; + else if(headDir==3) headDir=0; + canMove=false; + } + } + + if (delayTime < 0) { + canMove = true; + var prevX = headX; + var prevY = headY; + + switch (headDir) { + case 0: + headY -= 1; + break; + case 1: + headY += 1; + break; + case 2: + headX -= 1; + break; + case 3: + headX += 1; + break + } + + if (headX !== prevX || headY !== prevY) { + drawFillRect(prevX * gridSize, prevY * gridSize, gridSize, gridSize, cBG); + drawFillRect(headX * gridSize, headY * gridSize, gridSize, gridSize, cSnake); + } + + if (headX === appleX && headY === appleY) { + do { + appleX = Math.floor(Math.random() * (screenWidth / gridSize)); + appleY = Math.floor(Math.random() * (screenHeight / gridSize)); + } while (isOnSnake(appleX, appleY)); + drawFillRect(appleX * gridSize, appleY * gridSize, gridSize, gridSize, cApple); + tails.push([prevX, prevY]); + totalDelay -= 10; + } + + updateTails(); + + if (headX < 0 || headX >= screenWidth / gridSize || headY < 0 || headY >= screenHeight / gridSize) { + gameOver(); + } + + for (var i = 1; i < tails.length; i++) { + if (headX === tails[i][0] && headY === tails[i][1]) { + gameOver(); + } + } + + delayTime = totalDelay; + } +} + + +while (true) { + updateDelayTime(); + updateSnake(); +} \ No newline at end of file diff --git a/src/core/globals.h b/src/core/globals.h index f15424bd1..e0ef4c76d 100644 --- a/src/core/globals.h +++ b/src/core/globals.h @@ -59,8 +59,13 @@ extern char16_t FGCOLOR; extern SerialDisplayClass& draw; #endif +extern bool interpreter_start; + extern char timeStr[10]; extern SPIClass sdcardSPI; +#if defined(STICK_C_PLUS) || defined(STICK_C_PLUS2) +extern SPIClass CC_NRF_SPI; +#endif extern bool clock_set; extern time_t localTime; extern struct tm* timeInfo; diff --git a/src/core/main_menu.cpp b/src/core/main_menu.cpp index 0edce6429..ab44471c6 100644 --- a/src/core/main_menu.cpp +++ b/src/core/main_menu.cpp @@ -28,6 +28,7 @@ #include "modules/wifi/wifi_atks.h" #include "modules/wifi/wardriving.h" #include "modules/fm/fm.h" +#include "modules/bjs_interpreter/interpreter.h" #ifdef USB_as_HID #include "modules/others/bad_usb.h" @@ -251,6 +252,9 @@ void otherOptions(){ #ifndef LITE_VERSION {"Openhaystack", [=]() { openhaystack_setup(); }}, #endif + #if !defined(CORE) && !defined(CORE2) + {"Interpreter", [=]() { run_bjs_script(); }}, + #endif {"Main Menu", [=]() { backToMenu(); }}, }; delay(200); diff --git a/src/main.cpp b/src/main.cpp index 968c59b42..a477de34f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,11 @@ #include "esp32-hal-psram.h" + SPIClass sdcardSPI; +#if defined(STICK_C_PLUS) || defined(STICK_C_PLUS2) +SPIClass CC_NRF_SPI; +#endif // Public Globals Variables unsigned long previousMillis = millis(); int prog_handler; // 0 - Flash, 1 - LittleFS, 3 - Download @@ -25,6 +29,7 @@ int dimmerSet; int bright=100; int tmz=3; int devMode=0; +bool interpreter_start = false; bool sdcardMounted = false; bool gpsConnected = false; bool wifiConnected = false; @@ -84,7 +89,7 @@ uint8_t buff[4096] = {0}; #include "core/serialcmds.h" #include "modules/others/audio.h" // for playAudioFile #include "modules/rf/rf.h" // for initCC1101once - +#include "modules/bjs_interpreter/interpreter.h" // for JavaScript interpreter /********************************************************************* ** Function: setup_gpio @@ -346,11 +351,21 @@ void loop() { int index = 0; int opt = 9; + // Interpreter must be ran in the loop() function, otherwise it breaks + // called by 'stack canary watchpoint triggered (loopTask)' +#if !defined(CORE) && !defined(CORE2) + if(interpreter_start) { + interpreter(); + previousMillis = millis(); // ensure that will not dim screen when get back to menu + goto END; + } +#endif tft.fillRect(0,0,WIDTH,HEIGHT,BGCOLOR); getConfigs(); while(1){ + if(interpreter_start) goto END; if (returnToMenu) { returnToMenu = false; tft.fillScreen(BGCOLOR); //fix any problem with the mainMenu screen when coming back from submenus or functions @@ -405,6 +420,8 @@ void loop() { tft.print("BRUCE " + String(BRUCE_VERSION)); } } + END: + delay(1); } #else diff --git a/src/modules/bjs_interpreter/interpreter.cpp b/src/modules/bjs_interpreter/interpreter.cpp new file mode 100644 index 000000000..101ae5d41 --- /dev/null +++ b/src/modules/bjs_interpreter/interpreter.cpp @@ -0,0 +1,409 @@ +#include "interpreter.h" +#include "core/sd_functions.h" +#include "core/wifi_common.h" +#include "core/mykeyboard.h" + + +String headers[20]; +String script = "drawString('Something wrong.', 4, 4);"; +HTTPClient http; + +#ifdef CARDPUTER + Keyboard_Class kb; +#endif + + +static duk_ret_t native_load(duk_context *ctx) { + script = duk_to_string(ctx, 0); + return 0; +} + +static duk_ret_t native_print(duk_context *ctx) { + Serial.print(duk_to_string(ctx, 0)); + return 0; +} + +static duk_ret_t native_now(duk_context *ctx) { + using namespace std::chrono; + auto now = high_resolution_clock::now(); + auto duration = now.time_since_epoch(); + auto millis = duration_cast(duration).count(); + duk_push_number(ctx, static_cast(millis)); + return 1; // Return 1 value (the timestamp) to JavaScript +} + +static duk_ret_t native_delay(duk_context *ctx) { + delay(duk_to_number(ctx, 0)); + return 0; +} + +// Hardware GPIO interactions +static duk_ret_t native_digitalWrite(duk_context *ctx) { + digitalWrite(duk_to_number(ctx, 0),duk_to_boolean(ctx, 1)); + return 0; +} + +static duk_ret_t native_pinMode(duk_context *ctx) { + pinMode(duk_to_number(ctx, 0),duk_to_number(ctx, 1)); + return 0; +} +// Get information from the board; +static duk_ret_t native_getBattery(duk_context *ctx) { + int bat = getBattery(); + duk_push_int(ctx, bat); + return 1; +} +static duk_ret_t native_getBoard(duk_context *ctx) { + String board = "Undefined"; +#if defined(STICK_C_PLUS) + board = "StickCPlus"; +#endif +#if defined(STICK_C_PLUS2) + board = "StickCPlus2"; +#endif +#if defined(CARDPUTER) + board = "Cardputer"; +#endif +#if defined(CORE2) + board = "Core2"; +#endif +#if defined(CORE) + board = "Core"; +#endif +#if defined(CORES3) + board = "CoreS3/SE"; +#endif + duk_push_string(ctx, board.c_str()); + return 1; +} + +// Wifi Functions +static duk_ret_t native_wifiConnect(duk_context *ctx) { + wifiConnectMenu(); + return 0; +} +static duk_ret_t native_wifiDisconnect(duk_context *ctx) { + wifiDisconnect(); + return 0; +} +static duk_ret_t native_get(duk_context *ctx) { + duk_idx_t obj_idx; + if(WiFi.status() != WL_CONNECTED) wifiConnectMenu(); + + if(WiFi.status()== WL_CONNECTED){ + // Your Domain name with URL path or IP address with path + http.begin(duk_to_string(ctx, 0)); + + // Add Headers if headers are included. + if (duk_is_array(ctx, 1)) { + // Get the length of the array + duk_uint_t len = duk_get_length(ctx, 1); + for (duk_uint_t i = 0; i < len; i++) { + // Get each element in the array + duk_get_prop_index(ctx, 1, i); + + // Ensure it's a string + if (!duk_is_string(ctx, -1)) { + duk_pop(ctx); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Header array elements must be strings."); + } + + // Get the string + const char *headerKey = duk_get_string(ctx, -1); + duk_pop(ctx); + i++; + duk_get_prop_index(ctx, 1, i); + + // Ensure it's a string + if (!duk_is_string(ctx, -1)) { + duk_pop(ctx); + duk_error(ctx, DUK_ERR_TYPE_ERROR, "Header array elements must be strings."); + } + + // Get the string + const char *headerValue = duk_get_string(ctx, -1); + duk_pop(ctx); + http.addHeader(headerKey, headerValue); + } + } + + // Send HTTP GET request + int httpResponseCode = http.GET(); + + if (httpResponseCode>0) { + String payload = http.getString(); + + obj_idx = duk_push_object(ctx); + duk_push_int(ctx, httpResponseCode); + duk_put_prop_string(ctx, obj_idx, "response"); + duk_push_string(ctx, payload.c_str()); + duk_put_prop_string(ctx, obj_idx, "body"); + + } + else { + String errorMessage = "Error Response"; + obj_idx = duk_push_object(ctx); + duk_push_int(ctx, 0); + duk_put_prop_string(ctx, obj_idx, "response"); + duk_push_string(ctx, errorMessage.c_str()); + duk_put_prop_string(ctx, obj_idx, "body"); + } + // Free resources + http.end(); + } + else { + String noWifiMessage = "WIFI Not Connected"; + obj_idx = duk_push_object(ctx); + duk_push_int(ctx, 0); + duk_put_prop_string(ctx, obj_idx, "response"); + duk_push_string(ctx, noWifiMessage.c_str()); + duk_put_prop_string(ctx, obj_idx, "body"); + } + return 1; +} + + +// TFT display functions + +static duk_ret_t native_color(duk_context *ctx) { + int color = tft.color565(duk_to_int(ctx, 0),duk_to_int(ctx, 1),duk_to_int(ctx, 2)); + duk_push_int(ctx, color); + return 1; +} + +static duk_ret_t native_setTextColor(duk_context *ctx) { + tft.setTextColor(duk_to_int(ctx, 0)); + return 0; +} + +static duk_ret_t native_setTextSize(duk_context *ctx) { + tft.setTextSize(duk_to_number(ctx, 0)); + return 0; +} + +static duk_ret_t native_drawRect(duk_context *ctx) { + tft.drawRect(duk_to_int(ctx, 0),duk_to_int(ctx, 1),duk_to_int(ctx, 2),duk_to_int(ctx, 3),duk_to_int(ctx, 4)); + return 0; +} + +static duk_ret_t native_drawFillRect(duk_context *ctx) { + tft.fillRect(duk_to_int(ctx, 0),duk_to_int(ctx, 1),duk_to_int(ctx, 2),duk_to_int(ctx, 3),duk_to_int(ctx, 4)); + return 0; +} + +static duk_ret_t native_drawString(duk_context *ctx) { + tft.drawString(duk_to_string(ctx, 0),duk_to_int(ctx, 1),duk_to_int(ctx, 2)); + return 0; +} + +static duk_ret_t native_width(duk_context *ctx) { + int width = tft.width(); + duk_push_int(ctx, width); + return 1; +} + +static duk_ret_t native_height(duk_context *ctx) { + int height = tft.height(); + duk_push_int(ctx, height); + return 1; +} + +// Input functions + +static duk_ret_t native_getPrevPress(duk_context *ctx) { + if(checkPrevPress()) duk_push_boolean(ctx, true); + else duk_push_boolean(ctx, false); + return 1; +} +static duk_ret_t native_getSelPress(duk_context *ctx) { + if(checkSelPress()) duk_push_boolean(ctx, true); + else duk_push_boolean(ctx, false); + return 1; +} +static duk_ret_t native_getNextPress(duk_context *ctx) { + if(checkNextPress()) duk_push_boolean(ctx, true); + else duk_push_boolean(ctx, false); + return 1; +} + +static duk_ret_t native_getKeysPressed(duk_context *ctx) { +#ifdef CARDPUTER + // Create a new array on the stack + duk_push_array(ctx); + + kb.update(); + if (kb.isChange()) { + if (kb.isPressed()) { + Keyboard_Class::KeysState status = kb.keysState(); + int arrayIndex = 0; + for (auto i : status.word) { + char str[2] = { i, '\0' }; + duk_push_string(ctx, str); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.del) { + duk_push_string(ctx, "Delete"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.enter) { + duk_push_string(ctx, "Enter"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.alt) { + duk_push_string(ctx, "Alt"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.tab) { + duk_push_string(ctx, "Tab"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.fn) { + duk_push_string(ctx, "Function"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + + if (status.opt) { + duk_push_string(ctx, "Option"); + duk_put_prop_index(ctx, -2, arrayIndex); + arrayIndex++; + } + } + } +#endif + return 1; +} + +// Read script file +String readScriptFile(FS fs, String filename) { + String fileError = "drawString('No boot.js file.', 4, 4);"; + + File file = fs.open(filename); + if (!file) { + return fileError; + } + + String s; + Serial.println("Read from file"); + while (file.available()) { + s += (char)file.read(); + } + file.close(); + Serial.println("loaded file:"); + Serial.println(s); + return s; +} +// Code interpreter, must be called in the loop() function to work +void interpreter() { + if(!checkPrevPress() && !checkNextPress()) interpreter_start=false; + tft.fillRect(0,0,WIDTH,HEIGHT,TFT_BLACK); + tft.setRotation(rotation); + tft.setTextSize(FM); + tft.setTextColor(TFT_WHITE); + // Create context. + duk_context *ctx = duk_create_heap_default(); + + // Add native functions to context. + duk_push_c_function(ctx, native_load, 1); + duk_put_global_string(ctx, "load"); + duk_push_c_function(ctx, native_print, 1); + duk_put_global_string(ctx, "print"); + duk_push_c_function(ctx, native_now, 0); + duk_put_global_string(ctx, "now"); + duk_push_c_function(ctx, native_delay, 1); + duk_put_global_string(ctx, "delay"); + duk_push_c_function(ctx, native_digitalWrite, 2); + duk_put_global_string(ctx, "digitalWrite"); + duk_push_c_function(ctx, native_pinMode, 2); + duk_put_global_string(ctx, "pinMode"); + + // Get Informations from the board + duk_push_c_function(ctx, native_getBattery, 0); + duk_put_global_string(ctx, "getBattery"); + duk_push_c_function(ctx, native_getBoard, 0); + duk_put_global_string(ctx, "getBoard"); + + + // Networking + duk_push_c_function(ctx, native_wifiConnect, 0); + duk_put_global_string(ctx, "wifiConnect"); + duk_push_c_function(ctx, native_wifiDisconnect, 0); + duk_put_global_string(ctx, "wifiDisconnect"); + duk_push_c_function(ctx, native_get, 2); + duk_put_global_string(ctx, "httpGet"); + + // Graphics + duk_push_c_function(ctx, native_color, 3); + duk_put_global_string(ctx, "color"); + duk_push_c_function(ctx, native_setTextColor, 1); + duk_put_global_string(ctx, "setTextColor"); + duk_push_c_function(ctx, native_setTextSize, 1); + duk_put_global_string(ctx, "setTextSize"); + duk_push_c_function(ctx, native_drawRect, 5); + duk_put_global_string(ctx, "drawRect"); + duk_push_c_function(ctx, native_drawFillRect, 5); + duk_put_global_string(ctx, "drawFillRect"); + duk_push_c_function(ctx, native_drawString, 3); + duk_put_global_string(ctx, "drawString"); + duk_push_c_function(ctx, native_width, 0); + duk_put_global_string(ctx, "width"); + duk_push_c_function(ctx, native_height, 0); + duk_put_global_string(ctx, "height"); + + // Input + duk_push_c_function(ctx, native_getKeysPressed, 0); // keyboard btns for cardputer (entry) + duk_put_global_string(ctx, "getKeysPressed"); + duk_push_c_function(ctx, native_getPrevPress, 0); // checkPrevPress + duk_put_global_string(ctx, "getPrevPress"); + duk_push_c_function(ctx, native_getSelPress, 0); // checkSelPress + duk_put_global_string(ctx, "getSelPress"); + duk_push_c_function(ctx, native_getNextPress, 0); // checkNextPress + duk_put_global_string(ctx, "getNextPress"); + + duk_push_string(ctx, script.c_str()); + if (duk_peval(ctx) != 0) { + printf("eval failed: %s\n", duk_safe_to_string(ctx, -1)); + } else { + printf("result is: %s\n", duk_safe_to_string(ctx, -1)); + } + duk_pop(ctx); + + // Clean up. + duk_destroy_heap(ctx); + + delay(1000); +} + +// function to start the JS Interpreterm choosinng the file, processing and start +void run_bjs_script() { + String filename; + FS *fs=&LittleFS; + setupSdCard(); + if(sdcardMounted) { + options = { + {"Sd Card", [&](){ fs=&SD; }}, + {"LittleFs", [&](){ fs=&LittleFS; }}, + }; + delay(200); + loopOptions(options); + delay(200); + } + filename = loopSD(*fs,true,"BJS|JS"); + script = readScriptFile(*fs, filename); + + returnToMenu=true; + interpreter_start=true; + + // To stop the script, press Prev and Next together for a few seconds +} + diff --git a/src/modules/bjs_interpreter/interpreter.h b/src/modules/bjs_interpreter/interpreter.h new file mode 100644 index 000000000..eb3cf14b8 --- /dev/null +++ b/src/modules/bjs_interpreter/interpreter.h @@ -0,0 +1,16 @@ +#include "stdio.h" +#include +#include +#include +#include +#include +#include +#include + +// Credits to https://github.com/justinknight93/Doolittle +// This functionality is dedicated to @justinknight93 for providing such a nice example! Consider yourself a part of the team! + + +void run_bjs_script(); + +void interpreter(); \ No newline at end of file diff --git a/src/modules/ble/ble_jammer.cpp b/src/modules/ble/ble_jammer.cpp index 1be953234..fd0eefdab 100644 --- a/src/modules/ble/ble_jammer.cpp +++ b/src/modules/ble/ble_jammer.cpp @@ -10,11 +10,25 @@ ************************************************************************************** */ void ble_jammer() { #if defined(USE_NRF24_VIA_SPI) + #if defined(STICK_C_PLUS) || defined(STICK_C_PLUS2) + CC_NRF_SPI.begin(NRF24_SCK_PIN,NRF24_MISO_PIN,NRF24_MOSI_PIN,NRF24_SS_PIN); + #elif defined(CARDPUTER) || defined(ESP32S3DEVKITC1) sdcardSPI.begin(NRF24_SCK_PIN,NRF24_MISO_PIN,NRF24_MOSI_PIN,NRF24_SS_PIN); + #else + SPI.begin(NRF24_SCK_PIN,NRF24_MISO_PIN,NRF24_MOSI_PIN,NRF24_SS_PIN); + #endif + RF24 radio(NRF24_CE_PIN, NRF24_SS_PIN); ///ce-csn byte hopping_channel[] = {32,34, 46,48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80, 82, 84,86 }; // channel to hop byte ptr_hop = 0; // Pointer to the hopping array - if(radio.begin(&sdcardSPI)) { + #if defined(STICK_C_PLUS) || defined(STICK_C_PLUS2) + if(radio.begin(&CC_NRF_SPI)) + #elif defined(CARDPUTER) || defined(ESP32S3DEVKITC1) + if(radio.begin(&sdcardSPI)) + #else + if(radio.begin(&SPI)) + #endif + { Serial.println("NRF24 turned On"); radio.setPALevel(RF24_PA_MAX); diff --git a/src/modules/rf/rf.cpp b/src/modules/rf/rf.cpp index 434666c00..7c0b55cad 100644 --- a/src/modules/rf/rf.cpp +++ b/src/modules/rf/rf.cpp @@ -28,7 +28,6 @@ #define DISPLAY_WIDTH 240 // Width of the display area #define LINE_WIDTH 2 // Adjust line width as needed - struct RfCodes { uint32_t frequency = 0; uint64_t key=0; @@ -407,7 +406,13 @@ void deinitRfModule() { bool initRfModule(String mode, float frequency) { + #if defined(STICK_C_PLUS) || defined(STICK_C_PLUS2) + initCC1101once(&CC_NRF_SPI); + #elif defined(CARDPUTER) || defined(ESP32S3DEVKITC1) initCC1101once(&sdcardSPI); + #else + initCC1101once(&SPI); + #endif // use default frequency if no one is passed if(!frequency) frequency = RfFreq; From 49d9fb2ca8ce95d4e51817331363dccd2541e366 Mon Sep 17 00:00:00 2001 From: Pirata Date: Sun, 25 Aug 2024 16:24:13 -0300 Subject: [PATCH 2/2] JavaScript Interpreter Added JavaScript Interpreter with some examples. Changed the SPIClass to StickCs to work with SD Card.. need testing --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4124c432a..9caa892d6 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) ## Specific functions per Device, the ones not mentioned here are available to all. | Device | CC1101 | NRF24 | Interpreter | FMRadio | Mic_SPM1423 | BadUSB | RGB Led | Speaker | LITE_MODE | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Cardputer | :ok: | :ok: | :ok: | :x: | :ok: | :ok: | :ok: | NS4168 | :x: | | StickCPlus2 | :ok: | :ok: | :ok: | :ok: | :ok: | :x: | :x: | Tone | :x: | | StickCPlus 1.1 | :ok: | :ok: | :ok: | :x: | :ok: | :x: | :x: | Tone | :ok: |