From 41a9df2e200090f679ade231e0bae53616356af3 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 5 Nov 2021 11:10:43 +0000 Subject: [PATCH] nRF52: Move neopixel LRCK pin which can't be disabled due to hardware errata, and restore state after (fix #2071) --- ChangeLog | 1 + boards/MDBT42Q.py | 5 +++-- boards/PIXLJS.py | 3 ++- boards/PUCKJS.py | 5 +++-- targets/nrf5x/i2s_ws2812b_drive.c | 37 ++++++++++++++++++++++++++++++- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15550643b..ab5cb4037 100644 --- a/ChangeLog +++ b/ChangeLog @@ -78,6 +78,7 @@ Fix parser errors in arrow functions (fix #2067) Bangle.js2: Add Unistroke object, and 'Bangle.stroke' event Fix pretokenised '1 / /.../' and ensure jslSeek resets the previous token (ref #2086) + nRF52: Move neopixel LRCK pin which can't be disabled due to hardware errata, and restore state after (fix #2071) 2v10 : Bangle.js: Improved HRM calculations - swapped autocorrelation for bandpass filter Bangle.js: Significantly improved step counting algorithm using bandpass filter (fix #1846) diff --git a/boards/MDBT42Q.py b/boards/MDBT42Q.py index 297bb0916..46bbe2f65 100644 --- a/boards/MDBT42Q.py +++ b/boards/MDBT42Q.py @@ -45,7 +45,7 @@ info = { 'DEFINES+=-DNRF_BLE_GATT_MAX_MTU_SIZE=53 -DNRF_BLE_MAX_MTU_SIZE=53', # increase MTU from default of 23 'LDFLAGS += -Xlinker --defsym=LD_APP_RAM_BASE=0x2c40', # set RAM base to match MTU 'DEFINES+=-DBLUETOOTH_NAME_PREFIX=\'"MDBT42Q"\'', - 'DEFINES+=-DNEOPIXEL_SCK_PIN=23', + 'DEFINES+=-DNEOPIXEL_SCK_PIN=23 -DNEOPIXEL_LRCK_PIN=13', # see https://github.com/espruino/Espruino/issues/2071 'DFU_PRIVATE_KEY=targets/nrf5x_dfu/dfu_private_key.pem', 'DFU_SETTINGS=--application-version 0xff --hw-version 52 --sd-req 0x8C,0x91' ] @@ -88,7 +88,8 @@ board_module = { 'bottom' : [ 'GND','D0','D1','D2','D3','D4','D5','D6','D7','D8','D9','D10','GND' ], '_notes' : { 'D21' : "Also NRST if configured", - 'D23' : "This is used as SCK when driving Neopixels with 'require('neopixel').write'. This pin is not accessible.", + 'D13' : "This is used as LRCK when driving Neopixels, and will output a signal when 'require('neopixel').write' is called", + 'D23' : "This is used as SCK when driving Neopixels, and will output a signal when 'require('neopixel').write' is called", } }; diff --git a/boards/PIXLJS.py b/boards/PIXLJS.py index d82be7696..c048a6ffd 100644 --- a/boards/PIXLJS.py +++ b/boards/PIXLJS.py @@ -50,7 +50,7 @@ info = { 'DEFINES+=-DCUSTOM_GETBATTERY=jswrap_pixljs_getBattery', 'DEFINES+=-DNFC_DEFAULT_URL=\'"https://www.espruino.com/ide"\'', 'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'', - 'DEFINES+=-DNEOPIXEL_SCK_PIN=14', + 'DEFINES+=-DNEOPIXEL_SCK_PIN=14 -DNEOPIXEL_LRCK_PIN=15', # see https://github.com/espruino/Espruino/issues/2071 'DFU_PRIVATE_KEY=targets/nrf5x_dfu/dfu_private_key.pem', 'DFU_SETTINGS=--application-version 0xff --hw-version 52 --sd-req 0x8C,0x91', 'INCLUDE += -I$(ROOT)/libs/pixljs', @@ -111,6 +111,7 @@ board = { 'A4' : "Also used for the pin marked SDA", 'A5' : "Also used for the pin marked SCL", 'H8' : "This is used as SCK when driving Neopixels with 'require('neopixel').write'. It will not affect the LCD as CS won't be asserted.", + 'H9' : "This is used as LRCK when driving Neopixels with 'require('neopixel').write'. It will not affect the LCD as CS won't be asserted.", '5V' : "Pixl.js has no 5v rail so this is not connected by default. A solder jumper can be used to connect it to Vin or 3.3v" } }; diff --git a/boards/PUCKJS.py b/boards/PUCKJS.py index 1698e5bae..e543a5a26 100644 --- a/boards/PUCKJS.py +++ b/boards/PUCKJS.py @@ -42,7 +42,7 @@ info = { 'DEFINES+=-DHAL_NFC_ENGINEERING_BC_FTPAN_WORKAROUND=1', # Looks like proper production nRF52s had this issue # 'DEFINES+=-DCONFIG_GPIO_AS_PINRESET', # reset isn't being used, so let's just have an extra IO (needed for Puck.js V2) 'DEFINES+=-DESPR_DCDC_ENABLE', # Ensure DCDC converter is enabled - 'DEFINES += -DNEOPIXEL_SCK_PIN=22', # SCK pin needs defining as something unused for neopixel (HW errata means they can't be disabled) + 'DEFINES += -DNEOPIXEL_SCK_PIN=22 -DNEOPIXEL_LRCK_PIN=16', # SCK pin needs defining as something unused for neopixel (HW errata means they can't be disabled) see https://github.com/espruino/Espruino/issues/2071 'DEFINES+=-DNRF_BLE_GATT_MAX_MTU_SIZE=53 -DNRF_BLE_MAX_MTU_SIZE=53', # increase MTU from default of 23 'LDFLAGS += -Xlinker --defsym=LD_APP_RAM_BASE=0x2c40', # set RAM base to match MTU 'DEFINES+=-DBLUETOOTH_NAME_PREFIX=\'"Puck.js"\'', @@ -122,7 +122,8 @@ board = { '_notes' : { 'D11' : "Capacitive sense. D12 is connected to this pin via a 1 MOhm resistor", 'D28' : "If pulled up to 1 on startup, D28 and D29 become Serial1", - 'D22' : "This is used as SCK when driving Neopixels with 'require('neopixel').write'" + 'D22' : "This is used as SCK when driving Neopixels, and will output a signal when 'require('neopixel').write' is called", + 'D16' : "This is used as LRCK when driving Neopixels, and will output a signal when 'require('neopixel').write' is called" } }; diff --git a/targets/nrf5x/i2s_ws2812b_drive.c b/targets/nrf5x/i2s_ws2812b_drive.c index 22969ce57..75aa3a576 100644 --- a/targets/nrf5x/i2s_ws2812b_drive.c +++ b/targets/nrf5x/i2s_ws2812b_drive.c @@ -9,6 +9,7 @@ #include "i2s_ws2812b_drive.h" #include "app_util_platform.h" #include "nrf_delay.h" +#include "nrf_gpio.h" volatile uint8_t i2s_ws2812b_drive_flag_buffer_cnt = 0; @@ -35,6 +36,26 @@ static void i2s_ws2812b_drive_handler(uint32_t const * p_data_received, ret_code_t i2s_ws2812b_drive_xfer(rgb_led_t *led_array, uint16_t num_leds, uint8_t drive_pin) { ret_code_t err_code; + + // save pin state before +#ifdef NEOPIXEL_SCK_PIN + uint32_t sckPinNumber = NEOPIXEL_SCK_PIN; +#if NRF_SD_BLE_API_VERSION>5 + NRF_GPIO_Type *sckReg = nrf_gpio_pin_port_decode(&sckPinNumber); +#else + NRF_GPIO_Type *sckReg = NRF_GPIO; +#endif + uint32_t sckConf = sckReg->PIN_CNF[sckPinNumber]; +#endif +#ifdef NEOPIXEL_LRCK_PIN + uint32_t lrckPinNumber = NEOPIXEL_LRCK_PIN; +#if NRF_SD_BLE_API_VERSION>5 + NRF_GPIO_Type *lrckReg = nrf_gpio_pin_port_decode(&lrckPinNumber); +#else + NRF_GPIO_Type *lrckReg = NRF_GPIO; +#endif + uint32_t lrckConf = lrckReg->PIN_CNF[lrckPinNumber]; +#endif // define configs nrf_drv_i2s_config_t config; @@ -43,7 +64,7 @@ ret_code_t i2s_ws2812b_drive_xfer(rgb_led_t *led_array, uint16_t num_leds, uint8 #ifdef NEOPIXEL_SCK_PIN config.sck_pin = NEOPIXEL_SCK_PIN; #else - config.sck_pin = 22; + #error "Must define an SCK pin if using neopixels" #endif #ifdef NEOPIXEL_LRCK_PIN // On nRF52840 lrck needs defining too - http://forum.espruino.com/conversations/354468/ @@ -147,6 +168,20 @@ ret_code_t i2s_ws2812b_drive_xfer(rgb_led_t *led_array, uint16_t num_leds, uint8 // un-initialize i2s nrf_drv_i2s_uninit(); + + // I2S not only uses pins when it's not supposed to, it doesn't + // even de-allocate them after so we must do it manually + // https://github.com/espruino/Espruino/issues/2071 + NRF_I2S->PSEL.SCK = NRF_DRV_I2S_PIN_NOT_USED; + NRF_I2S->PSEL.LRCK = NRF_DRV_I2S_PIN_NOT_USED; +#ifdef NEOPIXEL_SCK_PIN + sckReg->PIN_CNF[sckPinNumber] = sckConf; +#endif +#ifdef NEOPIXEL_LRCK_PIN + lrckReg->PIN_CNF[lrckPinNumber] = lrckConf; +#endif + + return NRF_SUCCESS; }