diff --git a/ChangeLog b/ChangeLog index 12cfc59be..90ecd8107 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,7 +21,11 @@ Bangle.js: StorageFile now uses 10x bigger chunks which reduces stress on Storage.list() Storage.list now allows you to specifically request StorageFile, only ever reports first StorageFile chunk Graphics: Allow colors to be specified as '#rgb' strings + Graphics: Antialiased lines now read the background color so overlap nicely + Graphics: Add fillPolyAA and use antialiased vector fonts (on platforms where AA is enabled) Puck.js: Fix regression where IR LED was left on after transmission (fix #1969) + Graphics: Fix overdraw when drawing ellipses/circles + NRF52840: Use SPI3 by default as it's more capable/faster than SPI0 2v08 : nRF52: Added option to build in I2C slave support Fix Tensorflow aiGesture regression from 2v07 (re-add opcodes) (fix #1936) diff --git a/boards/BANGLEJS.py b/boards/BANGLEJS.py index 27ce0dd3a..ffb5d7d36 100644 --- a/boards/BANGLEJS.py +++ b/boards/BANGLEJS.py @@ -123,7 +123,7 @@ devices = { 'pin_scl' : 'D14' }, 'MAG' : { # Magnetometer/compass - 'device' : 'unknown', + 'device' : 'GMC303', 'addr' : 0x0C, 'pin_sda' : 'D15', 'pin_scl' : 'D14' diff --git a/boards/DICKENS.py b/boards/DICKENS.py new file mode 100644 index 000000000..08ecb08bd --- /dev/null +++ b/boards/DICKENS.py @@ -0,0 +1,205 @@ +#!/bin/false +# This file is part of Espruino, a JavaScript interpreter for Microcontrollers +# +# Copyright (C) 2013 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/. +# +# ---------------------------------------------------------------------------------------- +# This file contains information for a specific board - the available pins, and where LEDs, +# Buttons, and other in-built peripherals are. It is used to build documentation as well +# as various source and header files for Espruino. +# ---------------------------------------------------------------------------------------- + +import pinutils; + +# NOTES FROM REVERSE ENGINEERING +#==================================== +# Flash init: +# w(0x6), while (r(5)&1); + +# D2 and D8 and used together. Both outputs +# D8 set/cleared then 10ms delay + +# D2 set then I2C device 0x70[0x38] contacted + +# D0/D1 will be 32kHz crystal + +# Button flex header +# o GND D28(btn) +# VCC D46(btn) +# D3 D9 +# D29(btn) D10 +# D42(btn) GND + +# unfitted big flash-ish chip +# o D14 NC? +# D15 D17 +# D2 D19 +# GND D18 +# + +# unfitted header (assuming same dir as Button flex header) +# VCC D10 +# VCC D9 +# FET GND +# GND D31 +# ? D30 +# ... there's an unpopulated footprint - likely a FET (not checked to see what IO this is connected to) + +# Unknown pins: +# D8,D16,D17,D26,D32,D34,D35,D36, +# D37,D38,D39,D41,D44,D45,D47 + +#==================================== + +info = { + 'name' : "DICKENS", + 'link' : [ "" ], + 'espruino_page_link' : '', + 'variables' : 2500, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile. +# 'bootloader' : 1, + 'binary_name' : 'espruino_%v_dickens.hex', + 'build' : { + 'optimizeflags' : '-Os', + 'libraries' : [ + 'BLUETOOTH', + 'TERMINAL', + 'GRAPHICS', + 'LCD_SPI' + ], + 'makefile' : [ +# 'DEFINES += -DNRF_LOG_ENABLED=1 -DNRF_LOG_FILTERS_ENABLED=0', + 'DEFINES += -DCONFIG_NFCT_PINS_AS_GPIOS', # Allow the reset pin to work + 'DEFINES += -DNRF_BL_DFU_ENTER_METHOD_BUTTON=1 -DNRF_BL_DFU_ENTER_METHOD_BUTTON_PIN=29', + 'DEFINES += -DBUTTONPRESS_TO_REBOOT_BOOTLOADER', + 'BOOTLOADER_SETTINGS_FAMILY = NRF52840', + 'DFU_PRIVATE_KEY=targets/nrf5x_dfu/dfu_private_key.pem', + 'DFU_SETTINGS=--application-version 0xff --hw-version 52 --sd-req 0xA9', # SD 6.0.0 + + 'DEFINES+=-DBLUETOOTH_NAME_PREFIX=\'"Bangle.js"\'', + 'DEFINES+=-DCUSTOM_GETBATTERY=jswrap_banglejs_getBattery', + 'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'', + 'DEFINES+=-DUSE_FONT_6X8 -DGRAPHICS_PALETTED_IMAGES -DESPR_GRAPHICS_12BIT -DGRAPHICS_ANTIALIAS', + 'DEFINES+=-DNO_DUMP_HARDWARE_INITIALISATION', # don't dump hardware init - not used and saves 1k of flash + 'INCLUDE += -I$(ROOT)/libs/banglejs -I$(ROOT)/libs/misc', + 'WRAPPERSOURCES += libs/banglejs/jswrap_bangle.c', + 'JSMODULESOURCES += libs/js/banglejs/locale.min.js', + 'DEFINES += -DBANGLEJS', + + 'NRF_SDK15=1' + ] + } +}; + + +chip = { + 'part' : "NRF52840", + 'family' : "NRF52", + 'package' : "QFN48", + 'ram' : 256, + 'flash' : 1024, + 'speed' : 64, + 'usart' : 2, + 'spi' : 1, + 'i2c' : 1, + 'adc' : 1, + 'dac' : 0, + 'saved_code' : { +# 'address' : ((246 - 10) * 4096), # Bootloader takes pages 248-255, FS takes 246-247 +# 'page_size' : 4096, +# 'pages' : 10, +# 'flash_available' : 1024 - ((31 + 8 + 2 + 10)*4) # Softdevice uses 31 pages of flash, bootloader 8, FS 2, code 10. Each page is 4 kb. + 'address' : 0x60000000, # put this in external spiflash (see below) + 'page_size' : 4096, + 'pages' : 1024, # Entire 4MB of external flash + 'flash_available' : 1024 - ((31 + 8 + 2)*4) # Softdevice uses 31 pages of flash, bootloader 8, FS 2. Each page is 4 kb. + }, +}; + +devices = { + 'BTN1' : { 'pin' : 'D29', 'pinstate' : 'IN_PULLDOWN' }, # TR STATUS Pin negated in software + 'BTN2' : { 'pin' : 'D46', 'pinstate' : 'IN_PULLDOWN' }, # BL ATMOS Pin negated in software + 'BTN3' : { 'pin' : 'D42', 'pinstate' : 'IN_PULLDOWN' }, # BR Pin negated in software + 'BTN4' : { 'pin' : 'D28', 'pinstate' : 'IN_PULLDOWN' }, # TL Pin negated in software + + 'VIBRATE' : { 'pin' : 'D6' }, # Pin negated in software + 'LCD' : { + 'width' : 240, 'height' : 240, 'bpp' : 16, # 16 normal, 12 bit is possible + 'controller' : 'gc9a01', + 'pin_dc' : 'D7', + 'pin_cs' : 'D11', + 'pin_rst' : 'D40', + 'pin_sck' : 'D12', + 'pin_mosi' : 'D5', + 'pin_miso' : 'D27', + 'pin_en' : 'D43', + 'pin_bl' : 'D33', # TESTED! + 'bitrate' : 32000000 + }, + 'BAT' : { + 'pin_charging' : 'D13', + 'pin_voltage' : 'D4' + }, + 'MAG' : { # Magnetometer/compass + 'device' : 'GMC303', + 'addr' : 0x0C, + 'pin_sda' : 'D9', + 'pin_scl' : 'D10' + }, + 'ACCEL' : { + 'device' : 'KXTJ3_1057', 'addr' : 0x0e, + 'pin_sda' : 'D9', + 'pin_scl' : 'D10', +# 'pin_int' : '' # unknown + }, + 'PRESSURE' : { + 'device' : 'SPL06_007', 'addr' : 0x76, + 'pin_sda' : 'D9', + 'pin_scl' : 'D10', + }, + # KX126-1063 + 'SPIFLASH' : { + 'pin_cs' : 'D20', + 'pin_sck' : 'D25', + 'pin_mosi' : 'D22', # D0 + 'pin_miso' : 'D23', # D1 + 'pin_wp' : 'D21', # D2 + 'pin_rst' : 'D24', # D3 + 'size' : 4096*1024, + 'memmap_base' : 0x60000000 # map into the address space (in software) + } +}; + +# left-right, or top-bottom order +board = { +}; +board["_css"] = """ +"""; + +def get_pins(): + pins = pinutils.generate_pins(0,47) # 48 General Purpose I/O Pins. + pinutils.findpin(pins, "PD0", True)["functions"]["XL1"]=0; + pinutils.findpin(pins, "PD1", True)["functions"]["XL2"]=0; + pinutils.findpin(pins, "PD2", True)["functions"]["ADC1_IN0"]=0; + pinutils.findpin(pins, "PD3", True)["functions"]["ADC1_IN1"]=0; + pinutils.findpin(pins, "PD4", True)["functions"]["ADC1_IN2"]=0; + pinutils.findpin(pins, "PD5", True)["functions"]["ADC1_IN3"]=0; + pinutils.findpin(pins, "PD28", True)["functions"]["ADC1_IN4"]=0; + pinutils.findpin(pins, "PD29", True)["functions"]["ADC1_IN5"]=0; + pinutils.findpin(pins, "PD30", True)["functions"]["ADC1_IN6"]=0; + pinutils.findpin(pins, "PD31", True)["functions"]["ADC1_IN7"]=0; + # Make buttons and LEDs negated + pinutils.findpin(pins, "PD29", True)["functions"]["NEGATED"]=0; # ok + pinutils.findpin(pins, "PD46", True)["functions"]["NEGATED"]=0; # ok + pinutils.findpin(pins, "PD42", True)["functions"]["NEGATED"]=0; # ok + pinutils.findpin(pins, "PD28", True)["functions"]["NEGATED"]=0; # ok + + + # everything is non-5v tlerant + for pin in pins: + pin["functions"]["3.3"]=0; + #The boot/reset button will function as a reset button in normal operation. Pin reset on PD21 needs to be enabled on the nRF52832 device for this to work. + return pins diff --git a/libs/banglejs/jswrap_bangle.c b/libs/banglejs/jswrap_bangle.c index 8aea04edb..4991e5e3a 100644 --- a/libs/banglejs/jswrap_bangle.c +++ b/libs/banglejs/jswrap_bangle.c @@ -51,7 +51,7 @@ #ifdef LCD_CONTROLLER_ST7789_8BIT #include "lcd_st7789_8bit.h" #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) #include "lcd_spilcd.h" #endif @@ -363,13 +363,19 @@ JshI2CInfo i2cInternal; #define ACCEL_I2C &i2cInternal #define PRESSURE_I2C &i2cInternal #endif +#ifdef DICKENS +JshI2CInfo i2cInternal; +#define ACCEL_I2C &i2cInternal +#define PRESSURE_I2C &i2cInternal +#define MAG_I2C &i2cInternal +#endif #ifdef ID205 #endif + #ifdef PRESSURE_I2C /// Promise when pressure is requested JsVar *promisePressure; - #endif #ifndef EMSCRIPTEN @@ -557,6 +563,7 @@ void jswrap_banglejs_pwrBacklight(bool on) { /// Flip buffer contents with the screen. void lcd_flip(JsVar *parent, bool all) { +#ifdef LCD_WIDTH JsVar *graphics = jsvObjectGetChild(execInfo.hiddenRoot, JS_GRAPHICS_VAR, 0); if (!graphics) return; JsGraphics gfx; @@ -583,11 +590,12 @@ void lcd_flip(JsVar *parent, bool all) { #ifdef LCD_CONTROLLER_ST7789_8BIT lcdST7789_flip(&gfx); #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) lcdFlip_SPILCD(&gfx); #endif graphicsSetVar(&gfx); jsvUnLock(graphics); +#endif } char clipi8(int x) { @@ -664,13 +672,13 @@ void peripheralPollHandler() { if (i2cBusy) return; i2cBusy = true; unsigned char buf[7]; -#ifdef MAG_I2C +#ifdef MAG_DEVICE_GMC303 // check the magnetometer if we had it on if (compassPowerOn) { buf[0]=0x10; jsi2cWrite(MAG_I2C, MAG_ADDR, 1, buf, true); jsi2cRead(MAG_I2C, MAG_ADDR, 7, buf, true); - if (buf[0]&1) { // then we have data (hopefully? No datasheet) + if (buf[0]&1) { // then we have data mag.y = buf[1] | (buf[2]<<8); mag.x = buf[3] | (buf[4]<<8); mag.z = buf[5] | (buf[6]<<8); @@ -686,6 +694,7 @@ void peripheralPollHandler() { } #endif #ifdef ACCEL_I2C +#ifdef ACCEL_DEVICE_KX023 // poll KX023 accelerometer (no other way as IRQ line seems disconnected!) // read interrupt source data buf[0]=0x12; // INS1 @@ -705,6 +714,14 @@ void peripheralPollHandler() { jsi2cWrite(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); jsi2cRead(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); } +#endif +#ifdef ACCEL_DEVICE_KXTJ3_1057 + // read interrupt source data + buf[0]=0x16; // INT_SOURCE1 + jsi2cWrite(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); + jsi2cRead(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); + bool hasAccelData = (buf[0]&16)!=0; // DRDY +#endif if (hasAccelData) { buf[0]=6; jsi2cWrite(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); @@ -926,7 +943,7 @@ void btnHandlerCommon(int button, bool state, IOEventFlags flags) { jshPushIOEvent(flags | (state?EV_EXTI_IS_HIGH:0), t); } -#ifdef BTN4_PININDEX +#ifdef BANGLEJS_F18 // returns true if handled and shouldn't create a normal watch event bool btnTouchHandler() { if (bangleFlags&JSBF_WAKEON_TOUCH) { @@ -975,7 +992,7 @@ void btn3Handler(bool state, IOEventFlags flags) { btnHandlerCommon(3,state,flags); } #endif -#ifdef BTN4_PININDEX +#ifdef BANGLEJS_F18 void btn4Handler(bool state, IOEventFlags flags) { if (btnTouchHandler()) return; btnHandlerCommon(4,state,flags); @@ -984,6 +1001,10 @@ void btn5Handler(bool state, IOEventFlags flags) { if (btnTouchHandler()) return; btnHandlerCommon(5,state,flags); } +#else +void btn4Handler(bool state, IOEventFlags flags) { + btnHandlerCommon(4,state,flags); +} #endif #ifdef SMAQ3 @@ -1111,7 +1132,8 @@ void jswrap_banglejs_setLCDPower(bool isOn) { lcdST7789_cmd(0x10, 0, NULL); // SLPIN } #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) + // TODO: LCD_CONTROLLER_GC9A01 - has an enable/power pin if (isOn) { // wake lcdCmd_SPILCD(0x11, 0, NULL); // SLPOUT jshDelayMicroseconds(20); @@ -1483,9 +1505,15 @@ JsVarInt jswrap_banglejs_getBattery() { #ifdef SMAQ3 const JsVarFloat vlo = 0.22; // guess const JsVarFloat vhi = 0.32; // guess -#else +#elif defined(BANGLEJS_F18) const JsVarFloat vlo = 0.51; const JsVarFloat vhi = 0.62; +#elif defined(DICKENS) + const JsVarFloat vlo = 3.3 / (2.8*2); + const JsVarFloat vhi = 3.8 / (2.8*2); +#else + const JsVarFloat vlo = 0; + const JsVarFloat vhi = 1; #endif int pc = (v-vlo)*100/(vhi-vlo); if (pc>100) pc=100; @@ -1514,7 +1542,7 @@ void jswrap_banglejs_lcdWr(JsVarInt cmd, JsVar *data) { #ifdef LCD_CONTROLLER_ST7789_8BIT lcdST7789_cmd(cmd, dLen, (const uint8_t *)dPtr); #endif -#ifdef LCD_CONTROLLER_ST7789V +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) lcdCmd_SPILCD(cmd, dLen, (const uint8_t *)dPtr); #endif } @@ -1631,7 +1659,9 @@ Bangle.on('mag',print); */ void jswrap_banglejs_setCompassPower(bool isOn) { compassPowerOn = isOn; - jswrap_banglejs_compassWr(0x31,isOn ? 8 : 0); +#ifdef MAG_DEVICE_GMC303 + jswrap_banglejs_compassWr(0x31,isOn ? 4 : 0); // continuous measurement mode, 20Hz +#endif mag.x = 0; mag.y = 0; mag.z = 0; @@ -1755,8 +1785,7 @@ void jswrap_banglejs_init() { i2cTouch.pinSDA = TOUCH_PIN_SDA; i2cTouch.pinSCL = TOUCH_PIN_SCL; jsi2cSetup(&i2cTouch); -#endif -#if defined(BANGLEJS_F18) || defined(DTNO1_F5) +#elif defined(ACCEL_PIN_SDA) // assume all the rest just use a global I2C jshI2CInitInfo(&i2cInternal); i2cInternal.bitrate = 0x7FFFFFFF; // make it as fast as we can go i2cInternal.pinSDA = ACCEL_PIN_SDA; @@ -1799,6 +1828,7 @@ void jswrap_banglejs_init() { lcdBrightness = 255; lcdPowerTimeout = DEFAULT_LCD_POWER_TIMEOUT; lcdWakeButton = 0; +#ifdef LCD_WIDTH // Create backing graphics for LCD JsVar *graphics = jspNewObject(0, "Graphics"); if (!graphics) return; // low memory @@ -1810,7 +1840,7 @@ void jswrap_banglejs_init() { #ifdef LCD_CONTROLLER_ST7789_8BIT gfx.data.type = JSGRAPHICSTYPE_ST7789_8BIT; #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) gfx.data.type = JSGRAPHICSTYPE_SPILCD; #endif gfx.data.flags = 0; @@ -1828,7 +1858,7 @@ void jswrap_banglejs_init() { #ifdef LCD_CONTROLLER_ST7789_8BIT lcdST7789_init(&gfx); #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) lcdInit_SPILCD(&gfx); #endif graphicsSetVar(&gfx); @@ -1890,13 +1920,17 @@ void jswrap_banglejs_init() { } #ifdef SMAQ3 lcdMemLCD_flip(&gfx); +#endif +#if defined(LCD_CONTROLLER_GC9A01) + lcdFlip_SPILCD(&gfx); #endif graphicsStructResetState(&gfx); graphicsSetVar(&gfx); jsvUnLock(graphics); +#endif -#ifdef ACCEL_DEVICE +#ifdef ACCEL_DEVICE_KX023 // KX023-1025 accelerometer init jswrap_banglejs_accelWr(0x18,0x0a); // CNTL1 Off (top bit) jswrap_banglejs_accelWr(0x19,0x80); // CNTL2 Software reset @@ -1924,24 +1958,42 @@ void jswrap_banglejs_init() { jswrap_banglejs_accelWr(0x18,0b10101100); // CNTL1 On, low power, DRDYE=1, 4g range, TDTE (tap enable)=1, Wakeup=0, Tilt=0 // high power vs low power uses an extra 150uA #endif -#ifdef PRESSURE_DEVICE +#ifdef ACCEL_DEVICE_KXTJ3_1057 + // KXTJ3-1057 accelerometer init + jswrap_banglejs_accelWr(0x1B,0b00101000); // CNTL1 Off (top bit) + jswrap_banglejs_accelWr(0x1D,0x80); // CNTL2 Software reset + jshDelayMicroseconds(2000); + jswrap_banglejs_accelWr(0x21,0); // DATA_CTRL_REG - 12.5Hz out + jswrap_banglejs_accelWr(0x1B,0b00101000); // CNTL1 On (top bit), low power, DRDYE=1, 4g, Wakeup=0, + jswrap_banglejs_accelWr(0x1B,0b10101000); // CNTL1 On (top bit), low power, DRDYE=1, 4g, Wakeup=0, +#endif +#ifdef PRESSURE_DEVICE_HP203 // pressure init char *buf[2]; buf[0]=0x06; jsi2cWrite(PRESSURE_I2C, PRESSURE_ADDR, 1, (uint8_t)*buf, true); // SOFT_RST #endif +#ifdef PRESSURE_DEVICE_SPL06-007 + // pressure init + char *buf[2]; + buf[0]=0x0C; buf[1]=0x89; + jsi2cWrite(PRESSURE_I2C, PRESSURE_ADDR, 1, (uint8_t)*buf, true); // SOFT_RST +#endif + // Accelerometer variables init stepCounter = 0; stepWasLow = false; -#ifndef EMSCRIPTEN +#ifdef MAG_DEVICE_GMC303 // compass init - jswrap_banglejs_compassWr(0x32,1); - jswrap_banglejs_compassWr(0x31,0); + jswrap_banglejs_compassWr(0x32,1); // soft reset + jswrap_banglejs_compassWr(0x31,0); // power down mode #endif compassPowerOn = false; i2cBusy = false; // Other IO +#ifdef BAT_PIN_CHARGING jshPinSetState(BAT_PIN_CHARGING, JSHPINSTATE_GPIO_IN_PULLUP); +#endif // touch touchStatus = TS_NONE; touchLastState = 0; @@ -2002,9 +2054,11 @@ void jswrap_banglejs_init() { #endif #ifdef BTN4_PININDEX jshSetPinShouldStayWatched(BTN4_PININDEX,true); - jshSetPinShouldStayWatched(BTN5_PININDEX,true); channel = jshPinWatch(BTN4_PININDEX, true); if (channel!=EV_NONE) jshSetEventCallback(channel, btn4Handler); +#endif +#ifdef BTN5_PININDEX + jshSetPinShouldStayWatched(BTN5_PININDEX,true); channel = jshPinWatch(BTN5_PININDEX, true); if (channel!=EV_NONE) jshSetEventCallback(channel, btn5Handler); #endif @@ -2075,9 +2129,11 @@ void jswrap_banglejs_kill() { #endif #ifdef BTN4_PININDEX jshSetPinShouldStayWatched(BTN4_PININDEX,false); - jshSetPinShouldStayWatched(BTN5_PININDEX,false); jshPinWatch(BTN4_PININDEX, false); +#endif +#ifdef BTN5_PININDEX jshPinWatch(BTN5_PININDEX, false); + jshSetPinShouldStayWatched(BTN5_PININDEX,false); #endif #endif } @@ -2356,7 +2412,7 @@ bool jswrap_banglejs_idle() { } jsvUnLock(bangle); bangleTasks = JSBT_NONE; -#if defined(LCD_CONTROLLER_LPM013M126) || defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) +#if defined(LCD_CONTROLLER_LPM013M126) || defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) // Automatically flip! JsVar *graphics = jsvObjectGetChild(execInfo.hiddenRoot, JS_GRAPHICS_VAR, 0); JsGraphics gfx; @@ -2549,7 +2605,7 @@ JsVar *jswrap_banglejs_accelRd(JsVarInt reg, JsVarInt cnt) { buf[0] = (unsigned char)reg; i2cBusy = true; jsi2cWrite(ACCEL_I2C, ACCEL_ADDR, 1, buf, true); - jsi2cRead(ACCEL_I2C, ACCEL_ADDR, cnt, buf, true); + jsi2cRead(ACCEL_I2C, ACCEL_ADDR, (cnt==0)?1:cnt, buf, true); i2cBusy = false; if (cnt) { JsVar *ab = jsvNewArrayBufferWithData(cnt, buf); @@ -2620,7 +2676,7 @@ void jswrap_banglejs_ioWr(JsVarInt mask, bool on) { "name" : "getPressure", "generate" : "jswrap_banglejs_getPressure", "return" : ["JsVar","A promise that will be resolved with `{temperature, pressure, altitude}`"], - "ifdef" : "DTNO1_F5" + "#if" : "defined(DTNO1_F5) || defined(DICKENS)" } Read temperature, pressure and altitude data. A promise is returned which will be resolved with `{temperature, pressure, altitude}`. @@ -2640,6 +2696,7 @@ void jswrap_banglejs_getPressure_callback() { if (o) { i2cBusy = true; unsigned char buf[6]; +#ifdef PRESSURE_DEVICE_HP203 // ADC_CVT - 0b010 01 000 - pressure and temperature channel, OSR = 4096 buf[0] = 0x48; jsi2cWrite(PRESSURE_I2C, PRESSURE_ADDR, 1, buf, true); // wait 100ms @@ -2658,6 +2715,17 @@ void jswrap_banglejs_getPressure_callback() { int altitude = (buf[0]<<16)|(buf[1]<<8)|buf[2]; if (altitude&0x800000) altitude-=0x1000000; jsvObjectSetChildAndUnLock(o,"altitude", jsvNewFromFloat(altitude/100.0)); +#endif +#ifdef PRESSURE_DEVICE_SPL06_007 + buf[0] = 0; jsi2cWrite(PRESSURE_I2C, PRESSURE_ADDR, 1, buf, true); // PSR + jsi2cRead(PRESSURE_I2C, PRESSURE_ADDR, 6, buf, true); + int pressure = (buf[0]<<16)|(buf[1]<<8)|buf[2]; + int temperature = (buf[3]<<16)|(buf[4]<<8)|buf[5]; + if (temperature&0x800000) temperature-=0x1000000; + // FIXME - need to read calibration registers/etc + jsvObjectSetChildAndUnLock(o,"temperature", jsvNewFromInteger(temperature)); + jsvObjectSetChildAndUnLock(o,"pressure", jsvNewFromInteger(pressure)); +#endif i2cBusy = false; jspromise_resolve(promisePressure, o); } @@ -2672,8 +2740,13 @@ JsVar *jswrap_banglejs_getPressure() { } promisePressure = jspromise_create(); if (!promisePressure) return 0; - - jsiSetTimeout(jswrap_banglejs_getPressure_callback, 100); + unsigned char buf[6]; +#ifdef PRESSURE_DEVICE_SPL06_007 + buf[0] = 0x08; + buf[1] = 1; + jsi2cWrite(PRESSURE_I2C, PRESSURE_ADDR, 2, buf, true); +#endif + jsiSetTimeout(jswrap_banglejs_getPressure_callback, 500); return jsvLockAgain(promisePressure); } #endif @@ -2848,8 +2921,15 @@ void jswrap_banglejs_off() { jswrap_banglejs_pwrGPS(false); // GPS off jshPinOutput(VIBRATE_PIN,0); // vibrate off jswrap_banglejs_setLCDPower(0); +#ifdef ACCEL_DEVICE_KX023 jswrap_banglejs_accelWr(0x18,0x0a); // accelerometer off +#endif +#ifdef ACCEL_DEVICE_KXTJ3_1057 + jswrap_banglejs_accelWr(0x1B,0); // accelerometer off +#endif +#ifdef MAG_DEVICE_GMC303 jswrap_banglejs_compassWr(0x31,0); // compass off +#endif #ifdef BTN2_PININDEX diff --git a/libs/graphics/graphics.c b/libs/graphics/graphics.c index 7fc5cd04c..651b473b7 100644 --- a/libs/graphics/graphics.c +++ b/libs/graphics/graphics.c @@ -56,7 +56,7 @@ unsigned int graphicsFallbackGetPixel(JsGraphics *gfx, int x, int y) { NOT_USED(gfx); NOT_USED(x); NOT_USED(y); - return 0; + return gfx->data.bgColor; } void graphicsFallbackFillRect(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col) { @@ -277,41 +277,46 @@ JsGraphicsSetPixelFn graphicsGetSetPixelUnclippedFn(JsGraphics *gfx, int x1, int } /// Merge one color into another based on current bit depth (amt is 0..256) -uint32_t graphicsBlendColor(JsGraphics *gfx, int iamt) { +uint32_t graphicsBlendColor(JsGraphics *gfx, unsigned int fg, unsigned int bg, int iamt) { unsigned int amt = (iamt>0) ? (unsigned)iamt : 0; if (amt>255) amt=255; if (gfx->data.bpp==2 || gfx->data.bpp==4 || gfx->data.bpp==8) { - return (gfx->data.bgColor*(256-amt) + gfx->data.fgColor*amt) >> 8; + return (bg*(256-amt) + fg*amt) >> 8; } else if (gfx->data.bpp==16) { // Blend from bg to fg - unsigned int b = gfx->data.bgColor; - unsigned int br = (b>>8)&0xF8; - unsigned int bg = (b>>3)&0xFC; - unsigned int bb = (b<<3)&0xF8; - unsigned int f = gfx->data.fgColor; - unsigned int fr = (f>>8)&0xF8; - unsigned int fg = (f>>3)&0xFC; - unsigned int fb = (f<<3)&0xF8; + unsigned int b = bg; + unsigned int br = (b>>11)&0x1F; + unsigned int bg = (b>>5)&0x3F; + unsigned int bb = b&0x1F; + unsigned int f = fg; + unsigned int fr = (f>>11)&0x1F; + unsigned int fg = (f>>5)&0x3F; + unsigned int fb = f&0x1F; unsigned int ri = (br*(256-amt) + fr*amt) >> 8; unsigned int gi = (bg*(256-amt) + fg*amt) >> 8; unsigned int bi = (bb*(256-amt) + fb*amt) >> 8; - return (uint16_t)((bi>>3) | (gi>>2)<<5 | (ri>>3)<<11); + return (uint16_t)(bi | gi<<5 | ri<<11); #ifdef ESPR_GRAPHICS_12BIT } else if (gfx->data.bpp==12) { // Blend from bg to fg - unsigned int b = gfx->data.bgColor; - unsigned int br = (b>>8)&0xF0; - unsigned int bg = (b>>4)&0xF0; - unsigned int bb = (b<<4)&0xF0; - unsigned int f = gfx->data.fgColor; - unsigned int fr = (f>>8)&0xF0; - unsigned int fg = (f>>4)&0xF0; - unsigned int fb = (f<<4)&0xF0; + unsigned int b = bg; + unsigned int br = (b>>8)&0x0F; + unsigned int bg = (b>>4)&0x0F; + unsigned int bb = b&0x0F; + unsigned int f = fg; + unsigned int fr = (f>>8)&0x0F; + unsigned int fg = (f>>4)&0x0F; + unsigned int fb = f&0x0F; unsigned int ri = (br*(256-amt) + fr*amt) >> 8; unsigned int gi = (bg*(256-amt) + fg*amt) >> 8; unsigned int bi = (bb*(256-amt) + fb*amt) >> 8; - return (uint16_t)((bi>>4) | (gi>>4)<<4 | (ri>>4)<<8); + return (uint16_t)(bi | gi<<4 | ri<<8); #endif } // TODO: 24 bit - return (amt>=128) ? gfx->data.fgColor : gfx->data.bgColor; + return (amt>=128) ? fg : bg; +} + +/// Merge one color into another based on current bit depth (amt is 0..256) +uint32_t graphicsBlendGfxColor(JsGraphics *gfx, int iamt) { + return graphicsBlendColor(gfx, gfx->data.fgColor, gfx->data.bgColor, iamt); } // ---------------------------------------------------------------------------------------------- @@ -337,6 +342,13 @@ static unsigned int graphicsGetPixelDevice(JsGraphics *gfx, int x, int y) { return gfx->getPixel(gfx, x, y); } +/// For Antialiasing - blends between FG and BG colors +static void graphicsSetPixelDeviceBlended(JsGraphics *gfx, int x, int y, int amt) { + unsigned int bg = graphicsGetPixelDevice(gfx, x, y); + unsigned int col = graphicsBlendColor(gfx, gfx->data.fgColor, bg, amt); + graphicsSetPixelDevice(gfx, x, y, col); +} + static void graphicsFillRectDevice(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col) { if (x1>x2) { int t = x1; @@ -457,18 +469,20 @@ void graphicsFillEllipse(JsGraphics *gfx, int posX1, int posY1, int posX2, int p int err = b2-(2*b-1)*a2; int e2; bool changed = false; - do { changed = false; - graphicsFillRectDevice(gfx,posX+dx,posY+dy,posX-dx,posY+dy,gfx->data.fgColor); - graphicsFillRectDevice(gfx,posX+dx,posY-dy,posX-dx,posY-dy,gfx->data.fgColor); e2 = 2*err; if (e2 < (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; changed=true; } - if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; changed=true; } + if (e2 > -(2*dy-1)*a2) { + // draw only just before we change Y, to avoid a bunch of overdraw + graphicsFillRectDevice(gfx,posX+dx,posY+dy,posX-dx,posY+dy,gfx->data.fgColor); + graphicsFillRectDevice(gfx,posX+dx,posY-dy,posX-dx,posY-dy,gfx->data.fgColor); + dy--; err -= (2*dy-1)*a2; changed=true; + } } while (changed && dy >= 0); while (dx++ < a) { /* erroneous termination in flat ellipses(b=1) */ - graphicsFillRectDevice(gfx,posX+dx,posY,posX-dx,posY,gfx->data.fgColor ); + graphicsFillRectDevice(gfx,posX+dx,posY,posX-dx,posY,gfx->data.fgColor ); } } @@ -509,6 +523,7 @@ void graphicsDrawLine(JsGraphics *gfx, int x1, int y1, int x2, int y2) { } } +#ifdef GRAPHICS_ANTIALIAS // In 16x accuracy void graphicsDrawLineAA(JsGraphics *gfx, int ix1, int iy1, int ix2, int iy2) { // https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm @@ -540,12 +555,13 @@ void graphicsDrawLineAA(JsGraphics *gfx, int ix1, int iy1, int ix2, int iy2) { int ypxl1 = yend >> 8; int c = yend & 255; if (steep) { - graphicsSetPixelDevice(gfx, ypxl1, xpxl1, graphicsBlendColor(gfx, ((256-c)*xgap)>>8)); - graphicsSetPixelDevice(gfx, ypxl1+1, xpxl1, graphicsBlendColor(gfx, (c*xgap)>>8)); + graphicsSetPixelDeviceBlended(gfx, ypxl1, xpxl1, ((256-c)*xgap)>>8); + graphicsSetPixelDeviceBlended(gfx, ypxl1+1, xpxl1, (c*xgap)>>8); } else { - graphicsSetPixelDevice(gfx, xpxl1, ypxl1, graphicsBlendColor(gfx, ((256-c)*xgap)>>8)); - graphicsSetPixelDevice(gfx, xpxl1, ypxl1+1, graphicsBlendColor(gfx, (c*xgap)>>8)); + graphicsSetPixelDeviceBlended(gfx, xpxl1, ypxl1, ((256-c)*xgap)>>8); + graphicsSetPixelDeviceBlended(gfx, xpxl1, ypxl1+1, (c*xgap)>>8); } + int intery = yend + gradient; // first y-intersection for the main loop // handle second endpoint xend = (x1+256) & ~255; @@ -555,29 +571,30 @@ void graphicsDrawLineAA(JsGraphics *gfx, int ix1, int iy1, int ix2, int iy2) { int ypxl2 = yend>>8; c = yend & 255; if (steep) { - graphicsSetPixelDevice(gfx, ypxl2 , xpxl2, graphicsBlendColor(gfx, ((256-c)*xgap)>>8)); - graphicsSetPixelDevice(gfx, ypxl2+1, xpxl2, graphicsBlendColor(gfx, (c*xgap)>>8)); + graphicsSetPixelDeviceBlended(gfx, ypxl2 , xpxl2, ((256-c)*xgap)>>8); + graphicsSetPixelDeviceBlended(gfx, ypxl2+1, xpxl2, (c*xgap)>>8); } else { - graphicsSetPixelDevice(gfx, xpxl2, ypxl2, graphicsBlendColor(gfx, ((256-c)*xgap)>>8)); - graphicsSetPixelDevice(gfx, xpxl2, ypxl2+1, graphicsBlendColor(gfx, (c*xgap)>>8)); + graphicsSetPixelDeviceBlended(gfx, xpxl2, ypxl2, ((256-c)*xgap)>>8); + graphicsSetPixelDeviceBlended(gfx, xpxl2, ypxl2+1, (c*xgap)>>8); } // main loop for (int x=xpxl1+1;x>8; c = intery & 255; if (steep) { - graphicsSetPixelDevice(gfx, y , x, graphicsBlendColor(gfx, 256-c)); - graphicsSetPixelDevice(gfx, y+1, x, graphicsBlendColor(gfx, c)); + graphicsSetPixelDeviceBlended(gfx, y , x, 256-c); + graphicsSetPixelDeviceBlended(gfx, y+1, x, c); } else { - graphicsSetPixelDevice(gfx, x, y, graphicsBlendColor(gfx, 256-c)); - graphicsSetPixelDevice(gfx, x, y+1, graphicsBlendColor(gfx, c)); + graphicsSetPixelDeviceBlended(gfx, x, y, 256-c); + graphicsSetPixelDeviceBlended(gfx, x, y+1, c); } intery += gradient; } } +#endif // Fill poly - each member of vertices is 1/16th pixel -void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices) { +void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices, bool antiAlias) { typedef struct { short x,y; } VertXY; @@ -610,6 +627,7 @@ void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices) { // for each scanline for (y=miny<<4;y<=maxy<<4;y+=16) { + int yl = y>>4; short cross[MAX_CROSSES]; bool slopes[MAX_CROSSES]; int crosscnt = 0; @@ -648,9 +666,30 @@ void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices) { if (s==0) x=cross[i]; if (slopes[i]) s++; else s--; if (!s || i==crosscnt-1) { - int x1 = (x+15)>>4; - int x2 = (cross[i]+15)>>4; - if (x2>x1) graphicsFillRectDevice(gfx,x1,y>>4,x2-1,y>>4,gfx->data.fgColor); +#ifdef GRAPHICS_ANTIALIAS + if (!antiAlias) { +#endif + int x1 = (x+15)>>4; + int x2 = (cross[i]+15)>>4; + if (x2>x1) graphicsFillRectDevice(gfx,x1,yl,x2-1,yl,gfx->data.fgColor); +#ifdef GRAPHICS_ANTIALIAS + } else { + int x1 = x; + int x2 = cross[i]; + if (x2>x1) { + int x1i = x1>>4; + int x2i = x2>>4; + if (x2i==x1i) { + graphicsSetPixelDeviceBlended(gfx, x1i, yl, 16*(1+x2-x1)); + } else if (x2i>x1i) { + graphicsSetPixelDeviceBlended(gfx, x1i, yl, 16*(15-(x1&15))); + if (x2i>x1i+1) + graphicsFillRectDevice(gfx,x1i+1,yl,x2i-1,yl,gfx->data.fgColor); + graphicsSetPixelDeviceBlended(gfx, x2i, yl, 16*(x2&15)); + } + } + } +#endif } if (jspIsInterrupted()) break; } diff --git a/libs/graphics/graphics.h b/libs/graphics/graphics.h index 8a048a403..7af1ef640 100644 --- a/libs/graphics/graphics.h +++ b/libs/graphics/graphics.h @@ -145,7 +145,9 @@ JsGraphicsSetPixelFn graphicsGetSetPixelFn(JsGraphics *gfx); /// Get a setPixel function and set modified area (assuming no clipping) (inclusive of x2,y2) - if all is ok it can choose a faster draw function JsGraphicsSetPixelFn graphicsGetSetPixelUnclippedFn(JsGraphics *gfx, int x1, int y1, int x2, int y2); /// Merge one color into another based on current bit depth (amt is 0..256) -uint32_t graphicsBlendColor(JsGraphics *gfx, int amt); +uint32_t graphicsBlendColor(JsGraphics *gfx, unsigned int fg, unsigned int bg, int iamt); +/// Merge one color into another based on current bit depth (amt is 0..256) +uint32_t graphicsBlendGfxColor(JsGraphics *gfx, int iamt); // drawing functions - all coordinates are in USER coordinates, not DEVICE coordinates void graphicsSetPixel(JsGraphics *gfx, int x, int y, unsigned int col); @@ -158,7 +160,7 @@ void graphicsDrawEllipse(JsGraphics *gfx, int x, int y, int x2, int y2); void graphicsFillEllipse(JsGraphics *gfx, int x, int y, int x2, int y2); void graphicsDrawLine(JsGraphics *gfx, int x1, int y1, int x2, int y2); void graphicsDrawLineAA(JsGraphics *gfx, int ix1, int iy1, int ix2, int iy2); ///< antialiased drawline. each pixel is 1/16th -void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices); ///< each pixel is 1/16th a pixel may overwrite vertices... +void graphicsFillPoly(JsGraphics *gfx, int points, short *vertices, bool antiAlias); ///< each pixel is 1/16th a pixel may overwrite vertices... #ifndef NO_VECTOR_FONT unsigned int graphicsFillVectorChar(JsGraphics *gfx, int x1, int y1, int size, char ch); ///< prints character, returns width unsigned int graphicsVectorCharWidth(JsGraphics *gfx, unsigned int size, char ch); ///< returns the width of a character diff --git a/libs/graphics/jswrap_graphics.c b/libs/graphics/jswrap_graphics.c index 463d059d5..af8920f45 100644 --- a/libs/graphics/jswrap_graphics.c +++ b/libs/graphics/jswrap_graphics.c @@ -1473,7 +1473,7 @@ JsVar *jswrap_graphics_drawString(JsVar *parent, JsVar *var, int x, int y, bool (y + cy*scale), (x + cx*scale + scale-1), (y + cy*scale + scale-1), - graphicsBlendColor(&gfx, (256*col)/customBPPRange)); + graphicsBlendGfxColor(&gfx, (256*col)/customBPPRange)); bmpOffset += customBPP; citdata <<= customBPP; if (bmpOffset>=8) { @@ -1755,7 +1755,7 @@ JsVar *jswrap_graphics_drawPoly_X(JsVar *parent, JsVar *poly, bool closed, bool "class" : "Graphics", "name" : "fillPoly", "ifndef" : "SAVE_ON_FLASH", - "generate" : "jswrap_graphics_fillPoly", + "generate_full" : "jswrap_graphics_fillPoly_X(parent, poly, false);", "params" : [ ["poly","JsVar","An array of vertices, of the form ```[x1,y1,x2,y2,x3,y3,etc]```"] ], @@ -1779,7 +1779,36 @@ This fills from the top left hand side of the polygon (low X, low Y) will align perfectly without overdraw - but this will not fill the same pixels as `drawPoly` (drawing a line around the edge of the polygon). */ -JsVar *jswrap_graphics_fillPoly(JsVar *parent, JsVar *poly) { +/*JSON{ + "type" : "method", + "class" : "Graphics", + "name" : "fillPolyAA", + "ifdef" : "GRAPHICS_ANTIALIAS", + "generate_full" : "jswrap_graphics_fillPoly_X(parent, poly, true);", + "params" : [ + ["poly","JsVar","An array of vertices, of the form ```[x1,y1,x2,y2,x3,y3,etc]```"] + ], + "return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"], + "return_object" : "Graphics" +} +Draw a filled polygon in the current foreground color. + +``` +g.fillPolyAA([ + 16, 0, + 31, 31, + 26, 31, + 16, 12, + 6, 28, + 0, 27 ]); +``` + +This fills from the top left hand side of the polygon (low X, low Y) +*down to but not including* the bottom right. When placed together polygons +will align perfectly without overdraw - but this will not fill the +same pixels as `drawPoly` (drawing a line around the edge of the polygon). +*/ +JsVar *jswrap_graphics_fillPoly_X(JsVar *parent, JsVar *poly, bool antiAlias) { JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0; if (!jsvIsIterable(poly)) return 0; const int maxVerts = 128; @@ -1794,7 +1823,7 @@ JsVar *jswrap_graphics_fillPoly(JsVar *parent, JsVar *poly) { if (jsvIteratorHasElement(&it)) jsExceptionHere(JSET_ERROR, "Maximum number of points (%d) exceeded for fillPoly", maxVerts/2); jsvIteratorFree(&it); - graphicsFillPoly(&gfx, idx/2, verts); + graphicsFillPoly(&gfx, idx/2, verts, antiAlias); graphicsSetVar(&gfx); // gfx data changed because modified area return jsvLockAgain(parent); @@ -1956,8 +1985,8 @@ static bool _jswrap_graphics_parseImage(JsGraphics *gfx, JsVar *image, GfxDrawIm #ifdef GRAPHICS_PALETTED_IMAGES } else if (gfx->data.bpp>8 && info->bpp==2) { // Blend from bg to fg info->_simplePalette[0] = (uint16_t)gfx->data.bgColor; - info->_simplePalette[1] = graphicsBlendColor(gfx, 85); - info->_simplePalette[2] = graphicsBlendColor(gfx, 171); + info->_simplePalette[1] = graphicsBlendGfxColor(gfx, 85); + info->_simplePalette[2] = graphicsBlendGfxColor(gfx, 171); info->_simplePalette[3] = (uint16_t)gfx->data.fgColor; info->palettePtr = info->_simplePalette; info->paletteMask = 3; diff --git a/libs/graphics/jswrap_graphics.h b/libs/graphics/jswrap_graphics.h index 4199f4710..3801d2a2b 100644 --- a/libs/graphics/jswrap_graphics.h +++ b/libs/graphics/jswrap_graphics.h @@ -77,7 +77,7 @@ JsVar *jswrap_graphics_drawLineAA(JsVar *parent, double x1, double y1, double x2 JsVar *jswrap_graphics_lineTo(JsVar *parent, int x, int y); JsVar *jswrap_graphics_moveTo(JsVar *parent, int x, int y); JsVar *jswrap_graphics_drawPoly_X(JsVar *parent, JsVar *poly, bool closed, bool antiAlias); -JsVar *jswrap_graphics_fillPoly(JsVar *parent, JsVar *poly); +JsVar *jswrap_graphics_fillPoly_X(JsVar *parent, JsVar *poly, bool antiAlias); JsVar *jswrap_graphics_setRotation(JsVar *parent, int rotation, bool reflect); JsVar *jswrap_graphics_drawImage(JsVar *parent, JsVar *image, int xPos, int yPos, JsVar *options); JsVar *jswrap_graphics_drawImages(JsVar *parent, JsVar *layersVar, JsVar *options); diff --git a/libs/graphics/lcd_spilcd.c b/libs/graphics/lcd_spilcd.c index 02deb3029..d23f78e34 100644 --- a/libs/graphics/lcd_spilcd.c +++ b/libs/graphics/lcd_spilcd.c @@ -18,6 +18,9 @@ #include "lcd_spilcd.h" #include "lcd_spilcd_info.h" #include "lcd_spilcd_palette.h" +#if defined(NRF52_SERIES) +#include "nrf_gpio.h" +#endif // ====================================================================== @@ -37,9 +40,9 @@ unsigned short lcdPalette[256]; // ====================================================================== -void lcdCmd_SPILCD(int cmd, int dataLen, const char *data) { - jshPinSetValue(LCD_SPI_CS, 0); +void lcdCmd_SPILCD(int cmd, int dataLen, const unsigned char *data) { jshPinSetValue(LCD_SPI_DC, 0); // command + jshPinSetValue(LCD_SPI_CS, 0); jshSPISend(LCD_SPI, cmd); if (dataLen) { jshPinSetValue(LCD_SPI_DC, 1); // data @@ -52,7 +55,7 @@ void lcdCmd_SPILCD(int cmd, int dataLen, const char *data) { } void lcdSendInitCmd_SPILCD() { // Send initialization commands to ST7735 - const char *cmd = SPILCD_INIT_CODE; + const unsigned char *cmd = SPILCD_INIT_CODE; while(cmd[CMDINDEX_DATALEN]!=255) { lcdCmd_SPILCD(cmd[CMDINDEX_CMD], cmd[CMDINDEX_DATALEN], &cmd[3]); if (cmd[CMDINDEX_DELAY]) @@ -86,6 +89,11 @@ unsigned int lcdGetPixel_SPILCD(JsGraphics *gfx, int x, int y) { if (x&1) return c & 0xFFF; else return (c>>12) & 0xFFF; #endif +#if LCD_BPP==16 + int addr = (x<<1) + (y*LCD_STRIDE); + uint16_t *p = (uint16_t*)(&lcdBuffer[addr]); + return __builtin_bswap16(*p); +#endif } @@ -110,6 +118,11 @@ void lcdSetPixel_SPILCD(JsGraphics *gfx, int x, int y, unsigned int col) { else c = (c & 0xFF000FFF) | ((col & 0xFFF)<<12); *p = __builtin_bswap32(c); #endif +#if LCD_BPP==16 + int addr = (x<<1) + (y*LCD_STRIDE); + uint16_t *p = (uint16_t*)(&lcdBuffer[addr]); + *p = __builtin_bswap16(col); +#endif } void lcdFlip_SPILCD_callback() { @@ -122,11 +135,13 @@ void lcdFlip_SPILCD(JsGraphics *gfx) { // use nearest 2 pixels as we're sending 12 bits gfx->data.modMinX = (gfx->data.modMinX)&~1; gfx->data.modMaxX = (gfx->data.modMaxX+2)&~1; -#if LCD_BPP==12 +#if LCD_BPP==12 || LCD_BPP==16 + // Just send full rows as this allows us to issue a single SPI + // transfer. + // TODO: could swap to a transfer per row if we're filling less than half a row gfx->data.modMinX = 0; - gfx->data.modMaxX = LCD_WIDTH; + gfx->data.modMaxX = LCD_WIDTH-1; #else - unsigned char buffer2[LCD_STRIDE]; int xlen = gfx->data.modMaxX - gfx->data.modMinX; int xstart = gfx->data.modMinX; #endif @@ -140,7 +155,7 @@ void lcdFlip_SPILCD(JsGraphics *gfx) { buffer1[0] = 0; buffer1[1] = gfx->data.modMinX; buffer1[2] = 0; - buffer1[3] = gfx->data.modMaxX-1; + buffer1[3] = gfx->data.modMaxX; jshSPISendMany(LCD_SPI, buffer1, NULL, 4, NULL); jshPinSetValue(LCD_SPI_DC, 0); // command buffer1[0] = SPILCD_CMD_WINDOW_Y; @@ -149,22 +164,32 @@ void lcdFlip_SPILCD(JsGraphics *gfx) { buffer1[0] = 0; buffer1[1] = gfx->data.modMinY; buffer1[2] = 0; - buffer1[3] = gfx->data.modMaxY+1; + buffer1[3] = gfx->data.modMaxY; jshSPISendMany(LCD_SPI, buffer1, NULL, 4, NULL); jshPinSetValue(LCD_SPI_DC, 0); // command buffer1[0] = SPILCD_CMD_DATA; jshSPISendMany(LCD_SPI, buffer1, NULL, 1, NULL); jshPinSetValue(LCD_SPI_DC, 1); // data -#if LCD_BPP==12 - // if 12 bit, we can just push it out directly - jshSPISendMany( - LCD_SPI, - &lcdBuffer[LCD_STRIDE-gfx->data.modMinY], - 0, - (gfx->data.modMaxY+1-gfx->data.modMinY)*LCD_STRIDE, - NULL); +#if LCD_BPP==12 || LCD_BPP==16 + // FIXME: hack because SPI send on NRF52 fails for >65k transfers + // we should fix this in jshardware.c + unsigned char *p = &lcdBuffer[LCD_STRIDE*gfx->data.modMinY]; + int c = (gfx->data.modMaxY+1-gfx->data.modMinY)*LCD_STRIDE; + while (c) { + int n = c; + if (n>65535) n=65535; + jshSPISendMany( + LCD_SPI, + p, + 0, + n, + NULL); + p+=n; + c-=n; + } #else + unsigned char buffer2[LCD_STRIDE]; for (int y=gfx->data.modMinY;y<=gfx->data.modMaxY;y++) { unsigned char *buffer = (y&1)?buffer1:buffer2; // skip any lines that don't need updating @@ -210,6 +235,12 @@ void lcdInit_SPILCD(JsGraphics *gfx) { lcdSetPalette_SPILCD(0); +#ifdef LCD_BL + jshPinOutput(LCD_BL, 1); +#endif +#ifdef LCD_EN + jshPinOutput(LCD_EN, 1); +#endif jshPinOutput(LCD_SPI_CS,1); jshPinOutput(LCD_SPI_DC,1); jshPinOutput(LCD_SPI_SCK,1); @@ -221,10 +252,32 @@ void lcdInit_SPILCD(JsGraphics *gfx) { JshSPIInfo inf; jshSPIInitInfo(&inf); - inf.baudRate = 8000000; +#ifndef LCD_SPI_BITRATE +#define LCD_SPI_BITRATE 8000000 +#endif + inf.baudRate = LCD_SPI_BITRATE; inf.pinMOSI = LCD_SPI_MOSI; +#ifdef LCD_SPI_MISO + inf.pinMISO = LCD_SPI_MISO; +#endif inf.pinSCK = LCD_SPI_SCK; jshSPISetup(LCD_SPI, &inf); +#if defined(NRF52_SERIES) // configure 'high drive' for GPIOs + nrf_gpio_cfg( + LCD_SPI_MOSI, + GPIO_PIN_CNF_DIR_Output, + GPIO_PIN_CNF_INPUT_Disconnect, + GPIO_PIN_CNF_PULL_Disabled, + GPIO_PIN_CNF_DRIVE_H0H1, + GPIO_PIN_CNF_SENSE_Disabled); + nrf_gpio_cfg( + LCD_SPI_SCK, + GPIO_PIN_CNF_DIR_Output, + GPIO_PIN_CNF_INPUT_Disconnect, + GPIO_PIN_CNF_PULL_Disabled, + GPIO_PIN_CNF_DRIVE_H0H1, + GPIO_PIN_CNF_SENSE_Disabled); +#endif lcdSendInitCmd_SPILCD(); } diff --git a/libs/graphics/lcd_spilcd.h b/libs/graphics/lcd_spilcd.h index a83b19107..12bcaa74a 100644 --- a/libs/graphics/lcd_spilcd.h +++ b/libs/graphics/lcd_spilcd.h @@ -17,5 +17,5 @@ void lcdInit_SPILCD(JsGraphics *gfx); void lcdSetCallbacks_SPILCD(JsGraphics *gfx); void lcdFlip_SPILCD(JsGraphics *gfx); // run this to flip the offscreen buffer to the screen -void lcdCmd_SPILCD(int cmd, int dataLen, const char *data); // to send specific commands to the display +void lcdCmd_SPILCD(int cmd, int dataLen, const unsigned char *data); // to send specific commands to the display void lcdSetPalette_SPILCD(const char *pal); diff --git a/libs/graphics/lcd_spilcd_info.h b/libs/graphics/lcd_spilcd_info.h index 8ae240f38..2a020a54c 100644 --- a/libs/graphics/lcd_spilcd_info.h +++ b/libs/graphics/lcd_spilcd_info.h @@ -19,7 +19,7 @@ #define CMDINDEX_DATALEN 2 #ifdef LCD_CONTROLLER_ST7735 -static const char SPILCD_INIT_CODE[] = { +static const unsigned char SPILCD_INIT_CODE[] = { // CMD,DELAY,DATA_LEN,D0,D1,D2... // SWRESET Software reset - but we have hardware reset // 0x01, 20, 0, @@ -66,7 +66,7 @@ const unsigned char SPILCD_CMD_WINDOW_Y = 0x2B; const unsigned char SPILCD_CMD_DATA = 0x2C; #endif #ifdef LCD_CONTROLLER_ST7789V -static const char SPILCD_INIT_CODE[] = { +static const unsigned char SPILCD_INIT_CODE[] = { // CMD,DELAY,DATA_LEN,D0,D1,D2... 0x11, 100, 0, // SLPOUT Leave sleep mode 0x36,0,1,/*data*/0, // memory access control @@ -101,3 +101,59 @@ const unsigned char SPILCD_CMD_WINDOW_X = 0x2A; const unsigned char SPILCD_CMD_WINDOW_Y = 0x2B; const unsigned char SPILCD_CMD_DATA = 0x2C; #endif +#ifdef LCD_CONTROLLER_GC9A01 +static const unsigned char SPILCD_INIT_CODE[] = { +// CMD,DELAY,DATA_LEN,D0,D1,D2... + 0xfe,0,0, + 0xef,0,0, + 0xeb,0,1, 0x14, + 0x84,0,1, 0x40, + 0x88,0,1, 10, + 0x89,0,1, 0x21, + 0x8a,0,1, 0, + 0x8b,0,1, 0x80, + 0x8c,0,1, 1, + 0x8d,0,1, 1, + 0xb6,0,1, 0x20, + 0x36,0,1, 0x48, // Memory Access Control + 0x3a,0,1, 5, // could be 16/12 bit? + 0x90,0,4, 8, 8, 8, 8, + 0xbd,0,1, 6, + 0xbc,0,1, 0, + 0xff,0,3, 0x60, 1, 4, + 0xc3,0,1, 0x13, + 0xc4,0,1, 0x13, + 0xc9,0,1, 0x22, + 0xbe,0,1, 0x11, + 0xe1,0,2, 0x10, 0xe, + 0xdf,0,3, 0x21, 0xc, 2, + 0xf0,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, + 0xf1,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, + 0xf2,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, + 0xf3,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, + 0xed,0,2, 0x1b, 0xb, + 0xae,0,1, 0x74, + 0xcd,0,1, 99, + 0x70,0,9, 7, 9, 4, 0xe, 0xf, 9, 7, 8, 3, + 0xe8,0,1, 0x34, + 0x62,0,12, 0x18, 0xd, 0x71, 0xed, 0x70, 0x70, 0x18, 0xf, 0x71, 0xef, 0x70, 0x70, + 99,0,12, 0x18, 0x11, 0x71, 0xf1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xf3, 0x70, 0x70, + 100,0,7, 0x28, 0x29, 0xf1, 1, 0xf1, 0, 7, + 0x66,0,10, 0x3c, 0, 0xcd, 0x67, 0x45, 0x45, 0x10, 0, 0, 0, + 0x67,0,10, 0, 0x3c, 0, 0, 0, 1, 0x54, 0x10, 0x32, 0x98, + 0x74,0,7, 0x10, 0x85, 0x80, 0, 0, 0x4e, 0, + 0x98,0,2, 0x3e, 7, + 0x35,0,0, + 0x21,10,0, + 0x11,20,0, + 0x29,10,0, + 0x2c,0,0, + // End + 0, 0, 255/*DATA_LEN = 255 => END*/ + }; + +const unsigned char SPILCD_CMD_WINDOW_X = 0x2A; +const unsigned char SPILCD_CMD_WINDOW_Y = 0x2B; +const unsigned char SPILCD_CMD_DATA = 0x2C; +#endif + diff --git a/libs/graphics/vector_font.c b/libs/graphics/vector_font.c index e5b193b02..a4d225ac6 100644 --- a/libs/graphics/vector_font.c +++ b/libs/graphics/vector_font.c @@ -456,7 +456,7 @@ unsigned int vfDrawCharPtr(JsGraphics *gfx, int x1, int y1, int size, const uint poly[j*2 ] = (short)(x1 + vx*size*16/VF_SCALE); poly[j*2+1] = (short)(y1 + (vy+VF_OFFSET_Y)*size*16/VF_SCALE); } - graphicsFillPoly(gfx, polyLen, poly); + graphicsFillPoly(gfx, polyLen, poly, true/*antialias if available*/); } return (unsigned int)(((w+1+VF_CHAR_SPACING)*size*16/VF_SCALE+7)>>4); } diff --git a/scripts/build_platform_config.py b/scripts/build_platform_config.py index f45804c12..04b506bf6 100755 --- a/scripts/build_platform_config.py +++ b/scripts/build_platform_config.py @@ -378,8 +378,12 @@ if "LCD" in board.devices: codeOut("#define LCD_HEIGHT "+str(board.devices["LCD"]["height"])) if "bpp" in board.devices["LCD"]: codeOut("#define LCD_BPP "+str(board.devices["LCD"]["bpp"])) + if "bitrate" in board.devices["LCD"]: + codeOut("#define LCD_SPI_BITRATE "+str(board.devices["LCD"]["bitrate"])) if "pin_bl" in board.devices["LCD"]: codeOutDevicePin("LCD", "pin_bl", "LCD_BL") + if "pin_en" in board.devices["LCD"]: + codeOutDevicePin("LCD", "pin_en", "LCD_EN") if board.devices["LCD"]["controller"]=="fsmc": for i in range(0,16): codeOutDevicePin("LCD", "pin_d"+str(i), "LCD_FSMC_D"+str(i)) @@ -390,7 +394,7 @@ if "LCD" in board.devices: codeOutDevicePin("LCD", "pin_rs", "LCD_FSMC_RS") if "pin_reset" in board.devices["LCD"]: codeOutDevicePin("LCD", "pin_reset", "LCD_RESET") - if board.devices["LCD"]["controller"]=="ssd1306" or board.devices["LCD"]["controller"]=="st7567" or board.devices["LCD"]["controller"]=="st7789v" or board.devices["LCD"]["controller"]=="st7735": + if board.devices["LCD"]["controller"]=="ssd1306" or board.devices["LCD"]["controller"]=="st7567" or board.devices["LCD"]["controller"]=="st7789v" or board.devices["LCD"]["controller"]=="st7735" or board.devices["LCD"]["controller"]=="gc9a01": codeOutDevicePin("LCD", "pin_mosi", "LCD_SPI_MOSI") codeOutDevicePin("LCD", "pin_sck", "LCD_SPI_SCK") codeOutDevicePin("LCD", "pin_cs", "LCD_SPI_CS") @@ -402,8 +406,9 @@ if "LCD" in board.devices: codeOutDevicePin("LCD", "pin_cs", "LCD_SPI_CS") codeOutDevicePin("LCD", "pin_disp", "LCD_DISP") codeOutDevicePin("LCD", "pin_extcomin", "LCD_EXTCOMIN") - if "pin_bl" in board.devices["LCD"]: - codeOutDevicePin("LCD", "pin_bl", "LCD_BL") + if "pin_miso" in board.devices["LCD"]: + codeOutDevicePin("LCD", "pin_miso", "LCD_SPI_MISO") + if board.devices["LCD"]["controller"]=="st7789_8bit": codeOutDevicePins("LCD","LCD"); @@ -447,11 +452,13 @@ if "GPS" in board.devices: if "ACCEL" in board.devices: codeOut("#define ACCEL_DEVICE \""+board.devices["ACCEL"]["device"].upper()+"\"") + codeOut("#define ACCEL_DEVICE_"+board.devices["ACCEL"]["device"].upper()) codeOut("#define ACCEL_ADDR "+str(board.devices["ACCEL"]["addr"])) codeOutDevicePins("ACCEL", "ACCEL") if "MAG" in board.devices: codeOut("#define MAG_DEVICE \""+board.devices["MAG"]["device"].upper()+"\"") + codeOut("#define MAG_DEVICE_"+board.devices["MAG"]["device"].upper()) if "addr" in board.devices["MAG"]: codeOut("#define MAG_ADDR "+str(board.devices["MAG"]["addr"])) codeOutDevicePins("MAG", "MAG") @@ -463,6 +470,7 @@ if "TEMP" in board.devices: if "PRESSURE" in board.devices: codeOut("#define PRESSURE_DEVICE \""+board.devices["PRESSURE"]["device"].upper()+"\"") + codeOut("#define PRESSURE_DEVICE_"+board.devices["PRESSURE"]["device"].upper()) codeOut("#define PRESSURE_ADDR "+str(board.devices["PRESSURE"]["addr"])) codeOutDevicePins("PRESSURE", "PRESSURE") diff --git a/targetlibs/nrf5x_15/nrf52_config/sdk_config.h b/targetlibs/nrf5x_15/nrf52_config/sdk_config.h index 30582237a..6652eacdc 100644 --- a/targetlibs/nrf5x_15/nrf52_config/sdk_config.h +++ b/targetlibs/nrf5x_15/nrf52_config/sdk_config.h @@ -77,6 +77,11 @@ #define NRFX_UARTE_ENABLED 0 #define NRFX_UARTE0_ENABLED 0 #define NRFX_UARTE1_ENABLED 0 +#ifdef NRF52840 +#define NRFX_SPIM3_ENABLED 1 +#endif + +#define NRF_SDH_CLOCK_LF_ACCURACY NRF_CLOCK_LF_ACCURACY_500_PPM // Board Support @@ -7662,7 +7667,6 @@ #ifndef NRF_SDH_CLOCK_LF_ACCURACY #define NRF_SDH_CLOCK_LF_ACCURACY 7 - #endif // diff --git a/targetlibs/nrf5x_15/nrf5x_linkers/secure_bootloader_gcc_nrf52.ld b/targetlibs/nrf5x_15/nrf5x_linkers/secure_bootloader_gcc_nrf52.ld index e8ee99a63..17968e84a 100644 --- a/targetlibs/nrf5x_15/nrf5x_linkers/secure_bootloader_gcc_nrf52.ld +++ b/targetlibs/nrf5x_15/nrf5x_linkers/secure_bootloader_gcc_nrf52.ld @@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0xf8000, LENGTH = 0x6000 + FLASH (rx) : ORIGIN = 0xf7000, LENGTH = 0x7000 RAM (rwx) : ORIGIN = 0x200057b8, LENGTH = 0x3a848 uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4 mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000 @@ -136,4 +136,4 @@ SECTIONS } INSERT AFTER .text -INCLUDE "nrf_common.ld" \ No newline at end of file +INCLUDE "nrf_common.ld" diff --git a/targets/nrf5x/jshardware.c b/targets/nrf5x/jshardware.c index 6067ca825..40a588468 100644 --- a/targets/nrf5x/jshardware.c +++ b/targets/nrf5x/jshardware.c @@ -285,7 +285,11 @@ volatile bool nrf_analog_read_interrupted = false; #define SPI_MAXAMT 65535 #endif +#ifdef NRF52840 +static nrf_drv_spi_t spi0 = NRF_DRV_SPI_INSTANCE(3); // USE SPI3 on 52840 as it's far more complete +#else static nrf_drv_spi_t spi0 = NRF_DRV_SPI_INSTANCE(0); +#endif bool spi0Initialised = false; unsigned char *spi0RxPtr; unsigned char *spi0TxPtr; @@ -1734,10 +1738,15 @@ void jshSPISetup(IOEventFlags device, JshSPIInfo *inf) { freq = SPI_FREQUENCY_FREQUENCY_M2; else if (inf->baudRate<((4000000+8000000)/2)) freq = SPI_FREQUENCY_FREQUENCY_M4; +#ifdef NRF52840 + // NRF52840 supports >8MHz but ONLY on SPIM3 + else if (inf->baudRate>((16000000+32000000)/2) && spi0.inst_idx==3) + freq = SPIM_FREQUENCY_FREQUENCY_M32; + else if (inf->baudRate>((8000000+16000000)/2) && spi0.inst_idx==3) + freq = SPIM_FREQUENCY_FREQUENCY_M16; +#endif else freq = SPI_FREQUENCY_FREQUENCY_M8; - // NRF52840 supports >8MHz but ONLY on SPIM3 - /* Numbers for SPI_FREQUENCY_FREQUENCY_M16/SPI_FREQUENCY_FREQUENCY_M32 are in the nRF52 datasheet but they don't appear to actually work (and @@ -1822,7 +1831,9 @@ int jshSPISend(IOEventFlags device, int data) { return rx; #endif #endif - +/* unsigned char d = data; + jshSPISendMany(device, &d, &d, 1, NULL); + return d;*/ } /** Send 16 bit data through the given SPI device. */ diff --git a/targets/nrf5x_dfu/lcd.c b/targets/nrf5x_dfu/lcd.c index d16becfd3..f224c41ed 100644 --- a/targets/nrf5x_dfu/lcd.c +++ b/targets/nrf5x_dfu/lcd.c @@ -109,7 +109,7 @@ void lcd_wr(int data) { } } #endif -#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_LPM013M126) +#if defined(LCD_CONTROLLER_ST7789V) || defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_LPM013M126) || defined(LCD_CONTROLLER_GC9A01) void lcd_pixel(int x, int y) { // each byte is horizontal @@ -280,7 +280,6 @@ void lcd_flip() { if (ymin<=ymax) { ymin=ymin*2; ymax=ymax*2+1; - jshPinOutput(LCD_BL,0); // testing jshPinSetValue(LCD_SPI_CS, 0); jshPinSetValue(LCD_SPI_DC, 0); // command lcd_wr(0x2A); @@ -314,7 +313,7 @@ void lcd_flip() { } void lcd_init() { jshPinOutput(3,1); // general VDD power? - jshPinOutput(LCD_BL,1); // backlight + jshPinOutput(LCD_BL, LCD_BL_ON); // backlight // LCD Init 1 jshPinOutput(LCD_SPI_CS,1); jshPinOutput(LCD_SPI_DC,1); @@ -349,7 +348,7 @@ void lcd_init() { } void lcd_kill() { - jshPinOutput(LCD_BL,0); + jshPinOutput(LCD_BL, !LCD_BL_ON); lcd_cmd(0xAE, 0, NULL); // DISPOFF } #endif @@ -490,12 +489,13 @@ void lcd_kill() { } #endif -#ifdef LCD_CONTROLLER_ST7735 +#if defined(LCD_CONTROLLER_ST7735) || defined(LCD_CONTROLLER_GC9A01) #define CMDINDEX_CMD 0 #define CMDINDEX_DELAY 1 #define CMDINDEX_DATALEN 2 -static const char ST7735_INIT_CODE[] = { +static const char SPILCD_INIT_CODE[] = { +#ifdef LCD_CONTROLLER_ST7735 // CMD,DELAY,DATA_LEN,D0,D1,D2... // SWRESET Software reset 0x01, 150, 0, @@ -534,7 +534,54 @@ static const char ST7735_INIT_CODE[] = { 0x29, 100, 0, // NORON Normal on 0x13, 10, 0, - // End +#endif +#ifdef LCD_CONTROLLER_GC9A01 + 0xfe,0,0, + 0xef,0,0, + 0xeb,0,1, 0x14, + 0x84,0,1, 0x40, + 0x88,0,1, 10, + 0x89,0,1, 0x21, + 0x8a,0,1, 0, + 0x8b,0,1, 0x80, + 0x8c,0,1, 1, + 0x8d,0,1, 1, + 0xb6,0,1, 0x20, + 0x36,0,1, 0x48, // Memory Access Control + 0x3a,0,1, 5, // could be 16/12 bit? + 0x90,0,4, 8, 8, 8, 8, + 0xbd,0,1, 6, + 0xbc,0,1, 0, + 0xff,0,3, 0x60, 1, 4, + 0xc3,0,1, 0x13, + 0xc4,0,1, 0x13, + 0xc9,0,1, 0x22, + 0xbe,0,1, 0x11, + 0xe1,0,2, 0x10, 0xe, + 0xdf,0,3, 0x21, 0xc, 2, + 0xf0,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, + 0xf1,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, + 0xf2,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, + 0xf3,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, + 0xed,0,2, 0x1b, 0xb, + 0xae,0,1, 0x74, + 0xcd,0,1, 99, + 0x70,0,9, 7, 9, 4, 0xe, 0xf, 9, 7, 8, 3, + 0xe8,0,1, 0x34, + 0x62,0,12, 0x18, 0xd, 0x71, 0xed, 0x70, 0x70, 0x18, 0xf, 0x71, 0xef, 0x70, 0x70, + 99,0,12, 0x18, 0x11, 0x71, 0xf1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xf3, 0x70, 0x70, + 100,0,7, 0x28, 0x29, 0xf1, 1, 0xf1, 0, 7, + 0x66,0,10, 0x3c, 0, 0xcd, 0x67, 0x45, 0x45, 0x10, 0, 0, 0, + 0x67,0,10, 0, 0x3c, 0, 0, 0, 1, 0x54, 0x10, 0x32, 0x98, + 0x74,0,7, 0x10, 0x85, 0x80, 0, 0, 0x4e, 0, + 0x98,0,2, 0x3e, 7, + 0x35,0,0, + 0x21,10,0, + 0x11,20,0, + 0x29,10,0, + 0x2c,0,0, +#endif + // End 0, 0, 255/*DATA_LEN = 255 => END*/ }; void lcd_cmd(int cmd, int dataLen, const char *data) { @@ -552,30 +599,41 @@ void lcd_cmd(int cmd, int dataLen, const char *data) { } void lcd_flip() { +#ifndef LCD_STORE_MODIFIED + int ymin=0; + int ymax=LCD_HEIGHT-1; +#endif if (ymin<=ymax) { - jshPinSetValue(LCD_SPI_CS, 0); jshPinSetValue(LCD_SPI_DC, 0); // command + jshPinSetValue(LCD_SPI_CS, 0); lcd_wr(0x2A); - jshPinSetValue(LCD_SPI_DC, 1); // data - lcd_wr(0); - lcd_wr(0); - lcd_wr(0); - lcd_wr(LCD_WIDTH); jshPinSetValue(LCD_SPI_CS, 1); + jshPinSetValue(LCD_SPI_DC, 1); // data jshPinSetValue(LCD_SPI_CS, 0); - jshPinSetValue(LCD_SPI_DC, 0); // command - lcd_wr(0x2B); - jshPinSetValue(LCD_SPI_DC, 1); // data lcd_wr(0); - lcd_wr(LCD_HEIGHT - (ymax+1)); lcd_wr(0); - lcd_wr(LCD_HEIGHT - ymin); - jshPinSetValue(LCD_SPI_DC, 0); // command + lcd_wr(0); + lcd_wr(LCD_WIDTH-1); jshPinSetValue(LCD_SPI_CS, 1); + jshPinSetValue(LCD_SPI_DC, 0); // command + jshPinSetValue(LCD_SPI_CS, 0); + lcd_wr(0x2B); + jshPinSetValue(LCD_SPI_CS, 1); + jshPinSetValue(LCD_SPI_DC, 1); // data + jshPinSetValue(LCD_SPI_CS, 0); + lcd_wr(0); + lcd_wr(ymin); + lcd_wr(0); + lcd_wr(ymax); + jshPinSetValue(LCD_SPI_CS, 1); + jshPinSetValue(LCD_SPI_DC, 0); // command jshPinSetValue(LCD_SPI_CS, 0); lcd_wr(0x2C); + jshPinSetValue(LCD_SPI_CS, 1); jshPinSetValue(LCD_SPI_DC, 1); // data - for (int y=ymax;y>=ymin;y--) { + jshPinSetValue(LCD_SPI_CS, 0); + for (int y=ymin;y<=ymax;y++) { +#ifdef LCD_CONTROLLER_ST7735 for (int x=LCD_WIDTH-1;x>=0;) { bool a = lcd_data[(x>>3)+(y*LCD_ROWSTRIDE)]&1<<(x&7);x--; bool b = lcd_data[(x>>3)+(y*LCD_ROWSTRIDE)]&1<<(x&7);x--; @@ -583,6 +641,14 @@ void lcd_flip() { lcd_wr((a?0xF0:0)|(b?0x0F:0)); lcd_wr(b?0xFF:0); } +#endif +#ifdef LCD_CONTROLLER_GC9A01 + for (int x=0;x>3)+(y*LCD_ROWSTRIDE)]&1<<(x&7); + lcd_wr(a?0xFF:0); + lcd_wr(a?0xFF:0); + } +#endif } jshPinSetValue(LCD_SPI_CS,1); } @@ -591,8 +657,13 @@ void lcd_flip() { } void lcd_init() { +#ifdef GPS_PIN_EN jshPinOutput(GPS_PIN_EN,1); // GPS off - jshPinOutput(LCD_BL,0); // backlight on +#endif + jshPinOutput(LCD_BL, LCD_BL_ON); // backlight on +#ifdef LCD_EN + jshPinOutput(LCD_EN,1); // enable on +#endif // LCD Init 1 jshPinOutput(LCD_SPI_CS,1); jshPinOutput(LCD_SPI_DC,1); @@ -603,8 +674,8 @@ void lcd_init() { jshPinOutput(LCD_SPI_RST, 1); jshDelayMicroseconds(10000); - // Send initialization commands to ST7735 - const char *cmd = ST7735_INIT_CODE; + // Send initialization commands + const char *cmd = SPILCD_INIT_CODE; while(cmd[CMDINDEX_DATALEN]!=255) { lcd_cmd(cmd[CMDINDEX_CMD], cmd[CMDINDEX_DATALEN], &cmd[3]); if (cmd[CMDINDEX_DELAY]) @@ -613,8 +684,11 @@ void lcd_init() { } } void lcd_kill() { - jshPinOutput(LCD_BL,1); // backlight off + jshPinOutput(LCD_BL,!LCD_BL_ON); // backlight off lcd_cmd(0x28, 0, NULL); // display off +#ifdef LCD_EN + jshPinOutput(LCD_EN,0); // enable off +#endif } #endif @@ -661,10 +735,10 @@ void lcd_init() { jshPinOutput(LCD_SPI_MOSI,1); jshPinOutput(LCD_DISP,1); jshPinOutput(LCD_EXTCOMIN,1); - jshPinOutput(LCD_BL,1); // backlight on + jshPinOutput(LCD_BL, LCD_BL_ON); // backlight on } void lcd_kill() { - jshPinOutput(LCD_BL,0); // backlight off + jshPinOutput(LCD_BL, !LCD_BL_ON); // backlight off jshPinOutput(LCD_DISP,0); // display off } diff --git a/targets/nrf5x_dfu/lcd.h b/targets/nrf5x_dfu/lcd.h index db09101ea..7bf8d8cba 100644 --- a/targets/nrf5x_dfu/lcd.h +++ b/targets/nrf5x_dfu/lcd.h @@ -22,12 +22,14 @@ #define LCD_DATA_WIDTH 120 // pixel doubled #define LCD_DATA_HEIGHT 120 // pixel doubled #define LCD_STORE_MODIFIED +#define LCD_BL_ON 1 #endif #ifdef LCD_CONTROLLER_ST7735 // F5 #define LCD #define LCD_DATA_WIDTH 128 #define LCD_DATA_HEIGHT 96 #define LCD_STORE_MODIFIED +#define LCD_BL_ON 0 #endif #ifdef LCD_CONTROLLER_ST7789_8BIT // Bangle.js #define LCD @@ -45,6 +47,16 @@ #define LCD_DATA_WIDTH 88 // pixel doubled #define LCD_DATA_HEIGHT 88 // pixel doubled #define LCD_STORE_MODIFIED +#define LCD_BL_ON 1 +#endif +#ifdef LCD_CONTROLLER_GC9A01 +#define LCD +#define LCD_DATA_WIDTH 240 +#define LCD_DATA_HEIGHT 240 +#define LCD_STORE_MODIFIED +#define LCD_START_X 60 +#define LCD_START_Y 60 +#define LCD_BL_ON 1 #endif #ifndef LCD_START_X diff --git a/targets/nrf5x_dfu/sdk15/sdk_config.h b/targets/nrf5x_dfu/sdk15/sdk_config.h index 5ec2b5af8..4c6ca4aad 100644 --- a/targets/nrf5x_dfu/sdk15/sdk_config.h +++ b/targets/nrf5x_dfu/sdk15/sdk_config.h @@ -79,7 +79,7 @@ // NRF_BL_DFU_ENTER_METHOD_BUTTON - Enter DFU mode on button press. //========================================================== #ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON -#define NRF_BL_DFU_ENTER_METHOD_BUTTON 1 +#define NRF_BL_DFU_ENTER_METHOD_BUTTON 0 #endif // NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN - Button for entering DFU mode. @@ -117,7 +117,8 @@ // <31=> 31 (P0.31) #ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN -#define NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN 16 +//#define NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN -1 +#error DFU button must be defined #endif //