mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Merging Dickens-specific changes into master
This commit is contained in:
parent
61effcaffd
commit
138452fb65
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
import serial
|
||||
|
||||
@ -35,7 +35,7 @@ import pinutils;
|
||||
# D42(btn) GND
|
||||
|
||||
# unfitted big flash-ish chip
|
||||
# o D14 NC?
|
||||
# o D14 VCC
|
||||
# D15 D17
|
||||
# D2 D19
|
||||
# GND D18
|
||||
@ -61,7 +61,7 @@ info = {
|
||||
'espruino_page_link' : '',
|
||||
'default_console' : "EV_BLUETOOTH",
|
||||
'variables' : 5000, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
|
||||
'io_buffer_size' : 512, # How big is the input buffer (in 4 byte words). Default on nRF52 is 256
|
||||
'io_buffer_size' : 512,
|
||||
'bootloader' : 1,
|
||||
'binary_name' : 'espruino_%v_dickens.hex',
|
||||
'build' : {
|
||||
@ -69,14 +69,27 @@ info = {
|
||||
'libraries' : [
|
||||
'BLUETOOTH',
|
||||
'GRAPHICS',
|
||||
'LCD_SPI'
|
||||
'LCD_SPI',
|
||||
'JIT'
|
||||
],
|
||||
'makefile' : [
|
||||
# 'DEFINES += -DNRF_LOG_ENABLED=1 -DNRF_LOG_FILTERS_ENABLED=0',
|
||||
'DEFINES += -DCONFIG_NFCT_PINS_AS_GPIOS', # Allow the reset pin to work
|
||||
'DEFINES += -DCONFIG_NFCT_PINS_AS_GPIOS', # Allow us to use NFC pins as GPIO
|
||||
'DEFINES += -DESPR_LSE_ENABLE=1', # Ensure low speed external osc enabled
|
||||
'DEFINES += -DNRF_SDH_BLE_GATT_MAX_MTU_SIZE=131', # 23+x*27 rule as per https://devzone.nordicsemi.com/f/nordic-q-a/44825/ios-mtu-size-why-only-185-bytes
|
||||
'LDFLAGS += -Xlinker --defsym=LD_APP_RAM_BASE=0x2ec0', # set RAM base to match MTU
|
||||
# 'DEFINES += -DESPR_REGOUT0_1_8V=1', # Leave REGOUT0 as 1.8v (not 3.3v) - seems to be what original watch firmware did
|
||||
'DEFINES += -DESPR_DCDC_ENABLE=1', # Use DC/DC converter
|
||||
'ESPR_BLUETOOTH_ANCS=1', # Enable ANCS (Apple notifications) support
|
||||
'DEFINES += -DSPIFLASH_SLEEP_CMD', # SPI flash needs to be explicitly slept and woken up
|
||||
'DEFINES += -DSPIFLASH_READ2X', # Read SPI flash at 2x speed using MISO and MOSI for IO
|
||||
'DEFINES += -DESPR_USE_SPI3=1', # Use SPI3 (even though it has errata 195) as it's much faster
|
||||
'DEFINES += -DESPR_BACKLIGHT_FADE=1', # Smoothly fade backlight on and off
|
||||
'DEFINES += -DNRF_BL_DFU_ENTER_METHOD_BUTTON=1 -DNRF_BL_DFU_ENTER_METHOD_BUTTON_PIN=29',
|
||||
'DEFINES += -DNRF_BOOTLOADER_NO_WRITE_PROTECT=1', # By default the bootloader protects flash. Avoid this (a patch for NRF_BOOTLOADER_NO_WRITE_PROTECT must be applied first)
|
||||
'DEFINES += -DBUTTONPRESS_TO_REBOOT_BOOTLOADER',
|
||||
'DEFINES += -DESPR_BOOTLOADER_SPIFLASH', # Allow bootloader to flash direct from SPI flash
|
||||
'DEFINES += -DAPP_TIMER_OP_QUEUE_SIZE=6', # Bangle.js accelerometer poll handler needs something else in queue size
|
||||
|
||||
'BOOTLOADER_SETTINGS_FAMILY = NRF52840',
|
||||
'DFU_PRIVATE_KEY=targets/nrf5x_dfu/dfu_private_key.pem',
|
||||
@ -85,16 +98,24 @@ info = {
|
||||
'DEFINES+=-DBLUETOOTH_NAME_PREFIX=\'"Dickens"\'',
|
||||
'DEFINES+=-DCUSTOM_GETBATTERY=jswrap_banglejs_getBattery',
|
||||
'DEFINES+=-DDUMP_IGNORE_VARIABLES=\'"g\\0"\'',
|
||||
'DEFINES+=-DESPR_GRAPHICS_INTERNAL=1',
|
||||
'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',
|
||||
'INCLUDE += -I$(ROOT)/libs/banglejs -I$(ROOT)/libs/dickens -I$(ROOT)/libs/misc',
|
||||
'WRAPPERSOURCES += libs/banglejs/jswrap_bangle.c',
|
||||
'WRAPPERSOURCES += libs/dickens/jswrap_dickens.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_architekt10.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_architekt12.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_architekt15.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_architekt35.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_grotesk14.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_grotesk16.c',
|
||||
'WRAPPERSOURCES += libs/graphics/jswrap_font_grotesk20.c',
|
||||
'SOURCES += libs/graphics/line_font.c',
|
||||
'SOURCES += libs/misc/stepcount.c',
|
||||
'JSMODULESOURCES += libs/js/banglejs/locale.min.js',
|
||||
'DEFINES += -DBANGLEJS',
|
||||
'DEFINES += -DESPR_NO_LOADING_SCREEN', # disable 'loading...' message when switching apps
|
||||
|
||||
'NRF_SDK15=1'
|
||||
]
|
||||
@ -115,10 +136,10 @@ chip = {
|
||||
'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' : ((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' : 768, # 3MB of 4MB flash
|
||||
@ -143,7 +164,7 @@ devices = {
|
||||
'pin_mosi' : 'D5',
|
||||
'pin_miso' : 'D27',
|
||||
'pin_en' : 'D43',
|
||||
'pin_bl' : 'D33', # TESTED!
|
||||
'pin_bl' : 'D33', # Also enables the power supply for the vibration motor
|
||||
'bitrate' : 32000000
|
||||
},
|
||||
'BAT' : {
|
||||
|
||||
4151
libs/banglejs/dickens_storage_default.c
Normal file
4151
libs/banglejs/dickens_storage_default.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -639,6 +639,10 @@ JshI2CInfo i2cInternal;
|
||||
#define HOME_BTN 2
|
||||
#define DEFAULT_BTN_LOAD_TIMEOUT 4000
|
||||
#define DEFAULT_LCD_POWER_TIMEOUT 20000
|
||||
#define DEFAULT_TWIST_THRESHOLD 600
|
||||
#define DEFAULT_TWIST_MAXY 0
|
||||
#define WAKE_FROM_OFF_TIME 1000
|
||||
#define MAG_MAX_RANGE 400 // maximum range of readings allowed between magmin/magmax. In the UK at ~20uT 250 is ok, and the max field strength us ~40uT
|
||||
#endif
|
||||
|
||||
#ifdef ID205
|
||||
@ -681,6 +685,15 @@ JshI2CInfo i2cInternal;
|
||||
#ifndef DEFAULT_LOCK_TIMEOUT
|
||||
#define DEFAULT_LOCK_TIMEOUT 30000 // in msec - default for lockTimeout
|
||||
#endif
|
||||
#ifndef DEFAULT_TWIST_THRESHOLD
|
||||
#define DEFAULT_TWIST_THRESHOLD 800
|
||||
#endif
|
||||
#ifndef DEFAULT_TWIST_MAXY
|
||||
#define DEFAULT_TWIST_MAXY -800
|
||||
#endif
|
||||
#ifndef WAKE_FROM_OFF_TIME
|
||||
#define WAKE_FROM_OFF_TIME 200
|
||||
#endif
|
||||
|
||||
#ifdef TOUCH_DEVICE
|
||||
short touchX, touchY; ///< current touch event coordinates
|
||||
@ -833,8 +846,10 @@ bool lcdFadeHandlerActive;
|
||||
Vector3 mag, magmin, magmax;
|
||||
bool magOnWhenCharging;
|
||||
#define MAG_CHARGE_TIMEOUT 3000 // time after charging when magnetometer value gets automatically reset
|
||||
#ifndef MAG_MAX_RANGE
|
||||
#define MAG_MAX_RANGE 500 // maximum range of readings allowed between magmin/magmax. In the UK at ~20uT 250 is ok, and the max field strength us ~40uT
|
||||
#endif
|
||||
#endif // MAG_I2C
|
||||
#ifdef MAG_DEVICE_GMC303
|
||||
uint8_t magCalib[3]; // Magnetic Coefficient Registers - used to rescale the magnetometer values
|
||||
#endif
|
||||
@ -869,9 +884,9 @@ int accelGestureInactiveCount = 4;
|
||||
/// how many samples must a gesture have before we notify about it?
|
||||
int accelGestureMinLength = 10;
|
||||
/// How much acceleration to register a twist of the watch strap?
|
||||
int twistThreshold = 800;
|
||||
int twistThreshold = DEFAULT_TWIST_THRESHOLD;
|
||||
/// Maximum acceleration in Y to trigger a twist (low Y means watch is facing the right way up)
|
||||
int twistMaxY = -800;
|
||||
int twistMaxY = DEFAULT_TWIST_MAXY;
|
||||
/// How little time (in ms) must a twist take from low->high acceleration?
|
||||
int twistTimeout = 1000;
|
||||
|
||||
@ -1171,8 +1186,14 @@ void peripheralPollHandler() {
|
||||
if (homeBtnTimer < TIMER_MAX) {
|
||||
homeBtnTimer += pollInterval;
|
||||
if (btnLoadTimeout && (homeBtnTimer >= btnLoadTimeout)) {
|
||||
bangleTasks |= JSBT_RESET;
|
||||
jshHadEvent();
|
||||
#ifdef DICKENS
|
||||
if (!jsfIsStorageEmpty()) { // Only reset if there's something in flash storage
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
bangleTasks |= JSBT_RESET;
|
||||
jshHadEvent();
|
||||
}
|
||||
homeBtnTimer = TIMER_MAX;
|
||||
// Allow home button to break out of debugger
|
||||
if (jsiStatus & JSIS_IN_DEBUGGER) {
|
||||
@ -1410,7 +1431,26 @@ void peripheralPollHandler() {
|
||||
if (tapType) {
|
||||
// report tap
|
||||
tapInfo = buf[0] | (tapType<<6);
|
||||
bangleTasks |= JSBT_ACCEL_TAPPED;
|
||||
bool handled = false;
|
||||
// wake on tap, for front (for Dickens)
|
||||
#ifdef DICKENS
|
||||
if ((bangleFlags&JSBF_WAKEON_TOUCH) && (tapInfo&1)) {
|
||||
if (!(bangleFlags&JSBF_LCD_ON)) {
|
||||
bangleTasks |= JSBT_LCD_ON;
|
||||
handled = true;
|
||||
}
|
||||
if (!(bangleFlags&JSBF_LCD_BL_ON)) {
|
||||
bangleTasks |= JSBT_LCD_BL_ON;
|
||||
handled = true;
|
||||
}
|
||||
if (bangleFlags&JSBF_LOCKED) {
|
||||
bangleTasks |= JSBT_UNLOCK;
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!handled)
|
||||
bangleTasks |= JSBT_ACCEL_TAPPED;
|
||||
jshHadEvent();
|
||||
}
|
||||
// clear the IRQ flags
|
||||
@ -1437,6 +1477,15 @@ void peripheralPollHandler() {
|
||||
#endif
|
||||
#ifdef ACCEL_DEVICE_KX126
|
||||
newy = -newy;
|
||||
#endif
|
||||
#ifdef LCD_ROTATION
|
||||
#if LCD_ROTATION == 180
|
||||
newy = -newy;
|
||||
#elif LCD_ROTATION == 0
|
||||
newx = -newx; //consistent directions with Bangle
|
||||
#else
|
||||
#error "LCD rotation is only implemented for 180 and 0 degrees"
|
||||
#endif
|
||||
#endif
|
||||
// if the graphics instance is rotated, also rotate accelerometer values
|
||||
if (graphicsInternal.data.flags & JSGRAPHICSFLAGS_INVERT_X) newx = -newx;
|
||||
@ -1504,8 +1553,8 @@ void peripheralPollHandler() {
|
||||
bangleTasks |= JSBT_ACCEL_DATA;
|
||||
jshHadEvent();
|
||||
}
|
||||
// check for 'face up'
|
||||
faceUp = (acc.z<-6700) && (acc.z>-9000) && abs(acc.x)<2048 && abs(acc.y)<2048;
|
||||
// check for 'face up' (or tilted towards the viewer, which reduces the Y value)
|
||||
faceUp = (acc.z<-5700) && (acc.z>-9000) && abs(acc.x)<2048 && abs(acc.y+4096)<2048;
|
||||
if (faceUp!=wasFaceUp) {
|
||||
faceUpTimer = 0;
|
||||
faceUpSent = false;
|
||||
@ -1980,12 +2029,12 @@ static void jswrap_banglejs_setLCDPowerController(bool isOn) {
|
||||
// TODO: LCD_CONTROLLER_GC9A01 - has an enable/power pin
|
||||
if (isOn) { // wake
|
||||
lcdCmd_SPILCD(0x11, 0, NULL); // SLPOUT
|
||||
jshDelayMicroseconds(20);
|
||||
jshDelayMicroseconds(5000); // For GC9A01, we should wait 5ms after SLPOUT for power supply and clocks to stabilise before sending next command
|
||||
lcdCmd_SPILCD(0x29, 0, NULL); // DISPON
|
||||
} else { // sleep
|
||||
lcdCmd_SPILCD(0x28, 0, NULL); // DISPOFF
|
||||
jshDelayMicroseconds(20);
|
||||
lcdCmd_SPILCD(0x10, 0, NULL); // SLPIN
|
||||
lcdCmd_SPILCD(0x10, 0, NULL); // SLPIN - for GC9A01, it takeds 120ms to get into sleep mode after sending SPLIN
|
||||
}
|
||||
#endif
|
||||
#ifdef LCD_EN
|
||||
@ -2133,7 +2182,6 @@ void jswrap_banglejs_setLCDPower(bool isOn) {
|
||||
#ifdef ESPR_BACKLIGHT_FADE
|
||||
if (isOn) jswrap_banglejs_setLCDPowerController(1);
|
||||
else jswrap_banglejs_setLCDPowerBacklight(0); // RB: don't turn on the backlight here if fading is enabled
|
||||
jswrap_banglejs_setLCDPowerBacklight(isOn);
|
||||
#else
|
||||
jswrap_banglejs_setLCDPowerController(isOn);
|
||||
jswrap_banglejs_setLCDPowerBacklight(isOn);
|
||||
@ -2457,6 +2505,9 @@ which the touchscreen/buttons start being ignored). To set both separately, use
|
||||
`Bangle.setOptions`
|
||||
*/
|
||||
void jswrap_banglejs_setLCDTimeout(JsVarFloat timeout) {
|
||||
#ifdef DICKENS
|
||||
inactivityTimer = 0; // reset the LCD timeout timer
|
||||
#endif
|
||||
if (!isfinite(timeout))
|
||||
timeout=0;
|
||||
else if (timeout<0) timeout=0;
|
||||
@ -3625,7 +3676,10 @@ NO_INLINE void jswrap_banglejs_init() {
|
||||
|
||||
/* If first run and button is held down, enter recovery mode. During this
|
||||
we will try not to access storage */
|
||||
#ifndef DICKENS
|
||||
#ifdef DICKENS
|
||||
if (jshPinGetValue(BTN1_PININDEX) && jshPinGetValue(BTN4_PININDEX))
|
||||
recoveryMode = true;
|
||||
#else
|
||||
if (jshPinGetValue(HOME_BTN_PININDEX))
|
||||
recoveryMode = true;
|
||||
#endif
|
||||
@ -3653,6 +3707,14 @@ NO_INLINE void jswrap_banglejs_init() {
|
||||
if (!recoveryMode) {
|
||||
JsVar *settingsFN = jsvNewFromString("setting.json");
|
||||
JsVar *settings = jswrap_storage_readJSON(settingsFN,true);
|
||||
#ifdef DICKENS
|
||||
// Remove the whitelist from settings, in case it was set when the watch
|
||||
// was running the original factory firmware
|
||||
if (jsvIsObject(settings)) {
|
||||
jsvObjectRemoveChild(settings, "whitelist");
|
||||
jswrap_storage_writeJSON(settingsFN, settings);
|
||||
}
|
||||
#endif
|
||||
jsvUnLock(settingsFN);
|
||||
JsVar *v;
|
||||
v = jsvIsObject(settings) ? jsvObjectGetChildIfExists(settings,"beep") : 0;
|
||||
@ -3809,6 +3871,22 @@ NO_INLINE void jswrap_banglejs_init() {
|
||||
}
|
||||
w = (int)(unsigned char)jsvGetCharInString(img, 0);
|
||||
h = (int)(unsigned char)jsvGetCharInString(img, 1);
|
||||
char addrStr[20];
|
||||
#ifndef EMULATED
|
||||
JsVar *addr = jswrap_ble_getAddress(); // Write MAC address in bottom right
|
||||
#else
|
||||
JsVar *addr = jsvNewFromString("Emulated");
|
||||
#endif
|
||||
jsvGetString(addr, addrStr, sizeof(addrStr));
|
||||
jsvUnLock(addr);
|
||||
#if (defined(DICKENS) || defined(EMSCRIPTEN_DICKENS))
|
||||
int y=111;
|
||||
jswrap_graphics_drawCString(&graphicsInternal,20,y-10,"---------------");
|
||||
jswrap_graphics_drawCString(&graphicsInternal,20,y,"PROJECT DICKENS");
|
||||
jswrap_graphics_drawCString(&graphicsInternal,20,y+10,"---------------");
|
||||
jswrap_graphics_drawCString(&graphicsInternal,20,y+30,JS_VERSION);
|
||||
jswrap_graphics_drawCString(&graphicsInternal,20,y+40,addrStr);
|
||||
#else // not DICKENS
|
||||
int y=(LCD_HEIGHT-h)/2;
|
||||
jsvUnLock2(jswrap_graphics_drawImage(graphics,img,(LCD_WIDTH-w)/2,y,NULL),img);
|
||||
if (drawInfo) {
|
||||
@ -3826,8 +3904,13 @@ NO_INLINE void jswrap_banglejs_init() {
|
||||
jswrap_graphics_drawCString(&graphicsInternal,8,y+10,addrStr);
|
||||
jswrap_graphics_drawCString(&graphicsInternal,8,y+20,"Copyright 2021 G.Williams");
|
||||
}
|
||||
#endif // DICKENS
|
||||
}
|
||||
graphicsInternalFlip();
|
||||
#ifdef DICKENS
|
||||
if (showSplashScreen)
|
||||
#endif
|
||||
graphicsInternalFlip();
|
||||
|
||||
graphicsStructResetState(&graphicsInternal);
|
||||
// no need to unlock graphics as we stored it in 'graphicsVar'
|
||||
#endif
|
||||
@ -3880,17 +3963,20 @@ NO_INLINE void jswrap_banglejs_init() {
|
||||
jshDelayMicroseconds(2000);
|
||||
jswrap_banglejs_accelWr(KX126_CNTL3,KX126_CNTL3_OTP_12P5|KX126_CNTL3_OTDT_400|KX126_CNTL3_OWUF_0P781); // CNTL3 12.5Hz tilt, 400Hz tap, 0.781Hz motion detection
|
||||
jswrap_banglejs_accelWr(KX126_ODCNTL,KX126_ODCNTL_OSA_12P5); // ODCNTL - 12.5Hz output data rate (ODR), with low-pass filter set to ODR/9
|
||||
jswrap_banglejs_accelWr(KX126_INC1,0); // INC1 - interrupt output pin INT1 disabled
|
||||
jswrap_banglejs_accelWr(KX126_INC2,0); // INC2 - wake-up & back-to-sleep ignores all 3 axes
|
||||
jswrap_banglejs_accelWr(KX126_INC3,0); // INC3 - tap detection ignores all 3 axes
|
||||
jswrap_banglejs_accelWr(KX126_INC4,0); // INC4 - no routing of interrupt reporting to pin INT1
|
||||
jswrap_banglejs_accelWr(KX126_INC5,0); // INC5 - interrupt output pin INT2 disabled
|
||||
jswrap_banglejs_accelWr(KX126_INC6,0); // INC6 - no routing of interrupt reporting to pin INT2
|
||||
jswrap_banglejs_accelWr(KX126_INC7,0); // INC7 - no step counter interrupts reported on INT1 or INT2
|
||||
jswrap_banglejs_accelWr(KX126_INC1,0); // INC1 - interrupt output pin INT1 disabled
|
||||
jswrap_banglejs_accelWr(KX126_INC2,0); // INC2 - wake-up & back-to-sleep ignores all 3 axes
|
||||
jswrap_banglejs_accelWr(KX126_INC3,0x3F); // INC3 - enable tap detection in all 6 directions
|
||||
jswrap_banglejs_accelWr(KX126_INC4,0); // INC4 - no routing of interrupt reporting to pin INT1
|
||||
jswrap_banglejs_accelWr(KX126_INC5,0); // INC5 - interrupt output pin INT2 disabled
|
||||
jswrap_banglejs_accelWr(KX126_INC6,0); // INC6 - no routing of interrupt reporting to pin INT2
|
||||
jswrap_banglejs_accelWr(KX126_INC7,0); // INC7 - no step counter interrupts reported on INT1 or INT2
|
||||
jswrap_banglejs_accelWr(KX126_TDTRC,3); // TDTRC - enable interrupts on single and double taps
|
||||
jswrap_banglejs_accelWr(KX126_TDTC, 0x78); // TDTC - tap detect double tap (0x78 default)
|
||||
jswrap_banglejs_accelWr(KX126_TTH, 0xCB); // TTH - tap detect threshold high (0xCB default)
|
||||
jswrap_banglejs_accelWr(KX126_TTL, 0x22); // TTL - tap detect threshold low (0x1A default)
|
||||
jswrap_banglejs_accelWr(KX126_BUF_CLEAR,0); // clear the buffer
|
||||
|
||||
jswrap_banglejs_accelWr(KX126_CNTL1,KX126_CNTL1_DRDYE|KX126_CNTL1_GSEL_4G); // CNTL1 - standby mode, low power, enable "data ready" interrupt, 4g, disable tap, tilt & pedometer (for now)
|
||||
jswrap_banglejs_accelWr(KX126_CNTL1,KX126_CNTL1_DRDYE|KX126_CNTL1_GSEL_4G|KX126_CNTL1_PC1); // CNTL1 - same as above but change from standby to operating mode
|
||||
jswrap_banglejs_accelWr(KX126_CNTL1,KX126_CNTL1_DRDYE|KX126_CNTL1_GSEL_4G|KX126_CNTL1_TDTE); // CNTL1 - standby mode, low power, enable "data ready" interrupt, 4g, enable tap, disable tilt & pedometer (for now)
|
||||
jswrap_banglejs_accelWr(KX126_CNTL1,KX126_CNTL1_DRDYE|KX126_CNTL1_GSEL_4G|KX126_CNTL1_TDTE|KX126_CNTL1_PC1); // CNTL1 - same as above but change from standby to operating mode
|
||||
#endif
|
||||
|
||||
#ifdef PRESSURE_DEVICE
|
||||
@ -4140,6 +4226,14 @@ bool jswrap_banglejs_idle() {
|
||||
JsVar *o = jsvNewObject();
|
||||
if (o) {
|
||||
const char *string="";
|
||||
#ifdef DICKENS
|
||||
if (tapInfo&1) string="front";
|
||||
if (tapInfo&2) string="back";
|
||||
if (tapInfo&4) string="top";
|
||||
if (tapInfo&8) string="bottom";
|
||||
if (tapInfo&16) string="left";
|
||||
if (tapInfo&32) string="right";
|
||||
#else
|
||||
#ifdef BANGLEJS_Q3
|
||||
if (tapInfo&2) string="front";
|
||||
if (tapInfo&1) string="back";
|
||||
@ -4154,6 +4248,7 @@ bool jswrap_banglejs_idle() {
|
||||
if (tapInfo&8) string="bottom";
|
||||
if (tapInfo&16) string="left";
|
||||
if (tapInfo&32) string="right";
|
||||
#endif
|
||||
#endif
|
||||
int n = (tapInfo&0x80)?2:1;
|
||||
jsvObjectSetChildAndUnLock(o, "dir", jsvNewFromString(string));
|
||||
@ -5229,8 +5324,10 @@ static void jswrap_banglejs_periph_off() {
|
||||
nrf_gpio_cfg_sense_set(pinInfo[BTN4_PININDEX].pin, NRF_GPIO_PIN_NOSENSE);
|
||||
#endif
|
||||
|
||||
#ifndef DICKENS // RB: the call to jswrap_banglejs_kill via jswInit can cause increased power draw
|
||||
jsiKill();
|
||||
jsvKill();
|
||||
#endif
|
||||
jshKill();
|
||||
|
||||
/* The low power pin watch code (nrf_drv_gpiote_in_init) somehow causes
|
||||
@ -5239,12 +5336,25 @@ static void jswrap_banglejs_periph_off() {
|
||||
to re-enable everything. */
|
||||
jshPinWatch(BTN1_PININDEX, true, JSPW_NONE);
|
||||
nrf_gpio_cfg_sense_set(pinInfo[BTN1_PININDEX].pin, NRF_GPIO_PIN_SENSE_LOW);
|
||||
#ifdef DICKENS
|
||||
jshPinWatch(BAT_PIN_CHARGING, true, JSPW_NONE); // watch for when power applied
|
||||
nrf_gpio_cfg_sense_set(pinInfo[BAT_PIN_CHARGING].pin, NRF_GPIO_PIN_SENSE_LOW); // falling -> on charge
|
||||
#endif
|
||||
#else
|
||||
jsExceptionHere(JSET_ERROR, ".off not implemented on emulator");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// True if a button/charge input/etc should wake the Bangle from being off
|
||||
static bool _jswrap_banglejs_shouldWake() {
|
||||
return jshPinGetValue(BTN1_PININDEX)==BTN1_ONSTATE
|
||||
#ifdef DICKENS
|
||||
|| jshPinGetValue(BAT_PIN_CHARGING)==0/*charging*/
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Bangle",
|
||||
@ -5257,7 +5367,7 @@ Turn Bangle.js off. It can only be woken by pressing BTN1.
|
||||
void jswrap_banglejs_off() {
|
||||
#ifndef EMULATED
|
||||
// If BTN1 is pressed wait until it is released
|
||||
while (jshPinGetValue(BTN1_PININDEX));
|
||||
while (_jswrap_banglejs_shouldWake());
|
||||
// turn peripherals off
|
||||
jswrap_banglejs_periph_off();
|
||||
// system off
|
||||
@ -5291,17 +5401,17 @@ void jswrap_banglejs_softOff() {
|
||||
// keep sleeping until a button is pressed
|
||||
jshKickWatchDog();
|
||||
do {
|
||||
// sleep until BTN1 pressed
|
||||
while (!jshPinGetValue(BTN1_PININDEX)) {
|
||||
jshKickWatchDog();
|
||||
jshSleep(jshGetTimeFromMilliseconds(4*1000));
|
||||
}
|
||||
// wait for button to be pressed for at least 200ms
|
||||
int timeout = 200;
|
||||
while (jshPinGetValue(BTN1_PININDEX) && timeout--)
|
||||
// sleep until BTN1 pressed
|
||||
while (!_jswrap_banglejs_shouldWake()) {
|
||||
jshKickWatchDog();
|
||||
jshSleep(jshGetTimeFromMilliseconds(4*1000));
|
||||
}
|
||||
// wait for button to be pressed for at least WAKE_FROM_OFF_TIME (200ms usually)
|
||||
int timeout = WAKE_FROM_OFF_TIME;
|
||||
while (_jswrap_banglejs_shouldWake() && timeout--)
|
||||
nrf_delay_ms(1);
|
||||
// if button not pressed, keep sleeping
|
||||
} while (!jshPinGetValue(BTN1_PININDEX));
|
||||
} while (!_jswrap_banglejs_shouldWake());
|
||||
// restart
|
||||
jshReboot();
|
||||
|
||||
@ -5995,8 +6105,11 @@ other issues when switching apps. Please see http://www.espruino.com/Bangle.js+F
|
||||
"type" : "staticmethod",
|
||||
"class" : "Bangle",
|
||||
"name" : "factoryReset",
|
||||
"params" : [
|
||||
["noReboot","bool","Do not reboot the watch when done (default false, so will reboot)"]
|
||||
],
|
||||
"generate" : "jswrap_banglejs_factoryReset",
|
||||
"#if" : "defined(BANGLEJS_Q3) || defined(EMULATED)"
|
||||
"#if" : "defined(BANGLEJS_Q3) || defined(EMULATED) || defined(DICKENS)"
|
||||
}
|
||||
|
||||
Erase all storage and reload it with the default contents.
|
||||
@ -6005,9 +6118,9 @@ This is only available on Bangle.js 2.0. On Bangle.js 1.0 you need to use
|
||||
`Install Default Apps` under the `More...` tab of http://banglejs.com/apps
|
||||
*/
|
||||
extern void ble_app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
|
||||
void jswrap_banglejs_factoryReset() {
|
||||
void jswrap_banglejs_factoryReset(bool noReboot) {
|
||||
jsfResetStorage();
|
||||
jsiStatus |= JSIS_TODO_FLASH_LOAD;
|
||||
if (!noReboot) jsiStatus |= JSIS_TODO_FLASH_LOAD;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
@ -6086,4 +6199,4 @@ void jsbangle_push_event(JsBangleEvent type, uint16_t value) {
|
||||
evt.data.chars[1] = (char)((value>>8) & 0xFF);
|
||||
evt.data.chars[2] = (char)(value & 0xFF);
|
||||
jshPushEvent(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ JsVar *jswrap_banglejs_buzz(int time, JsVarFloat amt);
|
||||
void jswrap_banglejs_off();
|
||||
void jswrap_banglejs_softOff();
|
||||
JsVar *jswrap_banglejs_getLogo();
|
||||
void jswrap_banglejs_factoryReset();
|
||||
void jswrap_banglejs_factoryReset(bool noReboot);
|
||||
|
||||
JsVar *jswrap_banglejs_appRect();
|
||||
|
||||
|
||||
@ -175,6 +175,8 @@ typedef enum {
|
||||
BLEP_TASK_CHARACTERISTIC_NOTIFY, //< Central: Started requesting notifications
|
||||
BLEP_CENTRAL_NOTIFICATION, //< A characteristic we were watching has changed
|
||||
BLEP_CENTRAL_DISCONNECTED, //< Central: Disconnected (reason as data low byte, index in m_central_conn_handles as high byte )
|
||||
#endif
|
||||
#if PEER_MANAGER_ENABLED
|
||||
BLEP_BONDING_STATUS, //< Bonding negotiation status (data is one of BLEBondingStatus)
|
||||
#endif
|
||||
BLEP_WRITE, //< One of our characteristics written by someone else
|
||||
|
||||
8
libs/dickens/README.md
Normal file
8
libs/dickens/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
Dickens Smartwatch
|
||||
------------------
|
||||
|
||||
This directory contains extra files used by the Dickens smartwatch manufactured by The Wand Company.
|
||||
|
||||
The watch's board description file is in `boards/DICKENS.py`
|
||||
|
||||
**However** because this watch uses some fonts that aren't licensed for redistribution, it is not possible to fully build the firmware as-is. This is fully allowed by the MPLv2 license.
|
||||
200
libs/dickens/jswrap_dickens.c
Normal file
200
libs/dickens/jswrap_dickens.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* 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 is designed to be parsed during the build process
|
||||
*
|
||||
* Contains JavaScript function just for the Dickens smartwatch
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jswrap_dickens.h"
|
||||
#include "jswrap_graphics.h"
|
||||
#include "jswrap_math.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "lcd_spilcd.h"
|
||||
|
||||
/*JSON{
|
||||
"type": "class",
|
||||
"class" : "Dickens",
|
||||
"ifdef" : "BANGLEJS"
|
||||
}
|
||||
*/
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod", "class" : "Bangle", "name" : "drawWidgets", "patch":true,
|
||||
"generate_js" : "libs/js/dickens/Bangle_drawWidgets_DICKENS.min.js",
|
||||
"#if" : "defined(BANGLEJS) && defined(DICKENS)"
|
||||
}
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "staticmethod", "class" : "E", "name" : "showMenu", "patch":true,
|
||||
"generate_js" : "libs/js/dickens/E_showMenu_DICKENS.min.js",
|
||||
"#if" : "defined(BANGLEJS) && defined(DICKENS)"
|
||||
}
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "staticmethod", "class" : "E", "name" : "showPrompt", "patch":true,
|
||||
"generate_js" : "libs/js/dickens/E_showPrompt_DICKENS.min.js",
|
||||
"#if" : "defined(BANGLEJS) && defined(DICKENS)"
|
||||
}
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "staticmethod", "class" : "E", "name" : "showMessage", "patch":true,
|
||||
"generate_js" : "libs/js/dickens/E_showMessage_DICKENS.min.js",
|
||||
"#if" : "defined(BANGLEJS) && defined(DICKENS)"
|
||||
}
|
||||
*/
|
||||
/*JSON{
|
||||
"type" : "staticmethod", "class" : "Bangle", "name" : "setUI", "patch":true,
|
||||
"generate_js" : "libs/js/dickens/Bangle_setUI_DICKENS.min.js",
|
||||
"#if" : "defined(BANGLEJS) && defined(DICKENS)"
|
||||
}
|
||||
*/
|
||||
|
||||
// add a radial point to an array
|
||||
void addRadialPoint(JsVar *arr, double r, double a) {
|
||||
jsvArrayPushAndUnLock(arr, jsvNewFromFloat(119.0 + (r*jswrap_math_sin(a))));
|
||||
jsvArrayPushAndUnLock(arr, jsvNewFromFloat(119.0 - (r*jswrap_math_cos(a))));
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "fillArc",
|
||||
"ifdef" : "DICKENS",
|
||||
"generate" : "jswrap_graphics_fillArc",
|
||||
"params" : [
|
||||
["a1","float","Angle 1 (radians)"],
|
||||
["a2","float","Angle 2 (radians)"],
|
||||
["r","float","Radius"]
|
||||
],
|
||||
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Draw a filled arc between two angles
|
||||
*/
|
||||
JsVar *jswrap_graphics_fillArc(JsVar *parent, double a1, double a2, double r) {
|
||||
if (a2<a1) return jsvLockAgain(parent);
|
||||
if ((a2-a1)>6.28) a2=a1+6.28; // No need for more than a full circle - if the polygon has too many points, a memory leak will happen
|
||||
double a;
|
||||
const int res = 8;
|
||||
JsVar *poly = jsvNewEmptyArray();
|
||||
for (double i=a1*res;i<a2*res;i++) {
|
||||
a = i/res;
|
||||
addRadialPoint(poly, r, a);
|
||||
}
|
||||
addRadialPoint(poly, r, a2);
|
||||
|
||||
jswrap_graphics_fillPoly_X(parent, poly, true/*antialias*/);
|
||||
jsvUnLock(poly);
|
||||
return parent; // jswrap_graphics_fillPoly_X clready locked it
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "fillSeg",
|
||||
"ifdef" : "DICKENS",
|
||||
"generate" : "jswrap_graphics_fillSeg",
|
||||
"params" : [
|
||||
["a","float","Angle (radians)"],
|
||||
["ar","float","Angle either side (radians)"],
|
||||
["r1","float","Radius"],
|
||||
["r2","float","Radius"]
|
||||
],
|
||||
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Draw rectangle between angles a-ar and a+ar, and radius r1/r2
|
||||
*/
|
||||
JsVar *jswrap_graphics_fillSeg(JsVar *parent, double a, double ar, double r1, double r2) {
|
||||
double a1 = a-ar;
|
||||
double a2 = a+ar;
|
||||
|
||||
JsVar *poly = jsvNewEmptyArray();
|
||||
addRadialPoint(poly, r1, a1);
|
||||
addRadialPoint(poly, r1, a2);
|
||||
addRadialPoint(poly, r2, a2);
|
||||
addRadialPoint(poly, r2, a1);
|
||||
jswrap_graphics_fillPoly_X(parent, poly, true/*antialias*/);
|
||||
jsvUnLock(poly);
|
||||
return parent; // jswrap_graphics_fillPoly_X clready locked it
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "drawSeg",
|
||||
"ifdef" : "DICKENS",
|
||||
"generate" : "jswrap_graphics_drawSeg",
|
||||
"params" : [
|
||||
["a","float","Angle (radians)"],
|
||||
["ar","float","Angle either side (radians)"],
|
||||
["r","float","Radius"]
|
||||
],
|
||||
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Draw A line between angles a-ar and a+ar at radius r
|
||||
*/
|
||||
JsVar *jswrap_graphics_drawSeg(JsVar *parent, double a, double ar, double r) {
|
||||
double a1 = a-ar;
|
||||
double a2 = a+ar;
|
||||
return jswrap_graphics_drawLineAA(parent,
|
||||
119.0 + (r*jswrap_math_sin(a1)),
|
||||
119.0 - (r*jswrap_math_cos(a1)),
|
||||
119.0 + (r*jswrap_math_sin(a2)),
|
||||
119.0 - (r*jswrap_math_cos(a2))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DICKENS
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Bangle",
|
||||
"name" : "setLCDRotation",
|
||||
"generate" : "jswrap_banglejs_setLCDRotation",
|
||||
"params" : [
|
||||
["d","int","The number of degrees to the LCD display (0, 90, 180 or 270)"]
|
||||
],
|
||||
"ifdef" : "BANGLEJS"
|
||||
}
|
||||
Sets the rotation of the LCD display (relative to its nominal orientation)
|
||||
*/
|
||||
void jswrap_banglejs_setLCDRotation(int d) {
|
||||
#ifdef LCD_ROTATION
|
||||
// If the LCD is already rotated in the board definition file, add this
|
||||
d += LCD_ROTATION;
|
||||
if (d>=360) d-=360;
|
||||
#endif
|
||||
uint8_t regValue;
|
||||
// Register values are OK for GC9A01 on Dickens, but will need to be different on other hardware.
|
||||
switch (d) {
|
||||
case 0:
|
||||
regValue = 0x88;
|
||||
break;
|
||||
case 90:
|
||||
regValue = 0x78;
|
||||
break;
|
||||
case 180:
|
||||
regValue = 0x48;
|
||||
break;
|
||||
case 270:
|
||||
regValue = 0xB8;
|
||||
break;
|
||||
default:
|
||||
jsExceptionHere(JSET_ERROR, "setLCDRotation expects a rotation value of 0, 90, 180 or 270");
|
||||
}
|
||||
lcdCmd_SPILCD(0x36, 1, (const uint8_t *)®Value);
|
||||
}
|
||||
#endif
|
||||
21
libs/dickens/jswrap_dickens.h
Normal file
21
libs/dickens/jswrap_dickens.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* 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/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Contains JavaScript function just for the Dickens smartwatch
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jsvar.h"
|
||||
|
||||
JsVar *jswrap_graphics_fillArc(JsVar *parent, double a1, double a2, double r);
|
||||
JsVar *jswrap_graphics_fillSeg(JsVar *parent, double a, double ar, double r1, double r2);
|
||||
JsVar *jswrap_graphics_drawSeg(JsVar *parent, double a, double ar, double r);
|
||||
|
||||
void jswrap_banglejs_setLCDRotation(int d);
|
||||
@ -127,7 +127,7 @@ const unsigned short LCD_FONT_3X5[] IN_FLASH_MEMORY = { // from 33 up to 127
|
||||
PACK_5_TO_16( X_X , X_X , X__ , _X_ , X_X ),
|
||||
PACK_5_TO_16( X_X , XX_ , _X_ , _X_ , X_X ),
|
||||
PACK_5_TO_16( X_X , X_X , __X , _X_ , X_X ),
|
||||
PACK_5_TO_16( _XX , X_X , XX_ , _X_ , _X_ ),
|
||||
PACK_5_TO_16( _XX , X_X , XX_ , _X_ , XXX ),
|
||||
|
||||
PACK_5_TO_16( ___ , ___ , ___ , X_X , ___ ), // vwxyz
|
||||
PACK_5_TO_16( ___ , X_X , X_X , X_X , ___ ),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
/* This is a super hacky bit of code that takes a specially formatted SVG file
|
||||
and creates an Espruino vector font from it.
|
||||
|
||||
|
||||
@ -520,7 +520,7 @@ fn : "Light20px.png",
|
||||
bpp : 2,
|
||||
height : 20, // actual used height of font map
|
||||
firstChar : 32,
|
||||
maxChars : 128-32
|
||||
maxChars : 256-32
|
||||
});
|
||||
f.fullHeight = false;
|
||||
f.glyphPadX = 0;*/
|
||||
@ -558,7 +558,7 @@ f.debugPixelsUsed();
|
||||
console.log(f.outputJS());
|
||||
|
||||
// Write a binary PBF file
|
||||
//require("fs").writeFileSync("font.pbf", Buffer.from(f.outputPBF()))
|
||||
require("fs").writeFileSync("font.pbf", Buffer.from(f.outputPBF()))
|
||||
|
||||
// Write a PBF file as a jswrap_ C file that can be included in the build
|
||||
// by adding 'WRAPPERSOURCES += libs/graphics/jswrap_font_light20.c' to the BOARD.py file
|
||||
|
||||
@ -262,6 +262,7 @@ size_t graphicsGetMemoryRequired(const JsGraphics *gfx) {
|
||||
|
||||
// If graphics is flipped or rotated then the coordinates need modifying
|
||||
void graphicsToDeviceCoordinates(const JsGraphics *gfx, int *x, int *y) {
|
||||
#ifndef DICKENS // For Dickens, we can use Bangle.lcdWr(0x36, xxx) to set the screen rotation
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_SWAP_XY) {
|
||||
int t = *x;
|
||||
*x = *y;
|
||||
@ -269,6 +270,7 @@ void graphicsToDeviceCoordinates(const JsGraphics *gfx, int *x, int *y) {
|
||||
}
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_INVERT_X) *x = (int)(gfx->data.width - (*x+1));
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_INVERT_Y) *y = (int)(gfx->data.height - (*y+1));
|
||||
#endif
|
||||
}
|
||||
|
||||
// If graphics is flipped or rotated then the coordinates need modifying. This is to go back - eg for touchscreens
|
||||
@ -284,6 +286,7 @@ void deviceToGraphicsCoordinates(const JsGraphics *gfx, int *x, int *y) {
|
||||
|
||||
// If graphics is flipped or rotated then the coordinates need modifying
|
||||
void graphicsToDeviceCoordinates16x(const JsGraphics *gfx, int *x, int *y) {
|
||||
#ifndef DICKENS // For Dickens, we can use Bangle.lcdWr(0x36, xxx) to set the screen rotation
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_SWAP_XY) {
|
||||
int t = *x;
|
||||
*x = *y;
|
||||
@ -291,6 +294,7 @@ void graphicsToDeviceCoordinates16x(const JsGraphics *gfx, int *x, int *y) {
|
||||
}
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_INVERT_X) *x = (int)((gfx->data.width-1)*16 - *x);
|
||||
if (gfx->data.flags & JSGRAPHICSFLAGS_INVERT_Y) *y = (int)((gfx->data.height-1)*16 - *y);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned short graphicsGetWidth(const JsGraphics *gfx) {
|
||||
|
||||
@ -32,6 +32,11 @@
|
||||
|
||||
#include "jswrap_functions.h" // for asURL
|
||||
#include "jswrap_object.h" // for getFonts
|
||||
#ifdef DICKENS
|
||||
#include "jsflash.h" // for saveScreenshot
|
||||
#include "lcd_spilcd.h"
|
||||
#define ESPR_LINE_FONTS
|
||||
#endif
|
||||
|
||||
#include "bitmap_font_4x6.h"
|
||||
#include "bitmap_font_6x8.h"
|
||||
@ -39,6 +44,10 @@
|
||||
#ifdef ESPR_PBF_FONTS
|
||||
#include "pbf_font.h"
|
||||
#endif
|
||||
#ifdef ESPR_LINE_FONTS
|
||||
#include "line_font.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GRAPHICS_PALETTED_IMAGES
|
||||
#if defined(ESPR_GRAPHICS_12BIT)
|
||||
@ -1142,6 +1151,32 @@ Draw a filled circle in the Foreground Color
|
||||
return jswrap_graphics_fillEllipse(parent, x-rad, y-rad, x+rad, y+rad);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "fillAnnulus",
|
||||
"#if" : "defined(DICKENS)",
|
||||
"generate" : "jswrap_graphics_fillAnnulus",
|
||||
"params" : [
|
||||
["x","int32","The X axis"],
|
||||
["y","int32","The Y axis"],
|
||||
["r1","int32","The annulus inner radius"],
|
||||
["r2","int32","The annulus outer radius"]
|
||||
],
|
||||
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Draw a filled annulus in the Foreground Color
|
||||
*/
|
||||
// JsVar *jswrap_graphics_fillAnnulus(JsVar *parent, int x, int y, int r1, int r2, unsigned short quadrants) { // Too many arguments!
|
||||
JsVar *jswrap_graphics_fillAnnulus(JsVar *parent, int x, int y, int r1, int r2) {
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
unsigned short quadrants = 0x0F; // Just do all quadrants for now
|
||||
graphicsFillAnnulus(&gfx, x,y,r1,r2,quadrants);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
return jsvLockAgain(parent);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
@ -2696,6 +2731,75 @@ JsVar *jswrap_graphics_getVectorFontPolys(JsGraphics *gfx, JsVar *str, JsVar *op
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "drawLineString",
|
||||
"#if" : "defined(DICKENS)",
|
||||
"generate" : "jswrap_graphics_drawLineString",
|
||||
"params" : [
|
||||
["str","JsVar","The string"],
|
||||
["x","int32","The X position of the start of the text string"],
|
||||
["y","int32","The Y position of the middle of the text string"],
|
||||
["options","JsVar","Options for drawing this font (see below)"]
|
||||
],
|
||||
"return" : ["JsVar","The instance of Graphics this was called on, to allow call chaining"],
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Draw a string of text as a fixed-width line font
|
||||
|
||||
`options` contains:
|
||||
|
||||
* `size`: font size in pixels (char width is half font size) - default 16
|
||||
* `rotate`: Initial rotation in radians - default 0
|
||||
* `twist`: Subsequent rotation per character in radians - default 0
|
||||
*/
|
||||
#ifdef ESPR_LINE_FONTS
|
||||
JsVar *jswrap_graphics_drawLineString(JsVar *parent, JsVar *var, int x, int y, JsVar *options) {
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
|
||||
int fontSize = 16;
|
||||
double rotate = 0, twist = 0;
|
||||
jsvConfigObject configs[] = {
|
||||
{"size", JSV_INTEGER, &fontSize},
|
||||
{"rotate", JSV_FLOAT, &rotate},
|
||||
{"twist", JSV_FLOAT, &twist}
|
||||
};
|
||||
if (!jsvReadConfigObject(options, configs, sizeof(configs) / sizeof(jsvConfigObject))) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid options");
|
||||
return 0;
|
||||
}
|
||||
fontSize *= 16;
|
||||
|
||||
x = x*16 - 8;
|
||||
y = y*16 - 8;
|
||||
int startx = x;
|
||||
|
||||
JsVar *str = jsvAsString(var);
|
||||
JsvStringIterator it;
|
||||
jsvStringIteratorNew(&it, str, 0);
|
||||
while (jsvStringIteratorHasChar(&it)) {
|
||||
char ch = jsvStringIteratorGetCharAndNext(&it);
|
||||
if (ch=='\n') {
|
||||
x = startx;
|
||||
y += fontSize;
|
||||
continue;
|
||||
}
|
||||
int xdx = (int)(0.5 + fontSize*cos(rotate));
|
||||
int xdy = (int)(0.5 + fontSize*sin(rotate));
|
||||
graphicsDrawLineChar(&gfx, x, y, xdx, xdy, ch);
|
||||
x += xdx * 1 / 2;
|
||||
y += xdy * 1 / 2;
|
||||
rotate += twist;
|
||||
if (jspIsInterrupted()) break;
|
||||
}
|
||||
jsvStringIteratorFree(&it);
|
||||
jsvUnLock(str);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
return jsvLockAgain(parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
@ -4002,6 +4106,38 @@ void jswrap_graphics_dump(JsVar *parent) {
|
||||
jsvUnLock(jswrap_graphics_asBMP_X(parent, true/*printBase64*/));
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "saveScreenshot",
|
||||
"#if" : "defined(DICKENS)",
|
||||
"generate" : "jswrap_graphics_saveScreenshot",
|
||||
"params" : [
|
||||
["filename","JsVar","If supplied, a file to save, otherwise 'screenshot.img'"]
|
||||
]
|
||||
}
|
||||
*/
|
||||
void jswrap_graphics_saveScreenshot(JsVar *parent, JsVar *fileNameVar) {
|
||||
#ifdef DICKENS
|
||||
JsfFileName fileName = jsfNameFromString("screenshot.img");
|
||||
if (fileNameVar) fileName = jsfNameFromVar(fileNameVar);
|
||||
|
||||
JsVar *v = jsvNewFromString("\xF0\xF0\x10");
|
||||
jsfWriteFile(fileName, v, JSFF_NONE, 0, sizeof(lcdBuffer)+3);
|
||||
jsvUnLock(v);
|
||||
const int chunkSize = 16384;
|
||||
for (int i=0;i<sizeof(lcdBuffer);i+=chunkSize) {
|
||||
int s = chunkSize;
|
||||
if (s+i > sizeof(lcdBuffer))
|
||||
s=sizeof(lcdBuffer)-i;
|
||||
JsVar *gfxBufferString = jsvNewNativeString(&lcdBuffer[i], s);
|
||||
jsfWriteFile(fileName, gfxBufferString, JSFF_NONE, 3+i, 0);
|
||||
jsvUnLock(gfxBufferString);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
|
||||
@ -45,6 +45,7 @@ JsVar *jswrap_graphics_drawRect(JsVar *parent, JsVar *opt, int y1, int x2, int y
|
||||
JsVar *jswrap_graphics_drawCircle(JsVar *parent, int x, int y, int rad);
|
||||
JsVar *jswrap_graphics_drawCircleAA(JsVar *parent, int x, int y, int r);
|
||||
JsVar *jswrap_graphics_fillCircle(JsVar *parent, int x, int y, int rad);
|
||||
JsVar *jswrap_graphics_fillAnnulus(JsVar *parent, int x, int y, int r1, int r2);
|
||||
JsVar *jswrap_graphics_drawEllipse(JsVar *parent, int x, int y, int x2, int y2);
|
||||
JsVar *jswrap_graphics_fillEllipse(JsVar *parent, int x, int y, int x2, int y2);
|
||||
int jswrap_graphics_getPixel(JsVar *parent, int x, int y);
|
||||
@ -66,6 +67,7 @@ JsVar *jswrap_graphics_wrapString(JsVar *parent, JsVar *str, int maxWidth);
|
||||
JsVar *jswrap_graphics_drawString(JsVar *parent, JsVar *str, int x, int y, bool solidBackground);
|
||||
void jswrap_graphics_drawCString(JsGraphics *gfx, int x, int y, char *str); /// Convenience function for using drawString from C code
|
||||
JsVarInt jswrap_graphics_stringWidth(JsVar *parent, JsVar *var);
|
||||
JsVar *jswrap_graphics_drawLineString(JsVar *parent, JsVar *var, int x, int y, JsVar *options);
|
||||
JsVar* jswrap_graphics_stringMetrics(JsVar *parent, JsVar *var);
|
||||
JsVar *jswrap_graphics_getVectorFontPolys(JsGraphics *gfx, JsVar *var, JsVar *options);
|
||||
JsVar *jswrap_graphics_drawLine(JsVar *parent, int x1, int y1, int x2, int y2);
|
||||
@ -85,6 +87,7 @@ JsVar *jswrap_graphics_blit(JsVar *parent, JsVar *options);
|
||||
JsVar *jswrap_graphics_asBMP(JsVar *parent);
|
||||
JsVar *jswrap_graphics_asURL(JsVar *parent);
|
||||
void jswrap_graphics_dump(JsVar *parent);
|
||||
void jswrap_graphics_saveScreenshot(JsVar *parent, JsVar *fileNameVar);
|
||||
JsVar *jswrap_graphics_quadraticBezier(JsVar *parent, JsVar * arr, JsVar *options);
|
||||
JsVar *jswrap_graphics_transformVertices(JsVar *parent, JsVar *verts, JsVar *transformation);
|
||||
JsVar *jswrap_graphics_floodFill(JsVar *parent, int x, int y, JsVar *col);
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#define LCD_STRIDE ((LCD_WIDTH*LCD_BPP+7)>>3)
|
||||
unsigned char lcdBuffer[LCD_STRIDE*LCD_HEIGHT];
|
||||
#if LCD_BPP==4
|
||||
unsigned short lcdPalette[16];
|
||||
@ -377,9 +376,9 @@ void lcdInit_SPILCD(JsGraphics *gfx) {
|
||||
jshPinOutput(LCD_SPI_MOSI,1);
|
||||
#ifdef LCD_SPI_RST
|
||||
jshPinOutput(LCD_SPI_RST,0);
|
||||
jshDelayMicroseconds(1000);
|
||||
jshDelayMicroseconds(50000);
|
||||
jshPinOutput(LCD_SPI_RST, 1);
|
||||
jshDelayMicroseconds(2000);
|
||||
jshDelayMicroseconds(50000);
|
||||
#endif
|
||||
JshSPIInfo inf;
|
||||
jshSPIInitInfo(&inf);
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
*/
|
||||
#include "graphics.h"
|
||||
|
||||
#define LCD_STRIDE ((LCD_WIDTH*LCD_BPP+7)>>3)
|
||||
unsigned char lcdBuffer[LCD_STRIDE*LCD_HEIGHT];
|
||||
|
||||
void lcdInit_SPILCD(JsGraphics *gfx);
|
||||
void lcdSetCallbacks_SPILCD(JsGraphics *gfx);
|
||||
|
||||
@ -23,4 +26,4 @@ void lcdSetPalette_SPILCD(const char *pal);
|
||||
#if LCD_BPP==12 || LCD_BPP==16
|
||||
// Enable overlay mode (to overlay a graphics instance on top of the LCD contents)
|
||||
void lcdSetOverlay_SPILCD(JsVar *imgVar, int x, int y);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -107,47 +107,69 @@ static const unsigned char SPILCD_INIT_CODE[] = {
|
||||
0xfe,0,0,
|
||||
0xef,0,0,
|
||||
0xeb,0,1, 0x14,
|
||||
0x84,0,1, 0x40,
|
||||
0x84,0,1, 0x60, // 0x40->0x60 0xb5 en 20200924 james
|
||||
0x85,0,1, 0xFF,
|
||||
0x86,0,1, 0xFF,
|
||||
0x87,0,1, 0xFF,
|
||||
0x8e,0,1, 0xFF,
|
||||
0x8f,0,1, 0xFF,
|
||||
0x88,0,1, 10,
|
||||
0x89,0,1, 0x21,
|
||||
0x89,0,1, 0x23, // 0x21->0x23 spi 2data reg en
|
||||
0x8a,0,1, 0,
|
||||
0x8b,0,1, 0x80,
|
||||
0x8c,0,1, 1,
|
||||
0x8d,0,1, 1,
|
||||
0xb6,0,1, 0x20,
|
||||
0x36,0,1, 0x88, // Memory Access Control (0x48 flips upside-down)
|
||||
0x8d,0,1, 3, // 1->3 99 en
|
||||
0xb5,0,4, 0x08, 0x09, 0x14, 0x08,
|
||||
0xb6,0,2, 0, 0, // Positive sweep 0x20->0 GS SS 0x20
|
||||
#ifdef LCD_ROTATION
|
||||
#if (LCD_ROTATION == 90)
|
||||
0x36,0,1, 0x78, // Memory Access Control (rotated 90 degrees)
|
||||
#elif (LCD_ROTATION == 180)
|
||||
0x36,0,1, 0x48, // Memory Access Control (rotated 180 degrees)
|
||||
#elif (LCD_ROTATION == 270)
|
||||
0x36,0,1, 0xB8, // Memory Access Control (rotated 270 degrees)
|
||||
#else
|
||||
0x36,0,1, 0x88, // Memory Access Control (no rotation)
|
||||
#endif
|
||||
#else
|
||||
0x36,0,1, 0x88, // Memory Access Control (no rotation)
|
||||
#endif
|
||||
0x3a,0,1, 5, // could be 16/12 bit?
|
||||
0x90,0,4, 8, 8, 8, 8,
|
||||
0xba,0,1, 1, // TE width
|
||||
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,
|
||||
0xc3,0,1, 0x13, // Power control 2: 0x13->0x1d->0x13 (again)
|
||||
0xc4,0,1, 0x13, // Power control 3: 0x13->0x1d->0x13 (again)
|
||||
0xc9,0,1, 0x25, // Power control 4: 0x22->0x25
|
||||
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,
|
||||
0xf0,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 1
|
||||
0xf1,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 2
|
||||
0xf2,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 3
|
||||
0xf3,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 4
|
||||
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,
|
||||
0xae,0,1, 0x77, // 0x74->0x77
|
||||
0xcd,0,1, 0x63,
|
||||
0x70,0,9, 7, 7, 4, 0xe, 0xf, 9, 7, 8, 3, // 7,9,4... -> 7,7,4...
|
||||
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,
|
||||
0x60,0,8, 0x38, 0x0b, 0x6d, 0x6d, 0x39, 0xf0, 0x6d, 0x6d,
|
||||
0x61,0,8, 0x38, 0xf4, 0x6d, 0x6d, 0x38, 0xf7, 0x6d, 0x6d,
|
||||
0x62,0,12, 0x38, 0xd, 0x71, 0xed, 0x70, 0x70, 0x38, 0xf, 0x71, 0xef, 0x70, 0x70,
|
||||
0x63,0,12, 0x38, 0x11, 0x71, 0xf1, 0x70, 0x70, 0x38, 0x13, 0x71, 0xf3, 0x70, 0x70,
|
||||
0x64,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,
|
||||
0x74,0,7, 0x10, 0x68, 0x80, 0, 0, 0x4e, 0, // 0x85->0x68
|
||||
0x98,0,2, 0x3e, 7,
|
||||
0x35,0,0,
|
||||
0x21,5,0,
|
||||
0x11,5,0,
|
||||
0x29,5,0,
|
||||
0x2c,0,0,
|
||||
0x99,0,2, 0x3e, 7, // bvee 2x
|
||||
0x35,0,1, 0, // Tearing effect (TE) line ON, with V-blanking only
|
||||
0x21,5,0, // Display inversion ON
|
||||
0x11,5,0, // Sleep out
|
||||
0x29,5,0, // Display ON
|
||||
0x2c,0,0, // Memory write
|
||||
// End
|
||||
0, 0, 255/*DATA_LEN = 255 => END*/
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
Bangle.removeAllListeners();
|
||||
E.removeAllListeners();
|
||||
NRF.removeAllListeners();
|
||||
Bangle.setLCDBrightness(1);
|
||||
E.showMenu({"":{title:"Recovery"},
|
||||
"Attempt Compact": () => {
|
||||
E.showMessage("Compacting...\nMay take\n5 min.");
|
||||
@ -13,7 +14,7 @@
|
||||
require("Storage").compact();
|
||||
E.reboot();
|
||||
},
|
||||
"Rewrite bootloader": () => {
|
||||
"Rewrite Bootloader": () => {
|
||||
setTimeout(load,1000);
|
||||
eval(require("Storage").read("bootupdate.js"));
|
||||
},
|
||||
@ -21,6 +22,7 @@
|
||||
E.showPrompt("Are you sure?\nThis will remove all data.",{title:"Factory Reset"}).then(ok => {
|
||||
if (!ok) return Bangle.showRecoveryMenu();
|
||||
E.showMessage("Resetting");
|
||||
Bangle.setLCDTimeout(0);
|
||||
if(!NRF.getSecurityStatus().connected)
|
||||
Terminal.setConsole();
|
||||
Bangle.factoryReset();
|
||||
@ -35,11 +37,15 @@
|
||||
"Turn Off": () => {
|
||||
Bangle.off();
|
||||
},
|
||||
"Exit": () => {
|
||||
E.showMessage("Loading...");
|
||||
if(!NRF.getSecurityStatus().connected)
|
||||
Terminal.setConsole();
|
||||
load();
|
||||
"Exit": () => {
|
||||
if (require("Storage").list().length>0) {
|
||||
E.showMessage("Loading...");
|
||||
if(!NRF.getSecurityStatus().connected)
|
||||
Terminal.setConsole();
|
||||
load();
|
||||
} else {
|
||||
E.reboot();
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
14
libs/js/dickens/Bangle_drawWidgets_DICKENS.js
Normal file
14
libs/js/dickens/Bangle_drawWidgets_DICKENS.js
Normal file
@ -0,0 +1,14 @@
|
||||
(function() {
|
||||
if (!global.WIDGETS) return;
|
||||
var pad = 4, w = -pad, wd;
|
||||
for (wd of WIDGETS) w += wd.width+pad;
|
||||
var x = 119-w/2;
|
||||
g.reset();
|
||||
for (wd of WIDGETS) {
|
||||
wd.x = x;
|
||||
wd.y = 26;
|
||||
x += wd.width+pad;
|
||||
wd.draw(wd);
|
||||
}
|
||||
g.reset();
|
||||
})
|
||||
1
libs/js/dickens/Bangle_drawWidgets_DICKENS.min.js
vendored
Normal file
1
libs/js/dickens/Bangle_drawWidgets_DICKENS.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(function(){if(global.WIDGETS){var b=-4,a;for(a of WIDGETS)b+=a.width+4;b=119-b/2;g.reset();for(a of WIDGETS)a.x=b,a.y=26,b+=a.width+4,a.draw(a);g.reset()}})
|
||||
9
libs/js/dickens/Bangle_setUI_DICKENS.js
Normal file
9
libs/js/dickens/Bangle_setUI_DICKENS.js
Normal file
@ -0,0 +1,9 @@
|
||||
(function(mode, cb) {
|
||||
if (Bangle.btnWatches) {
|
||||
Bangle.btnWatches.forEach(w => {
|
||||
try { clearWatch(w); } catch (e) {}
|
||||
});
|
||||
delete Bangle.btnWatches;
|
||||
}
|
||||
// this is just a replacement for E.clearWatches for the moment
|
||||
})
|
||||
1
libs/js/dickens/Bangle_setUI_DICKENS.min.js
vendored
Normal file
1
libs/js/dickens/Bangle_setUI_DICKENS.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(function(b,c){Bangle.btnWatches&&(Bangle.btnWatches.forEach(a=>{try{clearWatch(a)}catch(d){}}),delete Bangle.btnWatches)})
|
||||
126
libs/js/dickens/E_showMenu_DICKENS.js
Normal file
126
libs/js/dickens/E_showMenu_DICKENS.js
Normal file
@ -0,0 +1,126 @@
|
||||
(function(items, onCancel) {
|
||||
if (!global.Dickens) Dickens={}; // for when called with no boot code
|
||||
Bangle.setUI(); // clear Bangle.btnWatches
|
||||
|
||||
g.clear(1);
|
||||
// clear screen if no menu supplied
|
||||
if (!items) return;
|
||||
|
||||
var cHighlightBg = "#304060";
|
||||
var cBorderBg = "#305080";
|
||||
g.setColor(cBorderBg);
|
||||
g.fillArc(-Math.PI*0.285,Math.PI*0.285,96);
|
||||
g.fillArc(Math.PI*(1-0.285),Math.PI*1.285,96);
|
||||
g.fillRect(41,62,195,62);
|
||||
g.fillRect(41,175,195,175);
|
||||
|
||||
var menuItems = Object.keys(items);
|
||||
var options = items[""];
|
||||
if (options) menuItems.splice(menuItems.indexOf(""),1);
|
||||
if (!(options instanceof Object)) options = {};
|
||||
options.fontHeight=16;
|
||||
if (options.selected === undefined)
|
||||
options.selected = 0;
|
||||
var x = 38;
|
||||
var x2 = 200;
|
||||
var y = 65+6;
|
||||
var y2 = 174;
|
||||
var cBg = 0; // background col
|
||||
var cFg = -1; // foreground col
|
||||
var cHighlightFg = -1;
|
||||
var loc = require("locale");
|
||||
var l = {
|
||||
draw : function() {
|
||||
g.reset().setColor(cFg).setFontGrotesk16();
|
||||
if (options.title) {
|
||||
g.setFontAlign(0,-1,0);
|
||||
g.setBgColor(cBorderBg).drawString(options.title,119,42);
|
||||
}
|
||||
g.setBgColor(0);
|
||||
var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length);
|
||||
var idx = E.clip(options.selected-(rows>>1),0,menuItems.length-rows);
|
||||
var iy = y;
|
||||
var less = idx>0;
|
||||
g.setColor(idx>0?cHighlightBg:cBorderBg).fillPoly([111,36,127,36,119,28]);
|
||||
while (rows--) {
|
||||
var name = menuItems[idx];
|
||||
var item = items[name];
|
||||
var hl = (idx==options.selected && !l.selectEdit);
|
||||
g.setBgColor(hl ? cHighlightBg : cBg);
|
||||
g.setColor(hl ? cHighlightFg : cFg);
|
||||
g.clearRect(x,iy-1,x2,iy+options.fontHeight-1);
|
||||
g.setFontAlign(-1,-1);
|
||||
g.drawString(loc.translate(name),x+2,iy);
|
||||
if ("object" == typeof item) {
|
||||
var xo = x2;
|
||||
var v = item.value;
|
||||
if (item.format) v=item.format(v);
|
||||
if (("number" == typeof v) && item.precision) v=v.toFixed(item.precision);
|
||||
v = loc.translate(""+v);
|
||||
if (l.selectEdit && idx==options.selected) {
|
||||
xo -= 24 + 1;
|
||||
g.setColor(cHighlightBg);
|
||||
g.fillRect(xo-(g.stringWidth(v)+8),iy-1,x2,iy+options.fontHeight-1);
|
||||
g.setColor(cHighlightFg);
|
||||
g.drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2});
|
||||
}
|
||||
g.setFontAlign(1,-1);
|
||||
g.drawString(v,xo-2,iy);
|
||||
}
|
||||
iy += options.fontHeight+1;
|
||||
idx++;
|
||||
}
|
||||
g.setFontAlign(-1,-1);
|
||||
g.setColor(idx<menuItems.length?cHighlightBg:cBorderBg).fillPoly([110,191,128,191,119,200]);
|
||||
g.flip();
|
||||
},
|
||||
select : function(dir) {
|
||||
var item = items[menuItems[options.selected]];
|
||||
if ("function" == typeof item) {
|
||||
Bangle.setUI(); // clear Bangle.btnWatches
|
||||
item(l);
|
||||
}
|
||||
else if ("object" == typeof item) {
|
||||
// if a number, go into 'edit mode'
|
||||
if ("number" == typeof item.value)
|
||||
l.selectEdit = l.selectEdit?undefined:item;
|
||||
else { // else just toggle bools
|
||||
if ("boolean" == typeof item.value) item.value=!item.value;
|
||||
if (item.onchange) item.onchange(item.value);
|
||||
}
|
||||
l.draw();
|
||||
}
|
||||
},
|
||||
move : function(dir) {
|
||||
if (l.selectEdit) {
|
||||
var item = l.selectEdit;
|
||||
item.value -= (dir||1)*(item.step||1);
|
||||
if (Math.abs(item.value)<1e-10) item.value=0;
|
||||
if (item.min!==undefined && item.value<item.min) {
|
||||
if (item.wrap) item.value = item.max;
|
||||
else item.value = item.min;
|
||||
}
|
||||
if (item.max!==undefined && item.value>item.max) {
|
||||
if (item.wrap) item.value = item.min;
|
||||
else item.value = item.max;
|
||||
}
|
||||
if (item.onchange) item.onchange(item.value);
|
||||
} else {
|
||||
options.selected = (dir+options.selected)%menuItems.length;
|
||||
if (options.selected<0) options.selected += menuItems.length;
|
||||
}
|
||||
l.draw();
|
||||
}
|
||||
};
|
||||
Dickens.buttonIcons=['select',null,'down','up'];
|
||||
if (onCancel) Dickens.buttonIcons[1]='back';
|
||||
l.draw();
|
||||
Dickens.loadSurround&&Dickens.loadSurround();
|
||||
Bangle.btnWatches = [
|
||||
setWatch(function() { l.move(-1); }, BTN4, {repeat:1}),
|
||||
setWatch(function() { l.move(1); }, BTN3, {repeat:1}),
|
||||
setWatch(function() { l.select(); }, BTN1, {repeat:1})
|
||||
];
|
||||
if (onCancel) Bangle.btnWatches.push(setWatch(onCancel, BTN2, {repeat:1}))
|
||||
return l;
|
||||
})
|
||||
5
libs/js/dickens/E_showMenu_DICKENS.min.js
vendored
Normal file
5
libs/js/dickens/E_showMenu_DICKENS.min.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
(function(m,n){global.Dickens||(Dickens={});Bangle.setUI();g.clear(1);if(m){g.setColor("#305080");g.fillArc(.285*-Math.PI,.285*Math.PI,96);g.fillArc(Math.PI*(1-.285),1.285*Math.PI,96);g.fillRect(41,62,195,62);g.fillRect(41,175,195,175);var e=Object.keys(m),b=m[""];b&&e.splice(e.indexOf(""),1);b instanceof Object||(b={});b.fontHeight=16;void 0===b.selected&&(b.selected=0);var p=require("locale"),d={draw:function(){g.reset().setColor(-1).setFontGrotesk16();b.title&&(g.setFontAlign(0,
|
||||
-1,0),g.setBgColor("#305080").drawString(b.title,119,42));g.setBgColor(0);var c=0|Math.min(103/b.fontHeight,e.length),a=E.clip(b.selected-(c>>1),0,e.length-c),h=71;for(g.setColor(0<a?"#304060":"#305080").fillPoly([111,36,127,36,119,28]);c--;){var k=e[a],l=m[k];g.setBgColor(a!=b.selected||d.selectEdit?0:"#304060");g.setColor(-1);g.clearRect(38,h-1,200,h+b.fontHeight-1);g.setFontAlign(-1,-1);g.drawString(p.translate(k),40,h);if("object"==typeof l){k=200;var f=l.value;l.format&&(f=l.format(f));"number"==
|
||||
typeof f&&l.precision&&(f=f.toFixed(l.precision));f=p.translate(""+f);d.selectEdit&&a==b.selected&&(k-=25,g.setColor("#304060"),g.fillRect(k-(g.stringWidth(f)+8),h-1,200,h+b.fontHeight-1),g.setColor(-1),g.drawImage("\f\x05\x81\x00 \x07\x00\xf9\xf0\x0e\x00@",k,h+(b.fontHeight-10)/2,{scale:2}));g.setFontAlign(1,-1);g.drawString(f,k-2,h)}h+=b.fontHeight+1;a++}g.setFontAlign(-1,-1);g.setColor(a<e.length?"#304060":"#305080").fillPoly([110,191,128,191,119,200]);g.flip()},select:function(c){c=
|
||||
m[e[b.selected]];if("function"==typeof c)Bangle.setUI(),c(d);else if("object"==typeof c){if("number"==typeof c.value)d.selectEdit=d.selectEdit?void 0:c;else if("boolean"==typeof c.value&&(c.value=!c.value),c.onchange)c.onchange(c.value);d.draw()}},move:function(c){if(d.selectEdit){var a=d.selectEdit;a.value-=(c||1)*(a.step||1);1E-10>Math.abs(a.value)&&(a.value=0);void 0!==a.min&&a.value<a.min&&(a.value=a.wrap?a.max:a.min);void 0!==a.max&&a.value>a.max&&(a.value=a.wrap?a.min:a.max);if(a.onchange)a.onchange(a.value)}else b.selected=
|
||||
(c+b.selected)%e.length,0>b.selected&&(b.selected+=e.length);d.draw()}};Dickens.buttonIcons=["select",null,"down","up"];n&&(Dickens.buttonIcons[1]="back");d.draw();Dickens.loadSurround&&Dickens.loadSurround();Bangle.btnWatches=[setWatch(function(){d.move(-1)},BTN4,{repeat:1}),setWatch(function(){d.move(1)},BTN3,{repeat:1}),setWatch(function(){d.select()},BTN1,{repeat:1})];n&&Bangle.btnWatches.push(setWatch(n,BTN2,{repeat:1}));return d}})
|
||||
24
libs/js/dickens/E_showMessage_DICKENS.js
Normal file
24
libs/js/dickens/E_showMessage_DICKENS.js
Normal file
@ -0,0 +1,24 @@
|
||||
(function(msg,title,icon) {
|
||||
// TODO: Widgets?
|
||||
g.clear(1).setColor("#305080");
|
||||
g.fillArc(-Math.PI*0.285,Math.PI*0.285,96);
|
||||
g.fillArc(Math.PI*(1-0.285),Math.PI*1.285,96);
|
||||
g.fillRect(41,62,195,62);
|
||||
g.fillRect(41,175,195,175);
|
||||
g.setColor(-1);
|
||||
var loc = require("locale");
|
||||
var W = g.getWidth();
|
||||
var H = g.getHeight();
|
||||
if (title) {
|
||||
title = loc.translate(title);
|
||||
g.setFontGrotesk16().setFontAlign(0,-1,0).setBgColor("#305080").drawString(E.decodeUTF8(title),119,42).setBgColor(0);
|
||||
}
|
||||
if (icon) {
|
||||
g.setBgColor(cBorderBg).drawImage(icon.img, icon.x, icon.y);
|
||||
}
|
||||
g.setFontGrotesk20().setFontAlign(0,0,0);
|
||||
var lines = msg.split("\n");
|
||||
var offset = 11 + (H - lines.length*22)/2;
|
||||
lines.forEach((line,y)=>g.drawString(E.decodeUTF8(loc.translate(line)),W/2,offset + y*22));
|
||||
g.flip();
|
||||
})
|
||||
2
libs/js/dickens/E_showMessage_DICKENS.min.js
vendored
Normal file
2
libs/js/dickens/E_showMessage_DICKENS.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
(function(a,b,c){g.clear(1).setColor("#305080");g.fillArc(.285*-Math.PI,.285*Math.PI,96);g.fillArc(Math.PI*(1-.285),1.285*Math.PI,96);g.fillRect(41,62,195,62);g.fillRect(41,175,195,175);g.setColor(-1);var d=require("locale"),e=g.getWidth(),f=g.getHeight();b&&(b=d.translate(b),g.setFontGrotesk16().setFontAlign(0,-1,0).setBgColor("#305080").drawString(E.decodeUTF8(b),119,42).setBgColor(0));c&&g.setBgColor(cBorderBg).drawImage(c.img,c.x,c.y);g.setFontGrotesk20().setFontAlign(0,0,0);a=a.split("\n");
|
||||
var h=11+(f-22*a.length)/2;a.forEach((k,l)=>g.drawString(E.decodeUTF8(d.translate(k)),e/2,h+22*l));g.flip()})
|
||||
98
libs/js/dickens/E_showPrompt_DICKENS.js
Normal file
98
libs/js/dickens/E_showPrompt_DICKENS.js
Normal file
@ -0,0 +1,98 @@
|
||||
(function(msg,options) {
|
||||
if (!global.Dickens) Dickens={}; // for when called with no boot code
|
||||
var cHighlightBg = "#304060";
|
||||
var cBorderBg = "#305080";
|
||||
if (!options) options={};
|
||||
if (!options.buttons)
|
||||
options.buttons = {"Yes":true,"No":false};
|
||||
var loc = require("locale");
|
||||
var btns = Object.keys(options.buttons);
|
||||
if (!options.selected)
|
||||
options.selected = 0;
|
||||
if (options.vstack===undefined)
|
||||
options.vstack = 1;
|
||||
function draw() {
|
||||
g.reset();
|
||||
g.setColor(cBorderBg);
|
||||
g.fillArc(-Math.PI*0.285,Math.PI*0.285,96);
|
||||
g.fillArc(Math.PI*(1-0.285),Math.PI*1.285,96);
|
||||
g.fillRect(41,62,195,62);
|
||||
g.fillRect(41,175,195,175);
|
||||
g.setColor(-1);
|
||||
var W = g.getWidth();
|
||||
var H = g.getHeight();
|
||||
var title = options.title;
|
||||
if (title) {
|
||||
title = loc.translate(title);
|
||||
g.setFontGrotesk16().setFontAlign(0,-1,0).setBgColor(cBorderBg).drawString(title,119,42).setBgColor(0);
|
||||
}
|
||||
var i =options.icon;
|
||||
if (i) {
|
||||
g.setBgColor(cBorderBg).drawImage(i.img, i.x, i.y);
|
||||
}
|
||||
g.setFontGrotesk16().setFontAlign(0,0,0);
|
||||
var lines = msg.split("\n");
|
||||
var offset = 105 - lines.length*16/2;
|
||||
lines.forEach((line,y)=>
|
||||
g.drawString(loc.translate(line),W/2,offset + y*16));
|
||||
var buttonWidths = 0;
|
||||
var buttonPadding = 16;
|
||||
var x, y, w, bw, poly;
|
||||
if (options.vstack) {
|
||||
x = 120;
|
||||
y = 172-btns.length*18;
|
||||
btns.forEach((btn,idx)=>{
|
||||
btn = loc.translate(btn);
|
||||
bw = 50;
|
||||
poly = [x-bw-4,y-9,x+bw+4,y-9,x+bw+4,y+9,x-bw-4,y+9];
|
||||
g.setColor(idx==options.selected ? cHighlightBg : 0).fillPoly(poly).setColor(-1).drawPoly(poly,1).setFontGrotesk14().drawString(btn,x,y+1);
|
||||
y += 18;
|
||||
});
|
||||
} else
|
||||
{
|
||||
btns.forEach(btn=>buttonWidths += buttonPadding+g.stringWidth(loc.translate(btn)));
|
||||
x = (W-buttonWidths)/2;
|
||||
y = 150;
|
||||
btns.forEach((btn,idx)=>{
|
||||
btn = loc.translate(btn);
|
||||
w = g.stringWidth(btn);
|
||||
x += (buttonPadding+w)/2;
|
||||
bw = 2+w/2;
|
||||
poly = [x-bw-4,y-10,x+bw+4,y-10,x+bw+4,y+10,x-bw-4,y+10];
|
||||
g.setColor(idx==options.selected ? cHighlightBg : 0).fillPoly(poly).setColor(-1).drawPoly(poly,1).drawString(btn,x,y+1);
|
||||
x += (buttonPadding+w)/2;
|
||||
});
|
||||
}
|
||||
g.setColor(-1).flip(); // turn screen on
|
||||
}
|
||||
Bangle.setUI(); // clear Bangle.btnWatches
|
||||
// TODO: Widgets?
|
||||
g.clear(1);
|
||||
Dickens.buttonIcons=['select',null,'down','up'];
|
||||
if (!msg) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
draw();
|
||||
Dickens.loadSurround&&Dickens.loadSurround();
|
||||
return new Promise(resolve=>{
|
||||
Bangle.btnWatches = [
|
||||
setWatch(function() {
|
||||
if (options.selected>0) {
|
||||
options.selected--;
|
||||
draw();
|
||||
}
|
||||
}, BTN4, {repeat:1}),
|
||||
setWatch(function() {
|
||||
if (options.selected<btns.length-1) {
|
||||
options.selected++;
|
||||
draw();
|
||||
}
|
||||
}, BTN3, {repeat:1}),
|
||||
setWatch(function() {
|
||||
E.showPrompt();
|
||||
Bangle.setUI(); // clear Bangle.btnWatches
|
||||
resolve(options.buttons[btns[options.selected]]);
|
||||
}, BTN1, {repeat:1})
|
||||
];
|
||||
});
|
||||
})
|
||||
4
libs/js/dickens/E_showPrompt_DICKENS.min.js
vendored
Normal file
4
libs/js/dickens/E_showPrompt_DICKENS.min.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
(function(r,a){function q(){g.reset();g.setColor("#305080");g.fillArc(.285*-Math.PI,.285*Math.PI,96);g.fillArc(Math.PI*(1-.285),1.285*Math.PI,96);g.fillRect(41,62,195,62);g.fillRect(41,175,195,175);g.setColor(-1);var n=g.getWidth();g.getHeight();var e=a.title;e&&(e=l.translate(e),g.setFontGrotesk16().setFontAlign(0,-1,0).setBgColor("#305080").drawString(e,119,42).setBgColor(0));(e=a.icon)&&g.setBgColor("#305080").drawImage(e.img,e.x,e.y);g.setFontGrotesk16().setFontAlign(0,
|
||||
0,0);e=r.split("\n");var u=105-16*e.length/2;e.forEach((c,m)=>g.drawString(l.translate(c),n/2,u+16*m));var t=0,p,f,h;if(a.vstack){var b=120;var d=172-18*k.length;k.forEach((c,m)=>{c=l.translate(c);f=50;h=[b-f-4,d-9,b+f+4,d-9,b+f+4,d+9,b-f-4,d+9];g.setColor(m==a.selected?"#304060":0).fillPoly(h).setColor(-1).drawPoly(h,1).setFontGrotesk14().drawString(c,b,d+1);d+=18})}else k.forEach(c=>t+=16+g.stringWidth(l.translate(c))),b=(n-t)/2,d=150,k.forEach((c,m)=>{c=l.translate(c);p=g.stringWidth(c);b+=(16+
|
||||
p)/2;f=2+p/2;h=[b-f-4,d-10,b+f+4,d-10,b+f+4,d+10,b-f-4,d+10];g.setColor(m==a.selected?"#304060":0).fillPoly(h).setColor(-1).drawPoly(h,1).drawString(c,b,d+1);b+=(16+p)/2});g.setColor(-1).flip()}global.Dickens||(Dickens={});a||(a={});a.buttons||(a.buttons={Yes:!0,No:!1});var l=require("locale"),k=Object.keys(a.buttons);a.selected||(a.selected=0);void 0===a.vstack&&(a.vstack=1);Bangle.setUI();g.clear(1);Dickens.buttonIcons=["select",null,"down","up"];if(!r)return Promise.resolve();q();Dickens.loadSurround&&
|
||||
Dickens.loadSurround();return new Promise(n=>{Bangle.btnWatches=[setWatch(function(){0<a.selected&&(a.selected--,q())},BTN4,{repeat:1}),setWatch(function(){a.selected<k.length-1&&(a.selected++,q())},BTN3,{repeat:1}),setWatch(function(){E.showPrompt();Bangle.setUI();n(a.buttons[k[a.selected]])},BTN1,{repeat:1})]})})
|
||||
@ -18,10 +18,10 @@ wget https://www.espruino.com/modules/MPU9250.min.js -O MPU9250.min.js
|
||||
wget https://www.espruino.com/modules/LPS22HB.min.js -O LPS22HB.min.js
|
||||
wget https://www.espruino.com/modules/HTS221.min.js -O HTS221.min.js
|
||||
wget https://www.espruino.com/modules/CCS811.min.js -O CCS811.min.js
|
||||
wget https://www.espruino.com/modules/BH1745.min.js -O BH1745.min.js
|
||||
wget https://www.espruino.com/modules/BH1745.min.js -O BH1745.min.js
|
||||
wget https://www.espruino.com/modules/SHT3C.min.js -O SHT3C.min.js
|
||||
#wget https://www.espruino.com/modules/PCA9685.min.js -O PCA9685.min.js
|
||||
#wget https://www.espruino.com/modules/Smartibot.min.js -O Smartibot.min.js
|
||||
#wget https://www.espruino.com/modules/PCA9685.min.js -O PCA9685.min.js
|
||||
#wget https://www.espruino.com/modules/Smartibot.min.js -O Smartibot.min.js
|
||||
|
||||
# Other libs
|
||||
wget https://www.espruino.com/modules/EspruinoWiFi.min.js -O espruino_wifi/Wifi.min.js
|
||||
@ -54,4 +54,9 @@ node ../../../EspruinoDocs/bin/minify.js banglejs/Bangle_setUI_F18.js banglejs/B
|
||||
node ../../../EspruinoDocs/bin/minify.js banglejs/Bangle_setUI_Q3.js banglejs/Bangle_setUI_Q3.min.js
|
||||
node ../../../EspruinoDocs/bin/minify.js banglejs/locale.js banglejs/locale.min.js
|
||||
|
||||
node ../../../EspruinoDocs/bin/minify.js dickens/Bangle_setUI_DICKENS.js dickens/Bangle_setUI_DICKENS.min.js
|
||||
node ../../../EspruinoDocs/bin/minify.js dickens/Bangle_drawWidgets_DICKENS.js dickens/Bangle_drawWidgets_DICKENS.min.js
|
||||
node ../../../EspruinoDocs/bin/minify.js dickens/E_showMenu_DICKENS.js dickens/E_showMenu_DICKENS.min.js
|
||||
node ../../../EspruinoDocs/bin/minify.js dickens/E_showPrompt_DICKENS.js dickens/E_showPrompt_DICKENS.min.js
|
||||
node ../../../EspruinoDocs/bin/minify.js dickens/E_showMessage_DICKENS.js dickens/E_showMessage_DICKENS.min.js
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python2.7
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
/* This builds a js file containing the addresses of a chip's PERIPHERALS and
|
||||
the values of the bits in each register. Can be used for quickly building
|
||||
ways to access the underlying hardware from JS.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
/* This'll take JavaScript source files and convert them
|
||||
to jswrap files to be included in the interpreter.
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
|
||||
// sudo npm install -g marked highlight.js
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Add two spaces at the beginning of every line.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
# Checks to see if an Elf file will fit in memory before the
|
||||
# area reserved for Storage (saved code). This is mainly used
|
||||
# for nRF5x parts (which don't generate binaries and which
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
|
||||
if (process.argv.length == 3 && process.argv[2] == "BANGLEJS") {
|
||||
var EMULATOR = "banglejs1";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
/** This scans a source code listing file for Thumb assembly
|
||||
code instructions that are repeated. It scores them according
|
||||
to `no_of_instructions * times_repeated` and outputs the top
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/nodejs
|
||||
#!/usr/bin/env node
|
||||
/* Take a hex file and turn it into Espruino commands that write
|
||||
to external flash. Special flash bootloaders (targets/nrf52_dfu/flash.c)
|
||||
can then take this and do the firmware update.
|
||||
@ -18,7 +18,7 @@ var inputFile = process.argv[2];
|
||||
|
||||
var hex = require("fs").readFileSync(inputFile).toString().split("\n");
|
||||
function parseLines(dataCallback) {
|
||||
var addrHi = 0;
|
||||
var addrHi = 0;
|
||||
hex.forEach(function(hexline) {
|
||||
if (DEBUG) console.log(hexline);
|
||||
var bytes = hexline.substr(1,2);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2008,2010,2011,2013,2014,2015 Alexander Belchenko
|
||||
# All rights reserved.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/nodejs
|
||||
#!/usr/bin/env node
|
||||
/* This is a big hack - we take a hex file and turn it into
|
||||
Espruino commands that write the memory directly via JS. Can
|
||||
be used to do bootloader updates/etc.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
# (c) Alexander Belchenko, 2007, 2009
|
||||
|
||||
# [2013/08] NOTE: This file is keeping for historical reasons.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/node
|
||||
#!/usr/bin/env node
|
||||
/* This was designed to be run once over Espruino
|
||||
* ... hence it has probably already been run.
|
||||
*
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
#
|
||||
|
||||
@ -1370,10 +1370,14 @@ JsVar *jsfGetBootCodeFromFlash(bool isReset) {
|
||||
}
|
||||
|
||||
bool jsfLoadBootCodeFromFlash(bool isReset) {
|
||||
// Load code in .bootFirst at first boot UNLESS BTN1 IS HELD DOWN
|
||||
// Load code in .bootFirst at first boot UNLESS BTN1 IS HELD DOWN (BTN3 for Dickens)
|
||||
#ifndef SAVE_ON_FLASH
|
||||
#if (defined(BANGLEJS) && !defined(DICKENS))
|
||||
#if defined(BANGLEJS)
|
||||
#if defined(DICKENS)
|
||||
if (!(jshPinGetValue(BTN3_PININDEX)==BTN3_ONSTATE))
|
||||
#else
|
||||
if (!(jshPinGetValue(BTN1_PININDEX)==BTN1_ONSTATE))
|
||||
#endif
|
||||
#endif
|
||||
if (jsiStatus & JSIS_FIRST_BOOT) {
|
||||
JsVar *code = jsfReadFile(jsfNameFromString(".bootPowerOn"),0,0);
|
||||
@ -1381,11 +1385,16 @@ bool jsfLoadBootCodeFromFlash(bool isReset) {
|
||||
jsvUnLock2(jspEvaluateVar(code,0,0), code);
|
||||
}
|
||||
#endif
|
||||
// Load code in .boot0/1/2/3 UNLESS BTN1 IS HELD DOWN FOR BANGLE.JS ON FIRST BOOT
|
||||
// Load code in .boot0/1/2/3 UNLESS BTN1 IS HELD DOWN FOR BANGLE.JS ON FIRST BOOT (BTN3 for Dickens)
|
||||
// On an average Bangle.js 2 this takes 0.25 ms (so not worth optimising)
|
||||
#if (defined(BANGLEJS) && !defined(DICKENS))
|
||||
#if defined(BANGLEJS)
|
||||
#if defined(DICKENS)
|
||||
if (!(jshPinGetValue(BTN3_PININDEX)==BTN3_ONSTATE &&
|
||||
(jsiStatus & JSIS_FIRST_BOOT)))
|
||||
#else // not DICKENS
|
||||
if (!(jshPinGetValue(BTN1_PININDEX)==BTN1_ONSTATE &&
|
||||
(jsiStatus & JSIS_FIRST_BOOT)))
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
char filename[7] = ".bootX";
|
||||
|
||||
@ -860,6 +860,12 @@ void jsiSemiInit(bool autoLoad, JsfFileName *loadedFilename) {
|
||||
// set up terminal to avoid word wrap
|
||||
"\e[?7l"
|
||||
#endif
|
||||
#if (defined(DICKENS) || defined(EMSCRIPTEN_DICKENS))
|
||||
"\n"
|
||||
"------------------------\n"
|
||||
"PROJECT DICKENS "JS_VERSION"\n"
|
||||
"© 2023 G.Williams & TWC\n"
|
||||
#else
|
||||
// rectangles @ http://www.network-science.de/ascii/
|
||||
"\n"
|
||||
" ____ _ \n"
|
||||
@ -867,7 +873,7 @@ void jsiSemiInit(bool autoLoad, JsfFileName *loadedFilename) {
|
||||
"| __|_ -| . | _| | | | | . |\n"
|
||||
"|____|___| _|_| |___|_|_|_|___|\n"
|
||||
" |_| espruino.com\n"
|
||||
" "JS_VERSION" (c) 2021 G.Williams\n"
|
||||
" "JS_VERSION" (c) 2023 G.Williams\n"
|
||||
// Point out about donations - but don't bug people
|
||||
// who bought boards that helped Espruino
|
||||
#if !defined(PICO) && !defined(ESPRUINOBOARD) && !defined(ESPRUINOWIFI) && !defined(PUCKJS) && !defined(PIXLJS) && !defined(BANGLEJS) && !defined(EMSCRIPTEN)
|
||||
@ -875,6 +881,7 @@ void jsiSemiInit(bool autoLoad, JsfFileName *loadedFilename) {
|
||||
"Espruino is Open Source. Our work is supported\n"
|
||||
"only by sales of official boards and donations:\n"
|
||||
"http://espruino.com/Donate\n"
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
#ifdef ESP8266
|
||||
|
||||
@ -805,6 +805,7 @@ void vcbprintf(
|
||||
user_callback(buf,user_data);
|
||||
break;
|
||||
}
|
||||
case 'i': // Added to support some NRF_LOG_INFO calls in, for example, nrf_ble_ancs_c.c
|
||||
case 'd': itostr(va_arg(argp, int), buf, 10); user_callback(buf,user_data); break;
|
||||
case 'x': itostr_extra(va_arg(argp, int), buf, false, 16); user_callback(buf,user_data); break;
|
||||
case 'L': {
|
||||
|
||||
@ -423,15 +423,24 @@ void jswrap_storage_debug() {
|
||||
"ifndef" : "SAVE_ON_FLASH",
|
||||
"class" : "Storage",
|
||||
"name" : "getFree",
|
||||
"params" : [
|
||||
["checkInternalFlash","bool","Check the internal flash (rather than external SPI flash). Default false, so will check external storage"]
|
||||
],
|
||||
"generate" : "jswrap_storage_getFree",
|
||||
"return" : ["int","The amount of free bytes"]
|
||||
}
|
||||
Return the amount of free bytes available in Storage. Due to fragmentation there
|
||||
may be more bytes available, but this represents the maximum size of file that
|
||||
can be written.
|
||||
|
||||
**NOTE:** `checkInternalFlash` is only useful on DICKENS devices - other devices don't use two different flash banks
|
||||
*/
|
||||
int jswrap_storage_getFree() {
|
||||
return (int)jsfGetStorageStats(0,true).free;
|
||||
int jswrap_storage_getFree(bool checkInternalFlash) {
|
||||
uint32_t addr = 0;
|
||||
#ifdef FLASH_SAVED_CODE2_START
|
||||
addr = checkInternalFlash ? FLASH_SAVED_CODE_START : FLASH_SAVED_CODE2_START;
|
||||
#endif
|
||||
return (int)jsfGetStorageStats(addr,true).free;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
@ -439,6 +448,9 @@ int jswrap_storage_getFree() {
|
||||
"ifndef" : "SAVE_ON_FLASH",
|
||||
"class" : "Storage",
|
||||
"name" : "getStats",
|
||||
"params" : [
|
||||
["checkInternalFlash","bool","Check the internal flash (rather than external SPI flash). Default false, so will check external storage"]
|
||||
],
|
||||
"generate" : "jswrap_storage_getStats",
|
||||
"return" : ["JsVar","An object containing info about the current Storage system"]
|
||||
}
|
||||
@ -454,11 +466,18 @@ Returns:
|
||||
trashCount // How many trash files do we have? (can be cleared with .compact)
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE:** `checkInternalFlash` is only useful on DICKENS devices - other devices don't use two different flash banks
|
||||
*/
|
||||
JsVar *jswrap_storage_getStats() {
|
||||
JsVar *jswrap_storage_getStats(bool checkInternalFlash) {
|
||||
JsVar *o = jsvNewObject();
|
||||
if (!o) return NULL;
|
||||
JsfStorageStats stats = jsfGetStorageStats(0, true);
|
||||
uint32_t addr = 0;
|
||||
#ifdef FLASH_SAVED_CODE2_START
|
||||
addr = checkInternalFlash ? FLASH_SAVED_CODE_START : FLASH_SAVED_CODE2_START;
|
||||
|
||||
#endif
|
||||
JsfStorageStats stats = jsfGetStorageStats(addr, true);
|
||||
jsvObjectSetChildAndUnLock(o, "totalBytes", jsvNewFromInteger((JsVarInt)stats.total));
|
||||
jsvObjectSetChildAndUnLock(o, "freeBytes", jsvNewFromInteger((JsVarInt)stats.free));
|
||||
jsvObjectSetChildAndUnLock(o, "fileBytes", jsvNewFromInteger((JsVarInt)stats.fileBytes));
|
||||
|
||||
@ -29,8 +29,8 @@ void jswrap_storage_compact(bool showMessage);
|
||||
JsVar *jswrap_storage_list(JsVar *regex, JsVar *filter);
|
||||
JsVarInt jswrap_storage_hash(JsVar *regex);
|
||||
void jswrap_storage_debug();
|
||||
int jswrap_storage_getFree();
|
||||
JsVar *jswrap_storage_getStats();
|
||||
int jswrap_storage_getFree(bool checkInternalFlash);
|
||||
JsVar *jswrap_storage_getStats(bool checkInternalFlash);
|
||||
void jswrap_storage_optimise();
|
||||
|
||||
JsVar *jswrap_storage_open(JsVar *name, JsVar *mode);
|
||||
|
||||
@ -614,6 +614,89 @@ JsVar *jswrap_string_toUpperLowerCase(JsVar *parent, bool upper) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "String",
|
||||
"name" : "removeAccents",
|
||||
"ifndef" : "SAVE_ON_FLASH",
|
||||
"generate_full" : "jswrap_string_removeAccents(parent)",
|
||||
"return" : ["JsVar","This string with the accents/diacritics (such as é, ü) removed from characters in the ISO 8859-1 set"]
|
||||
}*/
|
||||
JsVar *jswrap_string_removeAccents(JsVar *parent) {
|
||||
bool isLowerCase;
|
||||
JsVar *res = jsvNewFromEmptyString();
|
||||
if (!res) return 0; // out of memory
|
||||
JsVar *parentStr = jsvAsString(parent);
|
||||
|
||||
JsvStringIterator itsrc, itdst;
|
||||
jsvStringIteratorNew(&itsrc, parentStr, 0);
|
||||
jsvStringIteratorNew(&itdst, res, 0);
|
||||
|
||||
while (jsvStringIteratorHasChar(&itsrc)) {
|
||||
char ch = jsvStringIteratorGetCharAndNext(&itsrc);
|
||||
if (ch >= 0xE0) {
|
||||
isLowerCase = true;
|
||||
ch -= 32;
|
||||
} else {
|
||||
isLowerCase = false;
|
||||
}
|
||||
if (ch >= 0xC0) {
|
||||
switch (ch) {
|
||||
case 0xC0 ... 0xC5: // À Á Â Ã Ä Å
|
||||
ch = 'A';
|
||||
break;
|
||||
case 0xC6: // convert Æ to AE
|
||||
jsvStringIteratorAppend(&itdst, isLowerCase ? 'a' : 'A');
|
||||
ch = 'E';
|
||||
break;
|
||||
case 0xC7: // Ç
|
||||
ch = 'C';
|
||||
break;
|
||||
case 0xC8 ... 0xCB: // È É Ê Ë
|
||||
ch = 'E';
|
||||
break;
|
||||
case 0xCC ... 0xCF: // Ì Í Î Ï
|
||||
ch = 'I';
|
||||
break;
|
||||
case 0xD0: // Ð
|
||||
ch = 'D';
|
||||
break;
|
||||
case 0xD1: // Ñ
|
||||
ch = 'N';
|
||||
break;
|
||||
case 0xD2 ... 0xD6: // Ò Ó Ô Õ Ö
|
||||
case 0xD8: // Ø
|
||||
ch = 'O';
|
||||
break;
|
||||
case 0xD9 ... 0xDC: // Ù Ú Û Ü
|
||||
ch = 'U';
|
||||
break;
|
||||
case 0xDD: // Ý
|
||||
ch = 'Y';
|
||||
break;
|
||||
case 0xDE: // Þ
|
||||
ch = 'P';
|
||||
break;
|
||||
case 0xDF: // ß to SS or ÿ to y (if lowercase)
|
||||
if (isLowerCase) {
|
||||
ch = 'Y';
|
||||
} else {
|
||||
jsvStringIteratorAppend(&itdst, 'S');
|
||||
ch = 'S';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
jsvStringIteratorAppend(&itdst, isLowerCase ? ch+32 : ch);
|
||||
}
|
||||
|
||||
jsvStringIteratorFree(&itsrc);
|
||||
jsvStringIteratorFree(&itdst);
|
||||
jsvUnLock(parentStr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "String",
|
||||
|
||||
@ -29,6 +29,7 @@ JsVar *jswrap_string_substr(JsVar *parent, JsVarInt pStart, JsVar *vLen);
|
||||
JsVar *jswrap_string_slice(JsVar *parent, JsVarInt pStart, JsVar *vEnd);
|
||||
JsVar *jswrap_string_split(JsVar *parent, JsVar *split);
|
||||
JsVar *jswrap_string_toUpperLowerCase(JsVar *parent, bool upper);
|
||||
JsVar *jswrap_string_removeAccents(JsVar *parent);
|
||||
JsVar *jswrap_string_trim(JsVar *parent);
|
||||
JsVar *jswrap_string_concat(JsVar *parent, JsVar *args);
|
||||
bool jswrap_string_startsWith(JsVar *parent, JsVar *search, int position);
|
||||
|
||||
@ -448,7 +448,7 @@ ret_code_t ble_ams_c_remote_command_write(ble_ams_c_t const * p_ams_c,
|
||||
}
|
||||
|
||||
ret_code_t ble_ams_c_entity_update_write(ble_ams_c_t const * p_ams_c,
|
||||
ble_ams_c_evt_id_values_t entity_id,
|
||||
ble_ams_c_entity_id_values_t entity_id,
|
||||
uint8_t attribute_number,
|
||||
uint8_t * attribute_list)
|
||||
{
|
||||
@ -490,7 +490,7 @@ ret_code_t ble_ams_c_entity_update_write(ble_ams_c_t const * p_ams_c,
|
||||
}
|
||||
|
||||
ret_code_t ble_ams_c_entity_attribute_write(ble_ams_c_t const * p_ams_c,
|
||||
ble_ams_c_evt_id_values_t entity_id,
|
||||
ble_ams_c_entity_id_values_t entity_id,
|
||||
uint8_t attribute_id)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_ams_c);
|
||||
|
||||
@ -164,7 +164,7 @@ typedef enum
|
||||
BLE_AMS_ENTITY_ID_PLAYER, /**< The iOS notification was added. */
|
||||
BLE_AMS_ENTITY_ID_QUEUE, /**< The iOS notification was modified. */
|
||||
BLE_AMS_ENTITY_ID_TRACK /**< The iOS notification was removed. */
|
||||
} ble_ams_c_evt_id_values_t;
|
||||
} ble_ams_c_entity_id_values_t;
|
||||
|
||||
/**@brief Flags for iOS media (Entity Update). */
|
||||
typedef struct
|
||||
@ -420,7 +420,7 @@ ret_code_t ble_ams_c_remote_command_write(ble_ams_c_t const * p_ams_c,
|
||||
* \param[in] attribute_list List of the desired attributes
|
||||
*/
|
||||
ret_code_t ble_ams_c_entity_update_write(ble_ams_c_t const * p_ams_c,
|
||||
ble_ams_c_evt_id_values_t entity_id,
|
||||
ble_ams_c_entity_id_values_t entity_id,
|
||||
uint8_t attribute_number,
|
||||
uint8_t * attribute_list);
|
||||
|
||||
@ -434,7 +434,7 @@ ret_code_t ble_ams_c_entity_update_write(ble_ams_c_t const * p_ams_c,
|
||||
* \param[in] attribute_id ID of the desired Attribute
|
||||
*/
|
||||
ret_code_t ble_ams_c_entity_attribute_write(ble_ams_c_t const * p_ams_c,
|
||||
ble_ams_c_evt_id_values_t entity_id,
|
||||
ble_ams_c_entity_id_values_t entity_id,
|
||||
uint8_t attribute_id);
|
||||
|
||||
/**
|
||||
|
||||
@ -528,16 +528,21 @@ int jsble_exec_pending(IOEvent *event) {
|
||||
#ifdef LINK_SECURITY
|
||||
case BLEP_TASK_PASSKEY_DISPLAY: { // data = connection handle
|
||||
uint16_t conn_handle = data;
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
/* TODO: yes/no passkey
|
||||
uint8_t match_request : 1; If 1 requires the application to report the match using @ref sd_ble_gap_auth_key_reply
|
||||
with either @ref BLE_GAP_AUTH_KEY_TYPE_NONE if there is no match or
|
||||
@ref BLE_GAP_AUTH_KEY_TYPE_PASSKEY if there is a match. */
|
||||
int centralIdx = jsble_get_central_connection_idx(conn_handle);
|
||||
#endif
|
||||
if (bufferLen==BLE_GAP_PASSKEY_LEN) {
|
||||
buffer[BLE_GAP_PASSKEY_LEN] = 0;
|
||||
JsVar *passkey = jsvNewFromString((char*)buffer);
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
if (centralIdx<0) { // it's on the peripheral connection
|
||||
#endif
|
||||
bleQueueEventAndUnLock(JS_EVENT_PREFIX"passkey", passkey);
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
} else { // it's on a central connection
|
||||
JsVar *gattServer = bleGetActiveBluetoothGattServer(centralIdx);
|
||||
if (gattServer) {
|
||||
@ -549,6 +554,7 @@ uint8_t match_request : 1; If 1 requires the application to report
|
||||
jsvUnLock2(bluetoothDevice, gattServer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
jsvUnLock(passkey);
|
||||
}
|
||||
break;
|
||||
@ -669,6 +675,8 @@ uint8_t match_request : 1; If 1 requires the application to report
|
||||
default:
|
||||
jsWarn("jsble_exec_pending: Unknown enum type %d",(int)blep);
|
||||
}
|
||||
if (jspIsInterrupted())
|
||||
jsWarn("jsble_exec_pending: Interrupted processing event %d",(int)blep);
|
||||
return eventsHandled;
|
||||
}
|
||||
|
||||
@ -1834,8 +1842,10 @@ static void pm_evt_handler(pm_evt_t const * p_evt) {
|
||||
|
||||
case PM_EVT_STORAGE_FULL:
|
||||
{
|
||||
jsWarn("PM: PM_EVT_STORAGE_FULL - running garbage collection");
|
||||
// Run garbage collection on the flash.
|
||||
err_code = fds_gc();
|
||||
jsWarn("Garbage collection result: %d", err_code);
|
||||
if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
|
||||
{
|
||||
// Retry.
|
||||
@ -3379,9 +3389,11 @@ void jsble_set_tx_power(int8_t pwr) {
|
||||
#if NRF_SD_BLE_API_VERSION > 5
|
||||
if (m_peripheral_conn_handle != BLE_CONN_HANDLE_INVALID)
|
||||
err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_peripheral_conn_handle, pwr);
|
||||
#if CENTRAL_LINK_COUNT>0
|
||||
for (int i=0;i<CENTRAL_LINK_COUNT;i++)
|
||||
if (m_central_conn_handles[i] != BLE_CONN_HANDLE_INVALID)
|
||||
err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_central_conn_handles[i], pwr);
|
||||
#endif
|
||||
if (m_adv_handle != BLE_GAP_ADV_SET_HANDLE_NOT_SET)
|
||||
err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, pwr);
|
||||
err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_SCAN_INIT, 0/*ignored*/, pwr);
|
||||
|
||||
@ -286,7 +286,7 @@ void ble_cts_handle_time(BLEPending blep, char *buffer, size_t bufferLen) {
|
||||
ble_date_time_t time = p_time->exact_time_256.day_date_time.date_time;
|
||||
CalendarDate date;
|
||||
date.year = time.year;
|
||||
date.month = time.month;
|
||||
date.month = time.month-1; // JS months are 0-11, but CTS uses 1-12
|
||||
date.day = time.day;
|
||||
TimeInDay td;
|
||||
td.daysSinceEpoch = fromCalenderDate(&date);
|
||||
|
||||
@ -664,9 +664,12 @@ static NO_INLINE void jshPinSetFunction_int(JshPinFunction func, uint32_t pin) {
|
||||
case JSH_TIMER2:
|
||||
case JSH_TIMER3: {
|
||||
NRF_PWM_Type *pwm = nrf_get_pwm(fType);
|
||||
pwm->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin;
|
||||
// FIXME: Only disable if nothing else is using it!
|
||||
if (pin==0xFFFFFFFF) nrf_pwm_disable(pwm);
|
||||
if (pin==0xFFFFFFFF) {
|
||||
nrf_pwm_task_trigger(pwm, NRF_PWM_TASK_STOP);
|
||||
nrf_pwm_disable(pwm);
|
||||
}
|
||||
pwm->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -93,7 +93,6 @@ static void flashReset(){
|
||||
nrf_delay_us(50);
|
||||
}
|
||||
|
||||
|
||||
// Wake up the SPI Flash from deep power-down mode
|
||||
static void flashWakeUp() {
|
||||
unsigned char buf = 0xAB; // SPI Flash release from deep power-down
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "jspininfo.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "lcd.h"
|
||||
|
||||
/// Because Nordic's library functions don't inline on NRF52840!
|
||||
#ifdef NRF_P1
|
||||
@ -81,6 +82,15 @@ static bool get_btn2_state() {
|
||||
return jshPinGetValue(BTN2_PININDEX)==BTN2_ONSTATE;
|
||||
}
|
||||
#endif
|
||||
#ifdef BAT_PIN_CHARGING
|
||||
static bool get_charging_state() {
|
||||
return jshPinGetValue(BAT_PIN_CHARGING)==0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void print_fw_version(void) {
|
||||
lcd_println("BL " JS_VERSION "\n");
|
||||
}
|
||||
|
||||
static void hardware_init(void) {
|
||||
#if defined(PIXLJS)
|
||||
@ -88,6 +98,15 @@ static void hardware_init(void) {
|
||||
jshPinOutput(LED1_PININDEX, 0);
|
||||
#endif
|
||||
set_led_state(false, false);
|
||||
#ifdef DICKENS // Simpler setup of BTN1 and BTN2 to save 48 bytes of code space
|
||||
NRF_GPIO_PIN_CNF(BTN1_PININDEX,0x0000000c); // BTN1 input (with pullup)
|
||||
NRF_GPIO_PIN_CNF(BTN2_PININDEX,0x0000000c); // BTN2 input (with pullup)
|
||||
jshPinOutput(LCD_BL, !LCD_BL_ON); // backlight off
|
||||
// NRF_P1->OUT=0x00000001; // Backlight output high (for off)
|
||||
#ifdef BAT_PIN_CHARGING
|
||||
NRF_GPIO_PIN_CNF(BAT_PIN_CHARGING,0x0000000c); // Charge input (with pullup)
|
||||
#endif
|
||||
#else // !DICKENS
|
||||
#ifdef BTN1_PININDEX
|
||||
bool polarity;
|
||||
uint32_t pin;
|
||||
@ -108,7 +127,10 @@ static void hardware_init(void) {
|
||||
nrf_gpio_cfg_input(pin,
|
||||
polarity ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP);
|
||||
#endif
|
||||
#endif // !DICKENS
|
||||
#ifdef VIBRATE_PIN
|
||||
jshPinOutput(VIBRATE_PIN,0); // vibrate off
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ const unsigned short LCD_FONT_3X5[] = { // from 33 up to 127
|
||||
PACK_5_TO_16( X__ , _X_ , X_X , X_X , X_X ),
|
||||
PACK_5_TO_16( _X_ , _X_ , X_X , X_X , XXX ),
|
||||
PACK_5_TO_16( __X , _X_ , X_X , _X_ , XXX ),
|
||||
PACK_5_TO_16( XX_ , _X_ , _X_ , _X_ , X_X ),
|
||||
PACK_5_TO_16( XX_ , _X_ , XXX , _X_ , X_X ),
|
||||
|
||||
PACK_5_TO_16( X_X , X_X , XXX , _XX , ___ ), // XYZ[\ end
|
||||
PACK_5_TO_16( X_X , X_X , __X , _X_ , ___ ), // \ is used as .
|
||||
@ -591,20 +591,20 @@ static const char SPILCD_INIT_CODE[] = {
|
||||
#endif
|
||||
#ifdef LCD_CONTROLLER_GC9A01
|
||||
// CMD,DELAY,DATA_LEN,D0,D1,D2...
|
||||
0xfe,0,0,
|
||||
0xef,0,0,
|
||||
0xeb,0,1, 0x14,
|
||||
0xfe,0,0,
|
||||
0xef,0,0,
|
||||
0xeb,0,1, 0x14,
|
||||
0x84,0,1, 0x60, // 0x40->0x60 0xb5 en 20200924 james
|
||||
0x85,0,1, 0xFF,
|
||||
0x86,0,1, 0xFF,
|
||||
0x87,0,1, 0xFF,
|
||||
0x8e,0,1, 0xFF,
|
||||
0x8f,0,1, 0xFF,
|
||||
0x88,0,1, 10,
|
||||
0x88,0,1, 10,
|
||||
0x89,0,1, 0x23, // 0x21->0x23 spi 2data reg en
|
||||
0x8a,0,1, 0,
|
||||
0x8b,0,1, 0x80,
|
||||
0x8c,0,1, 1,
|
||||
0x8a,0,1, 0,
|
||||
0x8b,0,1, 0x80,
|
||||
0x8c,0,1, 1,
|
||||
0x8d,0,1, 3, // 1->3 99 en
|
||||
0xb5,0,4, 0x08, 0x09, 0x14, 0x08,
|
||||
0xb6,0,2, 0, 0, // Positive sweep 0x20->0 GS SS 0x20
|
||||
@ -623,43 +623,41 @@ static const char SPILCD_INIT_CODE[] = {
|
||||
#else
|
||||
0x36,0,1, 0x88, // Memory Access Control (no rotation)
|
||||
#endif
|
||||
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, 0x1d, // Power control 2: 0x13->0x1d
|
||||
0xc4,0,1, 0x1d, // Power control 3: 0x13->0x1d
|
||||
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, // Power control 2: 0x13->0x1d->0x13 (again)
|
||||
0xc4,0,1, 0x13, // Power control 3: 0x13->0x1d->0x13 (again)
|
||||
0xc9,0,1, 0x25, // Power control 4: 0x22->0x25
|
||||
0xbe,0,1, 0x11,
|
||||
0xe1,0,2, 0x10, 0xe,
|
||||
0xdf,0,3, 0x21, 0xc, 2,
|
||||
0xf0,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 1
|
||||
0xf1,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 2
|
||||
0xf2,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 3
|
||||
0xf3,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 4
|
||||
0xed,0,2, 0x1b, 0xb,
|
||||
0xbe,0,1, 0x11,
|
||||
0xe1,0,2, 0x10, 0xe,
|
||||
0xdf,0,3, 0x21, 0xc, 2,
|
||||
// disabled to save flash: 0xf0,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 1
|
||||
// disabled to save flash: 0xf1,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 2
|
||||
// disabled to save flash: 0xf2,0,6, 0x45, 9, 8, 8, 0x26, 0x2a, // Gamma 3
|
||||
// disabled to save flash: 0xf3,0,6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6f, // Gamma 4
|
||||
0xed,0,2, 0x1b, 0xb,
|
||||
0xae,0,1, 0x77, // 0x74->0x77
|
||||
0xcd,0,1, 99,
|
||||
0xcd,0,1, 0x63,
|
||||
0x70,0,9, 7, 7, 4, 0xe, 0xf, 9, 7, 8, 3, // 7,9,4... -> 7,7,4...
|
||||
0xe8,0,1, 0x34,
|
||||
0x60,0,4, 0x38, 0x0b, 0x6d, 0x6d,
|
||||
0x39,0,3, 0xf0, 0x6d, 0x6d,
|
||||
0x61,0,4, 0x38, 0xf4, 0x6d, 0x6d,
|
||||
0x38,0,3, 0xf7, 0x6d, 0x6d,
|
||||
0xe8,0,1, 0x34,
|
||||
0x60,0,8, 0x38, 0x0b, 0x6d, 0x6d, 0x39, 0xf0, 0x6d, 0x6d,
|
||||
0x61,0,8, 0x38, 0xf4, 0x6d, 0x6d, 0x38, 0xf7, 0x6d, 0x6d,
|
||||
0x62,0,12, 0x38, 0xd, 0x71, 0xed, 0x70, 0x70, 0x38, 0xf, 0x71, 0xef, 0x70, 0x70,
|
||||
0x63,0,12, 0x38, 0x11, 0x71, 0xf1, 0x70, 0x70, 0x38, 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,
|
||||
0x64,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, 0x68, 0x80, 0, 0, 0x4e, 0, // 0x85->0x68
|
||||
0x98,0,2, 0x3e, 7,
|
||||
0x99,0,2, 0x3e, 7, // bvee 2x
|
||||
0x35,0,1, 0,
|
||||
0x21,5,0,
|
||||
0x11,5,0,
|
||||
0x29,5,0,
|
||||
0x2c,0,0,
|
||||
0x35,0,1, 0, // Tearing effect (TE) line ON, with V-blanking only
|
||||
0x21,5,0, // Display inversion ON
|
||||
0x11,5,0, // Sleep out
|
||||
0x29,5,0, // Display ON
|
||||
0x2c,0,0, // Memory write
|
||||
#endif
|
||||
// End
|
||||
0, 0, 255/*DATA_LEN = 255 => END*/
|
||||
@ -751,9 +749,9 @@ void lcd_init() {
|
||||
jshPinOutput(LCD_SPI_SCK,1);
|
||||
jshPinOutput(LCD_SPI_MOSI,1);
|
||||
jshPinOutput(LCD_SPI_RST,0);
|
||||
jshDelayMicroseconds(10000);
|
||||
nrf_delay_ms(50);
|
||||
jshPinOutput(LCD_SPI_RST, 1);
|
||||
jshDelayMicroseconds(10000);
|
||||
nrf_delay_ms(120);
|
||||
|
||||
// Send initialization commands
|
||||
const char *cmd = SPILCD_INIT_CODE;
|
||||
@ -764,8 +762,9 @@ void lcd_init() {
|
||||
cmd += 3 + cmd[CMDINDEX_DATALEN];
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_kill() {
|
||||
jshPinOutput(LCD_BL,!LCD_BL_ON); // backlight off
|
||||
jshPinOutput(LCD_BL, !LCD_BL_ON); // backlight off
|
||||
lcd_cmd(0x28, 0, NULL); // display off
|
||||
jshDelayMicroseconds(20);
|
||||
lcd_cmd(0x10, 0, NULL); // SLPIN
|
||||
@ -774,7 +773,7 @@ void lcd_kill() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // LCD_CONTROLLER_ST7735 or LCD_CONTROLLER_GC9A01
|
||||
|
||||
#ifdef LCD_CONTROLLER_LPM013M126
|
||||
|
||||
|
||||
@ -80,38 +80,43 @@ void turn_off() {
|
||||
#if defined(SPIFLASH_SLEEP_CMD) && defined(ESPR_BOOTLOADER_SPIFLASH)
|
||||
flashPowerDown(); // Put the SPI Flash into deep power-down
|
||||
#endif
|
||||
#ifdef VIBRATE_PIN
|
||||
jshPinOutput(VIBRATE_PIN,1); // vibrate on
|
||||
#if defined(VIBRATE_PIN) && !defined(DICKENS)
|
||||
jshPinOutput(VIBRATE_PIN,1); // vibrate whilst waiting for button release
|
||||
#endif
|
||||
#if defined(BTN2_PININDEX)
|
||||
while (get_btn1_state() || get_btn2_state()) {}; // wait for BTN1 and BTN2 to be released
|
||||
#else
|
||||
while (get_btn1_state()) {}; // wait for BTN1 and BTN2 to be released
|
||||
while (get_btn1_state()) {}; // wait for BTN1 to be released
|
||||
#endif
|
||||
#ifdef VIBRATE_PIN
|
||||
jshPinSetValue(VIBRATE_PIN,0); // vibrate off
|
||||
#endif
|
||||
#ifdef DICKENS
|
||||
NRF_P0->OUT=0x03300f04; // 00000011 00110000 00001111 00000100 - high pins: D2, D8, SDA, SCL, LCD_CS, FLASH_CS, FLASH_WP, FLASH_RST, FLASH_SCK
|
||||
//NRF_P0->OUT=0x03300e00; // 00000011 00110000 00001110 00000000 - high pins: SDA, SCL, LCD_CS, FLASH_CS, FLASH_WP, FLASH_RST, FLASH_SCK
|
||||
//NRF_P0->OUT=0x03300e00; // 00000011 00110000 00001110 00000000 - high pins: SDA, SCL, LCD_CS, FLASH_CS, FLASH_WP, FLASH_RST, FLASH_SCK
|
||||
if (pinInfo[LCD_BL].port&JSH_PIN_NEGATED) // if backlight negated
|
||||
NRF_P1->OUT=0x00000001; // High pins: LCD_BL
|
||||
NRF_P1->OUT=0x00000101; // High pins: LCD_BL, P1.16 (doesn't exist, but seems to draw around 3 µA extra if this is not set)
|
||||
else
|
||||
NRF_P1->OUT=0x00000000;
|
||||
for (uint8_t pin=0; pin<48; pin++) {
|
||||
NRF_GPIO_PIN_CNF(pin,0x00000004); // Set all pins as input with pulldown
|
||||
}
|
||||
NRF_P1->OUT=0x00000100;
|
||||
// for (uint8_t pin=0; pin<48; pin++) {
|
||||
// NRF_GPIO_PIN_CNF(pin,0x00000006); // Set all pins as input disconnect with pulldown
|
||||
// }
|
||||
NRF_GPIO_PIN_CNF(BAT_PIN_VOLTAGE,0x00000002); // D4 = battery voltage measurement (no pull, input buffer disconnected)
|
||||
NRF_GPIO_PIN_CNF(ACCEL_PIN_SDA,0x0000060d); // D9 = SDA open-drain output
|
||||
NRF_GPIO_PIN_CNF(ACCEL_PIN_SCL,0x0000060d); // D10 = SCL open-drain output
|
||||
NRF_GPIO_PIN_CNF(LCD_SPI_MISO,0x0000000c); // D27 = LCD_MISO input with pullup
|
||||
if (pinInfo[LCD_BL].port&JSH_PIN_NEGATED) // if backlight negated
|
||||
NRF_GPIO_PIN_CNF(LCD_BL,0x00000003); // D32 = LCD backlight pin
|
||||
#ifdef ACCEL_PIN_INT1
|
||||
NRF_GPIO_PIN_CNF(ACCEL_PIN_INT1,0x00000002); // D21 = INT1 (no pull, input buffer disconnected)
|
||||
NRF_GPIO_PIN_CNF(ACCEL_PIN_INT2,0x00000002); // D23 = INT2 (no pull, input buffer disconnected)
|
||||
#endif
|
||||
NRF_GPIO_PIN_CNF(LCD_SPI_MISO,0x00000002); // D27 = LCD_MISO (no pull, input buffer disconnected)
|
||||
//if (pinInfo[LCD_BL].port&JSH_PIN_NEGATED) // if backlight negated
|
||||
// NRF_GPIO_PIN_CNF(LCD_BL,0x00000003); // D32 = LCD backlight pin
|
||||
//NRF_GPIO_PIN_CNF(BTN2_PININDEX,0x0003000c); // D28 = BTN2 input (with pullup and low-level sense)
|
||||
//NRF_GPIO_PIN_CNF(BTN3_PININDEX,0x0003000c); // D29 = BTN3 input (with pullup and low-level sense)
|
||||
//NRF_GPIO_PIN_CNF(31,0x00000003); // D31 = Debug output pin (brought out to external header on)
|
||||
//NRF_GPIO_PIN_CNF(BTN4_PININDEX,0x0003000c); // D42 = BTN4 input (with pullup and low-level sense)
|
||||
NRF_GPIO_PIN_CNF(BTN1_PININDEX,0x0003000c); // D46 = BTN1 input (with pullup and low-level sense)
|
||||
NRF_GPIO_PIN_CNF(BAT_PIN_CHARGING,0x0000000c); // Charge input (with pullup)
|
||||
#else // !DICKENS
|
||||
set_led_state(0,0);
|
||||
#if defined(BTN2_PININDEX)
|
||||
@ -187,6 +192,7 @@ bool dfu_enter_check(void) {
|
||||
#endif
|
||||
} else {
|
||||
lcd_clear();
|
||||
print_fw_version();
|
||||
lcd_println("DFU START");
|
||||
}
|
||||
set_led_state(true, true);
|
||||
@ -356,24 +362,33 @@ int main(void)
|
||||
dfuIsColdBoot = (r&0xF)==0;
|
||||
|
||||
#if defined(DICKENS) || defined(BANGLEJS)
|
||||
// On smartwatches, turn on only if BTN1 held for >1 second
|
||||
// On smartwatches, turn on only if BTN1 held for >1 second (or charging on Dickens)
|
||||
// This may help in cases where battery is TOTALLY flat
|
||||
if ((r&0b1011)==0) {
|
||||
// if not watchdog, lockup, or reset pin...
|
||||
if ((r&0xF)==0) { // Bangle.softOff causes 'SW RESET' after 1 sec, so r==4
|
||||
nrf_delay_ms(1000);
|
||||
}
|
||||
#ifndef DICKENS
|
||||
if (!get_btn1_state() && (r&0xF)==0) { // Don't turn off after a SW reset, to avoid user input needed during reflashing
|
||||
turn_off();
|
||||
} else {
|
||||
#ifdef DICKENS
|
||||
#else // DICKENS
|
||||
if (!get_btn1_state() && get_charging_state()) {
|
||||
nrf_delay_ms(3000); // wait 4 secs in total before booting if on charge
|
||||
}
|
||||
if (!get_btn1_state() && !get_charging_state() && (r&0xF)==0) { // Don't turn off after a SW reset, to avoid user input needed during reflashing
|
||||
turn_off();
|
||||
} else {
|
||||
// DICKENS: Enter bootloader only if BTN2 held as well
|
||||
if (!get_btn2_state()) {
|
||||
// Clear reset reason flags
|
||||
NRF_POWER->RESETREAS = 0xFFFFFFFF;
|
||||
#ifdef ESPR_BOOTLOADER_SPIFLASH
|
||||
lcd_init();
|
||||
lcd_println("DFU " JS_VERSION "\n");
|
||||
#ifndef DICKENS
|
||||
print_fw_version();
|
||||
#endif
|
||||
// Check if we should reflash new firmware
|
||||
flashCheckAndRun();
|
||||
#endif
|
||||
@ -400,7 +415,7 @@ int main(void)
|
||||
}
|
||||
// Clear reset reason flags
|
||||
NRF_POWER->RESETREAS = 0xFFFFFFFF;
|
||||
lcd_println("DFU " JS_VERSION "\n");
|
||||
print_fw_version();
|
||||
#ifdef ESPR_BOOTLOADER_SPIFLASH
|
||||
if (!get_btn1_state()) flashCheckAndRun();
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user