From 3bfca52623e5b37da721c15dcdcbf13615acc45c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Sat, 14 Dec 2024 16:15:10 +0000 Subject: [PATCH] CYD add Qwiic classes for P1/P3/CN1, invert LEDs and buttons --- boards/ESP32_CYD.py | 13 +++-- boards/JOLTJS.py | 2 +- libs/graphics/lcd_spi_unbuf.c | 25 ++++++--- libs/misc/jswrap_esp32_cyd.c | 77 ++++++++++++++++++++++++++++ libs/misc/jswrap_esp32_cyd.h | 20 ++++++++ libs/{joltjs => misc}/jswrap_qwiic.c | 0 libs/{joltjs => misc}/jswrap_qwiic.h | 0 targets/esp32/jshardware.c | 26 +++++++--- targets/esp32/jshardwareSpi.c | 27 +++++----- 9 files changed, 155 insertions(+), 35 deletions(-) create mode 100644 libs/misc/jswrap_esp32_cyd.c create mode 100644 libs/misc/jswrap_esp32_cyd.h rename libs/{joltjs => misc}/jswrap_qwiic.c (100%) rename libs/{joltjs => misc}/jswrap_qwiic.h (100%) diff --git a/boards/ESP32_CYD.py b/boards/ESP32_CYD.py index 1d05a4dd2b..81dbf15a6b 100755 --- a/boards/ESP32_CYD.py +++ b/boards/ESP32_CYD.py @@ -62,6 +62,7 @@ 'CRYPTO','SHA256','SHA512', 'TLS', 'TELNET', + 'TERMINAL', # 'NEOPIXEL', 'FILESYSTEM', 'BLUETOOTH', @@ -72,7 +73,8 @@ 'DEFINES+=-DESP_STACK_SIZE=25000', 'DEFINES+=-DJSVAR_MALLOC', # Allocate space for variables at jsvInit time 'DEFINES+=-DESPR_GRAPHICS_INTERNAL -DESPR_GRAPHICS_SELF_INIT', # ensure graphics instantiates itself - 'DEFINES+=-DUSE_FONT_6X8 -DSPISENDMANY_BUFFER_SIZE=1600', + 'DEFINES+=-DUSE_FONT_6X8 -DSPISENDMANY_BUFFER_SIZE=1600 -DLCD_SPI_BITRATE=32000000 -DESPR_TERMNINAL_NO_SCROLL', + 'WRAPPERSOURCES += libs/misc/jswrap_esp32_cyd.c libs/misc/jswrap_qwiic.c', 'ESP32_FLASH_MAX=1572864' ] } @@ -99,10 +101,10 @@ }; devices = { #https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display/blob/main/PINS.md - 'LED1' : { 'pin' : 'D4' }, # FIXME swap polarity of LEDs + 'LED1' : { 'pin' : 'D4' }, 'LED2' : { 'pin' : 'D16' }, 'LED3' : { 'pin' : 'D17' }, - 'BTN1' : { 'pin' : 'D0', "inverted":1, 'pinstate' : 'IN_PULLUP' }, # FIXME swap polarity of button + 'BTN1' : { 'pin' : 'D0' }, 'SD' : { 'pin_cs' : 'D5', 'pin_di' : 'D23', 'pin_do' : 'D19', @@ -216,7 +218,10 @@ def get_pins(): pinutils.findpin(pins, "PD25", True)["functions"]["DAC_OUT1"]=0; pinutils.findpin(pins, "PD26", True)["functions"]["DAC_OUT2"]=0; - pinutils.findpin(pins, "PD0", True)["functions"]["LED_1"]=0; + pinutils.findpin(pins, "PD4", True)["functions"]["NEGATED"]=0; # LED + pinutils.findpin(pins, "PD16", True)["functions"]["NEGATED"]=0; + pinutils.findpin(pins, "PD17", True)["functions"]["NEGATED"]=0; + pinutils.findpin(pins, "PD0", True)["functions"]["NEGATED"]=0; # BTN1 pinutils.findpin(pins, "PD10", True)["functions"]["USART0_TX"]=0; pinutils.findpin(pins, "PD16", True)["functions"]["USART2_RX"]=0; diff --git a/boards/JOLTJS.py b/boards/JOLTJS.py index 8f040928dd..9d3e5790ca 100644 --- a/boards/JOLTJS.py +++ b/boards/JOLTJS.py @@ -56,7 +56,7 @@ 'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES -DGRAPHICS_ANTIALIAS -DESPR_PBF_FONTS', 'BOOTLOADER_SETTINGS_FAMILY=NRF52840', 'INCLUDE += -I$(ROOT)/libs/jolt.js', - 'WRAPPERSOURCES += libs/joltjs/jswrap_jolt.c libs/joltjs/jswrap_qwiic.c', + 'WRAPPERSOURCES += libs/joltjs/jswrap_jolt.c libs/misc/jswrap_qwiic.c', 'NRF_SDK15=1', ] } diff --git a/libs/graphics/lcd_spi_unbuf.c b/libs/graphics/lcd_spi_unbuf.c index aa12b50fec..8ea7d6b42b 100644 --- a/libs/graphics/lcd_spi_unbuf.c +++ b/libs/graphics/lcd_spi_unbuf.c @@ -25,10 +25,10 @@ #include "jswrap_graphics.h" #include "jshardware.h" -static int _pin_mosi; -static int _pin_clk; -static int _pin_cs; -static int _pin_dc; +static Pin _pin_mosi; +static Pin _pin_clk; +static Pin _pin_cs; +static Pin _pin_dc; static int _colstart; static int _rowstart; static int _lastx=-1; @@ -79,13 +79,17 @@ void lcdSendInitCmd_SPILCD() { } /// flush chunk buffer to screen -void lcd_flip(JsVar *parent) { +void lcd_flip() { if(_chunk_index == 0) return; jshPinSetValue(_pin_cs, 0); flush_chunk_buffer(); jshPinSetValue(_pin_cs, 1); } +void graphicsInternalFlip() { + lcd_flip(); +} + void jshLCD_SPI_UNBUFInitInfo(JshLCD_SPI_UNBUFInfo *inf) { inf->pinCS = PIN_UNDEFINED; inf->pinDC = PIN_UNDEFINED; @@ -115,7 +119,7 @@ bool jsspiPopulateOptionsInfo( JshLCD_SPI_UNBUFInfo *inf, JsVar *options){ "generate" : "jswrap_lcd_spi_unbuf_idle" }*/ bool jswrap_lcd_spi_unbuf_idle() { - lcd_flip(NULL); + lcd_flip(); return false; } @@ -173,7 +177,7 @@ JsVar *jswrap_lcd_spi_unbuf_connect(JsVar *device, JsVar *options) { // Create 'flip' fn JsVar *fn; - fn = jsvNewNativeFunction((void (*)(void))lcd_flip, JSWAT_VOID|JSWAT_THIS_ARG); + fn = jsvNewNativeFunction((void (*)(void))lcd_flip, JSWAT_VOID); jsvObjectSetChildAndUnLock(parent,"flip",fn); return parent; @@ -241,7 +245,7 @@ void disp_spi_transfer_addrwin(int x1, int y1, int x2, int y2) { } void lcd_spi_unbuf_setPixel(JsGraphics *gfx, int x, int y, unsigned int col) { - uint16_t color = (col>>8) | (col<<8); + uint16_t color = (col>>8) | (col<<8); if (x!=_lastx+1 || y!=_lasty) { jshPinSetValue(_pin_cs, 0); disp_spi_transfer_addrwin(x, y, gfx->data.width, y+1); @@ -272,7 +276,12 @@ void lcd_spi_unbuf_fillRect(JsGraphics *gfx, int x1, int y1, int x2, int y2, uns _lasty=-1; } +void lcd_spi_unbuf_scroll(JsGraphics *gfx, int xdir, int ydir, int x1, int y1, int x2, int y2) { + // don't even try scrolling at the moment - we could maybe adjust display registers but then we have to adjust x/y of any subsequent writes +} + void lcd_spi_unbuf_setCallbacks(JsGraphics *gfx) { gfx->setPixel = lcd_spi_unbuf_setPixel; gfx->fillRect = lcd_spi_unbuf_fillRect; + gfx->scroll = lcd_spi_unbuf_scroll; } diff --git a/libs/misc/jswrap_esp32_cyd.c b/libs/misc/jswrap_esp32_cyd.c new file mode 100644 index 0000000000..c8cb52caca --- /dev/null +++ b/libs/misc/jswrap_esp32_cyd.c @@ -0,0 +1,77 @@ +/* + * This file is part of Espruino, a JavaScript interpreter for Microcontrollers + * + * Copyright (C) 2024 Gordon Williams + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * ---------------------------------------------------------------------------- + * ESP32 CYD (cheap yellow display) implementation + * ---------------------------------------------------------------------------- + */ +#include "jswrap_curio.h" +#include "jshardware.h" +#include "jsparse.h" + +/* DO_NOT_INCLUDE_IN_DOCS - this is a special token for common.py */ + +/*JSON{ + "type" : "variable", + "name" : "CN1", + "generate" : "jswrap_cyd_cn1", + "return" : ["JsVar","An object containing the pins for the CN1 connector"], + "return_object" : "Qwiic" +} +*/ +JsVar *jswrap_cyd_cn1() { + JsVar *o = jspNewObject(0, "Qwiic"); + if (!o) return 0; + jsvObjectSetChildAndUnLock(o, "sda", jsvNewFromPin(QWIIC0_PIN_SDA)); + jsvObjectSetChildAndUnLock(o, "scl", jsvNewFromPin(QWIIC0_PIN_SCL)); + jsvObjectSetChild(execInfo.root, "CN1", o); + return o; +} +/*JSON{ + "type" : "variable", + "name" : "P1", + "generate" : "jswrap_cyd_p1", + "return" : ["JsVar","An object containing the pins for the P1 connector"], + "return_object" : "Qwiic" +} +*/ +JsVar *jswrap_cyd_p1() { + JsVar *o = jspNewObject(0, "Qwiic"); + if (!o) return 0; + jsvObjectSetChildAndUnLock(o, "sda", jsvNewFromPin(QWIIC1_PIN_SDA)); + jsvObjectSetChildAndUnLock(o, "scl", jsvNewFromPin(QWIIC1_PIN_SCL)); + jsvObjectSetChild(execInfo.root, "P1", o); + return o; +} +/*JSON{ + "type" : "variable", + "name" : "P3", + "generate" : "jswrap_cyd_p3", + "return" : ["JsVar","An object containing the pins for the P3 connector"], + "return_object" : "Qwiic" +} +*/ +JsVar *jswrap_cyd_p3() { + JsVar *o = jspNewObject(0, "Qwiic"); + if (!o) return 0; + jsvObjectSetChildAndUnLock(o, "sda", jsvNewFromPin(QWIIC3_PIN_SDA)); + jsvObjectSetChildAndUnLock(o, "scl", jsvNewFromPin(QWIIC3_PIN_SCL)); + jsvObjectSetChildAndUnLock(o, "vcc", jsvNewFromPin(QWIIC3_PIN_VCC)); + jsvObjectSetChild(execInfo.root, "P3", o); + return o; +} + +/*JSON{ + "type" : "init", + "generate" : "jswrap_cyd_init" +}*/ +void jswrap_cyd_init() { + jshPinOutput(LED1_PININDEX,0); // LED1 is glowing by default? + jshPinOutput(LED3_PININDEX,0); // LED3 is on by default? +} diff --git a/libs/misc/jswrap_esp32_cyd.h b/libs/misc/jswrap_esp32_cyd.h new file mode 100644 index 0000000000..acc11f01fc --- /dev/null +++ b/libs/misc/jswrap_esp32_cyd.h @@ -0,0 +1,20 @@ +/* + * This file is part of Espruino, a JavaScript interpreter for Microcontrollers + * + * Copyright (C) 2024 Gordon Williams + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * ---------------------------------------------------------------------------- + * ESP32 CYD (cheap yellow display) + * ---------------------------------------------------------------------------- + */ + +#include "jsvar.h" + +JsVar *jswrap_cyd_cn1(); +JsVar *jswrap_cyd_p1(); +JsVar *jswrap_cyd_p3(); +void jswrap_cyd_init(); diff --git a/libs/joltjs/jswrap_qwiic.c b/libs/misc/jswrap_qwiic.c similarity index 100% rename from libs/joltjs/jswrap_qwiic.c rename to libs/misc/jswrap_qwiic.c diff --git a/libs/joltjs/jswrap_qwiic.h b/libs/misc/jswrap_qwiic.h similarity index 100% rename from libs/joltjs/jswrap_qwiic.h rename to libs/misc/jswrap_qwiic.h diff --git a/targets/esp32/jshardware.c b/targets/esp32/jshardware.c index 601340c34f..1343d38634 100644 --- a/targets/esp32/jshardware.c +++ b/targets/esp32/jshardware.c @@ -297,6 +297,7 @@ void jshPinSetState( } gpio_mode_t mode; gpio_pull_mode_t pull_mode=GPIO_FLOATING; + bool negated = pinInfo[pin].port & JSH_PIN_NEGATED; switch(state) { case JSHPINSTATE_GPIO_OUT: mode = GPIO_MODE_INPUT_OUTPUT; @@ -306,18 +307,20 @@ void jshPinSetState( break; case JSHPINSTATE_GPIO_IN_PULLUP: mode = GPIO_MODE_INPUT; - pull_mode=GPIO_PULLUP_ONLY; + pull_mode= negated ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY; break; case JSHPINSTATE_GPIO_IN_PULLDOWN: mode = GPIO_MODE_INPUT; - pull_mode=GPIO_PULLDOWN_ONLY; + pull_mode= negated ? GPIO_PULLUP_ONLY : GPIO_PULLDOWN_ONLY; break; case JSHPINSTATE_GPIO_OUT_OPENDRAIN: mode = GPIO_MODE_INPUT_OUTPUT_OD; + if (negated) jsError( "jshPinSetState: can't do Open Drain on negated pin"); break; - case JSHPINSTATE_GPIO_OUT_OPENDRAIN_PULLUP: + case JSHPINSTATE_GPIO_OUT_OPENDRAIN_PULLUP: // not possible if negated mode = GPIO_MODE_INPUT_OUTPUT_OD; - pull_mode=GPIO_PULLUP_ONLY; + pull_mode= GPIO_PULLUP_ONLY; + if (negated) jsError( "jshPinSetState: can't do Open Drain on negated pin"); break; default: jsError( "jshPinSetState: Unexpected state: %d", state); @@ -361,6 +364,7 @@ void jshPinSetValue( Pin pin, //!< The pin to have its value changed. bool value //!< The new value of the pin. ) { + if (pinInfo[pin].port & JSH_PIN_NEGATED) value=!value; gpio_num_t gpioNum = pinToESP32Pin(pin); #if ESP_IDF_VERSION_MAJOR>=5 gpio_iomux_out(gpioNum,SIG_GPIO_OUT_IDX,0); // reset pin to be GPIO in case it was used as rmt or something else @@ -379,22 +383,27 @@ bool CALLED_FROM_INTERRUPT jshPinGetValue( // can be called at interrupt time Pin pin //!< The pin to have its value read. ) { gpio_num_t gpioNum = pinToESP32Pin(pin); - bool level = gpio_get_level(gpioNum); - return level; + bool value = gpio_get_level(gpioNum); + if (pinInfo[pin].port & JSH_PIN_NEGATED) value=!value; + return value; } JsVarFloat jshPinAnalog(Pin pin) { if (pinInfo[pin].analog == JSH_ANALOG_NONE) return NAN; - return (JsVarFloat) readADC(pin) / 4096; + JsVarFloat v = (JsVarFloat) readADC(pin) / 4096; + if (pinInfo[pin].port & JSH_PIN_NEGATED) v=1-v; + return v; } int jshPinAnalogFast(Pin pin) { if (pinInfo[pin].analog == JSH_ANALOG_NONE) return 0; - return readADC(pin) << 4; + int v = readADC(pin) << 4; + if (pinInfo[pin].port & JSH_PIN_NEGATED) v=65535-v; + return v; } @@ -406,6 +415,7 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used UNUSED(flags); + if (pinInfo[pin].port & JSH_PIN_NEGATED) value=1-value; if (value<0) value=0; if (value>1) value=1; if (!isfinite(freq)) freq=0; diff --git a/targets/esp32/jshardwareSpi.c b/targets/esp32/jshardwareSpi.c index 8d08f48e76..e499a77605 100644 --- a/targets/esp32/jshardwareSpi.c +++ b/targets/esp32/jshardwareSpi.c @@ -116,7 +116,7 @@ void jshSPISetup( mosi = inf->pinMOSI != PIN_UNDEFINED ? inf->pinMOSI : 13; } else { - dma_chan = 2; + dma_chan = 2; sck = inf->pinSCK != PIN_UNDEFINED ? inf->pinSCK : 5; miso = inf->pinMISO != PIN_UNDEFINED ? inf->pinMISO : 19; mosi = inf->pinMOSI != PIN_UNDEFINED ? inf->pinMOSI : 23; @@ -139,9 +139,9 @@ void jshSPISetup( .queue_size=7, //We want to be able to queue 7 transactions at a time .flags=flags }; - if(SPIChannels[channelPnt].spi){ - SPIChannelReset(channelPnt); - jsWarn("spi was already in use, removed old assignment"); + if(SPIChannels[channelPnt].spi) { + SPIChannelReset(channelPnt); + jsWarn("spi was already in use, removed old assignment"); } esp_err_t ret=spi_bus_initialize(SPIChannels[channelPnt].HOST, &buscfg, dma_chan); assert(ret==ESP_OK); @@ -189,20 +189,19 @@ bool jshSPISendMany(IOEventFlags device, unsigned char *tx, unsigned char *rx, s return true; } jshSPIWait(device); - int channelPnt = getSPIChannelPnt(device); + int channelPnt = getSPIChannelPnt(device); esp_err_t ret; - memset(&spi_trans, 0, sizeof(spi_trans)); - spi_trans.length=count*8; - spi_trans.tx_buffer=tx; - spi_trans.rx_buffer=rx; + memset(&spi_trans, 0, sizeof(spi_trans)); + spi_trans.length=count*8; + spi_trans.tx_buffer=tx; + spi_trans.rx_buffer=rx; spi_Sending = true; - ret=spi_device_queue_trans(SPIChannels[channelPnt].spi, &spi_trans, rx?0:portMAX_DELAY); - + ret=spi_device_queue_trans(SPIChannels[channelPnt].spi, &spi_trans, rx?0:portMAX_DELAY); if (ret != ESP_OK) { spi_Sending = false; - jsExceptionHere(JSET_INTERNALERROR, "SPI Send Error %d", ret); - return false; - } + jsExceptionHere(JSET_INTERNALERROR, "SPI Send Error %d", ret); + return false; + } jshSPIWait(device); if(callback)callback(); return true;